@@ -27,7 +27,10 @@ import qualified Data.Vector.Unboxed as VU
2727import qualified Data.Vector.Unboxed.Base as VU
2828import Data.Word
2929import Database.LSMTree.Extras
30- import Database.LSMTree.Extras.Generators as Gen
30+ import Database.LSMTree.Extras.Generators (BiasedKeyForIndexCompact ,
31+ ChunkSize (.. ), LogicalPageSummaries ,
32+ LogicalPageSummary (.. ), Pages (.. ), genRawBytes ,
33+ isKeyForIndexCompact , labelPages , toAppends )
3134import Database.LSMTree.Extras.Index (Append (.. ), appendToCompact )
3235import Database.LSMTree.Internal.BitMath
3336import Database.LSMTree.Internal.Chunk as Chunk (toByteString )
@@ -36,6 +39,8 @@ import Database.LSMTree.Internal.Index.Compact
3639import Database.LSMTree.Internal.Index.CompactAcc
3740import Database.LSMTree.Internal.Page (PageNo (PageNo ), PageSpan ,
3841 multiPage , singlePage )
42+ import Database.LSMTree.Internal.RawBytes (RawBytes (.. ))
43+ import qualified Database.LSMTree.Internal.RawBytes as RB
3944import Database.LSMTree.Internal.Serialise
4045import Numeric (showHex )
4146import Prelude hiding (max , min , pi )
@@ -51,7 +56,9 @@ import Text.Printf (printf)
5156
5257tests :: TestTree
5358tests = testGroup " Test.Database.LSMTree.Internal.Index.Compact" [
54- testProperty " prop_distribution @BiasedKeyForIndexCompact" $
59+ testGroup " TestKey" $
60+ prop_arbitraryAndShrinkPreserveInvariant @ TestKey noTags isTestKey
61+ , testProperty " prop_distribution @BiasedKeyForIndexCompact" $
5562 prop_distribution @ BiasedKeyForIndexCompact
5663 , testProperty " prop_searchMinMaxKeysAfterConstruction" $
5764 prop_searchMinMaxKeysAfterConstruction @ BiasedKeyForIndexCompact 100
@@ -127,6 +134,57 @@ tests = testGroup "Test.Database.LSMTree.Internal.Index.Compact" [
127134 ]
128135 ]
129136
137+ {- ------------------------------------------------------------------------------
138+ Test key
139+ -------------------------------------------------------------------------------}
140+
141+ -- | Key type for compact index tests
142+ --
143+ -- Tests outside this module don't have to worry about generating clashing keys.
144+ -- We can assume that the compact index handles clashes correctly, because we
145+ -- test this extensively in this module already.
146+ newtype TestKey = TestKey RawBytes
147+ deriving stock (Show , Eq , Ord )
148+ deriving newtype SerialiseKey
149+
150+ -- | Generate keys with a non-neglible probability of clashes. This generates
151+ -- sliced keys too.
152+ --
153+ -- Note: recall that keys /clash/ only if their primary bits (first 8 bytes)
154+ -- match. It does not matter whether the other bytes do not match.
155+ instance Arbitrary TestKey where
156+ arbitrary = do
157+ -- Generate primary bits from a relatively small distribution. This
158+ -- ensures that we get clashes between keys with a non-negligible
159+ -- probability.
160+ primBits <- do
161+ lastPrefixByte <- QC. getSmall <$> arbitrary
162+ pure $ RB. pack ([0 ,0 ,0 ,0 ,0 ,0 ,0 ] <> [lastPrefixByte])
163+ -- The rest of the bits after the primary bits can be anything
164+ restBits <- genRawBytes
165+ -- The compact index should store keys without retaining unused memory.
166+ -- Therefore, we generate slices of keys too.
167+ prefix <- elements [RB. pack [] , RB. pack [0 ]]
168+ suffix <- elements [RB. pack [] , RB. pack [0 ]]
169+ -- Combine the bytes and make sure to take out only the slice we need.
170+ let bytes = prefix <> primBits <> restBits <> suffix
171+ n = RB. size primBits + RB. size restBits
172+ bytes' = RB. take n $ RB. drop (RB. size prefix) bytes
173+ pure $ TestKey bytes'
174+
175+ -- Shrink keys extensively: most failures will occur in small counterexamples,
176+ -- so we don't have to limit the number of shrinks as much.
177+ shrink (TestKey bytes) = [
178+ TestKey bytes'
179+ | let RawBytes vec = bytes
180+ , vec' <- VP. fromList <$> shrink (VP. toList vec)
181+ , let bytes' = RawBytes vec'
182+ , isKeyForIndexCompact bytes'
183+ ]
184+
185+ isTestKey :: TestKey -> Bool
186+ isTestKey (TestKey bytes) = isKeyForIndexCompact bytes
187+
130188{- ------------------------------------------------------------------------------
131189 Properties
132190-------------------------------------------------------------------------------}
0 commit comments