blob: e005924d5a740e5fd061684d112b97fac8dfba05 [file] [log] [blame]
#!/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.
"""Unit-tests for build/build_tests_json.py functions."""
import json
import os
import sys
import tempfile
import typing as T
import unittest
from pathlib import Path
_SCRIPT_DIR = os.path.dirname(__file__)
sys.path.insert(0, _SCRIPT_DIR)
import build_tests_json
from build_utils import BazelPaths, CommandRunner, MockCommandRunner
class BuildTestsJsonTest(unittest.TestCase):
def setUp(self):
self._td = tempfile.TemporaryDirectory()
self._dir = Path(self._td.name)
self.source_dir = self._dir / "source"
self.source_dir.mkdir()
(self.source_dir / ".jiri_manifest").touch()
self.build_dir = self.source_dir / "out" / "not-default"
self.build_dir.mkdir(parents=True)
self.output_dir = self._dir / "output"
self.output_dir.mkdir()
(self.build_dir / "obj" / "tests").mkdir(parents=True)
# Compute the Bazel execroot path, relative to the build directory.
BazelPaths.write_topdir_config_for_test(self.source_dir, "bazel_topdir")
self.execroot_path = os.path.relpath(
BazelPaths(self.source_dir, self.build_dir).execroot,
self.build_dir,
)
def tearDown(self):
self._td.cleanup()
def _test(
self,
tests_from_metadata: T.Dict,
test_groups: T.Dict,
product_bundles: T.Dict,
with_bazel_host_tests: bool = False,
command_runner: T.Optional[CommandRunner] = None,
) -> (T.Set[Path], T.Dict):
tests_from_metadata = json.dumps(tests_from_metadata)
tests_from_metadata_path = self.build_dir / "tests_from_metadata.json"
tests_from_metadata_path.write_text(tests_from_metadata)
test_groups = json.dumps(test_groups)
test_groups_path = (
self.build_dir / "obj" / "tests" / "product_bundle_test_groups.json"
)
test_groups_path.write_text(test_groups)
product_bundles = json.dumps(product_bundles)
product_bundles_path = self.build_dir / "product_bundles.json"
product_bundles_path.write_text(product_bundles)
inputs = build_tests_json.build_tests_json(
self.build_dir, with_bazel_host_tests, command_runner
)
tests_string = (self.build_dir / "tests.json").read_text()
tests = json.loads(tests_string)
return (inputs, tests)
def test_only_tests_from_metadata_no_environments(self):
tests_from_metadata = [
{"test": {"name": "test1"}},
{"test": {"name": "test2"}},
]
product_bundles = [{"name": "my_pb"}]
(_, tests) = self._test(tests_from_metadata, [], product_bundles)
self.assertEqual(tests_from_metadata, tests)
def test_only_test_groups(self):
tests_json = [{"test": {"name": "test1"}}, {"test": {"name": "test2"}}]
tests_json = json.dumps(tests_json)
tests_json_path = self.build_dir / "pb_tests.json"
tests_json_path.write_text(tests_json)
test_groups = [
{"product_bundle_name": "my_pb", "tests_json": str(tests_json_path)}
]
product_bundles = [{"name": "my_pb"}]
(_, tests) = self._test([], test_groups, product_bundles)
expected_tests_json = [
{"product_bundle": "my_pb", "test": {"name": "test1-my_pb"}},
{"product_bundle": "my_pb", "test": {"name": "test2-my_pb"}},
]
self.assertEqual(expected_tests_json, tests)
def test_incorrect_product_bundle_name(self):
tests_json = [{"test": {"name": "test1"}}, {"test": {"name": "test2"}}]
tests_json = json.dumps(tests_json)
tests_json_path = self.build_dir / "pb_tests.json"
tests_json_path.write_text(tests_json)
test_groups = [
{
"product_bundle_name": "my_pb_incorrect",
"tests_json": str(tests_json_path),
}
]
product_bundles = [{"name": "my_pb"}]
with self.assertRaises(SystemExit):
self._test([], test_groups, product_bundles)
def test_metadata_and_product_bundles(self):
tests_from_metadata = [
{"test": {"name": "test1"}},
{"test": {"name": "test2"}},
]
tests_json = [{"test": {"name": "test1"}}, {"test": {"name": "test2"}}]
tests_json = json.dumps(tests_json)
tests_json_path = self.build_dir / "pb_tests.json"
tests_json_path.write_text(tests_json)
product_bundles = [{"name": "my_pb"}]
env = {"dimensions": {"device_type": "Vim3"}}
test_groups = [
{
"product_bundle_name": "my_pb",
"environments": [env],
"tests_json": str(tests_json_path),
}
]
_, tests = self._test(
tests_from_metadata,
test_groups,
product_bundles,
)
expected_tests_json = [
{"test": {"name": "test1"}},
{"test": {"name": "test2"}},
{
"product_bundle": "my_pb",
"environments": [env],
"test": {"name": "test1-my_pb"},
},
{
"product_bundle": "my_pb",
"environments": [env],
"test": {"name": "test2-my_pb"},
},
]
self.assertEqual(expected_tests_json, tests)
def test_bazel_host_tests(self):
# Prepare mock runner for bazel cquery
mock_runner = MockCommandRunner()
test1 = {
"name": "test1",
"label": "@@//t1",
"launcher_execroot_path": "p1",
"runtime_deps_json_execroot_path": "d1",
"os": "linux",
"cpu": "x64",
}
test2 = {
"name": "test2",
"label": "@@//t2",
"launcher_execroot_path": "p2",
"runtime_deps_json_execroot_path": "d2",
"os": "linux",
"cpu": "x64",
}
mock_runner.push_result(
stdout=json.dumps(test1) + "\n" + json.dumps(test2)
)
_, tests = self._test(
[], [], [], with_bazel_host_tests=True, command_runner=mock_runner
)
expected_tests_json = [
{
"environments": [],
"expects_ssh": False,
"test": {
"name": "test1",
"label": "@@//t1",
"path": f"{self.execroot_path}/p1",
"runtime_deps": f"{self.execroot_path}/d1",
"os": "linux",
"cpu": "x64",
},
},
{
"environments": [],
"expects_ssh": False,
"test": {
"name": "test2",
"label": "@@//t2",
"path": f"{self.execroot_path}/p2",
"runtime_deps": f"{self.execroot_path}/d2",
"os": "linux",
"cpu": "x64",
},
},
]
self.assertEqual(len(expected_tests_json), len(tests))
self.assertDictEqual(expected_tests_json[0], tests[0])
self.assertDictEqual(expected_tests_json[1], tests[1])
def test_full(self):
tests_from_metadata = [
{"test": {"name": "test1"}},
{"test": {"name": "test2"}},
]
tests_json = [{"test": {"name": "test1"}}, {"test": {"name": "test2"}}]
tests_json = json.dumps(tests_json)
tests_json_path = self.build_dir / "pb_tests.json"
tests_json_path.write_text(tests_json)
product_bundles = [{"name": "my_pb"}]
env = {"dimensions": {"device_type": "Vim3"}}
test_groups = [
{
"product_bundle_name": "my_pb",
"environments": [env],
"tests_json": str(tests_json_path),
}
]
mock_runner = MockCommandRunner()
test1 = {
"name": "test1",
"label": "@@//t1",
"launcher_execroot_path": "p1",
"runtime_deps_json_execroot_path": "d1",
"os": "linux",
"cpu": "x64",
}
mock_runner.push_result(stdout=json.dumps(test1))
(_, tests) = self._test(
tests_from_metadata,
test_groups,
product_bundles,
with_bazel_host_tests=True,
command_runner=mock_runner,
)
expected_tests_json = [
{"test": {"name": "test1"}},
{"test": {"name": "test2"}},
{
"product_bundle": "my_pb",
"environments": [env],
"test": {"name": "test1-my_pb"},
},
{
"product_bundle": "my_pb",
"environments": [env],
"test": {"name": "test2-my_pb"},
},
{
"environments": [],
"expects_ssh": False,
"test": {
"name": "test1",
"label": "@@//t1",
"path": f"{self.execroot_path}/p1",
"runtime_deps": f"{self.execroot_path}/d1",
"os": "linux",
"cpu": "x64",
},
},
]
self.assertEqual(expected_tests_json, tests)
def test_ninja_inputs(self):
(inputs, _) = self._test([], [], [])
self.assertEqual(
{
Path(self.build_dir / "tests_from_metadata.json"),
Path(
self.build_dir
/ "obj"
/ "tests"
/ "product_bundle_test_groups.json"
),
},
inputs,
)
def test_only_write_if_changed(self):
tests_from_metadata = [
{"test": {"name": "test1"}},
{"test": {"name": "test2"}},
]
tests_json = json.dumps(tests_from_metadata)
tests_json_path = self.build_dir / "tests.json"
tests_json_path.write_text(tests_json)
previous_write_time = os.path.getmtime(tests_json_path)
self._test(tests_from_metadata, [], [])
# ensure the file did not change
current_write_time = os.path.getmtime(tests_json_path)
self.assertEqual(previous_write_time, current_write_time)
if __name__ == "__main__":
unittest.main()