lsm-tree-1.0.0.0: test/map-range-test.hs
{-# LANGUAGE OverloadedStrings #-}
{-# OPTIONS_GHC -Wno-orphans #-}
module Main (main) where
import Data.ByteString (ByteString)
import Data.Map (Map)
import qualified Data.Map as Map
import Database.LSMTree.Internal.Map.Range (Bound (..), Clusive (..),
rangeLookup)
import Test.QuickCheck (Arbitrary (..), Property, elements, frequency,
(===))
import Test.Tasty (defaultMain, testGroup)
import Test.Tasty.HUnit (testCase, (@?=))
import Test.Tasty.QuickCheck (testProperty)
main :: IO ()
main = defaultMain $ testGroup "map-range-test"
[ testProperty "model" prop
, testCase "example1" $ do
let m = Map.fromList [(0 :: Int, 'x'), (2, 'y')]
rangeLookup (Bound 0 Inclusive) (Bound 1 Inclusive) m @?= [(0, 'x')]
, testCase "example2" $ do
let m = Map.fromList [("\NUL\NUL\NUL\NUL\NUL\NUL\NUL\SOH" :: ByteString,'x')]
let lb = Bound "\NUL\NUL\NUL\NUL\NUL\NUL\NUL\SOH" Inclusive
ub = Bound "\NUL\NUL\NUL\NUL\NUL\NUL\NUL\STX" Inclusive
rangeLookup lb ub m @?= [("\NUL\NUL\NUL\NUL\NUL\NUL\NUL\SOH",'x')]
, testCase "unordered-bounds" $ do
let m = Map.fromList [('x', "ex"), ('y', "why" :: String)]
-- if lower bound is greater than upper bound empty list is returned.
rangeLookup (Bound 'z' Inclusive) (Bound 'a' Inclusive) m @?= []
naiveRangeLookup (Bound 'z' Inclusive) (Bound 'a' Inclusive) m @?= []
]
prop :: Bound Int -> Bound Int -> Map Int Int -> Property
prop lb ub m =
rangeLookup lb ub m === naiveRangeLookup lb ub m
naiveRangeLookup ::
Ord k
=> Bound k -- ^ lower bound
-> Bound k -- ^ upper bound
-> Map k v
-> [(k, v)]
naiveRangeLookup lb ub m =
[ p
| p@(k, _) <- Map.toList m
, evalLowerBound lb k
, evalUpperBound ub k
]
evalLowerBound :: Ord k => Bound k -> k -> Bool
evalLowerBound NoBound _ = True
evalLowerBound (Bound b Exclusive) k = b < k
evalLowerBound (Bound b Inclusive) k = b <= k
evalUpperBound :: Ord k => Bound k -> k -> Bool
evalUpperBound NoBound _ = True
evalUpperBound (Bound b Exclusive) k = k < b
evalUpperBound (Bound b Inclusive) k = k <= b
instance Arbitrary k => Arbitrary (Bound k) where
arbitrary = frequency
[ (1, pure NoBound)
, (20, Bound <$> arbitrary <*> arbitrary)
]
shrink NoBound = []
shrink (Bound k b) = NoBound : map (`Bound` b) (shrink k)
instance Arbitrary Clusive where
arbitrary = elements [Exclusive, Inclusive]