Test coverage: atol/rtol forwarding on cupy and dask+cupy backends#2540
Conversation
The atol/rtol kwargs route through _polygonize_cupy and _polygonize_dask
into the chunked _polygonize_chunk helper (polygonize.py:823-825,
829-830, 1748-1758). Existing tests pin the parameter behaviour on
the numpy and dask+numpy backends only -- the cupy and dask+cupy
dispatchers were untested. A regression that dropped the kwargs in
either dispatcher would silently change the float polygon count and
would not be caught.
15 new tests cover:
- cupy: atol=0, rtol=0 strict equality on _REPRO_2173 produces three
distinct polygons; default tolerance still merges to one;
intermediate atol picks the documented splits; rtol-only branch
coverage at large/small values.
- dask+cupy: single-chunk and multi-chunk strict equality (the
multi-chunk case engages the _bucket_key_for_value cross-chunk
merge); default tolerance still merges adjacent pixels;
intermediate atol single + multi chunk.
- integer cupy and dask+cupy: huge atol does not collapse distinct
integer regions, matching the existing numpy / dask+numpy pins.
Mutation against the _polygonize_cupy float-branch forward call (drop
atol/rtol on the _polygonize_numpy call at polygonize.py:823-825)
flips 3 of 5 cupy tests red. Mutation against the dask path
(drop atol, rtol args from dask.delayed(_polygonize_chunk)(...) at
polygonize.py:1748-1754) flips 2 of 6 dask+cupy tests red. Source
was restored bit-exact via md5sum.
Test-only. No source changes. Updates the deep-sweep state CSV with
the pass-2 audit notes.
brendancol
left a comment
There was a problem hiding this comment.
Review
Scope: test additions only, no source changes. Reviewed the new file and the state CSV diff.
Blockers
None.
Suggestions
None. The tests follow the existing conventions in the polygonize coverage file:
cuda_and_cupy_availableanddask_array_availablemarkers are applied correctly so a CUDA-free host skips cleanly.- Strict-equality, intermediate-atol, default-tolerance, and integer-no-op cases mirror the numpy / dask+numpy pins for the same kwargs (1:1 parity with
test_polygonize_strict_float_equality,test_polygonize_custom_atol_intermediate,test_polygonize_dask_integer_atol_ignored). - The
_areas_by_valuehelper accepts an explicit atol/rtol for cross-backend bucket matching, matching the helper used intest_polygonize_dask_float_tolerance_matches_numpy_2171. - Mutation evidence is documented in the commit message: removing
atol=atol, rtol=rtolfrom_polygonize_cupyat lines 823-825 flips 3 cupy tests red; removing the same kwargs fromdask.delayed(_polygonize_chunk)(...)flips 2 dask+cupy tests red. The mutated source was restored bit-exact.
Nits
None.
Disposition
LGTM. Test-only PR closes a Cat 4 MEDIUM parameter-coverage gap surfaced by the 2026-05-27 test-coverage sweep on the polygonize module. The state CSV has the audit notes for the future re-inspection.
Expand atol/rtol coverage and tighten one docstring on the new
dask+cupy / cupy parameter-coverage tests. All additions are test-only
and confirmed via mutation evidence (cupy kwargs drop -> 3 reds;
dask.delayed kwargs drop -> 2 reds; source restored bit-exact).
- TestRtolDaskCuPy: new class mirroring TestRtolCuPy on the dask+cupy
backend. Adds three tests (large_rtol single + multi chunk,
small_rtol multi chunk) pinning the rtol-only branch through
_polygonize_chunk and _bucket_key_for_value with atol=0.
- TestIntermediateAtolDaskCuPy.test_large_atol_one_polygon_multi_chunk:
pins the cross-chunk merge bucket with a non-default atol (1e-4),
closing the missing single-chunk / multi-chunk pair for the large-
atol case.
- test_default_tolerance_still_merges_multi_chunk docstring: now
documents the intentional 2-vs-1 polygon count divergence between
single-chunk numpy (transitive merge: 1.0 <-> 1.000009 <-> 1.000018)
and the dask cross-chunk merge bucket (pairwise comparison only),
so the hard-coded assert len(v_dc) == 2 is no longer surprising.
19 passed (was 15), full polygonize suite 256 passed / 13 skipped.
Self-review (post-merge follow-up)Reviewed the diff against the correctness, backend-parity, and test-coverage rubric. No blockers. Pushed one follow-up commit (6f46951) to address the two coverage gaps below and clarify one docstring. All additions are test-only. What was added in 6f46951
Mutation evidence re-run on the expanded suite
Test counts
Suggestions deferred
|
Closes #2537.
Summary
test_polygonize_atol_rtol_backend_coverage_2026_05_27.pycovering theatol/rtolkwargs on the cupy and dask+cupy backends ofpolygonize().atol=0, rtol=0), intermediate atol splits, and the integer-no-op contract.Backend coverage
#2173and#2174tests; this PR does not duplicate those.Mutation evidence
atol=atol, rtol=rtolfrom the_polygonize_numpyforward call atpolygonize.py:823-825(cupy float branch) flips 3 of 5 cupy tests red.atol, rtolargs fromdask.delayed(_polygonize_chunk)(...)atpolygonize.py:1748-1754flips 2 of 6 dask+cupy tests red.md5sum.Test plan
pytest test_polygonize_atol_rtol_backend_coverage_2026_05_27.py) -> 15 passedtest_polygonize.py+ the two prior coverage files + this one) -> 252 passed, 13 skipped