haskey-btree-0.3.0.0: tests/Integration/WriteOpenRead/Debug.hs
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
module Integration.WriteOpenRead.Debug where
import Test.Framework (Test, testGroup)
import Test.Framework.Providers.QuickCheck2 (testProperty)
import Test.QuickCheck
import Control.Applicative ((<$>))
import Control.Monad
import Control.Monad.Identity
import Control.Monad.Trans.State
import Data.Binary (Binary)
import Data.Foldable (foldlM)
import Data.Map (Map)
import Data.Typeable (Typeable)
import Data.Word (Word8)
import qualified Data.Map as M
import GHC.Generics (Generic)
import Data.BTree.Alloc.Class
import Data.BTree.Alloc.Debug
import Data.BTree.Impure (Tree)
import Data.BTree.Primitives
import qualified Data.BTree.Impure as B
import Integration.WriteOpenRead.Transactions
tests :: Test
tests = testGroup "WriteOpenRead.Concurrent"
[ testProperty "debug allocator" prop_debug_allocator
]
data AllocatorState k v = AllocatorState {
allocatorStatePages :: Pages
, allocatorStateTree :: Tree k v }
prop_debug_allocator :: Property
prop_debug_allocator = forAll genTestSequence $ \(TestSequence txs) ->
let s = AllocatorState emptyPages B.empty
m = runIdentity $ evalStateT (runSeq txs) s
in
m `seq` True
where
runSeq = foldlM writeReadTest M.empty
writeReadTest :: Map Integer TestValue
-> TestTransaction Integer TestValue
-> StateT (AllocatorState Integer TestValue)
Identity
(Map Integer TestValue)
writeReadTest m tx = do
openAndWrite tx
read' <- openAndRead
let expected = testTransactionResult m tx
if read' == M.toList expected
then return expected
else error $ "error:"
++ "\n after: " ++ show tx
++ "\n expectd: " ++ show (M.toList expected)
++ "\n got: " ++ show read'
openAndRead = do
pages <- gets allocatorStatePages
tree <- gets allocatorStateTree
return $ evalDebug pages (readAll tree)
openAndWrite tx = do
pages <- gets allocatorStatePages
tree <- gets allocatorStateTree
let (tree', pages') = runDebug pages (doTx tree tx)
put AllocatorState {
allocatorStatePages = pages'
, allocatorStateTree = tree' }
readAll :: (AllocM m, Key k, Value v)
=> Tree k v
-> m [(k, v)]
readAll = B.toList
doTx :: (AllocM m, Key k, Value v)
=> Tree k v
-> TestTransaction k v
-> m (Tree k v)
doTx tree (TestTransaction actions) =
foldl (>=>) return (map writeAction actions) tree
where
writeAction (Insert k v) = B.insert k v
writeAction (Replace k v) = B.insert k v
writeAction (Delete k) = B.delete k
--------------------------------------------------------------------------------
-- | Value used for testing.
--
-- This value will overflow 20% of the time.
newtype TestValue = TestValue (Either Integer [Word8])
deriving (Eq, Generic, Show, Typeable)
instance Binary TestValue where
instance Value TestValue where
instance Arbitrary TestValue where
arbitrary =
TestValue <$> frequency [(80, Left <$> small), (20, Right <$> big)]
where
small = arbitrary
big = arbitrary
--------------------------------------------------------------------------------