{- |
Module      : Haskoin.Test.Network
Copyright   : No rights reserved
License     : MIT
Maintainer  : jprupp@protonmail.ch
Stability   : experimental
Portability : POSIX
-}
module Haskoin.Util.Arbitrary.Network where

import qualified Data.ByteString as BS (empty, pack)
import qualified Data.ByteString.Char8 as C8
import Data.Word (Word16, Word32)
import Haskoin.Network
import Haskoin.Util.Arbitrary.Crypto
import Haskoin.Util.Arbitrary.Util
import Network.Socket (SockAddr (..))
import Test.QuickCheck

-- | Arbitrary 'VarInt'.
arbitraryVarInt :: Gen VarInt
arbitraryVarInt :: Gen VarInt
arbitraryVarInt = Word64 -> VarInt
VarInt forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Arbitrary a => Gen a
arbitrary

-- | Arbitrary 'VarString'.
arbitraryVarString :: Gen VarString
arbitraryVarString :: Gen VarString
arbitraryVarString = ByteString -> VarString
VarString forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen ByteString
arbitraryBS

-- | Arbitrary 'NetworkAddress'.
arbitraryNetworkAddress :: Gen NetworkAddress
arbitraryNetworkAddress :: Gen NetworkAddress
arbitraryNetworkAddress = do
    Word64
s <- forall a. Arbitrary a => Gen a
arbitrary
    Word32
a <- forall a. Arbitrary a => Gen a
arbitrary
    Word16
p <- forall a. Arbitrary a => Gen a
arbitrary
    SockAddr
d <-
        forall a. [Gen a] -> Gen a
oneof
            [ do
                Word32
b <- forall a. Arbitrary a => Gen a
arbitrary
                Word32
c <- forall a. Arbitrary a => Gen a
arbitrary
                Word32
d <- forall a. Arbitrary a => Gen a
arbitrary
                forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ PortNumber -> Word32 -> HostAddress6 -> Word32 -> SockAddr
SockAddrInet6 (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word16
p) Word32
0 (Word32
a, Word32
b, Word32
c, Word32
d) Word32
0
            , forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ PortNumber -> Word32 -> SockAddr
SockAddrInet (forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word16
p :: Word16)) Word32
a
            ]
    let n :: HostAddress
n = SockAddr -> HostAddress
sockToHostAddress SockAddr
d
    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Word64 -> HostAddress -> NetworkAddress
NetworkAddress Word64
s HostAddress
n

-- | Arbitrary 'NetworkAddressTime'.
arbitraryNetworkAddressTime :: Gen (Word32, NetworkAddress)
arbitraryNetworkAddressTime :: Gen (Word32, NetworkAddress)
arbitraryNetworkAddressTime = (,) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Arbitrary a => Gen a
arbitrary forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen NetworkAddress
arbitraryNetworkAddress

-- | Arbitrary 'InvType'.
arbitraryInvType :: Gen InvType
arbitraryInvType :: Gen InvType
arbitraryInvType = forall a. [a] -> Gen a
elements [InvType
InvError, InvType
InvTx, InvType
InvBlock, InvType
InvMerkleBlock]

-- | Arbitrary 'InvVector'.
arbitraryInvVector :: Gen InvVector
arbitraryInvVector :: Gen InvVector
arbitraryInvVector = InvType -> Hash256 -> InvVector
InvVector forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen InvType
arbitraryInvType forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen Hash256
arbitraryHash256

-- | Arbitrary non-empty 'Inv'.
arbitraryInv1 :: Gen Inv
arbitraryInv1 :: Gen Inv
arbitraryInv1 = [InvVector] -> Inv
Inv forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Gen a -> Gen [a]
listOf1 Gen InvVector
arbitraryInvVector

-- | Arbitrary 'Version'.
arbitraryVersion :: Gen Version
arbitraryVersion :: Gen Version
arbitraryVersion =
    Word32
-> Word64
-> Word64
-> NetworkAddress
-> NetworkAddress
-> Word64
-> VarString
-> Word32
-> Bool
-> Version
Version forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Arbitrary a => Gen a
arbitrary
        forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. Arbitrary a => Gen a
arbitrary
        forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. Arbitrary a => Gen a
arbitrary
        forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen NetworkAddress
arbitraryNetworkAddress
        forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen NetworkAddress
arbitraryNetworkAddress
        forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. Arbitrary a => Gen a
arbitrary
        forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen VarString
arbitraryVarString
        forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. Arbitrary a => Gen a
arbitrary
        forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. Arbitrary a => Gen a
arbitrary

-- | Arbitrary non-empty 'Addr'.
arbitraryAddr1 :: Gen Addr
arbitraryAddr1 :: Gen Addr
arbitraryAddr1 = [(Word32, NetworkAddress)] -> Addr
Addr forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Gen a -> Gen [a]
listOf1 Gen (Word32, NetworkAddress)
arbitraryNetworkAddressTime

{- | Arbitrary 'Alert' with random payload and signature. Signature is not
 valid.
-}
arbitraryAlert :: Gen Alert
arbitraryAlert :: Gen Alert
arbitraryAlert = VarString -> VarString -> Alert
Alert forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen VarString
arbitraryVarString forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen VarString
arbitraryVarString

-- | Arbitrary 'Reject'.
arbitraryReject :: Gen Reject
arbitraryReject :: Gen Reject
arbitraryReject = do
    MessageCommand
m <- Gen MessageCommand
arbitraryMessageCommand
    RejectCode
c <- Gen RejectCode
arbitraryRejectCode
    VarString
s <- Gen VarString
arbitraryVarString
    ByteString
d <-
        forall a. [Gen a] -> Gen a
oneof
            [ forall (m :: * -> *) a. Monad m => a -> m a
return ByteString
BS.empty
            , [Word8] -> ByteString
BS.pack forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Int -> Gen a -> Gen [a]
vectorOf Int
32 forall a. Arbitrary a => Gen a
arbitrary
            ]
    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ MessageCommand -> RejectCode -> VarString -> ByteString -> Reject
Reject MessageCommand
m RejectCode
c VarString
s ByteString
d

-- | Arbitrary 'RejectCode'.
arbitraryRejectCode :: Gen RejectCode
arbitraryRejectCode :: Gen RejectCode
arbitraryRejectCode =
    forall a. [a] -> Gen a
elements
        [ RejectCode
RejectMalformed
        , RejectCode
RejectInvalid
        , RejectCode
RejectInvalid
        , RejectCode
RejectDuplicate
        , RejectCode
RejectNonStandard
        , RejectCode
RejectDust
        , RejectCode
RejectInsufficientFee
        , RejectCode
RejectCheckpoint
        ]

-- | Arbitrary non-empty 'GetData'.
arbitraryGetData :: Gen GetData
arbitraryGetData :: Gen GetData
arbitraryGetData = [InvVector] -> GetData
GetData forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Gen a -> Gen [a]
listOf1 Gen InvVector
arbitraryInvVector

-- | Arbitrary 'NotFound'.
arbitraryNotFound :: Gen NotFound
arbitraryNotFound :: Gen NotFound
arbitraryNotFound = [InvVector] -> NotFound
NotFound forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Gen a -> Gen [a]
listOf1 Gen InvVector
arbitraryInvVector

-- | Arbitrary 'Ping'.
arbitraryPing :: Gen Ping
arbitraryPing :: Gen Ping
arbitraryPing = Word64 -> Ping
Ping forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Arbitrary a => Gen a
arbitrary

-- | Arbitrary 'Pong'.
arbitraryPong :: Gen Pong
arbitraryPong :: Gen Pong
arbitraryPong = Word64 -> Pong
Pong forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Arbitrary a => Gen a
arbitrary

-- | Arbitrary bloom filter flags.
arbitraryBloomFlags :: Gen BloomFlags
arbitraryBloomFlags :: Gen BloomFlags
arbitraryBloomFlags =
    forall a. [a] -> Gen a
elements
        [ BloomFlags
BloomUpdateNone
        , BloomFlags
BloomUpdateAll
        , BloomFlags
BloomUpdateP2PubKeyOnly
        ]

{- | Arbitrary bloom filter with its corresponding number of elements
 and false positive rate.
-}
arbitraryBloomFilter :: Gen (Int, Double, BloomFilter)
arbitraryBloomFilter :: Gen (Int, Double, BloomFilter)
arbitraryBloomFilter = do
    Int
n <- forall a. Random a => (a, a) -> Gen a
choose (Int
0, Int
100000)
    Double
fp <- forall a. Random a => (a, a) -> Gen a
choose (Double
1e-8, Double
1)
    Word32
tweak <- forall a. Arbitrary a => Gen a
arbitrary
    BloomFlags
fl <- Gen BloomFlags
arbitraryBloomFlags
    forall (m :: * -> *) a. Monad m => a -> m a
return (Int
n, Double
fp, Int -> Double -> Word32 -> BloomFlags -> BloomFilter
bloomCreate Int
n Double
fp Word32
tweak BloomFlags
fl)

-- | Arbitrary 'FilterLoad'.
arbitraryFilterLoad :: Gen FilterLoad
arbitraryFilterLoad :: Gen FilterLoad
arbitraryFilterLoad = do
    (Int
_, Double
_, BloomFilter
bf) <- Gen (Int, Double, BloomFilter)
arbitraryBloomFilter
    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ BloomFilter -> FilterLoad
FilterLoad BloomFilter
bf

-- | Arbitrary 'FilterAdd'.
arbitraryFilterAdd :: Gen FilterAdd
arbitraryFilterAdd :: Gen FilterAdd
arbitraryFilterAdd = ByteString -> FilterAdd
FilterAdd forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen ByteString
arbitraryBS

-- | Arbitrary 'MessageCommand'.
arbitraryMessageCommand :: Gen MessageCommand
arbitraryMessageCommand :: Gen MessageCommand
arbitraryMessageCommand = do
    ASCIIString String
str <- forall a. Arbitrary a => Gen a
arbitrary
    forall a. [a] -> Gen a
elements
        [ MessageCommand
MCVersion
        , MessageCommand
MCVerAck
        , MessageCommand
MCAddr
        , MessageCommand
MCInv
        , MessageCommand
MCGetData
        , MessageCommand
MCNotFound
        , MessageCommand
MCGetBlocks
        , MessageCommand
MCGetHeaders
        , MessageCommand
MCTx
        , MessageCommand
MCBlock
        , MessageCommand
MCMerkleBlock
        , MessageCommand
MCHeaders
        , MessageCommand
MCGetAddr
        , MessageCommand
MCFilterLoad
        , MessageCommand
MCFilterAdd
        , MessageCommand
MCFilterClear
        , MessageCommand
MCPing
        , MessageCommand
MCPong
        , MessageCommand
MCAlert
        , ByteString -> MessageCommand
MCOther (Int -> ByteString -> ByteString
C8.take Int
12 (String -> ByteString
C8.pack (forall a. (a -> Bool) -> [a] -> [a]
filter (forall a. Eq a => a -> a -> Bool
/= Char
'\NUL') String
str)))
        ]