blob: 3fe012f4ede2b2467b0c49791d50e10b7d93dad5 [file]
#!/usr/bin/env fuchsia-vendored-python
# Copyright 2026 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import os
import sys
import tempfile
import unittest
from pathlib import Path
_SCRIPT_DIR = Path(__file__).parent
sys.path.insert(0, str(_SCRIPT_DIR))
from bazel_source_path_mapper import BazelSourcePathMapper
from build_utils import BazelPaths
class BazelSourcePathMapperTest(unittest.TestCase):
def setUp(self) -> None:
self._td = tempfile.TemporaryDirectory()
self.fuchsia_dir = Path(self._td.name) / "fuchsia"
self.fuchsia_dir.mkdir()
(self.fuchsia_dir / ".jiri_manifest").write_text("")
self.build_dir = self.fuchsia_dir / "out" / "build_dir"
self.build_dir.mkdir(parents=True)
BazelPaths.write_topdir_config_for_test(
self.fuchsia_dir, "gen/build/bazel"
)
self.bazel_paths = BazelPaths(self.fuchsia_dir, self.build_dir)
self.mapper = BazelSourcePathMapper(self.bazel_paths)
def tearDown(self) -> None:
self._td.cleanup()
def test_resolve_artifact_path(self) -> None:
# Relative artifact paths
self.assertEqual(self.mapper.resolve_path("bazel-out/foo/bar"), "")
# Absolute artifact paths via execroot
execroot_artifact = f"{self.bazel_paths.execroot}/bazel-out/foo/bar"
self.assertEqual(self.mapper.resolve_path(execroot_artifact), "")
# Absolute artifact paths via output_base
output_base_artifact = f"{self.bazel_paths.output_base}/execroot/_main/bazel-out/config_dir/bin/foo/bar"
self.assertEqual(self.mapper.resolve_path(output_base_artifact), "")
# External repository generated files
execroot_external = f"{self.bazel_paths.execroot}/external/repo_canonical_name+/generated"
self.assertEqual(self.mapper.resolve_path(execroot_external), "")
def test_resolve_regular_source_path(self) -> None:
# A file relative to the execroot, not starting with bazel-out or external
self.assertEqual(self.mapper.resolve_path("src/foo/bar"), "src/foo/bar")
# A file with an absolute path to a source file.
self.assertEqual(
self.mapper.resolve_path(f"{self.fuchsia_dir}/src/foo/bar"),
"src/foo/bar",
)
def test_resolve_external_repository_path(self) -> None:
# Setup an external repo path that is a symlink into Fuchsia source directory
foo_src = self.fuchsia_dir / "src" / "foo"
foo_src.mkdir(parents=True)
foo_file = foo_src / "bar.cc"
foo_file.write_text("Hello")
# external_dir is output_base/external
external_dir = self.bazel_paths.output_base / "external"
external_foo_repo = external_dir / "foo_repo"
external_foo_repo.mkdir(parents=True)
# Create a symlink in the external repo that points to the fuchsia source file
os.symlink(foo_file, external_foo_repo / "bar.cc")
# Resolve an external path
self.assertEqual(
self.mapper.resolve_path("external/foo_repo/bar.cc"),
"src/foo/bar.cc",
)
def test_resolve_workspace_exception_path(self) -> None:
# Path inside the workspace that is one of the generated files exception
workspace_bazelrc = self.bazel_paths.workspace / ".bazelrc"
self.assertEqual(self.mapper.resolve_path(str(workspace_bazelrc)), "")
workspace_generated = (
self.bazel_paths.workspace / "fuchsia_build_generated" / "foo"
)
self.assertEqual(self.mapper.resolve_path(str(workspace_generated)), "")
def test_resolve_workspace_symlink(self) -> None:
# Workspace is symlinked to the main source checkout.
workspace_file = self.bazel_paths.workspace / "src/foo/bar.cc"
# We don't necessarily need to create the actual symlinks, because path reasoning uses
# removeprefix() to strip the workspace prefix.
self.assertEqual(
self.mapper.resolve_path(str(workspace_file)), "src/foo/bar.cc"
)
def test_cache(self) -> None:
# First call calculates
path = "src/foo/bar"
self.assertEqual(self.mapper.resolve_path(path), "src/foo/bar")
# Second call should use cache
self.assertEqual(self.mapper.resolve_path(path), "src/foo/bar")
# Verify cache content
self.assertIn(path, self.mapper._cache)
self.assertEqual(self.mapper._cache[path], "src/foo/bar")
def test_install_base_ignored(self) -> None:
install_base_file = "/path/to/prebuilt/third_party/bazel/some_file"
self.assertEqual(self.mapper.resolve_path(install_base_file), "")
def test_resolve_relative_generated_file(self) -> None:
self.assertEqual(self.mapper.resolve_path(".bazelrc"), "")
self.assertEqual(
self.mapper.resolve_path("fuchsia_build_generated/foo"), ""
)
def test_resolve_execroot_source(self) -> None:
execroot_source = f"{self.bazel_paths.execroot}/src/foo/bar.cc"
self.assertEqual(
self.mapper.resolve_path(execroot_source), "src/foo/bar.cc"
)
def test_resolve_output_base_non_execroot(self) -> None:
# Path starts with output_base but not execroot
output_base_file = f"{self.bazel_paths.output_base}/some_file"
self.assertEqual(self.mapper.resolve_path(output_base_file), "")
def test_resolve_outside_path(self) -> None:
# Path outside everything
outside_path = "/some/other/path/file.cc"
expected = os.path.relpath(outside_path, self.fuchsia_dir)
self.assertEqual(self.mapper.resolve_path(outside_path), expected)
def test_resolve_external_repository_non_symlink(self) -> None:
# Setup an external repo path that is NOT a symlink
external_dir = self.bazel_paths.output_base / "external"
external_foo_repo = external_dir / "foo_repo"
external_foo_repo.mkdir(parents=True)
foo_file = external_foo_repo / "bar.cc"
foo_file.write_text("Hello")
# Resolve an external path that is a real file in external repo
self.assertEqual(
self.mapper.resolve_path("external/foo_repo/bar.cc"),
"",
)
if __name__ == "__main__":
unittest.main()