From 41008544880769f3813ab3bffb631a277ab7e5a7 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 29 Apr 2023 20:32:47 +0000 Subject: [PATCH] Move compare_obj_to_small test next to similar tests --- soroban-env-host/src/host/comparison.rs | 170 ++++++++++++++++++++++++ soroban-env-host/src/test.rs | 1 - soroban-env-host/src/test/comparison.rs | 170 ------------------------ 3 files changed, 170 insertions(+), 171 deletions(-) delete mode 100644 soroban-env-host/src/test/comparison.rs diff --git a/soroban-env-host/src/host/comparison.rs b/soroban-env-host/src/host/comparison.rs index 957cac8be..5b8626407 100644 --- a/soroban-env-host/src/host/comparison.rs +++ b/soroban-env-host/src/host/comparison.rs @@ -383,6 +383,9 @@ impl Compare for Budget { #[cfg(test)] mod tests { use super::*; + use crate::xdr::ScVal; + use crate::{Compare, Host, RawVal, Tag, TryFromVal}; + use itertools::Itertools; #[test] fn test_scvec_unequal_lengths() { @@ -578,4 +581,171 @@ mod tests { assert_eq!(xdr1, xdr2); } } + + /// Test that comparison of an object of one type to a small value of another + /// type produces the same results as the equivalent ScVal comparison. + /// + /// This is a test of the Host::obj_cmp and Tag::get_scval_type methods. + /// + /// It works by generating an "example" RawVal for every possible tag, + /// with a match on Tag that ensures it will be updated as Tag changes. + /// + /// Those examples are then converted to an array of ScVal. + /// + /// For both arrays, every pairwise comparison is performed, and must be equal. + #[test] + fn compare_obj_to_small() { + let host = Host::default(); + let rawvals: Vec = all_tags() + .into_iter() + .map(|t| example_for_tag(&host, t)) + .collect(); + let scvals: Vec = rawvals + .iter() + .map(|r| ScVal::try_from_val(&host, r).expect("scval")) + .collect(); + + let rawval_pairs = rawvals.iter().cartesian_product(&rawvals); + let scval_pairs = scvals.iter().cartesian_product(&scvals); + + let pair_pairs = rawval_pairs.zip(scval_pairs); + + for ((rawval1, rawval2), (scval1, scval2)) in pair_pairs { + let rawval_cmp = host.compare(rawval1, rawval2).expect("compare"); + let scval_cmp = scval1.cmp(scval2); + assert_eq!(rawval_cmp, scval_cmp); + } + } + + fn all_tags() -> Vec { + (0_u8..=255) + .map(Tag::from_u8) + .filter(|t| { + // bad tags can't be converted to ScVal + !matches!(t, Tag::Bad) + }) + .filter(|t| { + // objects of this type can't be instantiated + !matches!(t, Tag::LedgerKeyNonceObject) + }) + .collect() + } + + fn example_for_tag(host: &Host, tag: Tag) -> RawVal { + use crate::{xdr, Status}; + + let ex = match tag { + Tag::False => RawVal::from(false), + Tag::True => RawVal::from(true), + Tag::Void => RawVal::from(()), + Tag::Status => RawVal::from(Status::from(xdr::ScStatus::Ok)), + Tag::U32Val => RawVal::from(u32::MAX), + Tag::I32Val => RawVal::from(i32::MAX), + Tag::U64Small => RawVal::try_from_val(host, &0_u64).unwrap(), + Tag::I64Small => RawVal::try_from_val(host, &0_i64).unwrap(), + Tag::TimepointSmall => { + RawVal::try_from_val(host, &ScVal::Timepoint(xdr::TimePoint(0))).unwrap() + } + Tag::DurationSmall => { + RawVal::try_from_val(host, &ScVal::Duration(xdr::Duration(0))).unwrap() + } + Tag::U128Small => RawVal::try_from_val(host, &0_u128).unwrap(), + Tag::I128Small => RawVal::try_from_val(host, &0_i128).unwrap(), + Tag::U256Small => RawVal::try_from_val( + host, + &ScVal::U256(xdr::UInt256Parts { + hi_hi: 0, + hi_lo: 0, + lo_hi: 0, + lo_lo: 0, + }), + ) + .unwrap(), + Tag::I256Small => RawVal::try_from_val( + host, + &ScVal::I256(xdr::Int256Parts { + hi_hi: 0, + hi_lo: 0, + lo_hi: 0, + lo_lo: 0, + }), + ) + .unwrap(), + Tag::SymbolSmall => { + RawVal::try_from_val(host, &ScVal::Symbol(xdr::ScSymbol::try_from("").unwrap())) + .unwrap() + } + Tag::LedgerKeyContractExecutable => { + RawVal::try_from_val(host, &ScVal::LedgerKeyContractExecutable).unwrap() + } + Tag::SmallCodeUpperBound => panic!(), + Tag::ObjectCodeLowerBound => panic!(), + Tag::U64Object => RawVal::try_from_val(host, &u64::MAX).unwrap(), + Tag::I64Object => RawVal::try_from_val(host, &i64::MAX).unwrap(), + Tag::TimepointObject => { + RawVal::try_from_val(host, &ScVal::Timepoint(xdr::TimePoint(u64::MAX))).unwrap() + } + Tag::DurationObject => { + RawVal::try_from_val(host, &ScVal::Duration(xdr::Duration(u64::MAX))).unwrap() + } + Tag::U128Object => RawVal::try_from_val(host, &u128::MAX).unwrap(), + Tag::I128Object => RawVal::try_from_val(host, &i128::MAX).unwrap(), + Tag::U256Object => RawVal::try_from_val( + host, + &ScVal::U256(xdr::UInt256Parts { + hi_hi: u64::MAX, + hi_lo: u64::MAX, + lo_hi: u64::MAX, + lo_lo: u64::MAX, + }), + ) + .unwrap(), + Tag::I256Object => RawVal::try_from_val( + host, + &ScVal::I256(xdr::Int256Parts { + hi_hi: i64::MIN, + hi_lo: u64::MAX, + lo_hi: u64::MAX, + lo_lo: u64::MAX, + }), + ) + .unwrap(), + Tag::BytesObject => RawVal::try_from_val(host, &vec![1]).unwrap(), + Tag::StringObject => RawVal::try_from_val(host, &"foo").unwrap(), + Tag::SymbolObject => RawVal::try_from_val( + host, + &ScVal::Symbol(xdr::ScSymbol::try_from("a-big-symbol").unwrap()), + ) + .unwrap(), + Tag::VecObject => { + RawVal::try_from_val(host, &ScVal::Vec(Some(xdr::ScVec::try_from((0,)).unwrap()))) + .unwrap() + } + Tag::MapObject => RawVal::try_from_val( + host, + &ScVal::Map(Some(xdr::ScMap::try_from(vec![]).unwrap())), + ) + .unwrap(), + Tag::ContractExecutableObject => RawVal::try_from_val( + host, + &ScVal::ContractExecutable(xdr::ScContractExecutable::Token), + ) + .unwrap(), + Tag::AddressObject => RawVal::try_from_val( + host, + &ScVal::Address(xdr::ScAddress::Contract(xdr::Hash([0; 32]))), + ) + .unwrap(), + Tag::LedgerKeyNonceObject => panic!(), + Tag::ObjectCodeUpperBound => panic!(), + Tag::Bad => panic!(), + // NB: do not add a fallthrough case here if new Tag variants are added. + // this test depends on the match being exhaustive in order to ensure + // the correctness of Tag discriminants. + }; + + assert_eq!(ex.get_tag(), tag); + + ex + } } diff --git a/soroban-env-host/src/test.rs b/soroban-env-host/src/test.rs index 219185f2f..a88ab3c8e 100644 --- a/soroban-env-host/src/test.rs +++ b/soroban-env-host/src/test.rs @@ -3,7 +3,6 @@ pub(crate) mod util; mod address; mod basic; mod bytes; -mod comparison; mod crypto; mod ledger; mod map; diff --git a/soroban-env-host/src/test/comparison.rs b/soroban-env-host/src/test/comparison.rs deleted file mode 100644 index 07db83b95..000000000 --- a/soroban-env-host/src/test/comparison.rs +++ /dev/null @@ -1,170 +0,0 @@ -use crate::xdr::ScVal; -use crate::{Compare, Host, RawVal, Tag, TryFromVal}; -use itertools::Itertools; - -/// Test that comparison of an object of one type to a small value of another -/// type produces the same results as the equivalent ScVal comparison. -/// -/// This is a test of the Host::obj_cmp and Tag::get_scval_type methods. -/// -/// It works by generating an "example" RawVal for every possible tag, -/// with a match on Tag that ensures it will be updated as Tag changes. -/// -/// Those examples are then converted to an array of ScVal. -/// -/// For both arrays, every pairwise comparison is performed, and must be equal. -#[test] -fn compare_obj_to_small() { - let host = Host::default(); - let rawvals: Vec = all_tags() - .into_iter() - .map(|t| example_for_tag(&host, t)) - .collect(); - let scvals: Vec = rawvals - .iter() - .map(|r| ScVal::try_from_val(&host, r).expect("scval")) - .collect(); - - let rawval_pairs = rawvals.iter().cartesian_product(&rawvals); - let scval_pairs = scvals.iter().cartesian_product(&scvals); - - let pair_pairs = rawval_pairs.zip(scval_pairs); - - for ((rawval1, rawval2), (scval1, scval2)) in pair_pairs { - let rawval_cmp = host.compare(rawval1, rawval2).expect("compare"); - let scval_cmp = scval1.cmp(scval2); - assert_eq!(rawval_cmp, scval_cmp); - } -} - -fn all_tags() -> Vec { - (0_u8..=255) - .map(Tag::from_u8) - .filter(|t| { - // bad tags can't be converted to ScVal - !matches!(t, Tag::Bad) - }) - .filter(|t| { - // objects of this type can't be instantiated - !matches!(t, Tag::LedgerKeyNonceObject) - }) - .collect() -} - -fn example_for_tag(host: &Host, tag: Tag) -> RawVal { - use crate::{xdr, Status}; - - let ex = match tag { - Tag::False => RawVal::from(false), - Tag::True => RawVal::from(true), - Tag::Void => RawVal::from(()), - Tag::Status => RawVal::from(Status::from(xdr::ScStatus::Ok)), - Tag::U32Val => RawVal::from(u32::MAX), - Tag::I32Val => RawVal::from(i32::MAX), - Tag::U64Small => RawVal::try_from_val(host, &0_u64).unwrap(), - Tag::I64Small => RawVal::try_from_val(host, &0_i64).unwrap(), - Tag::TimepointSmall => { - RawVal::try_from_val(host, &ScVal::Timepoint(xdr::TimePoint(0))).unwrap() - } - Tag::DurationSmall => { - RawVal::try_from_val(host, &ScVal::Duration(xdr::Duration(0))).unwrap() - } - Tag::U128Small => RawVal::try_from_val(host, &0_u128).unwrap(), - Tag::I128Small => RawVal::try_from_val(host, &0_i128).unwrap(), - Tag::U256Small => RawVal::try_from_val( - host, - &ScVal::U256(xdr::UInt256Parts { - hi_hi: 0, - hi_lo: 0, - lo_hi: 0, - lo_lo: 0, - }), - ) - .unwrap(), - Tag::I256Small => RawVal::try_from_val( - host, - &ScVal::I256(xdr::Int256Parts { - hi_hi: 0, - hi_lo: 0, - lo_hi: 0, - lo_lo: 0, - }), - ) - .unwrap(), - Tag::SymbolSmall => { - RawVal::try_from_val(host, &ScVal::Symbol(xdr::ScSymbol::try_from("").unwrap())) - .unwrap() - } - Tag::LedgerKeyContractExecutable => { - RawVal::try_from_val(host, &ScVal::LedgerKeyContractExecutable).unwrap() - } - Tag::SmallCodeUpperBound => panic!(), - Tag::ObjectCodeLowerBound => panic!(), - Tag::U64Object => RawVal::try_from_val(host, &u64::MAX).unwrap(), - Tag::I64Object => RawVal::try_from_val(host, &i64::MAX).unwrap(), - Tag::TimepointObject => { - RawVal::try_from_val(host, &ScVal::Timepoint(xdr::TimePoint(u64::MAX))).unwrap() - } - Tag::DurationObject => { - RawVal::try_from_val(host, &ScVal::Duration(xdr::Duration(u64::MAX))).unwrap() - } - Tag::U128Object => RawVal::try_from_val(host, &u128::MAX).unwrap(), - Tag::I128Object => RawVal::try_from_val(host, &i128::MAX).unwrap(), - Tag::U256Object => RawVal::try_from_val( - host, - &ScVal::U256(xdr::UInt256Parts { - hi_hi: u64::MAX, - hi_lo: u64::MAX, - lo_hi: u64::MAX, - lo_lo: u64::MAX, - }), - ) - .unwrap(), - Tag::I256Object => RawVal::try_from_val( - host, - &ScVal::I256(xdr::Int256Parts { - hi_hi: i64::MIN, - hi_lo: u64::MAX, - lo_hi: u64::MAX, - lo_lo: u64::MAX, - }), - ) - .unwrap(), - Tag::BytesObject => RawVal::try_from_val(host, &vec![1]).unwrap(), - Tag::StringObject => RawVal::try_from_val(host, &"foo").unwrap(), - Tag::SymbolObject => RawVal::try_from_val( - host, - &ScVal::Symbol(xdr::ScSymbol::try_from("a-big-symbol").unwrap()), - ) - .unwrap(), - Tag::VecObject => { - RawVal::try_from_val(host, &ScVal::Vec(Some(xdr::ScVec::try_from((0,)).unwrap()))) - .unwrap() - } - Tag::MapObject => RawVal::try_from_val( - host, - &ScVal::Map(Some(xdr::ScMap::try_from(vec![]).unwrap())), - ) - .unwrap(), - Tag::ContractExecutableObject => RawVal::try_from_val( - host, - &ScVal::ContractExecutable(xdr::ScContractExecutable::Token), - ) - .unwrap(), - Tag::AddressObject => RawVal::try_from_val( - host, - &ScVal::Address(xdr::ScAddress::Contract(xdr::Hash([0; 32]))), - ) - .unwrap(), - Tag::LedgerKeyNonceObject => panic!(), - Tag::ObjectCodeUpperBound => panic!(), - Tag::Bad => panic!(), - // NB: do not add a fallthrough case here if new Tag variants are added. - // this test depends on the match being exhaustive in order to ensure - // the correctness of Tag discriminants. - }; - - assert_eq!(ex.get_tag(), tag); - - ex -}