mirror of
https://github.com/YGGverse/aquatic.git
synced 2026-03-31 17:55:36 +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",
|
||||
]
|
||||
|
||||
[[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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -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)));
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -29,4 +29,4 @@ fn main(){
|
|||
tasks::clean_connections(&state);
|
||||
tasks::clean_torrents(&state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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