mirror of
https://github.com/YGGverse/aquatic.git
synced 2026-04-02 02:35:31 +00:00
Add quickcheck tests; actually delete types.rs file
This commit is contained in:
parent
268235c8e1
commit
c26fc942e3
6 changed files with 206 additions and 131 deletions
112
Cargo.lock
generated
112
Cargo.lock
generated
|
|
@ -9,6 +9,15 @@ dependencies = [
|
||||||
"const-random",
|
"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]]
|
[[package]]
|
||||||
name = "aquatic"
|
name = "aquatic"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
@ -18,6 +27,8 @@ dependencies = [
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"mio",
|
"mio",
|
||||||
"net2",
|
"net2",
|
||||||
|
"quickcheck",
|
||||||
|
"quickcheck_macros",
|
||||||
"rand",
|
"rand",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -77,6 +88,16 @@ dependencies = [
|
||||||
"num_cpus",
|
"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]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.1.14"
|
version = "0.1.14"
|
||||||
|
|
@ -127,6 +148,12 @@ dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mio"
|
name = "mio"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
|
|
@ -193,6 +220,47 @@ version = "0.5.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0d659fe7c6d27f25e9d80a1a094c223f5246f6a6596453e09d7229bf42750b63"
|
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]]
|
[[package]]
|
||||||
name = "rand"
|
name = "rand"
|
||||||
version = "0.7.3"
|
version = "0.7.3"
|
||||||
|
|
@ -250,6 +318,24 @@ version = "0.1.56"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
|
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]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
version = "0.3.12"
|
version = "0.3.12"
|
||||||
|
|
@ -262,6 +348,32 @@ dependencies = [
|
||||||
"winapi",
|
"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]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.9.0+wasi-snapshot-preview1"
|
version = "0.9.0+wasi-snapshot-preview1"
|
||||||
|
|
|
||||||
|
|
@ -21,3 +21,7 @@ features = ["small_rng"]
|
||||||
[dependencies.mio]
|
[dependencies.mio]
|
||||||
version = "0.7"
|
version = "0.7"
|
||||||
features = ["udp", "os-poll", "os-util"]
|
features = ["udp", "os-poll", "os-util"]
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
quickcheck = "0.9"
|
||||||
|
quickcheck_macros = "0.9"
|
||||||
|
|
@ -131,3 +131,28 @@ impl State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[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)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -182,3 +182,66 @@ pub fn create_torrent_scrape_statistics(
|
||||||
leechers: NumberOfPeers(leechers)
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue