Skip to content
This repository was archived by the owner on Aug 18, 2020. It is now read-only.

Commit 9c41f87

Browse files
committed
[CBR-475] add synchronization unit tests for TxMeta api
1 parent dfbe405 commit 9c41f87

File tree

2 files changed

+97
-1
lines changed

2 files changed

+97
-1
lines changed

wallet-new/cardano-sl-wallet-new.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,7 @@ test-suite wallet-unit-tests
506506
hs-source-dirs: server test/unit
507507

508508
build-depends: acid-state
509+
, async
509510
, base
510511
, bytestring
511512
, cardano-crypto

wallet-new/test/unit/TxMetaStorageSpecs.hs

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import Universum
1212
import qualified Cardano.Wallet.Kernel.DB.Sqlite as SQlite
1313
import Cardano.Wallet.Kernel.DB.TxMeta
1414
import Control.Exception.Safe (bracket)
15+
import Control.Concurrent.Async
1516
import qualified Data.List as List
1617
import qualified Data.List.NonEmpty as NonEmpty
1718
import qualified Data.Set as Set
@@ -25,7 +26,7 @@ import Serokell.Util.Text (listJsonIndent, pairF)
2526
import Test.Hspec (expectationFailure, shouldContain, shouldThrow)
2627
import Test.Hspec.QuickCheck (prop)
2728
import Test.QuickCheck (Arbitrary, Gen, arbitrary, forAll, suchThat,
28-
vectorOf)
29+
vectorOf, withMaxSuccess)
2930
import Test.QuickCheck.Monadic (assert, monadicIO, pick, run)
3031
import Util.Buildable (ShowThroughBuild (..))
3132
import Util.Buildable.Hspec
@@ -167,9 +168,103 @@ sortByCreationAt direction = sortBy sortFn
167168
hasDupes :: Ord a => [a] -> Bool
168169
hasDupes xs = length (Set.fromList xs) /= List.length xs
169170

171+
172+
threadRead :: Int -> MetaDBHandle -> IO ()
173+
threadRead times hdl = do
174+
let getNoFilters = getTxMetas hdl (Offset 0) (Limit 100) Everything Nothing NoFilterOp NoFilterOp Nothing
175+
replicateM_ times getNoFilters
176+
177+
threadWrite :: [TxMeta] -> MetaDBHandle -> IO ()
178+
threadWrite metas hdl = do
179+
let f meta = do
180+
putTxMetaT hdl meta `shouldReturn` Tx
181+
mapM_ f metas
182+
183+
-- here we try to add the same tx 2 times. The second must fail, but without crashing
184+
-- anything, as this is a no-op.
185+
threadWriteWithNoOp :: [TxMeta] -> MetaDBHandle -> IO ()
186+
threadWriteWithNoOp metas hdl = do
187+
let f meta = do
188+
putTxMetaT hdl meta `shouldReturn` Tx
189+
putTxMetaT hdl meta `shouldReturn` No
190+
mapM_ f metas
191+
170192
-- | Specs which tests the persistent storage and API provided by 'TxMeta'.
171193
txMetaStorageSpecs :: Spec
172194
txMetaStorageSpecs = do
195+
describe "synchronization" $ do
196+
it "synchronized with 2 write workers and no-ops" $ withMaxSuccess 5 $ monadicIO $ do
197+
-- beware of the big data.
198+
testMetas <- pick (genMetas 2000)
199+
let metas = unSTB <$> testMetas
200+
(meta0, meta1) = splitAt (div 2000 2) metas
201+
run $ withTemporaryDb $ \hdl -> do
202+
t0 <- async $ threadWriteWithNoOp meta0 hdl
203+
t1 <- async $ threadWriteWithNoOp meta1 hdl
204+
_ <- waitAny [t0, t1]
205+
return ()
206+
207+
it "synchronized with 2 write workers and no-ops: correct count" $ withMaxSuccess 5 $ monadicIO $ do
208+
-- beware of the big data.
209+
testMetas <- pick (genMetas 200)
210+
let metas = unSTB <$> testMetas
211+
(meta0, meta1) = splitAt (div 200 2) metas
212+
run $ withTemporaryDb $ \hdl -> do
213+
t0 <- async $ threadWriteWithNoOp meta0 hdl
214+
t1 <- async $ threadWriteWithNoOp meta1 hdl
215+
_ <- waitAny [t0, t1]
216+
(ls, count) <- getTxMetas hdl (Offset 0) (Limit 300) Everything Nothing NoFilterOp NoFilterOp Nothing
217+
count `shouldBe` (Just 200)
218+
length ls `shouldBe` 200
219+
return ()
220+
221+
it "synchronized with 2 write workers" $ withMaxSuccess 5 $ monadicIO $ do
222+
-- beware of the big data.
223+
testMetas <- pick (genMetas 2000)
224+
let metas = unSTB <$> testMetas
225+
(meta0, meta1) = splitAt (div 2000 2) metas
226+
run $ withTemporaryDb $ \hdl -> do
227+
t0 <- async $ threadWrite meta0 hdl
228+
t1 <- async $ threadWrite meta1 hdl
229+
_ <- waitAny [t0, t1]
230+
return ()
231+
232+
it "synchronized with 2 write workers: correct count" $ withMaxSuccess 5 $ monadicIO $ do
233+
-- beware of the big data.
234+
testMetas <- pick (genMetas 200)
235+
let metas = unSTB <$> testMetas
236+
(meta0, meta1) = splitAt (div 200 2) metas
237+
run $ withTemporaryDb $ \hdl -> do
238+
t0 <- async $ threadWrite meta0 hdl
239+
t1 <- async $ threadWrite meta1 hdl
240+
_ <- waitAny [t0, t1]
241+
(ls, count) <- getTxMetas hdl (Offset 0) (Limit 300) Everything Nothing NoFilterOp NoFilterOp Nothing
242+
count `shouldBe` (Just 200)
243+
length ls `shouldBe` 200
244+
return ()
245+
246+
it "synchronized 1 write and 1 read workers" $ withMaxSuccess 5 $ monadicIO $ do
247+
-- beware of the big data.
248+
testMetas <- pick (genMetas 2000)
249+
let metas = unSTB <$> testMetas
250+
run $ withTemporaryDb $ \hdl -> do
251+
t0 <- async $ threadWriteWithNoOp metas hdl
252+
t1 <- async $ threadRead 2000 hdl
253+
_ <- waitAny [t0, t1]
254+
return ()
255+
256+
it "synchronized 1 write and 1 read workers: correct count" $ withMaxSuccess 5 $ monadicIO $ do
257+
-- beware of the big data.
258+
testMetas <- pick (genMetas 200)
259+
let metas = unSTB <$> testMetas
260+
run $ withTemporaryDb $ \hdl -> do
261+
t0 <- async $ threadWriteWithNoOp metas hdl
262+
t1 <- async $ threadRead 200 hdl
263+
_ <- waitAny [t0, t1]
264+
(ls, count) <- getTxMetas hdl (Offset 0) (Limit 300) Everything Nothing NoFilterOp NoFilterOp Nothing
265+
count `shouldBe` (Just 200)
266+
length ls `shouldBe` 200
267+
return ()
173268

174269
describe "SQlite transactions" $ do
175270
it "throws an exception when tx with double spending" $ monadicIO $ do

0 commit comments

Comments
 (0)