Runs a corpus case that carries a host object (ADR-0070 decision 5):
the host registers the case's send_types (ADR-0069), and the sends
handed to it must be the case's expect_sends.
Statifier.Testing.Case.test_scxml/4 starts its session with no
registration, so a host case runs here instead, through the same public
session API: Statifier.start_session/2 with :send_types naming
Mix.Statifier.Corpus.HostCase.Processor for every registered type,
Statifier.Session.send_event/2 for each step, and
Statifier.Session.status/1 and Statifier.Session.snapshot/1 to wait
for the chart to settle and read its active leaf states. The waiting
follows test_scxml/4's: a pending library timer is given a short window
to fire before the next event, and a configuration is read once the
session has had nothing queued and no timer pending on two consecutive
polls, or the chart has left the running status, or a deadline passed.
A case agrees when the active leaf states after initialization and after
every step are the ones it expects, and the sends handed to the processor
over the whole run, in order, are exactly its expect_sends. Each handed
send is written in the case's language-neutral item shape: type,
target, event with its name and, when the send carries a payload,
its data; delay_ms for a delayed send; and send_id only when the
author named the send, which is when the delivered event carries one.
A registered delayed send is the host's timer, and this host never fires
one.
A host object may also carry declared_events and expect_accepts,
present together or not at all (ADR-0071 decision 7). Before it starts the
session, the runner calls Statifier.Chart.check_accepts/2 on the compiled
chart with declared_events, and the case agrees only when both lists it
answers are exactly expect_accepts' unreachable and undeclared, order
included. Either key without the other is a disagreement.
A host object may carry a diff pair as well - to_source and
expect_diff, with an optional mapping and expect_compatible_at
(ADR-0072, conformance/schema/case.json) - and this runner compares
none of them: it runs such a case like any other host case. Nothing in
lib/ calls the chart diff or the position predicate (ADR-0072
decision 6), so the test suite compares those four keys
(test/corpus/diff_cases_test.exs), through run/2's :after_steps
option for the position the steps leave.
Summary
Functions
Runs one host case, returning :agree or {:disagree, message}.
Functions
@spec run( corpus_case :: map(), opts :: [ {:after_steps, (Statifier.MachineState.t() -> :ok | {:disagree, String.t()})} ] ) :: :agree | {:disagree, String.t()}
Runs one host case, returning :agree or {:disagree, message}.
opts takes :after_steps, a function the runner calls once, after the
last step's configuration agrees and before it compares the handed sends,
with the session's settled Statifier.MachineState; it answers :ok or
{:disagree, message}, and a disagreement is the case's. A case that
disagrees before the sends are compared leaves them in the calling
process's mailbox, so each run belongs in a process of its own, as
Mix.Statifier.Corpus.Runner.run/1 gives it.