|
7 | 7 |
|
8 | 8 |
|
9 | 9 | class TestAsyncBatchFetcher(unittest.TestCase): |
| 10 | + def test_rejects_invalid_concurrency(self) -> None: |
| 11 | + async def mock_fetch(item: dict) -> dict: |
| 12 | + return {"status_code": 200, "data": item} |
| 13 | + |
| 14 | + async def run_invalid(value: object) -> None: |
| 15 | + # Bound the regression test itself: Semaphore(0) used to hang. |
| 16 | + await asyncio.wait_for( |
| 17 | + async_batch_fetch([{"id": 1}], mock_fetch, max_concurrency=value), |
| 18 | + timeout=1, |
| 19 | + ) |
| 20 | + |
| 21 | + for invalid in (0, -1, True, False, 1.5, "2", None, float("nan"), float("inf")): |
| 22 | + with self.subTest(max_concurrency=invalid): |
| 23 | + with self.assertRaisesRegex(ValueError, "max_concurrency must be a positive integer"): |
| 24 | + asyncio.run(run_invalid(invalid)) |
| 25 | + with self.assertRaisesRegex(ValueError, "max_concurrency must be a positive integer"): |
| 26 | + asyncio.run(async_batch_fetch([], mock_fetch, max_concurrency=invalid)) |
| 27 | + |
| 28 | + def test_single_concurrency_and_empty_input(self) -> None: |
| 29 | + async def mock_fetch(item: dict) -> dict: |
| 30 | + return {"status_code": 200, "data": item["id"]} |
| 31 | + |
| 32 | + self.assertEqual(asyncio.run(async_batch_fetch([], mock_fetch, max_concurrency=1)), []) |
| 33 | + results = asyncio.run(async_batch_fetch([{"id": 1}], mock_fetch, max_concurrency=1)) |
| 34 | + self.assertTrue(results[0]["success"]) |
| 35 | + self.assertEqual(results[0]["data"], 1) |
| 36 | + |
10 | 37 | def test_bounded_concurrency(self) -> None: |
11 | 38 | active_concurrency = 0 |
12 | 39 | peak_concurrency = 0 |
|
0 commit comments