Skip to content

Commit 4e1a661

Browse files
committed
Add a prop_isStructurallyEmpty for MergingTree
This ensures the property that any structurally empty tree can be immediately recognised as a structurally empty.
1 parent bbbe1fa commit 4e1a661

File tree

3 files changed

+68
-0
lines changed

3 files changed

+68
-0
lines changed

lsm-tree.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,7 @@ test-suite lsm-tree-test
366366
Test.Database.LSMTree.Internal.Index.Ordinary
367367
Test.Database.LSMTree.Internal.Lookup
368368
Test.Database.LSMTree.Internal.Merge
369+
Test.Database.LSMTree.Internal.MergingTree
369370
Test.Database.LSMTree.Internal.Monkey
370371
Test.Database.LSMTree.Internal.PageAcc
371372
Test.Database.LSMTree.Internal.PageAcc1

test/Main.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import qualified Test.Database.LSMTree.Internal.Index.Compact
1717
import qualified Test.Database.LSMTree.Internal.Index.Ordinary
1818
import qualified Test.Database.LSMTree.Internal.Lookup
1919
import qualified Test.Database.LSMTree.Internal.Merge
20+
import qualified Test.Database.LSMTree.Internal.MergingTree
2021
import qualified Test.Database.LSMTree.Internal.Monkey
2122
import qualified Test.Database.LSMTree.Internal.PageAcc
2223
import qualified Test.Database.LSMTree.Internal.PageAcc1
@@ -57,6 +58,7 @@ main = do
5758
, Test.Database.LSMTree.Internal.Entry.tests
5859
, Test.Database.LSMTree.Internal.Lookup.tests
5960
, Test.Database.LSMTree.Internal.Merge.tests
61+
, Test.Database.LSMTree.Internal.MergingTree.tests
6062
, Test.Database.LSMTree.Internal.Monkey.tests
6163
, Test.Database.LSMTree.Internal.PageAcc.tests
6264
, Test.Database.LSMTree.Internal.PageAcc1.tests
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
module Test.Database.LSMTree.Internal.MergingTree (tests) where
2+
3+
import Control.Exception (bracket)
4+
import Control.RefCount
5+
import Database.LSMTree.Internal.MergingTree
6+
import Test.QuickCheck
7+
import Test.Tasty
8+
import Test.Tasty.QuickCheck
9+
10+
tests :: TestTree
11+
tests = testGroup "Test.Database.LSMTree.Internal.MergingTree"
12+
[ testProperty "prop_isStructurallyEmpty" prop_isStructurallyEmpty
13+
]
14+
15+
-- | Check that the merging tree constructor functions preserve the property
16+
-- that if the inputs are obviously empty, the output is also obviously empty.
17+
--
18+
prop_isStructurallyEmpty :: EmptyMergingTree -> Property
19+
prop_isStructurallyEmpty emt =
20+
ioProperty $
21+
bracket (mkEmptyMergingTree emt)
22+
releaseRef
23+
isStructurallyEmpty
24+
25+
-- | An expression to specify the shape of an empty 'MergingTree'
26+
--
27+
data EmptyMergingTree = ObviouslyEmptyLevelMerge
28+
| ObviouslyEmptyUnionMerge
29+
| NonObviouslyEmptyLevelMerge EmptyMergingTree
30+
| NonObviouslyEmptyUnionMerge [EmptyMergingTree]
31+
deriving stock (Eq, Show)
32+
33+
instance Arbitrary EmptyMergingTree where
34+
arbitrary =
35+
sized $ \sz ->
36+
frequency $
37+
take (1 + sz)
38+
[ (1, pure ObviouslyEmptyLevelMerge)
39+
, (1, pure ObviouslyEmptyUnionMerge)
40+
, (2, NonObviouslyEmptyLevelMerge <$> resize (sz `div` 2) arbitrary)
41+
, (2, NonObviouslyEmptyUnionMerge <$> resize (sz `div` 2) arbitrary)
42+
]
43+
shrink ObviouslyEmptyLevelMerge = []
44+
shrink ObviouslyEmptyUnionMerge = [ObviouslyEmptyLevelMerge]
45+
shrink (NonObviouslyEmptyLevelMerge mt) = ObviouslyEmptyLevelMerge
46+
: [ NonObviouslyEmptyLevelMerge mt'
47+
| mt' <- shrink mt ]
48+
shrink (NonObviouslyEmptyUnionMerge mt) = ObviouslyEmptyUnionMerge
49+
: [ NonObviouslyEmptyUnionMerge mt'
50+
| mt' <- shrink mt ]
51+
52+
mkEmptyMergingTree :: EmptyMergingTree -> IO (Ref (MergingTree IO h))
53+
mkEmptyMergingTree ObviouslyEmptyLevelMerge = newPendingLevelMerge [] Nothing
54+
mkEmptyMergingTree ObviouslyEmptyUnionMerge = newPendingUnionMerge []
55+
mkEmptyMergingTree (NonObviouslyEmptyLevelMerge emt) = do
56+
mt <- mkEmptyMergingTree emt
57+
mt' <- newPendingLevelMerge [] (Just mt)
58+
releaseRef mt
59+
return mt'
60+
mkEmptyMergingTree (NonObviouslyEmptyUnionMerge emts) = do
61+
mts <- mapM mkEmptyMergingTree emts
62+
mt' <- newPendingUnionMerge mts
63+
mapM_ releaseRef mts
64+
return mt'
65+

0 commit comments

Comments
 (0)