diff --git a/.github/workflows/feature-matrix.yml b/.github/workflows/feature-matrix.yml index 6e96dc1f..46c0a7f2 100644 --- a/.github/workflows/feature-matrix.yml +++ b/.github/workflows/feature-matrix.yml @@ -30,7 +30,7 @@ jobs: # Common library usage pattern (issue #595): consumer enables # std + arc + rvm and relies on indexmap/std propagation. - name: library (std + arc + rvm) - features: std,arc,rvm + features: std,arc,rvm,test-utils # New default after removing mimalloc from full-opa. # Ensures all builtins compile without the allocator. @@ -45,12 +45,12 @@ jobs: # Selective builtins without full-opa: validates that popular # features can be cherry-picked independently. - name: cherry-picked builtins - features: std,arc,rvm,regex,time,semver,cache + features: std,arc,rvm,regex,time,semver,cache,test-utils # Observability features only: coverage + cache without the # heavier builtins (regex, time, etc.). - name: observability - features: std,arc,rvm,coverage,cache + features: std,arc,rvm,coverage,cache,test-utils # Azure Policy adds jsonschema + dashmap; test it compiles # and runs on top of full-opa. diff --git a/Cargo.toml b/Cargo.toml index ac9b210c..20bb2c28 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,6 +48,7 @@ time = ["dep:chrono", "dep:chrono-tz"] uuid = ["dep:uuid"] urlquery = ["dep:url"] yaml = ["serde_yaml"] +test-utils = [] full-opa = [ "base64", "base64url", diff --git a/src/lib.rs b/src/lib.rs index 0056fa0b..057e000c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -152,7 +152,7 @@ mod scheduler; mod schema; #[cfg(feature = "azure_policy")] pub mod target; -#[cfg(any(test, all(feature = "yaml", feature = "std")))] +#[cfg(any(test, feature = "test-utils", all(feature = "yaml", feature = "std")))] pub mod test_utils; pub mod utils; mod value; diff --git a/src/test_utils.rs b/src/test_utils.rs index 34c465f3..859c5bbe 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -93,9 +93,9 @@ pub fn process_value(v: &Value) -> Result { /// Diff-friendly equality helper used by multiple YAML suites. pub fn match_values(computed: &Value, expected: &Value) -> Result<()> { if computed != expected { - let expected_yaml = serde_yaml::to_string(expected)?; - let computed_yaml = serde_yaml::to_string(computed)?; - bail!("expected:\n{}computed:\n{}", expected_yaml, computed_yaml); + let expected_str = serde_json::to_string_pretty(expected)?; + let computed_str = serde_json::to_string_pretty(computed)?; + bail!("expected:\n{expected_str}\ncomputed:\n{computed_str}"); } Ok(()) } diff --git a/src/tests/interpreter/mod.rs b/src/tests/interpreter/mod.rs index 9b88180c..82e2277b 100644 --- a/src/tests/interpreter/mod.rs +++ b/src/tests/interpreter/mod.rs @@ -611,6 +611,61 @@ fn yaml_test_impl(file: &str) -> Result<()> { } } } + #[cfg(not(feature = "time"))] + { + let skip = [ + "add_date.yaml", + "date.yaml", + "clock.yaml", + "diff.yaml", + "format.yaml", + "now_ns.yaml", + "parse_duration_ns.yaml", + "parse_ns.yaml", + "parse_rfc3339_ns.yaml", + "weekday.yaml", + ]; + for s in skip { + if file.contains(s) { + std::println!("skipped {file} without time feature."); + return Ok(()); + } + } + } + #[cfg(not(feature = "semver"))] + { + let skip = ["semver/compare.yaml", "semver/is_valid.yaml"]; + for s in skip { + if file.contains(s) { + std::println!("skipped {file} without semver feature."); + return Ok(()); + } + } + } + #[cfg(not(feature = "glob"))] + { + if file.contains("globmatch.yaml") { + std::println!("skipped {file} without glob feature."); + return Ok(()); + } + } + #[cfg(not(feature = "uuid"))] + { + let skip = ["uuid/generate.yaml", "uuid/parse.yaml"]; + for s in skip { + if file.contains(s) { + std::println!("skipped {file} without uuid feature."); + return Ok(()); + } + } + } + #[cfg(not(feature = "regex"))] + { + if file.contains("regex/") { + std::println!("skipped {file} without regex feature."); + return Ok(()); + } + } #[cfg(not(feature = "graph"))] { // Skip tests that depend on graph builtin that need graph feature.