metamon

Metamon top-level public API.

metamon exports the small surface that most tests interact with: forall, forall_morph, assert_morph, forall_morphs, the Mr smart constructors, and a handful of metamorphic-relation templates (idempotency_of, round_trip_with, invariant_under, equivariant_under).

Configuration lives in metamon/config; generators in metamon/generator; transforms in metamon/transform; relations in metamon/relation; per-property context in metamon/annotate and metamon/coverage; structural diff in metamon/diff.

Types

Re-export of Config so callers can write metamon.Config.

pub type Config =
  config.Config

Mr

opaque </>

A named metamorphic relation. Construct via mr (the Plain form, f(T(x)) ≈ f(x)) or mr_equivariant (the Equivariant form, f(T(x)) ≈ U(f(x))).

Opaque on purpose: future versions may add fields without breaking callers that always go through the smart constructors.

pub opaque type Mr(a, b)

Re-export of OutputFormat so callers can write metamon.OutputFormat.

pub type OutputFormat =
  config.OutputFormat

Re-export of the seed type so callers can write metamon.Seed.

pub type Seed =
  seed.Seed

Values

pub fn assert_morph(input: a, m: Mr(a, b), f: fn(a) -> b) -> Nil

Run a metamorphic relation against a single input. Generator-free.

pub fn commutativity_of(
  name name: String,
  of op: fn(a, a) -> b,
) -> Mr(#(a, a), b)

op(a, b) == op(b, a)op is commutative.

The MR is over the input pair #(a, a) and the output type b. Use it as:

let mr = metamon.commutativity_of(name: "add_commutative", of: add)
metamon.forall_morph(
  generator.tuple2(int_gen, int_gen),
  mr,
  fn(pair) { add(pair.0, pair.1) },
)
pub fn default_config() -> config.Config

Re-export of Config and default_config.

pub fn equivariant_under(
  name name: String,
  input input_transform: transform.Transform(a),
  output output_transform: transform.Transform(b),
  relation rel: relation.Relation(b),
) -> Mr(a, b)

R(U(f(x)), f(T(x))). Equivariance: the input transform T and the output transform U commute with f modulo R.

pub fn forall(
  g: generator.Generator(a),
  property: fn(a) -> Bool,
) -> Nil

Run a property over many random inputs.

pub fn forall_morph(
  g: generator.Generator(a),
  m: Mr(a, b),
  f: fn(a) -> b,
) -> Nil

Run a metamorphic relation over many random inputs.

pub fn forall_morph_n(
  g: generator.Generator(a),
  transforms: List(transform.Transform(a)),
  rel: relation.RelationN(b),
  f: fn(a) -> b,
) -> Nil

Run an N-ary metamorphic relation: apply each of transforms to the source input to build follow-up inputs, then assert that the resulting outputs [f(x), f(T0(x)), ..., f(Tn(x))] satisfy relation. Useful when the property requires comparing more than two outputs in one shot (e.g. (a, b, c) ↦ op(op(a,b), c) and its re-associations all agree).

pub fn forall_morph_n_with(
  cfg: config.Config,
  g: generator.Generator(a),
  transforms: List(transform.Transform(a)),
  rel: relation.RelationN(b),
  f: fn(a) -> b,
) -> Nil

forall_morph_n with an explicit configuration.

pub fn forall_morph_with(
  cfg: config.Config,
  g: generator.Generator(a),
  m: Mr(a, b),
  f: fn(a) -> b,
) -> Nil

Run a metamorphic relation with an explicit configuration.

pub fn forall_morphs(
  g: generator.Generator(a),
  ms: List(Mr(a, b)),
  f: fn(a) -> b,
) -> Nil

Run multiple metamorphic relations against the same generator. Each MR is tried independently; failures are collected and reported together at the end.

pub fn forall_with(
  cfg: config.Config,
  g: generator.Generator(a),
  property: fn(a) -> Bool,
) -> Nil

Run a property with an explicit configuration.

pub fn idempotency_of(
  name name: String,
  of f: fn(a) -> a,
) -> Mr(a, a)

f(f(x)) == f(x). Idempotency.

Encoded as a Plain MR whose transform is f itself and whose relation is structural equality.

pub fn invariant_under(
  name name: String,
  under under: transform.Transform(a),
) -> Mr(a, b)

f(T(x)) == f(x)f is invariant under the input transform.

pub fn mr(
  name name: String,
  transform transform: transform.Transform(a),
  relation relation: relation.Relation(b),
) -> Mr(a, b)

Construct a Plain MR. The relation is checked between f(source_input) and f(transform.apply(source_input)).

pub fn mr_equivariant(
  name name: String,
  input input_transform: transform.Transform(a),
  output output_transform: transform.Transform(b),
  relation relation: relation.Relation(b),
) -> Mr(a, b)

Construct an Equivariant MR. The relation is checked between output_transform.apply(f(source_input)) and f(input_transform.apply(source_input)).

pub fn name_of(m: Mr(a, b)) -> String

Get the user-facing name of an MR.

pub fn random_seed() -> seed.Seed

Convenience: a fresh random seed.

pub fn seed(value: Int) -> seed.Seed

Construct a deterministic seed from an integer.

pub fn with_diff_enabled(
  c: config.Config,
  enabled: Bool,
) -> config.Config

Re-export of with_diff_enabled.

pub fn with_max_edges(
  c: config.Config,
  n: Int,
) -> Result(config.Config, config.ConfigError)

Re-export of with_max_edges.

pub fn with_max_size(
  c: config.Config,
  n: Int,
) -> Result(config.Config, config.ConfigError)

Re-export of with_max_size.

pub fn with_output_format(
  c: config.Config,
  fmt: config.OutputFormat,
) -> config.Config

Choose the failure-report output format. Text (default) is human-friendly; Json is single-line JSON for CI / LLM consumers.

pub fn with_regression_file(
  c: config.Config,
  path: String,
) -> Result(config.Config, config.ConfigError)

Re-export of with_regression_file.

pub fn with_runs(
  c: config.Config,
  n: Int,
) -> Result(config.Config, config.ConfigError)

Re-export of with_runs.

pub fn with_seed(c: config.Config, s: seed.Seed) -> config.Config

Re-export of with_seed.

pub fn with_shrink_limit(
  c: config.Config,
  n: Int,
) -> Result(config.Config, config.ConfigError)

Re-export of with_shrink_limit.

Search Document