@@ -8,7 +8,6 @@ module Test.Database.LSMTree.Internal.Entry (tests) where
88
99import Data.Coerce
1010import Data.List.NonEmpty (NonEmpty )
11- import qualified Data.List.NonEmpty as NE
1211import Data.Semigroup
1312import Database.LSMTree.Extras.Generators ()
1413import Database.LSMTree.Internal.BlobRef
@@ -18,7 +17,6 @@ import qualified Database.LSMTree.Internal.Normal as Normal
1817import Test.QuickCheck
1918import Test.QuickCheck.Classes (semigroupLaws )
2019import Test.Tasty
21- import Test.Tasty.HUnit
2220import Test.Tasty.QuickCheck (QuickCheckMaxSize (QuickCheckMaxSize ),
2321 QuickCheckTests (QuickCheckTests ), testProperty )
2422import Test.Util.QC
@@ -30,49 +28,66 @@ tests = adjustOption (\_ -> QuickCheckTests 10000) $
3028 testClassLaws " EntrySG" $
3129 semigroupLaws (Proxy @ (EntrySG (Sum Int ) BlobSpanSG ))
3230 , testClassLaws " NormalUpdateSG" $
33- semigroupLaws (Proxy @ (NormalUpdateSG (Sum Int ) String ))
31+ -- Note that we are using Unlawful here because mupserts /should/ not
32+ -- show up for normal updates.
33+ semigroupLaws (Proxy @ (NormalUpdateSG (Unlawful Int ) String ))
3434 , testClassLaws " MonoidalUpdateSG" $
3535 semigroupLaws (Proxy @ (MonoidalUpdateSG (Sum Int )))
3636 , testProperty " prop_resolveEntriesNormalSemantics" $
37- prop_resolveEntriesNormalSemantics @ Int @ String
37+ -- Note that we are using Unlawful here because mupserts /should/ not
38+ -- show up for normal updates.
39+ prop_resolveEntriesNormalSemantics @ (Unlawful Int ) @ String
3840 , testProperty " prop_resolveMonoidalSemantics" $
3941 prop_resolveMonoidalSemantics @ (Sum Int )
40- , testCase " example resolveEntriesNormal" $ do
41- let es = [InsertWithBlob (2 :: Int ) ' a' , Insert 17 ]
42- Just (Normal. Insert 2 (Just ' a' )) @=?
43- resolveEntriesNormal (NE. fromList es)
44- , testCase " example resolveEntriesMonoidal" $ do
45- let es = [Mupdate (Sum 11 :: Sum Int ), Mupdate (Sum 5 ), Insert 1 ]
46- Just (Monoidal. Insert (Sum 17 )) @=?
47- resolveEntriesMonoidal (<>) (NE. fromList es)
4842 ]
4943
44+ -- | @resolve == fromEntry . resolve . toEntry@
5045prop_resolveEntriesNormalSemantics ::
51- (Show v , Show blob , Eq v , Eq blob )
46+ (Show v , Show blob , Eq v , Eq blob , Semigroup v )
5247 => NonEmpty (Normal. Update v blob )
5348 -> Property
54- prop_resolveEntriesNormalSemantics es = real === expected
55- where expected = coerce ( Just . foldr1 (<>) . fmap NormalUpdateSG $ es)
56- real = resolveEntriesNormal ( fmap updateToEntryNormal es)
49+ prop_resolveEntriesNormalSemantics es = expected === real
50+ where expected = Just . unNormalUpdateSG . sconcat . fmap NormalUpdateSG $ es
51+ real = entryToUpdateNormal (sconcat ( fmap updateToEntryNormal es) )
5752
53+ -- | @resolve == fromEntry . resolve . toEntry@
5854prop_resolveMonoidalSemantics ::
5955 (Show v , Eq v , Semigroup v )
6056 => NonEmpty (Monoidal. Update v ) -> Property
61- prop_resolveMonoidalSemantics es = real === expected
62- where expected = coerce (Just . foldr1 (<>) . fmap MonoidalUpdateSG $ es)
63- real = resolveEntriesMonoidal (<>) (fmap updateToEntryMonoidal es)
57+ prop_resolveMonoidalSemantics es = expected === real
58+ where expected = Just . unMonoidalUpdateSG . sconcat . fmap MonoidalUpdateSG $ es
59+ real = entryToUpdateMonoidal (sconcat (fmap updateToEntryMonoidal es))
60+
61+ {- ------------------------------------------------------------------------------
62+ Types
63+ -------------------------------------------------------------------------------}
64+
65+ -- | A wrapper type with a 'Semigroup' instance that always throws an error.
66+ newtype Unlawful a = Unlawful a
67+ deriving stock (Show , Eq )
68+ deriving newtype Arbitrary
69+
70+ -- | A 'Semigroup' instance that always throws an error.
71+ instance Semigroup (Unlawful a ) where
72+ _ <> _ = error " unlawful"
6473
6574-- | Semigroup wrapper for 'Normal.Update'
6675newtype NormalUpdateSG v blob = NormalUpdateSG (Normal. Update v blob )
6776 deriving stock (Show , Eq )
6877 deriving newtype (Arbitrary )
6978 deriving Semigroup via First (Normal. Update v blob )
7079
80+ unNormalUpdateSG :: NormalUpdateSG v b -> Normal. Update v b
81+ unNormalUpdateSG (NormalUpdateSG x) = x
82+
7183-- | Semigroup wrapper for 'Monoidal.Update'
7284newtype MonoidalUpdateSG v = MonoidalUpdateSG (Monoidal. Update v )
7385 deriving stock (Show , Eq )
7486 deriving newtype (Arbitrary )
7587
88+ unMonoidalUpdateSG :: MonoidalUpdateSG v -> Monoidal. Update v
89+ unMonoidalUpdateSG (MonoidalUpdateSG x) = x
90+
7691instance Semigroup v => Semigroup (MonoidalUpdateSG v ) where
7792 (<>) = coerce $ \ upd1 upd2 -> case (upd1 :: Monoidal. Update v , upd2 ) of
7893 (e1@ Monoidal. Delete , _ ) -> e1
@@ -81,24 +96,22 @@ instance Semigroup v => Semigroup (MonoidalUpdateSG v) where
8196 (Monoidal. Mupsert v1 , Monoidal. Insert v2) -> Monoidal. Insert (v1 <> v2)
8297 (Monoidal. Mupsert v1 , Monoidal. Mupsert v2) -> Monoidal. Mupsert (v1 <> v2)
8398
84- -- | Semigroup wrapper for Entry
8599newtype EntrySG v blob = EntrySG (Entry v blob )
86100 deriving stock (Show , Eq )
87-
88- -- | As long as values are a semigroup, an Entry is too
89- instance Semigroup v => Semigroup (EntrySG v blob ) where
90- EntrySG e1 <> EntrySG e2 = EntrySG (combine (<>) e1 e2)
101+ deriving newtype Semigroup
91102
92103instance (Arbitrary v , Arbitrary blob ) => Arbitrary (EntrySG v blob ) where
93104 arbitrary = arbitrary2
94105 shrink = shrink2
95106
107+ -- | We do not use the @'Arbitrary' 'Entry'@ instance here, because we want to
108+ -- generate each constructor with equal probability.
96109instance Arbitrary2 EntrySG where
97110 liftArbitrary2 genVal genBlob = EntrySG <$> frequency
98111 [ (1 , Insert <$> genVal)
99- , (1 , InsertWithBlob <$> genVal <*> genBlob)
100- , (1 , Mupdate <$> genVal)
101- , (1 , pure Delete )
112+ , (1 , InsertWithBlob <$> genVal <*> genBlob)
113+ , (1 , Mupdate <$> genVal)
114+ , (1 , pure Delete )
102115 ]
103116
104117 liftShrink2 shrinkVal shrinkBlob = coerce $ \ case
@@ -127,8 +140,8 @@ updateToEntryNormal = \case
127140 Normal. Insert v (Just b) -> InsertWithBlob v b
128141 Normal. Delete -> Delete
129142
130- _entryToUpdateNormal :: Entry v blob -> Maybe (Normal. Update v blob )
131- _entryToUpdateNormal = \ case
143+ entryToUpdateNormal :: Entry v blob -> Maybe (Normal. Update v blob )
144+ entryToUpdateNormal = \ case
132145 Insert v -> Just (Normal. Insert v Nothing )
133146 InsertWithBlob v b -> Just (Normal. Insert v (Just b))
134147 Mupdate _ -> Nothing
@@ -140,8 +153,8 @@ updateToEntryMonoidal = \case
140153 Monoidal. Mupsert v -> Mupdate v
141154 Monoidal. Delete -> Delete
142155
143- _entryToUpdateMonoidal :: Entry v blob -> Maybe (Monoidal. Update v )
144- _entryToUpdateMonoidal = \ case
156+ entryToUpdateMonoidal :: Entry v blob -> Maybe (Monoidal. Update v )
157+ entryToUpdateMonoidal = \ case
145158 Insert v -> Just (Monoidal. Insert v)
146159 InsertWithBlob _ _ -> Nothing
147160 Mupdate v -> Just (Monoidal. Mupsert v)
0 commit comments