Skip to content

Commit 1f13742

Browse files
authored
test(indexing): broaden planner property coverage (#4346)
* docs(indexing): ground design and integration claims in current behavior Assisted-by: Codex:GPT-6 * docs(indexing): correct reader lazy-array and cache contracts Assisted-by: Codex:GPT-6 * fix(indexing): validate wire boundaries and clarify format contracts Assisted-by: Codex:GPT-6 * fix(indexing): validate selector bounds and shared dependencies Correct mathematical API documentation to match supported coordinate, grid, and chunk projection contracts. Assisted-by: Codex:GPT-6 * docs(indexing): reconcile reader contracts and record audit fixes Assisted-by: Codex:GPT-6 * docs(indexing): reconcile audit with current partition implementation Retain the existing unsigned selector fix and update the unsupported mixed-dependency error assertion for general intersection routing. Assisted-by: Codex:GPT-6 * docs(indexing): clarify planning coverage and benchmark measurement boundaries Assisted-by: Codex:GPT-6 * fix(indexing): group signed chunk coordinates without collisions Use lexicographic tuple grouping when chunk indices contain negative values. Cover shared one-axis and two-axis array dependencies, repeated points, and extreme signed coordinates. Assisted-by: Codex:GPT-6 * docs(indexing): state remaining planner limits precisely Assisted-by: Codex:GPT-6 * test(indexing): broaden planner property coverage Assisted-by: Codex:GPT-6 * test(indexing): generate mixed affine planner dependencies Assisted-by: Codex:GPT-6 * docs(indexing): number audit changelog entries for PR 4345 Assisted-by: Codex:GPT-6 * docs(indexing): describe current contracts in docstrings Remove implementation history and unsupported historical claims from source and test docstrings. Distinguish immutable coordinate mappings from mutable source values. Assisted-by: Codex:GPT-6
1 parent 8ff7cb1 commit 1f13742

2 files changed

Lines changed: 112 additions & 11 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Expand planner property tests across signed origins and chunk IDs, custom grids, mixed affine and lookup dependencies, duplicate coordinates, and empty domains. Verify exact request coverage and storage mapping with an independent pointwise oracle.

packages/zarr-indexing/tests/test_chunk_resolution.py

Lines changed: 111 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import numpy as np
66
import pytest
7-
from hypothesis import assume, given
7+
from hypothesis import assume, given, settings
88
from hypothesis import strategies as st
99

1010
import zarr_indexing
@@ -955,25 +955,125 @@ def test_independent_components_scatter_through_lazy_array(reader_kind: str) ->
955955
np.testing.assert_array_equal(view.result(), source[a, b, c, :])
956956

957957

958-
@given(data=st.data())
959-
def test_component_dependency_graph_matches_pointwise_oracle(data: st.DataObject) -> None:
960-
shape = tuple(data.draw(st.lists(st.integers(1, 3), min_size=0, max_size=3)))
958+
class SignedGrid:
959+
"""An unbounded grid with translated boundaries and signed chunk identifiers."""
960+
961+
def __init__(self, size: int, origin: int) -> None:
962+
self.size = size
963+
self.origin = origin
964+
965+
def index_to_chunk(self, index: int) -> int:
966+
return (index - self.origin) // self.size
967+
968+
def indices_to_chunks(
969+
self, indices: np.ndarray[Any, np.dtype[np.intp]]
970+
) -> np.ndarray[Any, np.dtype[np.intp]]:
971+
return (indices - self.origin) // self.size
972+
973+
def chunk_offset(self, chunk: int) -> int:
974+
return self.origin + chunk * self.size
975+
976+
def chunk_size(self, chunk: int) -> int:
977+
return self.size
978+
979+
980+
@settings(max_examples=300)
981+
@given(data=st.data(), shape=st.lists(st.integers(0, 3), min_size=0, max_size=3))
982+
def test_component_dependency_graph_matches_pointwise_oracle(
983+
data: st.DataObject, shape: list[int]
984+
) -> None:
985+
"""Catch lost duplicates, signed chunk collisions, and incorrect request origins.
986+
987+
Enumerate the transform's small domain directly: no planner intersection,
988+
grouping, or dependency helpers contribute to the expected mapping.
989+
"""
990+
origin = tuple(data.draw(st.integers(-4, 4)) for _ in shape)
961991
output_rank = data.draw(st.integers(1, 5))
962-
maps = []
992+
affine_axes = {axis for axis in range(len(shape)) if data.draw(st.booleans())}
993+
maps: list[ArrayMap | ConstantMap | DimensionMap] = [
994+
DimensionMap(
995+
axis, offset=data.draw(st.integers(-3, 3)), stride=data.draw(st.integers(-2, 2))
996+
)
997+
for axis in sorted(affine_axes)
998+
]
963999
for _ in range(output_rank):
964-
dependencies = data.draw(st.lists(st.booleans(), min_size=len(shape), max_size=len(shape)))
1000+
if data.draw(st.booleans()):
1001+
maps.append(ConstantMap(data.draw(st.integers(-3, 3))))
1002+
continue
1003+
# Reserve affine axes for one DimensionMap each. Unsupported shared
1004+
# affine dependencies are exercised explicitly in the error properties.
1005+
dependencies = [
1006+
axis not in affine_axes and data.draw(st.booleans()) for axis in range(len(shape))
1007+
]
9651008
array_shape = tuple(
9661009
size if dependent else 1 for size, dependent in zip(shape, dependencies, strict=True)
9671010
)
9681011
count = int(np.prod(array_shape))
969-
values = data.draw(st.lists(st.integers(0, 3), min_size=count, max_size=count))
970-
maps.append(ArrayMap(np.array(values, dtype=np.intp).reshape(array_shape)))
971-
transform = IndexTransform(IndexDomain.from_shape(shape), tuple(maps))
972-
grids = dimension_grids_from_chunks((2,) * output_rank, (4,) * output_rank)
973-
partition = plan_chunks(transform, grids).partition()
1012+
# A small value range produces repeated storage points at distinct request positions.
1013+
values = data.draw(st.lists(st.integers(-2, 2), min_size=count, max_size=count))
1014+
maps.append(
1015+
ArrayMap(
1016+
np.array(values, dtype=np.intp).reshape(array_shape),
1017+
offset=data.draw(st.integers(-3, 3)),
1018+
stride=data.draw(st.integers(-2, 2)),
1019+
)
1020+
)
1021+
grids = [SignedGrid(data.draw(st.integers(1, 3)), data.draw(st.integers(-3, 3))) for _ in maps]
1022+
transform = IndexTransform(
1023+
IndexDomain(origin, tuple(lo + size for lo, size in zip(origin, shape, strict=True))),
1024+
tuple(maps),
1025+
)
1026+
expected = {point: _storage_of(transform, point) for point in _points(transform.domain)}
1027+
expected_chunks = {
1028+
tuple(grid.index_to_chunk(value) for grid, value in zip(grids, storage, strict=True))
1029+
for storage in expected.values()
1030+
}
1031+
partition = plan_chunks(transform, tuple(grids)).partition()
9741032
rows = list(partition)
9751033
_check_projections(transform, rows)
1034+
assert {row.chunk_coords for row in rows} == expected_chunks
1035+
assert len(rows) == len(expected_chunks)
9761036
assert partition.chunk_coords().tolist() == [list(row.chunk_coords) for row in rows]
1037+
reconstructed = []
1038+
for row in rows:
1039+
assert row.chunk_domain.inclusive_min == tuple(
1040+
grid.chunk_offset(chunk) for grid, chunk in zip(grids, row.chunk_coords, strict=True)
1041+
)
1042+
for cell in _points(row.cell_transform.domain):
1043+
request = _storage_of(row.cell_transform, cell)
1044+
storage = tuple(
1045+
local + grid.chunk_offset(chunk)
1046+
for local, grid, chunk in zip(
1047+
_storage_of(row.chunk_transform, cell), grids, row.chunk_coords, strict=True
1048+
)
1049+
)
1050+
reconstructed.append((request, storage))
1051+
# A list comparison retains multiplicity: repeating one position cannot hide a missing one.
1052+
assert sorted(reconstructed) == sorted(expected.items())
1053+
1054+
1055+
@given(origin=st.integers(-4, 4), size=st.integers(2, 5), stride=st.sampled_from([-2, -1, 1, 2]))
1056+
def test_generated_shared_affine_dependency_is_rejected(
1057+
origin: int, size: int, stride: int
1058+
) -> None:
1059+
transform = IndexTransform(
1060+
IndexDomain((origin,), (origin + size,)),
1061+
(DimensionMap(0, stride=stride), DimensionMap(0, offset=3)),
1062+
)
1063+
with pytest.raises(ValueError, match="read input axis 0"):
1064+
list(plan_chunks(transform, (SignedGrid(2, -1), SignedGrid(3, 1))))
1065+
1066+
1067+
@given(origin=st.integers(-4, 4), size=st.integers(2, 5), stride=st.sampled_from([-2, -1, 1, 2]))
1068+
def test_generated_mixed_affine_array_dependency_is_rejected(
1069+
origin: int, size: int, stride: int
1070+
) -> None:
1071+
transform = IndexTransform(
1072+
IndexDomain((origin,), (origin + size,)),
1073+
(DimensionMap(0, stride=stride), ArrayMap(np.zeros(size, dtype=np.intp))),
1074+
)
1075+
with pytest.raises(NotImplementedError, match="also bound by a slice map"):
1076+
list(plan_chunks(transform, (SignedGrid(2, -1), SignedGrid(3, 1))))
9771077

9781078

9791079
@pytest.mark.parametrize("stride", [0, 1, 2, -2])

0 commit comments

Comments
 (0)