Skip to content

Commit

Permalink
tests: add proptests for Message
Browse files Browse the repository at this point in the history
Signed-off-by: ljedrz <[email protected]>
  • Loading branch information
ljedrz committed Oct 18, 2023
1 parent 489fb4c commit c810f71
Show file tree
Hide file tree
Showing 14 changed files with 515 additions and 0 deletions.
18 changes: 18 additions & 0 deletions node/router/messages/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,21 @@ features = [ "codec" ]

[dependencies.tracing]
version = "0.1"

[dev-dependencies.snarkos-node-sync-locators]
path = "../../sync/locators"
version = "=2.1.7"
features = [ "test" ]

[dev-dependencies.snarkvm]
workspace = true
features = [ "algorithms" ]

[dev-dependencies.snarkvm-ledger-test-helpers]
version = "=0.15.4"

[dev-dependencies.proptest]
version = "1.3.1"

[dev-dependencies.test-strategy]
version = "0.3.1"
22 changes: 22 additions & 0 deletions node/router/messages/src/block_request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,25 @@ impl Display for BlockRequest {
write!(f, "{}..{}", self.start_height, self.end_height)
}
}

#[cfg(test)]
pub mod prop_tests {
use crate::BlockRequest;

use bytes::{Buf, BufMut, BytesMut};
use proptest::prelude::{any, BoxedStrategy, Strategy};
use snarkvm::utilities::{FromBytes, ToBytes};
use test_strategy::proptest;

pub fn any_block_request() -> BoxedStrategy<BlockRequest> {
any::<(u32, u32)>().prop_map(|(start_height, end_height)| BlockRequest { start_height, end_height }).boxed()
}

#[proptest]
fn block_request_roundtrip(#[strategy(any_block_request())] block_request: BlockRequest) {
let mut bytes = BytesMut::default().writer();
block_request.write_le(&mut bytes).unwrap();
let decoded = BlockRequest::read_le(&mut bytes.into_inner().reader()).unwrap();
assert_eq![decoded, block_request];
}
}
45 changes: 45 additions & 0 deletions node/router/messages/src/block_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,48 @@ impl<N: Network> FromBytes for BlockResponse<N> {
Ok(Self { request, blocks })
}
}

#[cfg(test)]
pub mod prop_tests {
use crate::{block_request::prop_tests::any_block_request, BlockResponse, DataBlocks};

use bytes::{Buf, BufMut, BytesMut};
use proptest::{
collection::vec,
prelude::{any, BoxedStrategy, Strategy},
};
use snarkvm::{
prelude::{block::Block, narwhal::Data},
utilities::{FromBytes, TestRng, ToBytes},
};
use snarkvm_ledger_test_helpers::sample_genesis_block;
use test_strategy::proptest;

type CurrentNetwork = snarkvm::prelude::Testnet3;

pub fn any_block() -> BoxedStrategy<Block<CurrentNetwork>> {
any::<u64>().prop_map(|seed| sample_genesis_block(&mut TestRng::fixed(seed))).boxed()
}

pub fn any_data_blocks() -> BoxedStrategy<DataBlocks<CurrentNetwork>> {
vec(any_block(), 0..=1).prop_map(DataBlocks).boxed()
}

pub fn any_block_response() -> BoxedStrategy<BlockResponse<CurrentNetwork>> {
(any_block_request(), any_data_blocks())
.prop_map(|(request, data_blocks)| BlockResponse { request, blocks: Data::Object(data_blocks) })
.boxed()
}

#[proptest]
fn block_response_roundtrip(#[strategy(any_block_response())] block_response: BlockResponse<CurrentNetwork>) {
let mut bytes = BytesMut::default().writer();
block_response.write_le(&mut bytes).unwrap();
let decoded = BlockResponse::<CurrentNetwork>::read_le(&mut bytes.into_inner().reader()).unwrap();
assert_eq!(block_response.request, decoded.request);
assert_eq!(
block_response.blocks.deserialize_blocking().unwrap(),
decoded.blocks.deserialize_blocking().unwrap(),
);
}
}
52 changes: 52 additions & 0 deletions node/router/messages/src/challenge_request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,55 @@ impl<N: Network> ChallengeRequest<N> {
Self { version: Message::<N>::VERSION, listener_port, node_type, address, nonce }
}
}

#[cfg(test)]
pub mod prop_tests {
use crate::{ChallengeRequest, NodeType};
use snarkvm::{
console::prelude::{FromBytes, ToBytes},
prelude::{Address, TestRng, Uniform},
};

use bytes::{Buf, BufMut, BytesMut};
use proptest::prelude::{any, BoxedStrategy, Strategy};
use test_strategy::proptest;

type CurrentNetwork = snarkvm::prelude::Testnet3;

pub fn any_valid_address() -> BoxedStrategy<Address<CurrentNetwork>> {
any::<u64>().prop_map(|seed| Address::rand(&mut TestRng::fixed(seed))).boxed()
}

pub fn any_node_type() -> BoxedStrategy<NodeType> {
(0..=2)
.prop_map(|id| match id {
0 => NodeType::Client,
1 => NodeType::Prover,
2 => NodeType::Validator,
_ => unreachable!(),
})
.boxed()
}

pub fn any_challenge_request() -> BoxedStrategy<ChallengeRequest<CurrentNetwork>> {
(any_valid_address(), any::<u64>(), any::<u32>(), any::<u16>(), any_node_type())
.prop_map(|(address, nonce, version, listener_port, node_type)| ChallengeRequest {
address,
nonce,
version,
listener_port,
node_type,
})
.boxed()
}

#[proptest]
fn challenge_request_roundtrip(#[strategy(any_challenge_request())] original: ChallengeRequest<CurrentNetwork>) {
let mut buf = BytesMut::default().writer();
ChallengeRequest::write_le(&original, &mut buf).unwrap();

let deserialized: ChallengeRequest<CurrentNetwork> =
ChallengeRequest::read_le(buf.into_inner().reader()).unwrap();
assert_eq!(original, deserialized);
}
}
54 changes: 54 additions & 0 deletions node/router/messages/src/challenge_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,57 @@ impl<N: Network> FromBytes for ChallengeResponse<N> {
Ok(Self { genesis_header: Header::read_le(&mut reader)?, signature: Data::read_le(reader)? })
}
}

#[cfg(test)]
pub mod prop_tests {
use crate::ChallengeResponse;
use snarkvm::{
console::prelude::{FromBytes, ToBytes},
ledger::narwhal::Data,
prelude::{block::Header, PrivateKey, Signature},
utilities::rand::{TestRng, Uniform},
};
use snarkvm_ledger_test_helpers::sample_genesis_block;

use bytes::{Buf, BufMut, BytesMut};
use proptest::prelude::{any, BoxedStrategy, Strategy};
use test_strategy::proptest;

type CurrentNetwork = snarkvm::prelude::Testnet3;

pub fn any_signature() -> BoxedStrategy<Signature<CurrentNetwork>> {
(0..64)
.prop_map(|message_size| {
let rng = &mut TestRng::default();
let message: Vec<_> = (0..message_size).map(|_| Uniform::rand(rng)).collect();
let private_key = PrivateKey::new(rng).unwrap();
Signature::sign(&private_key, &message, rng).unwrap()
})
.boxed()
}

pub fn any_genesis_header() -> BoxedStrategy<Header<CurrentNetwork>> {
any::<u64>().prop_map(|seed| *sample_genesis_block(&mut TestRng::fixed(seed)).header()).boxed()
}

pub fn any_challenge_response() -> BoxedStrategy<ChallengeResponse<CurrentNetwork>> {
(any_signature(), any_genesis_header())
.prop_map(|(sig, genesis_header)| ChallengeResponse { signature: Data::Object(sig), genesis_header })
.boxed()
}

#[proptest]
fn challenge_response_roundtrip(#[strategy(any_challenge_response())] original: ChallengeResponse<CurrentNetwork>) {
let mut buf = BytesMut::default().writer();
ChallengeResponse::write_le(&original, &mut buf).unwrap();

let deserialized: ChallengeResponse<CurrentNetwork> =
ChallengeResponse::read_le(buf.into_inner().reader()).unwrap();

assert_eq!(original.genesis_header, deserialized.genesis_header);
assert_eq!(
original.signature.deserialize_blocking().unwrap(),
deserialized.signature.deserialize_blocking().unwrap()
);
}
}
50 changes: 50 additions & 0 deletions node/router/messages/src/disconnect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,53 @@ impl FromBytes for Disconnect {
Ok(Disconnect { reason: DisconnectReason::read_le(&mut reader)? })
}
}

#[cfg(test)]
mod tests {
use crate::{Disconnect, DisconnectReason};
use snarkvm::{
console::prelude::{FromBytes, ToBytes},
prelude::{Rng, TestRng},
};

use bytes::{Buf, BufMut, BytesMut};

#[test]
fn disconnect_roundtrip() {
// TODO switch to an iteration method that doesn't require manually updating this vec if variants are added
let all_reasons = [
DisconnectReason::ExceededForkRange,
DisconnectReason::InvalidChallengeResponse,
DisconnectReason::InvalidForkDepth,
DisconnectReason::INeedToSyncFirst,
DisconnectReason::NoReasonGiven,
DisconnectReason::ProtocolViolation,
DisconnectReason::OutdatedClientVersion,
DisconnectReason::PeerHasDisconnected,
DisconnectReason::PeerRefresh,
DisconnectReason::ShuttingDown,
DisconnectReason::SyncComplete,
DisconnectReason::TooManyFailures,
DisconnectReason::TooManyPeers,
DisconnectReason::YouNeedToSyncFirst,
DisconnectReason::YourPortIsClosed(TestRng::default().gen()),
];

for reason in all_reasons.iter() {
let disconnect = Disconnect::from(*reason);
let mut buf = BytesMut::default().writer();
Disconnect::write_le(&disconnect, &mut buf).unwrap();

let disconnect = Disconnect::read_le(buf.into_inner().reader()).unwrap();
assert_eq!(reason, &disconnect.reason);
}
}

#[test]
#[should_panic]
fn disconnect_invalid_data_panics() {
let mut buf = BytesMut::default().writer();
"not a DisconnectReason-value".as_bytes().write_le(&mut buf).unwrap();
let _disconnect = Disconnect::read_le(buf.into_inner().reader()).unwrap();
}
}
17 changes: 17 additions & 0 deletions node/router/messages/src/peer_request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,20 @@ impl FromBytes for PeerRequest {
Ok(Self)
}
}

#[cfg(test)]
pub mod tests {
use crate::PeerRequest;

use bytes::{Buf, BufMut, BytesMut};
use snarkvm::utilities::{FromBytes, ToBytes};

#[test]
fn peer_request_roundtrip() {
let peer_request = PeerRequest;
let mut bytes = BytesMut::default().writer();
peer_request.write_le(&mut bytes).unwrap();
let decoded = PeerRequest::read_le(&mut bytes.into_inner().reader()).unwrap();
assert_eq!(decoded, peer_request);
}
}
34 changes: 34 additions & 0 deletions node/router/messages/src/peer_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,37 @@ impl FromBytes for PeerResponse {
Ok(Self { peers })
}
}

#[cfg(test)]
pub mod prop_tests {
use crate::PeerResponse;

use bytes::{Buf, BufMut, BytesMut};
use proptest::{
collection::vec,
prelude::{any, BoxedStrategy, Strategy},
};
use snarkvm::utilities::{FromBytes, ToBytes};
use std::net::{IpAddr, SocketAddr};
use test_strategy::proptest;

pub fn any_valid_socket_addr() -> BoxedStrategy<SocketAddr> {
any::<(IpAddr, u16)>().prop_map(|(ip_addr, port)| SocketAddr::new(ip_addr, port)).boxed()
}

pub fn any_vec() -> BoxedStrategy<Vec<SocketAddr>> {
vec(any_valid_socket_addr(), 0..50).prop_map(|v| v).boxed()
}

pub fn any_peer_response() -> BoxedStrategy<PeerResponse> {
any_vec().prop_map(|peers| PeerResponse { peers }).boxed()
}

#[proptest]
fn peer_response_roundtrip(#[strategy(any_peer_response())] peer_response: PeerResponse) {
let mut bytes = BytesMut::default().writer();
peer_response.write_le(&mut bytes).unwrap();
let decoded = PeerResponse::read_le(&mut bytes.into_inner().reader()).unwrap();
assert_eq!(decoded, peer_response);
}
}
32 changes: 32 additions & 0 deletions node/router/messages/src/ping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,35 @@ impl<N: Network> Ping<N> {
Self { version: <Message<N>>::VERSION, node_type, block_locators }
}
}

#[cfg(test)]
pub mod prop_tests {
use crate::Ping;

use crate::challenge_request::prop_tests::any_node_type;
use bytes::{Buf, BufMut, BytesMut};
use proptest::prelude::{any, BoxedStrategy, Strategy};
use snarkos_node_sync_locators::{test_helpers::sample_block_locators, BlockLocators};
use snarkvm::utilities::{FromBytes, ToBytes};
use test_strategy::proptest;

type CurrentNetwork = snarkvm::prelude::Testnet3;

pub fn any_block_locators() -> BoxedStrategy<BlockLocators<CurrentNetwork>> {
any::<u32>().prop_map(sample_block_locators).boxed()
}

pub fn any_ping() -> BoxedStrategy<Ping<CurrentNetwork>> {
(any::<u32>(), any_block_locators(), any_node_type())
.prop_map(|(version, bls, node_type)| Ping { version, block_locators: Some(bls), node_type })
.boxed()
}

#[proptest]
fn ping_roundtrip(#[strategy(any_ping())] ping: Ping<CurrentNetwork>) {
let mut bytes = BytesMut::default().writer();
ping.write_le(&mut bytes).unwrap();
let decoded = Ping::<CurrentNetwork>::read_le(&mut bytes.into_inner().reader()).unwrap();
assert_eq!(ping, decoded);
}
}
26 changes: 26 additions & 0 deletions node/router/messages/src/pong.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,29 @@ impl FromBytes for Pong {
Ok(Self { is_fork })
}
}

#[cfg(test)]
pub mod tests {
use crate::Pong;

use snarkvm::utilities::{FromBytes, ToBytes};

use bytes::{Buf, BufMut, BytesMut};
use proptest::{
option::of,
prelude::{any, BoxedStrategy, Strategy},
};
use test_strategy::proptest;

pub fn any_pong() -> BoxedStrategy<Pong> {
of(any::<bool>()).prop_map(|is_fork| Pong { is_fork }).boxed()
}

#[proptest]
fn pong_roundtrip(#[strategy(any_pong())] pong: Pong) {
let mut bytes = BytesMut::default().writer();
pong.write_le(&mut bytes).unwrap();
let decoded = Pong::read_le(&mut bytes.into_inner().reader()).unwrap();
assert_eq!(pong, decoded);
}
}
Loading

0 comments on commit c810f71

Please sign in to comment.