Skip to main content

Crate faucet_conformance

Crate faucet_conformance 

Source
Expand description

§faucet-conformance

A reusable test battery that any faucet connector can call from its own tests/ to prove it upholds the connector contract. Passing this battery is the Tier-1 criterion for a connector — there is no separate tiering scheme; a connector is “supported” exactly when it invokes and passes these checks in CI.

use faucet_conformance as conf;
let source = /* your Source */
conf::assert_config_schema_valid(&source);
conf::assert_bounded_memory(&source, 100, 1000).await;

The core contract checks:

  1. assert_config_schema_valid — the config schema is a valid JSON Schema.
  2. assert_bounded_memory — the source pages instead of buffering.
  3. assert_bookmark_roundtrip — an incremental source resumes from its bookmark rather than restarting.
  4. assert_idempotent_replay — re-delivering committed rows leaves no duplicates (atomic-watermark or keyed-upsert mechanism).
  5. assert_capabilities_truthful — advertised capabilities match real behaviour.
  6. assert_errors_not_panics — failures surface as a typed faucet_core::FaucetError, never a panic.

Capability-demonstration checks — each proves a connector that advertises a capability actually demonstrates it: 7. assert_write_modes_truthful — a sink advertising Upsert/Delete genuinely converges by key and removes on delete, and missing/null keys are reported as failed rather than silently written. 8. assert_schema_evolution_effective — an evolvable sink’s evolve_schema makes the added column appear in a fresh current_schema(). 9. assert_batch_size_zero_single_page — a source built with batch_size = 0 yields the whole result set as one page. 10. assert_connector_name_nonemptyconnector_name() is non-empty (an empty name becomes the "unknown" metric label). 11. assert_preflight_check_wellformedcheck() returns Ok(CheckReport) with well-formed probes; a probe failure is a Fail probe, not an Err.

Each check has both a passing and a #[should_panic] failing test in this crate — a check that cannot fail is worthless.

Modules§

doubles
Synthetic Source / Sink doubles the battery drives (and that connector authors can reuse in their own tests).

Traits§

HasConfigSchema
Anything that can expose a config JSON Schema + a label — blanket-implemented for every Source so assert_config_schema_valid accepts a source directly. (Sinks can be checked via assert_config_schema_valid_value.)

Functions§

assert_batch_size_zero_single_page
Check 9. Drive a source built with batch_size = 0 and assert it yields the entire result set as a single StreamPage — the documented “no batching” sentinel (small lookup tables, sinks that prefer one large request).
assert_bookmark_roundtrip
Check 3. Drive an incremental source to completion, capture the bookmark it emits, feed it back via apply_start_bookmark, and assert the second run resumes after that point — strictly fewer records reappear (zero for a fully-consumed static source).
assert_bounded_memory
Check 2. Drive stream_pages over a source that yields total records and assert the consumer never holds more than ~batch_size records live at once (i.e. the source pages instead of buffering everything).
assert_capabilities_truthful
Check 5. Assert a sink’s advertised capabilities match real behaviour:
assert_config_schema_valid
Check 1. Assert the connector’s config_schema() is a structurally valid JSON Schema that round-trips through serde_json.
assert_config_schema_valid_value
The value-level core of assert_config_schema_valid — usable for sinks: assert_config_schema_valid_value(&sink.config_schema(), sink.connector_name()).
assert_connector_name_nonempty
Check 10. Assert a source’s connector_name is a non-empty string. An empty name is a cardinality-rule violation — the observability layer falls back to the "unknown" metric label, silently merging distinct connectors’ metrics.
assert_connector_name_nonempty_value
The value-level core of assert_connector_name_nonempty — usable for sinks.
assert_errors_not_panics
Check 6. Drive a source configured to fail (unreachable endpoint / bad config) and assert it surfaces a typed faucet_core::FaucetError without unwinding. Catches any panic and re-raises it as a check failure, so a connector that unwrap()s on bad input is caught rather than crashing the test process silently.
assert_idempotent_replay
Check 4. Assert re-delivering already-committed rows leaves no duplicates in the destination — the trust-critical effectively-once check.
assert_preflight_check_wellformed
Check 11. Assert a source’s check returns Ok(CheckReport) with at least one well-formed probe (non-empty name; a Fail/Skip probe carries a non-empty reason). A connector must surface a probe failure as a ProbeStatus::Fail inside Ok(report), never as an Err from check() (an Err means “no probe could run at all”, which faucet doctor renders differently).
assert_schema_evolution_effective
Check 8. For a sink advertising supports_schema_evolution: read current_schema, apply a real add-column SchemaEvolution via evolve_schema, and assert the new column appears in a fresh current_schema(). Stronger than assert_capabilities_truthful, which only checks a no-op evolve does not error.
assert_sink_preflight_check_wellformed
The sink counterpart of assert_preflight_check_wellformed.
assert_write_modes_truthful
Check 7. Assert a sink advertising Upsert/Delete in supported_write_modes genuinely upholds those modes: