use tcn::*;
#[test]
fn generate_temporary_contact_numbers_and_report_them() {
let rak = ReportAuthorizationKey::new(rand::thread_rng());
let mut tck = rak.initial_temporary_contact_key(); let mut tcns = Vec::new();
for _ in 0..100 {
tcns.push(tck.temporary_contact_number());
tck = tck.ratchet().unwrap();
}
let signed_report = rak
.create_report(
MemoType::CoEpiV1, b"symptom data".to_vec(), 20, 90, )
.expect("Report creation can only fail if the memo data is too long");
let report = signed_report
.verify()
.expect("Valid reports should verify correctly");
let recomputed_tcns = report.temporary_contact_numbers().collect::<Vec<_>>();
assert_eq!(&recomputed_tcns[..], &tcns[20 - 1..90 - 1]);
}
#[test]
fn match_btreeset() {
use rand::{
distributions::{Bernoulli, Distribution},
thread_rng,
};
use std::collections::BTreeSet;
let num_reports = 10_000;
let tcns_per_report: u16 = 24 * 60 / 15;
let tcn_observation = Bernoulli::new(0.001).unwrap();
let mut observed_tcns = BTreeSet::new();
let reports = (0..num_reports)
.map(|_| {
let rak = ReportAuthorizationKey::new(thread_rng());
let mut tck = rak.initial_temporary_contact_key();
for _ in 1..tcns_per_report {
if tcn_observation.sample(&mut thread_rng()) {
observed_tcns.insert(tck.temporary_contact_number());
}
tck = tck.ratchet().expect("tcns_per_report < u16::MAX");
}
rak.create_report(MemoType::CoEpiV1, Vec::new(), 1, tcns_per_report)
.expect("empty memo is not too long, so report creation cannot fail")
})
.collect::<Vec<_>>();
let expected_reported_tcns = observed_tcns.clone();
{
let rak = ReportAuthorizationKey::new(thread_rng());
let mut tck = rak.initial_temporary_contact_key();
for _ in 1..60_000 {
observed_tcns.insert(tck.temporary_contact_number());
tck = tck.ratchet().expect("60_000 < u16::MAX");
}
}
use std::time::Instant;
println!("Expanding candidates");
let expansion_start = Instant::now();
let mut candidate_tcns = BTreeSet::new();
for report in reports.into_iter() {
let report = report.verify().expect("test reports should be valid");
candidate_tcns.extend(report.temporary_contact_numbers());
}
let expansion_time = expansion_start.elapsed();
println!(
"Comparing {} candidates against {} observations",
candidate_tcns.len(),
observed_tcns.len()
);
let comparison_start = Instant::now();
let reported_tcns = candidate_tcns
.intersection(&observed_tcns)
.cloned()
.collect::<BTreeSet<_>>();
let comparison_time = comparison_start.elapsed();
assert_eq!(reported_tcns, expected_reported_tcns);
println!(
"Took {:?} (expansion) + {:?} (comparison) = {:?} (total)",
expansion_time,
comparison_time,
(expansion_time + comparison_time),
);
}
#[test]
fn basic_read_write_round_trip() {
use std::io::Cursor;
let rak = ReportAuthorizationKey::new(rand::thread_rng());
let mut buf1 = Vec::new();
let mut buf2 = Vec::new();
rak.write(Cursor::new(&mut buf1))
.expect("writing should succeed");
ReportAuthorizationKey::read(Cursor::new(&buf1))
.expect("reading should succeed")
.write(Cursor::new(&mut buf2))
.expect("writing should succeed");
assert_eq!(buf1, buf2);
let tck = rak.initial_temporary_contact_key();
let mut buf1 = Vec::new();
let mut buf2 = Vec::new();
tck.write(Cursor::new(&mut buf1))
.expect("writing should succeed");
TemporaryContactKey::read(Cursor::new(&buf1))
.expect("reading should succeed")
.write(Cursor::new(&mut buf2))
.expect("writing should succeed");
assert_eq!(buf1, buf2);
let signed_report = rak
.create_report(
MemoType::CoEpiV1, b"symptom data".to_vec(), 20, 100, )
.expect("Report creation can only fail if the memo data is too long");
let mut buf1 = Vec::new();
let mut buf2 = Vec::new();
signed_report
.write(Cursor::new(&mut buf1))
.expect("writing should succeed");
SignedReport::read(Cursor::new(&buf1))
.expect("reading should succeed")
.write(Cursor::new(&mut buf2))
.expect("writing should succeed");
assert_eq!(buf1, buf2);
let report = signed_report
.verify()
.expect("Valid reports should verify correctly");
let mut buf1 = Vec::new();
let mut buf2 = Vec::new();
report
.write(Cursor::new(&mut buf1))
.expect("writing should succeed");
Report::read(Cursor::new(&buf1))
.expect("reading should succeed")
.write(Cursor::new(&mut buf2))
.expect("writing should succeed");
assert_eq!(buf1, buf2);
}