use crate::core::config::e2e::{ArgMapping, CallConfig};
use crate::core::ir::{FieldDef, TypeDef, TypeRef};
use crate::e2e::fixture::Fixture;
const DIAMOND_LEVELS: u32 = 12;
const GRAPH_DEFINITIONS: usize = 3 * DIAMOND_LEVELS as usize + 1;
const UNMEMOIZED_NAMED_RESOLUTIONS: usize = 2usize.pow(DIAMOND_LEVELS + 2) - 3;
const MEMOIZED_NAMED_RESOLUTIONS: usize = 4 * DIAMOND_LEVELS as usize + 1;
const SHORT_CIRCUIT_NAMED_RESOLUTIONS: usize = 2 * DIAMOND_LEVELS as usize + 1;
const _: () = assert!(
MEMOIZED_NAMED_RESOLUTIONS * 300 < UNMEMOIZED_NAMED_RESOLUTIONS,
"the diamond chain must be wide enough that memoization changes the complexity class"
);
fn root_arg() -> ArgMapping {
ArgMapping {
name: "request".into(),
field: "input".into(),
arg_type: "json_object".into(),
optional: false,
owned: true,
element_type: Some("Level0".into()),
go_type: None,
vec_inner_is_ref: false,
trait_name: None,
}
}
fn level_name(level: u32) -> String {
if level == DIAMOND_LEVELS {
"SampleLeaf".to_string()
} else {
format!("Level{level}")
}
}
fn flattened_field(name: &str, target: &str) -> FieldDef {
FieldDef {
name: name.into(),
ty: TypeRef::Named(target.into()),
serde_flatten: true,
..Default::default()
}
}
fn diamond_chain_types() -> Vec<TypeDef> {
let mut types = Vec::with_capacity(GRAPH_DEFINITIONS);
for level in 0..DIAMOND_LEVELS {
let left = format!("LeftBridge{level}");
let right = format!("RightBridge{level}");
let next = level_name(level + 1);
types.push(TypeDef {
name: level_name(level),
fields: vec![flattened_field("left", &left), flattened_field("right", &right)],
..Default::default()
});
types.push(TypeDef {
name: left,
fields: vec![flattened_field("down", &next)],
..Default::default()
});
types.push(TypeDef {
name: right,
fields: vec![flattened_field("down", &next)],
..Default::default()
});
}
types.push(TypeDef {
name: "SampleLeaf".into(),
fields: vec![FieldDef {
name: "content".into(),
ty: TypeRef::Bytes,
..Default::default()
}],
..Default::default()
});
types
}
fn scan(content: &str) -> (bool, usize) {
let fixture = Fixture {
input: serde_json::json!({ "content": content }),
..Default::default()
};
let call = CallConfig {
args: vec![root_arg()],
..Default::default()
};
let types = diamond_chain_types();
assert_eq!(
types.len(),
GRAPH_DEFINITIONS,
"the fixture graph must actually be wide -- a smaller graph would make the count bound vacuous"
);
let index = super::build_named_index(&types, &[]);
super::scan_fixture(&index, &fixture, &call)
}
#[test]
fn wide_flatten_diamond_chain_enters_named_resolution_a_linear_number_of_times() {
let (found, named_resolutions) = scan("inline text");
assert!(!found, "inline leaf bytes are not a document path");
assert_eq!(
named_resolutions, MEMOIZED_NAMED_RESOLUTIONS,
"each (value, name) pair must be computed once and every further edge served from the memo"
);
}
#[test]
fn memoized_wide_diamond_chain_still_finds_the_leaf_document_path() {
let (found, named_resolutions) = scan("documents/sample.bin");
assert!(
found,
"the leaf document path must still be reached through 12 flattened diamonds"
);
assert_eq!(named_resolutions, SHORT_CIRCUIT_NAMED_RESOLUTIONS);
}