soma.cell

E0054: test_machine_ambiguous

E0054 test_machine_ambiguous — a test rule calls transition() with several machines in scope.

A compile-time error of soma check, the checker of the Soma programming language (soma explain E0054).

The rule

A test rule calls transition(), get_status(), has_state() or valid_transitions() directly while the program has several state machines, so the call cannot tell which machine it means. At run time it would raise an error, which an assert_fails would then accept for the wrong reason. Call a handler of the cell that owns the machine instead, for example an order_status(id) handler that returns get_status(id).

A program that triggers it

wrong.cell

cell Orders {
    state order {
        initial: placed
        placed -> shipped
    }
    on ship(id: String) { transition(id, "shipped") }
    on order_status(id: String) { return get_status(id) }
}

cell Payments {
    state payment {
        initial: pending
        pending -> settled
    }
    on settle(id: String) { transition(id, "settled") }
}

cell test ShippingTests {
    rules {
        let _ = ship("o1")
        assert get_status("o1") == "shipped"
    }
}

What soma check prints:

$ soma check wrong.cell
error: a test rule calls transition() / get_status() directly, but the program has several state machines — it cannot tell which one (and `assert_fails` would pass on that error): call a handler of the cell that owns the machine, and write `assert_fails … matching "invalid_transition"`
  --> wrong.cell:21:9
   |
21 |         assert get_status("o1") == "shipped"
   |         ^
  = code: E0054
✗ 1 error(s), 0 warning(s).

The fix field of soma check --json: it cannot tell which one (and `assert_fails` would pass on that error): call a handler of the cell that owns the machine, and write `assert_fails … matching "invalid_transition"`

On line 21, assert get_status("o1") == "shipped" becomes assert order_status("o1") == "shipped".

wrong.cell → right.cell

--- wrong.cell
+++ right.cell
@@ -19,5 +19,5 @@
     rules {
         let _ = ship("o1")
-        assert get_status("o1") == "shipped"
+        assert order_status("o1") == "shipped"
     }
 }

With the fix, soma check accepts the program:

$ soma check right.cell
✓ All checks passed.