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}