Skip to content

Commit d492d74

Browse files
author
NIK-TIGER-BILL
committed
fix(testing): correct delete_dir prefix matching in stateful tests
Fix flaky stateful test bookkeeping when delete_dir matches string prefixes instead of true directory descendants. A path such as 6/faNT... could be incorrectly removed when deleting 6/f. Closes #3977 Signed-off-by: NIK-TIGER-BILL <nik.tiger.bill@github.com>
1 parent c0e2afa commit d492d74

3 files changed

Lines changed: 24 additions & 1 deletion

File tree

changes/3977.bugfix.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix flaky stateful test bookkeeping when `delete_dir` matches string prefixes instead of true directory descendants. Previously a path such as `6/faNT…` could be incorrectly removed when deleting `6/f`. (See [issue #3977](https://github.com/zarr-developers/zarr-python/issues/3977).)

src/zarr/testing/stateful.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ def delete_dir(self, data: DataObject) -> None:
306306

307307
matches = set()
308308
for node in self.all_groups | self.all_arrays:
309-
if node.startswith(path):
309+
if node == path or node.startswith(path + "/"):
310310
matches.add(node)
311311
self.all_groups = self.all_groups - matches
312312
self.all_arrays = self.all_arrays - matches

tests/test_store/test_stateful.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,25 @@ def mk_test_instance_sync() -> ZarrStoreStateMachine:
4949
# But LocalStore, directories can hang around even after a key is delete-d.
5050
pytest.skip(reason="Test isn't suitable for LocalStore.")
5151
run_state_machine_as_test(mk_test_instance_sync) # type: ignore[no-untyped-call]
52+
53+
54+
def test_delete_dir_prefix_matching() -> None:
55+
"""Regression test for delete_dir prefix matching bug (GH#3977).
56+
57+
Verifies that delete_dir bookkeeping only removes exact path matches
58+
and true descendants, not unrelated nodes that merely share a string
59+
prefix (e.g. ``6/faNT…`` must NOT be deleted when removing ``6/f``).
60+
"""
61+
all_groups = {"6/f", "6/faNT7p7jvJsO3_C._HYi", "other"}
62+
all_arrays = {"6/f/child", "6/other"}
63+
path = "6/f"
64+
65+
matches = set()
66+
for node in all_groups | all_arrays:
67+
if node == path or node.startswith(path + "/"):
68+
matches.add(node)
69+
70+
assert matches == {"6/f", "6/f/child"}
71+
assert "6/faNT7p7jvJsO3_C._HYi" not in matches
72+
assert "other" not in matches
73+
assert "6/other" not in matches

0 commit comments

Comments
 (0)