caseweave

Deterministic constrained combinatorial test matrix generator for MoonBit.

testing
pairwise
covering-array
constraints
ci
moon add LF-ai-nb/caseweave@0.1.0
Download zip
Author
Version
0.1.0
License
MIT
Last updated
3 hours ago
Downloads
2
README

#CaseWeave

MoonBit package documentation lives in README.md.

#
CasePattern

pub(all) struct CasePattern {
choices : Array[NamedChoice]
} derive(Eq,
Debug
)

A partial assignment such as os=linux, browser=chrome.

#
CasePattern::matches

fn CasePattern::matches(self : CasePattern, model : Model, test_case : TestCase) -> Result[Bool, CaseWeaveError]

#
CasePattern::to_case

fn CasePattern::to_case(self : CasePattern, model : Model, line_no? : Int) -> Result[TestCase, CaseWeaveError]

#
CasePattern::to_exclusion_constraint

fn CasePattern::to_exclusion_constraint(self : CasePattern, label : String) -> Result[Constraint, CaseWeaveError]

#
CasePattern::to_text

fn CasePattern::to_text(self : CasePattern) -> String

#
CasePattern::validate

fn CasePattern::validate(self : CasePattern, model : Model) -> Result[Unit, CaseWeaveError]

#
CaseRisk

pub(all) struct CaseRisk {
score : Int
reasons : Array[String]
} derive(Eq,
Debug
)

Risk score for one concrete case.

#
CaseWeaveError

pub(all) enum CaseWeaveError {
EmptyModel
EmptyParameterName(Int)
DuplicateParameter(String)
EmptyValues(String)
EmptyValue(String, Int)
DuplicateValue(String, String)
InvalidStrength(Int, Int)
InvalidCandidateLimit(Int)
InvalidSuggestionLimit(Int)
CandidateLimitExceeded(Int)
NoValidCases
UncoverableInteraction
ParseError(Int, String)
UnknownParameter(String)
UnknownValue(String, String)
InvalidCaseWidth(Int, Int)
InvalidCaseValue(String, String)
ConstraintViolation(Int, String)
} derive(Eq,
Debug
)

Errors returned by model validation, constraint parsing, generation and coverage analysis. Public operations return Result so callers can report input problems without relying on panics.

#
Constraint

pub(all) struct Constraint {
label : String
expression : ConstraintExpr
} derive(Eq,
Debug
)

#
Constraint::matches

fn Constraint::matches(self : Constraint, model : Model, test_case : TestCase) -> Result[Bool, CaseWeaveError]

#
Constraint::new

fn Constraint::new(label : String, expression : ConstraintExpr) -> Constraint

#
Constraint::parse

fn Constraint::parse(label : String, source : String) -> Result[Constraint, CaseWeaveError]

#
Constraint::validate

fn Constraint::validate(self : Constraint, model : Model) -> Result[Unit, CaseWeaveError]

#
ConstraintExpr

pub(all) enum ConstraintExpr {
Equal(String, String)
NotEqual(String, String)
OneOf(String, Array[String])
NoneOf(String, Array[String])
And(ConstraintExpr, ConstraintExpr)
Or(ConstraintExpr, ConstraintExpr)
Implies(ConstraintExpr, ConstraintExpr)
Not(ConstraintExpr)
Always
Never
} derive(Eq,
Debug
)

Boolean constraint language used to exclude impossible or unwanted test combinations. Atoms address parameters and values by name, keeping models readable and independent from internal indexes.

#
CoverageReport

pub(all) struct CoverageReport {
strength : Int
case_count : Int
total_interactions : Int
covered_interactions : Int
coverage_percent : Double
missing : Array[MissingInteraction]
} derive(
Debug
)

Coverage audit for an arbitrary suite. Missing interactions are named so they can be printed directly in CI diagnostics.

#
CoverageReport::is_complete

fn CoverageReport::is_complete(self : CoverageReport) -> Bool

#
CoverageReport::missing_text

fn CoverageReport::missing_text(self : CoverageReport) -> String

Render missing interactions as readable lines.

#
CoverageReport::summary

fn CoverageReport::summary(self : CoverageReport) -> String

One-line coverage summary suitable for CI logs.

#
GateFailure

pub(all) struct GateFailure {
kind : GateFailureKind
message : String
} derive(Eq,
Debug
)

#
GateFailureKind

pub(all) enum GateFailureKind {
IncompleteCoverage(Int, Int)
TooManyMissingInteractions(Int, Int)
TooFewCases(Int, Int)
TooManyCases(Int, Int)
TopRiskTooLow(Int, Int)
TooFewPositiveRiskCases(Int, Int)
ScenarioWarnings(Int)
} derive(Eq,
Debug
)

#
GateReport

pub(all) struct GateReport {
passed : Bool
failures : Array[GateFailure]
warnings : Array[SpecWarning]
coverage : CoverageReport
case_count : Int
top_risk_score : Int
positive_risk_cases : Int
}

#
GateReport::failure_text

fn GateReport::failure_text(self : GateReport) -> String

#
GateReport::is_passed

fn GateReport::is_passed(self : GateReport) -> Bool

#
GateReport::summary

fn GateReport::summary(self : GateReport) -> String

#
GateReport::to_markdown

fn GateReport::to_markdown(self : GateReport) -> String

#
GateReport::warning_text

fn GateReport::warning_text(self : GateReport) -> String

#
GenerationOptions

pub(all) struct GenerationOptions {
strength : Int
max_candidates : Int
minimize : Bool
} derive(Eq,
Debug
)

Controls covering-array generation. max_candidates bounds the exhaustive candidate phase; constraints are evaluated during enumeration so invalid branches are pruned early.

#
GenerationOptions::default

#
GenerationOptions::pairwise

fn GenerationOptions::pairwise(max_candidates? : Int) -> GenerationOptions

#
GenerationStats

pub(all) struct GenerationStats {
cartesian_size : Int64
examined_candidates : Int
feasible_candidates : Int
required_interactions : Int
selected_cases : Int
removed_redundant_cases : Int
} derive(Eq,
Debug
)

#
InteractionRisk

pub(all) struct InteractionRisk {
pattern : CasePattern
weight : Int
note : String
} derive(Eq,
Debug
)

A risk attached to an interaction pattern.

#
MissingInteraction

pub(all) struct MissingInteraction {
choices : Array[NamedChoice]
} derive(Eq,
Debug
)

#
Model

pub struct Model {
parameters : Array[Parameter]
}

A validated ordered collection of parameters.

#
Model::combination_count

fn Model::combination_count(self : Model) -> Int64

#
Model::new

fn Model::new(parameters : Array[Parameter]) -> Result[Model, CaseWeaveError]

#
Model::parameter

fn Model::parameter(self : Model, index : Int) -> Parameter?

#
Model::parameter_count

fn Model::parameter_count(self : Model) -> Int

#
Model::parameter_index

fn Model::parameter_index(self : Model, name : String) -> Int?

#
Model::parameters

fn Model::parameters(self : Model) -> Array[Parameter]

#
Model::validate_case

fn Model::validate_case(self : Model, test_case : TestCase) -> Result[Unit, CaseWeaveError]

#
Model::value_index

fn Model::value_index(self : Model, parameter_index : Int, value : String) -> Int?

#
NamedChoice

pub(all) struct NamedChoice {
parameter : String
value : String
} derive(Eq,
Debug
)

#
Parameter

pub(all) struct Parameter {
name : String
values : Array[String]
} derive(Eq,
Debug
)

One dimension in the input space. Values are kept in declaration order so generation and exported output remain deterministic.

#
Parameter::new

fn Parameter::new(name : String, values : Array[String]) -> Parameter

#
RankedCase

pub(all) struct RankedCase {
rank : Int
index : Int
test_case : TestCase
score : Int
reasons : Array[String]
} derive(Eq,
Debug
)

A generated case ordered by descending risk score.

#
RepairGate

pub(all) struct RepairGate {
require_complete : Bool
max_additions : Int
max_final_missing : Int
min_largest_gain : Int
}

#
RepairGate::best_effort

fn RepairGate::best_effort(max_additions : Int, max_final_missing : Int) -> RepairGate

#
RepairGate::budget

fn RepairGate::budget(max_additions : Int) -> RepairGate

#
RepairGate::default

fn RepairGate::default() -> RepairGate

#
RepairGate::normalize

fn RepairGate::normalize(self : RepairGate) -> RepairGate

#
RepairGateFailure

pub(all) struct RepairGateFailure {
kind : RepairGateFailureKind
message : String
} derive(Eq,
Debug
)

#
RepairGateFailureKind

pub(all) enum RepairGateFailureKind {
RepairIncomplete(Int)
TooManyRepairAdditions(Int, Int)
TooManyRemainingInteractions(Int, Int)
LargestGainTooLow(Int, Int)
} derive(Eq,
Debug
)

#
RepairGateReport

pub(all) struct RepairGateReport {
passed : Bool
failures : Array[RepairGateFailure]
additions : Int
initial_missing : Int
final_missing : Int
largest_gain : Int
complete : Bool
}

#
RepairGateReport::failure_text

fn RepairGateReport::failure_text(self : RepairGateReport) -> String

#
RepairGateReport::is_passed

fn RepairGateReport::is_passed(self : RepairGateReport) -> Bool

#
RepairGateReport::summary

fn RepairGateReport::summary(self : RepairGateReport) -> String

#
RepairGateReport::to_markdown

fn RepairGateReport::to_markdown(self : RepairGateReport) -> String

#
RepairOptions

pub(all) struct RepairOptions {
strength : Int
max_candidates : Int
max_suggestions : Int
}

Options for repairing an incomplete suite. The planner uses the same interaction model as audit, then greedily proposes additional feasible cases that cover the largest number of currently missing interactions.

#
RepairOptions::default

fn RepairOptions::default() -> RepairOptions

#
RepairOptions::from_generation

fn RepairOptions::from_generation(options : GenerationOptions, max_suggestions? : Int) -> RepairOptions

#
RepairOptions::normalize

fn RepairOptions::normalize(self : RepairOptions) -> RepairOptions

#
RepairOptions::pairwise

fn RepairOptions::pairwise(max_candidates? : Int, max_suggestions? : Int) -> RepairOptions

#
RepairPlan

pub(all) struct RepairPlan {
model : Model
original_cases : Array[TestCase]
additions : Array[TestCase]
merged_cases : Array[TestCase]
original_report : CoverageReport
final_report : CoverageReport
steps : Array[RepairStep]
complete : Bool
initial_missing : Int
final_missing : Int
}

#
RepairPlan::addition_count

fn RepairPlan::addition_count(self : RepairPlan) -> Int

#
RepairPlan::additions

fn RepairPlan::additions(self : RepairPlan) -> Array[TestCase]

#
RepairPlan::additions_markdown

fn RepairPlan::additions_markdown(self : RepairPlan) -> String

#
RepairPlan::evaluate_repair_gate

fn RepairPlan::evaluate_repair_gate(self : RepairPlan, gate? : RepairGate) -> RepairGateReport

#
RepairPlan::highest_risk_step

fn RepairPlan::highest_risk_step(self : RepairPlan) -> RepairStep?

#
RepairPlan::is_complete

fn RepairPlan::is_complete(self : RepairPlan) -> Bool

#
RepairPlan::largest_gain_step

fn RepairPlan::largest_gain_step(self : RepairPlan) -> RepairStep?

#
RepairPlan::largest_repair_gain

fn RepairPlan::largest_repair_gain(self : RepairPlan) -> Int

#
RepairPlan::merged_cases

fn RepairPlan::merged_cases(self : RepairPlan) -> Array[TestCase]

#
RepairPlan::merged_markdown

fn RepairPlan::merged_markdown(self : RepairPlan) -> String

#
RepairPlan::missing_after_text

fn RepairPlan::missing_after_text(self : RepairPlan) -> String

#
RepairPlan::risk_summary

fn RepairPlan::risk_summary(self : RepairPlan) -> String

#
RepairPlan::steps

fn RepairPlan::steps(self : RepairPlan) -> Array[RepairStep]

#
RepairPlan::steps_markdown

fn RepairPlan::steps_markdown(self : RepairPlan, top? : Int) -> String

#
RepairPlan::summary

fn RepairPlan::summary(self : RepairPlan) -> String

#
RepairPlan::to_markdown

fn RepairPlan::to_markdown(self : RepairPlan) -> String

#
RepairStep

pub(all) struct RepairStep {
index : Int
test_case : TestCase
newly_covered : Array[MissingInteraction]
remaining_missing : Int
risk_score : Int
reasons : Array[String]
} derive(Eq,
Debug
)

#
ScenarioGate

pub(all) struct ScenarioGate {
require_complete_coverage : Bool
max_missing_interactions : Int
min_cases : Int
max_cases : Int
min_top_risk_score : Int
min_positive_risk_cases : Int
allow_warnings : Bool
}

CI-oriented policy for generated scenario runs. It turns coverage, risk and scenario-lint facts into a small pass/fail report that can be printed in a release job.

#
ScenarioGate::coverage_only

fn ScenarioGate::coverage_only() -> ScenarioGate

#
ScenarioGate::default

fn ScenarioGate::default() -> ScenarioGate

#
ScenarioGate::describe

fn ScenarioGate::describe(self : ScenarioGate) -> String

#
ScenarioGate::normalize

fn ScenarioGate::normalize(self : ScenarioGate) -> ScenarioGate

#
ScenarioGate::strict

fn ScenarioGate::strict() -> ScenarioGate

#
ScenarioGate::with_case_budget

fn ScenarioGate::with_case_budget(min_cases : Int, max_cases : Int) -> ScenarioGate

#
ScenarioGate::with_risk_floor

fn ScenarioGate::with_risk_floor(min_top_risk_score : Int, min_positive_risk_cases : Int) -> ScenarioGate

#
ScenarioRun

pub(all) struct ScenarioRun {
spec_name : String
model : Model
suite : Suite
cases : Array[TestCase]
included_case_count : Int
coverage : CoverageReport
ranked_cases : Array[RankedCase]
}

End-to-end execution result for a parsed scenario spec.

#
ScenarioRun::cases_markdown

fn ScenarioRun::cases_markdown(self : ScenarioRun) -> String

#
ScenarioRun::evaluate_gate

fn ScenarioRun::evaluate_gate(self : ScenarioRun, spec : ScenarioSpec, gate? : ScenarioGate) -> GateReport

#
ScenarioRun::evaluate_normalized_gate

fn ScenarioRun::evaluate_normalized_gate(self : ScenarioRun, spec : ScenarioSpec, gate : ScenarioGate) -> GateReport

#
ScenarioRun::positive_risk_case_count

fn ScenarioRun::positive_risk_case_count(self : ScenarioRun) -> Int

#
ScenarioRun::risk_markdown

fn ScenarioRun::risk_markdown(self : ScenarioRun, top? : Int) -> String

#
ScenarioRun::summary

fn ScenarioRun::summary(self : ScenarioRun) -> String

#
ScenarioRun::top_risk_score

fn ScenarioRun::top_risk_score(self : ScenarioRun) -> Int

#
ScenarioSpec

pub(all) struct ScenarioSpec {
name : String
model : Model
constraints : Array[Constraint]
options : GenerationOptions
included_cases : Array[TestCase]
excluded_patterns : Array[CasePattern]
value_risks : Array[ValueRisk]
interaction_risks : Array[InteractionRisk]
}

A compact, line-oriented scenario format for teams that want to keep their covering-array model beside design docs, issues or CI configuration.

#
ScenarioSpec::generate_suite

fn ScenarioSpec::generate_suite(self : ScenarioSpec) -> Result[Suite, CaseWeaveError]

#
ScenarioSpec::lint

#
ScenarioSpec::lint_text

fn ScenarioSpec::lint_text(self : ScenarioSpec) -> String

#
ScenarioSpec::parse

fn ScenarioSpec::parse(source : String) -> Result[ScenarioSpec, CaseWeaveError]

#
ScenarioSpec::plan_repair

fn ScenarioSpec::plan_repair(self : ScenarioSpec, cases : Array[TestCase], options? : RepairOptions) -> Result[RepairPlan, CaseWeaveError]

#
ScenarioSpec::rank_cases

fn ScenarioSpec::rank_cases(self : ScenarioSpec, cases : Array[TestCase]) -> Result[Array[RankedCase], CaseWeaveError]

#
ScenarioSpec::run

#
ScenarioSpec::score_case

fn ScenarioSpec::score_case(self : ScenarioSpec, test_case : TestCase) -> Result[CaseRisk, CaseWeaveError]

#
ScenarioSpec::summary

fn ScenarioSpec::summary(self : ScenarioSpec) -> String

#
SpecWarning

pub(all) struct SpecWarning {
kind : SpecWarningKind
message : String
} derive(Eq,
Debug
)

#
SpecWarningKind

pub(all) enum SpecWarningKind {
NoConstraints
NoRiskHints
NoIncludedCases
StrengthOne
CandidateLimitBelowCartesian(Int64, Int)
SingleValueParameter(String)
} derive(Eq,
Debug
)

Non-blocking quality hints for scenario specifications.

#
Suite

pub struct Suite {
cases : Array[TestCase]
strength : Int
stats : GenerationStats
}

Generated cases plus reproducibility and compression statistics.

#
Suite::cases

fn Suite::cases(self : Suite) -> Array[TestCase]

#
Suite::length

fn Suite::length(self : Suite) -> Int

#
Suite::stats

fn Suite::stats(self : Suite) -> GenerationStats

#
Suite::strength

fn Suite::strength(self : Suite) -> Int

#
Suite::summary

fn Suite::summary(self : Suite) -> String

One-line generation summary suitable for CLI output.

#
Suite::to_csv

fn Suite::to_csv(self : Suite, model : Model) -> String

Render a generated suite as CSV with a header row in model order.

#
Suite::to_json

fn Suite::to_json(self : Suite, model : Model) -> String

Render a generated suite as a compact JSON document.

#
Suite::to_markdown

fn Suite::to_markdown(self : Suite, model : Model) -> String

Render a generated suite as a Markdown table for READMEs and issue reports.

#
TestCase

pub(all) struct TestCase {
values : Array[String]
} derive(Eq,
Debug
)

A concrete test vector in model order.

#
TestCase::assignment_text

fn TestCase::assignment_text(self : TestCase, model : Model) -> String

#
TestCase::get

fn TestCase::get(self : TestCase, index : Int) -> String?

#
TestCase::new

fn TestCase::new(values : Array[String]) -> TestCase

#
TestCase::value_for

fn TestCase::value_for(self : TestCase, model : Model, parameter : String) -> String?

#
ValueRisk

pub(all) struct ValueRisk {
choice : NamedChoice
weight : Int
note : String
} derive(Eq,
Debug
)

A risk attached to one parameter value.

#
audit

fn audit(model : Model, cases : Array[TestCase], strength? : Int, constraints? : Array[Constraint], max_candidates? : Int) -> Result[CoverageReport, CaseWeaveError]

#
cases_to_csv

fn cases_to_csv(model : Model, cases : Array[TestCase]) -> String

Render arbitrary cases as CSV. This is useful when callers load a suite from another source and want the same escaping rules as generated suites.

#
cases_to_markdown

fn cases_to_markdown(model : Model, cases : Array[TestCase]) -> String

Render arbitrary cases as a Markdown table.

#
generate

fn generate(model : Model, constraints? : Array[Constraint], options? : GenerationOptions) -> Result[Suite, CaseWeaveError]

Generate a deterministic constrained covering array. Candidate order, greedy tie-breaking, and redundancy elimination are stable, so identical inputs always produce identical suites.

#
parse_scenario_spec

fn parse_scenario_spec(source : String) -> Result[ScenarioSpec, CaseWeaveError]

#
plan_repair

fn plan_repair(model : Model, cases : Array[TestCase], constraints? : Array[Constraint], options? : RepairOptions) -> Result[RepairPlan, CaseWeaveError]

#
version

let version : String

CaseWeave builds deterministic covering arrays for configuration-heavy software tests. The public API is split across the files in this package; this file intentionally keeps the package-level overview close to the generated interface.

Powered by MoonBit

Site sourceReport issuePackagesBuild queueSkillsStatistics

© 2026 mooncakes.io