diff --git a/src/codechecker_script.py b/src/codechecker_script.py index 43f6227d..a66672df 100644 --- a/src/codechecker_script.py +++ b/src/codechecker_script.py @@ -193,6 +193,19 @@ def analyze(): fail("Make sure that the target can be built first") +def fix_path_with_regex(data:str) -> str: + """ + The absolute paths of the analyzed source files found in the plist files + do not point to their original location, but rather wherever bazel copied + them. This might either be in a subdirectory in bazel-bin on the + local machine, or somewhere unrelated if the analysis was executed on a + remote worker. This function tries to replace these paths to the location + of the original location of the source file. + """ + for pattern, replace in BAZEL_PATHS.items(): + data = re.sub(pattern, replace, data) + return data + def fix_bazel_paths(): """ Remove Bazel leading paths in all files """ stage("Fix CodeChecker output:") @@ -203,9 +216,7 @@ def fix_bazel_paths(): for filename in files: fullpath = os.path.join(root, filename) with open(fullpath, "rt") as data_file: - data = data_file.read() - for pattern, replace in BAZEL_PATHS.items(): - data = re.sub(pattern, replace, data) + data = fix_path_with_regex(data_file.read()) with open(fullpath, "w") as data_file: data_file.write(data) counter += 1 diff --git a/test/unit/plist_res/__init__.py b/test/unit/plist_res/__init__.py new file mode 100644 index 00000000..5fecda68 --- /dev/null +++ b/test/unit/plist_res/__init__.py @@ -0,0 +1,25 @@ +# Copyright 2023 Ericsson AB +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Setup module paths for testing directly on `codechecker_script.py` +""" + +import os +import sys + +# Allow relative imports within the test project to work as expected +# Without it we wouldn't be able to include the fix_bazel_paths function +src = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..", '..') +sys.path.append(src) diff --git a/test/unit/plist_res/test_path_resolution.py b/test/unit/plist_res/test_path_resolution.py new file mode 100644 index 00000000..b34a8a15 --- /dev/null +++ b/test/unit/plist_res/test_path_resolution.py @@ -0,0 +1,62 @@ +# Copyright 2023 Ericsson AB +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Tests regex resolution from remote executor absolute path +to local relative paths +""" +import os +import re +import shutil +import unittest +from typing import Dict +from common.base import TestBase +from src.codechecker_script import fix_path_with_regex + + +class TestPathResolve(TestBase): + """Test regex resolution of remote execution paths""" + + # Set working directory + __test_path__ = os.path.dirname(os.path.abspath(__file__)) + BAZEL_BIN_DIR = os.path.join( + "../../..", "bazel-bin", "test", "unit", "plist_res" + ) + BAZEL_TESTLOGS_DIR = os.path.join( + "../../..", "bazel-testlogs", "test", "unit", "plist_res" + ) + dir = os.path.dirname(os.path.abspath(__file__)) + "/tmp" + + def test_remote_worker_path_resolution(self): + """ + Test: Resolve absolute path of remote worker + to a relative path of the original project + """ + test_path_collection: Dict[str, str] = { + # {Remote execution absolute path}: {project relative path} + "/worker/build/5d2c60d87885b089/root/test/unit/legacy/src/lib.cc": "test/unit/legacy/src/lib.cc", + "/worker/build/a0ed5e04f7c3b444/root/test/unit/legacy/src/ctu.cc": "test/unit/legacy/src/ctu.cc", + "/worker/build/a0ed5e04f7c3b444/root/test/unit/legacy/src/fail.cc": "test/unit/legacy/src/fail.cc", + # This resolution is impossible, because "test_inc" => "inc" cannot be resolved + # "/worker/build/28e82627f5078a2d/root/bazel-out/k8-fastbuild/bin/test/unit/virtual_include/_virtual_includes/test_inc/zeroDiv.h": "test/unit/virtual_include/inc/zeroDiv.h" + } + test_on: Dict[str, str] = test_path_collection.copy() + for before, res in test_on.items(): + after: str = fix_path_with_regex(before[:]) + # FIXME: change to assertEqual + self.assertNotEqual(after, res) + + +if __name__ == "__main__": + unittest.main(buffer=True)