def test_new_ldlogger(self): """ Test log file parsing escape behaviour with after-#631 LD-LOGGER. """ logfile = os.path.join(self.__test_files, "ldlogger-new.json") # LD-LOGGERS after http://github.com/Ericsson/codechecker/pull/631 # now properly log the multiword arguments. When these are parsed by # the log_parser, the define's value will be passed to the analyzer. # # Logfile contains -DVARIABLE="some value" # and --target=x86_64-linux-gnu. build_action = log_parser.parse_log(logfile, ParseLogOptions())[0] self.assertEqual(list(build_action.sources)[0], r'/tmp/a.cpp') self.assertEqual(len(build_action.analyzer_options), 1) self.assertTrue(len(build_action.target) > 0) self.assertEqual(build_action.analyzer_options[0], r'-DVARIABLE="\"some value"\"') # Test source file with spaces. logfile = os.path.join(self.__test_files, "ldlogger-new-space.json") build_action = log_parser.parse_log(logfile, ParseLogOptions())[0] self.assertEqual(list(build_action.sources)[0], r'/tmp/a b.cpp') self.assertEqual(build_action.lang, 'c++')
def test_old_intercept_build(self): """ Test log file parsing escape behaviour with clang-5.0 intercept-build. """ logfile = os.path.join(self.__test_files, "intercept-old.json") # Scan-build-py shipping with clang-5.0 makes a logfile that contains: # -DVARIABLE=\"some value\" and --target=x86_64-linux-gnu # # The define is passed to the analyzer properly. build_action = log_parser.parse_log(logfile, ParseLogOptions())[0] self.assertEqual(list(build_action.sources)[0], r'/tmp/a.cpp') self.assertEqual(len(build_action.analyzer_options), 1) self.assertTrue(len(build_action.target) > 0) self.assertEqual(build_action.analyzer_options[0], r'-DVARIABLE="\"some value"\"') # Test source file with spaces. logfile = os.path.join(self.__test_files, "intercept-old-space.json") build_action = log_parser.parse_log(logfile, ParseLogOptions())[0] self.assertEqual(list(build_action.sources)[0], r'/tmp/a b.cpp') self.assertEqual(build_action.lang, 'c++')
def test_new_intercept_build(self): """ Test log file parsing escapes with upstream (GitHub) intercept-build. """ logfile = os.path.join(self.__test_files, "intercept-new.json") # Upstream scan-build-py creates an argument vector, as opposed to a # command string. This argument vector contains the define as it's # element in the following format: # -DVARIABLE=\"some value\" # and the target triplet, e.g.: # --target=x86_64-linux-gnu # # The define is passed to the analyzer properly. build_action = log_parser.parse_log(logfile, ParseLogOptions())[0] self.assertEqual(list(build_action.sources)[0], r'/tmp/a.cpp') self.assertEqual(len(build_action.analyzer_options), 1) self.assertTrue(len(build_action.target) > 0) self.assertEqual(build_action.analyzer_options[0], r'-DVARIABLE="\"some value"\"') # Test source file with spaces. logfile = os.path.join(self.__test_files, "intercept-new-space.json") build_action = log_parser.parse_log(logfile, ParseLogOptions())[0] self.assertEqual(list(build_action.sources)[0], r'/tmp/a b.cpp') self.assertEqual(build_action.lang, 'c++')
def test_old_ldlogger(self): """ Test log file parsing escape behaviour with pre-2017 Q2 LD-LOGGER. """ logfile = os.path.join(self.__test_files, "ldlogger-old.json") # LD-LOGGER before http://github.com/Ericsson/codechecker/pull/631 # used an escape mechanism that, when parsed by the log parser via # shlex, made CodeChecker parse arguments with multiword string # literals in them be considered as "file" (instead of compile option), # eventually ignored by the command builder, thus lessening analysis # accuracy, as defines were lost. # # Logfile contains "-DVARIABLE="some value"". # # There is no good way to back-and-forth convert in log_parser or # option_parser, so here we aim for a non-failing stalemate of the # define being considered a file and ignored, for now. build_action = log_parser.parse_log(logfile, ParseLogOptions())[0] results = option_parser.parse_options(build_action.original_command) self.assertEqual(' '.join(results.files), r'"-DVARIABLE="some value"" /tmp/a.cpp') self.assertEqual(len(build_action.analyzer_options), 0)
def test_skip_preproc(self): """ Compiler preprocessor actions should be marked as skipped. """ preprocessor_actions = StringIO('''[ {"directory": "/tmp", "command": "g++ /tmp/a.cpp -E /tmp/a.cpp", "file": "/tmp/a.cpp" }, {"directory": "/tmp", "command": "g++ /tmp/a.cpp -MT /tmp/a.cpp", "file": "/tmp/a.cpp" }, {"directory": "/tmp", "command": "g++ /tmp/a.cpp -MM /tmp/a.cpp", "file": "/tmp/a.cpp" }, {"directory": "/tmp", "command": "g++ /tmp/a.cpp -MF /tmp/a.cpp", "file": "/tmp/a.cpp" }, {"directory": "/tmp", "command": "g++ /tmp/a.cpp -M /tmp/a.cpp", "file": "/tmp/a.cpp" }] ''') build_actions = \ log_parser.parse_compile_commands_json(preprocessor_actions, ParseLogOptions()) for build_action in build_actions: self.assertTrue(build_action.skip)
def test_omit_preproc(self): """ Compiler preprocessor actions should be omitted. """ preprocessor_actions = StringIO('''[ {"directory": "/tmp", "command": "g++ /tmp/a.cpp -c /tmp/a.cpp", "file": "/tmp/a.cpp" }, {"directory": "/tmp", "command": "g++ /tmp/a.cpp -E /tmp/a.cpp", "file": "/tmp/a.cpp" }, {"directory": "/tmp", "command": "g++ /tmp/a.cpp -MT /tmp/a.cpp", "file": "/tmp/a.cpp" }, {"directory": "/tmp", "command": "g++ /tmp/a.cpp -MM /tmp/a.cpp", "file": "/tmp/a.cpp" }, {"directory": "/tmp", "command": "g++ /tmp/a.cpp -MF /tmp/a.cpp", "file": "/tmp/a.cpp" }, {"directory": "/tmp", "command": "g++ /tmp/a.cpp -M /tmp/a.cpp", "file": "/tmp/a.cpp" }] ''') build_actions = \ log_parser.parse_compile_commands_json(preprocessor_actions, ParseLogOptions()) self.assertEqual(len(build_actions), 1) self.assertTrue('-M' not in build_actions[0].original_command) self.assertTrue('-E' not in build_actions[0].original_command) self.assertTrue('-c' in build_actions[0].original_command)
def __get_comp_actions(self, compile_cmd): """ Generate a compilation command json file and parse it to return the compilation actions. """ comp_cmd_json = self.__get_cmp_json(compile_cmd) return log_parser.parse_compile_commands_json(comp_cmd_json, ParseLogOptions())
def __get_comp_actions(self, compile_cmd): """ Generate a compilation command json file and parse it to return the compilation actions. """ comp_cmd_json = self.__get_cmp_json(compile_cmd) with closing(StringIO(comp_cmd_json)) as text: return log_parser.parse_compile_commands_json( text, ParseLogOptions())
def test_include_rel_to_abs(self): """ Test working directory prepending to relative include paths. """ logfile = os.path.join(self.__test_files, "include.json") build_action = log_parser.parse_log(logfile, ParseLogOptions())[0] self.assertEqual(len(build_action.analyzer_options), 3) self.assertEqual(build_action.analyzer_options[0], '-I/include') self.assertEqual(build_action.analyzer_options[1], '-I/include') self.assertEqual(build_action.analyzer_options[2], '-I/tmp')
def test_keep_compile_and_dep(self): """ Keep the compile command if -MD is set. Dependency generation is done as a side effect of the compilation. """ preprocessor_actions = StringIO('''[ {"directory": "/tmp", "command": "g++ /tmp/a.cpp -MD /tmp/a.cpp", "file": "/tmp/a.cpp" }] ''') build_actions = \ log_parser.parse_compile_commands_json(preprocessor_actions, ParseLogOptions()) for build_action in build_actions: self.assertFalse(build_action.skip)
def test_keep_compile_and_dep(self): """ Keep the compile command if -MD is set. Dependency generation is done as a side effect of the compilation. """ preprocessor_actions = [{ "directory": "/tmp", "command": "g++ /tmp/a.cpp -MD /tmp/a.cpp", "file": "/tmp/a.cpp" }] build_actions = \ log_parser.parse_compile_commands_json(preprocessor_actions, ParseLogOptions()) self.assertEqual(len(build_actions), 1) self.assertTrue('-MD' in build_actions[0].original_command)
def test_omit_dep_with_e(self): """ Skip the compile command if -MD is set together with -E. """ preprocessor_actions = StringIO('''[ {"directory": "/tmp", "command": "g++ /tmp/a.cpp -MD -E /tmp/a.cpp", "file": "/tmp/a.cpp" }, {"directory": "/tmp", "command": "g++ /tmp/a.cpp -E -MD /tmp/a.cpp", "file": "/tmp/a.cpp" } ] ''') build_actions = \ log_parser.parse_compile_commands_json(preprocessor_actions, ParseLogOptions()) self.assertEqual(len(build_actions), 0)