11# Stateful tests for arbitrary Zarr stores.
2-
3-
42import hypothesis .strategies as st
3+ import pytest
54from hypothesis import assume , note
65from hypothesis .stateful import (
76 RuleBasedStateMachine ,
7+ Settings ,
8+ initialize ,
89 invariant ,
910 precondition ,
1011 rule ,
12+ run_state_machine_as_test ,
1113)
1214from hypothesis .strategies import DataObject
1315
1416import zarr
1517from zarr .abc .store import AccessMode , Store
1618from zarr .core .buffer import BufferPrototype , cpu , default_buffer_prototype
17- from zarr .store import MemoryStore
18- from zarr .testing .strategies import key_ranges , paths
19+ from zarr .store import ZipStore
20+ from zarr .testing .strategies import key_ranges , keys
1921
2022
2123class SyncStoreWrapper (zarr .core .sync .SyncMixin ):
@@ -103,13 +105,17 @@ class ZarrStoreStateMachine(RuleBasedStateMachine):
103105 https://hypothesis.readthedocs.io/en/latest/stateful.html
104106 """
105107
106- def __init__ (self ) -> None :
108+ def __init__ (self , store ) -> None :
107109 super ().__init__ ()
108110 self .model : dict [str , bytes ] = {}
109- self .store = SyncStoreWrapper (MemoryStore ( mode = "w" ) )
111+ self .store = SyncStoreWrapper (store )
110112 self .prototype = default_buffer_prototype ()
111113
112- @rule (key = paths , data = st .binary (min_size = 0 , max_size = 100 ))
114+ @initialize ()
115+ def init_store (self ):
116+ self .store .clear ()
117+
118+ @rule (key = keys , data = st .binary (min_size = 0 , max_size = 100 ))
113119 def set (self , key : str , data : DataObject ) -> None :
114120 note (f"(set) Setting { key !r} with { data } " )
115121 assert not self .store .mode .readonly
@@ -118,7 +124,7 @@ def set(self, key: str, data: DataObject) -> None:
118124 self .model [key ] = data_buf
119125
120126 @precondition (lambda self : len (self .model .keys ()) > 0 )
121- @rule (key = paths , data = st .data ())
127+ @rule (key = keys , data = st .data ())
122128 def get (self , key : str , data : DataObject ) -> None :
123129 key = data .draw (
124130 st .sampled_from (sorted (self .model .keys ()))
@@ -128,7 +134,7 @@ def get(self, key: str, data: DataObject) -> None:
128134 # to bytes here necessary because data_buf set to model in set()
129135 assert self .model [key ].to_bytes () == (store_value .to_bytes ())
130136
131- @rule (key = paths , data = st .data ())
137+ @rule (key = keys , data = st .data ())
132138 def get_invalid_keys (self , key : str , data : DataObject ) -> None :
133139 note ("(get_invalid)" )
134140 assume (key not in self .model .keys ())
@@ -186,7 +192,7 @@ def empty(self) -> None:
186192 # make sure they either both are or both aren't empty (same state)
187193 assert self .store .empty () == (not self .model )
188194
189- @rule (key = paths )
195+ @rule (key = keys )
190196 def exists (self , key : str ) -> None :
191197 note ("(exists)" )
192198
@@ -227,4 +233,10 @@ def check_keys(self) -> None:
227233 note ("checking keys / exists / empty" )
228234
229235
230- StatefulStoreTest = ZarrStoreStateMachine .TestCase
236+ def test_zarr_hierarchy (sync_store : Store ):
237+ def mk_test_instance_sync ():
238+ return ZarrStoreStateMachine (sync_store )
239+
240+ if isinstance (sync_store , ZipStore ):
241+ pytest .skip (reason = "ZipStore does not support delete" )
242+ run_state_machine_as_test (mk_test_instance_sync , settings = Settings (report_multiple_bugs = False ))
0 commit comments