diff --git a/crates/lox-distributor/src/troll_patrol_handler.rs b/crates/lox-distributor/src/troll_patrol_handler.rs index f86b8ec..85ae577 100644 --- a/crates/lox-distributor/src/troll_patrol_handler.rs +++ b/crates/lox-distributor/src/troll_patrol_handler.rs @@ -334,10 +334,9 @@ mod tests { ); // Invalid country code - let mut invalid_report_2 = - NegativeReport::from_bridgeline(bridges[1], "ru".to_string(), BridgeDistributor::Lox) + let invalid_report_2 = + NegativeReport::from_bridgeline(bridges[1], "xx".to_string(), BridgeDistributor::Lox) .to_serializable_report(); - invalid_report_2.country = "xx".to_string(); reports.insert( serde_json::to_string(&invalid_report_2).unwrap(), num_invalid_report_2, @@ -359,7 +358,7 @@ mod tests { reports.insert(invalid_report_3.to_json(), num_invalid_report_3); // Incorrect BridgeLine hash - let mut invalid_report_4 = NegativeReport::new( + let invalid_report_4 = NegativeReport::new( bridges[0].fingerprint, ProofOfBridgeKnowledge::HashOfBridgeLine(HashOfBridgeLine::new(&BridgeLine::default())), "ru".to_string(), @@ -387,4 +386,95 @@ mod tests { let count: u32 = body_to_string(response).await.parse().unwrap(); assert_eq!(num_report_1 + num_report_2 + num_report_3, count); } + + #[tokio::test] + async fn test_positive_reports() { + let mut th = TestHarness::new(); + th.generate_bridge_infos(); + let tpc = TpClientMock {}; + let mut Htables = HashMap::::new(); + + // Get new level 3 credential + let cred = get_new_credential(&mut th).await; + let cred = level_up(&mut th, &cred).await; + let cred = level_up(&mut th, &cred).await; + let cred = level_up(&mut th, &cred).await; + + th.generate_bridge_infos(); + + let mut ba = th.context.ba.lock().unwrap(); + + // Get bucket + let (id, key) = bridge_table::from_scalar(cred.bucket).unwrap(); + let encbuckets = ba.enc_bridge_table(); + let bucket = + bridge_table::BridgeTable::decrypt_bucket(id, &key, encbuckets.get(&id).unwrap()) + .unwrap(); + let bridges = bucket.0; + + // Create a positive report for each bridge in bucket + let mut reports = Vec::::new(); + for bridge in bridges { + let report = PositiveReport::from_lox_credential( + bridge.fingerprint, + None, + &cred, + &ba.lox_pub, + "ru".to_string(), + ); + reports.push(report.to_serializable_report()); + } + assert_eq!(reports.len(), 3); + + // Check that reports with invalid fields are not counted + + // Date in the future + let mut invalid_report_1 = PositiveReport::from_lox_credential( + bridges[0].fingerprint, + None, + &cred, + &ba.lox_pub, + "ru".to_string(), + ); + invalid_report_1.date = invalid_report_1.date + 2; + reports.push(invalid_report_1.to_serializable_report()); + + // Invalid country code + let invalid_report_2 = PositiveReport::from_lox_credential( + bridges[1].fingerprint, + None, + &cred, + &ba.lox_pub, + "xx".to_string(), + ); + reports.push(invalid_report_2.to_serializable_report()); + + // Check that well-formed reports with incorrect bridge data are not counted + + let mut hasher = Sha1::new(); + hasher.update([0; 20]); + let empty_bridgeline_fingerprint: [u8; 20] = hasher.finalize().into(); + + // Unknown bridge fingerprint + let mut invalid_report_3 = PositiveReport::from_lox_credential( + bridges[2].fingerprint, + None, + &cred, + &ba.lox_pub, + "ru".to_string(), + ); + invalid_report_3.fingerprint = empty_bridgeline_fingerprint; + reports.push(invalid_report_3.to_serializable_report()); + + // Release lock so BA can be used to verify reports below + drop(ba); + + let request = tpc.verifypositive(reports); + let response = handle(th.context.clone(), &mut Htables, request) + .await + .unwrap(); + assert_eq!(response.status(), StatusCode::OK); + let count: usize = body_to_string(response).await.parse().unwrap(); + assert_eq!(count, lox_library::bridge_table::MAX_BRIDGES_PER_BUCKET); + } }