blob: 4a87043dccbfff1b5d83ebb4363f99536898e9b9 [file] [log] [blame]
Xuehai Pan8a67daf2024-06-29 12:48:06 +08001from __future__ import annotations
2
Michael Dagitsesb936a102021-09-17 12:07:19 -07003import contextlib
4import os
5import typing
Michael Dagitsesb936a102021-09-17 12:07:19 -07006import unittest
7import unittest.mock
Xuehai Pan8a67daf2024-06-29 12:48:06 +08008from typing import Iterator, Sequence
Huy Do347b0362022-07-13 07:59:20 +00009
10import tools.setup_helpers.cmake
Michael Dagitsesb936a102021-09-17 12:07:19 -070011import tools.setup_helpers.env # noqa: F401 unused but resolves circular import
Michael Dagitsesb936a102021-09-17 12:07:19 -070012
13
Edward Z. Yanga11c1bb2022-04-20 08:51:02 -040014T = typing.TypeVar("T")
Michael Dagitsesb936a102021-09-17 12:07:19 -070015
16
17class TestCMake(unittest.TestCase):
Edward Z. Yanga11c1bb2022-04-20 08:51:02 -040018 @unittest.mock.patch("multiprocessing.cpu_count")
Michael Dagitsesb936a102021-09-17 12:07:19 -070019 def test_build_jobs(self, mock_cpu_count: unittest.mock.MagicMock) -> None:
20 """Tests that the number of build jobs comes out correctly."""
21 mock_cpu_count.return_value = 13
22 cases = [
23 # MAX_JOBS, USE_NINJA, IS_WINDOWS, want
Edward Z. Yanga11c1bb2022-04-20 08:51:02 -040024 (("8", True, False), ["-j", "8"]), # noqa: E201,E241
25 ((None, True, False), None), # noqa: E201,E241
26 (("7", False, False), ["-j", "7"]), # noqa: E201,E241
27 ((None, False, False), ["-j", "13"]), # noqa: E201,E241
28 (("6", True, True), ["-j", "6"]), # noqa: E201,E241
29 ((None, True, True), None), # noqa: E201,E241
30 (("11", False, True), ["/p:CL_MPCount=11"]), # noqa: E201,E241
31 ((None, False, True), ["/p:CL_MPCount=13"]), # noqa: E201,E241
Michael Dagitsesb936a102021-09-17 12:07:19 -070032 ]
33 for (max_jobs, use_ninja, is_windows), want in cases:
Edward Z. Yanga11c1bb2022-04-20 08:51:02 -040034 with self.subTest(
35 MAX_JOBS=max_jobs, USE_NINJA=use_ninja, IS_WINDOWS=is_windows
36 ):
Michael Dagitsesb936a102021-09-17 12:07:19 -070037 with contextlib.ExitStack() as stack:
Edward Z. Yanga11c1bb2022-04-20 08:51:02 -040038 stack.enter_context(env_var("MAX_JOBS", max_jobs))
39 stack.enter_context(
40 unittest.mock.patch.object(
41 tools.setup_helpers.cmake, "USE_NINJA", use_ninja
42 )
43 )
44 stack.enter_context(
45 unittest.mock.patch.object(
46 tools.setup_helpers.cmake, "IS_WINDOWS", is_windows
47 )
48 )
Michael Dagitsesb936a102021-09-17 12:07:19 -070049
50 cmake = tools.setup_helpers.cmake.CMake()
51
Edward Z. Yanga11c1bb2022-04-20 08:51:02 -040052 with unittest.mock.patch.object(cmake, "run") as cmake_run:
Michael Dagitsesb936a102021-09-17 12:07:19 -070053 cmake.build({})
54
55 cmake_run.assert_called_once()
Edward Z. Yanga11c1bb2022-04-20 08:51:02 -040056 (call,) = cmake_run.mock_calls
Michael Dagitsesb936a102021-09-17 12:07:19 -070057 build_args, _ = call.args
58
Michael Dagitses047e6822021-09-17 12:07:19 -070059 if want is None:
Edward Z. Yanga11c1bb2022-04-20 08:51:02 -040060 self.assertNotIn("-j", build_args)
Michael Dagitses047e6822021-09-17 12:07:19 -070061 else:
62 self.assert_contains_sequence(build_args, want)
Michael Dagitsesb936a102021-09-17 12:07:19 -070063
64 @staticmethod
Edward Z. Yanga11c1bb2022-04-20 08:51:02 -040065 def assert_contains_sequence(
66 sequence: Sequence[T], subsequence: Sequence[T]
67 ) -> None:
Michael Dagitsesb936a102021-09-17 12:07:19 -070068 """Raises an assertion if the subsequence is not contained in the sequence."""
69 if len(subsequence) == 0:
70 return # all sequences contain the empty subsequence
71
72 # Iterate over all windows of len(subsequence). Stop if the
73 # window matches.
74 for i in range(len(sequence) - len(subsequence) + 1):
75 candidate = sequence[i : i + len(subsequence)]
76 assert len(candidate) == len(subsequence) # sanity check
77 if candidate == subsequence:
78 return # found it
Edward Z. Yanga11c1bb2022-04-20 08:51:02 -040079 raise AssertionError(f"{subsequence} not found in {sequence}")
Michael Dagitsesb936a102021-09-17 12:07:19 -070080
81
82@contextlib.contextmanager
Xuehai Pan8a67daf2024-06-29 12:48:06 +080083def env_var(key: str, value: str | None) -> Iterator[None]:
Michael Dagitsesb936a102021-09-17 12:07:19 -070084 """Sets/clears an environment variable within a Python context."""
85 # Get the previous value and then override it.
86 previous_value = os.environ.get(key)
87 set_env_var(key, value)
88 try:
89 yield
90 finally:
91 # Restore to previous value.
92 set_env_var(key, previous_value)
93
94
Xuehai Pan8a67daf2024-06-29 12:48:06 +080095def set_env_var(key: str, value: str | None) -> None:
Michael Dagitsesb936a102021-09-17 12:07:19 -070096 """Sets/clears an environment variable."""
97 if value is None:
98 os.environ.pop(key, None)
99 else:
100 os.environ[key] = value
101
102
103if __name__ == "__main__":
104 unittest.main()