use proptest::{ arbitrary::{any, Arbitrary}, collection::vec, option, prelude::*, }; use crate::{ serialization::{ZcashDeserialize, ZcashSerialize}, types::LockTime, }; use super::*; #[cfg(test)] impl Transaction { pub fn v1_strategy() -> impl Strategy { ( vec(any::(), 0..10), vec(any::(), 0..10), any::(), ) .prop_map(|(inputs, outputs, lock_time)| Transaction::V1 { inputs: inputs, outputs: outputs, lock_time: lock_time, }) .boxed() } pub fn v2_strategy() -> impl Strategy { ( vec(any::(), 0..10), vec(any::(), 0..10), any::(), option::of(any::>()), ) .prop_map( |(inputs, outputs, lock_time, joinsplit_data)| Transaction::V2 { inputs: inputs, outputs: outputs, lock_time: lock_time, joinsplit_data: joinsplit_data, }, ) .boxed() } pub fn v3_strategy() -> impl Strategy { ( vec(any::(), 0..10), vec(any::(), 0..10), any::(), any::(), option::of(any::>()), ) .prop_map( |(inputs, outputs, lock_time, expiry_height, joinsplit_data)| Transaction::V3 { inputs: inputs, outputs: outputs, lock_time: lock_time, expiry_height: expiry_height, joinsplit_data: joinsplit_data, }, ) .boxed() } pub fn v4_strategy() -> impl Strategy { ( vec(any::(), 0..10), vec(any::(), 0..10), any::(), any::(), any::(), option::of(any::()), option::of(any::>()), ) .prop_map( |( inputs, outputs, lock_time, expiry_height, value_balance, shielded_data, joinsplit_data, )| Transaction::V4 { inputs: inputs, outputs: outputs, lock_time: lock_time, expiry_height: expiry_height, value_balance: value_balance, shielded_data: shielded_data, joinsplit_data: joinsplit_data, }, ) .boxed() } } #[cfg(test)] impl Arbitrary for Transaction { type Parameters = (); fn arbitrary_with(_args: ()) -> Self::Strategy { prop_oneof![ Self::v1_strategy(), Self::v2_strategy(), Self::v3_strategy(), Self::v4_strategy() ] .boxed() } type Strategy = BoxedStrategy; } #[test] fn librustzcash_tx_deserialize_and_round_trip() { let tx = Transaction::zcash_deserialize(&test_vectors::GENERIC_TESTNET_TX[..]) .expect("transaction test vector from librustzcash should deserialize"); let mut data2 = Vec::new(); tx.zcash_serialize(&mut data2).expect("tx should serialize"); assert_eq!(&test_vectors::GENERIC_TESTNET_TX[..], &data2[..]); } #[cfg(test)] proptest! { #[test] fn transaction_roundtrip(tx in any::()) { let mut data = Vec::new(); tx.zcash_serialize(&mut data).expect("tx should serialize"); let tx2 = Transaction::zcash_deserialize(&data[..]).expect("randomized tx should deserialize"); prop_assert_eq![tx, tx2]; } }