ytxp-plutarch-0.1.0: Control scripts, types, and utilities for the YTxP architecture
Safe HaskellSafe-Inferred
LanguageHaskell2010

Cardano.TestUtils

Description

This module exposes a flexible way to generate test cases that go through a pre-processing -> pre-condition -> execution -> post-condition pipeline.

The intention is to provide an easier interface to re-using predicates and pre-processors between many tests and between different _kinds_ of tests, including nominal and attack cases, as well as unit and property testing.

This module is currently targeted primarily at tests run on the CEK machine. In the future, it may be expanded to be polymorphic in terms of arbitrary "computation". The current computation type is essentially hard-coded to

(Maybe Datum, Redeemer, ScriptContext, Script) -> (Either EvalError Script, ExBudget, Logs)

but this could be expanded so that other types of tests (emulator, integration, serialization, golden) could be run as well.

Synopsis

Polymorphic Types and Functions

PreProcessing

data PreProcessor err input Source #

PreProcessing -- could be used for normalization or attacks

Construction

mkPreProcessor :: (input -> Either err input) -> PreProcessor err input Source #

Elimination

preProcess :: [PreProcessor err input] -> input -> Either err input Source #

Given a list of preprocessors, apply them in order from left to right. Returns the first error encountered, if any.

PreCondition Checking

data PreCondition err input Source #

Checks for after the preprocessing is run. Could be used to check for balancing, etc

TODO: rewrite as Kleisli?

Construction

mkPreCondition :: (input -> Maybe err) -> PreCondition err input Source #

Elimination

checkPreConditions :: [PreCondition err input] -> input -> Maybe err Source #

Check a list of pre-conditions, returning the first error encountered

PostCondition Checking

data PostCondition err output Source #

Represents a partial post-condition predicate on the result of a call to `evalScript :: Script -> (Either EvalError Script, ExBudget, [Text]) ` TODO: Rewrite as Kleisli?

TODO: If its possible to turn budgeting off, we should. These scripts will be run with some logging output, and they wouldn't in production; thus costing is not actually representative of anything useful.

Construction

mkPostCondition :: (output -> Maybe err) -> PostCondition err output Source #

Elimination

checkPostConditions :: [PostCondition err output] -> output -> Maybe err Source #

Check a list of post-conditions from left to right, returning the first error encountered

Test Cases

data PipelinedTestCase errPP errPreC errPostC input output Source #

A type representing a named test case for a transaction family. NOTE: if the `sc-tools` work ends up panning out, the args and script arguments might get combined to a (Maybe Datum, Redeemer, ScriptContext, Script)

Constructors

PipelinedTestCase 

Fields

data PipelinedTestErrors errPP errPreC errPostC Source #

A sum type to collect the errors of a pipelined test case

pipelinedUnitCase :: (Show errPP, Show errPreC, Show errPostC) => PipelinedTestCase errPP errPreC errPostC input output -> TestTree Source #

Behavior of this function:

  • 1.) All pre-processors are run in order from left to right on the arguments. If any pre-processor returns a Left, then the resulting test case fails with the appropriate error message.
  • 2.) All pre-condition checks are run on the pre-processed arguments. If any pre-condition checks return Nothing, then the resulting test case fails with the appropriate error meesage.
  • 3.) The pre-processed arguments are fed to the script.
  • 4.) The results of (3) are checked against each post-condition. If any of the post-condition checks fail, the test case fails with the appropriate error message
  • 5.) If none of the above checks cause a failure, the test succeeds.

TxFCEKMachinery

Generic TxF TestCase

data TxFCEKCase errPP errPreC errPostC Source #

A sum type of the errors for a TxFCEKCase

data TxFCEKInput Source #

The arguments needed to run a YTxP-style transaction family (single script) on the CEK Machine. Includes a datum (for validators only), a redeemer, script context, and the script itself.

Constructors

TxFCEKInput 

Fields

Instances

Instances details
Show TxFCEKInput Source # 
Instance details

Defined in Cardano.TestUtils

Eq TxFCEKInput Source # 
Instance details

Defined in Cardano.TestUtils

data TxFCEKOutput Source #

The data produced by the CEK machine when run against a TxFCEKInput.

Constructors

TxFCEKOutput 

Fields

Instances

Instances details
Show TxFCEKOutput Source # 
Instance details

Defined in Cardano.TestUtils

Eq TxFCEKOutput Source # 
Instance details

Defined in Cardano.TestUtils

mkTxFCEKCase Source #

Arguments

:: forall (errPP :: Type) (errPreC :: Type) (errPostC :: Type). String

Name of the test case

-> [PreProcessor errPP TxFCEKInput]

List of pre-processors over something like (Maybe Datum, Redeemer, ScriptContext, Script)

-> [PreCondition errPreC TxFCEKInput]

List of pre-condition checks over something like (Maybe Datum, Redeemer, ScriptContext, Script)

-> TxFCEKInput

Something like (Maybe Datum, Redeemer, ScriptContext, Script)

-> [PostCondition errPostC TxFCEKOutput]

Post-conditions over something like (Either EvalError Script, ExBudget, [Text])

-> TxFCEKCase errPP errPreC errPostC 

Create a TxFCEKCase by filling in the computation via running the script.

txfCEKUnitCase :: forall (errPP :: Type) (errPreC :: Type) (errPostC :: Type). (Show errPP, Show errPreC, Show errPostC) => TxFCEKCase errPP errPreC errPostC -> TestTree Source #

Nominal Tests

nominalPostCondition :: ((EvalError, [Text]) -> err) -> PostCondition err TxFCEKOutput Source #

A post condition for checking whether the script execution succeeded or failed You must supply a way to turn a generic evaluation error into your domain-specific error type

nominalCaseBasic Source #

Arguments

:: String

Name of the test case

-> Maybe Datum

Datum to apply to the script. Set this to Nothing unless you are testing a validator

-> Redeemer

Redeemer

-> ScriptContext

Nominal context to apply Nominal

-> Script

Nominal to apply

-> TxFCEKCase String String String 

A basic nominal case unit test. Only checks if the script succeeds; does not do pre-processing, pre-condition checking, or other post-condition checks.

Throws a generic String error (not domain-specific)

Attack Tests

attackCaseRegexPostCondition Source #

Arguments

:: ((Maybe Int, [Text]) -> err)

A way to go from the number of matches (if unequal to 1) and the logs to a domain-specific error

-> RE

The regular expression to match against. It must match exactly once for the post-condition check to pass

-> PostCondition err TxFCEKOutput 

The attackCaseRegex-style functions will fail with - A (Nothing, [Text]) if the script succeeds. [Text] in the tuple contains the logs. - A (Just Int, [Text]) if the script fails, but the regex does not match exactly once. The int contains the number of matches

attackCaseBasicRegex Source #

Arguments

:: String

Name of the test case

-> RE

Expected Failure String Match; TODO: This can be improved. Maybe use a discriminated error sum type with a injective string mapping?

-> Maybe Datum

Datum to apply to the script. Set this to Nothing unless you are testing a validator

-> Redeemer

Redeemer

-> ScriptContext

Nominal context to apply attack

-> Script

The script to execute

-> PreProcessor errPP TxFCEKInput

Attack to apply

-> TxFCEKCase errPP String String 

Generate an "attack case" test tree, given a name, an expected failure condition, the arguments to the script, an attack, and the script itself.

The expected failure condition is matched as a regex. It must match the logs exactly once.