Skip to content

Commit

Permalink
Basic addr (v1) and addrv2 deserialization tests
Browse files Browse the repository at this point in the history
  • Loading branch information
teor2345 committed Nov 11, 2021
1 parent a92a286 commit 4b30aca
Show file tree
Hide file tree
Showing 4 changed files with 478 additions and 4 deletions.
4 changes: 2 additions & 2 deletions zebra-network/src/protocol/external/codec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ impl Codec {
}

/// Deserialize an `addr` (v1) message into a list of `MetaAddr`s.
fn read_addr<R: Read>(&self, reader: R) -> Result<Message, Error> {
pub(super) fn read_addr<R: Read>(&self, reader: R) -> Result<Message, Error> {
let addrs: Vec<AddrV1> = reader.zcash_deserialize_into()?;

if addrs.len() > constants::MAX_ADDRS_IN_MESSAGE {
Expand All @@ -535,7 +535,7 @@ impl Codec {
///
/// Currently, Zebra parses received `addrv2`s, ignoring some address types.
/// Zebra never sends `addrv2` messages.
fn read_addrv2<R: Read>(&self, reader: R) -> Result<Message, Error> {
pub(super) fn read_addrv2<R: Read>(&self, reader: R) -> Result<Message, Error> {
let addrs: Vec<AddrV2> = reader.zcash_deserialize_into()?;

if addrs.len() > constants::MAX_ADDRS_IN_MESSAGE {
Expand Down
174 changes: 172 additions & 2 deletions zebra-network/src/protocol/external/tests/vectors.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
use std::io::Write;
use std::io::{self, Write};

use byteorder::{LittleEndian, WriteBytesExt};

use zebra_chain::serialization::ZcashDeserializeInto;

use super::super::InventoryHash;
use crate::protocol::external::{Codec, InventoryHash, Message};

/// Test if deserializing [`InventoryHash::Wtx`] does not produce an error.
#[test]
fn parses_msg_wtx_inventory_type() {
zebra_test::init();

let mut input = Vec::new();

input
Expand All @@ -24,3 +26,171 @@ fn parses_msg_wtx_inventory_type() {

assert_eq!(deserialized, InventoryHash::Wtx([0u8; 64].into()));
}

/// Test that deserializing [`AddrV1`] into [`MetaAddr`] succeeds,
/// and produces the expected number of addresses.
#[test]
fn parses_msg_addr_v1_ip() {
zebra_test::init();

let codec = Codec::builder().finish();

for (case_idx, addr_v1_bytes) in zebra_test::network_addr::ADDR_V1_IP_VECTORS
.iter()
.enumerate()
{
let mut addr_v1_bytes = io::Cursor::new(addr_v1_bytes);

let deserialized: Message = codec
.read_addr(&mut addr_v1_bytes)
.unwrap_or_else(|_| panic!("failed to deserialize AddrV1 case {}", case_idx));

if let Message::Addr(addrs) = deserialized {
assert!(
!addrs.is_empty(),
"expected some AddrV1s in case {}: {:?}",
case_idx,
addrs
);
assert!(
addrs.len() <= 2,
"too many AddrV1s in case {}: {:?}",
case_idx,
addrs
);
} else {
panic!(
"unexpected message variant in case {}: {:?}",
case_idx, deserialized
);
}
}
}

/// Test that deserializing empty [`AddrV1`] succeeds,
/// and produces no addresses.
#[test]
fn parses_msg_addr_v1_empty() {
zebra_test::init();

let codec = Codec::builder().finish();

for (case_idx, addr_v1_bytes) in zebra_test::network_addr::ADDR_V1_EMPTY_VECTORS
.iter()
.enumerate()
{
let mut addr_v1_bytes = io::Cursor::new(addr_v1_bytes);

let deserialized: Message = codec
.read_addr(&mut addr_v1_bytes)
.unwrap_or_else(|_| panic!("failed to deserialize AddrV1 case {}", case_idx));

if let Message::Addr(addrs) = deserialized {
assert!(
addrs.is_empty(),
"expected empty AddrV1 list for case {}: {:?}",
case_idx,
addrs,
);
} else {
panic!(
"unexpected message variant in case {}: {:?}",
case_idx, deserialized
);
}
}
}

/// Test that deserializing [`AddrV2`] into [`MetaAddr`] succeeds,
/// and produces the expected number of addresses.
#[test]
fn parses_msg_addr_v2_ip() {
zebra_test::init();

let codec = Codec::builder().finish();

for (case_idx, addr_v2_bytes) in zebra_test::network_addr::ADDR_V2_IP_VECTORS
.iter()
.enumerate()
{
let mut addr_v2_bytes = io::Cursor::new(addr_v2_bytes);

let deserialized: Message = codec
.read_addrv2(&mut addr_v2_bytes)
.unwrap_or_else(|_| panic!("failed to deserialize AddrV2 case {}", case_idx));

if let Message::Addr(addrs) = deserialized {
assert!(
!addrs.is_empty(),
"expected some AddrV2s in case {}: {:?}",
case_idx,
addrs
);
assert!(
addrs.len() <= 2,
"too many AddrV2s in case {}: {:?}",
case_idx,
addrs
);
} else {
panic!(
"unexpected message variant in case {}: {:?}",
case_idx, deserialized
);
}
}
}

/// Test that deserializing empty [`AddrV2`] succeeds,
/// and produces no addresses.
#[test]
fn parses_msg_addr_v2_empty() {
zebra_test::init();

let codec = Codec::builder().finish();

for (case_idx, addr_v2_bytes) in zebra_test::network_addr::ADDR_V2_EMPTY_VECTORS
.iter()
.enumerate()
{
let mut addr_v2_bytes = io::Cursor::new(addr_v2_bytes);

let deserialized: Message = codec
.read_addrv2(&mut addr_v2_bytes)
.unwrap_or_else(|_| panic!("failed to deserialize AddrV2 case {}", case_idx));

if let Message::Addr(addrs) = deserialized {
assert!(
addrs.is_empty(),
"expected empty AddrV2 list for case {}: {:?}",
case_idx,
addrs,
);
} else {
panic!(
"unexpected message variant in case {}: {:?}",
case_idx, deserialized
);
}
}
}

/// Test that deserializing invalid [`AddrV2`] fails.
#[test]
fn parses_msg_addr_v2_invalid() {
zebra_test::init();

let codec = Codec::builder().finish();

for (case_idx, addr_v2_bytes) in zebra_test::network_addr::ADDR_V2_INVALID_VECTORS
.iter()
.enumerate()
{
let mut addr_v2_bytes = io::Cursor::new(addr_v2_bytes);

codec.read_addrv2(&mut addr_v2_bytes).expect_err(&format!(
"unexpected success: deserializing invalid AddrV2 case {} should have failed",
case_idx
));
}
}
1 change: 1 addition & 0 deletions zebra-test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use std::sync::Once;
pub mod command;
pub mod mock_service;
pub mod net;
pub mod network_addr;
pub mod prelude;
pub mod transcript;
pub mod vectors;
Expand Down
Loading

0 comments on commit 4b30aca

Please sign in to comment.