Add basic tests for bridgetable sync with rdsys
This commit is contained in:
parent
5f34f49d17
commit
76bb8757f5
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"watched_blockages": [
|
||||||
|
"RU"
|
||||||
|
],
|
||||||
|
"percent_spares": 50
|
||||||
|
}
|
|
@ -67,7 +67,10 @@ impl LoxServerContext {
|
||||||
for bridge in blocked_bridgelines {
|
for bridge in blocked_bridgelines {
|
||||||
let res = self.mark_blocked(bridge);
|
let res = self.mark_blocked(bridge);
|
||||||
if res {
|
if res {
|
||||||
println!("BridgeLine {:?} successfully marked unreachable", bridge);
|
println!(
|
||||||
|
"BridgeLine {:?} successfully marked unreachable",
|
||||||
|
bridge.uid_fingerprint
|
||||||
|
);
|
||||||
self.metrics.blocked_bridges.inc();
|
self.metrics.blocked_bridges.inc();
|
||||||
} else {
|
} else {
|
||||||
println!(
|
println!(
|
||||||
|
@ -139,6 +142,7 @@ impl LoxServerContext {
|
||||||
// Next, handle the failing bridges. If resource last passed tests >= ACCEPTED_HOURS_OF_FAILURE ago,
|
// Next, handle the failing bridges. If resource last passed tests >= ACCEPTED_HOURS_OF_FAILURE ago,
|
||||||
// it should be replaced with a working resource and be removed from the bridgetable.
|
// it should be replaced with a working resource and be removed from the bridgetable.
|
||||||
for bridge in failing {
|
for bridge in failing {
|
||||||
|
println!("Got here with Resource {:?}", bridge.uid_fingerprint);
|
||||||
let res = self.replace_with_new(bridge);
|
let res = self.replace_with_new(bridge);
|
||||||
if res == lox_library::ReplaceSuccess::Replaced {
|
if res == lox_library::ReplaceSuccess::Replaced {
|
||||||
println!(
|
println!(
|
||||||
|
@ -702,3 +706,142 @@ fn prepare_header(response: String) -> Response<Body> {
|
||||||
.insert("Access-Control-Allow-Origin", HeaderValue::from_static("*"));
|
.insert("Access-Control-Allow-Origin", HeaderValue::from_static("*"));
|
||||||
resp
|
resp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::{fake_resource_state::TestResourceState, metrics::Metrics, BridgeConfig};
|
||||||
|
use lox_library::{bridge_table::MAX_BRIDGES_PER_BUCKET, BridgeAuth, BridgeDb};
|
||||||
|
use std::{
|
||||||
|
env, fs,
|
||||||
|
sync::{Arc, Mutex},
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::LoxServerContext;
|
||||||
|
|
||||||
|
struct TestHarness {
|
||||||
|
context: LoxServerContext,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestHarness {
|
||||||
|
fn new() -> Self {
|
||||||
|
let bridgedb = BridgeDb::new();
|
||||||
|
let mut lox_auth = BridgeAuth::new(bridgedb.pubkey);
|
||||||
|
lox_auth.enc_bridge_table();
|
||||||
|
let context = LoxServerContext {
|
||||||
|
db: Arc::new(Mutex::new(bridgedb)),
|
||||||
|
ba: Arc::new(Mutex::new(lox_auth)),
|
||||||
|
extra_bridges: Arc::new(Mutex::new(Vec::new())),
|
||||||
|
metrics: Metrics::default(),
|
||||||
|
};
|
||||||
|
Self { context }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_with_bridges() -> Self {
|
||||||
|
let mut bridgedb = BridgeDb::new();
|
||||||
|
let mut lox_auth = BridgeAuth::new(bridgedb.pubkey);
|
||||||
|
// Make 3 x num_buckets open invitation bridges, in sets of 3
|
||||||
|
for _ in 0..5 {
|
||||||
|
let bucket = [
|
||||||
|
lox_utils::random(),
|
||||||
|
lox_utils::random(),
|
||||||
|
lox_utils::random(),
|
||||||
|
];
|
||||||
|
let _ = lox_auth.add_openinv_bridges(bucket, &mut bridgedb);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add hot_spare more hot spare buckets
|
||||||
|
for _ in 0..5 {
|
||||||
|
let bucket = [
|
||||||
|
lox_utils::random(),
|
||||||
|
lox_utils::random(),
|
||||||
|
lox_utils::random(),
|
||||||
|
];
|
||||||
|
let _ = lox_auth.add_spare_bucket(bucket, &mut bridgedb);
|
||||||
|
}
|
||||||
|
// Create the encrypted bridge table
|
||||||
|
lox_auth.enc_bridge_table();
|
||||||
|
let context = LoxServerContext {
|
||||||
|
db: Arc::new(Mutex::new(bridgedb)),
|
||||||
|
ba: Arc::new(Mutex::new(lox_auth)),
|
||||||
|
extra_bridges: Arc::new(Mutex::new(Vec::new())),
|
||||||
|
metrics: Metrics::default(),
|
||||||
|
};
|
||||||
|
Self { context }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_config()-> BridgeConfig {
|
||||||
|
env::set_var("BRIDGE_CONFIG_PATH", "bridge_config.json");
|
||||||
|
let path = env::var("BRIDGE_CONFIG_PATH").unwrap();
|
||||||
|
let config_file = fs::File::open(&path).unwrap();
|
||||||
|
serde_json::from_reader(config_file).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_sync_with_bridgetable_only_working_resources() {
|
||||||
|
let bridge_config = get_config();
|
||||||
|
// Add bridges to empty bridge table and update with changed bridge state
|
||||||
|
let th = TestHarness::new();
|
||||||
|
let mut rs = TestResourceState::default();
|
||||||
|
for _ in 0..5 {
|
||||||
|
rs.add_working_resource();
|
||||||
|
}
|
||||||
|
assert_ne!(rs.rstate.working, None);
|
||||||
|
assert_eq!(rs.rstate.not_working, None);
|
||||||
|
|
||||||
|
th.context
|
||||||
|
.sync_with_bridgetable(bridge_config.watched_blockages.clone(), rs.rstate.clone());
|
||||||
|
let mut reachable_expected_length = rs.rstate.clone().working.unwrap().len();
|
||||||
|
let expected_extra_bridges = reachable_expected_length % MAX_BRIDGES_PER_BUCKET;
|
||||||
|
if expected_extra_bridges != 0 {
|
||||||
|
reachable_expected_length = reachable_expected_length - expected_extra_bridges;
|
||||||
|
}
|
||||||
|
assert_eq!(
|
||||||
|
th.context.ba.lock().unwrap().bridge_table.reachable.len(),
|
||||||
|
reachable_expected_length,
|
||||||
|
"Unexpected number of reachable bridges"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
th.context.extra_bridges.lock().unwrap().len(),
|
||||||
|
expected_extra_bridges,
|
||||||
|
"Unexpected number of extra bridges"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_sync_with_bridgetable_working_and_not_working_resources() {
|
||||||
|
let bridge_config = get_config();
|
||||||
|
// Add bridges to empty bridge table and update with changed bridge state
|
||||||
|
let th = TestHarness::new();
|
||||||
|
let mut rs = TestResourceState::default();
|
||||||
|
for _ in 0..5 {
|
||||||
|
rs.add_working_resource();
|
||||||
|
}
|
||||||
|
|
||||||
|
for _ in 0..5 {
|
||||||
|
rs.add_not_working_resource()
|
||||||
|
}
|
||||||
|
assert_ne!(rs.rstate.working, None);
|
||||||
|
assert_ne!(rs.rstate.not_working, None);
|
||||||
|
|
||||||
|
th.context
|
||||||
|
.sync_with_bridgetable(bridge_config.watched_blockages.clone(), rs.rstate.clone());
|
||||||
|
let mut reachable_expected_length = rs.rstate.clone().working.unwrap().len();
|
||||||
|
let expected_extra_bridges = reachable_expected_length % MAX_BRIDGES_PER_BUCKET;
|
||||||
|
if expected_extra_bridges != 0 {
|
||||||
|
reachable_expected_length = reachable_expected_length - expected_extra_bridges;
|
||||||
|
}
|
||||||
|
assert_eq!(
|
||||||
|
th.context.ba.lock().unwrap().bridge_table.reachable.len(),
|
||||||
|
reachable_expected_length,
|
||||||
|
"Unexpected number of reachable bridges"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
th.context.extra_bridges.lock().unwrap().len(),
|
||||||
|
expected_extra_bridges,
|
||||||
|
"Unexpected number of extra bridges"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -10,13 +10,13 @@ pub struct ResourceRequest {
|
||||||
pub resource_types: Vec<String>,
|
pub resource_types: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
|
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct TestResults {
|
pub struct TestResults {
|
||||||
pub last_passed: DateTime<Utc>,
|
pub last_passed: DateTime<Utc>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Representation of a bridge resource
|
/// Representation of a bridge resource
|
||||||
#[derive(Deserialize, PartialEq, Eq, Debug)]
|
#[derive(Clone, Deserialize, PartialEq, Eq, Debug)]
|
||||||
pub struct Resource {
|
pub struct Resource {
|
||||||
pub r#type: String,
|
pub r#type: String,
|
||||||
pub blocked_in: HashMap<String, bool>,
|
pub blocked_in: HashMap<String, bool>,
|
||||||
|
@ -57,7 +57,7 @@ impl Resource {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A ResourceState holds information about new, changed, or pruned resources
|
/// A ResourceState holds information about new, changed, or pruned resources
|
||||||
#[derive(Deserialize, Default, PartialEq, Eq, Debug)]
|
#[derive(Clone, Deserialize, Default, PartialEq, Eq, Debug)]
|
||||||
pub struct ResourceState {
|
pub struct ResourceState {
|
||||||
pub working: Option<Vec<Resource>>,
|
pub working: Option<Vec<Resource>>,
|
||||||
pub not_working: Option<Vec<Resource>>,
|
pub not_working: Option<Vec<Resource>>,
|
||||||
|
|
Loading…
Reference in New Issue