Initial public release
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
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
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
"""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
|
||||
Reference in New Issue
Block a user