Add quickcheck tests; actually delete types.rs file

This commit is contained in:
Joakim Frostegård 2020-04-05 04:07:18 +02:00
parent 268235c8e1
commit c26fc942e3
6 changed files with 206 additions and 131 deletions

112
Cargo.lock generated
View file

@ -9,6 +9,15 @@ dependencies = [
"const-random",
]
[[package]]
name = "aho-corasick"
version = "0.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada"
dependencies = [
"memchr",
]
[[package]]
name = "aquatic"
version = "0.1.0"
@ -18,6 +27,8 @@ dependencies = [
"indexmap",
"mio",
"net2",
"quickcheck",
"quickcheck_macros",
"rand",
]
@ -77,6 +88,16 @@ dependencies = [
"num_cpus",
]
[[package]]
name = "env_logger"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
dependencies = [
"log",
"regex",
]
[[package]]
name = "getrandom"
version = "0.1.14"
@ -127,6 +148,12 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "memchr"
version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
[[package]]
name = "mio"
version = "0.7.0"
@ -193,6 +220,47 @@ version = "0.5.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d659fe7c6d27f25e9d80a1a094c223f5246f6a6596453e09d7229bf42750b63"
[[package]]
name = "proc-macro2"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df246d292ff63439fea9bc8c0a270bed0e390d5ebd4db4ba15aba81111b5abe3"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quickcheck"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a44883e74aa97ad63db83c4bf8ca490f02b2fc02f92575e720c8551e843c945f"
dependencies = [
"env_logger",
"log",
"rand",
"rand_core",
]
[[package]]
name = "quickcheck_macros"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "608c156fd8e97febc07dc9c2e2c80bf74cfc6ef26893eae3daf8bc2bc94a4b7f"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "quote"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.7.3"
@ -250,6 +318,24 @@ version = "0.1.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
[[package]]
name = "regex"
version = "1.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f6946991529684867e47d86474e3a6d0c0ab9b82d5821e314b1ede31fa3a4b3"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
"thread_local",
]
[[package]]
name = "regex-syntax"
version = "0.6.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae"
[[package]]
name = "socket2"
version = "0.3.12"
@ -262,6 +348,32 @@ dependencies = [
"winapi",
]
[[package]]
name = "syn"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "thread_local"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
dependencies = [
"lazy_static",
]
[[package]]
name = "unicode-xid"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
[[package]]
name = "wasi"
version = "0.9.0+wasi-snapshot-preview1"

View file

@ -20,4 +20,8 @@ features = ["small_rng"]
[dependencies.mio]
version = "0.7"
features = ["udp", "os-poll", "os-util"]
features = ["udp", "os-poll", "os-util"]
[dev-dependencies]
quickcheck = "0.9"
quickcheck_macros = "0.9"

View file

@ -130,4 +130,29 @@ impl State {
torrents: Arc::new(DashMap::new()),
}
}
}
#[cfg(test)]
mod tests {
#[test]
fn test_peer_status_from_event_and_bytes_left(){
use crate::common::*;
use PeerStatus::*;
let f = PeerStatus::from_event_and_bytes_left;
assert_eq!(Stopped, f(AnnounceEvent::Stopped, NumberOfBytes(0)));
assert_eq!(Stopped, f(AnnounceEvent::Stopped, NumberOfBytes(1)));
assert_eq!(Seeding, f(AnnounceEvent::Started, NumberOfBytes(0)));
assert_eq!(Leeching, f(AnnounceEvent::Started, NumberOfBytes(1)));
assert_eq!(Seeding, f(AnnounceEvent::Completed, NumberOfBytes(0)));
assert_eq!(Leeching, f(AnnounceEvent::Completed, NumberOfBytes(1)));
assert_eq!(Seeding, f(AnnounceEvent::None, NumberOfBytes(0)));
assert_eq!(Leeching, f(AnnounceEvent::None, NumberOfBytes(1)));
}
}

View file

@ -181,4 +181,67 @@ pub fn create_torrent_scrape_statistics(
completed: NumberOfDownloads(0), // No implementation planned
leechers: NumberOfPeers(leechers)
}
}
#[cfg(test)]
mod tests {
use std::time::Instant;
use std::net::IpAddr;
use indexmap::IndexMap;
use quickcheck::{TestResult, quickcheck};
use super::*;
fn gen_peer_map_key_and_value(i: u8) -> (PeerMapKey, Peer) {
let ip_address: IpAddr = "127.0.0.1".parse().unwrap();
let peer_id = PeerId([i; 20]);
let key = PeerMapKey {
ip: ip_address,
peer_id,
};
let value = Peer {
connection_id: ConnectionId(0),
ip_address,
id: peer_id,
port: Port(1),
status: PeerStatus::Leeching,
last_announce: Time(Instant::now()),
};
(key, value)
}
#[test]
fn test_extract_response_peers(){
fn prop(data: (u8, u8)) -> TestResult {
let gen_num_peers = data.0;
let req_num_peers = data.1 as usize;
let mut peer_map: PeerMap = IndexMap::new();
for i in 0..gen_num_peers {
let (key, value) = gen_peer_map_key_and_value(i);
peer_map.insert(key, value);
}
let num_returned = extract_response_peers(
&peer_map,
req_num_peers
).len();
let mut success = num_returned <= req_num_peers;
if req_num_peers >= gen_num_peers as usize {
success &= num_returned == gen_num_peers as usize;
}
TestResult::from_bool(success)
}
quickcheck(prop as fn((u8, u8)) -> TestResult);
}
}

View file

@ -29,4 +29,4 @@ fn main(){
tasks::clean_connections(&state);
tasks::clean_torrents(&state);
}
}
}

View file

@ -1,129 +0,0 @@
use std::sync::Arc;
use std::sync::atomic::AtomicUsize;
use std::net::{SocketAddr, IpAddr};
use std::time::Instant;
use dashmap::DashMap;
use indexmap::IndexMap;
pub use bittorrent_udp::types::*;
#[derive(Debug, Clone, Copy)]
pub struct Time(pub Instant);
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ConnectionKey {
pub connection_id: ConnectionId,
pub socket_addr: SocketAddr
}
pub type ConnectionMap = DashMap<ConnectionKey, Time>;
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
pub enum PeerStatus {
Seeding,
Leeching,
Stopped
}
impl PeerStatus {
/// Determine peer status from announce event and number of bytes left.
///
/// Likely, the last branch will be taken most of the time.
pub fn from_event_and_bytes_left(
event: AnnounceEvent,
bytes_left: NumberOfBytes
) -> Self {
if event == AnnounceEvent::Stopped {
Self::Stopped
} else if bytes_left.0 == 0 {
Self::Seeding
} else {
Self::Leeching
}
}
}
#[derive(Clone, Debug)]
pub struct Peer {
pub id: PeerId,
pub connection_id: ConnectionId,
pub ip_address: IpAddr,
pub port: Port,
pub status: PeerStatus,
pub last_announce: Time
}
impl Peer {
pub fn to_response_peer(&self) -> ResponsePeer {
ResponsePeer {
ip_address: self.ip_address,
port: self.port
}
}
pub fn from_announce_and_ip(
announce_request: &AnnounceRequest,
ip_address: IpAddr
) -> Self {
Self {
id: announce_request.peer_id,
connection_id: announce_request.connection_id,
ip_address,
port: announce_request.port,
status: PeerStatus::from_event_and_bytes_left(
announce_request.event,
announce_request.bytes_left
),
last_announce: Time(Instant::now())
}
}
}
#[derive(PartialEq, Eq, Hash, Clone)]
pub struct PeerMapKey {
pub ip: IpAddr,
pub peer_id: PeerId
}
pub type PeerMap = IndexMap<PeerMapKey, Peer>;
pub struct TorrentData {
pub peers: PeerMap,
pub num_seeders: AtomicUsize,
pub num_leechers: AtomicUsize,
}
impl Default for TorrentData {
fn default() -> Self {
Self {
peers: IndexMap::new(),
num_seeders: AtomicUsize::new(0),
num_leechers: AtomicUsize::new(0),
}
}
}
pub type TorrentMap = DashMap<InfoHash, TorrentData>;
#[derive(Clone)]
pub struct State {
pub connections: Arc<ConnectionMap>,
pub torrents: Arc<TorrentMap>,
}
impl State {
pub fn new() -> Self {
Self {
connections: Arc::new(DashMap::new()),
torrents: Arc::new(DashMap::new()),
}
}
}