Skip to main content

fslite_conformance/
lib.rs

1//! Backend-agnostic conformance suite for [`fslite_core::FileSystem`]
2//! implementations.
3//!
4//! This crate does not duplicate a backend's own exhaustive test suite; it
5//! captures the canonical contract every implementation must satisfy, so a
6//! new backend can prove basic compliance by implementing
7//! [`ConformanceFactory`] and calling [`run_conformance`].
8
9mod attributes;
10mod batches;
11mod changes;
12mod directories;
13mod files;
14mod links;
15mod mutations;
16mod paths;
17mod search;
18mod security;
19mod trash;
20
21use fslite_core::{FileSystem, WorkspaceId};
22
23/// Constructs fresh, isolated backend instances and workspaces for one
24/// conformance case.
25///
26/// Workspace lifecycle (creating/naming a workspace) is backend-specific and
27/// intentionally not part of the canonical [`FileSystem`] contract, so it
28/// cannot be expressed generically over `dyn FileSystem`. Each conformance
29/// case instead calls [`fresh`](ConformanceFactory::fresh) to obtain a new
30/// backend and immediately calls
31/// [`workspace`](ConformanceFactory::workspace) on that same instance before
32/// calling `fresh` again for the next case; implementations may rely on
33/// this fresh-then-workspace pairing happening without interleaving (for
34/// example, by tracking the most recently created workspace in interior
35/// state rather than deriving it from the `fs` argument's identity).
36#[async_trait::async_trait]
37pub trait ConformanceFactory: Send + Sync {
38    /// Returns a new, empty backend instance.
39    async fn fresh(&self) -> Box<dyn FileSystem>;
40    /// Returns a workspace to use on the backend most recently returned by
41    /// [`fresh`](ConformanceFactory::fresh).
42    async fn workspace(&self, fs: &dyn FileSystem) -> WorkspaceId;
43}
44
45/// Runs every conformance case against `factory`, panicking on the first
46/// violated guarantee.
47pub async fn run_conformance(factory: &dyn ConformanceFactory) {
48    paths::run(factory).await;
49    directories::run(factory).await;
50    files::run(factory).await;
51    mutations::run(factory).await;
52    links::run(factory).await;
53    trash::run(factory).await;
54    attributes::run(factory).await;
55    batches::run(factory).await;
56    search::run(factory).await;
57    changes::run(factory).await;
58    security::run(factory).await;
59}