Skip to content

Commit

Permalink
Replace genFixedSize{Coin,TokenBundle} with `genTxOut{Coin,TokenBun…
Browse files Browse the repository at this point in the history
…dle}`.

These generators are specifically designed to generate values across the
full range of what's permitted to appear in a transaction output.

Therefore, we rename them to have the `genTxOut` prefix, and we move
them to the `Tx.Gen` module.
  • Loading branch information
jonathanknowles committed Nov 23, 2021
1 parent 32ad6ba commit 0084628
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 88 deletions.
57 changes: 7 additions & 50 deletions lib/core/src/Cardano/Wallet/Primitive/Types/TokenBundle/Gen.hs
@@ -1,6 +1,5 @@
module Cardano.Wallet.Primitive.Types.TokenBundle.Gen
( genFixedSizeTokenBundle
, genTokenBundleSmallRange
( genTokenBundleSmallRange
, genTokenBundleSmallRangePositive
, genTokenBundle
, shrinkTokenBundleSmallRange
Expand All @@ -10,59 +9,16 @@ module Cardano.Wallet.Primitive.Types.TokenBundle.Gen
import Prelude

import Cardano.Wallet.Primitive.Types.Coin.Gen
( genCoin
, genCoinFullRange
, genCoinPositive
, shrinkCoin
, shrinkCoinPositive
)
( genCoin, genCoinPositive, shrinkCoin, shrinkCoinPositive )
import Cardano.Wallet.Primitive.Types.TokenBundle
( TokenBundle (..) )
import Cardano.Wallet.Primitive.Types.TokenMap.Gen
( genAssetIdLargeRange, genTokenMapSmallRange, shrinkTokenMap )
import Cardano.Wallet.Primitive.Types.TokenQuantity
( TokenQuantity (..) )
import Cardano.Wallet.Primitive.Types.Tx
( txOutMaxTokenQuantity, txOutMinTokenQuantity )
import Control.Monad
( replicateM )
( genTokenMap, genTokenMapSmallRange, shrinkTokenMap )
import Test.QuickCheck
( Gen, choose, oneof, sized )
( Gen )
import Test.QuickCheck.Extra
( shrinkInterleaved )

import qualified Cardano.Wallet.Primitive.Types.TokenBundle as TokenBundle

--------------------------------------------------------------------------------
-- Token bundles with fixed numbers of assets.
--
-- Policy identifiers, asset names, token quantities are all allowed to vary.
--------------------------------------------------------------------------------

genFixedSizeTokenBundle :: Int -> Gen TokenBundle
genFixedSizeTokenBundle fixedAssetCount
= TokenBundle.fromFlatList
<$> genCoinFullRange
<*> replicateM fixedAssetCount genAssetQuantity
where
genAssetQuantity = (,)
<$> genAssetIdLargeRange
<*> genTokenQuantity
genTokenQuantity = integerToTokenQuantity <$> oneof
[ pure $ tokenQuantityToInteger txOutMinTokenQuantity
, pure $ tokenQuantityToInteger txOutMaxTokenQuantity
, choose
( tokenQuantityToInteger txOutMinTokenQuantity + 1
, tokenQuantityToInteger txOutMaxTokenQuantity - 1
)
]
where
tokenQuantityToInteger :: TokenQuantity -> Integer
tokenQuantityToInteger = fromIntegral . unTokenQuantity

integerToTokenQuantity :: Integer -> TokenQuantity
integerToTokenQuantity = TokenQuantity . fromIntegral

--------------------------------------------------------------------------------
-- Token bundles with variable numbers of assets, the upper bound being
-- QuickCheck's size parameter.
Expand All @@ -71,8 +27,9 @@ genFixedSizeTokenBundle fixedAssetCount
--------------------------------------------------------------------------------

genTokenBundle :: Gen TokenBundle
genTokenBundle = sized $ \maxAssetCount ->
choose (0, maxAssetCount) >>= genFixedSizeTokenBundle
genTokenBundle = TokenBundle
<$> genCoin
<*> genTokenMap

--------------------------------------------------------------------------------
-- Token bundles with coins, assets, and quantities chosen from small ranges
Expand Down
89 changes: 87 additions & 2 deletions lib/core/src/Cardano/Wallet/Primitive/Types/Tx/Gen.hs
Expand Up @@ -14,12 +14,15 @@ module Cardano.Wallet.Primitive.Types.Tx.Gen
, genTxInFunction
, genTxInLargeRange
, genTxOut
, genTxOutCoin
, genTxOutTokenBundle
, genTxScriptValidity
, shrinkTx
, shrinkTxHash
, shrinkTxIndex
, shrinkTxIn
, shrinkTxOut
, shrinkTxOutCoin
, shrinkTxScriptValidity
)
where
Expand All @@ -44,8 +47,22 @@ import Cardano.Wallet.Primitive.Types.TokenBundle
( TokenBundle )
import Cardano.Wallet.Primitive.Types.TokenBundle.Gen
( genTokenBundleSmallRange, shrinkTokenBundleSmallRange )
import Cardano.Wallet.Primitive.Types.TokenMap.Gen
( genAssetIdLargeRange )
import Cardano.Wallet.Primitive.Types.TokenQuantity
( TokenQuantity (..) )
import Cardano.Wallet.Primitive.Types.Tx
( Tx (..), TxIn (..), TxMetadata (..), TxOut (..), TxScriptValidity (..) )
( Tx (..)
, TxIn (..)
, TxMetadata (..)
, TxOut (..)
, TxScriptValidity (..)
, coinIsValidForTxOut
, txOutMaxCoin
, txOutMaxTokenQuantity
, txOutMinCoin
, txOutMinTokenQuantity
)
import Control.Monad
( replicateM )
import Data.Either
Expand All @@ -63,14 +80,17 @@ import GHC.Generics
import Test.QuickCheck
( Gen
, arbitrary
, choose
, coarbitrary
, elements
, frequency
, liftArbitrary
, liftArbitrary2
, liftShrink
, liftShrink2
, listOf
, listOf1
, oneof
, shrinkList
, shrinkMapBy
, sized
Expand All @@ -79,18 +99,22 @@ import Test.QuickCheck
import Test.QuickCheck.Arbitrary.Generic
( genericArbitrary, genericShrink )
import Test.QuickCheck.Extra
( genFunction
( chooseNatural
, genFunction
, genMapWith
, genSized2With
, genericRoundRobinShrink
, shrinkInterleaved
, shrinkMapWith
, shrinkNatural
, (<:>)
, (<@>)
)

import qualified Cardano.Wallet.Primitive.Types.Coin as Coin
import qualified Cardano.Wallet.Primitive.Types.TokenBundle as TokenBundle
import qualified Data.ByteString.Char8 as B8
import qualified Data.List as L
import qualified Data.Text as T

--------------------------------------------------------------------------------
Expand Down Expand Up @@ -235,6 +259,67 @@ shrinkTxOut (TxOut a b) = uncurry TxOut <$> shrinkInterleaved
tokenBundleHasNonZeroCoin :: TokenBundle -> Bool
tokenBundleHasNonZeroCoin b = TokenBundle.getCoin b /= Coin 0

--------------------------------------------------------------------------------
-- Coins chosen from the full range allowed in a transaction output
--------------------------------------------------------------------------------

-- | Generates coins across the full range allowed in a transaction output.
--
-- This generator has a slight bias towards the limits of the range, but
-- otherwise generates values uniformly across the whole range.
--
-- This can be useful when testing roundtrip conversions between different
-- types.
--
genTxOutCoin :: Gen Coin
genTxOutCoin = frequency
[ (1, pure txOutMinCoin)
, (1, pure txOutMaxCoin)
, (8, Coin.fromNatural <$> chooseNatural
( Coin.toNatural txOutMinCoin + 1
, Coin.toNatural txOutMaxCoin - 1
)
)
]

shrinkTxOutCoin :: Coin -> [Coin]
shrinkTxOutCoin
= L.filter coinIsValidForTxOut
. shrinkMapBy Coin.fromNatural Coin.toNatural shrinkNatural

--------------------------------------------------------------------------------
-- Token bundles with fixed numbers of assets.
--
-- Values are chosen from across the full range of values permitted within
-- transaction outputs.
--
-- Policy identifiers, asset names, token quantities are all allowed to vary.
--------------------------------------------------------------------------------

genTxOutTokenBundle :: Int -> Gen TokenBundle
genTxOutTokenBundle fixedAssetCount
= TokenBundle.fromFlatList
<$> genTxOutCoin
<*> replicateM fixedAssetCount genAssetQuantity
where
genAssetQuantity = (,)
<$> genAssetIdLargeRange
<*> genTokenQuantity
genTokenQuantity = integerToTokenQuantity <$> oneof
[ pure $ tokenQuantityToInteger txOutMinTokenQuantity
, pure $ tokenQuantityToInteger txOutMaxTokenQuantity
, choose
( tokenQuantityToInteger txOutMinTokenQuantity + 1
, tokenQuantityToInteger txOutMaxTokenQuantity - 1
)
]
where
tokenQuantityToInteger :: TokenQuantity -> Integer
tokenQuantityToInteger = fromIntegral . unTokenQuantity

integerToTokenQuantity :: Integer -> TokenQuantity
integerToTokenQuantity = TokenQuantity . fromIntegral

--------------------------------------------------------------------------------
-- Internal utilities
--------------------------------------------------------------------------------
Expand Down
8 changes: 4 additions & 4 deletions lib/core/test/unit/Cardano/Pool/DB/Arbitrary.hs
Expand Up @@ -46,10 +46,10 @@ import Cardano.Wallet.Primitive.Types
)
import Cardano.Wallet.Primitive.Types.Coin
( Coin (..) )
import Cardano.Wallet.Primitive.Types.Coin.Gen
( genCoinFullRange, shrinkCoinFullRange )
import Cardano.Wallet.Primitive.Types.Hash
( Hash (..) )
import Cardano.Wallet.Primitive.Types.Tx.Gen
( genTxOutCoin, shrinkTxOutCoin )
import Control.Arrow
( second )
import Control.Monad
Expand Down Expand Up @@ -141,8 +141,8 @@ instance Arbitrary (Quantity "lovelace" Word64) where
arbitrary = Quantity <$> arbitrary

instance Arbitrary Coin where
shrink = shrinkCoinFullRange
arbitrary = genCoinFullRange
shrink = shrinkTxOutCoin
arbitrary = genTxOutCoin

arbitraryEpochLength :: Word32
arbitraryEpochLength = 100
Expand Down
6 changes: 3 additions & 3 deletions lib/core/test/unit/Cardano/Wallet/Api/TypesSpec.hs
Expand Up @@ -253,7 +253,7 @@ import Cardano.Wallet.Primitive.Types.Address
import Cardano.Wallet.Primitive.Types.Coin
( Coin (..) )
import Cardano.Wallet.Primitive.Types.Coin.Gen
( genCoinFullRange, genCoinPositive )
( genCoinPositive )
import Cardano.Wallet.Primitive.Types.Hash
( Hash (..) )
import Cardano.Wallet.Primitive.Types.RewardAccount
Expand Down Expand Up @@ -291,7 +291,7 @@ import Cardano.Wallet.Primitive.Types.Tx
, unsafeSealedTxFromBytes
)
import Cardano.Wallet.Primitive.Types.Tx.Gen
( genTxScriptValidity, shrinkTxScriptValidity )
( genTxOutCoin, genTxScriptValidity, shrinkTxScriptValidity )
import Cardano.Wallet.Primitive.Types.UTxO
( HistogramBar (..)
, UTxO (..)
Expand Down Expand Up @@ -2359,7 +2359,7 @@ instance Arbitrary RewardAccount where

instance Arbitrary Coin where
-- No Shrinking
arbitrary = genCoinFullRange
arbitrary = genTxOutCoin

instance Arbitrary UTxO where
shrink (UTxO utxo) = UTxO <$> shrink utxo
Expand Down
6 changes: 2 additions & 4 deletions lib/core/test/unit/Cardano/Wallet/DB/Arbitrary.hs
Expand Up @@ -112,8 +112,6 @@ import Cardano.Wallet.Primitive.Types.Address
( Address (..), AddressState (..) )
import Cardano.Wallet.Primitive.Types.Coin
( Coin (..) )
import Cardano.Wallet.Primitive.Types.Coin.Gen
( genCoinFullRange )
import Cardano.Wallet.Primitive.Types.Hash
( Hash (..), mockHash )
import Cardano.Wallet.Primitive.Types.RewardAccount
Expand All @@ -132,7 +130,7 @@ import Cardano.Wallet.Primitive.Types.Tx
, isPending
)
import Cardano.Wallet.Primitive.Types.Tx.Gen
( genTxScriptValidity, shrinkTxScriptValidity )
( genTxOutCoin, genTxScriptValidity, shrinkTxScriptValidity )
import Cardano.Wallet.Primitive.Types.UTxO
( UTxO (..) )
import Cardano.Wallet.Unsafe
Expand Down Expand Up @@ -429,7 +427,7 @@ instance Arbitrary TxMetadata where
shrink = shrinkTxMetadata

instance Arbitrary Coin where
arbitrary = genCoinFullRange
arbitrary = genTxOutCoin

instance Arbitrary UTxO where
shrink (UTxO u) =
Expand Down
Expand Up @@ -14,15 +14,10 @@ import Cardano.Wallet.Primitive.Types
( MinimumUTxOValue (..) )
import Cardano.Wallet.Primitive.Types.Coin
( Coin (..) )
import Cardano.Wallet.Primitive.Types.Coin.Gen
( genCoinFullRange, shrinkCoinFullRange )
import Cardano.Wallet.Primitive.Types.TokenBundle
( Flat (..), TokenBundle )
import Cardano.Wallet.Primitive.Types.TokenBundle.Gen
( genFixedSizeTokenBundle
, genTokenBundleSmallRange
, shrinkTokenBundleSmallRange
)
( genTokenBundleSmallRange, shrinkTokenBundleSmallRange )
import Cardano.Wallet.Primitive.Types.TokenPolicy
( TokenName, TokenPolicyId )
import Cardano.Wallet.Primitive.Types.TokenPolicy.Gen
Expand All @@ -33,6 +28,8 @@ import Cardano.Wallet.Primitive.Types.TokenQuantity.Gen
( genTokenQuantityFullRange, shrinkTokenQuantityFullRange )
import Cardano.Wallet.Primitive.Types.Tx
( txOutMaxTokenQuantity, txOutMinTokenQuantity )
import Cardano.Wallet.Primitive.Types.Tx.Gen
( genTxOutCoin, genTxOutTokenBundle, shrinkTxOutCoin )
import Cardano.Wallet.Shelley.Compatibility.Ledger
( Convert (..), computeMinimumAdaQuantityInternal )
import Data.Bifunctor
Expand Down Expand Up @@ -271,8 +268,8 @@ newtype FixedSize256 a = FixedSize256 { unFixedSize256 :: a }
instance Arbitrary Coin where
-- This instance is used to test roundtrip conversions, so it's important
-- that we generate coins across the full range available.
arbitrary = genCoinFullRange
shrink = shrinkCoinFullRange
arbitrary = genTxOutCoin
shrink = shrinkTxOutCoin

instance Arbitrary MinimumUTxOValue where
arbitrary = oneof
Expand All @@ -288,15 +285,15 @@ instance Arbitrary TokenBundle where
shrink = shrinkTokenBundleSmallRange

instance Arbitrary (FixedSize8 TokenBundle) where
arbitrary = FixedSize8 <$> genFixedSizeTokenBundle 8
arbitrary = FixedSize8 <$> genTxOutTokenBundle 8
-- No shrinking

instance Arbitrary (FixedSize64 TokenBundle) where
arbitrary = FixedSize64 <$> genFixedSizeTokenBundle 64
arbitrary = FixedSize64 <$> genTxOutTokenBundle 64
-- No shrinking

instance Arbitrary (FixedSize256 TokenBundle) where
arbitrary = FixedSize256 <$> genFixedSizeTokenBundle 256
arbitrary = FixedSize256 <$> genTxOutTokenBundle 256
-- No shrinking

instance Arbitrary TokenName where
Expand Down

0 comments on commit 0084628

Please sign in to comment.