packages feed

bitcoin-compact-filters-0.1.0.2: test/Main.hs

module Main where

import Data.Serialize (decode, encode)
import Haskoin.Block (blockHeader, headerHash)
import Test.Tasty (TestTree, defaultMain, testGroup)
import Test.Tasty.HUnit (testCase, (@?=))
import Test.Tasty.QuickCheck (elements, forAll, testProperty, (===))

import Bitcoin.CompactFilter (
    blockFilterHeader,
    encodeFilter,
    filterContents,
    isMember,
 )
import Test.CompactFilter (genBlockFilter)
import qualified Test.Examples.Bip as BIP
import qualified Test.Examples.Mainnet as Mainnet
import Test.Util (Example (..))

main :: IO ()
main = do
    bipExamples <- BIP.examples
    mainnetExamples <- Mainnet.examples
    defaultMain . testGroup "bip158 unit tests" $
        [ testGroup "Serialization" [testRoundtrip]
        , testGroup
            "Filter"
            [ testGroup "BIP 158" $ testFilter <$> bipExamples
            , testGroup "Mainnet" $ testFilter <$> mainnetExamples
            ]
        ]

testRoundtrip :: TestTree
testRoundtrip = testProperty "serialization round trip" . forAll genBlockFilter $ \bf ->
    decode (encode bf) === Right bf

testFilter :: Example -> TestTree
testFilter v = testGroup (testLabel v) $ [construction] <> [membership | not (null ss)]
  where
    construction = testCase "Construction" $ do
        ourFilter @?= exampleFilter v
        ourHeader @?= exampleHeader v

    membership = testProperty "Filter membership" $
        forAll (elements ss) $ \s ->
            isMember bh [s] ourFilter

    ourFilter = encodeFilter (examplePrevOuts v) block
    ourHeader = blockFilterHeader (examplePrevHeader v) ourFilter
    bh = headerHash $ blockHeader block
    ss = filterContents (examplePrevOuts v) block

    block = exampleBlock v

testLabel :: Example -> String
testLabel e = "Block " <> show (exampleHeight e)