blob: 5c3ec389cf09516944423da86b094085f05b8bae [file] [log] [blame] [edit]
#!/usr/bin/env fuchsia-vendored-python
# Copyright 2025 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 unittest
sys.path.insert(0, os.path.dirname(__file__))
from runfiles_utils import RepoMapping, RunfilesManifest
class RepoMappingTest(unittest.TestCase):
# Some input test cases shared by the tests below.
# These all correspond to the same custom Bazel project
# built with different versions of Bazel and with or without
# BzlMod enabled.
_BAZEL8_BZLMOD_WITH_MODULE_EXTENSION_REPO_MAPPING = "\n".join(
[
",the_module,_main",
",the_repo,+custom_repo_ext+the_repo",
"+custom_repo_ext+the_repo,the_module,_main",
"+custom_repo_ext+the_repo,the_repo,+custom_repo_ext+the_repo",
]
)
_BAZEL7_BZLMOD_WITH_MODULE_EXTENSION_REPO_MAPPING = "\n".join(
[
",the_module,_main",
",the_repo,_main~custom_repo_ext~the_repo",
",the_workspace,_main",
"_main~custom_repo_ext~the_repo,the_module,_main",
"_main~custom_repo_ext~the_repo,the_repo,_main~custom_repo_ext~the_repo",
]
)
_BAZEL7_WORKSPACE_WITH_REPOSITORY_REPO_MAPPING = "\n".join(
[
",the_workspace,the_workspace",
"bazel_tools,__main__,the_workspace",
"local_config_cc,the_workspace,the_workspace",
"local_config_xcode,the_workspace,the_workspace",
"the_repo,the_workspace,the_workspace",
]
)
def test_parse_repo_mapping(self):
_TEST_CASES = [
(
"bazel8_bzlmod_with_module_extension",
self._BAZEL8_BZLMOD_WITH_MODULE_EXTENSION_REPO_MAPPING,
{
"": {
"the_module": "_main",
"the_repo": "+custom_repo_ext+the_repo",
},
"+custom_repo_ext+the_repo": {
"the_module": "_main",
"the_repo": "+custom_repo_ext+the_repo",
},
},
),
(
"bazel7_bzlmod_with_module_extension",
self._BAZEL7_BZLMOD_WITH_MODULE_EXTENSION_REPO_MAPPING,
{
"": {
"the_module": "_main",
"the_repo": "_main~custom_repo_ext~the_repo",
"the_workspace": "_main",
},
"_main~custom_repo_ext~the_repo": {
"the_module": "_main",
"the_repo": "_main~custom_repo_ext~the_repo",
},
},
),
(
"bazel7_workspace_with_custom_repository",
self._BAZEL7_WORKSPACE_WITH_REPOSITORY_REPO_MAPPING,
{
"": {"the_workspace": "the_workspace"},
"bazel_tools": {"__main__": "the_workspace"},
"local_config_cc": {"the_workspace": "the_workspace"},
"local_config_xcode": {"the_workspace": "the_workspace"},
"the_repo": {"the_workspace": "the_workspace"},
},
),
]
for test_case in _TEST_CASES:
name, content, expected = test_case
result = RepoMapping.parse_repo_mapping(content)
self.assertEqual(result, expected, name)
def test_map_apparent_name(self):
_TEST_CASES = [
(
"bazel8_bzlmod_with_module_extension",
self._BAZEL8_BZLMOD_WITH_MODULE_EXTENSION_REPO_MAPPING,
[
# (source_name,apparent_name,runfile_name)
("the_module", "", "_main"),
("the_module", "+custom_repo_ext+the_repo", "_main"),
("the_module", "unknown_source", ""),
("the_repo", "", "+custom_repo_ext+the_repo"),
(
"the_repo",
"+custom_repo_ext+the_repo",
"+custom_repo_ext+the_repo",
),
("the_repo", "unknown_source", ""),
],
),
(
"bazel7_bzlmod_with_module_extension",
self._BAZEL7_BZLMOD_WITH_MODULE_EXTENSION_REPO_MAPPING,
[
# (source_name,apparent_name,runfile_name)
("the_module", "", "_main"),
("the_module", "_main~custom_repo_ext~the_repo", "_main"),
("the_module", "unknown_source", ""),
("the_repo", "", "_main~custom_repo_ext~the_repo"),
(
"the_repo",
"_main~custom_repo_ext~the_repo",
"_main~custom_repo_ext~the_repo",
),
("the_repo", "unknown_source", ""),
],
),
(
"bazel7_workspace_with_custom_repository",
self._BAZEL7_WORKSPACE_WITH_REPOSITORY_REPO_MAPPING,
[
# (source_name,apparent_name,runfile_name)
("the_workspace", "", "the_workspace"),
("the_workspace", "local_config_cc", "the_workspace"),
("the_workspace", "local_config_xcode", "the_workspace"),
("the_workspace", "the_repo", "the_workspace"),
("the_workspace", "unknown_source", ""),
("__main__", "bazel_tools", "the_workspace"),
],
),
]
for test_case in _TEST_CASES:
name, content, subcases = test_case
mapping = RepoMapping.CreateFrom(content)
for apparent_name, source_name, expected_name in subcases:
self.assertEqual(
expected_name,
mapping.map_apparent_name(apparent_name, source_name),
f"{name}.{apparent_name} in {source_name}",
)
def test_map_input_path(self):
_TEST_CASES = [
(
"bazel8_bzlmod_with_module_extension",
self._BAZEL8_BZLMOD_WITH_MODULE_EXTENSION_REPO_MAPPING,
[
# (input_path,source_name,expected_path)
("the_module", "", "the_module"),
("the_module/foo/bar", "", "_main/foo/bar"),
(
"the_module/foo/bar",
"+custom_repo_ext+the_repo",
"_main/foo/bar",
),
(
"the_module/foo/bar",
"unknown_source",
"the_module/foo/bar",
),
(
"the_repo/data/file",
"",
"+custom_repo_ext+the_repo/data/file",
),
(
"the_repo/data/file",
"+custom_repo_ext+the_repo",
"+custom_repo_ext+the_repo/data/file",
),
(
"the_repo/data/file",
"unknown_source",
"the_repo/data/file",
),
],
),
(
"bazel7_bzlmod_with_module_extension",
self._BAZEL7_BZLMOD_WITH_MODULE_EXTENSION_REPO_MAPPING,
[
# (input_path,source_name,expected_path)
("the_module/src/foo", "", "_main/src/foo"),
(
"the_module/src/foo",
"_main~custom_repo_ext~the_repo",
"_main/src/foo",
),
(
"the_module/src/foo",
"unknown_source",
"the_module/src/foo",
),
(
"the_repo/data/file",
"",
"_main~custom_repo_ext~the_repo/data/file",
),
(
"the_repo/data/file",
"_main~custom_repo_ext~the_repo",
"_main~custom_repo_ext~the_repo/data/file",
),
(
"the_repo/data/file",
"unknown_source",
"the_repo/data/file",
),
],
),
(
"bazel7_workspace_with_custom_repository",
self._BAZEL7_WORKSPACE_WITH_REPOSITORY_REPO_MAPPING,
[
# (input_path,source_name,expected_path)
("the_workspace/src/foo", "", "the_workspace/src/foo"),
(
"the_workspace/src/foo",
"local_config_cc",
"the_workspace/src/foo",
),
(
"the_workspace/src/foo",
"local_config_xcode",
"the_workspace/src/foo",
),
(
"the_workspace/src/foo",
"the_repo",
"the_workspace/src/foo",
),
(
"the_workspace/src/foo",
"unknown_source",
"the_workspace/src/foo",
),
(
"__main__/data/file",
"bazel_tools",
"the_workspace/data/file",
),
],
),
]
for test_case in _TEST_CASES:
name, content, subcases = test_case
mapping = RepoMapping.CreateFrom(content)
for input_path, source_name, expected_path in subcases:
self.assertEqual(
expected_path,
mapping.map_input_path(input_path, source_name),
f"{name}.{input_path} from {source_name}",
)
class RunfilesManifestTest(unittest.TestCase):
def test_escape(self):
TEST_CASES = {
"a path with spaces": "a\\spath\\swith\\sspaces",
"a\npath\nwith\nnewlines": "a\\npath\\nwith\\nnewlines",
"a\\path\\with\\backslashes": "a\\bpath\\bwith\\bbackslashes",
" a mix\nof\\many things": "\\sa\\smix\\nof\\bmany\\sthings",
"a_regular_path": "a_regular_path",
}
for path, expected in TEST_CASES.items():
self.assertEqual(expected, RunfilesManifest.escape(path))
def test_unescape(self):
TEST_CASES = {
"a\\spath\\swith\\sspaces": "a path with spaces",
"a\\npath\\nwith\\nnewlines": "a\npath\nwith\nnewlines",
"a\\bpath\\bwith\\bbackslashes": "a\\path\\with\\backslashes",
"\\sa\\smix\\nof\\bmany\\sthings": " a mix\nof\\many things",
"unescapable_\\%sequence": "unescapable_\\%sequence",
"a_regular_path": "a_regular_path",
}
for path, expected in TEST_CASES.items():
self.assertEqual(expected, RunfilesManifest.unescape(path))
def test_parse_manifest(self):
VALID_TEST_CASES = {
"foo bar": {"foo": "bar"},
"foo bar\nqux zoo\n": {"foo": "bar", "qux": "zoo"},
" foo bar": {"foo": "bar"},
" foo\\s bar": {"foo ": "bar"},
" foo bar\\szoo": {"foo": "bar zoo"},
}
for content, expected in VALID_TEST_CASES.items():
result = RunfilesManifest.parse_manifest(content)
self.assertEqual(expected, result, content)
ERROR_TEST_CASES = {
"foo\n": "No space separator in manifest line: [foo]"
}
for content, error in ERROR_TEST_CASES.items():
with self.assertRaises(ValueError) as cm:
RunfilesManifest.parse_manifest(content)
self.assertEqual(str(cm.exception), error, content)
def test_as_dict(self):
TEST_CASES = {
"foo bar": {"foo": "bar"},
"foo bar\nqux zoo\n": {"foo": "bar", "qux": "zoo"},
" foo bar": {"foo": "bar"},
" foo\\s bar": {"foo ": "bar"},
" foo bar\\szoo": {"foo": "bar zoo"},
}
for content, expected_dict in TEST_CASES.items():
manifest = RunfilesManifest.CreateFrom(content)
self.assertDictEqual(manifest.as_dict(), expected_dict, msg=content)
def test_generate_runtime_deps_json(self):
pass
def test_generate_content(self):
TEST_CASES = [
({"foo": "bar"}, "foo bar\n"),
({"foo": "bar", "bar": "zoo"}, "bar zoo\nfoo bar\n"),
({"foo bar": "zoo"}, " foo\\sbar zoo\n"),
({"foo": "bar zoo"}, " foo bar\\szoo\n"),
({"foo\nbar": " zoo\\qux"}, " foo\\nbar \\szoo\\bqux\n"),
]
for file_map, expected_content in TEST_CASES:
manifest = RunfilesManifest(file_map)
self.assertEqual(manifest.generate_content(), expected_content)
if __name__ == "__main__":
unittest.main()