Documentation
¶
Overview ¶
Package sessionstoretest checks exp.SessionStore implementations against the contract the agent runtime relies on.
Run the suite from a test in the store's package:
func TestConformance(t *testing.T) {
sessionstoretest.Run(t, func(t *testing.T) aix.SessionStore[MyState] {
return newEmptyStore[MyState](t)
}, nil)
}
The suite works only through the store's exported methods, so it suits any implementation, including one outside this module. It checks the optional capabilities (exp.SnapshotMetadataReader and exp.SnapshotSubscriber) when the store implements them, and Options turns on the checks that need more than one store: a second instance over the same storage, and a store that partitions its rows by a key from the context.
The test data lives in the conversation (messages, artifacts, and usage) and the custom state keeps its zero value, so the suite runs with any State type, including against a store that supports only one State type.
APIs in this package are under active development and may change in any minor version release.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Run ¶
func Run[State any](t *testing.T, newStore func(t *testing.T) exp.SessionStore[State], opts *Options[State])
Run checks the stores newStore returns against the session store contract, as subtests of t grouped by area: Save, Lifecycle, Chains, Latest, Metadata, Subscriber, SecondInstance, and Scopes. A group whose capability the store lacks, or whose Options hook is nil, is skipped with the reason.
newStore must return a fresh, empty store on every call, with its default behavior: retention that deletes old rows, for example, must be off, because the suite reads back every row it writes. Stores from separate calls may share storage as long as neither can see the other's rows. Run calls newStore once more than its subtests need, to probe the optional capabilities.
The suite expects timestamps to round-trip to at least millisecond precision (it compares instants, so the time zone may change) and the state to round-trip as JSON. Its snapshot and session IDs contain only ASCII letters, digits, and hyphens. A store that cannot hold one of the larger cases (about 2.5 MiB of state) can leave it out with go test -skip.
Types ¶
type Options ¶
type Options[State any] struct { // Reopen returns a second store over the same storage as store, the way // another process would open it. With it, the suite checks that rows // written through one instance read back through the other, and that a // status change written through one reaches a subscriber on the other, // which is how one process aborts a detached run another process executes. // The suite subscribes through the reopened store and writes through the // original. Leave it nil when the storage is private to one instance. Reopen func(t *testing.T, store exp.SessionStore[State]) exp.SessionStore[State] // Scoped returns a fresh, empty store that partitions its rows by a key it // derives from each call's context, such as a tenant prefix, and two // contexts the store maps to different partitions. With it, the suite // checks that neither partition can read, change, or subscribe to the // other's rows, including under a snapshot ID both use. Leave it nil when // the store has no such partitioning. Scoped func(t *testing.T) (store exp.SessionStore[State], a, b context.Context) }
Options turns on the checks that need more than the store under test. A nil *Options runs the single-store checks only.