233 lines
6.3 KiB
Haskell
233 lines
6.3 KiB
Haskell
{- |
|
|
Module : Test.Util
|
|
Maintainer : emi@haskell.fyi
|
|
Description: Utility functions for testing Plutarch scripts with ScriptContext
|
|
|
|
Utility functions for testing Plutarch scripts with ScriptContext:
|
|
|
|
- 'policySucceedsWith': checks that a minting policy succeeds.
|
|
|
|
- 'policyFailsWith': checks that a minting policy fails.
|
|
|
|
- 'validatorSucceedsWith': checks that validator succeeds.
|
|
|
|
- 'validatorFailsWith': checks that validator fails.
|
|
|
|
- 'effectSucceedsWith': checks that effect succeeds.
|
|
|
|
- 'effectFailsWith': checks that effect fails.
|
|
|
|
- 'scriptSucceeds': checks that an arbitrary script does not
|
|
`perror`.
|
|
|
|
- 'scriptFails': checks that an arbitrary script `perror`s out.
|
|
-}
|
|
module Test.Util (
|
|
-- * Testing utils
|
|
scriptSucceeds,
|
|
scriptFails,
|
|
policySucceedsWith,
|
|
policyFailsWith,
|
|
validatorSucceedsWith,
|
|
validatorFailsWith,
|
|
effectSucceedsWith,
|
|
effectFailsWith,
|
|
|
|
-- * Plutus-land utils
|
|
datumHash,
|
|
toDatum,
|
|
toDatumHash,
|
|
datumPair,
|
|
) where
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
import Prelude
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
import Codec.Serialise (serialise)
|
|
import Data.ByteString.Lazy qualified as ByteString.Lazy
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
import Test.Tasty (TestTree)
|
|
import Test.Tasty.HUnit (assertFailure, testCase)
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
import Plutarch.Api.V1 (PMintingPolicy, PValidator)
|
|
import Plutarch.Builtin (pforgetData)
|
|
import Plutarch.Crypto (pblake2b_256)
|
|
import Plutarch.Evaluate (evalScript)
|
|
import Plutarch.Lift (PUnsafeLiftDecl (PLifted))
|
|
import Plutus.V1.Ledger.Contexts (ScriptContext)
|
|
import Plutus.V1.Ledger.Scripts (Datum (Datum), DatumHash (DatumHash), Script)
|
|
import PlutusTx.Builtins qualified as PlutusTx
|
|
import PlutusTx.IsData qualified as PlutusTx
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
-- | Check that a policy script succeeds, given a name and arguments.
|
|
policySucceedsWith ::
|
|
( PLift redeemer
|
|
, PlutusTx.ToData (PLifted redeemer)
|
|
) =>
|
|
String ->
|
|
ClosedTerm PMintingPolicy ->
|
|
PLifted redeemer ->
|
|
ScriptContext ->
|
|
TestTree
|
|
policySucceedsWith tag policy redeemer scriptContext =
|
|
scriptSucceeds tag $
|
|
compile
|
|
( policy
|
|
# pforgetData (pconstantData redeemer)
|
|
# pconstant scriptContext
|
|
)
|
|
|
|
-- | Check that a policy script fails, given a name and arguments.
|
|
policyFailsWith ::
|
|
( PLift redeemer
|
|
, PlutusTx.ToData (PLifted redeemer)
|
|
) =>
|
|
String ->
|
|
ClosedTerm PMintingPolicy ->
|
|
PLifted redeemer ->
|
|
ScriptContext ->
|
|
TestTree
|
|
policyFailsWith tag policy redeemer scriptContext =
|
|
scriptFails tag $
|
|
compile
|
|
( policy
|
|
# pforgetData (pconstantData redeemer)
|
|
# pconstant scriptContext
|
|
)
|
|
|
|
-- | Check that a validator script succeeds, given a name and arguments.
|
|
validatorSucceedsWith ::
|
|
( PLift datum
|
|
, PlutusTx.ToData (PLifted datum)
|
|
, PLift redeemer
|
|
, PlutusTx.ToData (PLifted redeemer)
|
|
) =>
|
|
String ->
|
|
ClosedTerm PValidator ->
|
|
PLifted datum ->
|
|
PLifted redeemer ->
|
|
ScriptContext ->
|
|
TestTree
|
|
validatorSucceedsWith tag validator datum redeemer scriptContext =
|
|
scriptSucceeds tag $
|
|
compile
|
|
( validator
|
|
# pforgetData (pconstantData datum)
|
|
# pforgetData (pconstantData redeemer)
|
|
# pconstant scriptContext
|
|
)
|
|
|
|
-- | Check that a validator script fails, given a name and arguments.
|
|
validatorFailsWith ::
|
|
( PLift datum
|
|
, PlutusTx.ToData (PLifted datum)
|
|
, PLift redeemer
|
|
, PlutusTx.ToData (PLifted redeemer)
|
|
) =>
|
|
String ->
|
|
ClosedTerm PValidator ->
|
|
PLifted datum ->
|
|
PLifted redeemer ->
|
|
ScriptContext ->
|
|
TestTree
|
|
validatorFailsWith tag validator datum redeemer scriptContext =
|
|
scriptFails tag $
|
|
compile
|
|
( validator
|
|
# pforgetData (pconstantData datum)
|
|
# pforgetData (pconstantData redeemer)
|
|
# pconstant scriptContext
|
|
)
|
|
|
|
{- | Check that a validator script succeeds, given a name and arguments.
|
|
TODO: Change docstring.
|
|
-}
|
|
effectSucceedsWith ::
|
|
( PLift datum
|
|
, PlutusTx.ToData (PLifted datum)
|
|
) =>
|
|
String ->
|
|
ClosedTerm PValidator ->
|
|
PLifted datum ->
|
|
ScriptContext ->
|
|
TestTree
|
|
effectSucceedsWith tag eff datum = validatorSucceedsWith tag eff datum ()
|
|
|
|
-- TODO: Change docstring.
|
|
|
|
{- | Check that a validator script fails, given a name and arguments.
|
|
TODO: Change docstring.
|
|
-}
|
|
effectFailsWith ::
|
|
( PLift datum
|
|
, PlutusTx.ToData (PLifted datum)
|
|
) =>
|
|
String ->
|
|
ClosedTerm PValidator ->
|
|
PLifted datum ->
|
|
ScriptContext ->
|
|
TestTree
|
|
effectFailsWith tag eff datum = validatorFailsWith tag eff datum ()
|
|
|
|
-- | Check that an arbitrary script doesn't error when evaluated, given a name.
|
|
scriptSucceeds :: String -> Script -> TestTree
|
|
scriptSucceeds name script = testCase name $ do
|
|
let (res, _budget, traces) = evalScript script
|
|
case res of
|
|
Left e -> do
|
|
assertFailure $
|
|
show e <> " Traces: " <> show traces
|
|
Right _v ->
|
|
pure ()
|
|
|
|
-- | Check that an arbitrary script **does** error when evaluated, given a name.
|
|
scriptFails :: String -> Script -> TestTree
|
|
scriptFails name script = testCase name $ do
|
|
let (res, _budget, traces) = evalScript script
|
|
case res of
|
|
Left _e ->
|
|
pure ()
|
|
Right v ->
|
|
assertFailure $
|
|
"Expected failure, but succeeded. " <> show v <> " Traces: " <> show traces
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
{- | Create a pair from data for use in 'txInfoData'.
|
|
|
|
Example:
|
|
@
|
|
myTxInfo { 'txInfoData' = ['datumPair' myDatum] }
|
|
@
|
|
-}
|
|
datumPair :: PlutusTx.ToData a => a -> (DatumHash, Datum)
|
|
datumPair = (,) <$> toDatumHash <*> toDatum
|
|
|
|
-- | Calculate the blake2b-256 hash of a Datum.
|
|
datumHash :: Datum -> DatumHash
|
|
datumHash (Datum data') = toDatumHash data'
|
|
|
|
-- | Convenience function to create a Datum from any type that implements ToData.
|
|
toDatum :: PlutusTx.ToData a => a -> Datum
|
|
toDatum = Datum . PlutusTx.toBuiltinData
|
|
|
|
{- | Calculate the blake2b-256 hash of any type that implements ToData
|
|
|
|
Shamelessly go through plutus.
|
|
-}
|
|
toDatumHash :: PlutusTx.ToData a => a -> DatumHash
|
|
toDatumHash datum =
|
|
DatumHash $
|
|
PlutusTx.toBuiltin $
|
|
plift $
|
|
pblake2b_256
|
|
# pconstant (ByteString.Lazy.toStrict $ serialise $ PlutusTx.toData datum)
|