diff --git a/changelog.d/sp-b3y4.md b/changelog.d/sp-b3y4.md new file mode 100644 index 0000000..86a268f --- /dev/null +++ b/changelog.d/sp-b3y4.md @@ -0,0 +1,3 @@ +### Changed + +- `StatifierPersistence.Testing.StorageConformance` defines every attribute, function and nested module it puts into a host test module under one reserved prefix, `conformance_` (`Conformance` for a nested module), and its moduledoc states that prefix as the host contract, so a host module's own helpers no longer collide with the suite's; a host test module that called one of the suite's helpers by its old name (`input_log_execution/2`, for one) adds the prefix, and the telemetry handler `__conformance_forward_adapter_call__/4` is now `conformance_forward_adapter_call/4`. diff --git a/docs/adr/0003-storage-adapter-behaviour-and-the-identity-guard.md b/docs/adr/0003-storage-adapter-behaviour-and-the-identity-guard.md index 191a452..e47c2d1 100644 --- a/docs/adr/0003-storage-adapter-behaviour-and-the-identity-guard.md +++ b/docs/adr/0003-storage-adapter-behaviour-and-the-identity-guard.md @@ -154,3 +154,59 @@ as a new decision.)* host-retained SCXML source for `chart_blob`, and does not need to: the guard, the keys, and the error vocabulary above hold regardless of which a host picks. + +## Amendment (2026-09-29): every name the conformance suite defines in a host module carries one reserved prefix + +Status of this amendment: proposed (2026-09-29). The record above is +accepted; this amendment does not change its status line. + +Decision 5 ships the conformance suite as a test-case template that a +host module `use`s. What the `use` defines in that module was not part +of the record: module attributes, private helper functions, one public +function and nested modules, a few under a `conformance` prefix and most +under plain names a host test module could already be using. A host +that used one of them collided with the suite: a `def` of the same name +and arity as the suite's `defp` does not compile, a second clause of a +private function is never reached, a nested module is redefined, and an +attribute set above the `use` is overwritten below it. This amendment +makes the names part of decision 5's contract. Ruled by the operator, +2026-09-29. The cites in `lib/` and `test/` are to the change that +carries this amendment; every other cite was read on `main` at +`c720da0`. + +**One reserved prefix.** Every name the template's `using` block +defines in the host module starts with `conformance`: module attributes +and functions, private and public, with `conformance_`, and nested +modules with `Conformance` +(`lib/statifier_persistence/testing/storage_conformance.ex`, the `using` +block). The spelling is the one the suite's attributes already carried. +The one public function, the telemetry handler one case attaches, was +spelled with a leading double underscore; it is now +`conformance_forward_adapter_call/4`, so a single spelling covers every +kind of name. + +**The prefix is the host's contract.** The suite's moduledoc states it: +the names under the prefix are the suite's, a host module that defines +an attribute, a function or a nested module under it collides with the +suite and that collision is the host's to fix, and every other +attribute, function and nested module name is the host's. The generated +tests' names, each starting `adapter:` or `facade:`, are named there +too. `test/statifier_persistence/storage/reserved_prefix_conformance_test.exs` +holds the contract: a host module that keeps an attribute, a nested +module and a private function under names the suite once defined +without the prefix, and runs the suite's own cases beside them. + +**The aliases are named, not removed.** The template also writes six +aliases into the host module. An alias holds to the end of the module, +so a host alias above the `use` with one of the same last names is +replaced below it. They stay, and the moduledoc names all six and the +two ways around them: alias below the `use`, or under a name of the +host's own with `as:`. Removing them would spell every module in the +template in full for no change in what a host can do. + +**A host that called a helper by its old name must rename the call.** +The template defines its helpers inside the host module, so a host test +module could call them, and one in this repository did +(`test/statifier_persistence/storage/setup_ordering_conformance_test.exs`). +Such a call no longer compiles until it carries the prefix. Nothing a +generated case asserts changes. diff --git a/lib/statifier_persistence/testing/storage_conformance.ex b/lib/statifier_persistence/testing/storage_conformance.ex index 1cfa6c8..0173b83 100644 --- a/lib/statifier_persistence/testing/storage_conformance.ex +++ b/lib/statifier_persistence/testing/storage_conformance.ex @@ -57,6 +57,30 @@ defmodule StatifierPersistence.Testing.StorageConformance do `context.store` is already open, and already isolated, by the time it is called. + Beyond that `setup`, the `use` defines names of its own in your module, + and every one of them carries one reserved prefix, `conformance`: the + module attributes and the private helper functions start with + `conformance_` (`@conformance_adapter`, `conformance_retirement/1`), so + does the one public function (`conformance_forward_adapter_call/4`, the + telemetry handler one case attaches), and the nested modules start with + `Conformance` (`ConformanceReentrantSerialization` under your module). + Those names are the suite's. A host module that defines an attribute, a + function or a nested module under the prefix collides with the suite, + and that collision is the host's to fix: the prefix is the contract, and + every other attribute, function and nested module name is yours. The + generated tests are named too, each starting `adapter:` or `facade:`; a + host test with one of those names collides as well. + + The `use` also writes six aliases into your module, and an alias holds + from where it is written to the end of the module: `Statifier.Machine`, + `Statifier.Machine.Identity`, `StatifierPersistence.Execution.Linkage`, + `StatifierPersistence.Migration.Plan`, `StatifierPersistence.Storage` + and `StatifierPersistence.Testing.Charts`. Below the `use`, `Machine`, + `Identity`, `Linkage`, `Plan`, `Storage` and `Charts` name those + modules, whatever an alias above the `use` said. A host that means + another module by one of those names aliases it below the `use`, or + under a name of its own with `as:`. + The optional execution `metadata` map (ADR-0006) is treated differently again: its cases are generated for every adapter and assert the answer this adapter gives - a round trip when it declares support through @@ -149,10 +173,13 @@ defmodule StatifierPersistence.Testing.StorageConformance do # Every chart hash a generated case retires is this host module's # own. On Postgres a retirement takes the hash's advisory lock - # exclusive, the tombstone read takes it shared, and the key is - # database-wide: no table, prefix or schema is in it. Cases in one - # module run one at a time, but two async modules running this - # suite against one database run the same case at once, each in a + # exclusive, the tombstone read takes it shared, and the key is per + # store: it hashes the charts table under its prefix with the hash. + # Two host modules that name one charts table the same way - the + # same table under the same prefix, or the same table name with no + # prefix, whatever schema it resolves to - share that key. Cases in + # one module run one at a time, but two async modules running this + # suite against one such table run the same case at once, each in a # sandbox transaction that lasts the whole test; with one shared # hash, a case that reads a tombstone and then retires the hash # upgrades its shared lock while the other module's copy holds @@ -862,9 +889,26 @@ defmodule StatifierPersistence.Testing.StorageConformance do # InMemory, "40 tests, 1 failure" over Ecto). Reverted from a # copy. test "adapter: two charts' executions never count into each other", %{store: store} do - insert_counted_execution(store, "counts-a-active", "sha256:counts-a", :active) - insert_counted_execution(store, "counts-b-active", "sha256:counts-b", :active) - insert_counted_execution(store, "counts-b-done", "sha256:counts-b", :completed) + conformance_insert_counted_execution( + store, + "counts-a-active", + "sha256:counts-a", + :active + ) + + conformance_insert_counted_execution( + store, + "counts-b-active", + "sha256:counts-b", + :active + ) + + conformance_insert_counted_execution( + store, + "counts-b-done", + "sha256:counts-b", + :completed + ) assert {:ok, a} = @conformance_adapter.count_executions_by_content_hash( @@ -895,7 +939,12 @@ defmodule StatifierPersistence.Testing.StorageConformance do test "adapter: an execution that completes moves from the active key to the completed one", %{store: store} do inserted = - insert_counted_execution(store, "counts-moving", "sha256:counts-moving", :active) + conformance_insert_counted_execution( + store, + "counts-moving", + "sha256:counts-moving", + :active + ) assert {:ok, %{active: 1, completed: 0}} = @conformance_adapter.count_executions_by_content_hash( @@ -929,7 +978,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do test "adapter: a parked execution round-trips and counts under needs_migration, never under active", %{store: store} do inserted = - insert_counted_execution( + conformance_insert_counted_execution( store, "hold-parked", "sha256:counts-parked-hold", @@ -939,7 +988,12 @@ defmodule StatifierPersistence.Testing.StorageConformance do assert {:ok, ^inserted} = @conformance_adapter.fetch_execution(store.opts, "hold-parked") - insert_counted_execution(store, "hold-waiting", "sha256:counts-parked-hold", :active) + conformance_insert_counted_execution( + store, + "hold-waiting", + "sha256:counts-parked-hold", + :active + ) assert {:ok, counts} = @conformance_adapter.count_executions_by_content_hash( @@ -989,7 +1043,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do test "adapter: a parent's two durable children count on the child chart, and stop counting when the parent leaves the active arm", %{store: store} do parent = - insert_counted_execution( + conformance_insert_counted_execution( store, "counts-pin-parent", "sha256:counts-pin-parent", @@ -997,7 +1051,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do ) for index <- 0..1 do - insert_pinned_child( + conformance_insert_pinned_child( store, "counts-pin-parent/call/#{index}", "sha256:counts-pin-child", @@ -1049,14 +1103,14 @@ defmodule StatifierPersistence.Testing.StorageConformance do # tests, 6 failures"): this case on both adapters, and four # more the inversion also breaks. Reverted from the copies. test "adapter: a terminal child of an active parent still counts", %{store: store} do - insert_counted_execution( + conformance_insert_counted_execution( store, "counts-terminal-parent", "sha256:counts-terminal-parent", :active ) - insert_pinned_child( + conformance_insert_pinned_child( store, "counts-terminal-parent/call/0", "sha256:counts-terminal-child", @@ -1088,14 +1142,14 @@ defmodule StatifierPersistence.Testing.StorageConformance do store: store } do parent = - insert_counted_execution( + conformance_insert_counted_execution( store, "counts-parked-parent", "sha256:counts-parked-parent", :needs_migration ) - insert_pinned_child( + conformance_insert_pinned_child( store, "counts-parked-parent/call/0", "sha256:counts-parked-child", @@ -1135,7 +1189,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do # tests, 2 failures"): this case on both adapters and nothing # else. Reverted from the copies. test "adapter: the pin decides, not the child row's own content hash", %{store: store} do - insert_counted_execution( + conformance_insert_counted_execution( store, "counts-pinned-parent", "sha256:counts-pinned-parent", @@ -1185,7 +1239,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do test "adapter: a pin whose parent execution is not stored counts nothing", %{ store: store } do - insert_pinned_child( + conformance_insert_pinned_child( store, "counts-orphan-parent/call/0", "sha256:counts-orphan-child", @@ -1200,7 +1254,13 @@ defmodule StatifierPersistence.Testing.StorageConformance do ) end - defp insert_pinned_child(store, execution_id, content_hash, child_index, status) do + defp conformance_insert_pinned_child( + store, + execution_id, + content_hash, + child_index, + status + ) do [parent_execution_id, invoke_id, _index] = String.split(execution_id, "/") linkage = @@ -1224,7 +1284,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do end end - defp insert_counted_execution(store, execution_id, content_hash, status) do + defp conformance_insert_counted_execution(store, execution_id, content_hash, status) do record = %{ execution_id: execution_id, status: status, @@ -1290,7 +1350,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do if Code.ensure_loaded?(conformance_adapter) and function_exported?(conformance_adapter, :retire_chart, 3) do - @retire_hash "sha256:conformance-retire-" <> @conformance_hash_suffix + @conformance_retire_hash "sha256:conformance-retire-" <> @conformance_hash_suffix # sabotage: drop the adapter under test's guard on the :active # arm - the `Adapter.pinned?(counts) -> ...` cond clause in the @@ -1300,18 +1360,30 @@ defmodule StatifierPersistence.Testing.StorageConformance do # refused. Verified red on both conformance suites. Reverted # from a copy. test "adapter: an :active execution on the hash refuses the retirement", %{store: store} do - save_retirable_chart(store, @retire_hash) - insert_retire_execution(store, "retire-active", @retire_hash, :active) + conformance_save_retirable_chart(store, @conformance_retire_hash) + + conformance_insert_retire_execution( + store, + "retire-active", + @conformance_retire_hash, + :active + ) assert {:error, {:pinned, counts}} = - @conformance_adapter.retire_chart(store.opts, @retire_hash, retirement()) + @conformance_adapter.retire_chart( + store.opts, + @conformance_retire_hash, + conformance_retirement() + ) assert counts.executions.active == 1 assert counts.children == 0 assert counts.positions == 0 assert counts.sources == %{} - assert {:ok, chart} = @conformance_adapter.fetch_chart(store.opts, @retire_hash) + assert {:ok, chart} = + @conformance_adapter.fetch_chart(store.opts, @conformance_retire_hash) + assert chart.chart_blob == <<4, 5, 6>> end @@ -1325,18 +1397,30 @@ defmodule StatifierPersistence.Testing.StorageConformance do # hold's chart was retired instead of refused. Verified red, reverted # from the copies. test "adapter: a parked execution on the hash refuses the retirement", %{store: store} do - save_retirable_chart(store, @retire_hash) - insert_retire_execution(store, "retire-parked", @retire_hash, :needs_migration) + conformance_save_retirable_chart(store, @conformance_retire_hash) + + conformance_insert_retire_execution( + store, + "retire-parked", + @conformance_retire_hash, + :needs_migration + ) assert {:error, {:pinned, counts}} = - @conformance_adapter.retire_chart(store.opts, @retire_hash, retirement()) + @conformance_adapter.retire_chart( + store.opts, + @conformance_retire_hash, + conformance_retirement() + ) assert counts.executions.needs_migration == 1 assert counts.executions.active == 0 assert counts.children == 0 assert counts.positions == 0 - assert {:ok, chart} = @conformance_adapter.fetch_chart(store.opts, @retire_hash) + assert {:ok, chart} = + @conformance_adapter.fetch_chart(store.opts, @conformance_retire_hash) + assert chart.chart_blob == <<4, 5, 6>> end @@ -1349,23 +1433,29 @@ defmodule StatifierPersistence.Testing.StorageConformance do # the bytes. Verified red on both conformance suites. Reverted # from a copy. test "adapter: a position row on the hash refuses the retirement", %{store: store} do - save_retirable_chart(store, @retire_hash) + conformance_save_retirable_chart(store, @conformance_retire_hash) assert :ok = @conformance_adapter.save_position(store.opts, %{ session_id: "sess_conformance_retire", - content_hash: @retire_hash, + content_hash: @conformance_retire_hash, identity_blob: <<1, 2, 3>>, position_blob: <<7, 8, 9>> }) assert {:error, {:pinned, counts}} = - @conformance_adapter.retire_chart(store.opts, @retire_hash, retirement()) + @conformance_adapter.retire_chart( + store.opts, + @conformance_retire_hash, + conformance_retirement() + ) assert counts.positions == 1 assert counts.executions.active == 0 - assert {:ok, chart} = @conformance_adapter.fetch_chart(store.opts, @retire_hash) + assert {:ok, chart} = + @conformance_adapter.fetch_chart(store.opts, @conformance_retire_hash) + assert chart.chart_blob == <<4, 5, 6>> end @@ -1388,34 +1478,46 @@ defmodule StatifierPersistence.Testing.StorageConformance do if function_exported?(conformance_adapter, :supports_metadata?, 1) do test "adapter: a terminal child's pin under an :active parent refuses the retirement", %{store: store} do - save_retirable_chart(store, @retire_hash) - insert_retire_execution(store, "retire-pin-parent", "sha256:retire-parent", :active) + conformance_save_retirable_chart(store, @conformance_retire_hash) + + conformance_insert_retire_execution( + store, + "retire-pin-parent", + "sha256:retire-parent", + :active + ) assert :ok = @conformance_adapter.insert_execution(store.opts, %{ execution_id: "retire-pin-parent/call/0", status: :completed, - content_hash: @retire_hash, + content_hash: @conformance_retire_hash, identity_blob: <<1, 2, 3>>, position_blob: <<7, 8, 9>>, failure: nil, metadata: Linkage.to_metadata( - Linkage.new("retire-pin-parent", "call", 0, @retire_hash) + Linkage.new("retire-pin-parent", "call", 0, @conformance_retire_hash) ), outcome_blob: nil, ended_at: nil }) assert {:error, {:pinned, counts}} = - @conformance_adapter.retire_chart(store.opts, @retire_hash, retirement()) + @conformance_adapter.retire_chart( + store.opts, + @conformance_retire_hash, + conformance_retirement() + ) assert counts.children == 1 assert counts.executions.active == 0 assert counts.executions.completed == 1 assert counts.positions == 0 - assert {:ok, chart} = @conformance_adapter.fetch_chart(store.opts, @retire_hash) + assert {:ok, chart} = + @conformance_adapter.fetch_chart(store.opts, @conformance_retire_hash) + assert chart.chart_blob == <<4, 5, 6>> end end @@ -1429,9 +1531,9 @@ defmodule StatifierPersistence.Testing.StorageConformance do if function_exported?(conformance_adapter, :supports_metadata?, 1) do test "adapter: a terminal child's pin under a parked parent refuses the retirement", %{store: store} do - save_retirable_chart(store, @retire_hash) + conformance_save_retirable_chart(store, @conformance_retire_hash) - insert_retire_execution( + conformance_insert_retire_execution( store, "retire-parked-parent", "sha256:retire-parent", @@ -1442,25 +1544,36 @@ defmodule StatifierPersistence.Testing.StorageConformance do @conformance_adapter.insert_execution(store.opts, %{ execution_id: "retire-parked-parent/call/0", status: :completed, - content_hash: @retire_hash, + content_hash: @conformance_retire_hash, identity_blob: <<1, 2, 3>>, position_blob: <<7, 8, 9>>, failure: nil, metadata: Linkage.to_metadata( - Linkage.new("retire-parked-parent", "call", 0, @retire_hash) + Linkage.new( + "retire-parked-parent", + "call", + 0, + @conformance_retire_hash + ) ), outcome_blob: nil, ended_at: nil }) assert {:error, {:pinned, counts}} = - @conformance_adapter.retire_chart(store.opts, @retire_hash, retirement()) + @conformance_adapter.retire_chart( + store.opts, + @conformance_retire_hash, + conformance_retirement() + ) assert counts.children == 1 assert counts.executions.needs_migration == 0 - assert {:ok, chart} = @conformance_adapter.fetch_chart(store.opts, @retire_hash) + assert {:ok, chart} = + @conformance_adapter.fetch_chart(store.opts, @conformance_retire_hash) + assert chart.chart_blob == <<4, 5, 6>> end end @@ -1473,21 +1586,23 @@ defmodule StatifierPersistence.Testing.StorageConformance do # on both conformance suites. Reverted from a copy. test "adapter: a source's non-zero count refuses, under that source's module name", %{store: store} do - save_retirable_chart(store, @retire_hash) + conformance_save_retirable_chart(store, @conformance_retire_hash) sources = %{__MODULE__ => %{pending_timers: 2}} assert {:error, {:pinned, counts}} = @conformance_adapter.retire_chart( store.opts, - @retire_hash, - retirement(sources) + @conformance_retire_hash, + conformance_retirement(sources) ) assert counts.sources == sources assert counts.executions.active == 0 assert counts.positions == 0 - assert {:ok, chart} = @conformance_adapter.fetch_chart(store.opts, @retire_hash) + assert {:ok, chart} = + @conformance_adapter.fetch_chart(store.opts, @conformance_retire_hash) + assert chart.chart_blob == <<4, 5, 6>> end @@ -1507,12 +1622,19 @@ defmodule StatifierPersistence.Testing.StorageConformance do # from a copy. test "adapter: a drained hash is retired, keeping the row and dropping the bytes", %{store: store} do - save_retirable_chart(store, @retire_hash) - insert_retire_execution(store, "retire-done", @retire_hash, :completed) + conformance_save_retirable_chart(store, @conformance_retire_hash) + + conformance_insert_retire_execution( + store, + "retire-done", + @conformance_retire_hash, + :completed + ) + at = DateTime.from_naive!(~N[2026-09-19 18:00:00.000000], "Etc/UTC") assert {:ok, info} = - @conformance_adapter.retire_chart(store.opts, @retire_hash, %{ + @conformance_adapter.retire_chart(store.opts, @conformance_retire_hash, %{ retired_at: at, retired_by: "conformance-operator", sources: %{} @@ -1524,7 +1646,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do # The row and its hash survive the removal: that is what makes # the retired arm answerable at all, rather than a miss. assert {:error, {:chart_retired, read_back}} = - @conformance_adapter.fetch_chart(store.opts, @retire_hash) + @conformance_adapter.fetch_chart(store.opts, @conformance_retire_hash) assert read_back.retired_at == at assert read_back.retired_by == "conformance-operator" @@ -1532,7 +1654,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do assert {:ok, counts} = @conformance_adapter.count_executions_by_content_hash( store.opts, - @retire_hash + @conformance_retire_hash ) assert counts.completed == 1 @@ -1545,19 +1667,35 @@ defmodule StatifierPersistence.Testing.StorageConformance do # both conformance suites. Reverted from a copy. test "adapter: a terminal execution never pins, and a retired hash is never a miss", %{store: store} do - save_retirable_chart(store, @retire_hash) - insert_retire_execution(store, "retire-failed", @retire_hash, :failed) - insert_retire_execution(store, "retire-cancelled", @retire_hash, :cancelled) + conformance_save_retirable_chart(store, @conformance_retire_hash) + + conformance_insert_retire_execution( + store, + "retire-failed", + @conformance_retire_hash, + :failed + ) + + conformance_insert_retire_execution( + store, + "retire-cancelled", + @conformance_retire_hash, + :cancelled + ) assert {:ok, _info} = - @conformance_adapter.retire_chart(store.opts, @retire_hash, retirement()) + @conformance_adapter.retire_chart( + store.opts, + @conformance_retire_hash, + conformance_retirement() + ) assert {:error, {:chart_retired, _info}} = - @conformance_adapter.fetch_chart(store.opts, @retire_hash) + @conformance_adapter.fetch_chart(store.opts, @conformance_retire_hash) refute match?( {:error, :chart_not_found}, - @conformance_adapter.fetch_chart(store.opts, @retire_hash) + @conformance_adapter.fetch_chart(store.opts, @conformance_retire_hash) ) end @@ -1571,19 +1709,19 @@ defmodule StatifierPersistence.Testing.StorageConformance do # from a copy. test "adapter: retiring twice answers the retired arm, never a second tombstone", %{store: store} do - save_retirable_chart(store, @retire_hash) + conformance_save_retirable_chart(store, @conformance_retire_hash) first = DateTime.from_naive!(~N[2026-09-19 18:00:00.000000], "Etc/UTC") second = DateTime.from_naive!(~N[2026-09-19 19:00:00.000000], "Etc/UTC") assert {:ok, _info} = - @conformance_adapter.retire_chart(store.opts, @retire_hash, %{ + @conformance_adapter.retire_chart(store.opts, @conformance_retire_hash, %{ retired_at: first, retired_by: "first-operator", sources: %{} }) assert {:error, {:chart_retired, info}} = - @conformance_adapter.retire_chart(store.opts, @retire_hash, %{ + @conformance_adapter.retire_chart(store.opts, @conformance_retire_hash, %{ retired_at: second, retired_by: "second-operator", sources: %{} @@ -1598,20 +1736,24 @@ defmodule StatifierPersistence.Testing.StorageConformance do # after the retirement answered :ok instead of the retired arm. # Verified red on both conformance suites. Reverted from a copy. test "adapter: saving a tombstoned hash refuses and does not revive it", %{store: store} do - save_retirable_chart(store, @retire_hash) + conformance_save_retirable_chart(store, @conformance_retire_hash) assert {:ok, _info} = - @conformance_adapter.retire_chart(store.opts, @retire_hash, retirement()) + @conformance_adapter.retire_chart( + store.opts, + @conformance_retire_hash, + conformance_retirement() + ) assert {:error, {:chart_retired, _info}} = @conformance_adapter.save_chart(store.opts, %{ - content_hash: @retire_hash, + content_hash: @conformance_retire_hash, identity_blob: <<1, 2, 3>>, chart_blob: <<4, 5, 6>> }) assert {:error, {:chart_retired, _info}} = - @conformance_adapter.fetch_chart(store.opts, @retire_hash) + @conformance_adapter.fetch_chart(store.opts, @conformance_retire_hash) end # sabotage: in the adapter under test's retire_chart/3, drop the @@ -1625,7 +1767,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do @conformance_adapter.retire_chart( store.opts, "sha256:conformance-retire-never-stored-" <> @conformance_hash_suffix, - retirement() + conformance_retirement() ) end @@ -1636,14 +1778,26 @@ defmodule StatifierPersistence.Testing.StorageConformance do # suites. Reverted from a copy. test "adapter: only the :active executions on the hash are listed for a pin source", %{store: store} do - save_retirable_chart(store, @retire_hash) - insert_retire_execution(store, "retire-listed", @retire_hash, :active) - insert_retire_execution(store, "retire-unlisted", @retire_hash, :completed) + conformance_save_retirable_chart(store, @conformance_retire_hash) + + conformance_insert_retire_execution( + store, + "retire-listed", + @conformance_retire_hash, + :active + ) + + conformance_insert_retire_execution( + store, + "retire-unlisted", + @conformance_retire_hash, + :completed + ) assert {:ok, ids} = @conformance_adapter.list_active_execution_ids_by_content_hash( store.opts, - @retire_hash + @conformance_retire_hash ) assert ids == ["retire-listed"] @@ -1659,14 +1813,26 @@ defmodule StatifierPersistence.Testing.StorageConformance do # this case alone in each: the parked id was listed too. Verified red, # reverted from the copies. test "adapter: a parked execution is not listed for a pin source", %{store: store} do - save_retirable_chart(store, @retire_hash) - insert_retire_execution(store, "retire-listed-active", @retire_hash, :active) - insert_retire_execution(store, "retire-unlisted-parked", @retire_hash, :needs_migration) + conformance_save_retirable_chart(store, @conformance_retire_hash) + + conformance_insert_retire_execution( + store, + "retire-listed-active", + @conformance_retire_hash, + :active + ) + + conformance_insert_retire_execution( + store, + "retire-unlisted-parked", + @conformance_retire_hash, + :needs_migration + ) assert {:ok, ids} = @conformance_adapter.list_active_execution_ids_by_content_hash( store.opts, - @retire_hash + @conformance_retire_hash ) assert ids == ["retire-listed-active"] @@ -1687,7 +1853,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do # the Ecto adapter over Postgres, is a live-connection property # and is pinned outside this suite. - defmodule RetiringSerialization do + defmodule ConformanceRetiringSerialization do @moduledoc false @behaviour StatifierPersistence.Serialization @@ -1705,7 +1871,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do end end - @loan_source """ + @conformance_loan_source """ @@ -1716,7 +1882,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do """ - @renewed_source """ + @conformance_renewed_source """ @@ -1737,8 +1903,8 @@ defmodule StatifierPersistence.Testing.StorageConformance do # from a copy. test "facade: a create whose hash is retired after the first check refuses and writes nothing", %{store: store} do - {:ok, machine} = Statifier.compile(@loan_source) - :ok = Storage.save_chart(store, machine, @loan_source) + {:ok, machine} = Statifier.compile(@conformance_loan_source) + :ok = Storage.save_chart(store, machine, @conformance_loan_source) content_hash = Machine.identity(machine).content_hash test_pid = self() executor = fn effect, _context -> send(test_pid, {:effect, effect}) && :ok end @@ -1750,7 +1916,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do machine, executor: executor, serialization: - {RetiringSerialization, + {ConformanceRetiringSerialization, {@conformance_adapter, store.opts, content_hash, test_pid}} ) @@ -1771,10 +1937,10 @@ defmodule StatifierPersistence.Testing.StorageConformance do # from a copy. test "facade: a migration whose to hash is retired after the first check refuses and writes nothing", %{store: store} do - {:ok, from_machine} = Statifier.compile(@loan_source) - {:ok, to_machine} = Statifier.compile(@renewed_source) - :ok = Storage.save_chart(store, from_machine, @loan_source) - :ok = Storage.save_chart(store, to_machine, @renewed_source) + {:ok, from_machine} = Statifier.compile(@conformance_loan_source) + {:ok, to_machine} = Statifier.compile(@conformance_renewed_source) + :ok = Storage.save_chart(store, from_machine, @conformance_loan_source) + :ok = Storage.save_chart(store, to_machine, @conformance_renewed_source) from_hash = Machine.identity(from_machine).content_hash to_hash = Machine.identity(to_machine).content_hash quiet = fn _effect, _context -> :ok end @@ -1803,7 +1969,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do to_machine: to_machine, on_failure: :park, serialization: - {RetiringSerialization, + {ConformanceRetiringSerialization, {@conformance_adapter, store.opts, to_hash, self()}} ) @@ -1813,7 +1979,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do Storage.fetch_execution(store, "retire-between-migrate") end - defp retirement(sources \\ %{}) do + defp conformance_retirement(sources \\ %{}) do %{ retired_at: DateTime.utc_now(), retired_by: "conformance-operator", @@ -1821,7 +1987,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do } end - defp save_retirable_chart(store, content_hash) do + defp conformance_save_retirable_chart(store, content_hash) do assert :ok = @conformance_adapter.save_chart(store.opts, %{ content_hash: content_hash, @@ -1830,7 +1996,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do }) end - defp insert_retire_execution(store, execution_id, content_hash, status) do + defp conformance_insert_retire_execution(store, execution_id, content_hash, status) do assert :ok = @conformance_adapter.insert_execution(store.opts, %{ execution_id: execution_id, @@ -1855,8 +2021,8 @@ defmodule StatifierPersistence.Testing.StorageConformance do if Code.ensure_loaded?(conformance_adapter) and function_exported?(conformance_adapter, :list_execution_ids_by_content_hash, 3) do - @listing_hash "sha256:conformance-listing-by-status" - @listing_other_hash "sha256:conformance-listing-other" + @conformance_listing_hash "sha256:conformance-listing-by-status" + @conformance_listing_other_hash "sha256:conformance-listing-other" # sabotage: in the adapter under test's # list_execution_ids_by_content_hash/3, drop the status predicate @@ -1865,25 +2031,55 @@ defmodule StatifierPersistence.Testing.StorageConformance do # from a copy. test "adapter: the listing names the executions on the hash in the asked statuses", %{store: store} do - save_listing_chart(store, @listing_hash) - save_listing_chart(store, @listing_other_hash) - insert_listing_execution(store, "listing-c-active", @listing_hash, :active) - insert_listing_execution(store, "listing-a-parked", @listing_hash, :needs_migration) - insert_listing_execution(store, "listing-b-done", @listing_hash, :completed) - insert_listing_execution(store, "listing-d-cancelled", @listing_hash, :cancelled) - insert_listing_execution(store, "listing-e-elsewhere", @listing_other_hash, :active) + conformance_save_listing_chart(store, @conformance_listing_hash) + conformance_save_listing_chart(store, @conformance_listing_other_hash) + + conformance_insert_listing_execution( + store, + "listing-c-active", + @conformance_listing_hash, + :active + ) + + conformance_insert_listing_execution( + store, + "listing-a-parked", + @conformance_listing_hash, + :needs_migration + ) + + conformance_insert_listing_execution( + store, + "listing-b-done", + @conformance_listing_hash, + :completed + ) + + conformance_insert_listing_execution( + store, + "listing-d-cancelled", + @conformance_listing_hash, + :cancelled + ) + + conformance_insert_listing_execution( + store, + "listing-e-elsewhere", + @conformance_listing_other_hash, + :active + ) assert {:ok, ["listing-a-parked", "listing-c-active"]} = @conformance_adapter.list_execution_ids_by_content_hash( store.opts, - @listing_hash, + @conformance_listing_hash, [:active, :needs_migration] ) assert {:ok, ["listing-b-done", "listing-d-cancelled"]} = @conformance_adapter.list_execution_ids_by_content_hash( store.opts, - @listing_hash, + @conformance_listing_hash, [:completed, :cancelled] ) end @@ -1904,7 +2100,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do # order. Verified red on the in-memory and the Ecto (Postgres) # suites, reverted from a copy. test "adapter: the listing is in ascending execution id", %{store: store} do - save_listing_chart(store, @listing_hash) + conformance_save_listing_chart(store, @conformance_listing_hash) ids = for n <- 1..40, do: "listing-order-#{n}" inserted = Enum.sort(ids, :desc) @@ -1912,13 +2108,13 @@ defmodule StatifierPersistence.Testing.StorageConformance do refute inserted == Enum.sort(ids) for id <- inserted do - insert_listing_execution(store, id, @listing_hash, :active) + conformance_insert_listing_execution(store, id, @conformance_listing_hash, :active) end assert {:ok, listed} = @conformance_adapter.list_execution_ids_by_content_hash( store.opts, - @listing_hash, + @conformance_listing_hash, [:active] ) @@ -1931,8 +2127,14 @@ defmodule StatifierPersistence.Testing.StorageConformance do # execution. Verified red on both conformance suites. Reverted # from a copy. test "adapter: a hash this store never held lists nothing", %{store: store} do - save_listing_chart(store, @listing_other_hash) - insert_listing_execution(store, "listing-f-elsewhere", @listing_other_hash, :active) + conformance_save_listing_chart(store, @conformance_listing_other_hash) + + conformance_insert_listing_execution( + store, + "listing-f-elsewhere", + @conformance_listing_other_hash, + :active + ) assert {:ok, []} = @conformance_adapter.list_execution_ids_by_content_hash( @@ -1942,7 +2144,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do ) end - defp save_listing_chart(store, content_hash) do + defp conformance_save_listing_chart(store, content_hash) do assert :ok = @conformance_adapter.save_chart(store.opts, %{ content_hash: content_hash, @@ -1951,7 +2153,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do }) end - defp insert_listing_execution(store, execution_id, content_hash, status) do + defp conformance_insert_listing_execution(store, execution_id, content_hash, status) do assert :ok = @conformance_adapter.insert_execution(store.opts, %{ execution_id: execution_id, @@ -1987,7 +2189,8 @@ defmodule StatifierPersistence.Testing.StorageConformance do test "adapter: a tree write lands every re-pin and park, the pin rewritten", %{ store: store } do - parent = insert_tree_execution(store, "tree-parent", "sha256:tree-parent-old", %{}) + parent = + conformance_insert_tree_execution(store, "tree-parent", "sha256:tree-parent-old", %{}) child_metadata = if Storage.metadata_supported?(store) do @@ -2000,7 +2203,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do end child = - insert_tree_execution( + conformance_insert_tree_execution( store, "tree-parent/pickup/0", "sha256:tree-child-old", @@ -2052,7 +2255,9 @@ defmodule StatifierPersistence.Testing.StorageConformance do # execution came back changed. Verified red, reverted from the # copies. test "adapter: a tree write that cannot land one write lands none", %{store: store} do - first = insert_tree_execution(store, "tree-first", "sha256:tree-first-old", %{}) + first = + conformance_insert_tree_execution(store, "tree-first", "sha256:tree-first-old", %{}) + repinned = %{first | content_hash: "sha256:tree-first-new", position_blob: <<21>>} assert {:error, :execution_not_found} = @@ -2064,7 +2269,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do assert {:ok, ^first} = @conformance_adapter.fetch_execution(store.opts, "tree-first") end - defp insert_tree_execution(store, execution_id, content_hash, metadata) do + defp conformance_insert_tree_execution(store, execution_id, content_hash, metadata) do record = %{ execution_id: execution_id, status: :active, @@ -2501,7 +2706,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do # reverted. test "adapter: append_input/3 assigns dense ordinals from zero and lists them in order", %{store: store} do - execution_id = input_log_execution(store, "execution-conformance-input-log") + execution_id = conformance_input_log_execution(store, "execution-conformance-input-log") for {door, index} <- Enum.with_index(["create", "step", "done_invocation"]) do assert {:ok, ^index} = @@ -2539,8 +2744,8 @@ defmodule StatifierPersistence.Testing.StorageConformance do # conformance modules and on the SQLite mirror: one execution's log came # back carrying the other's entries. Verified red, reverted. test "adapter: two executions' logs never see each other's entries", %{store: store} do - execution_id = input_log_execution(store, "execution-conformance-input-log") - other = input_log_execution(store, "execution-conformance-input-log-other") + execution_id = conformance_input_log_execution(store, "execution-conformance-input-log") + other = conformance_input_log_execution(store, "execution-conformance-input-log-other") for door <- ["step", "step"] do assert {:ok, _seq} = @@ -2582,7 +2787,8 @@ defmodule StatifierPersistence.Testing.StorageConformance do :ok = apply(@conformance_adapter, :isolate, [capped.opts]) end - execution_id = input_log_execution(capped, "execution-conformance-input-log-cap") + execution_id = + conformance_input_log_execution(capped, "execution-conformance-input-log-cap") append = fn -> @conformance_adapter.append_input(capped.opts, execution_id, %{ @@ -2616,7 +2822,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do test "facade: an event round-trips through the log equal to what was delivered", %{ store: store } do - execution_id = input_log_execution(store, "execution-conformance-input-log") + execution_id = conformance_input_log_execution(store, "execution-conformance-input-log") event = %Statifier.Event{ name: "done.invoke.call", @@ -2643,7 +2849,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do # there. Called from inside each case that needs it rather than # from a `setup`, so nothing this template registers writes before # a host's own callbacks have run (see the moduledoc). - defp input_log_execution(store, execution_id) do + defp conformance_input_log_execution(store, execution_id) do {_source, machine} = Charts.chart_a() machine_state = @@ -2678,7 +2884,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do %{store: store} do ended = ~U[2026-01-01 00:00:00.000000Z] - prune_execution(store, "execution-conformance-prune-kept", :failed, ended, + conformance_prune_execution(store, "execution-conformance-prune-kept", :failed, ended, failure: "boom" ) @@ -2720,22 +2926,34 @@ defmodule StatifierPersistence.Testing.StorageConformance do store: store } do cutoff = ~U[2026-02-01 00:00:00.000000Z] - prune_execution(store, "execution-conformance-prune-at-cutoff", :completed, cutoff) - prune_execution( + conformance_prune_execution( + store, + "execution-conformance-prune-at-cutoff", + :completed, + cutoff + ) + + conformance_prune_execution( store, "execution-conformance-prune-later", :cancelled, ~U[2026-03-01 00:00:00.000000Z] ) - prune_execution(store, "execution-conformance-prune-active", :active, nil) + conformance_prune_execution(store, "execution-conformance-prune-active", :active, nil) # A row stamped when it ended and then written back to :active # keeps its stamp (the execution record's rule) and is not # finished, so a prune must not take its position. reopened = "execution-conformance-prune-reopened" - prune_execution(store, reopened, :completed, ~U[2026-01-01 00:00:00.000000Z]) + + conformance_prune_execution( + store, + reopened, + :completed, + ~U[2026-01-01 00:00:00.000000Z] + ) # A terminal row with no stamp - one that ended before its store # could hold the field - has no end time to compare, so it is @@ -2781,7 +2999,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do } do cutoff = ~U[2026-02-01 00:00:00.000000Z] - prune_execution( + conformance_prune_execution( store, "execution-conformance-prune-once", :completed, @@ -2803,14 +3021,14 @@ defmodule StatifierPersistence.Testing.StorageConformance do } do cutoff = ~U[2026-02-01 00:00:00.000000Z] - prune_execution( + conformance_prune_execution( store, "execution-conformance-prune-second", :completed, ~U[2026-01-20 00:00:00.000000Z] ) - prune_execution( + conformance_prune_execution( store, "execution-conformance-prune-first", :completed, @@ -2846,8 +3064,15 @@ defmodule StatifierPersistence.Testing.StorageConformance do cutoff = ~U[2026-02-01 00:00:00.000000Z] finished = "execution-conformance-prune-logged" running = "execution-conformance-prune-logged-active" - prune_execution(store, finished, :completed, ~U[2026-01-01 00:00:00.000000Z]) - prune_execution(store, running, :active, nil) + + conformance_prune_execution( + store, + finished, + :completed, + ~U[2026-01-01 00:00:00.000000Z] + ) + + conformance_prune_execution(store, running, :active, nil) for id <- [finished, finished, running] do assert {:ok, _seq} = @@ -2883,7 +3108,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do outside = "execution-conformance-prune-scoped-outside" for {id, scope} <- [{inside, inside_scope}, {outside, outside_scope}] do - prune_execution(store, id, :completed, ~U[2026-01-01 00:00:00.000000Z]) + conformance_prune_execution(store, id, :completed, ~U[2026-01-01 00:00:00.000000Z]) if logs? do assert {:ok, _seq} = @@ -2924,7 +3149,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do # Inserts one execution in `status`, stamped `ended_at` when that # is terminal, with a stored position. Called from inside each case # rather than from a `setup`, for the input log helper's reason. - defp prune_execution(store, execution_id, status, ended_at, opts \\ []) do + defp conformance_prune_execution(store, execution_id, status, ended_at, opts \\ []) do {_source, machine} = Charts.chart_a() machine_state = @@ -2956,7 +3181,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do # `lock_execution/3` and carries no tag. Without the refusal the # nested step lands `x` and the outer write puts `b` over it. - defmodule ReentrantSerialization do + defmodule ConformanceReentrantSerialization do @moduledoc false @behaviour StatifierPersistence.Serialization @@ -2986,7 +3211,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do execution_id = "execution-conformance-reentrant" test_pid = self() - serialization = {ReentrantSerialization, nil} + serialization = {ConformanceReentrantSerialization, nil} quiet = fn _effect, _context -> :ok end assert {:ok, _execution, _machine_state} = @@ -3254,7 +3479,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do # reverted from a copy. test "facade: the tombstone check refuses a retired chart and lets a live one through", %{store: store} do - {source, machine} = own_chart_a() + {source, machine} = conformance_own_chart_a() content_hash = Machine.identity(machine).content_hash assert :ok = Storage.check_chart_retired(store, machine) @@ -3294,7 +3519,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do :telemetry.attach( handler_id, [:statifier_persistence, :adapter, :call], - &__MODULE__.__conformance_forward_adapter_call__/4, + &__MODULE__.conformance_forward_adapter_call/4, %{pid: test_pid} ) @@ -3304,9 +3529,9 @@ defmodule StatifierPersistence.Testing.StorageConformance do :telemetry.detach(handler_id) end - callbacks = collect_adapter_calls([]) + callbacks = conformance_collect_adapter_calls([]) - if narrow_read_declared?(store) do + if conformance_narrow_read_declared?(store) do assert :fetch_retired_info in callbacks refute :fetch_chart in callbacks else @@ -3320,7 +3545,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do # the calls made on the test's own process, so an async suite # running beside it adds nothing to what the case reads. @doc false - def __conformance_forward_adapter_call__(_event, _measurements, metadata, %{pid: pid}) do + def conformance_forward_adapter_call(_event, _measurements, metadata, %{pid: pid}) do if self() == pid, do: send(pid, {:adapter_call, metadata.callback}) end @@ -3328,7 +3553,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do # so its content hash is this module's own: the case above # retires it, and a retirement must never meet another async # module's copy of the case on one lock key. - defp own_chart_a do + defp conformance_own_chart_a do {source, _machine} = Charts.chart_a() own_source = @@ -3342,7 +3567,7 @@ defmodule StatifierPersistence.Testing.StorageConformance do {own_source, machine} end - defp narrow_read_declared?(store) do + defp conformance_narrow_read_declared?(store) do if function_exported?(@conformance_adapter, :supports_retired_info?, 1) and function_exported?(@conformance_adapter, :fetch_retired_info, 2) do # credo:disable-for-next-line Credo.Check.Refactor.Apply @@ -3352,9 +3577,9 @@ defmodule StatifierPersistence.Testing.StorageConformance do end end - defp collect_adapter_calls(acc) do + defp conformance_collect_adapter_calls(acc) do receive do - {:adapter_call, callback} -> collect_adapter_calls([callback | acc]) + {:adapter_call, callback} -> conformance_collect_adapter_calls([callback | acc]) after 0 -> Enum.reverse(acc) end diff --git a/test/statifier_persistence/storage/reserved_prefix_conformance_test.exs b/test/statifier_persistence/storage/reserved_prefix_conformance_test.exs new file mode 100644 index 0000000..c9d77fb --- /dev/null +++ b/test/statifier_persistence/storage/reserved_prefix_conformance_test.exs @@ -0,0 +1,55 @@ +defmodule StatifierPersistence.Storage.ReservedPrefixConformanceTest do + @moduledoc """ + The reserved-prefix contract in + `StatifierPersistence.Testing.StorageConformance`'s moduledoc, under + test. + + Every name the suite's `use` defines in a host module carries the + `conformance` prefix, so a host is free to keep every other name for + itself. This module is the host-shaped case: it keeps an attribute, a + nested module and a private function of its own under names the suite + once defined without the prefix, and the suite's own cases run beside + them against `StatifierPersistence.Storage.InMemory`, which exports every + optional callback those names were generated under. + """ + + # The host's own attribute, set above the `use`. + @retire_hash "sha256:the-host-module-own-hash" + + # The host's own nested module, defined above the `use`. + defmodule ReentrantSerialization do + @moduledoc false + + @spec owner() :: :host + def owner, do: :host + end + + use StatifierPersistence.Testing.StorageConformance, + async: true, + adapter: StatifierPersistence.Storage.InMemory, + opts: [] + + # sabotage: in the template, rename `@conformance_retire_hash` back to + # `@retire_hash` -> red, the attribute read here answers the suite's + # retire hash instead of the host's own. Verified red, reverted. + test "a host attribute named like a suite attribute keeps the host's value" do + assert @retire_hash == "sha256:the-host-module-own-hash" + end + + # sabotage: in the template, rename `ConformanceReentrantSerialization` + # back to `ReentrantSerialization` -> red, the suite's module replaces + # the host's and `owner/0` is gone. Verified red, reverted. + test "a host nested module named like a suite module keeps the host's functions" do + assert function_exported?(ReentrantSerialization, :owner, 0) + end + + # sabotage: in the template, rename `conformance_own_chart_a/0` back to + # `own_chart_a/0` -> red, the suite's clause comes first and answers + # its own chart instead of the host's atom. Verified red, reverted. + test "a host private function named like a suite helper keeps the host's body" do + assert own_chart_a() == :the_host_module_own_chart + end + + # The host's own private helper, defined below the `use`. + defp own_chart_a, do: :the_host_module_own_chart +end diff --git a/test/statifier_persistence/storage/setup_ordering_conformance_test.exs b/test/statifier_persistence/storage/setup_ordering_conformance_test.exs index 443e1e7..94d153e 100644 --- a/test/statifier_persistence/storage/setup_ordering_conformance_test.exs +++ b/test/statifier_persistence/storage/setup_ordering_conformance_test.exs @@ -17,7 +17,7 @@ defmodule StatifierPersistence.Storage.SetupOrderingConformanceTest do one. sabotage: put the eager fixture back - a - `setup %{store: store} do %{logged_execution: input_log_execution(store, "execution-conformance-input-log")} end` + `setup %{store: store} do %{logged_execution: conformance_input_log_execution(store, "execution-conformance-input-log")} end` above the input-log cases in the template, with the three cases reading `logged_execution` from the context again -> red here, on every case this module generates, with the fixture execution already inserted by the time the @@ -47,7 +47,7 @@ defmodule StatifierPersistence.Storage.SetupOrderingConformanceTest do end # sabotage: put the eager fixture back in the template - a - # `setup %{store: store} do %{logged_execution: input_log_execution(store, + # `setup %{store: store} do %{logged_execution: conformance_input_log_execution(store, # "execution-conformance-input-log")} end` above the input-log cases -> red, # 38 of 38 cases in this module, the host-shaped callback finding the # fixture execution already inserted. Verified red, reverted. @@ -56,7 +56,7 @@ defmodule StatifierPersistence.Storage.SetupOrderingConformanceTest do assert order == [:template_setup, :host_setup] end - # sabotage: in the template's `input_log_execution/2`, drop the + # sabotage: in the template's `conformance_input_log_execution/2`, drop the # `Storage.insert_execution(store, execution_id, machine_state, :active)` -> red, # this case plus the four input-log cases that build the fixture, all # reporting `:execution_not_found` where an execution was expected. Verified red, @@ -64,7 +64,7 @@ defmodule StatifierPersistence.Storage.SetupOrderingConformanceTest do test "the input-log fixture lands only when a case builds it", %{store: store} do assert {:error, :execution_not_found} = Storage.fetch_execution(store, @fixture_execution) - execution_id = input_log_execution(store, @fixture_execution) + execution_id = conformance_input_log_execution(store, @fixture_execution) assert {:ok, %{status: :active}} = Storage.fetch_execution(store, execution_id) end