Catalyst milestone 3: Testing and documentation

Outputs

  • A test suite checking for correct mapping from schema data types to PlutusData encodings against a known-good corpus of such mappings (golden tests).

    • A dedicated lbt-plutus test suite was implemented for both Haskell and Purescript backends. They leverage both golden unit testing approach and randomized property based testing to assert the essential properties of the LambdaBuffers Plutus package:
      • Plutus.V1.PlutusData derivation tests
        • Golden unit tests: forall (golden : Days.Day.*.pd.json): (toJson . toPlutusData . fromPlutusData . fromJson) golden == golden
        • Property tests: forall (x : Foo.*): (fromPlutusData . toPlutusData) x == x
      • Plutus.V1.PlutusData instance tests
        • Golden unit tests: forall (golden : *.pd.json): (toJson . toPlutusData . fromPlutusData . fromJson) golden == golden
  • A test suite checking for roundtrip compatibility between codegened target environments.

    • A dedicated lbt-plutus test suite was implemented for both Haskell and Purescript backends.
    • A dedicated lbt-prelude test suite was implemented for both Haskell and Purescript backends.
    • Both include golden unit tests that provide assurances that these backends implement the LambdaBuffers packages in a mutually compatible manner.
  • A modular and contract-based test suite architecture streamlining codegen testing compliance for any of the supported typeclasses.

  • A document mapping the schema data types and typeclasses to their corresponding code-generated variants in the target environments.

Acceptance Criteria

  • The test suites are passing for the Haskell+PlutusTx codegen module.
    • CI targets:
      • checks.x86_64-linux."check-lbt-prelude-haskell:test:tests"
      • checks.x86_64-linux."check-lbt-plutus-haskell:test:tests"
  • The test suites are passing for the Purescript+CTL codegen module.
    • CI targets:
      • checks.x86_64-linux."purescript:lbt-plutus:check"
      • checks.x86_64-linux."purescript:lbt-prelude:check"
  • The “Mappings” document is made available in the project repository.

Evidence of Milestone Completion

References

Documentation strategy

Each typeclass receives a Specification document that closely explains the required semantics for LB types (sum/products/records).

Each backend receives a User documentation that elaborates on how the generated code is used.

Testing strategy

LambdaBuffers works with typeclasses, such as Eq, PlutusData and JSON. When a LB type has been declared with support for any of such typeclass, values of said types need to be handled in exactly the same manner as elaborated in the Specification for a given Typeclass in ALL support target language environments.

Concretely, if a type Foo has been declared with support for JSON, and toJson and fromJson methods have been generated for target languages, they have to be in correspondence.

module Foo

import Prelude (Json)

sum Foo = Bar Integer | Baz Text

deriving Json Foo

In Haskell and Purescript values of Foo would be Bar 1 and Baz "baz", and their respective JSON mappings would be {"constructor" : "Bar", "product" : [1]} and {"constructor" : "Baz", "product" : ["baz"]}.

Testing encoding typeclasses: from . to goldens

For each typeclass, we maintain a set of golden' files of known good/bad that lift into the target language withfromand write it back withto` into a separate file. Then we provide an assertion that these files are semantically 'equal' (for example JSON spaces don't matter and such).

Example test:

  • test/foo/Foo.lbf
  • test/foo/json/bar.1.json
  • test/foo/json/bar.2.json
  • test/foo/json/baz.1.json
  • test/foo/json/baz.2.json
  • test/foo/json/haskell/bar.1.json
  • test/foo/json/haskell/bar.2.json
  • test/foo/json/haskell/baz.1.json
  • test/foo/json/haskell/baz.2.json
  • test/foo/json/purescript/bar.1.json
  • test/foo/json/purescript/bar.2.json
  • test/foo/json/purescript/baz.1.json
  • test/foo/json/purescript/baz.2.json
  • test/foo/plutusdata/bar.1.json
  • test/foo/plutusdata/bar.2.json
  • test/foo/plutusdata/baz.1.json
  • test/foo/plutusdata/baz.2.json
  • test/foo/plutusdata/haskell/bar.1.json
  • test/foo/plutusdata/haskell/bar.2.json
  • test/foo/plutusdata/haskell/baz.1.json
  • test/foo/plutusdata/haskell/baz.2.json
  • test/foo/plutusdata/purescript/bar.1.json
  • test/foo/plutusdata/purescript/bar.2.json
  • test/foo/plutusdata/purescript/baz.1.json
  • test/foo/plutusdata/purescript/baz.2.json

Testing equality typeclasses: symmetry and transitivity

  • sym :: (a :~: b) -> b :~: a
  • trans :: (a :~: b) -> (b :~: c) -> a :~: c

This could be done with goldens and randomized testing. However, goldens approach assumes a correct marshaling procedure while the randomized assumes generators. Perhaps having both makes sense.

TODO (provide time estimates)

  1. Define the version 1 of Prelude and Plutus LBF libraries which MUST be supported
  2. Support the Json typeclass
    1. Codegen
    2. Runtime support
  3. Support the Plutarch backend
  4. Document typeclasses
    1. Eq
    2. PlutusData
    3. Json
  5. Document backends
    1. Sum/Product/Record type construction and deconstruction (Haskell, Purescript, Plutarch)
    2. Eq/Json/PlutusData typeclass use (Haskell, Purescript, Plutarch minus Json)
  6. Devise goldens
    1. Eq
    2. PlutusData
    3. Json
  7. Implement the test suite
    1. Provide assertions
    2. Hook to the CI