Example #1
0
    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_actions, _ = log_parser.\
            parse_unique_log(load_json_or_empty(logfile), self.__this_dir)
        build_action = build_actions[0]

        self.assertEqual(build_action.source, 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_actions, _ = log_parser.\
            parse_unique_log(load_json_or_empty(logfile), self.__this_dir)
        build_action = build_actions[0]

        self.assertEqual(build_action.source, '/tmp/a b.cpp')
        self.assertEqual(build_action.lang, 'c++')
Example #2
0
    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_actions, _ = log_parser.\
            parse_unique_log(load_json_or_empty(logfile), self.__this_dir)
        build_action = build_actions[0]

        self.assertEqual(build_action.source, 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_actions, _ = log_parser.\
            parse_unique_log(load_json_or_empty(logfile), self.__this_dir)
        build_action = build_actions[0]

        self.assertEqual(build_action.source, r'/tmp/a b.cpp')
        self.assertEqual(build_action.lang, 'c++')
Example #3
0
    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_actions, _ = log_parser.\
            parse_unique_log(load_json_or_empty(logfile), self.__this_dir)
        build_action = build_actions[0]

        self.assertEqual(build_action.source, 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')

        # Test source file with spaces.
        logfile = os.path.join(self.__test_files, "intercept-old-space.json")

        build_actions, _ = log_parser.\
            parse_unique_log(load_json_or_empty(logfile), self.__this_dir)
        build_action = build_actions[0]

        self.assertEqual(build_action.source, '/tmp/a b.cpp')
        self.assertEqual(build_action.lang, 'c++')
Example #4
0
    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_actions, _ = log_parser.\
            parse_unique_log(load_json_or_empty(logfile), self.__this_dir)
        build_action = build_actions[0]

        self.assertEqual(build_action.source, r'/tmp/a.cpp')
        self.assertEqual(len(build_action.analyzer_options), 1)
Example #5
0
    def test_response_file_contains_source_file(self):
        """
        Test response file where the source file comes from the response file.
        """
        with open(self.compile_command_file_path,
                  "w",
                  encoding="utf-8",
                  errors="ignore") as build_json:
            build_json.write(
                json.dumps([
                    dict(directory=self.tmp_dir,
                         command="g++ @{0}".format(self.rsp_file_path),
                         file="@{0}".format(self.rsp_file_path))
                ]))

        with open(self.rsp_file_path, "w", encoding="utf-8",
                  errors="ignore") as rsp_file:
            rsp_file.write("""-DVARIABLE="some value" {0}""".format(
                self.src_file_path))

        logfile = os.path.join(self.compile_command_file_path)

        build_actions, _ = log_parser. \
            parse_unique_log(load_json_or_empty(logfile), self.__this_dir)
        build_action = build_actions[0]

        self.assertEqual(len(build_action.analyzer_options), 1)
        self.assertEqual(build_action.source, self.src_file_path)
        self.assertEqual(build_action.analyzer_options[0], '-DVARIABLE=some')
Example #6
0
    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_actions, _ = log_parser.\
            parse_unique_log(load_json_or_empty(logfile), self.__this_dir)
        build_action = build_actions[0]

        self.assertEqual(len(build_action.analyzer_options), 4)
        self.assertEqual(build_action.analyzer_options[0], '-I')
        self.assertEqual(build_action.analyzer_options[1], '/include')
        self.assertEqual(build_action.analyzer_options[2], '-I/include')
        self.assertEqual(build_action.analyzer_options[3], '-I/tmp')
Example #7
0
    def test_response_file_contains_multiple_source_files(self):
        """
        Test response file where multiple source files come from the response
        file.
        """
        with open(self.compile_command_file_path,
                  "w",
                  encoding="utf-8",
                  errors="ignore") as build_json:
            build_json.write(
                json.dumps([
                    dict(directory=self.tmp_dir,
                         command="g++ @{0}".format(self.rsp_file_path),
                         file="@{0}".format(self.rsp_file_path))
                ]))

        a_file_path = os.path.join(self.tmp_dir, "a.cpp")
        with open(a_file_path, "w", encoding="utf-8",
                  errors="ignore") as src_file:
            src_file.write("int main() { return 0; }")

        b_file_path = os.path.join(self.tmp_dir, "b.cpp")
        with open(b_file_path, "w", encoding="utf-8",
                  errors="ignore") as src_file:
            src_file.write("void foo() {}")

        with open(self.rsp_file_path, "w", encoding="utf-8",
                  errors="ignore") as rsp_file:
            rsp_file.write("""-DVARIABLE="some value" {0} {1}""".format(
                a_file_path, b_file_path))

        logfile = os.path.join(self.compile_command_file_path)

        build_actions, _ = log_parser. \
            parse_unique_log(load_json_or_empty(logfile), self.__this_dir)

        self.assertEqual(len(build_actions), 2)

        a_build_action = [b for b in build_actions
                          if b.source == a_file_path][0]
        self.assertEqual(len(a_build_action.analyzer_options), 1)
        self.assertEqual(a_build_action.analyzer_options[0], '-DVARIABLE=some')

        b_build_action = [b for b in build_actions
                          if b.source == b_file_path][0]
        self.assertEqual(len(b_build_action.analyzer_options), 1)
        self.assertEqual(b_build_action.analyzer_options[0], '-DVARIABLE=some')
Example #8
0
    def load_compiler_info(filename, compiler):
        """Load compiler information from a file."""
        contents = load_json_or_empty(filename, {})
        compiler_info = contents.get(compiler)
        if compiler_info is None:
            LOG.error("Could not find compiler %s in file %s", compiler,
                      filename)
            return

        ICI = ImplicitCompilerInfo

        if not ICI.compiler_info.get(compiler):
            ICI.compiler_info[compiler] = defaultdict(dict)

        # Load for language C
        ICI.compiler_info[compiler][ICI.c()]['compiler_includes'] = []
        c_lang_data = compiler_info.get(ICI.c())
        if c_lang_data:
            for element in map(shlex.split,
                               c_lang_data.get("compiler_includes")):
                element = [x for x in element if x != '-isystem']
                ICI.compiler_info[compiler][ICI.c()]['compiler_includes'] \
                    .extend(element)
            ICI.compiler_info[compiler][ICI.c()]['compiler_standard'] = \
                c_lang_data.get('compiler_standard')
            ICI.compiler_info[compiler][ICI.c()]['target'] = \
                c_lang_data.get('target')

        # Load for language C++
        ICI.compiler_info[compiler][ICI.cpp()]['compiler_includes'] = []
        cpp_lang_data = compiler_info.get(ICI.cpp())
        if cpp_lang_data:
            for element in map(shlex.split,
                               cpp_lang_data.get('compiler_includes')):
                element = [x for x in element if x != '-isystem']
                ICI.compiler_info[compiler][ICI.cpp()]['compiler_includes'] \
                    .extend(element)
            ICI.compiler_info[compiler][ICI.cpp()]['compiler_standard'] = \
                cpp_lang_data.get('compiler_standard')
            ICI.compiler_info[compiler][ICI.cpp()]['target'] = \
                cpp_lang_data.get('target')