|
| 1 | +import os |
1 | 2 | from typing import Dict, Optional, Set |
2 | | -from unittest.mock import sentinel |
| 3 | +from unittest.mock import sentinel, patch |
3 | 4 |
|
| 5 | +import joblib # type: ignore |
4 | 6 | import pytest # type: ignore |
5 | 7 |
|
6 | 8 | from grimp.application import usecases |
|
9 | 11 | from grimp.domain.valueobjects import DirectImport, Module |
10 | 12 | from tests.adaptors.filesystem import FakeFileSystem |
11 | 13 | from tests.adaptors.packagefinder import BaseFakePackageFinder |
| 14 | +from tests.adaptors.modulefinder import BaseFakeModuleFinder |
12 | 15 | from tests.config import override_settings |
13 | 16 |
|
| 17 | +SOME_CPU_COUNT = 8 |
| 18 | + |
14 | 19 |
|
15 | 20 | class TestBuildGraph: |
16 | 21 | @pytest.mark.parametrize("include_external_packages", (True, False)) |
@@ -131,3 +136,75 @@ def write( |
131 | 136 | if supplied_cache_dir is not sentinel.not_supplied: |
132 | 137 | kwargs["cache_dir"] = supplied_cache_dir |
133 | 138 | usecases.build_graph("mypackage", **kwargs) |
| 139 | + |
| 140 | + @patch.object(usecases, "_scan_chunks", return_value={}) |
| 141 | + @patch.object(joblib, "cpu_count", return_value=SOME_CPU_COUNT) |
| 142 | + @pytest.mark.parametrize( |
| 143 | + "number_of_modules, fake_environ, expected_number_of_chunks", |
| 144 | + [ |
| 145 | + ( |
| 146 | + usecases.DEFAULT_MIN_NUMBER_OF_MODULES_TO_SCAN_USING_MULTIPROCESSING - 1, |
| 147 | + {}, |
| 148 | + 1, |
| 149 | + ), |
| 150 | + ( |
| 151 | + usecases.DEFAULT_MIN_NUMBER_OF_MODULES_TO_SCAN_USING_MULTIPROCESSING, |
| 152 | + {}, |
| 153 | + SOME_CPU_COUNT, |
| 154 | + ), |
| 155 | + ( |
| 156 | + usecases.DEFAULT_MIN_NUMBER_OF_MODULES_TO_SCAN_USING_MULTIPROCESSING + 1, |
| 157 | + {}, |
| 158 | + SOME_CPU_COUNT, |
| 159 | + ), |
| 160 | + ( |
| 161 | + 149, |
| 162 | + {usecases.MIN_NUMBER_OF_MODULES_TO_SCAN_USING_MULTIPROCESSING_ENV_NAME: 150}, |
| 163 | + 1, |
| 164 | + ), |
| 165 | + ( |
| 166 | + 150, |
| 167 | + {usecases.MIN_NUMBER_OF_MODULES_TO_SCAN_USING_MULTIPROCESSING_ENV_NAME: 150}, |
| 168 | + SOME_CPU_COUNT, |
| 169 | + ), |
| 170 | + ( |
| 171 | + 151, |
| 172 | + {usecases.MIN_NUMBER_OF_MODULES_TO_SCAN_USING_MULTIPROCESSING_ENV_NAME: 150}, |
| 173 | + SOME_CPU_COUNT, |
| 174 | + ), |
| 175 | + ], |
| 176 | + ) |
| 177 | + def test_scanning_multiprocessing_respects_min_number_of_modules( |
| 178 | + self, |
| 179 | + mock_cpu_count, |
| 180 | + mock_scan_chunks, |
| 181 | + number_of_modules, |
| 182 | + fake_environ, |
| 183 | + expected_number_of_chunks, |
| 184 | + ): |
| 185 | + class FakePackageFinder(BaseFakePackageFinder): |
| 186 | + directory_map = {"mypackage": "/path/to/mypackage"} |
| 187 | + |
| 188 | + class FakeModuleFinder(BaseFakeModuleFinder): |
| 189 | + module_files_by_package_name = { |
| 190 | + "mypackage": frozenset( |
| 191 | + { |
| 192 | + ModuleFile( |
| 193 | + module=Module(f"mypackage.mod_{i}"), |
| 194 | + mtime=999, |
| 195 | + ) |
| 196 | + for i in range(number_of_modules) |
| 197 | + } |
| 198 | + ) |
| 199 | + } |
| 200 | + |
| 201 | + with override_settings( |
| 202 | + FILE_SYSTEM=FakeFileSystem(), |
| 203 | + PACKAGE_FINDER=FakePackageFinder(), |
| 204 | + MODULE_FINDER=FakeModuleFinder(), |
| 205 | + ), patch.object(os, "environ", fake_environ): |
| 206 | + usecases.build_graph("mypackage", cache_dir=None) |
| 207 | + |
| 208 | + [call] = mock_scan_chunks.call_args_list |
| 209 | + chunks = call.args[0] |
| 210 | + assert len(chunks) == expected_number_of_chunks |
0 commit comments