Normandy.Test.SessionStoreContract (normandy v2.2.0)

View Source

The ExUnit tests every Normandy.Behaviours.SessionStore implementation must pass. Normandy runs them against its own five backends; run them against yours.

defmodule MyApp.SessionStoreTest do
  use ExUnit.Case, async: true

  use Normandy.Test.SessionStoreContract,
    impl: MyApp.SessionStore,
    new: {MyApp.SessionStore, :new, [[url: "..."]]}
end

Options, checked when the test module compiles (a bad one raises ArgumentError):

  • :impl (atom/0) - Required. The module implementing Normandy.Behaviours.SessionStore.

  • :new - {module, function, args} returning a fresh, empty handle, called once per test. Default: {impl, :new, []}.

  • :stored_entry_ids - {module, function, args} called with the handle appended to args; it returns the id of every entry the backend still stores, in any session (an entry without an id of its own counts under the id history/2 returns for it). nil skips the storage-level delete checks. The default value is nil.

Every test builds its handle with :new and needs it empty: tests use fixed session ids ("s1", "parked") and assert exact list_resumable/1 results. A backend whose storage is shared between handles (a database, a node-global table) must give each handle its own namespace, or reset the storage in a setup placed before the use line, and its test module must be async: false when handles can see each other's data.

The tests run real concurrency (200 Tasks appending to one session, awaited for up to 5 s) and fork and delete sessions.

With :stored_entry_ids, the two tests that delete a fork's parent or a fork also check that the deleted session's own entries are gone from storage; without it they check through the behaviour's callbacks only (history/2 of the survivor).