@@ -490,6 +490,9 @@ instance ( Show (Class.TableConfig h)
490490 => Var h (WrapTable h IO k v b )
491491 -> Var h (WrapTable h IO k v b )
492492 -> Act h (WrapTable h IO k v b )
493+ Unions :: C k v b
494+ => V. Vector (Var h (WrapTable h IO k v b ))
495+ -> Act h (WrapTable h IO k v b )
493496
494497 initialState = Lockstep.Defaults. initialState initModelState
495498 nextState = Lockstep.Defaults. nextState
@@ -552,6 +555,8 @@ instance ( Eq (Class.TableConfig h)
552555 Just var1 == cast var2
553556 go (Union var1_1 var1_2) (Union var2_1 var2_2) =
554557 Just var1_1 == cast var2_1 && Just var1_2 == cast var2_2
558+ go (Unions vars1) (Unions vars2) =
559+ Just vars1 == cast vars2
555560 go _ _ = False
556561
557562 _coveredAllCases :: LockstepAction (ModelState h ) a -> ()
@@ -574,6 +579,7 @@ instance ( Eq (Class.TableConfig h)
574579 ListSnapshots {} -> ()
575580 Duplicate {} -> ()
576581 Union {} -> ()
582+ Unions {} -> ()
577583
578584{- ------------------------------------------------------------------------------
579585 InLockstep
@@ -681,6 +687,7 @@ instance ( Eq (Class.TableConfig h)
681687 ListSnapshots -> []
682688 Duplicate tableVar -> [SomeGVar tableVar]
683689 Union table1Var table2Var -> [SomeGVar table1Var, SomeGVar table2Var]
690+ Unions tableVars -> [SomeGVar tableVar | tableVar <- V. toList tableVars]
684691
685692 arbitraryWithVars ::
686693 ModelVarContext (ModelState h )
@@ -794,6 +801,7 @@ instance ( Eq (Class.TableConfig h)
794801 ListSnapshots {} -> OEither $ bimap OId (OList . fmap OId ) result
795802 Duplicate {} -> OEither $ bimap OId (const OTable ) result
796803 Union {} -> OEither $ bimap OId (const OTable ) result
804+ Unions {} -> OEither $ bimap OId (const OTable ) result
797805
798806 showRealResponse ::
799807 Proxy (RealMonad h IO )
@@ -818,6 +826,7 @@ instance ( Eq (Class.TableConfig h)
818826 ListSnapshots -> Just Dict
819827 Duplicate {} -> Nothing
820828 Union {} -> Nothing
829+ Unions {} -> Nothing
821830
822831instance ( Eq (Class. TableConfig h )
823832 , Class. IsTable h
@@ -852,6 +861,7 @@ instance ( Eq (Class.TableConfig h)
852861 ListSnapshots {} -> OEither $ bimap OId (OList . fmap OId ) result
853862 Duplicate {} -> OEither $ bimap OId (const OTable ) result
854863 Union {} -> OEither $ bimap OId (const OTable ) result
864+ Unions {} -> OEither $ bimap OId (const OTable ) result
855865
856866 showRealResponse ::
857867 Proxy (RealMonad h (IOSim s ))
@@ -876,6 +886,7 @@ instance ( Eq (Class.TableConfig h)
876886 ListSnapshots -> Just Dict
877887 Duplicate {} -> Nothing
878888 Union {} -> Nothing
889+ Unions {} -> Nothing
879890
880891{- ------------------------------------------------------------------------------
881892 RunModel
@@ -965,6 +976,9 @@ runModel lookUp = \case
965976 Union table1Var table2Var ->
966977 wrap MTable
967978 . Model. runModelM (Model. union Model. getResolve (getTable $ lookUp table1Var) (getTable $ lookUp table2Var))
979+ Unions tableVars ->
980+ wrap MTable
981+ . Model. runModelM (Model. unions Model. getResolve (V. map (getTable . lookUp) tableVars))
968982 where
969983 getTable ::
970984 ModelValue (ModelState h ) (WrapTable h IO k v b )
@@ -1043,6 +1057,8 @@ runIO action lookUp = ReaderT $ \(session, handler) -> do
10431057 WrapTable <$> Class. duplicate (unwrapTable $ lookUp' tableVar)
10441058 Union table1Var table2Var -> catchErr handler $
10451059 WrapTable <$> Class. union (unwrapTable $ lookUp' table1Var) (unwrapTable $ lookUp' table2Var)
1060+ Unions tableVars -> catchErr handler $
1061+ WrapTable <$> Class. unions (V. map (unwrapTable . lookUp') tableVars)
10461062
10471063 lookUp' :: Var h x -> Realized IO x
10481064 lookUp' = lookUpGVar (Proxy @ (RealMonad h IO )) lookUp
@@ -1097,6 +1113,8 @@ runIOSim action lookUp = ReaderT $ \(session, handler) ->
10971113 WrapTable <$> Class. duplicate (unwrapTable $ lookUp' tableVar)
10981114 Union table1Var table2Var -> catchErr handler $
10991115 WrapTable <$> Class. union (unwrapTable $ lookUp' table1Var) (unwrapTable $ lookUp' table2Var)
1116+ Unions tableVars -> catchErr handler $
1117+ WrapTable <$> Class. unions (V. map (unwrapTable . lookUp') tableVars)
11001118
11011119 lookUp' :: Var h x -> Realized (IOSim s ) x
11021120 lookUp' = lookUpGVar (Proxy @ (RealMonad h (IOSim s ))) lookUp
@@ -1155,6 +1173,7 @@ arbitraryActionWithVars _ label ctx (ModelState st _stats) =
11551173 OpenSnapshot {} -> ()
11561174 Duplicate {} -> ()
11571175 Union {} -> ()
1176+ Unions {} -> ()
11581177
11591178 genTableVar = QC. elements tableVars
11601179
@@ -1244,6 +1263,10 @@ arbitraryActionWithVars _ label ctx (ModelState st _stats) =
12441263 | length tableVars <= 5 -- no more than 5 tables at once
12451264 , False -- TODO: enable once table union is implemented
12461265 ]
1266+ ++ [ (2 , fmap Some $ Unions <$> genUnionsTableVars)
1267+ | length tableVars <= 5 -- no more than 5 tables at once
1268+ , False -- TODO: enable once table unions is implemented
1269+ ]
12471270
12481271 genActionsCursor :: [(Int , Gen (Any (LockstepAction (ModelState h ))))]
12491272 genActionsCursor
@@ -1296,6 +1319,20 @@ arbitraryActionWithVars _ label ctx (ModelState st _stats) =
12961319 genBlob :: Gen (Maybe b )
12971320 genBlob = QC. arbitrary
12981321
1322+ -- Generate at least a 2-way union, and at most a 3-way union.
1323+ --
1324+ -- Unit tests for 0-way and 1-way unions are included in the UnitTests
1325+ -- module. n-way unions for n>3 lead to larger unions, which are less likely
1326+ -- to be finished before the end of an action sequence.
1327+ genUnionsTableVars :: Gen (V. Vector (Var h (WrapTable h IO k v b )))
1328+ genUnionsTableVars = do
1329+ tableVar1 <- genTableVar
1330+ tableVar2 <- genTableVar
1331+ mtableVar3 <- QC. liftArbitrary genTableVar
1332+ pure $ V. fromList $ catMaybes [
1333+ Just tableVar1, Just tableVar2, mtableVar3
1334+ ]
1335+
12991336shrinkActionWithVars ::
13001337 forall h a . (
13011338 Eq (Class. TableConfig h )
@@ -1510,6 +1547,9 @@ updateStats action lookUp modelBefore _modelAfter result =
15101547 Union {}
15111548 | MEither (Right (MTable table)) <- result -> initCount table
15121549 | otherwise -> stats
1550+ Unions {}
1551+ | MEither (Right (MTable table)) <- result -> initCount table
1552+ | otherwise -> stats
15131553
15141554 -- Note that for the other actions we don't count success vs failure.
15151555 -- We don't need that level of detail. We just want to see the
@@ -1532,7 +1572,7 @@ updateStats action lookUp modelBefore _modelAfter result =
15321572 CloseCursor {} -> stats
15331573 ReadCursor {} -> stats
15341574 RetrieveBlobs {} -> stats
1535- CreateSnapshot {} -> stats
1575+ CreateSnapshot {} -> stats
15361576 DeleteSnapshot {} -> stats
15371577 ListSnapshots {} -> stats
15381578 where
0 commit comments