GeoIntel release gates / Compile, test, contracts and builds (push) Successful in 1m49s
GeoIntel release gates / Python and npm vulnerability policy (push) Successful in 21s
GeoIntel release gates / Production AI image, SBOM and container scan (push) Successful in 5m39s
GeoIntel release gates / Deploy exact gated revision to Unraid (push) Failing after 58m43s
87 lines
2.5 KiB
Python
87 lines
2.5 KiB
Python
"""Loading a run's results must not depend on the run being small.
|
|
|
|
``/detection/runs/{id}/detections`` and its GeoJSON sibling returned every
|
|
persisted detection. A regional run holds tens of thousands, so the endpoints
|
|
the map and the results table call after every run grew without bound. The
|
|
counts stay complete; what is transferred does not.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import uuid
|
|
|
|
import pytest
|
|
|
|
from app.services.detection_service import DetectionService
|
|
|
|
|
|
class _Detection:
|
|
def __init__(self, index: int) -> None:
|
|
self.id = uuid.uuid4()
|
|
self.index = index
|
|
|
|
|
|
def _rows(count: int) -> list[_Detection]:
|
|
return [_Detection(index) for index in range(count)]
|
|
|
|
|
|
def test_a_page_is_returned_with_the_complete_total() -> None:
|
|
page, total, truncated = DetectionService.paginate(_rows(1_000), limit=100, offset=0)
|
|
|
|
assert len(page) == 100
|
|
assert total == 1_000
|
|
assert truncated is True
|
|
|
|
|
|
def test_the_offset_walks_the_population() -> None:
|
|
page, total, _ = DetectionService.paginate(_rows(10), limit=3, offset=6)
|
|
|
|
assert [row.index for row in page] == [6, 7, 8]
|
|
assert total == 10
|
|
|
|
|
|
def test_an_offset_past_the_end_yields_an_empty_page_not_an_error() -> None:
|
|
page, total, truncated = DetectionService.paginate(_rows(5), limit=10, offset=50)
|
|
|
|
assert page == []
|
|
assert total == 5
|
|
assert truncated is True
|
|
|
|
|
|
def test_a_population_inside_one_page_is_not_reported_as_truncated() -> None:
|
|
page, total, truncated = DetectionService.paginate(_rows(7), limit=100, offset=0)
|
|
|
|
assert len(page) == 7
|
|
assert total == 7
|
|
assert truncated is False
|
|
|
|
|
|
def test_a_zero_limit_returns_everything_for_callers_that_need_it() -> None:
|
|
page, total, truncated = DetectionService.paginate(_rows(2_500), limit=0, offset=0)
|
|
|
|
assert len(page) == 2_500
|
|
assert total == 2_500
|
|
assert truncated is False
|
|
|
|
|
|
def test_a_negative_offset_is_treated_as_the_start() -> None:
|
|
page, _, _ = DetectionService.paginate(_rows(4), limit=2, offset=-5)
|
|
|
|
assert [row.index for row in page] == [0, 1]
|
|
|
|
|
|
@pytest.mark.parametrize("limit", [1, 2, 3])
|
|
def test_paging_covers_the_population_exactly_once(limit: int) -> None:
|
|
rows = _rows(7)
|
|
seen: list[int] = []
|
|
offset = 0
|
|
while True:
|
|
page, total, _ = DetectionService.paginate(rows, limit=limit, offset=offset)
|
|
if not page:
|
|
break
|
|
seen.extend(row.index for row in page)
|
|
offset += limit
|
|
|
|
assert seen == list(range(7))
|
|
assert total == 7
|