//! `loopd` holds no credentials, so no build of it enables `bxcore`'s feature `secrets` (M5b spec, //! section 5), and its binary does not contain the code that reads them. Three manifests decide //! that: `loopd`'s own, the workspace's entry for `bxcore`, and `bxcore`'s feature table. They are //! parsed, so every spelling TOML allows is read. `make gate` builds the workspace with the feature //! on (for `gatewayd`), so it cannot see a module that is not behind the feature; the last test //! checks that line of `bxcore`'s `lib.rs`. Do not edit. use std::path::{Path, PathBuf}; fn manifest(path: &Path) -> toml::Table { let text = std::fs::read_to_string(path) .unwrap_or_else(|e| panic!("cannot read {}: {e}", path.display())); text.parse::() .unwrap_or_else(|e| panic!("cannot parse {}: {e}", path.display())) } fn crates() -> PathBuf { Path::new(env!("CARGO_MANIFEST_DIR")).join("..") } /// Every string in `value`, at any depth, that turns the feature on: `secrets`, `bxcore/secrets` /// or `bxcore?/secrets`. fn enabling(value: &toml::Value, found: &mut Vec) { match value { toml::Value::String(s) if s == "secrets" || s.ends_with("/secrets") => { found.push(s.clone()) } toml::Value::Array(items) => items.iter().for_each(|v| enabling(v, found)), toml::Value::Table(table) => table.values().for_each(|v| enabling(v, found)), _ => {} } } #[test] fn loopd_never_names_the_feature() { let path = Path::new(env!("CARGO_MANIFEST_DIR")).join("Cargo.toml"); let table = manifest(&path); assert!(table.contains_key("dependencies"), "{}", path.display()); let mut found = Vec::new(); enabling(&toml::Value::Table(table), &mut found); assert!(found.is_empty(), "{} enables {found:?}", path.display()); } #[test] fn the_workspace_entry_for_bxcore_enables_nothing() { let path = crates().join("../Cargo.toml"); let table = manifest(&path); let entry = table .get("workspace") .and_then(|w| w.get("dependencies")) .and_then(|d| d.get("bxcore")) .unwrap_or_else(|| panic!("{}: no [workspace.dependencies] bxcore", path.display())); assert_eq!(entry.get("features"), None, "{entry:?}"); } #[test] fn only_the_feature_itself_turns_the_store_on() { let path = crates().join("bxcore/Cargo.toml"); let table = manifest(&path); let features = table .get("features") .and_then(toml::Value::as_table) .unwrap_or_else(|| panic!("{}: no [features]", path.display())); assert!(features.contains_key("secrets"), "{features:?}"); for (name, list) in features { if name == "secrets" { continue; } let mut found = Vec::new(); enabling(list, &mut found); assert!(found.is_empty(), "feature {name} turns on {found:?}"); } let zeroize = table .get("dependencies") .and_then(|d| d.get("zeroize")) .unwrap_or_else(|| panic!("{}: no zeroize", path.display())); assert_eq!( zeroize.get("optional").and_then(toml::Value::as_bool), Some(true), "zeroize is built only with the feature" ); } #[test] fn the_module_is_compiled_only_with_the_feature() { let path = crates().join("bxcore/src/lib.rs"); let text = std::fs::read_to_string(&path) .unwrap_or_else(|e| panic!("cannot read {}: {e}", path.display())); assert!( text.contains("#[cfg(feature = \"secrets\")]\npub mod secrets;\n"), "{}: `pub mod secrets;` must follow `#[cfg(feature = \"secrets\")]`", path.display() ); assert_eq!(text.matches("mod secrets").count(), 1, "{}", path.display()); }