linera_witty/
test.rs

1// Copyright (c) Zefchain Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4//! Functions and types useful for writing tests.
5
6use std::{collections::BTreeMap, fmt::Debug};
7
8use crate::{
9    wit_generation::WitInterface, InstanceWithMemory, Layout, MockInstance, RegisterWitTypes,
10    WitLoad, WitStore,
11};
12
13/// Test storing an instance of `T` to memory, checking that the instance can be loaded from those
14/// bytes.
15///
16/// Also checks if storing the loaded instance results in exactly the same bytes in
17/// memory.
18pub fn test_memory_roundtrip<T>(input: &T) -> anyhow::Result<()>
19where
20    T: Debug + Eq + WitLoad + WitStore,
21{
22    let mut first_instance = MockInstance::<()>::default();
23    let mut first_memory = first_instance.memory()?;
24
25    let first_address = first_memory.allocate(T::SIZE, <T::Layout as Layout>::ALIGNMENT)?;
26
27    input.store(&mut first_memory, first_address)?;
28
29    let loaded_instance = T::load(&first_memory, first_address)?;
30
31    assert_eq!(&loaded_instance, input);
32
33    // Create a clean separate memory instance
34    let mut second_instance = MockInstance::<()>::default();
35    let mut second_memory = second_instance.memory()?;
36
37    let second_address = second_memory.allocate(T::SIZE, <T::Layout as Layout>::ALIGNMENT)?;
38
39    loaded_instance.store(&mut second_memory, second_address)?;
40
41    let total_allocated_memory = first_memory.allocate(0, 1)?.0;
42
43    assert_eq!(
44        first_memory.read(first_address, total_allocated_memory)?,
45        second_memory.read(second_address, total_allocated_memory)?
46    );
47
48    Ok(())
49}
50
51/// Test lowering an instance of `T`, checking that the resulting flat layout matches the expected
52/// `flat_layout`, and check that the instance can be lifted from that flat layout.
53pub fn test_flattening_roundtrip<T>(input: &T) -> anyhow::Result<()>
54where
55    T: Debug + Eq + WitLoad + WitStore,
56    <T::Layout as Layout>::Flat: Copy + Debug + Eq,
57{
58    let mut first_instance = MockInstance::<()>::default();
59    let mut first_memory = first_instance.memory()?;
60    let first_start_address = first_memory.allocate(0, 1)?;
61
62    let first_lowered_layout = input.lower(&mut first_memory)?;
63    let lifted_instance = T::lift_from(first_lowered_layout, &first_memory)?;
64
65    assert_eq!(&lifted_instance, input);
66
67    // Create a clean separate memory instance
68    let mut second_instance = MockInstance::<()>::default();
69    let mut second_memory = second_instance.memory()?;
70    let second_start_address = second_memory.allocate(0, 1)?;
71
72    let second_lowered_layout = lifted_instance.lower(&mut second_memory)?;
73
74    assert_eq!(first_lowered_layout, second_lowered_layout);
75
76    let total_allocated_memory = first_memory.allocate(0, 1)?.0;
77
78    assert_eq!(
79        first_memory.read(first_start_address, total_allocated_memory)?,
80        second_memory.read(second_start_address, total_allocated_memory)?
81    );
82
83    Ok(())
84}
85
86/// Asserts that the WIT type dependencies of the `Interface` are the `expected_types`.
87pub fn assert_interface_dependencies<'i, Interface>(
88    expected_types: impl IntoIterator<Item = (&'i str, &'i str)>,
89) where
90    Interface: WitInterface,
91{
92    let mut wit_types = BTreeMap::new();
93
94    Interface::Dependencies::register_wit_types(&mut wit_types);
95
96    assert_eq!(
97        wit_types
98            .iter()
99            .map(|(name, declaration)| (name.as_str(), declaration.as_str()))
100            .collect::<Vec<_>>(),
101        expected_types.into_iter().collect::<Vec<_>>(),
102    );
103}
104
105/// Asserts that the function declarations of the `Interface` are the `expected_declarations`.
106pub fn assert_interface_functions<Interface>(expected_declarations: &[impl AsRef<str>])
107where
108    Interface: WitInterface,
109{
110    let wit_functions = Interface::wit_functions();
111
112    assert_eq!(
113        wit_functions.iter().map(String::as_str).collect::<Vec<_>>(),
114        expected_declarations
115            .iter()
116            .map(AsRef::as_ref)
117            .collect::<Vec<_>>()
118    );
119}