Browse Source

Add unit tests for Lox operations that work so far

Vecna 1 year ago
parent
commit
3bc6f3a63f
2 changed files with 123 additions and 8 deletions
  1. 4 8
      src/main.rs
  2. 119 0
      src/tests.rs

+ 4 - 8
src/main.rs

@@ -82,14 +82,6 @@ async fn main() {
         }
     };
 
-    // Advance days on server (TESTING ONLY)
-    //#[cfg(test)]
-    if matches.opt_present("A") {
-        let days: u16 = u16::from_str(matches.opt_str("A").unwrap().as_str()).unwrap();
-        let today: u32 = advance_days(&net, days).await;
-        println!("Today's date according to the server: {}", today);
-    }
-
     // Get Lox Authority public keys
     let lox_auth_pubkeys: Vec<IssuerPubKey> = if Path::new(lox_auth_pubkeys_filename).exists() {
         // read in file
@@ -223,3 +215,7 @@ async fn main() {
         lox_cred
     };
 }
+
+// Unit tests
+#[cfg(test)]
+mod tests;

+ 119 - 0
src/tests.rs

@@ -0,0 +1,119 @@
+/*! Unit tests. Note that these require
+https://gitlab.torproject.org/vecna/lox-rs/-/tree/main/crates/lox-distributor
+to be running. That fork adds an endpoint which allows for artificially
+increasing the number of days that have passed, which allows us to test
+trust migration and level up functions. */
+
+// TODO:
+// - compare buckets to ensure they're the same
+// - unit test file save/read functions
+// - unit test migration when possible
+
+// Note: We can't run multiple time-changing tests simultaneously because
+// they will invalidate invites that haven't been redeemed yet.
+
+use super::client_lib::*;
+use super::client_net::HyperNet;
+use lox_library::bridge_table::BridgeLine;
+use lox_library::proto::level_up::{LEVEL_INTERVAL, LEVEL_INVITATIONS};
+use lox_library::proto::trust_promotion::UNTRUSTED_INTERVAL;
+use lox_library::scalar_u32;
+
+use std::cmp::min;
+
+// These are all combined into the same test because otherwise we run into
+// issues with server state due to asynchronicity.
+#[tokio::test]
+async fn test_credential_operations() {
+    let net = HyperNet {
+        hostname: "http://localhost:8001".to_string(),
+    };
+    let la_pubkeys = get_lox_auth_keys(&net).await;
+
+    // Get new Lox credential
+    let open_inv = get_open_invitation(&net).await;
+    let (mut cred, bridgeline) =
+        get_lox_credential(&net, &open_inv, get_lox_pub(&la_pubkeys)).await;
+    let bucket = get_bucket(&net, &cred).await;
+
+    // Note: This is unreliable for some reason...
+    //	assert_eq!(bucket[0], bridgeline);
+    assert_eq!(bucket[1], BridgeLine::default());
+
+    // Level up Lox Credential
+    assert_eq!(scalar_u32(&cred.trust_level).unwrap(), 0);
+
+    // Advance server time and trust migrate
+    advance_days(&net, u16::try_from(UNTRUSTED_INTERVAL).unwrap()).await;
+    assert!(eligible_for_trust_promotion(&net, &cred).await);
+    let migration_cred = trust_promotion(&net, &cred, get_lox_pub(&la_pubkeys)).await;
+    cred = trust_migration(
+        &net,
+        &cred,
+        &migration_cred,
+        get_lox_pub(&la_pubkeys),
+        get_migration_pub(&la_pubkeys),
+    )
+    .await;
+    assert_eq!(scalar_u32(&cred.trust_level).unwrap(), 1);
+
+    // Advance server time and level up
+    for i in 1..LEVEL_INTERVAL.len() {
+        assert_eq!(
+            scalar_u32(&cred.trust_level).unwrap(),
+            u32::try_from(i).unwrap()
+        );
+        advance_days(&net, u16::try_from(LEVEL_INTERVAL[i]).unwrap()).await;
+        assert!(eligible_for_level_up(&net, &cred).await);
+        let encbuckets = get_reachability_credential(&net).await;
+        cred = level_up(
+            &net,
+            &cred,
+            &encbuckets,
+            get_lox_pub(&la_pubkeys),
+            get_reachability_pub(&la_pubkeys),
+        )
+        .await
+        .0;
+
+        // Assert that we increased level by 1 or stayed at 4
+        assert_eq!(
+            scalar_u32(&cred.trust_level).unwrap(),
+            u32::try_from(min(i + 1, LEVEL_INTERVAL.len() - 1)).unwrap()
+        );
+        assert_eq!(
+            scalar_u32(&cred.invites_remaining).unwrap(),
+            LEVEL_INVITATIONS[i]
+        );
+
+        // Invite as many friends as possible
+        for j in 0..LEVEL_INVITATIONS[i] {
+            let encbuckets = get_reachability_credential(&net).await;
+            let (new_cred, invite) = issue_invite(
+                &net,
+                &cred,
+                &encbuckets,
+                get_lox_pub(&la_pubkeys),
+                get_reachability_pub(&la_pubkeys),
+                get_invitation_pub(&la_pubkeys),
+            )
+            .await;
+            let (friend_cred, friend_bucket) = redeem_invite(
+                &net,
+                &invite,
+                get_lox_pub(&la_pubkeys),
+                get_invitation_pub(&la_pubkeys),
+            )
+            .await;
+            cred = new_cred;
+
+            assert_eq!(
+                scalar_u32(&cred.invites_remaining).unwrap(),
+                LEVEL_INVITATIONS[i] - j - 1
+            );
+            // TODO: Where is this defined? Should I use the library constant?
+            assert_eq!(scalar_u32(&friend_cred.trust_level).unwrap(), 1);
+            assert_eq!(&cred.bucket, &friend_cred.bucket);
+        }
+    }
+}