haskoin-store-1.9.0: test/Haskoin/Store/Database/ViewsSpec.hs
module Haskoin.Store.Database.ViewsSpec (spec) where
import Control.Monad (void)
import Data.List (sort)
import Haskoin (BlockHash, btcRegTest, prepareContext)
import Haskoin.Store.Database.Query qualified as Q
import Haskoin.Store.Database.Views
import Haskoin.Store.Histories
import Test.Hspec
import UnliftIO (withSystemTempDirectory)
spec :: Spec
spec = prepareContext $ \ctx -> describe "views of the database by block" $ do
let withChain go =
withSystemTempDirectory "haskoin-store-views-" $ \dir ->
open20 btcRegTest ctx dir $ \db -> do
void (start mixedRules db)
views <- newViews db
let best = Q.getBestBlock db >>= maybe (fail "no best block") return
mine = do
block <- blockOn db []
void (apply mixedRules db block)
b <- best
takeView views b
return b
go db views best mine `shouldReturn` ()
closeViews views
it "answer from the block that each was taken at, whatever came after" $
withChain $ \db views best mine -> do
first <- best
takeView views first
second <- mine
third <- mine
sort <$> heldViews views `shouldReturn` sort [first, second, third]
Q.getBestBlock db `shouldReturn` Just third
withViewAt views first Q.getBestBlock `shouldReturn` Just (Just first)
withViewAt views second Q.getBestBlock `shouldReturn` Just (Just second)
-- the second block was not there yet when the first view was taken
(fmap (fmap (const ())) <$> withViewAt views first (`Q.getBlock` second)) `shouldReturn` Just Nothing
it "let go of the views that are not to be kept" $
withChain $ \_ views best mine -> do
first <- best
takeView views first
second <- mine
keepViews views [second]
heldViews views `shouldReturn` [second]
withViewAt views first Q.getBestBlock `shouldReturn` (Nothing :: Maybe (Maybe BlockHash))
withViewAt views second Q.getBestBlock `shouldReturn` Just (Just second)
it "keep a view that is being read until its reader is done" $
withChain $ \_ views best mine -> do
first <- best
takeView views first
second <- mine
result <- withViewAt views first $ \old -> do
keepViews views [second]
-- gone for anyone who asks now
heldViews views `shouldReturn` [second]
withViewAt views first Q.getBestBlock `shouldReturn` (Nothing :: Maybe (Maybe BlockHash))
-- and still there for the one that was reading, while blocks go on
third <- mine
(,third) <$> Q.getBestBlock old
fmap fst result `shouldBe` Just (Just first)
-- the reader is done: the view is gone, and the others are as they were
sort <$> heldViews views `shouldReturn` sort (second : maybe [] (pure . snd) result)