88-- add proper support for IOSim for fault testing.
99module Test.Database.LSMTree.Internal (tests ) where
1010
11- import qualified Control.Concurrent.Class.MonadSTM.RWVar as RW
1211import Control.Exception
1312import Control.Monad (void )
1413import Control.Tracer
15- import Data.Bifunctor
1614import Data.Coerce (coerce )
1715import Data.Foldable (traverse_ )
1816import qualified Data.Map.Strict as Map
19- import Data.Maybe (fromMaybe , isJust , mapMaybe )
20- import Data.Monoid (Sum (.. ))
17+ import Data.Maybe (isJust , mapMaybe )
2118import qualified Data.Vector as V
22- import Data.Word (Word64 )
23- import Database.LSMTree.Extras (showPowersOf )
2419import Database.LSMTree.Extras.Generators (KeyForIndexCompact (.. ))
2520import Database.LSMTree.Internal
2621import Database.LSMTree.Internal.BlobRef
2722import Database.LSMTree.Internal.Config
2823import Database.LSMTree.Internal.Entry
29- import Database.LSMTree.Internal.MergeSchedule
30- import Database.LSMTree.Internal.Paths (mkSnapshotName )
3124import Database.LSMTree.Internal.Serialise
32- import Database.LSMTree.Internal.Snapshot (SnapshotLabel (.. ),
33- SnapshotTableType (.. ))
3425import qualified System.FS.API as FS
35- import qualified Test.Database.LSMTree.Internal.Lookup as Test
36- import Test.Database.LSMTree.Internal.Lookup
37- (InMemLookupData (runData ))
3826import Test.QuickCheck
3927import Test.Tasty
4028import Test.Tasty.HUnit
@@ -49,11 +37,6 @@ tests = testGroup "Test.Database.LSMTree.Internal" [
4937 , testProperty " twiceOpenSession" twiceOpenSession
5038 , testCase " sessionDirLayoutMismatch" sessionDirLayoutMismatch
5139 , testCase " sessionDirDoesNotExist" sessionDirDoesNotExist
52- , testProperty " prop_interimRestoreSessionUniqueRunNames"
53- prop_interimRestoreSessionUniqueRunNames
54- ]
55- , testGroup " Table" [
56- testProperty " prop_interimOpenSnapshot" prop_interimOpenSnapshot
5740 ]
5841 , testGroup " Cursor" [
5942 testProperty " prop_roundtripCursor" $ withMaxSuccess 500 $
@@ -112,101 +95,6 @@ showLeft x = \case
11295 Left e -> show e
11396 Right _ -> x
11497
115- -- | Runs are currently not deleted when they become unreferenced. As such, when
116- -- a session is restored, there are still runs in the active directory. When we
117- -- restore a session, we must ensure that we do not use names for new runs that
118- -- are already used for existing runs. As such, we should set the
119- -- @sessionUniqCounter@ accordingly, such that it starts at a number strictly
120- -- larger then numbers of the runs in the active directory.
121- --
122- -- TODO: remove once we have proper snapshotting, in which case files in the
123- -- active directory are deleted when a session is restored: loading snapshots is
124- -- the only way to get active runs into the active directory.
125- prop_interimRestoreSessionUniqueRunNames ::
126- Positive (Small Int )
127- -> NonNegative Int
128- -> Property
129- prop_interimRestoreSessionUniqueRunNames (Positive (Small n)) (NonNegative m) = ioProperty $
130- withTempIOHasBlockIO " TODO" $ \ hfs hbio -> do
131- prop1 <- withSession nullTracer hfs hbio (FS. mkFsPath [] ) $ \ sesh -> do
132- withTable sesh conf $ \ t -> do
133- updates const upds t
134- withOpenTable t $ \ thEnv -> do
135- RW. withReadAccess (tableContent thEnv) $ \ tc -> do
136- let (Sum nruns) = V. foldMap
137- (V. foldMap (const (Sum (1 :: Int ))) . residentRuns)
138- (tableLevels tc)
139- pure $ tabulate " number of runs on disk" [showPowersOf 2 nruns]
140- $ True
141-
142- withSession nullTracer hfs hbio (FS. mkFsPath [] ) $ \ sesh -> do
143- withTable sesh conf $ \ t -> do
144- eith <- try (updates const upds t)
145- fmap (prop1 .&&. ) $ case eith of
146- Left (e :: FS. FsError )
147- | FS. fsErrorType e == FS. FsResourceAlreadyExist
148- -> pure $ counterexample " Test failed... found an FsResourceAlreadyExist error" False
149- | otherwise
150- -> throwIO e
151- Right () -> pure $ property True
152- where
153- conf = testTableConfig {
154- confWriteBufferAlloc = AllocNumEntries (NumEntries n)
155- }
156-
157- upds = V. fromList [ (serialiseKey i, Insert (serialiseValue i))
158- | (i :: Word64 ) <- fmap fromIntegral [1 .. m]
159- ]
160-
161- -- | Check that opening a populated table via the interim table loading function
162- -- works as expected. Roughly, we test:
163- --
164- -- @
165- -- inserts t kvs == openSnapshot' (createSnapshot' (inserts t kvs))
166- -- @
167- --
168- -- TODO: remove once we have proper snapshotting
169- prop_interimOpenSnapshot ::
170- Test. InMemLookupData SerialisedKey SerialisedValue SerialisedBlob
171- -> Property
172- prop_interimOpenSnapshot dat = ioProperty $
173- withTempIOHasBlockIO " prop_interimOpenSnapshot" $ \ hfs hbio -> do
174- withSession nullTracer hfs hbio (FS. mkFsPath [] ) $ \ sesh -> do
175- withTable sesh conf $ \ t -> do
176- updates const upds t
177- let snap = fromMaybe (error " invalid name" ) $ mkSnapshotName " snap"
178- numRunsSnapped <- createSnapshot const snap (SnapshotLabel " someLabel" ) SnapNormalTable t
179- t' <- openSnapshot sesh (SnapshotLabel " someLabel" ) SnapNormalTable configNoOverride snap const
180- lhs <- fetchBlobs hfs =<< lookups const ks t
181- rhs <- fetchBlobs hfs =<< lookups const ks t'
182- -- We must fetch blobs because comparing blob references is meaningless
183- close t
184- close t'
185- -- TODO: checking lookups is a simple check, but we could have stronger
186- -- guarantee. For example, we might check that the internal structures
187- -- match.
188- --
189- pure $ tabulate " Number of runs snapshotted" [show numRunsSnapped]
190- -- Just Delete is semantically equivalent to Nothing but not
191- -- syntactically equal, so we "weaken" the property by mapping
192- -- Just Delete to Nothing.
193- $ fmap weaken lhs === fmap weaken rhs
194- where
195- conf = testTableConfig
196-
197- fetchBlobs :: FS. HasFS IO h
198- -> (V. Vector (Maybe (Entry v (WeakBlobRef IO h ))))
199- -> IO (V. Vector (Maybe (Entry v SerialisedBlob )))
200- fetchBlobs hfs = traverse (traverse (traverse (readWeakBlobRef hfs)))
201-
202- Test. InMemLookupData { runData, lookups = keysToLookup } = dat
203- ks = V. map serialiseKey (V. fromList keysToLookup)
204- upds = V. fromList $ fmap (bimap serialiseKey (bimap serialiseValue serialiseBlob))
205- $ Map. toList runData
206-
207- weaken (Just Delete ) = Nothing
208- weaken x = x
209-
21098-- | Check that reading from a cursor returns exactly the entries that have
21199-- been inserted into the table. Roughly:
212100--
0 commit comments