From b4ee6e3e24ff8716edf712c0e291e59c504f5878 Mon Sep 17 00:00:00 2001 From: Stanislav Pankevich Date: Sat, 23 Nov 2019 16:40:54 +0100 Subject: [PATCH] Feature: CHECK command: escaping non-regex parts --- src/FileCheck | 27 +++++-- tests/integration/lit.cfg | 2 +- .../filecheck.check | 1 + .../filecheck.input | 1 + .../04-escaping_non_regex_parts/sample.itest | 3 + .../filecheck.check | 23 ++++++ .../filecheck.input | 73 +++++++++++++++++++ .../01-mull-scalar-operator-enum/sample.itest | 3 + 8 files changed, 125 insertions(+), 8 deletions(-) create mode 100644 tests/integration/tests/check_commands/CHECK/one_string/positive-match/04-escaping_non_regex_parts/filecheck.check create mode 100644 tests/integration/tests/check_commands/CHECK/one_string/positive-match/04-escaping_non_regex_parts/filecheck.input create mode 100644 tests/integration/tests/check_commands/CHECK/one_string/positive-match/04-escaping_non_regex_parts/sample.itest create mode 100644 tests/integration/tests/real_world_samples/mull/01-mull-scalar-operator-enum/filecheck.check create mode 100644 tests/integration/tests/real_world_samples/mull/01-mull-scalar-operator-enum/filecheck.input create mode 100644 tests/integration/tests/real_world_samples/mull/01-mull-scalar-operator-enum/sample.itest diff --git a/src/FileCheck b/src/FileCheck index 2e5ddda..ae63a96 100755 --- a/src/FileCheck +++ b/src/FileCheck @@ -30,6 +30,20 @@ def similar(a, b): return SequenceMatcher(None, a, b).ratio() +def escape_non_regex_or_skip(match_obj): + non_regex = match_obj.group('non_regex') + if non_regex: + return re.escape(non_regex) + return match_obj.group() + + +def escape_non_regex_parts(string): + regex_line = re.sub(r"((?P[^\{{2}]+)|(?P\{\{(.*?)\}\}))", + escape_non_regex_or_skip, + check_expression) + + return regex_line + def dump_check(check): print("check dump") print("\tcheck_type: {}".format(check.check_type)) @@ -82,7 +96,7 @@ with open(check_file) as f: line = line.rstrip() if not args.strict_whitespace: - line = re.sub("\\s+", ' ', line).strip() + line = re.sub("\\s+", ' ', line) # CHECK and CHECK-NEXT strict_whitespace_match = "" if args.strict_whitespace and args.match_full_lines else " ?" @@ -100,9 +114,9 @@ with open(check_file) as f: match_type = MatchType.SUBSTRING - regex_line = re.sub(r"\{\{(.*?)\}\}", r"\1", check_expression) - - if check_expression != regex_line: + if re.search(r"\{\{.*\}\}", check_expression): + regex_line = escape_non_regex_parts(check_expression) + regex_line = re.sub(r"\{\{(.*?)\}\}", r"\1", regex_line) match_type = MatchType.REGEX check_expression = regex_line @@ -178,6 +192,8 @@ current_scan_base = 0 stdin_input_iter = enumerate(sys.stdin) for line_idx, line in stdin_input_iter: line = line.rstrip() + if not args.strict_whitespace: + line = re.sub("\\s+", ' ', line) input_lines.append(line) @@ -189,9 +205,6 @@ for line_idx, line in stdin_input_iter: elif current_check.check_type == CheckType.CHECK: if current_check.match_type == MatchType.SUBSTRING: - if not args.strict_whitespace: - line = re.sub("\\s+", ' ', line).strip() - if args.match_full_lines: if current_check.expression != line: continue diff --git a/tests/integration/lit.cfg b/tests/integration/lit.cfg index 4003577..9ec9aa5 100644 --- a/tests/integration/lit.cfg +++ b/tests/integration/lit.cfg @@ -1,6 +1,6 @@ import lit.formats -config.name = "Doorstop integration tests" +config.name = "FileCheck.py integration tests" config.test_format = lit.formats.ShTest("0") # LLVM LIT: Is it possible to pass user defined parameter into a test script? diff --git a/tests/integration/tests/check_commands/CHECK/one_string/positive-match/04-escaping_non_regex_parts/filecheck.check b/tests/integration/tests/check_commands/CHECK/one_string/positive-match/04-escaping_non_regex_parts/filecheck.check new file mode 100644 index 0000000..18922bb --- /dev/null +++ b/tests/integration/tests/check_commands/CHECK/one_string/positive-match/04-escaping_non_regex_parts/filecheck.check @@ -0,0 +1 @@ +; CHECK: {{^}}The following braces must be escaped by FileCheck: ( inside braces ): 0/1{{$}} diff --git a/tests/integration/tests/check_commands/CHECK/one_string/positive-match/04-escaping_non_regex_parts/filecheck.input b/tests/integration/tests/check_commands/CHECK/one_string/positive-match/04-escaping_non_regex_parts/filecheck.input new file mode 100644 index 0000000..1cce97d --- /dev/null +++ b/tests/integration/tests/check_commands/CHECK/one_string/positive-match/04-escaping_non_regex_parts/filecheck.input @@ -0,0 +1 @@ +The following braces must be escaped by FileCheck: ( inside braces ): 0/1 \ No newline at end of file diff --git a/tests/integration/tests/check_commands/CHECK/one_string/positive-match/04-escaping_non_regex_parts/sample.itest b/tests/integration/tests/check_commands/CHECK/one_string/positive-match/04-escaping_non_regex_parts/sample.itest new file mode 100644 index 0000000..78436f6 --- /dev/null +++ b/tests/integration/tests/check_commands/CHECK/one_string/positive-match/04-escaping_non_regex_parts/sample.itest @@ -0,0 +1,3 @@ +; RUN: cat %S/filecheck.input | %FILECHECK_EXEC %S/filecheck.check | %FILECHECK_TESTER_EXEC %s --match-full-lines +; CHECK: {{^.*}}FileCheck{{$}} +; CHECK-EMPTY: diff --git a/tests/integration/tests/real_world_samples/mull/01-mull-scalar-operator-enum/filecheck.check b/tests/integration/tests/real_world_samples/mull/01-mull-scalar-operator-enum/filecheck.check new file mode 100644 index 0000000..438b5cb --- /dev/null +++ b/tests/integration/tests/real_world_samples/mull/01-mull-scalar-operator-enum/filecheck.check @@ -0,0 +1,23 @@ +/** +; RUN: cd / && %CLANG_EXEC -fembed-bitcode -g -O0 -MJ %S/raw_compilation_database.tmp %s -o %s.exe +; RUN: cd %CURRENT_DIR +; RUN: compilation_database.sh %S/raw_compilation_database.tmp %S/compile_commands.tmp +; RUN: compilation_database.py %S/compile_commands.tmp %S/compile_commands.json +; RUN: %MULL_EXEC -enable-ast -test-framework CustomTest -compdb-path %S/compile_commands.json -compilation-flags="" -mutators=scalar_value_mutator -reporters=IDE -reporters=Elements -report-dir=%S -report-name=report %s.exe| %FILECHECK_EXEC %s --strict-whitespace +; CHECK-NOT: No mutants found. Mutation score: infinitely high +; CHECK: Running mutants (threads: 1): 0/1{{.*$}} +; CHECK: {{.*}}:17:3: warning: Replacing scalar with 0 or 42 +; CHECK: {{^ }}return SUCCESS;{{$}} +; CHECK: {{^ }}^{{$}} +**/ + +enum Enum { SUCCESS = 1234 }; + +Enum foo() { + return SUCCESS; +}; + +int main() { + return foo() != SUCCESS; +} + diff --git a/tests/integration/tests/real_world_samples/mull/01-mull-scalar-operator-enum/filecheck.input b/tests/integration/tests/real_world_samples/mull/01-mull-scalar-operator-enum/filecheck.input new file mode 100644 index 0000000..3fb0ee5 --- /dev/null +++ b/tests/integration/tests/real_world_samples/mull/01-mull-scalar-operator-enum/filecheck.input @@ -0,0 +1,73 @@ +Extracting bitcode from executable (threads: 1): 0/1 +Extracting bitcode from executable (threads: 1): 1/1. Finished in 3ms. + +Loading bitcode files (threads: 1): 0/1 +Loading bitcode files (threads: 1): 1/1. Finished in 12ms. + +AST Search: looking for mutations in the source files (threads: 1): 0/1 +AST Search: looking for mutations in the source files (threads: 1): 1/1. Finished in 12ms. + +Compiling instrumented code (threads: 1): 0/1 +Compiling instrumented code (threads: 1): 1/1. Finished in 12ms. + +Loading dynamic libraries (threads: 1): 0/1 +Loading dynamic libraries (threads: 1): 1/1. Finished in 0ms. + +Searching tests (threads: 1): 0/1 +Searching tests (threads: 1): 1/1. Finished in 0ms. + +Preparing original test run (threads: 1): 0/1 +Preparing original test run (threads: 1): 1/1. Finished in 1ms. + +Running original tests (threads: 1): 0/1 +Running original tests (threads: 1): 1/1. Finished in 10ms. + +Applying function filter: no debug info (threads: 1): 0/1 +Applying function filter: no debug info (threads: 1): 1/1. Finished in 13ms. + +Applying function filter: file path (threads: 1): 0/1 +Applying function filter: file path (threads: 1): 1/1. Finished in 10ms. + +Instruction selection (threads: 1): 0/1 +Instruction selection (threads: 1): 1/1. Finished in 13ms. + +Searching mutants across functions (threads: 1): 0/1 +Searching mutants across functions (threads: 1): 1/1. Finished in 10ms. +MutationsFinder: found 1 mutations. + +Applying filter: no debug info (threads: 1): 0/1 +Applying filter: no debug info (threads: 1): 1/1. Finished in 0ms. + +Applying filter: file path (threads: 1): 0/1 +Applying filter: file path (threads: 1): 1/1. Finished in 1ms. + +Prepare mutations (threads: 1): 0/1 +Prepare mutations (threads: 1): 1/1. Finished in 0ms. + +Cloning functions for mutation (threads: 1): 0/1 +Cloning functions for mutation (threads: 1): 1/1. Finished in 12ms. + +Removing original functions (threads: 1): 0/1 +Removing original functions (threads: 1): 1/1. Finished in 11ms. + +Redirect mutated functions (threads: 1): 0/1 +Redirect mutated functions (threads: 1): 1/1. Finished in 0ms. + +Applying mutations (threads: 1): 0/1 +Applying mutations (threads: 1): 1/1. Finished in 0ms. + +Compiling original code (threads: 1): 0/1 +Compiling original code (threads: 1): 1/1. Finished in 11ms. + +Running mutants (threads: 1): 0/1 +Running mutants (threads: 1): 1/1. Finished in 11ms. + +Survived mutants (0/1): + +/opt/mull-integration-tests/tests/mutations/scalar_value/13_enum_value/sample.cpp:17:3: warning: Replacing scalar with 0 or 42 + return SUCCESS; + ^ +Mutation score: 100% +Mutation Testing Elements reporter: generating report to /opt/mull-integration-tests/tests/mutations/scalar_value/13_enum_value/report.json + +Total execution time: 146ms diff --git a/tests/integration/tests/real_world_samples/mull/01-mull-scalar-operator-enum/sample.itest b/tests/integration/tests/real_world_samples/mull/01-mull-scalar-operator-enum/sample.itest new file mode 100644 index 0000000..01dfa68 --- /dev/null +++ b/tests/integration/tests/real_world_samples/mull/01-mull-scalar-operator-enum/sample.itest @@ -0,0 +1,3 @@ +; RUN: cat %S/filecheck.input | (%FILECHECK_EXEC %S/filecheck.check 2>&1; test $? = 0;) | %FILECHECK_TESTER_EXEC %s --strict-whitespace --match-full-lines +; CHECK:{{^.*}}FileCheck{{$}} +; CHECK-EMPTY: