#[allow(deprecated)]
use super::*;
use vyre::ir::Node;
fn write_words(out: &mut Vec<u8>, words: &[u32]) {
out.clear();
for word in words {
out.extend_from_slice(&word.to_le_bytes());
}
}
fn read_word(bytes: &[u8], index: usize) -> u32 {
let start = index * 4;
let mut word = [0; 4];
word.copy_from_slice(&bytes[start..start + 4]);
u32::from_le_bytes(word)
}
#[test]
fn summarize_function_emits_program_with_op_id() {
let p = summarize_function_with_count("ast", "cg", "cached", "out", 64);
let has_region = p.entry().iter().any(|n| {
matches!(
n,
Node::Region { generator, .. } if generator.as_str() == OP_ID
)
});
assert!(
has_region,
"weir::summary: Program body must contain a Region tagged `{OP_ID}`"
);
}
#[test]
fn summarize_function_declares_four_buffers() {
let p = summarize_function_with_count("ast", "cg", "cached", "out", 64);
assert_eq!(
p.buffers().len(),
4,
"weir::summary: Program must declare exactly 4 buffers (ast, cg, cached, out)"
);
}
#[test]
fn summarize_function_buffer_widths_match_bit_count() {
let p = summarize_function_with_count("ast", "cg", "cached", "out", 64);
for buf in p.buffers() {
assert_eq!(
buf.count(),
2,
"weir::summary: buffer `{}` must have count=2 for 64 bits",
buf.name()
);
}
}
#[test]
fn summarize_function_zero_bits_minimum_one_word() {
let p = summarize_function_with_count("ast", "cg", "cached", "out", 0);
for buf in p.buffers() {
assert_eq!(
buf.count(),
1,
"weir::summary: zero bits → 1-word floor (.max(1))"
);
}
}
#[test]
fn summary_soundness_is_mayover() {
use super::super::soundness::SoundnessTagged;
assert_eq!(
Summary.soundness(),
super::super::soundness::Soundness::MayOver,
"weir::summary: bottom-up summaries inherit MayOver from their constituent primitives"
);
}
#[test]
fn summarize_function_rejects_out_of_domain_input_tail_bits() {
let err = summarize_function_borrowed_via(
&|_, _, _| unreachable!("validation must reject before dispatch"),
&[0b1000],
&[0],
&[0],
3,
)
.expect_err("tail bit outside bit_count must be rejected");
assert!(
err.contains("outside the declared domain"),
"unexpected diagnostic: {err}"
);
}
#[test]
fn summarize_function_rejects_out_of_domain_output_tail_bits() {
let err = summarize_function_borrowed_via(
&|_, _, _| Ok(vec![0b1000u32.to_le_bytes().to_vec()]),
&[0],
&[0],
&[0],
3,
)
.expect_err("backend output tail bit outside bit_count must be rejected");
assert!(
err.contains("outside the declared domain"),
"unexpected diagnostic: {err}"
);
}
#[test]
fn summarize_function_into_reuses_caller_output_slot() {
use std::cell::Cell;
let mut outputs = vec![Vec::with_capacity(16)];
let outputs_addr = outputs.as_ptr() as usize;
let slot_addr = outputs[0].as_ptr() as usize;
let observed = Cell::new(false);
let out = summarize_function_borrowed_into_via(
&|_, inputs, grid, outputs| {
assert_eq!(grid, Some([1, 1, 1]));
assert_eq!(inputs.len(), 4);
assert_eq!(outputs.len(), 1);
assert_eq!(outputs.as_ptr() as usize, outputs_addr);
assert_eq!(outputs[0].as_ptr() as usize, slot_addr);
let ast = read_word(inputs[0], 0);
let callgraph = read_word(inputs[1], 0);
let cached = read_word(inputs[2], 0);
write_words(&mut outputs[0], &[ast | callgraph | cached]);
assert_eq!(outputs[0].as_ptr() as usize, slot_addr);
observed.set(true);
Ok(())
},
&[0b001],
&[0b010],
&[0b100],
3,
&mut outputs,
)
.expect("caller-owned output scratch should decode");
assert!(observed.get());
assert_eq!(out, vec![0b111]);
assert_eq!(outputs.len(), 1);
assert_eq!(outputs.as_ptr() as usize, outputs_addr);
assert_eq!(outputs[0].as_ptr() as usize, slot_addr);
}
#[test]
fn summarize_function_with_scratch_reuses_staging_and_output_slots() {
let mut scratch = SummarizeFunctionScratch::default();
let dispatch = |_: &vyre::ir::Program,
inputs: &[&[u8]],
_: Option<[u32; 3]>|
-> Result<Vec<Vec<u8>>, String> {
let ast = read_word(inputs[0], 0);
let callgraph = read_word(inputs[1], 0);
let cached = read_word(inputs[2], 0);
let mut out = Vec::with_capacity(64);
write_words(&mut out, &[ast | callgraph | cached]);
Ok(vec![out])
};
let first = summarize_function_borrowed_with_scratch_via(
&dispatch,
&[0b001],
&[0b010],
&[0b100],
3,
&mut scratch,
)
.expect("first scratch-backed summary should decode");
assert_eq!(first, vec![0b111]);
let ast_capacity = scratch.ast_bytes.capacity();
let callgraph_capacity = scratch.callgraph_bytes.capacity();
let cached_capacity = scratch.cached_summary_bytes.capacity();
let out_capacity = scratch.out_bytes.capacity();
let outputs_addr = scratch.outputs.as_ptr() as usize;
let slot_addr = scratch.outputs[0].as_ptr() as usize;
let second = summarize_function_borrowed_with_scratch_via(
&dispatch,
&[0b001],
&[0b000],
&[0b100],
3,
&mut scratch,
)
.expect("second scratch-backed summary should decode");
assert_eq!(second, vec![0b101]);
assert_eq!(scratch.ast_bytes.capacity(), ast_capacity);
assert_eq!(scratch.callgraph_bytes.capacity(), callgraph_capacity);
assert_eq!(scratch.cached_summary_bytes.capacity(), cached_capacity);
assert_eq!(scratch.out_bytes.capacity(), out_capacity);
assert_eq!(scratch.outputs.as_ptr() as usize, outputs_addr);
assert_eq!(scratch.outputs[0].as_ptr() as usize, slot_addr);
}
#[test]
fn summarize_function_into_result_with_scratch_reuses_decoded_result() {
let mut scratch = SummarizeFunctionScratch::default();
let mut result = Vec::with_capacity(4);
let result_addr = result.as_ptr() as usize;
let dispatch = |_: &vyre::ir::Program,
inputs: &[&[u8]],
_: Option<[u32; 3]>|
-> Result<Vec<Vec<u8>>, String> {
let ast = read_word(inputs[0], 0);
let callgraph = read_word(inputs[1], 0);
let cached = read_word(inputs[2], 0);
let mut out = Vec::with_capacity(64);
write_words(&mut out, &[ast | callgraph | cached]);
Ok(vec![out])
};
summarize_function_borrowed_into_result_with_scratch_via(
&dispatch,
&[0b001],
&[0b010],
&[0b100],
3,
&mut scratch,
&mut result,
)
.expect("first decoded-result scratch summary should decode");
assert_eq!(result, vec![0b111]);
assert_eq!(result.as_ptr() as usize, result_addr);
summarize_function_borrowed_into_result_with_scratch_via(
&dispatch,
&[0b001],
&[0b000],
&[0b100],
3,
&mut scratch,
&mut result,
)
.expect("second decoded-result scratch summary should decode");
assert_eq!(result, vec![0b101]);
assert_eq!(result.as_ptr() as usize, result_addr);
}