haskoin-store-data-0.65.0: test/Haskoin/Store/DataSpec.hs
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Haskoin.Store.DataSpec
( spec,
)
where
import Control.Monad (forM_)
import Data.Aeson (FromJSON (..))
import qualified Data.ByteString as B
import Data.String.Conversions (cs)
import Haskoin
import Haskoin.Store.Data
import Haskoin.Util.Arbitrary
import Test.Hspec (Spec, describe)
import Test.QuickCheck
serialVals :: [SerialBox]
serialVals =
[ SerialBox (arbitrary :: Gen DeriveType),
SerialBox (arbitrary :: Gen XPubSpec),
SerialBox (arbitrary :: Gen BlockRef),
SerialBox (arbitrary :: Gen TxRef),
SerialBox (arbitrary :: Gen Balance),
SerialBox (arbitrary :: Gen Unspent),
SerialBox (arbitrary :: Gen BlockData),
SerialBox (arbitrary :: Gen StoreInput),
SerialBox (arbitrary :: Gen Spender),
SerialBox (arbitrary :: Gen StoreOutput),
SerialBox (arbitrary :: Gen Prev),
SerialBox (arbitrary :: Gen TxData),
SerialBox (arbitrary :: Gen Transaction),
SerialBox (arbitrary :: Gen XPubBal),
SerialBox (arbitrary :: Gen XPubUnspent),
SerialBox (arbitrary :: Gen XPubSummary),
SerialBox (arbitrary :: Gen HealthCheck),
SerialBox (arbitrary :: Gen Event),
SerialBox (arbitrary :: Gen TxId),
SerialBox (arbitrary :: Gen PeerInformation),
SerialBox (arbitrary :: Gen (GenericResult BlockData)),
SerialBox (arbitrary :: Gen (RawResult BlockData)),
SerialBox (arbitrary :: Gen (RawResultList BlockData))
]
jsonVals :: [JsonBox]
jsonVals =
[ JsonBox (arbitrary :: Gen TxRef),
JsonBox (arbitrary :: Gen BlockRef),
JsonBox (arbitrary :: Gen Spender),
JsonBox (arbitrary :: Gen XPubSummary),
JsonBox (arbitrary :: Gen HealthCheck),
JsonBox (arbitrary :: Gen Event),
JsonBox (arbitrary :: Gen TxId),
JsonBox (arbitrary :: Gen PeerInformation),
JsonBox (arbitrary :: Gen (GenericResult XPubSummary)),
JsonBox (arbitrary :: Gen (RawResult BlockData)),
JsonBox (arbitrary :: Gen (RawResultList BlockData)),
JsonBox (arbitrary :: Gen Except),
JsonBox (arbitrary :: Gen BinfoWallet),
JsonBox (arbitrary :: Gen BinfoSymbol),
JsonBox (arbitrary :: Gen BinfoBlockInfo),
JsonBox (arbitrary :: Gen BinfoInfo),
JsonBox (arbitrary :: Gen BinfoSpender),
JsonBox (arbitrary :: Gen BinfoRate),
JsonBox (arbitrary :: Gen BinfoTicker),
JsonBox (arbitrary :: Gen BinfoTxId),
JsonBox (arbitrary :: Gen BinfoShortBal),
JsonBox (arbitrary :: Gen BinfoHistory),
JsonBox (arbitrary :: Gen BinfoHeader),
JsonBox (arbitrary :: Gen BinfoBlocks)
]
netVals :: [NetBox]
netVals =
[ NetBox
( balanceToJSON,
balanceToEncoding,
balanceParseJSON,
arbitraryNetData
),
NetBox
( storeOutputToJSON,
storeOutputToEncoding,
storeOutputParseJSON,
arbitraryNetData
),
NetBox
( unspentToJSON,
unspentToEncoding,
unspentParseJSON,
arbitraryNetData
),
NetBox
( xPubBalToJSON,
xPubBalToEncoding,
xPubBalParseJSON,
arbitraryNetData
),
NetBox
( xPubUnspentToJSON,
xPubUnspentToEncoding,
xPubUnspentParseJSON,
arbitraryNetData
),
NetBox
( storeInputToJSON,
storeInputToEncoding,
storeInputParseJSON,
arbitraryStoreInputNet
),
NetBox
( blockDataToJSON,
blockDataToEncoding,
const parseJSON,
arbitraryBlockDataNet
),
NetBox
( transactionToJSON,
transactionToEncoding,
transactionParseJSON,
arbitraryNetData
),
NetBox
( binfoMultiAddrToJSON,
binfoMultiAddrToEncoding,
binfoMultiAddrParseJSON,
arbitraryNetData
),
NetBox
( binfoBalanceToJSON,
binfoBalanceToEncoding,
binfoBalanceParseJSON,
arbitraryNetData
),
NetBox
( binfoBlockToJSON,
binfoBlockToEncoding,
binfoBlockParseJSON,
arbitraryNetData
),
NetBox
( binfoTxToJSON,
binfoTxToEncoding,
binfoTxParseJSON,
arbitraryNetData
),
NetBox
( binfoTxInputToJSON,
binfoTxInputToEncoding,
binfoTxInputParseJSON,
arbitraryNetData
),
NetBox
( binfoTxOutputToJSON,
binfoTxOutputToEncoding,
binfoTxOutputParseJSON,
arbitraryNetData
),
NetBox
( binfoXPubPathToJSON,
binfoXPubPathToEncoding,
binfoXPubPathParseJSON,
arbitraryNetData
),
NetBox
( binfoUnspentToJSON,
binfoUnspentToEncoding,
binfoUnspentParseJSON,
arbitraryNetData
),
NetBox
( binfoBlocksToJSON,
binfoBlocksToEncoding,
binfoBlocksParseJSON,
arbitraryNetData
),
NetBox
( binfoRawAddrToJSON,
binfoRawAddrToEncoding,
binfoRawAddrParseJSON,
arbitraryNetData
),
NetBox
( binfoMempoolToJSON,
binfoMempoolToEncoding,
binfoMempoolParseJSON,
arbitraryNetData
)
]
spec :: Spec
spec = do
describe "Binary Encoding" $
forM_ serialVals $ \(SerialBox g) -> testSerial g
describe "JSON Encoding" $
forM_ jsonVals $ \(JsonBox g) -> testJson g
describe "JSON Encoding with Network" $
forM_ netVals $ \(NetBox (j, e, p, g)) -> testNetJson j e p g
instance Arbitrary BlockRef where
arbitrary =
oneof [BlockRef <$> arbitrary <*> arbitrary, MemRef <$> arbitrary]
instance Arbitrary Prev where
arbitrary = Prev <$> arbitraryBS1 <*> arbitrary
instance Arbitrary TxData where
arbitrary =
TxData
<$> arbitrary
<*> arbitraryTx btc
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
instance Arbitrary StoreInput where
arbitrary =
oneof
[ StoreCoinbase
<$> arbitraryOutPoint
<*> arbitrary
<*> arbitraryBS1
<*> listOf arbitraryBS1,
StoreInput
<$> arbitraryOutPoint
<*> arbitrary
<*> arbitraryBS1
<*> arbitraryBS1
<*> arbitrary
<*> listOf arbitraryBS1
<*> arbitraryMaybe arbitraryAddress
]
arbitraryStoreInputNet :: Gen (Network, StoreInput)
arbitraryStoreInputNet = do
net <- arbitraryNetwork
store <- arbitrary
let res
| getSegWit net = store
| otherwise = store {inputWitness = []}
return (net, res)
instance Arbitrary Spender where
arbitrary = Spender <$> arbitraryTxHash <*> arbitrary
instance Arbitrary StoreOutput where
arbitrary =
StoreOutput
<$> arbitrary
<*> arbitraryBS1
<*> arbitrary
<*> arbitraryMaybe arbitraryAddress
instance Arbitrary Transaction where
arbitrary =
Transaction
<$> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitraryTxHash
<*> arbitrary
<*> arbitrary
<*> arbitrary
instance Arbitrary PeerInformation where
arbitrary =
PeerInformation
<$> (cs <$> listOf arbitraryUnicodeChar)
<*> listOf arbitraryPrintableChar
<*> arbitrary
<*> arbitrary
<*> arbitrary
instance Arbitrary BlockHealth where
arbitrary =
BlockHealth
<$> arbitrary
<*> arbitrary
<*> arbitrary
instance Arbitrary TimeHealth where
arbitrary =
TimeHealth
<$> arbitrary
<*> arbitrary
instance Arbitrary CountHealth where
arbitrary =
CountHealth
<$> arbitrary
<*> arbitrary
instance Arbitrary MaxHealth where
arbitrary =
MaxHealth
<$> arbitrary
<*> arbitrary
instance Arbitrary HealthCheck where
arbitrary =
HealthCheck
<$> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
instance Arbitrary RejectCode where
arbitrary =
elements
[ RejectMalformed,
RejectInvalid,
RejectObsolete,
RejectDuplicate,
RejectNonStandard,
RejectDust,
RejectInsufficientFee,
RejectCheckpoint
]
instance Arbitrary XPubSpec where
arbitrary = XPubSpec <$> (snd <$> arbitraryXPubKey) <*> arbitrary
instance Arbitrary DeriveType where
arbitrary = elements [DeriveNormal, DeriveP2SH, DeriveP2WPKH]
instance Arbitrary TxId where
arbitrary = TxId <$> arbitraryTxHash
instance Arbitrary TxRef where
arbitrary = TxRef <$> arbitrary <*> arbitraryTxHash
instance Arbitrary Balance where
arbitrary =
Balance
<$> arbitraryAddress
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
instance Arbitrary Unspent where
arbitrary =
Unspent
<$> arbitrary
<*> arbitraryOutPoint
<*> arbitrary
<*> arbitraryBS1
<*> arbitraryMaybe arbitraryAddress
instance Arbitrary BlockData where
arbitrary =
BlockData
<$> arbitrary
<*> arbitrary
<*> (fromInteger <$> suchThat arbitrary (0 <=))
<*> arbitraryBlockHeader
<*> arbitrary
<*> arbitrary
<*> listOf1 arbitraryTxHash
<*> arbitrary
<*> arbitrary
<*> arbitrary
arbitraryBlockDataNet :: Gen (Network, BlockData)
arbitraryBlockDataNet = do
net <- arbitraryNetwork
dat <- arbitrary
let res
| getSegWit net = dat
| otherwise = dat {blockDataWeight = 0}
return (net, res)
instance Arbitrary a => Arbitrary (GenericResult a) where
arbitrary = GenericResult <$> arbitrary
instance Arbitrary a => Arbitrary (RawResult a) where
arbitrary = RawResult <$> arbitrary
instance Arbitrary a => Arbitrary (RawResultList a) where
arbitrary = RawResultList <$> arbitrary
instance Arbitrary XPubBal where
arbitrary = XPubBal <$> arbitrary <*> arbitrary
instance Arbitrary XPubUnspent where
arbitrary = XPubUnspent <$> arbitrary <*> arbitrary
instance Arbitrary XPubSummary where
arbitrary =
XPubSummary
<$> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
instance Arbitrary Event where
arbitrary =
oneof
[ EventBlock <$> arbitraryBlockHash,
EventTx <$> arbitraryTxHash
]
instance Arbitrary Except where
arbitrary =
oneof
[ return ThingNotFound,
return ServerError,
return BadRequest,
UserError <$> arbitrary,
StringError <$> arbitrary,
TxIndexConflict <$> listOf1 arbitraryTxHash,
return ServerTimeout
]
---------------------------------------
-- Blockchain.info API Compatibility --
---------------------------------------
instance Arbitrary BinfoTxId where
arbitrary =
oneof
[ BinfoTxIdHash <$> arbitraryTxHash,
BinfoTxIdIndex <$> arbitrary
]
instance Arbitrary BinfoMultiAddr where
arbitrary = do
getBinfoMultiAddrAddresses <- arbitrary
getBinfoMultiAddrWallet <- arbitrary
getBinfoMultiAddrTxs <- resize 10 arbitrary
getBinfoMultiAddrInfo <- arbitrary
getBinfoMultiAddrRecommendFee <- arbitrary
getBinfoMultiAddrCashAddr <- arbitrary
return BinfoMultiAddr {..}
instance Arbitrary BinfoRawAddr where
arbitrary = do
binfoRawAddr <-
oneof
[ BinfoAddr <$> arbitraryAddress,
BinfoXpub . snd <$> arbitraryXPubKey
]
binfoRawBalance <- arbitrary
binfoRawTxCount <- arbitrary
binfoRawUnredeemed <- arbitrary
binfoRawReceived <- arbitrary
binfoRawSent <- arbitrary
binfoRawTxs <- arbitrary
return $ BinfoRawAddr {..}
instance Arbitrary BinfoShortBal where
arbitrary = BinfoShortBal <$> arbitrary <*> arbitrary <*> arbitrary
instance Arbitrary BinfoBalance where
arbitrary = do
getBinfoAddress <- arbitraryAddress
getBinfoAddrTxCount <- arbitrary
getBinfoAddrReceived <- arbitrary
getBinfoAddrSent <- arbitrary
getBinfoAddrBalance <- arbitrary
getBinfoXPubKey <- snd <$> arbitraryXPubKey
getBinfoXPubAccountIndex <- arbitrary
getBinfoXPubChangeIndex <- arbitrary
elements [BinfoAddrBalance {..}, BinfoXPubBalance {..}]
instance Arbitrary BinfoWallet where
arbitrary = do
getBinfoWalletBalance <- arbitrary
getBinfoWalletTxCount <- arbitrary
getBinfoWalletFilteredCount <- arbitrary
getBinfoWalletTotalReceived <- arbitrary
getBinfoWalletTotalSent <- arbitrary
return BinfoWallet {..}
instance Arbitrary BinfoBlock where
arbitrary = do
getBinfoBlockHash <- arbitraryBlockHash
getBinfoBlockVer <- arbitrary
getBinfoPrevBlock <- arbitraryBlockHash
getBinfoMerkleRoot <- getTxHash <$> arbitraryTxHash
getBinfoBlockTime <- arbitrary
getBinfoBlockBits <- arbitrary
getBinfoNextBlock <- listOf arbitraryBlockHash
getBinfoBlockTxCount <- arbitrary
getBinfoBlockFee <- arbitrary
getBinfoBlockNonce <- arbitrary
getBinfoBlockSize <- arbitrary
getBinfoBlockIndex <- arbitrary
getBinfoBlockMain <- arbitrary
getBinfoBlockHeight <- arbitrary
getBinfoBlockWeight <- arbitrary
getBinfoBlockTx <- resize 5 arbitrary
return BinfoBlock {..}
instance Arbitrary BinfoTx where
arbitrary = do
getBinfoTxHash <- arbitraryTxHash
getBinfoTxVer <- arbitrary
getBinfoTxInputs <- resize 5 $ listOf1 arbitrary
getBinfoTxOutputs <- resize 5 $ listOf1 arbitrary
let getBinfoTxVinSz = fromIntegral (length getBinfoTxInputs)
getBinfoTxVoutSz = fromIntegral (length getBinfoTxOutputs)
getBinfoTxSize <- arbitrary
getBinfoTxWeight <- arbitrary
getBinfoTxFee <- arbitrary
getBinfoTxRelayedBy <- cs <$> listOf arbitraryUnicodeChar
getBinfoTxLockTime <- arbitrary
getBinfoTxIndex <- arbitrary
getBinfoTxDoubleSpend <- arbitrary
getBinfoTxRBF <- arbitrary
getBinfoTxTime <- arbitrary
getBinfoTxBlockIndex <- arbitrary
getBinfoTxBlockHeight <- arbitrary
getBinfoTxResultBal <- arbitrary
return BinfoTx {..}
instance Arbitrary BinfoTxInput where
arbitrary = do
getBinfoTxInputSeq <- arbitrary
getBinfoTxInputWitness <- B.pack <$> listOf arbitrary
getBinfoTxInputScript <- B.pack <$> listOf arbitrary
getBinfoTxInputIndex <- arbitrary
getBinfoTxInputPrevOut <- arbitrary
return BinfoTxInput {..}
instance Arbitrary BinfoTxOutput where
arbitrary = do
getBinfoTxOutputType <- arbitrary
getBinfoTxOutputSpent <- arbitrary
getBinfoTxOutputValue <- arbitrary
getBinfoTxOutputIndex <- arbitrary
getBinfoTxOutputTxIndex <- arbitrary
getBinfoTxOutputScript <- B.pack <$> listOf arbitrary
getBinfoTxOutputSpenders <- arbitrary
getBinfoTxOutputAddress <-
oneof [return Nothing, Just <$> arbitraryAddress]
getBinfoTxOutputXPub <- arbitrary
return BinfoTxOutput {..}
instance Arbitrary BinfoSpender where
arbitrary = do
getBinfoSpenderTxIndex <- arbitrary
getBinfoSpenderIndex <- arbitrary
return BinfoSpender {..}
instance Arbitrary BinfoXPubPath where
arbitrary = do
getBinfoXPubPathKey <- snd <$> arbitraryXPubKey
getBinfoXPubPathDeriv <- arbitrarySoftPath
return BinfoXPubPath {..}
instance Arbitrary BinfoInfo where
arbitrary = do
getBinfoConnected <- arbitrary
getBinfoConversion <- arbitrary
getBinfoLocal <- arbitrary
getBinfoBTC <- arbitrary
getBinfoLatestBlock <- arbitrary
return BinfoInfo {..}
instance Arbitrary BinfoBlockInfo where
arbitrary = do
getBinfoBlockInfoHash <- arbitraryBlockHash
getBinfoBlockInfoHeight <- arbitrary
getBinfoBlockInfoTime <- arbitrary
getBinfoBlockInfoIndex <- arbitrary
return BinfoBlockInfo {..}
instance Arbitrary BinfoSymbol where
arbitrary = do
getBinfoSymbolCode <- cs <$> listOf1 arbitraryUnicodeChar
getBinfoSymbolString <- cs <$> listOf1 arbitraryUnicodeChar
getBinfoSymbolName <- cs <$> listOf1 arbitraryUnicodeChar
getBinfoSymbolConversion <- arbitrary
getBinfoSymbolAfter <- arbitrary
getBinfoSymbolLocal <- arbitrary
return BinfoSymbol {..}
instance Arbitrary BinfoRate where
arbitrary = BinfoRate <$> arbitrary <*> arbitrary <*> arbitrary
instance Arbitrary BinfoTicker where
arbitrary = do
binfoTicker15m <- arbitrary
binfoTickerSell <- arbitrary
binfoTickerBuy <- arbitrary
binfoTickerLast <- arbitrary
binfoTickerSymbol <- cs <$> listOf1 arbitraryUnicodeChar
return BinfoTicker {..}
instance Arbitrary BinfoHistory where
arbitrary = do
binfoHistoryDate <- cs <$> listOf1 arbitraryUnicodeChar
binfoHistoryTime <- cs <$> listOf1 arbitraryUnicodeChar
binfoHistoryType <- cs <$> listOf1 arbitraryUnicodeChar
binfoHistoryAmount <- arbitrary
binfoHistoryValueThen <- arbitrary
binfoHistoryValueNow <- arbitrary
binfoHistoryExchangeRateThen <- arbitrary
binfoHistoryTx <- arbitraryTxHash
return BinfoHistory {..}
instance Arbitrary BinfoUnspent where
arbitrary = do
getBinfoUnspentHash <- arbitraryTxHash
getBinfoUnspentOutputIndex <- arbitrary
getBinfoUnspentScript <- B.pack <$> listOf arbitrary
getBinfoUnspentValue <- arbitrary
getBinfoUnspentConfirmations <- arbitrary
getBinfoUnspentTxIndex <- arbitrary
getBinfoUnspentXPub <- arbitrary
return BinfoUnspent {..}
instance Arbitrary BinfoUnspents where
arbitrary = BinfoUnspents <$> arbitrary
instance Arbitrary BinfoHeader where
arbitrary =
BinfoHeader
<$> arbitraryBlockHash
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
instance Arbitrary BinfoMempool where
arbitrary = BinfoMempool <$> arbitrary
instance Arbitrary BinfoBlocks where
arbitrary = BinfoBlocks <$> arbitrary