ソースを参照

Start testing simulated extra-infos

Vecna 3 週間 前
コミット
45a6339c4c
2 ファイル変更113 行追加4 行削除
  1. 38 2
      src/extra_info.rs
  2. 75 2
      src/tests.rs

+ 38 - 2
src/extra_info.rs

@@ -5,10 +5,13 @@ Note, this is NOT a complete implementation of the document format.
 use chrono::DateTime;
 use julianday::JulianDay;
 use serde::{Deserialize, Serialize};
-use std::collections::{BTreeMap, HashMap, HashSet};
+use std::{
+    collections::{BTreeMap, HashMap, HashSet},
+    fmt,
+};
 
 /// Fields we need from extra-info document
-#[derive(Eq, PartialEq, Hash, Serialize, Deserialize)]
+#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
 pub struct ExtraInfo {
     /// Bridge nickname, probably unused
     pub nickname: String,
@@ -137,3 +140,36 @@ impl ExtraInfo {
         set
     }
 }
+
+/// Convert the ExtraInfo object to a string record, as in a downloaded file
+impl fmt::Display for ExtraInfo {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let mut str = String::from("@type bridge-extra-info 1.3");
+        str.push_str(
+            format!(
+                "\nextra-info {} {}",
+                self.nickname,
+                array_bytes::bytes2hex("", self.fingerprint).to_uppercase()
+            )
+            .as_str(),
+        );
+        let date = JulianDay::new(self.date.try_into().unwrap()).to_date();
+        str.push_str(format!("\nbridge-stats-end {} 23:59:59 (86400 s)", date).as_str());
+        str.push_str(format!("\npublished {} 23:59:59", date).as_str());
+
+        // These should be sorted in descending order by count, but that's not
+        // necessary for our purposes.
+        str.push_str("\nbridge-ips ");
+        let mut first_cc = true;
+        for (cc, count) in &self.bridge_ips {
+            if !first_cc {
+                str.push(',');
+            }
+            str.push_str(format!("{}={}", cc, count,).as_str());
+            first_cc = false;
+        }
+        str.push_str("\n");
+
+        write!(f, "{}", str)
+    }
+}

+ 75 - 2
src/tests.rs

@@ -150,12 +150,12 @@ pub fn random() -> BridgeLine {
 }
 
 #[tokio::test]
-async fn test_extra_infos() {
+async fn test_download_extra_infos() {
     let bridge_to_test =
         array_bytes::hex2array("72E12B89136B45BBC81D1EF0AC7DDDBB91B148DB").unwrap();
 
     // Open test database
-    let db: Db = sled::open("test_db_ei").unwrap();
+    let db: Db = sled::open("test_db_dei").unwrap();
 
     // Delete all data in test DB
     db.clear().unwrap();
@@ -180,6 +180,79 @@ async fn test_extra_infos() {
         bincode::deserialize(&db.get(bridge_to_test).unwrap().unwrap()).unwrap();
 }
 
+#[test]
+fn test_simulate_extra_infos() {
+    let extra_info_str = r#"@type bridge-extra-info 1.3
+extra-info ElephantBridgeDE2 72E12B89136B45BBC81D1EF0AC7DDDBB91B148DB
+master-key-ed25519 eWxjRwAWW7n8BGG9fNa6rApmBFbe3f0xcD7dqwOICW8
+published 2024-04-06 03:51:04
+transport obfs4
+write-history 2024-04-05 04:55:22 (86400 s) 31665735680,14918491136,15423603712,36168353792,40396827648
+read-history 2024-04-05 04:55:22 (86400 s) 31799622656,15229917184,15479115776,36317251584,40444155904
+ipv6-write-history 2024-04-05 04:55:22 (86400 s) 5972127744,610078720,516897792,327949312,640708608
+ipv6-read-history 2024-04-05 04:55:22 (86400 s) 4156158976,4040448000,2935756800,4263080960,6513532928
+dirreq-write-history 2024-04-05 04:55:22 (86400 s) 625217536,646188032,618014720,584386560,600778752
+dirreq-read-history 2024-04-05 04:55:22 (86400 s) 18816000,19000320,18484224,17364992,18443264
+geoip-db-digest 44073997E1ED63E183B79DE2A1757E9997A834E3
+geoip6-db-digest C0BF46880C6C132D746683279CC90DD4B2D31786
+dirreq-stats-end 2024-04-05 06:51:23 (86400 s)
+dirreq-v3-ips ru=16,au=8,by=8,cn=8,gb=8,ir=8,mt=8,nl=8,pl=8,tn=8,tr=8,us=8
+dirreq-v3-reqs ru=72,gb=64,pl=32,cn=16,ir=16,us=16,au=8,by=8,mt=8,nl=8,tn=8,tr=8
+dirreq-v3-resp ok=216,not-enough-sigs=0,unavailable=0,not-found=0,not-modified=328,busy=0
+dirreq-v3-direct-dl complete=0,timeout=0,running=0
+dirreq-v3-tunneled-dl complete=212,timeout=4,running=0,min=21595,d1=293347,d2=1624137,q1=1911800,d3=2066929,d4=2415000,md=2888500,d6=3264000,d7=3851333,q3=41>
+hidserv-stats-end 2024-04-05 06:51:23 (86400 s)
+hidserv-rend-relayed-cells 7924 delta_f=2048 epsilon=0.30 bin_size=1024
+hidserv-dir-onions-seen -12 delta_f=8 epsilon=0.30 bin_size=8
+hidserv-v3-stats-end 2024-04-05 12:00:00 (86400 s)
+hidserv-rend-v3-relayed-cells -4785 delta_f=2048 epsilon=0.30 bin_size=1024
+hidserv-dir-v3-onions-seen 5 delta_f=8 epsilon=0.30 bin_size=8
+padding-counts 2024-04-05 06:51:42 (86400 s) bin-size=10000 write-drop=0 write-pad=80000 write-total=79980000 read-drop=0 read-pad=1110000 read-total=7989000>
+bridge-stats-end 2024-04-05 06:51:44 (86400 s)
+bridge-ips ru=40,us=32,??=8,au=8,br=8,by=8,cn=8,de=8,eg=8,eu=8,gb=8,ge=8,hr=8,ie=8,ir=8,kp=8,lt=8,mt=8,nl=8,pl=8,ro=8,sg=8,tn=8,tr=8,vn=8
+bridge-ip-versions v4=104,v6=8
+bridge-ip-transports <OR>=56,obfs4=56
+router-digest-sha256 zK0VMl3i0B2eaeQTR03e2hZ0i8ytkuhK/psgD2J1/lQ
+router-digest F30B38390C375E1EE74BFED844177804442569E0"#;
+
+    let extra_info_set = ExtraInfo::parse_file(&extra_info_str);
+    assert_eq!(extra_info_set.len(), 1);
+
+    let extra_info = extra_info_set.iter().next().unwrap().clone();
+
+    let extra_info_str = extra_info.to_string();
+
+    let extra_info_2 = ExtraInfo::parse_file(&extra_info_str)
+        .into_iter()
+        .next()
+        .unwrap()
+        .clone();
+    assert_eq!(extra_info, extra_info_2);
+
+    let bridge_to_test: [u8; 20] =
+        array_bytes::hex2array("72E12B89136B45BBC81D1EF0AC7DDDBB91B148DB").unwrap();
+
+    // Open test database
+    let db: Db = sled::open("test_db_sei").unwrap();
+
+    // Delete all data in test DB
+    db.clear().unwrap();
+    assert!(!db.contains_key("bridges").unwrap());
+    assert!(!db.contains_key(bridge_to_test).unwrap());
+
+    // TODO: Run local web server and change this to update_extra_infos
+    add_extra_info_to_db(&db, extra_info_2);
+
+    // Check that DB contains information on a bridge with high uptime
+    assert!(db.contains_key("bridges").unwrap());
+    let bridges: HashSet<[u8; 20]> =
+        bincode::deserialize(&db.get("bridges").unwrap().unwrap()).unwrap();
+    assert!(bridges.contains(&bridge_to_test));
+    assert!(db.contains_key(bridge_to_test).unwrap());
+    let _bridge_info: BridgeInfo =
+        bincode::deserialize(&db.get(bridge_to_test).unwrap().unwrap()).unwrap();
+}
+
 #[test]
 fn test_negative_reports() {
     let mut th = TestHarness::new();