Test that uses parallel workers to get and set config. All the workers update the same configuration file concurrently. In a correct implementation with proper path file locking, the final config file remains valid JSON and includes all expected updates.
(tmp_path: Path)
| 277 | |
| 278 | @pytest.mark.slowtest |
| 279 | def test_parallel_get_set_config(tmp_path: Path): |
| 280 | """Test that uses parallel workers to get and set config. |
| 281 | |
| 282 | All the workers update the same configuration file concurrently. In a |
| 283 | correct implementation with proper path file locking, the final |
| 284 | config file remains valid JSON and includes all expected updates. |
| 285 | |
| 286 | """ |
| 287 | pytest.importorskip("joblib") |
| 288 | pytest.importorskip("filelock") |
| 289 | from joblib import Parallel, delayed |
| 290 | |
| 291 | # Use the temporary directory as our home directory. |
| 292 | home_dir = str(tmp_path) |
| 293 | # get_config_path will return home_dir/.mne/mne-python.json |
| 294 | config_file = get_config_path(home_dir=home_dir) |
| 295 | |
| 296 | # if the config file already exists, remove it |
| 297 | if os.path.exists(config_file): |
| 298 | os.remove(config_file) |
| 299 | |
| 300 | # Ensure that the .mne directory exists. |
| 301 | config_dir = tmp_path / ".mne" |
| 302 | config_dir.mkdir(exist_ok=True) |
| 303 | |
| 304 | # Write an initial (valid) config file. |
| 305 | initial_config = {"initial": "True"} |
| 306 | with open(config_file, "w") as f: |
| 307 | json.dump(initial_config, f) |
| 308 | |
| 309 | n_workers = 50 |
| 310 | iterations = 10 |
| 311 | |
| 312 | # Launch multiple workers concurrently using joblib. |
| 313 | Parallel(n_jobs=10)( |
| 314 | delayed(_worker_update_config_loop)(home_dir, worker_id, iterations) |
| 315 | for worker_id in range(n_workers) |
| 316 | ) |
| 317 | |
| 318 | # Now, read back the config file. |
| 319 | final_config = get_config(home_dir=home_dir) |
| 320 | expected_keys = set() |
| 321 | expected_values = set() |
| 322 | # For each worker and iteration, check that the expected key/value pair is present. |
| 323 | for worker_id in range(n_workers): |
| 324 | for i in range(iterations): |
| 325 | expected_key = f"worker_{worker_id}_{i}" |
| 326 | expected_value = f"value_{worker_id}_{i}" |
| 327 | |
| 328 | assert final_config.get(expected_key) == expected_value, ( |
| 329 | f"Missing or incorrect value for key {expected_key}" |
| 330 | ) |
| 331 | expected_keys.add(expected_key) |
| 332 | expected_values.add(expected_value) |
| 333 | |
| 334 | # include the initial key/value pair |
| 335 | # that was written before the workers started |
| 336 |
nothing calls this directly
no test coverage detected