cc_lb_plugin_conformance/lib.rs
1//! In-process conformance scaffolding for cc-lb plugin authors.
2//!
3//! This crate exposes protocol-layer wrappers, plugin-kind verifier entry points,
4//! and test fixture helpers for compiled WebAssembly plugins targeting cc-lb.
5//!
6//! # Supported Plugin Kinds
7//!
8//! The conformance suite supports testing the following plugin types:
9//!
10//! * **Router Plugins**: Plugins that route requests to different upstreams.
11//! * **Shape Plugins**: Plugins that transform request and response shapes.
12//! * **Observability Plugins**: Plugins that monitor and log request metrics.
13//!
14//! Signer plugins are **not** supported in the 0.1.x release series.
15//!
16//! # Quick-Start Example
17//!
18//! Here is a complete example of how to write conformance tests for your plugin.
19//! This example assumes you have compiled your plugin to a WebAssembly binary and
20//! made it available to your tests.
21//!
22//! ```rust,ignore
23//! use cc_lb_plugin_conformance::{handshake, self_check, dispatch::PluginSession, fixtures};
24//!
25//! const WASM: &[u8] = include_bytes!(env!("CARGO_CDYLIB_FILE_MY_CC_LB_PLUGIN"));
26//!
27//! #[test]
28//! fn handshake_negotiates_shape_v1() {
29//! let report = handshake::run(WASM).unwrap();
30//! assert_eq!(report.chosen_versions["shape"], 1);
31//! assert_eq!(report.identity.name, "my-plugin");
32//! }
33//!
34//! #[test]
35//! fn self_check_clean() {
36//! let report = self_check::run(WASM).unwrap();
37//! assert!(matches!(report.status, self_check::SelfCheckStatus::Success));
38//! assert!(report.failures.is_empty());
39//! }
40//!
41//! #[test]
42//! fn shape_round_trip_basic() {
43//! use cc_lb_plugin_conformance::prelude::*;
44//! let mut session = PluginSession::new(WASM).unwrap();
45//! let req = fixtures::shape_request_builder()
46//! .method("POST")
47//! .path("/v1/messages")
48//! .body_base64("eyJ0ZXN0IjoxfQ==")
49//! .build();
50//! let outcome = session.dispatch::<cc_lb_plugin_wire::wire_function::ShapeFn>(req).unwrap();
51//! let cc_lb_plugin_conformance::dispatch::DispatchOutcome::Ok(resp) = outcome else {
52//! panic!("shape returned Fallback");
53//! };
54//! assert_eq!(resp.url, "https://api.anthropic.com/v1/messages");
55//! }
56//! ```
57//!
58//! # SemVer Policy
59//!
60//! This crate follows the same 0.1.x to 0.2.x cadence as the other plugin-author SDK crates.
61//! All public structs and enums are marked `#[non_exhaustive]` to allow future additions.
62//! Error `reason` string fields are diagnostics and are not part of the stable SemVer contract.
63//! Callers should match on enum variants instead of asserting on exact error text.
64//!
65//! # Compile-Cost Note
66//!
67//! This crate depends on the Extism and Wasmtime runtimes.
68//! Transitive compilation of these dependencies can take about 5 to 10 minutes for a cold build.
69//!
70//! # CI Smoke Note
71//!
72//! The CI smoke tests for this crate are Linux-only.
73
74#![forbid(unsafe_code)]
75
76#[cfg(feature = "dispatch")]
77pub mod dispatch;
78mod errors;
79pub mod fixtures;
80pub mod handshake;
81pub mod identity;
82pub mod prelude;
83pub mod self_check;
84#[cfg(feature = "dispatch")]
85pub mod verify;
86
87pub use errors::{ExtraInfo, LayerResult, VerifyError, VerifyReport};
88#[cfg(feature = "dispatch")]
89pub use verify::{
90 verify_observability_plugin, verify_observability_plugin_with_caps, verify_router_plugin,
91 verify_router_plugin_with_caps, verify_shape_plugin, verify_shape_plugin_with_caps,
92};