Flezha.SDK.TaskletTestHarness (flezha_sdk v0.1.0)

Copy Markdown View Source

Run one tasklet as the dispatcher runs it, with no controller and no relay.

h = TaskletTestHarness.new(Counter)
{%{result: :ok, outputs: ["a=3"]}, h} = TaskletTestHarness.feed(h, "a:3")
assert TaskletTestHarness.state(h) == %{value: 3}
assert TaskletTestHarness.replay_equals(h) == :ok

Each call takes the harness and answers the next one beside what the invocation produced: a Flezha.SDK.TaskletTestHarness.Outcome. An invocation that fails changes nothing, as a live one is discarded.

now/1 is feed/3's now: when given, else what the declared clock reads: the input's event_time/1, the change count under logical_clock, 0 otherwise; inside a firing it is the scheduled time. The harness keeps the pending timers as one set per kind, as the core does; it does not judge them (the cap and the clock rule are the core's, when an item settles). An effect/4 name is judged by the core: an over-long one answers effect.bad_name; a well-formed one answers effect.outside_invocation, since keeping an outside call's result needs a live activation (Flezha.SDK.Local runs one).

Summary

Functions

Fire each pending event-time timer at or before to, earliest first; what a firing registers or cancels counts, as it does live.

Run run/3 against value. Options: now: (the clock's value for this input) and replay: true (the input is replayed).

Fire the kind timer scheduled at at, pending or not, through on_timer/3; a tasklet without it answers the non-retryable error a live firing parks with.

A harness for the tasklet module on one Cell. Options: cell_key: (default nil, a Single Cell) and state: (default init_state/1 of the key).

Fold every recorded change through apply_change/2 from the initial state: :ok when it rebuilds the live state, else {:mismatch, live, replayed}. A mismatch is an apply_change/2 that is not a pure fold, or a state changed without a recorded change.

The Cell's state, as the recorded invocations left it.

Types

t()

@type t() :: %Flezha.SDK.TaskletTestHarness{
  cell_key: term(),
  initial: term(),
  log: term(),
  module: term(),
  state: term(),
  timers: term()
}

Functions

advance_event_time(h, to)

@spec advance_event_time(t(), non_neg_integer()) ::
  {[Flezha.SDK.TaskletTestHarness.Outcome.t()], t()}

Fire each pending event-time timer at or before to, earliest first; what a firing registers or cancels counts, as it does live.

feed(h, value, opts \\ [])

@spec feed(t(), term(), keyword()) :: {Flezha.SDK.TaskletTestHarness.Outcome.t(), t()}

Run run/3 against value. Options: now: (the clock's value for this input) and replay: true (the input is replayed).

fire_timer(h, kind, at)

Fire the kind timer scheduled at at, pending or not, through on_timer/3; a tasklet without it answers the non-retryable error a live firing parks with.

new(module, opts \\ [])

@spec new(module(), keyword()) :: t()

A harness for the tasklet module on one Cell. Options: cell_key: (default nil, a Single Cell) and state: (default init_state/1 of the key).

replay_equals(h)

@spec replay_equals(t()) :: :ok | {:mismatch, term(), term()}

Fold every recorded change through apply_change/2 from the initial state: :ok when it rebuilds the live state, else {:mismatch, live, replayed}. A mismatch is an apply_change/2 that is not a pure fold, or a state changed without a recorded change.

state(tasklet_test_harness)

@spec state(t()) :: term()

The Cell's state, as the recorded invocations left it.