@@ -43,6 +43,7 @@ type ModelOp r = Model -> (r, Model)
4343modelNew :: ModelOp ModelLSM
4444modelInsert :: ModelLSM -> Key -> Value -> Maybe Blob -> ModelOp ()
4545modelDelete :: ModelLSM -> Key -> ModelOp ()
46+ modelMupsert :: ModelLSM -> Key -> Value -> ModelOp ()
4647modelLookup :: ModelLSM -> Key -> ModelOp (LookupResult Value Blob )
4748modelDuplicate :: ModelLSM -> ModelOp ModelLSM
4849modelDump :: ModelLSM -> ModelOp (Map Key (Value , Maybe Blob ))
@@ -61,14 +62,18 @@ modelInsert mlsm k v b Model {mlsms} =
6162modelDelete mlsm k Model {mlsms} =
6263 (() , Model { mlsms = Map. adjust (Map. delete k) mlsm mlsms })
6364
65+ modelMupsert mlsm k v Model {mlsms} =
66+ (() , Model { mlsms = Map. adjust (Map. insertWith f k (v, Nothing )) mlsm mlsms })
67+ where
68+ f _ (vOld, b) = (resolveValue v vOld, b)
69+
6470modelLookup mlsm k model@ Model {mlsms} =
6571 (result, model)
6672 where
6773 Just mval = Map. lookup mlsm mlsms
6874 result = case Map. lookup k mval of
69- Nothing -> NotFound
70- Just (v, Nothing ) -> Found v
71- Just (v, Just b) -> FoundWithBlob v b
75+ Nothing -> NotFound
76+ Just (v, mb) -> Found v mb
7277
7378modelDuplicate mlsm Model {mlsms} =
7479 (mlsm', Model { mlsms = Map. insert mlsm' mval mlsms })
@@ -95,6 +100,11 @@ instance StateModel (Lockstep Model) where
95100 -> Either (ModelVar Model Key ) Key
96101 -> Action (Lockstep Model ) ()
97102
103+ AMupsert :: ModelVar Model (LSM RealWorld )
104+ -> Either (ModelVar Model Key ) Key
105+ -> Value
106+ -> Action (Lockstep Model ) (Key )
107+
98108 ALookup :: ModelVar Model (LSM RealWorld )
99109 -> Either (ModelVar Model Key ) Key
100110 -> Action (Lockstep Model ) (LookupResult Value Blob )
@@ -144,6 +154,8 @@ instance InLockstep Model where
144154 : case evk of Left vk -> [SomeGVar vk]; _ -> []
145155 usedVars (ADelete v evk) = SomeGVar v
146156 : case evk of Left vk -> [SomeGVar vk]; _ -> []
157+ usedVars (AMupsert v evk _) = SomeGVar v
158+ : case evk of Left vk -> [SomeGVar vk]; _ -> []
147159 usedVars (ALookup v evk) = SomeGVar v
148160 : case evk of Left vk -> [SomeGVar vk]; _ -> []
149161 usedVars (ADuplicate v) = [SomeGVar v]
@@ -185,6 +197,19 @@ instance InLockstep Model where
185197 <*> existingKey)
186198 | not (null kvars)
187199 ]
200+ -- mupserts of potentially fresh keys
201+ ++ [ (1 , fmap Some $
202+ AMupsert <$> elements vars
203+ <*> freshKey
204+ <*> arbitrary @ Value )
205+ ]
206+ -- mupserts of the same keys as used earlier
207+ ++ [ (1 , fmap Some $
208+ AMupsert <$> elements vars
209+ <*> existingKey
210+ <*> arbitrary @ Value )
211+ | not (null kvars)
212+ ]
188213 -- lookup of arbitrary keys:
189214 ++ [ (1 , fmap Some $
190215 ALookup <$> elements vars
@@ -215,6 +240,14 @@ instance InLockstep Model where
215240 shrinkWithVars _ctx _model (ADelete var (Left _kv)) =
216241 [ Some $ ADelete var (Right k) | k <- shrink (K 100 ) ]
217242
243+ shrinkWithVars _ctx _model (AMupsert var (Right k) v) =
244+ [ Some $ AInsert var (Right k) v Nothing ] ++
245+ [ Some $ AMupsert var (Right k') v' | (k', v') <- shrink (k, v) ]
246+
247+ shrinkWithVars _ctx _model (AMupsert var (Left kv) v) =
248+ [ Some $ AInsert var (Left kv) v Nothing ] ++
249+ [ Some $ AMupsert var (Right k') v' | (k', v') <- shrink (K 100 , v) ]
250+
218251 shrinkWithVars _ctx _model _action = []
219252
220253
@@ -224,13 +257,15 @@ instance RunLockstep Model IO where
224257 (ANew , _) -> ORef
225258 (AInsert {}, x) -> OId x
226259 (ADelete {}, x) -> OId x
260+ (AMupsert {}, x) -> OId x
227261 (ALookup {}, x) -> OId x
228262 (ADump {}, x) -> OId x
229263 (ADuplicate {}, _) -> ORef
230264
231265 showRealResponse _ ANew = Nothing
232266 showRealResponse _ AInsert {} = Just Dict
233267 showRealResponse _ ADelete {} = Just Dict
268+ showRealResponse _ AMupsert {} = Just Dict
234269 showRealResponse _ ALookup {} = Just Dict
235270 showRealResponse _ ADump {} = Just Dict
236271 showRealResponse _ ADuplicate {} = Nothing
@@ -255,6 +290,8 @@ runActionIO action lookUp =
255290 where k = either lookUpVar id evk
256291 ADelete var evk -> delete tr (lookUpVar var) k >> return ()
257292 where k = either lookUpVar id evk
293+ AMupsert var evk v -> mupsert tr (lookUpVar var) k v >> return k
294+ where k = either lookUpVar id evk
258295 ALookup var evk -> lookup (lookUpVar var) k
259296 where k = either lookUpVar id evk
260297 ADuplicate var -> duplicate (lookUpVar var)
@@ -283,6 +320,10 @@ runModel action ctx m =
283320 where (() , m') = modelDelete (lookUpLsMVar var) k m
284321 k = either lookUpKeyVar id evk
285322
323+ AMupsert var evk v -> (MInsert k, m')
324+ where (() , m') = modelMupsert (lookUpLsMVar var) k v m
325+ k = either lookUpKeyVar id evk
326+
286327 ALookup var evk -> (MLookup mv, m')
287328 where (mv, m') = modelLookup (lookUpLsMVar var) k m
288329 k = either lookUpKeyVar id evk
0 commit comments