diff --git a/src/main.rs b/src/main.rs index 3d0fa4d..8d4de9c 100644 --- a/src/main.rs +++ b/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 = 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; diff --git a/src/tests.rs b/src/tests.rs new file mode 100644 index 0000000..4f1dc6a --- /dev/null +++ b/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); + } + } +}