From 762f39b331e5ea11fdb2f072c88416b75b025b6d Mon Sep 17 00:00:00 2001 From: Janito Vaqueiro Ferreira Filho Date: Wed, 2 Aug 2023 12:18:51 +0000 Subject: [PATCH] Add roundtrip tests for some `hlist` types Make sure that they can be stored in memory and read from memory, and that they can be lowered into its flat layout and lifted back from it. Ensure that their internal element alignment is properly respected. --- .../src/type_traits/implementations/mod.rs | 2 + .../src/type_traits/implementations/tests.rs | 104 ++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 linera-witty/src/type_traits/implementations/tests.rs diff --git a/linera-witty/src/type_traits/implementations/mod.rs b/linera-witty/src/type_traits/implementations/mod.rs index 5e7785d50485..bd729252a2cf 100644 --- a/linera-witty/src/type_traits/implementations/mod.rs +++ b/linera-witty/src/type_traits/implementations/mod.rs @@ -6,3 +6,5 @@ mod custom_types; mod frunk; mod std; +#[cfg(test)] +mod tests; diff --git a/linera-witty/src/type_traits/implementations/tests.rs b/linera-witty/src/type_traits/implementations/tests.rs new file mode 100644 index 000000000000..24277c20f352 --- /dev/null +++ b/linera-witty/src/type_traits/implementations/tests.rs @@ -0,0 +1,104 @@ +// Copyright (c) Zefchain Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +//! Unit tests for implementations of the custom traits for existing types. + +use crate::{FakeInstance, InstanceWithMemory, Layout, WitLoad, WitStore}; +use frunk::hlist; +use std::fmt::Debug; + +/// Test roundtrip of a heterogeneous list that doesn't need any internal padding. +#[test] +fn hlist_without_padding() { + let input = hlist![ + 0x1011_1213_1415_1617_1819_1a1b_1c1d_1e1f_u128, + 0x2021_2223_2425_2627_i64, + 0x3031_3233_u32, + 0x4041_i16, + true, + ]; + + test_memory_roundtrip( + input, + &[ + 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, + 0x11, 0x10, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x33, 0x32, 0x31, 0x30, + 0x41, 0x40, 0x01, + ], + ); + test_flattening_roundtrip( + input, + hlist![ + 0x1819_1a1b_1c1d_1e1f_i64, + 0x1011_1213_1415_1617_i64, + 0x2021_2223_2425_2627_i64, + 0x3031_3233_i32, + 0x0000_4041_i32, + 0x0000_0001_i32, + ], + ); +} + +/// Test roundtrip of a heterogeneous list that needs internal padding between some of its elements. +#[test] +fn hlist_with_padding() { + let input = hlist![ + true, + 0x1011_i16, + 0x2021_u16, + 0x3031_3233_u32, + 0x4041_4243_4445_4647_i64, + ]; + + test_memory_roundtrip( + input, + &[ + 0x01, 0, 0x11, 0x10, 0x21, 0x20, 0, 0, 0x33, 0x32, 0x31, 0x30, 0, 0, 0, 0, 0x47, 0x46, + 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, + ], + ); + test_flattening_roundtrip( + input, + hlist![ + 0x0000_0001_i32, + 0x0000_1011_i32, + 0x0000_2021_i32, + 0x3031_3233_i32, + 0x4041_4243_4445_4647_i64, + ], + ); +} + +/// Test storing an instance of `T` to memory, checking that the `memory_data` bytes are correctly +/// written, and check that the instance can be loaded from those bytes. +fn test_memory_roundtrip(input: T, memory_data: &[u8]) +where + T: Debug + Eq + WitLoad + WitStore, +{ + let mut instance = FakeInstance::default(); + let mut memory = instance.memory().unwrap(); + let length = memory_data.len() as u32; + + let address = memory.allocate(length).unwrap(); + + input.store(&mut memory, address).unwrap(); + + assert_eq!(memory.read(address, length).unwrap(), memory_data); + assert_eq!(T::load(&memory, address).unwrap(), input); +} + +/// Test lowering an instance of `T`, checking that the resulting flat layout matches the expected +/// `flat_layout`, and check that the instance can be lifted from that flat layout. +fn test_flattening_roundtrip(input: T, flat_layout: ::Flat) +where + T: Debug + Eq + WitLoad + WitStore, + ::Flat: Debug + Eq, +{ + let mut instance = FakeInstance::default(); + let mut memory = instance.memory().unwrap(); + + let lowered_layout = input.lower(&mut memory).unwrap(); + + assert_eq!(lowered_layout, flat_layout); + assert_eq!(T::lift_from(lowered_layout, &memory).unwrap(), input); +}