Laws selected by capability.
An adapter's harness says what it can make by implementing the fixture trait of each capability it has
(MemoryFixture, JournalFixture, ...); [Suite] then offers exactly the law sets of those capabilities.
A law set for a capability the harness has no fixture for is not skipped, it cannot be selected: the method
that would select it does not apply to the harness, and the compiler says which fixture is missing.
The fixture traits sit beside the Has… capability traits of whiskers-ports and mirror them: a capability
the service can be given (HasJournal) has a fixture the suite can be given (JournalFixture). A
harness for a whole adapter implements [Fixtures], which [Suite::complete] runs in full.
Capabilities with no fixture here have no law yet: the embedder and the thinker are held to nothing a
conformance run can show without calling out (what a real model server says back is the adapter's own
test), and Secrets is not served by a route; its laws are suite::secrets.
16use whiskers_ports::{Allowance, ChatHub, Clock, HouseholdHub, Journal, Judge, MemoryHub, PictureShelf, Voice};
A new, empty port of this capability.
27 fn fresh(&self) -> Self::Port;
The same port after its process restarted: it must find what it kept.
34stateful_fixture!(
How to make, and restart, the memory hub (capability HasMemory).
How to make, and restart, the household hub (capability HasHousehold).
How to make, and restart, the chat hub (capability HasChat).
How to make, and restart, the journal (capability HasJournal).
How to make, and restart, the picture shelf (capability HasPictures).
How to make, and restart, the allowance (capability HasAllowance).
How to make a chat hub whose storage can be told to refuse writes, as a full disk would. Not every harness can (a black box over HTTP cannot), so the law that needs it is selected apart from the chat hub's others.
A new chat hub and the switch that makes its storage refuse writes (true) or take them again.
64 fn fresh_refusing(&self) -> (Self::Port, WriteSwitch);
The same hub after a restart, its storage working again.
A judge with nothing to call with (capability HasJudge).
A voice with nothing to call with (capability HasVoice). The law that has it speak, which a paid voice
runs only when its operator agrees to the spend, is suite::timing::speaks_timed, called on purpose.
A clock (capability HasClock).
A harness for a whole adapter: a fixture for every capability there is a law for.
The capabilities whose laws a [Suite] has run, by name, in the order run.
109pub type Ran = Vec<&'static str>;
A harness, and the laws chosen for it so far. Every method runs the laws of one capability, and applies only to a harness with that capability's fixture. A harness with the memory hub and nothing else can run the memory hub's laws:
use whiskers_conformance::memory::MemMemoryHub;
use whiskers_conformance::suite::fixture::{MemoryFixture, Suite};
struct OnlyMemory;
impl MemoryFixture for OnlyMemory {
type Port = MemMemoryHub;
fn fresh(&self) -> MemMemoryHub { MemMemoryHub::default() }
fn restart(&self, port: MemMemoryHub) -> MemMemoryHub { port }
}
let suite = Suite::new(OnlyMemory).memory();
assert_eq!(suite.ran(), ["memory"]);
It cannot select the journal's laws. They are not skipped, there is no way to ask for them:
use whiskers_conformance::memory::MemMemoryHub;
use whiskers_conformance::suite::fixture::{MemoryFixture, Suite};
struct OnlyMemory;
impl MemoryFixture for OnlyMemory {
type Port = MemMemoryHub;
fn fresh(&self) -> MemMemoryHub { MemMemoryHub::default() }
fn restart(&self, port: MemMemoryHub) -> MemMemoryHub { port }
}
// error[E0277]: the trait bound `OnlyMemory: JournalFixture` is not satisfied
let _ = Suite::new(OnlyMemory).memory().journal();
151impl<F> Suite<F> {
A suite that has run nothing.
The memory hub's laws.
The household hub's laws.
The chat hub's laws, all but the one that needs its storage to fail ([Suite::chat_write_faults]).
The chat-hub law that a copy that cannot be kept is an error and changes nothing.
193 pub fn chat_write_faults(mut self) -> Self 194 where 195 F: ChatFaultFixture, 196 { 197 hubs::chat_a_copy_that_cannot_be_kept_is_an_error_and_changes_nothing( 198 &|| ChatFaultFixture::fresh_refusing(&self.fixture), 199 &|p| ChatFaultFixture::restart_refusing(&self.fixture, p), 200 ); 201 self.ran.push("chat write faults"); 202 self 203 }
The journal's laws.
The picture shelf's laws.
The allowance's laws.
What a judge with no credentials does.
What a voice with no credentials does.
The clock's laws.