From 5bb0187726f68ab9e8d9a88fb30fc08aa6b82d1e Mon Sep 17 00:00:00 2001 From: Dennis Schwerdel Date: Sun, 11 Oct 2020 21:45:28 +0200 Subject: [PATCH] More tests + clippy changes --- src/cloud.rs | 8 ++--- src/config.rs | 6 ++-- src/crypto/init.rs | 75 +++++++++++++++++++++++++++++++++++++++++----- src/crypto/mod.rs | 6 ++-- 4 files changed, 78 insertions(+), 17 deletions(-) diff --git a/src/cloud.rs b/src/cloud.rs index 1e351ef..35aa29a 100644 --- a/src/cloud.rs +++ b/src/cloud.rs @@ -442,9 +442,9 @@ impl GenericCloud Result<(), Error> { if let Some(ref path) = self.config.beacon_store { let peers: Vec<_> = self.own_addresses.choose_multiple(&mut thread_rng(), 3).cloned().collect(); - if path.starts_with('|') { + if let Some(path) = path.strip_prefix('|') { self.beacon_serializer - .write_to_cmd(&peers, &path[1..]) + .write_to_cmd(&peers, path) .map_err(|e| Error::BeaconIo("Failed to call beacon command", e))?; } else { self.beacon_serializer @@ -459,9 +459,9 @@ impl GenericCloud Result<(), Error> { let peers; if let Some(ref path) = self.config.beacon_load { - if path.starts_with('|') { + if let Some(path) = path.strip_prefix('|') { self.beacon_serializer - .read_from_cmd(&path[1..], Some(50)) + .read_from_cmd(path, Some(50)) .map_err(|e| Error::BeaconIo("Failed to call beacon command", e))?; return Ok(()) } else { diff --git a/src/config.rs b/src/config.rs index cb73de8..554fbae 100644 --- a/src/config.rs +++ b/src/config.rs @@ -17,8 +17,8 @@ pub const DEFAULT_PORT: u16 = 3210; fn parse_listen(addr: &str) -> SocketAddr { - if addr.starts_with("*:") { - let port = try_fail!(addr[2..].parse::(), "Invalid port: {}"); + if let Some(addr) = addr.strip_prefix("*:") { + let port = try_fail!(addr.parse::(), "Invalid port: {}"); SocketAddr::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), port) } else if addr.contains(':') { try_fail!(addr.parse::(), "Invalid address: {}: {}", addr) @@ -417,7 +417,7 @@ pub struct Args { pub version: bool, /// Generate and print a key-pair and exit - #[structopt(long, conflicts_with="private_key")] + #[structopt(long, conflicts_with = "private_key")] pub genkey: bool, /// Disable automatic port forwarding diff --git a/src/crypto/init.rs b/src/crypto/init.rs index ba8fef1..a503dbe 100644 --- a/src/crypto/init.rs +++ b/src/crypto/init.rs @@ -381,7 +381,7 @@ pub struct InitState { salted_node_id_hash: SaltedNodeIdHash, payload: P, key_pair: Arc, - trusted_keys: Arc>, + trusted_keys: Arc<[Ed25519PublicKey]>, ecdh_private_key: Option, next_stage: u8, close_time: usize, @@ -393,7 +393,7 @@ pub struct InitState { impl InitState

{ pub fn new( - node_id: NodeId, payload: P, key_pair: Arc, trusted_keys: Arc>, + node_id: NodeId, payload: P, key_pair: Arc, trusted_keys: Arc<[Ed25519PublicKey]>, algorithms: Algorithms ) -> Self { @@ -494,9 +494,7 @@ impl InitState

{ hash == d.as_ref() } - fn send_message( - &mut self, stage: u8, ecdh_public_key: Option, out: &mut MsgBuffer - ) { + fn send_message(&mut self, stage: u8, ecdh_public_key: Option, out: &mut MsgBuffer) { debug!("Sending init with stage={}", stage); assert!(out.is_empty()); let mut public_key = [0; ED25519_PUBLIC_KEY_LEN]; @@ -678,7 +676,7 @@ mod tests { let key_pair = Arc::new(Ed25519KeyPair::from_pkcs8(pkcs8_bytes.as_ref()).unwrap()); let mut public_key = [0; ED25519_PUBLIC_KEY_LEN]; public_key.clone_from_slice(key_pair.public_key().as_ref()); - let trusted_nodes = Arc::new(vec![public_key]); + let trusted_nodes = Arc::new([public_key]); let mut node1 = [0; NODE_ID_BYTES]; rng.fill(&mut node1).unwrap(); let mut node2 = [0; NODE_ID_BYTES]; @@ -714,7 +712,70 @@ mod tests { } } - // TODO Test: last message repeated when message is lost + #[test] + fn lost_init_sender_recovers() { + let (mut sender, mut receiver) = create_pair(); + let mut out = MsgBuffer::new(8); + sender.send_ping(&mut out); + assert_eq!(sender.stage(), STAGE_PONG); + // lost ping, sender recovers + out.clear(); + sender.every_second(&mut out).unwrap(); + let result = receiver.handle_init(&mut out).unwrap(); + assert_eq!(receiver.stage(), STAGE_PENG); + assert_eq!(result, InitResult::Continue); + // lost pong, sender recovers + out.clear(); + receiver.every_second(&mut out).unwrap(); + let result = sender.handle_init(&mut out).unwrap(); + assert_eq!(sender.stage(), WAITING_TO_CLOSE); + match result { + InitResult::Success { .. } => { + // lost peng, sender recovers + out.clear(); + } + InitResult::Continue => unreachable!() + }; + sender.every_second(&mut out).unwrap(); + let result = receiver.handle_init(&mut out).unwrap(); + assert_eq!(receiver.stage(), CLOSING); + match result { + InitResult::Success { .. } => assert!(out.is_empty()), + InitResult::Continue => unreachable!() + } + } + + #[test] + fn lost_init_receiver_recovers() { + let (mut sender, mut receiver) = create_pair(); + let mut out = MsgBuffer::new(8); + sender.send_ping(&mut out); + assert_eq!(sender.stage(), STAGE_PONG); + let result = receiver.handle_init(&mut out).unwrap(); + assert_eq!(receiver.stage(), STAGE_PENG); + assert_eq!(result, InitResult::Continue); + // lost pong, receiver recovers + out.clear(); + sender.every_second(&mut out).unwrap(); + receiver.handle_init(&mut out).unwrap(); + let result = sender.handle_init(&mut out).unwrap(); + assert_eq!(sender.stage(), WAITING_TO_CLOSE); + match result { + InitResult::Success { .. } => { + // lost peng, sender recovers + out.clear(); + } + InitResult::Continue => unreachable!() + }; + receiver.every_second(&mut out).unwrap(); + sender.handle_init(&mut out).unwrap(); + let result = receiver.handle_init(&mut out).unwrap(); + assert_eq!(receiver.stage(), CLOSING); + match result { + InitResult::Success { .. } => assert!(out.is_empty()), + InitResult::Continue => unreachable!() + } + } // TODO Test: timeout after 5 retries diff --git a/src/crypto/mod.rs b/src/crypto/mod.rs index 558bf43..2c10043 100644 --- a/src/crypto/mod.rs +++ b/src/crypto/mod.rs @@ -70,7 +70,7 @@ pub struct Config { pub struct Crypto { node_id: NodeId, key_pair: Arc, - trusted_keys: Arc>, + trusted_keys: Arc<[Ed25519PublicKey]>, algorithms: Algorithms } @@ -124,7 +124,7 @@ impl Crypto { speeds.into_iter().map(|(a, s)| format!("{}: {:.1} MiB/s", a, s)).collect::>().join(", ") ); } - Ok(Self { node_id, key_pair: Arc::new(key_pair), trusted_keys: Arc::new(trusted_keys), algorithms: algos }) + Ok(Self { node_id, key_pair: Arc::new(key_pair), trusted_keys: trusted_keys.into_boxed_slice().into(), algorithms: algos }) } pub fn generate_keypair(password: Option<&str>) -> (String, String) { @@ -215,7 +215,7 @@ pub struct PeerCrypto { impl PeerCrypto

{ pub fn new( - node_id: NodeId, init_payload: P, key_pair: Arc, trusted_keys: Arc>, + node_id: NodeId, init_payload: P, key_pair: Arc, trusted_keys: Arc<[Ed25519PublicKey]>, algorithms: Algorithms ) -> Self {