use super::ops;
fn ops_fixtures() -> Vec<(crate::LANG, &'static str)> {
vec![
#[cfg(feature = "rust")]
(
crate::LANG::Rust,
"fn caffè(zeta: u32) -> u32 { let αlpha = |b: u32| b * 2; αlpha(zeta) }\n",
),
#[cfg(feature = "python")]
(
crate::LANG::Python,
"def café(zeta):\n def ωmega(b):\n return b * 2\n return ωmega(zeta)\n",
),
#[cfg(feature = "cpp")]
(
crate::LANG::Cpp,
"int zeta(int q) { double μ = q + 1; return q - μ; }\n",
),
#[cfg(feature = "javascript")]
(
crate::LANG::Javascript,
"function caffè(z) { const ωf = (b) => b * 2; return ωf(z); }\n",
),
#[cfg(feature = "java")]
(
crate::LANG::Java,
"class Zêta { int q(int m) { long ωa = m + 1; return ωa > 2 ? m : 0; } }\n",
),
]
}
fn parse_ops(lang: crate::LANG, source: &str) -> ops::Ops {
crate::test_support::parse_named(lang, "fixture", source)
.ops()
.expect("ops walk must yield a top-level Ops")
}
#[test]
#[cfg(feature = "rust")]
fn borrowed_and_owned_ops_projections_serialize_alike() {
let fixtures = ops_fixtures();
crate::test_support::assert_fixtures_present(&fixtures);
for (lang, source) in fixtures {
let ops = parse_ops(lang, source);
let owned = ops.to_wire();
assert!(
!ops.spaces.is_empty() && ops.operands.iter().any(|o| !o.is_ascii()),
"{lang:?} fixture must nest a space and carry non-ASCII operand text: {ops:?}"
);
assert_eq!(
serde_json::to_string(&ops).expect("borrowed JSON"),
serde_json::to_string(&owned).expect("owned JSON"),
"{lang:?} JSON must not depend on the projection"
);
assert_eq!(
serde_yaml::to_string(&ops).expect("borrowed YAML"),
serde_yaml::to_string(&owned).expect("owned YAML"),
"{lang:?} YAML must not depend on the projection"
);
assert_eq!(
toml::to_string(&ops).expect("borrowed TOML"),
toml::to_string(&owned).expect("owned TOML"),
"{lang:?} TOML must not depend on the projection"
);
let (mut borrowed_cbor, mut owned_cbor) = (Vec::new(), Vec::new());
ciborium::into_writer(&ops, &mut borrowed_cbor).expect("borrowed CBOR");
ciborium::into_writer(&owned, &mut owned_cbor).expect("owned CBOR");
assert_eq!(
borrowed_cbor, owned_cbor,
"{lang:?} CBOR must not depend on the projection"
);
}
}
#[test]
#[cfg(feature = "rust")]
fn borrowed_and_owned_ops_projections_agree_on_the_optional_fields() {
let mut ops = parse_ops(crate::LANG::Rust, "fn f() { let a = 1 + 2; }\n");
ops.name = None;
ops.name_was_lossy = true;
let borrowed = serde_json::to_string(&ops).expect("borrowed JSON");
assert!(
borrowed.contains("\"name\":null") && borrowed.contains("\"name_was_lossy\":true"),
"both fields must be emitted for this test to compare anything: {borrowed}"
);
assert_eq!(
borrowed,
serde_json::to_string(&ops.to_wire()).expect("owned JSON"),
);
}
#[test]
#[cfg(feature = "rust")]
fn serializing_ops_builds_no_owned_projection() {
use super::tests::nested_functions;
use super::{MAX_SPACE_SERIALIZE_DEPTH, owned_ops_projections};
let ops = parse_ops(crate::LANG::Rust, "fn f() { fn g() { let a = 1 + 2; } }\n");
let before = owned_ops_projections::observed();
serde_json::to_string(&ops).expect("shallow tree serializes");
assert_eq!(
owned_ops_projections::observed(),
before,
"serializing must go through the borrowed projection"
);
let _ = ops.to_wire();
assert_eq!(
owned_ops_projections::observed(),
before + 1,
"`to_wire` is the caller-facing owned projection and must still build one"
);
let deep = parse_ops(
crate::LANG::Rust,
&nested_functions(MAX_SPACE_SERIALIZE_DEPTH + 1),
);
let before = owned_ops_projections::observed();
serde_json::to_string(&deep).expect_err("nesting past the limit must be refused");
assert_eq!(
owned_ops_projections::observed(),
before,
"a refused serialization must not have cloned the tree it refused"
);
}