11{-# LANGUAGE OverloadedStrings #-}
22{-# LANGUAGE TypeApplications #-}
33{-# LANGUAGE ViewPatterns #-}
4+ {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}
45{-# OPTIONS_GHC -Wno-orphans #-}
56
67module Value.Spec (tests ) where
@@ -11,15 +12,18 @@ import Data.Either
1112import Data.Foldable qualified as F
1213import Data.Map.Strict qualified as Map
1314import Data.Maybe
14- import PlutusCore.Flat qualified as Flat
15- import PlutusCore.Generators.QuickCheck.Builtin (ValueAmount (.. ), genShortHex )
16- import PlutusCore.Value (Value )
17- import PlutusCore.Value qualified as V
1815import Safe.Foldable (maximumMay )
1916import Test.QuickCheck
2017import Test.Tasty
2118import Test.Tasty.QuickCheck
2219
20+ import PlutusCore.Builtin (BuiltinResult (.. ))
21+ import PlutusCore.Data (Data (.. ))
22+ import PlutusCore.Flat qualified as Flat
23+ import PlutusCore.Generators.QuickCheck.Builtin (ValueAmount (.. ), genShortHex )
24+ import PlutusCore.Value (Value )
25+ import PlutusCore.Value qualified as V
26+
2327prop_packUnpackRoundtrip :: Value -> Property
2428prop_packUnpackRoundtrip v = v === V. pack (V. unpack v)
2529
@@ -38,15 +42,15 @@ prop_insertCoinBookkeeping :: Value -> ValueAmount -> Property
3842prop_insertCoinBookkeeping v (ValueAmount amt) =
3943 forAll (genShortHex (V. totalSize v)) $ \ currency ->
4044 forAll (genShortHex (V. totalSize v)) $ \ token ->
41- let v' = V. insertCoin (V. unK currency) (V. unK token) amt v
45+ let BuiltinSuccess v' = V. insertCoin (V. unK currency) (V. unK token) amt v
4246 in checkSizes v'
4347
4448-- | Verifies that @insertCoin@ preserves @Value@ invariants
4549prop_insertCoinPreservesInvariants :: Value -> ValueAmount -> Property
4650prop_insertCoinPreservesInvariants v (ValueAmount amt) =
4751 forAll (genShortHex (V. totalSize v)) $ \ currency ->
4852 forAll (genShortHex (V. totalSize v)) $ \ token ->
49- let v' = V. insertCoin (V. unK currency) (V. unK token) amt v
53+ let BuiltinSuccess v' = V. insertCoin (V. unK currency) (V. unK token) amt v
5054 in checkInvariants v'
5155
5256prop_unionCommutative :: Value -> Value -> Property
@@ -60,15 +64,33 @@ prop_insertCoinIdempotent :: Value -> Property
6064prop_insertCoinIdempotent v =
6165 v
6266 === F. foldl'
63- (\ acc (c, t, a) -> let v' = V. insertCoin (V. unK c) (V. unK t) a acc in v')
67+ (\ acc (c, t, a) -> let BuiltinSuccess v' = V. insertCoin (V. unK c) (V. unK t) a acc in v')
6468 v
6569 (V. toFlatList v)
6670
71+ prop_insertCoinValidatesCurrency :: Value -> Property
72+ prop_insertCoinValidatesCurrency v =
73+ forAll gen33Bytes $ \ c ->
74+ forAll gen32BytesOrFewer $ \ t ->
75+ forAll (arbitrary `suchThat` (/= 0 )) $ \ amt ->
76+ case V. insertCoin c t amt v of
77+ BuiltinFailure {} -> property True
78+ _ -> property False
79+
80+ prop_insertCoinValidatesToken :: Value -> Property
81+ prop_insertCoinValidatesToken v =
82+ forAll gen32BytesOrFewer $ \ c ->
83+ forAll gen33Bytes $ \ t ->
84+ forAll (arbitrary `suchThat` (/= 0 )) $ \ amt ->
85+ case V. insertCoin c t amt v of
86+ BuiltinFailure {} -> property True
87+ _ -> property False
88+
6789prop_lookupAfterInsertion :: Value -> ValueAmount -> Property
6890prop_lookupAfterInsertion v (ValueAmount amt) =
6991 forAll (genShortHex (V. totalSize v)) $ \ currency ->
7092 forAll (genShortHex (V. totalSize v)) $ \ token ->
71- let v' = V. insertCoin (V. unK currency) (V. unK token) amt v
93+ let BuiltinSuccess v' = V. insertCoin (V. unK currency) (V. unK token) amt v
7294 in V. lookupCoin (V. unK currency) (V. unK token) v' === amt
7395
7496prop_lookupAfterDeletion :: Value -> Property
@@ -84,7 +106,7 @@ prop_deleteCoinIdempotent v0 =
84106 let v' = V. deleteCoin c t v
85107 in v' === V. deleteCoin c t v'
86108 where
87- v = if V. totalSize v0 > 0 then v0 else V. insertCoin " c" " t" 1 v0
109+ BuiltinSuccess v = if V. totalSize v0 > 0 then pure v0 else V. insertCoin " c" " t" 1 v0
88110 fl = V. toFlatList v
89111
90112prop_containsReflexive :: Value -> Property
@@ -113,7 +135,7 @@ prop_flatDecodeSuccess = forAll (arbitrary `suchThat` (/= 0)) $ \amt ->
113135 forAll gen32BytesOrFewer $ \ c ->
114136 forAll gen32BytesOrFewer $ \ t ->
115137 let flat = Flat. flat $ Map. singleton c (Map. singleton t amt)
116- v = V. insertCoin c t amt V. empty
138+ BuiltinSuccess v = V. insertCoin c t amt V. empty
117139 in Flat. unflat flat === Right v
118140
119141prop_flatDecodeInvalidCurrency :: Property
@@ -145,6 +167,24 @@ checkInvariants (V.unpack -> v) =
145167 property ((not . any Map. null ) v)
146168 .&&. property ((not . any (elem 0 )) v)
147169
170+ prop_unValueDataValidatesCurrency :: ValueAmount -> Property
171+ prop_unValueDataValidatesCurrency (ValueAmount amt) =
172+ forAll gen33Bytes $ \ c ->
173+ forAll gen32BytesOrFewer $ \ t ->
174+ let d = Map [(B c, Map [(B t, I amt)])]
175+ in case V. unValueData d of
176+ BuiltinFailure {} -> property True
177+ _ -> property False
178+
179+ prop_unValueDataValidatesToken :: ValueAmount -> Property
180+ prop_unValueDataValidatesToken (ValueAmount amt) =
181+ forAll gen32BytesOrFewer $ \ c ->
182+ forAll gen33Bytes $ \ t ->
183+ let d = Map [(B c, Map [(B t, I amt)])]
184+ in case V. unValueData d of
185+ BuiltinFailure {} -> property True
186+ _ -> property False
187+
148188tests :: TestTree
149189tests =
150190 testGroup
@@ -173,6 +213,12 @@ tests =
173213 , testProperty
174214 " insertCoinIdempotent"
175215 prop_insertCoinIdempotent
216+ , testProperty
217+ " insertCoinValidatesCurrency"
218+ prop_insertCoinValidatesCurrency
219+ , testProperty
220+ " insertCoinValidatesToken"
221+ prop_insertCoinValidatesToken
176222 , testProperty
177223 " lookupAfterInsertion"
178224 prop_lookupAfterInsertion
@@ -188,6 +234,12 @@ tests =
188234 , testProperty
189235 " containsAfterDeletion"
190236 prop_containsAfterDeletion
237+ , testProperty
238+ " unValueDataValidatesCurrency"
239+ prop_unValueDataValidatesCurrency
240+ , testProperty
241+ " unValueDataValidatesToken"
242+ prop_unValueDataValidatesToken
191243 , testProperty
192244 " flatRoundtrip"
193245 prop_flatRoundtrip
0 commit comments