|  | #!/usr/bin/env python3 | 
|  |  | 
|  | # Copyright lowRISC contributors. | 
|  | # Licensed under the Apache License, Version 2.0, see LICENSE for details. | 
|  | # SPDX-License-Identifier: Apache-2.0 | 
|  |  | 
|  | import unittest | 
|  | from unittest.mock import ( | 
|  | MagicMock, | 
|  | patch, | 
|  | ) | 
|  | from pathlib import Path | 
|  | from io import BytesIO | 
|  |  | 
|  | import functest_coverage | 
|  |  | 
|  |  | 
|  | class AnyStringWith(str): | 
|  |  | 
|  | def __eq__(self, other): | 
|  | return self in other | 
|  |  | 
|  |  | 
|  | class TestFunc(unittest.TestCase): | 
|  |  | 
|  | def test_handle_libs(self): | 
|  | device_libs_all = [ | 
|  | "//foo/a", "//foo/b_on_host_do_not", "//foo/c_on_host", "//foo/d" | 
|  | ] | 
|  | device_libs = ["//foo/a", "//foo/d"] | 
|  |  | 
|  | self.assertEqual(functest_coverage.handle_libs(device_libs_all), | 
|  | device_libs) | 
|  |  | 
|  | @patch("functest_coverage.LLD_TARGET", "<lld_target>") | 
|  | @patch("functest_coverage.run") | 
|  | def test_handle_objs(self, mock_run): | 
|  | merged_library = Path("/foo/merged.so") | 
|  | obj_files = ["//foo/a.o", "//foo/d.o"] | 
|  |  | 
|  | functest_coverage.handle_objs(merged_library, obj_files) | 
|  |  | 
|  | mock_run.assert_called_once_with("<lld_target>", | 
|  | AnyStringWith("unresolved"), | 
|  | "-zmuldefs", "-o", | 
|  | str(merged_library), *obj_files) | 
|  |  | 
|  | @patch("functest_coverage.run") | 
|  | def test_handle_test_targets(self, mock_run): | 
|  | test_targets = [ | 
|  | "//foo/test", "//bar/test_cw310_test_rom", | 
|  | "//qux/long_wycheproof_test" | 
|  | ] | 
|  | mock_run.side_effect = ( | 
|  | None, | 
|  | ["workspace_path"], | 
|  | ["bitstream_file.bit"], | 
|  | None, | 
|  | ) | 
|  |  | 
|  | res = functest_coverage.handle_test_targets(test_targets) | 
|  |  | 
|  | self.assertEqual(res, ["//bar/test_cw310_test_rom"]) | 
|  | calls_mock_run = mock_run.call_args_list | 
|  | self.assertEqual(len(calls_mock_run), 4) | 
|  | self.assertEqual(calls_mock_run[0][0], | 
|  | (functest_coverage.BAZEL, "build", | 
|  | functest_coverage.BITSTREAM_TARGET)) | 
|  | self.assertEqual(calls_mock_run[1][0], | 
|  | (functest_coverage.BAZEL, "info", "workspace")) | 
|  | self.assertEqual( | 
|  | calls_mock_run[2][0], | 
|  | (functest_coverage.BAZEL, "cquery", "--output=starlark", | 
|  | "--starlark:expr", "target.files.to_list()[0].path", | 
|  | functest_coverage.BITSTREAM_TARGET)) | 
|  | self.assertEqual( | 
|  | calls_mock_run[3][0], | 
|  | (functest_coverage.BAZEL, "run", "//sw/host/opentitantool", "--", | 
|  | "fpga", "load-bitstream", "workspace_path/bitstream_file.bit")) | 
|  |  | 
|  | def mock_binary_file(self: unittest.TestCase, | 
|  | name: str, | 
|  | contents: bytes = None) -> MagicMock: | 
|  | mock_file = MagicMock(autospec=BytesIO) | 
|  | mock_file.__enter__.side_effect = [mock_file] | 
|  | mock_file.name = name | 
|  | if contents: | 
|  | mock_file.read.side_effect = [contents] | 
|  | return mock_file | 
|  |  | 
|  | @patch("pathlib.Path.open", autospec=True) | 
|  | @patch("functest_coverage.extract_profile_data") | 
|  | @patch("pathlib.Path.__truediv__", | 
|  | side_effect=Path.__truediv__, | 
|  | autospec=True) | 
|  | def test_handle_test_log_dirs(self, mock_path_div, | 
|  | mock_extract_profile_data, mock_path_open): | 
|  | test_log_dirs = [Path("/testlogs/foo"), Path("/testlogs/bar")] | 
|  | test_logs = [ | 
|  | Path("/testlogs/foo/test.log"), | 
|  | Path("/testlogs/bar/test.log") | 
|  | ] | 
|  | profiles = [ | 
|  | Path("/testlogs/foo/prof.raw"), | 
|  | Path("/testlogs/bar/prof.raw") | 
|  | ] | 
|  |  | 
|  | mock_files = [ | 
|  | self.mock_binary_file(name=test_logs[0], contents=b"<log_0>"), | 
|  | self.mock_binary_file(name=profiles[0]), | 
|  | self.mock_binary_file(name=test_logs[1], contents=b"<log_1>"), | 
|  | self.mock_binary_file(name=profiles[1]), | 
|  | ] | 
|  | mock_path_open.side_effect = mock_files | 
|  | mock_extract_profile_data.side_effect = (b"<raw_profile_0>", | 
|  | b"<raw_profile_1>") | 
|  |  | 
|  | self.assertEqual(functest_coverage.handle_test_log_dirs(test_log_dirs), | 
|  | profiles) | 
|  |  | 
|  | calls_path_div = mock_path_div.call_args_list | 
|  | self.assertEqual(len(calls_path_div), 4) | 
|  | self.assertEqual(calls_path_div[0][0], (test_log_dirs[0], "test.log")) | 
|  | self.assertEqual(calls_path_div[1][0], (test_log_dirs[0], "prof.raw")) | 
|  | self.assertEqual(calls_path_div[2][0], (test_log_dirs[1], "test.log")) | 
|  | self.assertEqual(calls_path_div[3][0], (test_log_dirs[1], "prof.raw")) | 
|  |  | 
|  | calls_path_open = mock_path_open.call_args_list | 
|  | self.assertEqual(len(calls_path_open), 4) | 
|  | self.assertEqual(calls_path_open[0][0], (test_logs[0], "rb")) | 
|  | self.assertEqual(calls_path_open[1][0], (profiles[0], "wb")) | 
|  | self.assertEqual(calls_path_open[2][0], (test_logs[1], "rb")) | 
|  | self.assertEqual(calls_path_open[3][0], (profiles[1], "wb")) | 
|  |  | 
|  | calls_extract_profile_data = mock_extract_profile_data.call_args_list | 
|  | self.assertEqual(len(calls_extract_profile_data), 2) | 
|  | self.assertEqual(calls_extract_profile_data[0][0], ("<log_0>", )) | 
|  | self.assertEqual(calls_extract_profile_data[1][0], ("<log_1>", )) | 
|  |  | 
|  | mock_files[1].write.assert_called_once_with(b"<raw_profile_0>") | 
|  | mock_files[3].write.assert_called_once_with(b"<raw_profile_1>") | 
|  |  | 
|  | def test_params(self): | 
|  | self.assertEqual(functest_coverage.PARAMS.bazel_test_type, | 
|  | AnyStringWith("sh_test")) | 
|  | self.assertEqual(functest_coverage.PARAMS.config, | 
|  | "ot_coverage_on_target") | 
|  | self.assertEqual(functest_coverage.PARAMS.libs_fn, | 
|  | functest_coverage.handle_libs) | 
|  | self.assertEqual(functest_coverage.PARAMS.objs_fn, | 
|  | functest_coverage.handle_objs) | 
|  | self.assertEqual(functest_coverage.PARAMS.test_targets_fn, | 
|  | functest_coverage.handle_test_targets) | 
|  | self.assertEqual(functest_coverage.PARAMS.test_log_dirs_fn, | 
|  | functest_coverage.handle_test_log_dirs) | 
|  | self.assertEqual(functest_coverage.PARAMS.report_title, | 
|  | AnyStringWith("Functional Test")) | 
|  |  | 
|  |  | 
|  | if __name__ == "__main__": | 
|  | unittest.main() |