Add proptests for sled conversions (#1253)
* Add proptests for sled conversions * document primary helper functions
This commit is contained in:
parent
1e3cf6dc5c
commit
06e74d15ae
|
@ -9,6 +9,7 @@ use zebra_chain::{
|
||||||
sprout, transaction, transparent,
|
sprout, transaction, transparent,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub struct TransactionLocation {
|
pub struct TransactionLocation {
|
||||||
pub height: block::Height,
|
pub height: block::Height,
|
||||||
pub index: u32,
|
pub index: u32,
|
||||||
|
@ -123,6 +124,13 @@ impl IntoSled for block::Hash {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FromSled for block::Hash {
|
||||||
|
fn from_ivec(bytes: sled::IVec) -> Self {
|
||||||
|
let array = bytes.as_ref().try_into().unwrap();
|
||||||
|
Self(array)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl IntoSled for &sprout::Nullifier {
|
impl IntoSled for &sprout::Nullifier {
|
||||||
type Bytes = [u8; 32];
|
type Bytes = [u8; 32];
|
||||||
|
|
||||||
|
@ -159,13 +167,6 @@ impl IntoSled for () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromSled for block::Hash {
|
|
||||||
fn from_ivec(bytes: sled::IVec) -> Self {
|
|
||||||
let array = bytes.as_ref().try_into().unwrap();
|
|
||||||
Self(array)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IntoSled for block::Height {
|
impl IntoSled for block::Height {
|
||||||
type Bytes = [u8; 4];
|
type Bytes = [u8; 4];
|
||||||
|
|
||||||
|
@ -274,3 +275,145 @@ impl SledDeserialize for sled::Tree {
|
||||||
value_bytes.map(V::from_ivec)
|
value_bytes.map(V::from_ivec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use proptest::{arbitrary::any, prelude::*};
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
impl Arbitrary for TransactionLocation {
|
||||||
|
type Parameters = ();
|
||||||
|
|
||||||
|
fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
|
||||||
|
(any::<block::Height>(), any::<u32>())
|
||||||
|
.prop_map(|(height, index)| Self { height, index })
|
||||||
|
.boxed()
|
||||||
|
}
|
||||||
|
|
||||||
|
type Strategy = BoxedStrategy<Self>;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn round_trip<T>(input: T) -> T
|
||||||
|
where
|
||||||
|
T: IntoSled + FromSled,
|
||||||
|
{
|
||||||
|
let bytes = input.into_ivec();
|
||||||
|
T::from_ivec(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The round trip test covers types that are used as value field in a sled
|
||||||
|
/// Tree. Only these types are ever deserialized, and so they're the only
|
||||||
|
/// ones that implement both `IntoSled` and `FromSled`.
|
||||||
|
fn assert_round_trip<T>(input: T)
|
||||||
|
where
|
||||||
|
T: IntoSled + FromSled + Clone + PartialEq + std::fmt::Debug,
|
||||||
|
{
|
||||||
|
let before = input.clone();
|
||||||
|
let after = round_trip(input);
|
||||||
|
assert_eq!(before, after);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This test asserts that types that are used as sled keys behave correctly.
|
||||||
|
/// Any type that implements `IntoIVec` can be used as a sled key. The value
|
||||||
|
/// is serialized via `IntoSled::into_ivec` when the `key`, `value` pair is
|
||||||
|
/// inserted into the sled tree. The `as_bytes` impl on the other hand is
|
||||||
|
/// called for most other operations when comparing a key against existing
|
||||||
|
/// keys in the sled database, such as `contains`.
|
||||||
|
fn assert_as_bytes_matches_ivec<T>(input: T)
|
||||||
|
where
|
||||||
|
T: IntoSled + Clone,
|
||||||
|
{
|
||||||
|
let before = input.clone();
|
||||||
|
let ivec = input.into_ivec();
|
||||||
|
assert_eq!(before.as_bytes().as_ref(), ivec.as_ref());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn roundtrip_transaction_location() {
|
||||||
|
zebra_test::init();
|
||||||
|
proptest!(|(val in any::<TransactionLocation>())| assert_round_trip(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn roundtrip_block_hash() {
|
||||||
|
zebra_test::init();
|
||||||
|
proptest!(|(val in any::<block::Hash>())| assert_round_trip(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn roundtrip_block_height() {
|
||||||
|
zebra_test::init();
|
||||||
|
proptest!(|(val in any::<block::Height>())| assert_round_trip(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn roundtrip_block() {
|
||||||
|
zebra_test::init();
|
||||||
|
|
||||||
|
proptest!(|(block in any::<Block>())| {
|
||||||
|
let bytes = block.into_ivec();
|
||||||
|
let deserialized: Arc<Block> = FromSled::from_ivec(bytes);
|
||||||
|
assert_eq!(&block, deserialized.deref());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn roundtrip_transparent_output() {
|
||||||
|
zebra_test::init();
|
||||||
|
|
||||||
|
proptest!(|(block in any::<transparent::Output>())| {
|
||||||
|
let bytes = block.into_ivec();
|
||||||
|
let deserialized: transparent::Output = FromSled::from_ivec(bytes);
|
||||||
|
assert_eq!(block, deserialized);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn key_matches_ivec_transaction_location() {
|
||||||
|
zebra_test::init();
|
||||||
|
proptest!(|(val in any::<TransactionLocation>())| assert_as_bytes_matches_ivec(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn key_matches_ivec_trans_hash() {
|
||||||
|
zebra_test::init();
|
||||||
|
proptest!(|(val in any::<transaction::Hash>())| assert_as_bytes_matches_ivec(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn key_matches_ivec_block_hash() {
|
||||||
|
zebra_test::init();
|
||||||
|
proptest!(|(val in any::<block::Hash>())| assert_as_bytes_matches_ivec(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn key_matches_ivec_sprout_nullifier() {
|
||||||
|
zebra_test::init();
|
||||||
|
proptest!(|(val in any::<sprout::Nullifier>())| assert_as_bytes_matches_ivec(&val));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn key_matches_ivec_sapling_nullifier() {
|
||||||
|
zebra_test::init();
|
||||||
|
proptest!(|(val in any::<sapling::Nullifier>())| assert_as_bytes_matches_ivec(&val));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn key_matches_ivec_block_height() {
|
||||||
|
zebra_test::init();
|
||||||
|
proptest!(|(val in any::<block::Height>())| assert_as_bytes_matches_ivec(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn key_matches_ivec_transparent_output() {
|
||||||
|
zebra_test::init();
|
||||||
|
proptest!(|(val in any::<transparent::Output>())| assert_as_bytes_matches_ivec(&val));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn key_matches_ivec_transparent_outpoint() {
|
||||||
|
zebra_test::init();
|
||||||
|
proptest!(|(val in any::<transparent::OutPoint>())| assert_as_bytes_matches_ivec(val));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue