Xuehai Pan | 8a67daf | 2024-06-29 12:48:06 +0800 | [diff] [blame] | 1 | from __future__ import annotations |
| 2 | |
Michael Dagitses | b936a10 | 2021-09-17 12:07:19 -0700 | [diff] [blame] | 3 | import contextlib |
| 4 | import os |
| 5 | import typing |
Michael Dagitses | b936a10 | 2021-09-17 12:07:19 -0700 | [diff] [blame] | 6 | import unittest |
| 7 | import unittest.mock |
Xuehai Pan | 8a67daf | 2024-06-29 12:48:06 +0800 | [diff] [blame] | 8 | from typing import Iterator, Sequence |
Huy Do | 347b036 | 2022-07-13 07:59:20 +0000 | [diff] [blame] | 9 | |
| 10 | import tools.setup_helpers.cmake |
Michael Dagitses | b936a10 | 2021-09-17 12:07:19 -0700 | [diff] [blame] | 11 | import tools.setup_helpers.env # noqa: F401 unused but resolves circular import |
Michael Dagitses | b936a10 | 2021-09-17 12:07:19 -0700 | [diff] [blame] | 12 | |
| 13 | |
Edward Z. Yang | a11c1bb | 2022-04-20 08:51:02 -0400 | [diff] [blame] | 14 | T = typing.TypeVar("T") |
Michael Dagitses | b936a10 | 2021-09-17 12:07:19 -0700 | [diff] [blame] | 15 | |
| 16 | |
| 17 | class TestCMake(unittest.TestCase): |
Edward Z. Yang | a11c1bb | 2022-04-20 08:51:02 -0400 | [diff] [blame] | 18 | @unittest.mock.patch("multiprocessing.cpu_count") |
Michael Dagitses | b936a10 | 2021-09-17 12:07:19 -0700 | [diff] [blame] | 19 | 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. Yang | a11c1bb | 2022-04-20 08:51:02 -0400 | [diff] [blame] | 24 | (("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 Dagitses | b936a10 | 2021-09-17 12:07:19 -0700 | [diff] [blame] | 32 | ] |
| 33 | for (max_jobs, use_ninja, is_windows), want in cases: |
Edward Z. Yang | a11c1bb | 2022-04-20 08:51:02 -0400 | [diff] [blame] | 34 | with self.subTest( |
| 35 | MAX_JOBS=max_jobs, USE_NINJA=use_ninja, IS_WINDOWS=is_windows |
| 36 | ): |
Michael Dagitses | b936a10 | 2021-09-17 12:07:19 -0700 | [diff] [blame] | 37 | with contextlib.ExitStack() as stack: |
Edward Z. Yang | a11c1bb | 2022-04-20 08:51:02 -0400 | [diff] [blame] | 38 | 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 Dagitses | b936a10 | 2021-09-17 12:07:19 -0700 | [diff] [blame] | 49 | |
| 50 | cmake = tools.setup_helpers.cmake.CMake() |
| 51 | |
Edward Z. Yang | a11c1bb | 2022-04-20 08:51:02 -0400 | [diff] [blame] | 52 | with unittest.mock.patch.object(cmake, "run") as cmake_run: |
Michael Dagitses | b936a10 | 2021-09-17 12:07:19 -0700 | [diff] [blame] | 53 | cmake.build({}) |
| 54 | |
| 55 | cmake_run.assert_called_once() |
Edward Z. Yang | a11c1bb | 2022-04-20 08:51:02 -0400 | [diff] [blame] | 56 | (call,) = cmake_run.mock_calls |
Michael Dagitses | b936a10 | 2021-09-17 12:07:19 -0700 | [diff] [blame] | 57 | build_args, _ = call.args |
| 58 | |
Michael Dagitses | 047e682 | 2021-09-17 12:07:19 -0700 | [diff] [blame] | 59 | if want is None: |
Edward Z. Yang | a11c1bb | 2022-04-20 08:51:02 -0400 | [diff] [blame] | 60 | self.assertNotIn("-j", build_args) |
Michael Dagitses | 047e682 | 2021-09-17 12:07:19 -0700 | [diff] [blame] | 61 | else: |
| 62 | self.assert_contains_sequence(build_args, want) |
Michael Dagitses | b936a10 | 2021-09-17 12:07:19 -0700 | [diff] [blame] | 63 | |
| 64 | @staticmethod |
Edward Z. Yang | a11c1bb | 2022-04-20 08:51:02 -0400 | [diff] [blame] | 65 | def assert_contains_sequence( |
| 66 | sequence: Sequence[T], subsequence: Sequence[T] |
| 67 | ) -> None: |
Michael Dagitses | b936a10 | 2021-09-17 12:07:19 -0700 | [diff] [blame] | 68 | """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. Yang | a11c1bb | 2022-04-20 08:51:02 -0400 | [diff] [blame] | 79 | raise AssertionError(f"{subsequence} not found in {sequence}") |
Michael Dagitses | b936a10 | 2021-09-17 12:07:19 -0700 | [diff] [blame] | 80 | |
| 81 | |
| 82 | @contextlib.contextmanager |
Xuehai Pan | 8a67daf | 2024-06-29 12:48:06 +0800 | [diff] [blame] | 83 | def env_var(key: str, value: str | None) -> Iterator[None]: |
Michael Dagitses | b936a10 | 2021-09-17 12:07:19 -0700 | [diff] [blame] | 84 | """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 Pan | 8a67daf | 2024-06-29 12:48:06 +0800 | [diff] [blame] | 95 | def set_env_var(key: str, value: str | None) -> None: |
Michael Dagitses | b936a10 | 2021-09-17 12:07:19 -0700 | [diff] [blame] | 96 | """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 | |
| 103 | if __name__ == "__main__": |
| 104 | unittest.main() |