packages feed

bitcoin-compact-filters-0.1.0.0: 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)