1- {-# LANGUAGE LambdaCase #-}
2- {-# LANGUAGE OverloadedStrings #-}
3- {-# LANGUAGE RecordWildCards #-}
1+ {-# LANGUAGE LambdaCase #-}
2+ {-# LANGUAGE OverloadedStrings #-}
3+ {-# LANGUAGE RecordWildCards #-}
4+ {-# OPTIONS_GHC -Wno-orphans #-}
5+
6+ {-# LANGUAGE AllowAmbiguousTypes #-}
7+ {-# LANGUAGE ExplicitForAll #-}
8+ {-# LANGUAGE FlexibleContexts #-}
9+ {-# LANGUAGE ScopedTypeVariables #-}
10+ {-# LANGUAGE TypeApplications #-}
411
512module Test.Database.LSMTree (tests ) where
613
714import Control.Exception
815import Control.Tracer
16+ import Data.Foldable
917import Data.Function (on )
1018import Data.IORef
11- import Data.Monoid
19+ import Data.Monoid (Sum (.. ))
20+ import Data.String (fromString )
1221import Data.Typeable (Typeable )
1322import qualified Data.Vector as V
1423import qualified Data.Vector.Algorithms as VA
@@ -19,15 +28,17 @@ import Database.LSMTree.Extras (showRangesOf)
1928import Database.LSMTree.Extras.Generators ()
2029import qualified System.FS.API as FS
2130import qualified System.FS.BlockIO.API as FS
22- import Test.QuickCheck
23- import Test.Tasty
31+ import Test.Database.LSMTree.Internal.Config ()
32+ import Test.Tasty ( TestTree , testGroup )
2433import Test.Tasty.QuickCheck
2534import Test.Util.FS
35+ import Test.Util.TypeClassLaws
36+
2637
2738tests :: TestTree
28- tests = testGroup " Test.Database.LSMTree" [
29- testGroup " Session" [
30- -- openSession
39+ tests = testGroup " Test.Database.LSMTree"
40+ [ testGroup " Session"
41+ [ -- openSession
3142 testProperty " prop_openSession_newSession" prop_openSession_newSession
3243 , testProperty " prop_openSession_restoreSession" prop_openSession_restoreSession
3344 -- happy path
@@ -41,6 +52,16 @@ tests = testGroup "Test.Database.LSMTree" [
4152 -- salt
4253 , testProperty " prop_goodAndBadSessionSalt" prop_goodAndBadSessionSalt
4354 ]
55+ , laws_Entry
56+ , laws_LookupResult
57+ , laws_Range
58+ , laws_RawBytes
59+ , laws_SnapshotName
60+ , laws_SnapshotLabel
61+ , laws_TableConfigOverride
62+ , laws_UnionCredits
63+ , laws_UnionDebt
64+ , laws_Update
4465 ]
4566
4667{- ------------------------------------------------------------------------------
@@ -312,3 +333,180 @@ prop_goodAndBadSessionSalt (Positive (Small bufferSize)) ins =
312333 conf = defaultTableConfig {
313334 confWriteBufferAlloc = AllocNumEntries bufferSize
314335 }
336+
337+ {- ------------------------------------------------------------------------------
338+ Type-class Laws
339+ -------------------------------------------------------------------------------}
340+
341+ -- |
342+ -- This alias exists for brevity in type signatures
343+ type W = Word
344+
345+ -- Entry
346+
347+ instance (Arbitrary k , Arbitrary v , Arbitrary b ) => Arbitrary (Entry k v b ) where
348+
349+ arbitrary = oneof
350+ [ Entry <$> arbitrary <*> arbitrary
351+ , EntryWithBlob <$> arbitrary <*> arbitrary <*> arbitrary
352+ ]
353+
354+ shrink (Entry k v) = [ Entry k' v' | k' <- shrink k, v' <- shrink v ]
355+ shrink (EntryWithBlob k v b) =
356+ [ EntryWithBlob k' v' b' | k' <- shrink k, v' <- shrink v, b' <- shrink b ]
357+
358+ laws_Entry :: TestTree
359+ laws_Entry = testGroup " Entry"
360+ -- Basic control structures
361+ [ functorLaws @ (Entry W W )
362+ , bifunctorLaws @ (Entry W )
363+ , foldableLaws @ (Entry W W )
364+ , traversableLaws @ (Entry W W )
365+ -- Data structures
366+ , equalityLaws @ (Entry W W W )
367+ , normalFormDataLaws @ (Entry W W W )
368+ , showProperties @ (Entry W W W )
369+ ]
370+
371+ -- LookupResult
372+
373+ instance (Arbitrary v , Arbitrary b ) => Arbitrary (LookupResult v b ) where
374+
375+ arbitrary = oneof
376+ [ pure NotFound
377+ , Found <$> arbitrary
378+ , FoundWithBlob <$> arbitrary <*> arbitrary
379+ ]
380+
381+ shrink NotFound = []
382+ shrink (Found v) = NotFound : [Found v' | v' <- shrink v]
383+ shrink (FoundWithBlob v b) = fold
384+ [ [NotFound , Found v]
385+ , [FoundWithBlob v' b | v' <- shrink v]
386+ , [FoundWithBlob v b' | b' <- shrink b]
387+ ]
388+
389+ laws_LookupResult :: TestTree
390+ laws_LookupResult = testGroup " LookupResult"
391+ -- Basic control structures
392+ [ functorLaws @ (LookupResult W )
393+ , bifunctorLaws @ (LookupResult )
394+ , foldableLaws @ (LookupResult W )
395+ , traversableLaws @ (LookupResult W )
396+ -- Data structures
397+ , equalityLaws @ (LookupResult W W )
398+ , normalFormDataLaws @ (LookupResult W W )
399+ , showProperties @ (LookupResult W W )
400+ ]
401+
402+ -- Range
403+
404+ laws_Range :: TestTree
405+ laws_Range = testGroup " Range"
406+ [ functorLaws @ (Range )
407+ , equalityLaws @ (Range W )
408+ , normalFormDataLaws @ (Range W )
409+ , showProperties @ (Range W )
410+ ]
411+
412+ -- RawBytes
413+
414+ laws_RawBytes :: TestTree
415+ laws_RawBytes = testGroup " RawBytes"
416+ [ equalityLaws @ (RawBytes )
417+ , orderingLaws @ (RawBytes )
418+ , semigroupLaws @ (RawBytes )
419+ , monoidLaws @ (RawBytes )
420+ , normalFormDataLaws @ (RawBytes )
421+ , showProperties @ (RawBytes )
422+ ]
423+
424+ -- SnapshotName
425+
426+ instance Arbitrary SnapshotName where
427+
428+ arbitrary = toSnapshotName . getPrintableString <$>
429+ (arbitrary `suchThat` (isValidSnapshotName . getPrintableString))
430+
431+ shrink = fmap toSnapshotName . filter isValidSnapshotName .
432+ fmap getPrintableString . shrink . PrintableString . show
433+
434+ laws_SnapshotName :: TestTree
435+ laws_SnapshotName = testGroup " SnapshotName"
436+ [ equalityLaws @ (SnapshotName )
437+ , orderingLaws @ (SnapshotName )
438+ , showProperties @ (SnapshotName )
439+ ]
440+
441+ -- SnapshotLabel
442+
443+ instance Arbitrary SnapshotLabel where
444+
445+ arbitrary = fromString . getPrintableString <$>
446+ (arbitrary `suchThat` (isValidSnapshotName . getPrintableString))
447+
448+ shrink = fmap fromString. filter isValidSnapshotName .
449+ fmap getPrintableString . shrink . PrintableString . show
450+
451+ laws_SnapshotLabel :: TestTree
452+ laws_SnapshotLabel = testGroup " SnapshotLabel"
453+ [ equalityLaws @ (SnapshotLabel )
454+ , normalFormDataLaws @ (SnapshotLabel )
455+ , showProperties @ (SnapshotLabel )
456+ ]
457+
458+ -- TableConfigOverride
459+
460+ instance Arbitrary TableConfigOverride where
461+
462+ arbitrary = TableConfigOverride <$> arbitrary <*> arbitrary
463+
464+ shrink (TableConfigOverride x y) =
465+ [ TableConfigOverride x' y' | x' <- shrink x, y' <- shrink y ]
466+
467+ laws_TableConfigOverride :: TestTree
468+ laws_TableConfigOverride = testGroup " TableConfigOverride"
469+ [ equalityLaws @ (SnapshotLabel )
470+ , showProperties @ (SnapshotLabel )
471+ ]
472+
473+ -- UnionCredits
474+
475+ instance Arbitrary UnionCredits where
476+
477+ arbitrary = UnionCredits . getNonNegative <$> arbitrary
478+
479+ shrink (UnionCredits x) = UnionCredits . getNonNegative <$> shrink (NonNegative x)
480+
481+ laws_UnionCredits :: TestTree
482+ laws_UnionCredits = testGroup " UnionCredits"
483+ [ equalityLaws @ (UnionCredits )
484+ , orderingLaws @ (UnionCredits )
485+ , numLaws @ (UnionCredits )
486+ , showProperties @ (UnionCredits )
487+ ]
488+
489+ -- UnionDebt
490+
491+ instance Arbitrary UnionDebt where
492+
493+ arbitrary = UnionDebt . getNonNegative <$> arbitrary
494+
495+ shrink (UnionDebt x) = UnionDebt . getNonNegative <$> shrink (NonNegative x)
496+
497+ laws_UnionDebt :: TestTree
498+ laws_UnionDebt = testGroup " UnionDebt"
499+ [ equalityLaws @ (UnionDebt )
500+ , orderingLaws @ (UnionDebt )
501+ , numLaws @ (UnionDebt )
502+ , showProperties @ (UnionDebt )
503+ ]
504+
505+ -- Update
506+
507+ laws_Update :: TestTree
508+ laws_Update = testGroup " Update"
509+ [ equalityLaws @ (Update W W )
510+ , normalFormDataLaws @ (Update W W )
511+ , showProperties @ (Update W W )
512+ ]
0 commit comments