Storage Conformance Tests
GraphStorageis experimental in 0.1.x: its methods and associated types may change in any 0.1.x release (a layered storage with snapshot reads is planned for 0.2). The trait's own rustdoc is the implementer's guide: handles, units, capabilities, change capture and statistics.
The crate graphersal-storage-tests (on crates.io, EXPERIMENTAL like the trait: it may break in any minor
release before 1.0, so pin the exact version) runs one contract against any GraphStorage implementation. Add it
as a dev-dependency (graphersal-storage-tests = "=0.1.0") and, in a test of the implementing crate:
graphersal_storage_tests::conformance!(my_storage, base = MyStorage::new() => base);
The suite uses only graphersal's public API.
Each contract item is a separate test (ids, label sets, edge endpoints, property kinds, JSONPath writes and
removals, cascading drops, counts and *_by_label equal to scans after every mutation, schema application,
read-only wrappers, stale handles that never alias another element) plus a smoke layer that loads the
modern graph through the trait and compares eight traversals with TraversalGraph.
Schema support is optional: the schema items check enforcement only when set_schema does not return
GraphError::Unsupported (the trait default); otherwise they pass without checking anything. Schema enforcement is
not reusable outside graphersal yet, so a storage in another crate keeps that default and still passes
conformance!. conformance_core! leaves the schema items out entirely, for a storage that accepts schemas but
deliberately does not enforce them.
Some items depend on what the storage claims in capabilities() (see Transactions):
capabilities_are_consistent always runs (change_capture requires atomic); the rollback, savepoint and
unit_changes items run for an atomic storage; the commit-hook and apply_change_set items run for a storage
with change_capture (and check that a storage without it refuses hook registration). Where the trait documentation is silent the reference implementation decides;
those points are listed in the crate README.
The suite is run against TraversalGraph, &mut TraversalGraph, Box<TraversalGraph>, Arc<TraversalGraph>,
(read-only items) &TraversalGraph and the blanket &G view of that wrapper, the crate's Forwarding test storage
(own handle types, every method forwarded to a TraversalGraph) and a wrapper in the suite's own tests that keeps the
trait's schema defaults. It found two contract violations in TraversalGraph (a panic in add_edge for a dropped endpoint, stale edge-id
entries after drop_vertex); both are fixed and the suite runs with no ignored test.
Running the TinkerPop suite against another storage
The harness (crates/graphersal/tests/tinkerpop/harness/) holds every dataset graph as
Arc<dyn AnyGraph>, so the suite is storage-independent above the storage. Inside this repository
GRAPHERSAL_TEST_STORAGE=forwarding runs it on the Forwarding storage of this crate (see
TinkerPop Compliance). A storage in another crate cannot run it yet: the
harness lives inside the library's integration tests and would have to move into a library-like
crate that does not depend on test-only paths. Until then such a storage follows the
Forwarding pattern: the same scripts on a
TraversalGraph and on the storage, results compared.
How a host plugs its storage into the DSL, the session and the Store: Custom Storages.