use super::bridge_table::BridgeLine; use super::lox_creds as cred; use super::proto::*; use super::*; use base64::{engine::general_purpose, Engine}; use chrono::{DateTime, NaiveTime, Timelike, Utc}; use rand::{seq::SliceRandom, CryptoRng, RngCore}; use statistical::{mean, standard_deviation}; use std::collections::HashSet; use std::thread; use std::time::{Duration, Instant}; #[cfg(feature = "fast")] const USERS: usize = 100; #[cfg(not(feature = "fast"))] const USERS: usize = 10000; struct PerfStat { // Report performance metrics for each test req_len: usize, resp_len: usize, req_t: Duration, resp_t: Duration, resp_handle_t: Duration, } /// Create a random BridgeLine for testing #[cfg(all(test, feature = "bridgeauth", feature = "test"))] pub fn random() -> BridgeLine { let mut rng = rand::rngs::OsRng; let mut res: BridgeLine = Default::default(); // Pick a random 4-byte address let mut addr: [u8; 4] = [0; 4]; rng.fill_bytes(&mut addr); // If the leading byte is 224 or more, that's not a valid IPv4 // address. Choose an IPv6 address instead (but don't worry too // much about it being well formed). if addr[0] >= 224 { rng.fill_bytes(&mut res.addr); } else { // Store an IPv4 address as a v4-mapped IPv6 address res.addr[10] = 255; res.addr[11] = 255; res.addr[12..16].copy_from_slice(&addr); }; let ports: [u16; 4] = [443, 4433, 8080, 43079]; let portidx = (rng.next_u32() % 4) as usize; res.port = ports[portidx]; res.uid_fingerprint = rng.next_u64(); // We need different bridges to have different unhashed fingerprints rng.fill_bytes(&mut res.unhashed_fingerprint); let mut cert: [u8; 52] = [0; 52]; rng.fill_bytes(&mut cert); let infostr: String = format!( "obfs4 cert={}, iat-mode=0", general_purpose::STANDARD_NO_PAD.encode(cert) ); res.info[..infostr.len()].copy_from_slice(infostr.as_bytes()); res } struct TestHarness { bdb: BridgeDb, pub ba: BridgeAuth, } impl TestHarness { fn new_buckets(num_buckets: u16, hot_spare: u16) -> Self { let rng = &mut rand::thread_rng(); // Create a BridegDb let mut bdb = BridgeDb::new(); // Create a BridgeAuth let mut ba = BridgeAuth::new(bdb.pubkey, rng); // Make 3 x num_buckets open invitation bridges, in sets of 3 for _ in 0..num_buckets { let bucket = [random(), random(), random()]; ba.add_openinv_bridges(bucket, &mut bdb).unwrap(); } // Add hot_spare more hot spare buckets for _ in 0..hot_spare { let bucket = [random(), random(), random()]; ba.add_spare_bucket(bucket, &mut bdb).unwrap(); } // Create the encrypted bridge table ba.enc_bridge_table(); Self { bdb, ba } } fn advance_days(&mut self, days: u16) { self.ba.advance_days(days); } pub fn open_invite( &mut self, rng: &mut (impl CryptoRng + RngCore), ) -> (PerfStat, (Lox, BridgeLine)) { let invite = self.bdb.invite().unwrap(); let req_start = Instant::now(); let (req, state) = open_invite::request(rng, self.ba.lox_pub.clone()).unwrap(); let encoded: Vec = bincode::serialize(&req).unwrap(); let req_t = req_start.elapsed(); // We have to send both encoded and invite let req_len = encoded.len() + invite.len(); let resp_start = Instant::now(); let decoded = bincode::deserialize(&encoded[..]).unwrap(); let resp = self.ba.open_invitation(decoded, &invite).unwrap(); let encoded_resp: Vec = bincode::serialize(&resp).unwrap(); let resp_t = resp_start.elapsed(); let resp_len = encoded_resp.len(); let resp_handle_start = Instant::now(); let (decode_resp, bridgeline) = bincode::deserialize(&encoded_resp[..]).unwrap(); let cred = open_invite::handle_response(state, decode_resp).unwrap(); let resp_handle_t = resp_handle_start.elapsed(); ( PerfStat { req_len, resp_len, req_t, resp_t, resp_handle_t, }, (cred, bridgeline), ) } fn trust_promotion( &mut self, rng: &mut (impl CryptoRng + RngCore), cred: &cred::Lox, ) -> (PerfStat, cred::Migration) { self.advance_days( (trust_promotion::UNTRUSTED_INTERVAL + 1) .try_into() .unwrap(), ); let req_start = Instant::now(); let (promreq, promstate) = trust_promotion::request( rng, cred.clone(), self.ba.migrationkey_pub.clone(), self.ba.today(), ) .unwrap(); let encoded: Vec = bincode::serialize(&promreq).unwrap(); let req_t = req_start.elapsed(); let req_len = encoded.len(); let resp_start = Instant::now(); let decoded = bincode::deserialize(&encoded[..]).unwrap(); let promresp = self.ba.handle_trust_promotion(decoded).unwrap(); let encoded_resp: Vec = bincode::serialize(&promresp).unwrap(); let resp_t = resp_start.elapsed(); let resp_len = encoded_resp.len(); let resp_handle_start = Instant::now(); let (decode_resp, enc) = bincode::deserialize(&encoded_resp[..]).unwrap(); let migcred = trust_promotion::handle_response( self.ba.migration_pub.clone(), promstate, decode_resp, enc, ) .unwrap(); let resp_handle_t = resp_handle_start.elapsed(); ( PerfStat { req_len, resp_len, req_t, resp_t, resp_handle_t, }, migcred, ) } fn migration( &mut self, rng: &mut (impl CryptoRng + RngCore), loxcred: &cred::Lox, migcred: &cred::Migration, ) -> (PerfStat, cred::Lox) { let req_start = Instant::now(); let (migreq, migstate) = migration::request(rng, loxcred.clone(), migcred.clone()).unwrap(); let encoded: Vec = bincode::serialize(&migreq).unwrap(); let req_t = req_start.elapsed(); let req_len = encoded.len(); let resp_start = Instant::now(); let decoded = bincode::deserialize(&encoded[..]).unwrap(); let migresp = self.ba.handle_migration(decoded).unwrap(); let encoded_resp: Vec = bincode::serialize(&migresp).unwrap(); let resp_t = resp_start.elapsed(); let resp_len = encoded_resp.len(); let resp_handle_start = Instant::now(); let decode_resp: migration::migration::Reply = bincode::deserialize(&encoded_resp[..]).unwrap(); let cred = migration::handle_response(migstate, decode_resp).unwrap(); let resp_handle_t = resp_handle_start.elapsed(); ( PerfStat { req_len, resp_len, req_t, resp_t, resp_handle_t, }, cred, ) } pub fn reach_cred(&mut self, cred: Lox) -> BucketReachability { let bucket = self.get_bucket(cred); bucket.1.unwrap() } pub fn get_bucket( &mut self, cred: Lox, ) -> ( [BridgeLine; MAX_BRIDGES_PER_BUCKET], Option, ) { let (id, key) = bridge_table::from_scalar(cred.bucket.unwrap()).unwrap(); let encbuckets = self.ba.enc_bridge_table().clone(); let reach_pub = self.ba.reachability_pub.clone(); bridge_table::BridgeTable::decrypt_bucket( id, &key, encbuckets.get(&id).unwrap(), &reach_pub, ) .unwrap() } fn level_up( &mut self, rng: &mut (impl CryptoRng + RngCore), cred: &cred::Lox, ) -> (PerfStat, cred::Lox) { self.advance_days( (level_up::LEVEL_INTERVAL[scalar_u32(&cred.trust_level.unwrap()).unwrap() as usize] + 1) .try_into() .unwrap(), ); let reachcred = self.reach_cred(cred.clone()); // Use the Bucket Reachability credential to advance to the next // level let req_start = Instant::now(); let (req, state) = level_up::request(rng, cred.clone(), reachcred, self.ba.today()).unwrap(); let encoded: Vec = bincode::serialize(&req).unwrap(); let req_t = req_start.elapsed(); let req_len = encoded.len(); let resp_start = Instant::now(); let decoded = bincode::deserialize(&encoded[..]).unwrap(); let resp = self.ba.handle_level_up(decoded).unwrap(); let encoded_resp: Vec = bincode::serialize(&resp).unwrap(); let resp_t = resp_start.elapsed(); let resp_len = encoded_resp.len(); let resp_handle_start = Instant::now(); let decode_resp = bincode::deserialize(&encoded_resp[..]).unwrap(); let cred = level_up::handle_response(state, decode_resp).unwrap(); let resp_handle_t = resp_handle_start.elapsed(); ( PerfStat { req_len, resp_len, req_t, resp_t, resp_handle_t, }, cred, ) } fn issue_invite( &mut self, rng: &mut (impl CryptoRng + RngCore), cred: &cred::Lox, ) -> (PerfStat, (cred::Lox, cred::Invitation)) { let reachcred = self.reach_cred(cred.clone()); let req_start = Instant::now(); let (req, state) = issue_invite::request( rng, cred.clone(), reachcred, self.ba.invitation_pub.clone(), self.ba.today(), ) .unwrap(); let encoded: Vec = bincode::serialize(&req).unwrap(); let req_t = req_start.elapsed(); let req_len = encoded.len(); let resp_start = Instant::now(); let decoded = bincode::deserialize(&encoded[..]).unwrap(); let resp = self.ba.handle_issue_invite(decoded).unwrap(); let encoded_resp: Vec = bincode::serialize(&resp).unwrap(); let resp_t = resp_start.elapsed(); let resp_len = encoded_resp.len(); let resp_handle_start = Instant::now(); let decode_resp = bincode::deserialize(&encoded_resp[..]).unwrap(); let (cred, invite) = issue_invite::handle_response(state, decode_resp).unwrap(); let resp_handle_t = resp_handle_start.elapsed(); ( PerfStat { req_len, resp_len, req_t, resp_t, resp_handle_t, }, (invite, cred), ) } fn redeem_invite( &mut self, rng: &mut (impl CryptoRng + RngCore), inv: &cred::Invitation, ) -> (PerfStat, cred::Lox) { let req_start = Instant::now(); let (req, state) = redeem_invite::request(rng, inv.clone(), self.ba.lox_pub.clone(), self.ba.today()) .unwrap(); let encoded: Vec = bincode::serialize(&req).unwrap(); let req_t = req_start.elapsed(); let req_len = encoded.len(); let resp_start = Instant::now(); let decoded = bincode::deserialize(&encoded[..]).unwrap(); let resp = self.ba.handle_redeem_invite(decoded).unwrap(); let encoded_resp: Vec = bincode::serialize(&resp).unwrap(); let resp_t = resp_start.elapsed(); let resp_len = encoded_resp.len(); let resp_handle_start = Instant::now(); let decode_resp = bincode::deserialize(&encoded_resp[..]).unwrap(); let cred = redeem_invite::handle_response(state, decode_resp).unwrap(); let resp_handle_t = resp_handle_start.elapsed(); ( PerfStat { req_len, resp_len, req_t, resp_t, resp_handle_t, }, cred, ) } fn check_blockage( &mut self, rng: &mut (impl CryptoRng + RngCore), cred: &cred::Lox, ) -> (PerfStat, cred::Migration) { let req_start = Instant::now(); let (req, state) = check_blockage::request(rng, cred.clone(), self.ba.migrationkey_pub.clone()).unwrap(); let encoded: Vec = bincode::serialize(&req).unwrap(); let req_t = req_start.elapsed(); let req_len = encoded.len(); let resp_start = Instant::now(); let decoded = bincode::deserialize(&encoded[..]).unwrap(); let resp = self.ba.handle_check_blockage(decoded).unwrap(); let encoded_resp: Vec = bincode::serialize(&resp).unwrap(); let resp_t = resp_start.elapsed(); let resp_len = encoded_resp.len(); let resp_handle_start = Instant::now(); let (decode_resp, enc) = bincode::deserialize(&encoded_resp[..]).unwrap(); let migcred = check_blockage::handle_response(self.ba.migration_pub.clone(), state, decode_resp, enc) .unwrap(); let resp_handle_t = resp_handle_start.elapsed(); ( PerfStat { req_len, resp_len, req_t, resp_t, resp_handle_t, }, migcred, ) } fn blockage_migration( &mut self, rng: &mut (impl CryptoRng + RngCore), cred: &cred::Lox, mig: &cred::Migration, ) -> (PerfStat, cred::Lox) { let req_start = Instant::now(); let (req, state) = blockage_migration::request(rng, cred.clone(), mig.clone()).unwrap(); let encoded: Vec = bincode::serialize(&req).unwrap(); let req_t = req_start.elapsed(); let req_len = encoded.len(); let resp_start = Instant::now(); let decoded = bincode::deserialize(&encoded[..]).unwrap(); let resp = self.ba.handle_blockage_migration(decoded).unwrap(); let encoded_resp: Vec = bincode::serialize(&resp).unwrap(); let resp_t = resp_start.elapsed(); let resp_len = encoded_resp.len(); let resp_handle_start = Instant::now(); let decode_resp: blockage_migration::blockage_migration::Reply = bincode::deserialize(&encoded_resp[..]).unwrap(); let cred = blockage_migration::handle_response(state, decode_resp).unwrap(); let resp_handle_t = resp_handle_start.elapsed(); ( PerfStat { req_len, resp_len, req_t, resp_t, resp_handle_t, }, cred, ) } fn report_submit( &mut self, rng: &mut (impl CryptoRng + RngCore), cred: &cred::Lox, resolve_cred: &cred::Resolve, bridges_being_reported: [bool; MAX_BRIDGES_PER_BUCKET], ) -> (PerfStat, cred::Lox) { let req_start = Instant::now(); let ((req, state), cc, D, bridges_being_reported) = report_submit::request( rng, cred.clone(), resolve_cred.clone(), report_table::CountryCode::RU, bridges_being_reported, ) .unwrap(); let encoded: Vec = bincode::serialize(&(req, cc, D, bridges_being_reported)).unwrap(); let req_t = req_start.elapsed(); let req_len = encoded.len(); let resp_start = Instant::now(); let (decoded, cc, D, bridges_being_reported) = bincode::deserialize(&encoded[..]).unwrap(); let resp = self .ba .handle_report_submit(decoded, cc, D, bridges_being_reported) .unwrap(); let encoded_resp: Vec = bincode::serialize(&resp).unwrap(); let resp_t = resp_start.elapsed(); let resp_len = encoded_resp.len(); let resp_handle_start = Instant::now(); let decode_resp = bincode::deserialize(&encoded_resp[..]).unwrap(); let cred = report_submit::handle_response(state, decode_resp).unwrap(); let resp_handle_t = resp_handle_start.elapsed(); ( PerfStat { req_len, resp_len, req_t, resp_t, resp_handle_t, }, cred, ) } fn report_status( &mut self, rng: &mut (impl CryptoRng + RngCore), cred: &cred::Lox, ) -> (PerfStat, (cred::Lox, cred::Resolve)) { let req_start = Instant::now(); let (req, state) = report_status::request(rng, cred.clone(), self.ba.resolve_pub.clone()).unwrap(); let encoded: Vec = bincode::serialize(&req).unwrap(); let req_t = req_start.elapsed(); let req_len = encoded.len(); let resp_start = Instant::now(); let decoded = bincode::deserialize(&encoded[..]).unwrap(); let resp = self.ba.handle_report_status(decoded).unwrap(); let encoded_resp: Vec = bincode::serialize(&resp).unwrap(); let resp_t = resp_start.elapsed(); let resp_len = encoded_resp.len(); let resp_handle_start = Instant::now(); let decode_resp = bincode::deserialize(&encoded_resp[..]).unwrap(); let (cred, resolve_cred) = report_status::handle_response(state, decode_resp).unwrap(); let resp_handle_t = resp_handle_start.elapsed(); ( PerfStat { req_len, resp_len, req_t, resp_t, resp_handle_t, }, (cred, resolve_cred), ) } fn report_resolve( &mut self, rng: &mut (impl CryptoRng + RngCore), cred: &cred::Lox, resolve_cred: &cred::Resolve, ) -> (PerfStat, cred::Lox) { let req_start = Instant::now(); let (req, state) = report_resolve::request(rng, cred.clone(), resolve_cred.clone()).unwrap(); let encoded: Vec = bincode::serialize(&req).unwrap(); let req_t = req_start.elapsed(); let req_len = encoded.len(); let resp_start = Instant::now(); let decoded = bincode::deserialize(&encoded[..]).unwrap(); let resp = self.ba.handle_report_resolve(decoded).unwrap(); let encoded_resp: Vec = bincode::serialize(&resp).unwrap(); let resp_t = resp_start.elapsed(); let resp_len = encoded_resp.len(); let resp_handle_start = Instant::now(); let decode_resp = bincode::deserialize(&encoded_resp[..]).unwrap(); let cred = report_resolve::handle_response(state, decode_resp).unwrap(); let resp_handle_t = resp_handle_start.elapsed(); ( PerfStat { req_len, resp_len, req_t, resp_t, resp_handle_t, }, cred, ) } } #[test] fn stats_test_trust_levels() { let buckets: Vec = vec![600]; let mut rng = rand::thread_rng(); for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut promo_req_size: Vec = Vec::new(); let mut promo_resp_size: Vec = Vec::new(); let mut promo_req_time: Vec = Vec::new(); let mut promo_resp_time: Vec = Vec::new(); let mut promo_resp_handle_time: Vec = Vec::new(); let mut mig_req_size: Vec = Vec::new(); let mut mig_resp_size: Vec = Vec::new(); let mut mig_req_time: Vec = Vec::new(); let mut mig_resp_time: Vec = Vec::new(); let mut mig_resp_handle_time: Vec = Vec::new(); let mut sec_req_size: Vec = Vec::new(); let mut sec_resp_size: Vec = Vec::new(); let mut sec_req_time: Vec = Vec::new(); let mut sec_resp_time: Vec = Vec::new(); let mut sec_resp_handle_time: Vec = Vec::new(); let mut three_req_size: Vec = Vec::new(); let mut three_resp_size: Vec = Vec::new(); let mut three_req_time: Vec = Vec::new(); let mut three_resp_time: Vec = Vec::new(); let mut three_resp_handle_time: Vec = Vec::new(); let mut four_req_size: Vec = Vec::new(); let mut four_resp_size: Vec = Vec::new(); let mut four_req_time: Vec = Vec::new(); let mut four_resp_time: Vec = Vec::new(); let mut four_resp_handle_time: Vec = Vec::new(); let mut open_req_size: Vec = Vec::new(); let mut open_resp_size: Vec = Vec::new(); let mut open_req_time: Vec = Vec::new(); let mut open_resp_time: Vec = Vec::new(); let mut open_resp_handle_time: Vec = Vec::new(); for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let (open_perf_stat, cred) = th.open_invite(&mut rng); th.advance_days(30); let (tp_perf_stat, migcred) = th.trust_promotion(&mut rng, &cred.0); let (mig_perf_stat, cred1) = th.migration(&mut rng, &cred.0, &migcred); th.advance_days(14); let (sec_perf_stat, cred2) = th.level_up(&mut rng, &cred1); th.advance_days(28); let (three_perf_stat, cred3) = th.level_up(&mut rng, &cred2); th.advance_days(56); let (four_perf_stat, _) = th.level_up(&mut rng, &cred3); open_req_size.push(open_perf_stat.req_len as f64); open_req_time.push(open_perf_stat.req_t.as_secs_f64()); open_resp_size.push(open_perf_stat.resp_len as f64); open_resp_time.push(open_perf_stat.resp_t.as_secs_f64()); open_resp_handle_time.push(open_perf_stat.resp_handle_t.as_secs_f64()); promo_req_size.push(tp_perf_stat.req_len as f64); promo_req_time.push(tp_perf_stat.req_t.as_secs_f64()); promo_resp_size.push(tp_perf_stat.resp_len as f64); promo_resp_time.push(tp_perf_stat.resp_t.as_secs_f64()); promo_resp_handle_time.push(tp_perf_stat.resp_handle_t.as_secs_f64()); mig_req_size.push(mig_perf_stat.req_len as f64); mig_req_time.push(mig_perf_stat.req_t.as_secs_f64()); mig_resp_size.push(mig_perf_stat.resp_len as f64); mig_resp_time.push(mig_perf_stat.resp_t.as_secs_f64()); mig_resp_handle_time.push(mig_perf_stat.resp_handle_t.as_secs_f64()); sec_req_size.push(sec_perf_stat.req_len as f64); sec_req_time.push(sec_perf_stat.req_t.as_secs_f64()); sec_resp_size.push(sec_perf_stat.resp_len as f64); sec_resp_time.push(sec_perf_stat.resp_t.as_secs_f64()); sec_resp_handle_time.push(sec_perf_stat.resp_handle_t.as_secs_f64()); three_req_size.push(three_perf_stat.req_len as f64); three_req_time.push(three_perf_stat.req_t.as_secs_f64()); three_resp_size.push(three_perf_stat.resp_len as f64); three_resp_time.push(three_perf_stat.resp_t.as_secs_f64()); three_resp_handle_time.push(three_perf_stat.resp_handle_t.as_secs_f64()); four_req_size.push(four_perf_stat.req_len as f64); four_req_time.push(four_perf_stat.req_t.as_secs_f64()); four_resp_size.push(four_perf_stat.resp_len as f64); four_resp_time.push(four_perf_stat.resp_t.as_secs_f64()); four_resp_handle_time.push(four_perf_stat.resp_handle_t.as_secs_f64()); } println!("\n***START: {}*3*2 BUCKETS LEVELS***\n", x); println!("\n----OPEN-INVITATION-{}---\n", x); print_stats_test_results( open_req_size, open_req_time, open_resp_size, open_resp_time, open_resp_handle_time, ); println!("\n----TRUST-PROMOTION-1: 30 days-{}---\n", x); print_stats_test_results( promo_req_size, promo_req_time, promo_resp_size, promo_resp_time, promo_resp_handle_time, ); println!("\n----TRUST-MIGRATION-0: 30 days-{}---\n", x); print_stats_test_results( mig_req_size, mig_req_time, mig_resp_size, mig_resp_time, mig_resp_handle_time, ); println!("\n----LEVEL-UP-2: 44 days-{}---\n", x); print_stats_test_results( sec_req_size, sec_req_time, sec_resp_size, sec_resp_time, sec_resp_handle_time, ); println!("\n----LEVEL-UP-3: 72 days---{}---\n", x); print_stats_test_results( three_req_size, three_req_time, three_resp_size, three_resp_time, three_resp_handle_time, ); println!("\n----LEVEL-UP-4: 128 days---{}---\n", x); print_stats_test_results( four_req_size, four_req_time, four_resp_size, four_resp_time, four_resp_handle_time, ); } } #[test] fn stats_test_invitations() { let buckets: Vec = vec![600]; let mut rng = rand::thread_rng(); for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut req_size: Vec = Vec::new(); let mut resp_size: Vec = Vec::new(); let mut req_time: Vec = Vec::new(); let mut resp_time: Vec = Vec::new(); let mut resp_handle_time: Vec = Vec::new(); let mut red_req_size: Vec = Vec::new(); let mut red_resp_size: Vec = Vec::new(); let mut red_req_time: Vec = Vec::new(); let mut red_resp_time: Vec = Vec::new(); let mut red_resp_handle_time: Vec = Vec::new(); for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite(&mut rng).1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&mut rng, &cred); let (_, cred1) = th.migration(&mut rng, &cred, &migcred); th.advance_days(14); let (_, cred2) = th.level_up(&mut rng, &cred1); th.advance_days(28); let (perf_stat, (_, invite)) = th.issue_invite(&mut rng, &cred2); let (bob_perf_stat, _) = th.redeem_invite(&mut rng, &invite); req_size.push(perf_stat.req_len as f64); req_time.push(perf_stat.req_t.as_secs_f64()); resp_size.push(perf_stat.resp_len as f64); resp_time.push(perf_stat.resp_t.as_secs_f64()); resp_handle_time.push(perf_stat.resp_handle_t.as_secs_f64()); red_req_size.push(bob_perf_stat.req_len as f64); red_req_time.push(bob_perf_stat.req_t.as_secs_f64()); red_resp_size.push(bob_perf_stat.resp_len as f64); red_resp_time.push(bob_perf_stat.resp_t.as_secs_f64()); red_resp_handle_time.push(bob_perf_stat.resp_handle_t.as_secs_f64()); } println!("\n***START: {}*3*2 BUCKETS INVITATIONS***\n", x); println!("\n----ISSUE-INVITATION-{}---\n", x); print_stats_test_results(req_size, req_time, resp_size, resp_time, resp_handle_time); println!("\n----REDEEM-INVITATION-{}---\n", x); print_stats_test_results( red_req_size, red_req_time, red_resp_size, red_resp_time, red_resp_handle_time, ); } } #[test] fn stats_test_percent_blockage_migration_05() { let buckets: Vec = vec![600]; let mut rng = rand::thread_rng(); for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite(&mut rng).1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&mut rng, &cred); let (_, cred1) = th.migration(&mut rng, &cred, &migcred); th.advance_days(14); let (_, cred2) = th.level_up(&mut rng, &cred1); let (_, (cred2a, invite)) = th.issue_invite(&mut rng, &cred2); let (_, bob_cred) = th.redeem_invite(&mut rng, &invite); th.advance_days(28); let (_, _) = th.level_up(&mut rng, &bob_cred); let (_, cred3) = th.level_up(&mut rng, &cred2a); credentials.push(cred3); } println!("\n***START: {}*3*2 BUCKETS 5***\n", x); block_bridges(&mut th, 5, credentials); } } #[test] fn stats_test_percent_blockage_migration_010() { let buckets: Vec = vec![600]; let mut rng = rand::thread_rng(); for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite(&mut rng).1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&mut rng, &cred); let (_, cred1) = th.migration(&mut rng, &cred, &migcred); th.advance_days(14); let (_, cred2) = th.level_up(&mut rng, &cred1); let (_, (cred2a, invite)) = th.issue_invite(&mut rng, &cred2); let (_, bob_cred) = th.redeem_invite(&mut rng, &invite); th.advance_days(28); let (_, _) = th.level_up(&mut rng, &bob_cred); let (_, cred3) = th.level_up(&mut rng, &cred2a); credentials.push(cred3); } println!("\n***START: {}*3*2 BUCKETS 10***\n", x); block_bridges(&mut th, 10, credentials); } } #[test] fn stats_test_percent_blockage_migration_15() { let buckets: Vec = vec![600]; let mut rng = rand::thread_rng(); for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite(&mut rng).1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&mut rng, &cred); let (_, cred1) = th.migration(&mut rng, &cred, &migcred); th.advance_days(14); let (_, cred2) = th.level_up(&mut rng, &cred1); let (_, (cred2a, invite)) = th.issue_invite(&mut rng, &cred2); let (_, bob_cred) = th.redeem_invite(&mut rng, &invite); th.advance_days(28); let (_, _) = th.level_up(&mut rng, &bob_cred); let (_, cred3) = th.level_up(&mut rng, &cred2a); credentials.push(cred3); } println!("\n***START: {}*3*2 BUCKETS 15***\n", x); block_bridges(&mut th, 15, credentials); } } #[test] fn stats_test_percent_blockage_migration_20() { let buckets: Vec = vec![600]; let mut rng = rand::thread_rng(); for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite(&mut rng).1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&mut rng, &cred); let (_, cred1) = th.migration(&mut rng, &cred, &migcred); th.advance_days(14); let (_, cred2) = th.level_up(&mut rng, &cred1); let (_, (cred2a, invite)) = th.issue_invite(&mut rng, &cred2); let (_, bob_cred) = th.redeem_invite(&mut rng, &invite); th.advance_days(28); let (_, _) = th.level_up(&mut rng, &bob_cred); let (_, cred3) = th.level_up(&mut rng, &cred2a); credentials.push(cred3); } println!("\n***START: {}*3*2 BUCKETS 20***\n", x); block_bridges(&mut th, 20, credentials); } } #[test] fn stats_test_percent_blockage_migration_25() { let buckets: Vec = vec![600]; let mut rng = rand::thread_rng(); for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite(&mut rng).1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&mut rng, &cred); let (_, cred1) = th.migration(&mut rng, &cred, &migcred); th.advance_days(14); let (_, cred2) = th.level_up(&mut rng, &cred1); let (_, (cred2a, invite)) = th.issue_invite(&mut rng, &cred2); let (_, bob_cred) = th.redeem_invite(&mut rng, &invite); th.advance_days(28); let (_, _) = th.level_up(&mut rng, &bob_cred); let (_, cred3) = th.level_up(&mut rng, &cred2a); credentials.push(cred3); } println!("\n***START: {}*3*2 BUCKETS 25***\n", x); block_bridges(&mut th, 25, credentials); } } #[test] fn stats_test_percent_blockage_migration_30() { let buckets: Vec = vec![600]; let mut rng = rand::thread_rng(); for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite(&mut rng).1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&mut rng, &cred); let (_, cred1) = th.migration(&mut rng, &cred, &migcred); th.advance_days(14); let (_, cred2) = th.level_up(&mut rng, &cred1); let (_, (cred2a, invite)) = th.issue_invite(&mut rng, &cred2); let (_, bob_cred) = th.redeem_invite(&mut rng, &invite); th.advance_days(28); let (_, _) = th.level_up(&mut rng, &bob_cred); let (_, cred3) = th.level_up(&mut rng, &cred2a); credentials.push(cred3); } println!("\n***START: {}*3*2 BUCKETS 30***\n", x); block_bridges(&mut th, 30, credentials); } } #[test] fn stats_test_percent_blockage_migration_35() { let buckets: Vec = vec![600]; let mut rng = rand::thread_rng(); for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite(&mut rng).1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&mut rng, &cred); let (_, cred1) = th.migration(&mut rng, &cred, &migcred); th.advance_days(14); let (_, cred2) = th.level_up(&mut rng, &cred1); let (_, (cred2a, invite)) = th.issue_invite(&mut rng, &cred2); let (_, bob_cred) = th.redeem_invite(&mut rng, &invite); th.advance_days(28); let (_, _) = th.level_up(&mut rng, &bob_cred); let (_, cred3) = th.level_up(&mut rng, &cred2a); credentials.push(cred3); } println!("\n***START: {}*3*2 BUCKETS 35***\n", x); block_bridges(&mut th, 35, credentials); } } #[test] fn stats_test_percent_blockage_migration_40() { let buckets: Vec = vec![600]; let mut rng = rand::thread_rng(); for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite(&mut rng).1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&mut rng, &cred); let (_, cred1) = th.migration(&mut rng, &cred, &migcred); th.advance_days(14); let (_, cred2) = th.level_up(&mut rng, &cred1); let (_, (cred2a, invite)) = th.issue_invite(&mut rng, &cred2); let (_, bob_cred) = th.redeem_invite(&mut rng, &invite); th.advance_days(28); let (_, _) = th.level_up(&mut rng, &bob_cred); let (_, cred3) = th.level_up(&mut rng, &cred2a); credentials.push(cred3); } println!("\n***START: {}*3*2 BUCKETS 40***\n", x); block_bridges(&mut th, 40, credentials); } } #[test] fn stats_test_percent_blockage_migration_45() { let buckets: Vec = vec![600]; let mut rng = rand::thread_rng(); for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite(&mut rng).1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&mut rng, &cred); let (_, cred1) = th.migration(&mut rng, &cred, &migcred); th.advance_days(14); let (_, cred2) = th.level_up(&mut rng, &cred1); let (_, (cred2a, invite)) = th.issue_invite(&mut rng, &cred2); let (_, bob_cred) = th.redeem_invite(&mut rng, &invite); th.advance_days(28); let (_, _) = th.level_up(&mut rng, &bob_cred); let (_, cred3) = th.level_up(&mut rng, &cred2a); credentials.push(cred3); } println!("\n***START: {}*3*2 BUCKETS 45***\n", x); block_bridges(&mut th, 45, credentials); } } #[test] fn stats_test_percent_blockage_migration_50() { let buckets: Vec = vec![600]; let mut rng = rand::thread_rng(); for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite(&mut rng).1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&mut rng, &cred); let (_, cred1) = th.migration(&mut rng, &cred, &migcred); th.advance_days(14); let (_, cred2) = th.level_up(&mut rng, &cred1); let (_, (cred2a, invite)) = th.issue_invite(&mut rng, &cred2); let (_, bob_cred) = th.redeem_invite(&mut rng, &invite); th.advance_days(28); let (_, _) = th.level_up(&mut rng, &bob_cred); let (_, cred3) = th.level_up(&mut rng, &cred2a); credentials.push(cred3); } println!("\n***START: {}*3*2 BUCKETS 50***\n", x); block_bridges(&mut th, 50, credentials); } } #[test] fn stats_test_percent_blockage_migration_55() { let buckets: Vec = vec![600]; let mut rng = rand::thread_rng(); for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite(&mut rng).1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&mut rng, &cred); let (_, cred1) = th.migration(&mut rng, &cred, &migcred); th.advance_days(14); let (_, cred2) = th.level_up(&mut rng, &cred1); let (_, (cred2a, invite)) = th.issue_invite(&mut rng, &cred2); let (_, bob_cred) = th.redeem_invite(&mut rng, &invite); th.advance_days(28); let (_, _) = th.level_up(&mut rng, &bob_cred); let (_, cred3) = th.level_up(&mut rng, &cred2a); credentials.push(cred3); } println!("\n***START: {}*3*2 BUCKETS 55***\n", x); block_bridges(&mut th, 55, credentials); } } #[test] fn stats_test_percent_blockage_migration_60() { let buckets: Vec = vec![600]; let mut rng = rand::thread_rng(); for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite(&mut rng).1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&mut rng, &cred); let (_, cred1) = th.migration(&mut rng, &cred, &migcred); th.advance_days(14); let (_, cred2) = th.level_up(&mut rng, &cred1); let (_, (cred2a, invite)) = th.issue_invite(&mut rng, &cred2); let (_, bob_cred) = th.redeem_invite(&mut rng, &invite); th.advance_days(28); let (_, _) = th.level_up(&mut rng, &bob_cred); let (_, cred3) = th.level_up(&mut rng, &cred2a); credentials.push(cred3); } println!("\n***START: {}*3*2 BUCKETS 60***\n", x); block_bridges(&mut th, 60, credentials); } } #[test] fn stats_test_percent_blockage_migration_65() { let buckets: Vec = vec![600]; let mut rng = rand::thread_rng(); for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite(&mut rng).1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&mut rng, &cred); let (_, cred1) = th.migration(&mut rng, &cred, &migcred); th.advance_days(14); let (_, cred2) = th.level_up(&mut rng, &cred1); let (_, (cred2a, invite)) = th.issue_invite(&mut rng, &cred2); let (_, bob_cred) = th.redeem_invite(&mut rng, &invite); th.advance_days(28); let (_, _) = th.level_up(&mut rng, &bob_cred); let (_, cred3) = th.level_up(&mut rng, &cred2a); credentials.push(cred3); } println!("\n***START: {}*3*2 BUCKETS 65***\n", x); block_bridges(&mut th, 65, credentials); } } #[test] fn stats_test_percent_blockage_migration_70() { let buckets: Vec = vec![600]; let mut rng = rand::thread_rng(); for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite(&mut rng).1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&mut rng, &cred); let (_, cred1) = th.migration(&mut rng, &cred, &migcred); th.advance_days(14); let (_, cred2) = th.level_up(&mut rng, &cred1); let (_, (cred2a, invite)) = th.issue_invite(&mut rng, &cred2); let (_, bob_cred) = th.redeem_invite(&mut rng, &invite); th.advance_days(28); let (_, _) = th.level_up(&mut rng, &bob_cred); let (_, cred3) = th.level_up(&mut rng, &cred2a); credentials.push(cred3); } println!("\n***START: {}*3*2 BUCKETS 70***\n", x); block_bridges(&mut th, 70, credentials); } } #[test] fn stats_test_percent_blockage_migration_75() { let buckets: Vec = vec![600]; let mut rng = rand::thread_rng(); for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite(&mut rng).1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&mut rng, &cred); let (_, cred1) = th.migration(&mut rng, &cred, &migcred); th.advance_days(14); let (_, cred2) = th.level_up(&mut rng, &cred1); let (_, (cred2a, invite)) = th.issue_invite(&mut rng, &cred2); let (_, bob_cred) = th.redeem_invite(&mut rng, &invite); th.advance_days(28); let (_, _) = th.level_up(&mut rng, &bob_cred); let (_, cred3) = th.level_up(&mut rng, &cred2a); credentials.push(cred3); } println!("\n***START: {}*3*2 BUCKETS 75***\n", x); block_bridges(&mut th, 75, credentials); } } #[test] fn stats_test_percent_blockage_migration_80() { let buckets: Vec = vec![600]; let mut rng = rand::thread_rng(); for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite(&mut rng).1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&mut rng, &cred); let (_, cred1) = th.migration(&mut rng, &cred, &migcred); th.advance_days(14); let (_, cred2) = th.level_up(&mut rng, &cred1); let (_, (cred2a, invite)) = th.issue_invite(&mut rng, &cred2); let (_, bob_cred) = th.redeem_invite(&mut rng, &invite); th.advance_days(28); let (_, _) = th.level_up(&mut rng, &bob_cred); let (_, cred3) = th.level_up(&mut rng, &cred2a); credentials.push(cred3); } println!("\n***START: {}*3*2 BUCKETS 80***\n", x); block_bridges(&mut th, 80, credentials); } } #[test] fn stats_test_percent_blockage_migration_85() { let buckets: Vec = vec![600]; let mut rng = rand::thread_rng(); for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite(&mut rng).1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&mut rng, &cred); let (_, cred1) = th.migration(&mut rng, &cred, &migcred); th.advance_days(14); let (_, cred2) = th.level_up(&mut rng, &cred1); let (_, (cred2a, invite)) = th.issue_invite(&mut rng, &cred2); let (_, bob_cred) = th.redeem_invite(&mut rng, &invite); th.advance_days(28); let (_, _) = th.level_up(&mut rng, &bob_cred); let (_, cred3) = th.level_up(&mut rng, &cred2a); credentials.push(cred3); } println!("\n***START: {}*3*2 BUCKETS 85***\n", x); block_bridges(&mut th, 85, credentials); } } #[test] fn stats_test_percent_blockage_migration_90() { let buckets: Vec = vec![600]; let mut rng = rand::thread_rng(); for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite(&mut rng).1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&mut rng, &cred); let (_, cred1) = th.migration(&mut rng, &cred, &migcred); th.advance_days(14); let (_, cred2) = th.level_up(&mut rng, &cred1); let (_, (cred2a, invite)) = th.issue_invite(&mut rng, &cred2); let (_, bob_cred) = th.redeem_invite(&mut rng, &invite); th.advance_days(28); let (_, _) = th.level_up(&mut rng, &bob_cred); let (_, cred3) = th.level_up(&mut rng, &cred2a); credentials.push(cred3); } println!("\n***START: {}*3*2 BUCKETS 90***\n", x); block_bridges(&mut th, 90, credentials); } } #[test] fn stats_test_percent_blockage_migration_95() { let buckets: Vec = vec![600]; let mut rng = rand::thread_rng(); for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite(&mut rng).1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&mut rng, &cred); let (_, cred1) = th.migration(&mut rng, &cred, &migcred); th.advance_days(14); let (_, cred2) = th.level_up(&mut rng, &cred1); let (_, (cred2a, invite)) = th.issue_invite(&mut rng, &cred2); let (_, bob_cred) = th.redeem_invite(&mut rng, &invite); th.advance_days(28); let (_, _) = th.level_up(&mut rng, &bob_cred); let (_, cred3) = th.level_up(&mut rng, &cred2a); credentials.push(cred3); } println!("\n***START: {}*3*2 BUCKETS 95***\n", x); block_bridges(&mut th, 95, credentials); } } #[test] fn stats_test_percent_blockage_migration_100() { let buckets: Vec = vec![600]; let mut rng = rand::thread_rng(); for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite(&mut rng).1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&mut rng, &cred); let (_, cred1) = th.migration(&mut rng, &cred, &migcred); th.advance_days(14); let (_, cred2) = th.level_up(&mut rng, &cred1); let (_, (cred2a, invite)) = th.issue_invite(&mut rng, &cred2); let (_, bob_cred) = th.redeem_invite(&mut rng, &invite); th.advance_days(28); let (_, _) = th.level_up(&mut rng, &bob_cred); let (_, cred3) = th.level_up(&mut rng, &cred2a); credentials.push(cred3); } println!("\n***START: {}*3*2 BUCKETS 100***\n", x); block_bridges(&mut th, 100, credentials); } } #[test] fn stats_test_reporting() { let buckets: Vec = vec![600]; let mut rng = rand::thread_rng(); for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut lv0_submit_req_size: Vec = Vec::new(); let mut lv0_submit_resp_size: Vec = Vec::new(); let mut lv0_submit_req_time: Vec = Vec::new(); let mut lv0_submit_resp_time: Vec = Vec::new(); let mut lv0_submit_resp_handle_time: Vec = Vec::new(); let mut lv0_status_req_size: Vec = Vec::new(); let mut lv0_status_resp_size: Vec = Vec::new(); let mut lv0_status_req_time: Vec = Vec::new(); let mut lv0_status_resp_time: Vec = Vec::new(); let mut lv0_status_resp_handle_time: Vec = Vec::new(); let mut lv0_resolve_req_size: Vec = Vec::new(); let mut lv0_resolve_resp_size: Vec = Vec::new(); let mut lv0_resolve_req_time: Vec = Vec::new(); let mut lv0_resolve_resp_time: Vec = Vec::new(); let mut lv0_resolve_resp_handle_time: Vec = Vec::new(); let mut lv1_submit_req_size: Vec = Vec::new(); let mut lv1_submit_resp_size: Vec = Vec::new(); let mut lv1_submit_req_time: Vec = Vec::new(); let mut lv1_submit_resp_time: Vec = Vec::new(); let mut lv1_submit_resp_handle_time: Vec = Vec::new(); let mut lv1_status_req_size: Vec = Vec::new(); let mut lv1_status_resp_size: Vec = Vec::new(); let mut lv1_status_req_time: Vec = Vec::new(); let mut lv1_status_resp_time: Vec = Vec::new(); let mut lv1_status_resp_handle_time: Vec = Vec::new(); let mut lv1_resolve_req_size: Vec = Vec::new(); let mut lv1_resolve_resp_size: Vec = Vec::new(); let mut lv1_resolve_req_time: Vec = Vec::new(); let mut lv1_resolve_resp_time: Vec = Vec::new(); let mut lv1_resolve_resp_handle_time: Vec = Vec::new(); for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let (_, (cred, _)) = th.open_invite(&mut rng); let bucket = th.get_bucket(cred.clone()).0; let resolve_cred = th.ba.get_resolve_cred_for_new_session(&mut rng); let (lv0_submit_perf_stat, cred) = th.report_submit(&mut rng, &cred, &resolve_cred, [true, false, false]); th.ba.report_table.process_scan_result( &bucket[0].get_hashed_fingerprint(), report_table::CountryCode::RU, report_table::ReportStatus::NotBlocked, ); let (lv0_status_perf_stat, (cred, resolve_cred)) = th.report_status(&mut rng, &cred); let (lv0_resolve_perf_stat, cred) = th.report_resolve(&mut rng, &cred, &resolve_cred); let (_, migcred) = th.trust_promotion(&mut rng, &cred); let (_, cred) = th.migration(&mut rng, &cred, &migcred); let bucket = th.get_bucket(cred.clone()).0; let resolve_cred = th.ba.get_resolve_cred_for_new_session(&mut rng); let (lv1_submit_1_perf_stat, cred) = th.report_submit(&mut rng, &cred, &resolve_cred, [true, false, false]); let (lv1_status_1_perf_stat, (cred, resolve_cred)) = th.report_status(&mut rng, &cred); let (lv1_submit_2_perf_stat, cred) = th.report_submit(&mut rng, &cred, &resolve_cred, [false, true, true]); for i in 0..MAX_BRIDGES_PER_BUCKET { th.ba.report_table.process_scan_result( &bucket[i].get_hashed_fingerprint(), report_table::CountryCode::RU, report_table::ReportStatus::NotBlocked, ); } let (lv1_status_2_perf_stat, (cred, resolve_cred)) = th.report_status(&mut rng, &cred); let (lv1_resolve_perf_stat, _cred) = th.report_resolve(&mut rng, &cred, &resolve_cred); lv0_submit_req_size.push(lv0_submit_perf_stat.req_len as f64); lv0_submit_req_time.push(lv0_submit_perf_stat.req_t.as_secs_f64()); lv0_submit_resp_size.push(lv0_submit_perf_stat.resp_len as f64); lv0_submit_resp_time.push(lv0_submit_perf_stat.resp_t.as_secs_f64()); lv0_submit_resp_handle_time.push(lv0_submit_perf_stat.resp_handle_t.as_secs_f64()); lv0_status_req_size.push(lv0_status_perf_stat.req_len as f64); lv0_status_req_time.push(lv0_status_perf_stat.req_t.as_secs_f64()); lv0_status_resp_size.push(lv0_status_perf_stat.resp_len as f64); lv0_status_resp_time.push(lv0_status_perf_stat.resp_t.as_secs_f64()); lv0_status_resp_handle_time.push(lv0_status_perf_stat.resp_handle_t.as_secs_f64()); lv0_resolve_req_size.push(lv0_resolve_perf_stat.req_len as f64); lv0_resolve_req_time.push(lv0_resolve_perf_stat.req_t.as_secs_f64()); lv0_resolve_resp_size.push(lv0_resolve_perf_stat.resp_len as f64); lv0_resolve_resp_time.push(lv0_resolve_perf_stat.resp_t.as_secs_f64()); lv0_resolve_resp_handle_time.push(lv0_resolve_perf_stat.resp_handle_t.as_secs_f64()); lv1_submit_req_size.push(lv1_submit_1_perf_stat.req_len as f64); lv1_submit_req_time.push(lv1_submit_1_perf_stat.req_t.as_secs_f64()); lv1_submit_resp_size.push(lv1_submit_1_perf_stat.resp_len as f64); lv1_submit_resp_time.push(lv1_submit_1_perf_stat.resp_t.as_secs_f64()); lv1_submit_resp_handle_time.push(lv1_submit_1_perf_stat.resp_handle_t.as_secs_f64()); lv1_submit_req_size.push(lv1_submit_2_perf_stat.req_len as f64); lv1_submit_req_time.push(lv1_submit_2_perf_stat.req_t.as_secs_f64()); lv1_submit_resp_size.push(lv1_submit_2_perf_stat.resp_len as f64); lv1_submit_resp_time.push(lv1_submit_2_perf_stat.resp_t.as_secs_f64()); lv1_submit_resp_handle_time.push(lv1_submit_2_perf_stat.resp_handle_t.as_secs_f64()); lv1_status_req_size.push(lv1_status_1_perf_stat.req_len as f64); lv1_status_req_time.push(lv1_status_1_perf_stat.req_t.as_secs_f64()); lv1_status_resp_size.push(lv1_status_1_perf_stat.resp_len as f64); lv1_status_resp_time.push(lv1_status_1_perf_stat.resp_t.as_secs_f64()); lv1_status_resp_handle_time.push(lv1_status_1_perf_stat.resp_handle_t.as_secs_f64()); lv1_status_req_size.push(lv1_status_2_perf_stat.req_len as f64); lv1_status_req_time.push(lv1_status_2_perf_stat.req_t.as_secs_f64()); lv1_status_resp_size.push(lv1_status_2_perf_stat.resp_len as f64); lv1_status_resp_time.push(lv1_status_2_perf_stat.resp_t.as_secs_f64()); lv1_status_resp_handle_time.push(lv1_status_2_perf_stat.resp_handle_t.as_secs_f64()); lv1_resolve_req_size.push(lv1_resolve_perf_stat.req_len as f64); lv1_resolve_req_time.push(lv1_resolve_perf_stat.req_t.as_secs_f64()); lv1_resolve_resp_size.push(lv1_resolve_perf_stat.resp_len as f64); lv1_resolve_resp_time.push(lv1_resolve_perf_stat.resp_t.as_secs_f64()); lv1_resolve_resp_handle_time.push(lv1_resolve_perf_stat.resp_handle_t.as_secs_f64()); } println!("\n***START: {}*3*2 BUCKETS REPORTS***\n", x); println!("\n----REPORT-SUBMIT-0-{}---\n", x); print_stats_test_results( lv0_submit_req_size, lv0_submit_req_time, lv0_submit_resp_size, lv0_submit_resp_time, lv0_submit_resp_handle_time, ); println!("\n----REPORT-STATUS-0-{}---\n", x); print_stats_test_results( lv0_status_req_size, lv0_status_req_time, lv0_status_resp_size, lv0_status_resp_time, lv0_status_resp_handle_time, ); println!("\n----REPORT-RESOLVE-0-{}---\n", x); print_stats_test_results( lv0_resolve_req_size, lv0_resolve_req_time, lv0_resolve_resp_size, lv0_resolve_resp_time, lv0_resolve_resp_handle_time, ); println!("\n----REPORT-SUBMIT-1-{}---\n", x); print_stats_test_results( lv1_submit_req_size, lv1_submit_req_time, lv1_submit_resp_size, lv1_submit_resp_time, lv1_submit_resp_handle_time, ); println!("\n----REPORT-STATUS-1-{}---\n", x); print_stats_test_results( lv1_status_req_size, lv1_status_req_time, lv1_status_resp_size, lv1_status_resp_time, lv1_status_resp_handle_time, ); println!("\n----REPORT-RESOLVE-1-{}---\n", x); print_stats_test_results( lv1_resolve_req_size, lv1_resolve_req_time, lv1_resolve_resp_size, lv1_resolve_resp_time, lv1_resolve_resp_handle_time, ); } } /// Blocks a percentage of the bridges for the passed Test Harness /// excluding the hot spare buckets as they will not have been handed out. fn block_bridges(th: &mut TestHarness, percentage: usize, credentials: Vec) { let blockable_num = th.ba.bridge_table.buckets.len() - th.ba.bridge_table.spares.len() - th.bdb.openinv_buckets.len(); let to_block: usize = blockable_num * percentage / 100; let rng = &mut rand::thread_rng(); // Buckets that are not hot spares or openinv buckets let mut blockable_buckets: Vec = th .ba .bridge_table .buckets .keys() .map(|&v| v) .collect::>() .difference(&th.ba.bridge_table.spares) .map(|&v| v) .collect::>() .difference(&th.bdb.openinv_buckets) .map(|&v| v) .collect(); blockable_buckets.shuffle(rng); for i in 0..to_block { let index = blockable_buckets[i]; let b0 = th.ba.bridge_table.buckets.get(&index).unwrap()[0]; let b1 = th.ba.bridge_table.buckets.get(&index).unwrap()[1]; let b2 = th.ba.bridge_table.buckets.get(&index).unwrap()[2]; th.ba.bridge_blocked(&b0, &mut th.bdb); th.ba.bridge_blocked(&b1, &mut th.bdb); th.ba.bridge_blocked(&b2, &mut th.bdb); } let mut req_size: Vec = Vec::new(); let mut resp_size: Vec = Vec::new(); let mut req_time: Vec = Vec::new(); let mut resp_time: Vec = Vec::new(); let mut resp_handle_time: Vec = Vec::new(); let mut red_req_size: Vec = Vec::new(); let mut red_resp_size: Vec = Vec::new(); let mut red_req_time: Vec = Vec::new(); let mut red_resp_time: Vec = Vec::new(); let mut red_resp_handle_time: Vec = Vec::new(); for cred in credentials { let (bucket, _encbuckets_res) = th.get_bucket(cred.clone()); let mut count = 0; for bridge_line in &bucket { if th.ba.bridge_table.reachable.contains_key(bridge_line) { count += 1; } } if count < 2 { let (perf_stat, migration) = th.check_blockage(rng, &cred); let (block_perf_stat, _) = th.blockage_migration(rng, &cred, &migration); req_size.push(perf_stat.req_len as f64); req_time.push(perf_stat.req_t.as_secs_f64()); resp_size.push(perf_stat.resp_len as f64); resp_time.push(perf_stat.resp_t.as_secs_f64()); resp_handle_time.push(perf_stat.resp_handle_t.as_secs_f64()); red_req_size.push(block_perf_stat.req_len as f64); red_req_time.push(block_perf_stat.req_t.as_secs_f64()); red_resp_size.push(block_perf_stat.resp_len as f64); red_resp_time.push(block_perf_stat.resp_t.as_secs_f64()); red_resp_handle_time.push(block_perf_stat.resp_handle_t.as_secs_f64()); } } println!("\n----CHECK-BLOCKAGE-{}----\n", percentage); print_stats_test_results(req_size, req_time, resp_size, resp_time, resp_handle_time); println!("\n----BLOCKAGE-MIGRATION-{}----\n", percentage); print_stats_test_results( red_req_size, red_req_time, red_resp_size, red_resp_time, red_resp_handle_time, ); } fn print_stats_test_results( req_size: Vec, req_time: Vec, resp_size: Vec, resp_time: Vec, resp_handle_time: Vec, ) { let mean_req_size = if req_size.len() > 0 { mean(&req_size) } else { 0.0 }; let req_std_dev = if req_size.len() > 1 { standard_deviation(&req_size, Some(mean_req_size)) } else { 0.0 }; let mean_req_time = if req_time.len() > 0 { mean(&req_time) } else { 0.0 }; let req_time_std_dev = if req_time.len() > 1 { standard_deviation(&req_time, Some(mean_req_time)) } else { 0.0 }; let mean_resp_size = if resp_size.len() > 0 { mean(&resp_size) } else { 0.0 }; let resp_std_dev = if resp_size.len() > 1 { standard_deviation(&resp_size, Some(mean_resp_size)) } else { 0.0 }; let mean_resp_time = if resp_time.len() > 0 { mean(&resp_time) } else { 0.0 }; let resp_time_std_dev = if resp_time.len() > 1 { standard_deviation(&resp_time, Some(mean_resp_time)) } else { 0.0 }; let mean_resp_handle_time = if resp_handle_time.len() > 0 { mean(&resp_handle_time) } else { 0.0 }; let resp_handle_time_std_dev = if resp_handle_time.len() > 1 { standard_deviation(&resp_handle_time, Some(mean_resp_handle_time)) } else { 0.0 }; println!("Average request size = {} bytes", mean_req_size); println!("Request size standard deviation = {} bytes", req_std_dev); println!( "Average request time = {:?}", Duration::from_secs_f64(mean_req_time) ); println!( "Request time standard deviation = {:?}", Duration::from_secs_f64(req_time_std_dev) ); println!("Average response size = {} bytes", mean_resp_size); println!("Response standard deviation = {} bytes", resp_std_dev); println!( "Average response time = {:?}", Duration::from_secs_f64(mean_resp_time) ); println!( "Response time standard deviation = {:?}", Duration::from_secs_f64(resp_time_std_dev) ); println!( "Average response handling time = {:?}", Duration::from_secs_f64(mean_resp_handle_time) ); println!( "Response handling time standard deviation = {:?}", Duration::from_secs_f64(resp_handle_time_std_dev) ); }