rpki/tests/test_store_db.rs

352 lines
10 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

mod common;
use std::net::Ipv6Addr;
use common::test_helper::{
indent_block, payloads_to_string, test_report, v4_origin, v6_origin,
};
use rpki::rtr::cache::{Delta, Snapshot};
use rpki::rtr::payload::Payload;
use rpki::rtr::store_db::RtrStore;
fn snapshot_to_string(snapshot: &Snapshot) -> String {
let payloads = snapshot.payloads_for_rtr();
payloads_to_string(&payloads)
}
fn delta_to_string(delta: &Delta) -> String {
format!(
"serial: {}\nannounced:\n{}withdrawn:\n{}",
delta.serial(),
indent_block(&payloads_to_string(delta.announced()), 2),
indent_block(&payloads_to_string(delta.withdrawn()), 2),
)
}
#[test]
fn store_db_save_and_get_snapshot() {
let dir = tempfile::tempdir().unwrap();
let store = RtrStore::open(dir.path()).unwrap();
let input_payloads = vec![
Payload::RouteOrigin(v4_origin(192, 0, 2, 0, 24, 24, 64496)),
Payload::RouteOrigin(v6_origin(
Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0),
32,
48,
64497,
)),
];
let snapshot = Snapshot::from_payloads(input_payloads.clone());
store.save_snapshot(&snapshot).unwrap();
let loaded = store.get_snapshot().unwrap().expect("snapshot should exist");
let input = format!(
"db_path: {}\nsnapshot:\n{}",
dir.path().display(),
indent_block(&payloads_to_string(&input_payloads), 2),
);
let output = format!(
"loaded snapshot:\n{}same_content: {}\n",
indent_block(&snapshot_to_string(&loaded), 2),
snapshot.same_content(&loaded),
);
test_report(
"store_db_save_and_get_snapshot",
"验证 save_snapshot() 后可以通过 get_snapshot() 正确读回 Snapshot。",
&input,
&output,
);
assert!(snapshot.same_content(&loaded));
}
#[test]
fn store_db_set_and_get_meta_fields() {
let dir = tempfile::tempdir().unwrap();
let store = RtrStore::open(dir.path()).unwrap();
store.set_session_id(42).unwrap();
store.set_serial(100).unwrap();
store.set_delta_window(101, 110).unwrap();
let session_id = store.get_session_id().unwrap();
let serial = store.get_serial().unwrap();
let window = store.get_delta_window().unwrap();
let input = format!(
"db_path: {}\nset_session_id=42\nset_serial=100\nset_delta_window=(101, 110)\n",
dir.path().display(),
);
let output = format!(
"get_session_id: {:?}\nget_serial: {:?}\nget_delta_window: {:?}\n",
session_id, serial, window,
);
test_report(
"store_db_set_and_get_meta_fields",
"验证 session_id / serial / delta_window 能正确写入并读回。",
&input,
&output,
);
assert_eq!(session_id, Some(42));
assert_eq!(serial, Some(100));
assert_eq!(window, Some((101, 110)));
}
#[test]
fn store_db_save_and_get_delta() {
let dir = tempfile::tempdir().unwrap();
let store = RtrStore::open(dir.path()).unwrap();
let delta = Delta::new(
101,
vec![Payload::RouteOrigin(v4_origin(198, 51, 100, 0, 24, 24, 64497))],
vec![Payload::RouteOrigin(v4_origin(192, 0, 2, 0, 24, 24, 64496))],
);
store.save_delta(&delta).unwrap();
let loaded = store.get_delta(101).unwrap().expect("delta should exist");
let input = format!(
"db_path: {}\ndelta:\n{}",
dir.path().display(),
indent_block(&delta_to_string(&delta), 2),
);
let output = format!(
"loaded delta:\n{}",
indent_block(&delta_to_string(&loaded), 2),
);
test_report(
"store_db_save_and_get_delta",
"验证 save_delta() 后可以通过 get_delta(serial) 正确读回 Delta。",
&input,
&output,
);
assert_eq!(loaded.serial(), 101);
assert_eq!(loaded.announced().len(), 1);
assert_eq!(loaded.withdrawn().len(), 1);
}
#[test]
fn store_db_load_deltas_since_returns_only_newer_deltas_in_order() {
let dir = tempfile::tempdir().unwrap();
let store = RtrStore::open(dir.path()).unwrap();
let d101 = Delta::new(
101,
vec![Payload::RouteOrigin(v4_origin(192, 0, 2, 0, 24, 24, 64496))],
vec![],
);
let d102 = Delta::new(
102,
vec![Payload::RouteOrigin(v4_origin(198, 51, 100, 0, 24, 24, 64497))],
vec![],
);
let d103 = Delta::new(
103,
vec![Payload::RouteOrigin(v4_origin(203, 0, 113, 0, 24, 24, 64498))],
vec![],
);
store.save_delta(&d101).unwrap();
store.save_delta(&d102).unwrap();
store.save_delta(&d103).unwrap();
let loaded = store.load_deltas_since(101).unwrap();
let input = format!(
"db_path: {}\nsaved delta serials: [101, 102, 103]\nload_deltas_since(101)\n",
dir.path().display(),
);
let output = {
let mut s = String::new();
for (idx, d) in loaded.iter().enumerate() {
s.push_str(&format!("loaded[{}]:\n", idx));
s.push_str(&indent_block(&delta_to_string(d), 2));
}
s
};
test_report(
"store_db_load_deltas_since_returns_only_newer_deltas_in_order",
"验证 load_deltas_since(x) 只返回 serial > x 的 Delta且顺序正确。",
&input,
&output,
);
assert_eq!(loaded.len(), 2);
assert_eq!(loaded[0].serial(), 102);
assert_eq!(loaded[1].serial(), 103);
}
#[test]
fn store_db_save_snapshot_and_meta_writes_all_fields() {
let dir = tempfile::tempdir().unwrap();
let store = RtrStore::open(dir.path()).unwrap();
let snapshot = Snapshot::from_payloads(vec![
Payload::RouteOrigin(v4_origin(192, 0, 2, 0, 24, 24, 64496)),
Payload::RouteOrigin(v4_origin(198, 51, 100, 0, 24, 24, 64497)),
]);
store.save_snapshot_and_meta(&snapshot, 42, 100).unwrap();
let loaded_snapshot = store.get_snapshot().unwrap().expect("snapshot should exist");
let loaded_session = store.get_session_id().unwrap();
let loaded_serial = store.get_serial().unwrap();
let input = format!(
"db_path: {}\nsnapshot:\n{}session_id=42\nserial=100\n",
dir.path().display(),
indent_block(&snapshot_to_string(&snapshot), 2),
);
let output = format!(
"loaded_snapshot:\n{}loaded_session_id: {:?}\nloaded_serial: {:?}\n",
indent_block(&snapshot_to_string(&loaded_snapshot), 2),
loaded_session,
loaded_serial,
);
test_report(
"store_db_save_snapshot_and_meta_writes_all_fields",
"验证 save_snapshot_and_meta() 会同时写入 snapshot、session_id 和 serial。",
&input,
&output,
);
assert!(snapshot.same_content(&loaded_snapshot));
assert_eq!(loaded_session, Some(42));
assert_eq!(loaded_serial, Some(100));
}
#[test]
fn store_db_load_snapshot_and_serial_returns_consistent_pair() {
let dir = tempfile::tempdir().unwrap();
let store = RtrStore::open(dir.path()).unwrap();
let snapshot = Snapshot::from_payloads(vec![
Payload::RouteOrigin(v4_origin(203, 0, 113, 0, 24, 24, 64498)),
]);
store.save_snapshot_and_serial(&snapshot, 200).unwrap();
let loaded = store
.load_snapshot_and_serial()
.unwrap()
.expect("snapshot+serial should exist");
let input = format!(
"db_path: {}\nsnapshot:\n{}serial=200\n",
dir.path().display(),
indent_block(&snapshot_to_string(&snapshot), 2),
);
let output = format!(
"loaded_snapshot:\n{}loaded_serial: {}\n",
indent_block(&snapshot_to_string(&loaded.0), 2),
loaded.1,
);
test_report(
"store_db_load_snapshot_and_serial_returns_consistent_pair",
"验证 load_snapshot_and_serial() 能正确返回一致的 snapshot 与 serial。",
&input,
&output,
);
assert!(snapshot.same_content(&loaded.0));
assert_eq!(loaded.1, 200);
}
#[test]
fn store_db_delete_snapshot_delta_and_serial_removes_data() {
let dir = tempfile::tempdir().unwrap();
let store = RtrStore::open(dir.path()).unwrap();
let snapshot = Snapshot::from_payloads(vec![
Payload::RouteOrigin(v4_origin(192, 0, 2, 0, 24, 24, 64496)),
]);
let delta = Delta::new(
101,
vec![Payload::RouteOrigin(v4_origin(198, 51, 100, 0, 24, 24, 64497))],
vec![],
);
store.save_snapshot(&snapshot).unwrap();
store.save_delta(&delta).unwrap();
store.set_serial(100).unwrap();
store.delete_snapshot().unwrap();
store.delete_delta(101).unwrap();
store.delete_serial().unwrap();
let loaded_snapshot = store.get_snapshot().unwrap();
let loaded_delta = store.get_delta(101).unwrap();
let loaded_serial = store.get_serial().unwrap();
let input = format!(
"db_path: {}\nsave snapshot + delta(101) + serial(100), then delete all three.\n",
dir.path().display(),
);
let output = format!(
"get_snapshot: {:?}\nget_delta(101): {:?}\nget_serial: {:?}\n",
loaded_snapshot.as_ref().map(|_| "Some(snapshot)"),
loaded_delta.as_ref().map(|_| "Some(delta)"),
loaded_serial,
);
test_report(
"store_db_delete_snapshot_delta_and_serial_removes_data",
"验证 delete_snapshot()/delete_delta()/delete_serial() 后,对应数据不再可读。",
&input,
&output,
);
assert!(loaded_snapshot.is_none());
assert!(loaded_delta.is_none());
assert!(loaded_serial.is_none());
}
#[test]
fn store_db_load_snapshot_and_serial_errors_on_inconsistent_state() {
let dir = tempfile::tempdir().unwrap();
let store = RtrStore::open(dir.path()).unwrap();
let snapshot = Snapshot::from_payloads(vec![
Payload::RouteOrigin(v4_origin(192, 0, 2, 0, 24, 24, 64496)),
]);
store.save_snapshot(&snapshot).unwrap();
// 故意不写 serial制造不一致状态
let result = store.load_snapshot_and_serial();
let input = format!(
"db_path: {}\n仅保存 snapshot不保存 serial。\n",
dir.path().display(),
);
let output = format!("load_snapshot_and_serial result: {:?}\n", result);
test_report(
"store_db_load_snapshot_and_serial_errors_on_inconsistent_state",
"验证当 snapshot 和 serial 状态不一致时load_snapshot_and_serial() 返回错误。",
&input,
&output,
);
assert!(result.is_err());
}