Skip to content

Commit

Permalink
add extra properties to test db initialization functions
Browse files Browse the repository at this point in the history
  • Loading branch information
KtorZ committed Apr 9, 2019
1 parent 762f785 commit c3b1a93
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 10 deletions.
2 changes: 1 addition & 1 deletion src/Cardano/Wallet/DB.hs
Original file line number Diff line number Diff line change
Expand Up @@ -116,5 +116,5 @@ newtype ErrWalletAlreadyExists (operation :: Symbol)
-- functions like 'enqueueCheckpoint' needs to be associated to a corresponding
-- wallet. Some other may not because they are information valid for all wallets
-- (like for instance, the last known network tip).
newtype PrimaryKey key = PrimaryKey { getPrimaryKey :: key }
newtype PrimaryKey key = PrimaryKey key
deriving (Eq, Ord)
53 changes: 44 additions & 9 deletions test/unit/Cardano/Wallet/DB/MVarSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeApplications #-}

{-# OPTIONS_GHC -fno-warn-orphans #-}
Expand All @@ -19,7 +18,11 @@ import Prelude
import Cardano.Wallet
( unsafeRunExceptT )
import Cardano.Wallet.DB
( DBLayer (..), ErrNoSuchWallet (..), PrimaryKey (..) )
( DBLayer (..)
, ErrNoSuchWallet (..)
, ErrWalletAlreadyExists (..)
, PrimaryKey (..)
)
import Cardano.Wallet.DB.MVar
( newDBLayer )
import Cardano.Wallet.Primitive.Model
Expand Down Expand Up @@ -88,6 +91,12 @@ import qualified Data.Map.Strict as Map

spec :: Spec
spec = do
describe "Extra Properties about DB initialization" $ do
it "createWallet . listWallets yields expected results"
(property prop_createListWallet)
it "creating same wallet twice yields an error"
(property prop_createWalletTwice)

describe "put . read yields a result" $ do
it "Checkpoint"
(property $ prop_readAfterPut putCheckpoint readCheckpoint)
Expand Down Expand Up @@ -274,12 +283,12 @@ prop_sequentialPut putOp readOp resolve (KeyValPairs pairs) =
setup = do
db <- liftIO newDBLayer
(cp, meta) <- pick arbitrary
liftIO $ unsafeRunExceptT $ once_ pairs $ \k ->
liftIO $ unsafeRunExceptT $ once_ pairs $ \(k, _) ->
createWallet db k cp meta
return db
prop db = liftIO $ do
unsafeRunExceptT $ forM_ pairs $ uncurry (putOp db)
res <- once pairs (readOp db)
res <- once pairs (readOp db . fst)
res `shouldBe` resolve pairs

-- | Check that the DB supports multiple sequential puts for a given resource
Expand Down Expand Up @@ -310,24 +319,50 @@ prop_parallelPut putOp readOp resolve (KeyValPairs pairs) =
setup = do
db <- liftIO newDBLayer
(cp, meta) <- pick arbitrary
liftIO $ unsafeRunExceptT $ once_ pairs $ \k ->
liftIO $ unsafeRunExceptT $ once_ pairs $ \(k, _) ->
createWallet db k cp meta
return db
prop db = liftIO $ do
forConcurrently_ pairs $ unsafeRunExceptT . uncurry (putOp db)
res <- once pairs (readOp db)
res <- once pairs (readOp db . fst)
length res `shouldBe` resolve pairs

-- | Can list created wallets
prop_createListWallet
:: KeyValPairs (PrimaryKey WalletId) (Wallet DummyState, WalletMetadata)
-> Property
prop_createListWallet (KeyValPairs pairs) =
monadicIO (setup >>= prop)
where
setup = liftIO newDBLayer
prop db = liftIO $ do
res <- once pairs $ \(k, (cp, meta)) ->
unsafeRunExceptT $ createWallet db k cp meta
(length <$> listWallets db) `shouldReturn` length res

-- | Trying to create a same wallet twice should yield an error
prop_createWalletTwice
:: (PrimaryKey WalletId, Wallet DummyState, WalletMetadata)
-> Property
prop_createWalletTwice (key@(PrimaryKey wid), cp, meta) =
monadicIO (setup >>= prop)
where
setup = liftIO newDBLayer
prop db = liftIO $ do
let err = ErrWalletAlreadyExists wid
runExceptT (createWallet db key cp meta) `shouldReturn` Right ()
runExceptT (createWallet db key cp meta) `shouldReturn` Left err

{-------------------------------------------------------------------------------
Tests machinery, Arbitrary instances
-------------------------------------------------------------------------------}

-- | Execute an action once per key @k@ present in the given list
once :: (Ord k, Monad m) => [(k,v)] -> (k -> m a) -> m [a]
once xs = forM (Map.keys (Map.fromList xs))
once :: (Ord k, Monad m) => [(k,v)] -> ((k,v) -> m a) -> m [a]
once xs = forM (Map.toList (Map.fromList xs))

-- | Like 'once', but discards the result
once_ :: (Ord k, Monad m) => [(k,v)] -> (k -> m a) -> m ()
once_ :: (Ord k, Monad m) => [(k,v)] -> ((k,v) -> m a) -> m ()
once_ xs = void . once xs

newtype KeyValPairs k v = KeyValPairs [(k, v)]
Expand Down

0 comments on commit c3b1a93

Please sign in to comment.