Implement QuickCheck tests for Orchard components #23
3 changed files with 51 additions and 12 deletions
|
@ -81,6 +81,7 @@ data CoinType
|
|||
= MainNetCoin
|
||||
| TestNetCoin
|
||||
| RegTestNetCoin
|
||||
deriving (Eq, Prelude.Show, Ord)
|
||||
|
||||
getValue :: CoinType -> Word32
|
||||
getValue c =
|
||||
|
|
60
test/Spec.hs
60
test/Spec.hs
|
@ -17,6 +17,7 @@
|
|||
|
||||
-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE TypeSynonymInstances #-}
|
||||
|
||||
import C.Zcash (rustWrapperUADecode)
|
||||
import Control.Monad.IO.Class (liftIO)
|
||||
|
@ -34,6 +35,8 @@ import qualified Data.Text.Lazy.IO as LTIO
|
|||
import Data.Word
|
||||
import GHC.Float.RealFracMethods (properFractionDoubleInteger)
|
||||
import Test.Hspec
|
||||
import Test.Hspec.QuickCheck
|
||||
import Test.QuickCheck
|
||||
import ZcashHaskell.Keys (generateWalletSeedPhrase, getWalletSeed)
|
||||
import ZcashHaskell.Orchard
|
||||
import ZcashHaskell.Sapling
|
||||
|
@ -49,6 +52,7 @@ import ZcashHaskell.Types
|
|||
, CoinType(..)
|
||||
, DecodedNote(..)
|
||||
, OrchardAction(..)
|
||||
, Phrase(..)
|
||||
, RawData(..)
|
||||
, RawTxResponse(..)
|
||||
, ShieldedOutput(..)
|
||||
|
@ -448,18 +452,12 @@ main = do
|
|||
msg `shouldBe`
|
||||
"Hello World!\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL"
|
||||
describe "Wallet seed phrase" $ do
|
||||
it "Generate phrase" $ do
|
||||
p <- generateWalletSeedPhrase
|
||||
BS.length p `shouldNotBe` 0
|
||||
it "Derive seed" $ do
|
||||
p <- generateWalletSeedPhrase
|
||||
let s = getWalletSeed p
|
||||
maybe 0 BS.length s `shouldBe` 64
|
||||
it "Generate Orchard spending key" $ do
|
||||
p <- generateWalletSeedPhrase
|
||||
let s = getWalletSeed p
|
||||
genOrchardSpendingKey (fromMaybe "" s) MainNetCoin 1 `shouldNotBe`
|
||||
Nothing
|
||||
prop "Generated phrases are valid" prop_PhraseLength
|
||||
prop "Derived seeds are valid" prop_SeedLength
|
||||
prop "Orchard spending keys are valid" $
|
||||
forAll genOrcArgs $ \(c, i, _) -> prop_OrchardSpendingKey c i
|
||||
prop "Orchard receivers are valid" $
|
||||
forAll genOrcArgs $ \(c, i, j) -> prop_OrchardReceiver c i j
|
||||
describe "Address tests" $ do
|
||||
it "Encode transparent" $ do
|
||||
let ua =
|
||||
|
@ -469,3 +467,41 @@ main = do
|
|||
Nothing -> "Bad UA"
|
||||
Just u -> maybe "No transparent" encodeTransparent $ t_rec u
|
||||
msg `shouldBe` "t1LPWuQnjCRH7JAeEErSXKixcUteLJRJjKD"
|
||||
|
||||
-- | Properties
|
||||
prop_PhraseLength :: Int -> Property
|
||||
prop_PhraseLength i =
|
||||
ioProperty $ do
|
||||
p <- generateWalletSeedPhrase
|
||||
return $ BS.length p >= 95
|
||||
|
||||
prop_SeedLength :: Int -> Property
|
||||
prop_SeedLength i =
|
||||
ioProperty $ do
|
||||
p <- generateWalletSeedPhrase
|
||||
let s = getWalletSeed p
|
||||
return $ maybe 0 BS.length s === 64
|
||||
|
||||
prop_OrchardSpendingKey :: CoinType -> Int -> Property
|
||||
prop_OrchardSpendingKey c i =
|
||||
ioProperty $ do
|
||||
p <- generateWalletSeedPhrase
|
||||
let s = getWalletSeed p
|
||||
return $ genOrchardSpendingKey (fromMaybe "" s) c i =/= Nothing
|
||||
|
||||
prop_OrchardReceiver :: CoinType -> Int -> Int -> Property
|
||||
prop_OrchardReceiver c i j =
|
||||
ioProperty $ do
|
||||
p <- generateWalletSeedPhrase
|
||||
let s = getWalletSeed p
|
||||
let sk = genOrchardSpendingKey (fromMaybe "" s) c i
|
||||
return $ genOrchardReceiver j (fromMaybe "" sk) =/= Nothing
|
||||
|
||||
-- | Generators
|
||||
genOrcArgs :: Gen (CoinType, Int, Int)
|
||||
genOrcArgs = do
|
||||
i <- arbitrarySizedNatural
|
||||
j <- arbitrarySizedNatural
|
||||
c <- elements [MainNetCoin, TestNetCoin, RegTestNetCoin]
|
||||
return (c, i, j)
|
||||
-- | Arbitrary instances
|
||||
|
|
|
@ -72,6 +72,8 @@ test-suite zcash-haskell-test
|
|||
, haskoin-core
|
||||
, hexstring
|
||||
, hspec
|
||||
, QuickCheck
|
||||
, quickcheck-transformer
|
||||
, text
|
||||
, zcash-haskell
|
||||
pkgconfig-depends: rustzcash_wrapper
|
||||
|
|
Loading…
Reference in a new issue