350 lines
10 KiB
Rust
350 lines
10 KiB
Rust
mod common;
|
|
|
|
use std::net::Ipv6Addr;
|
|
|
|
use common::test_helper::{v4_origin, v6_origin};
|
|
|
|
use rpki::rtr::cache::{CacheAvailability, Delta, Snapshot};
|
|
use rpki::rtr::payload::Payload;
|
|
use rpki::rtr::store::RtrStore;
|
|
|
|
#[test]
|
|
fn store_db_versioned_state_persists_and_restores_all_versions() {
|
|
let dir = tempfile::tempdir().unwrap();
|
|
let store = RtrStore::open(dir.path()).unwrap();
|
|
|
|
let snapshots = [
|
|
Snapshot::from_payloads(vec![Payload::RouteOrigin(v4_origin(
|
|
192, 0, 2, 0, 24, 24, 64496,
|
|
))]),
|
|
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)),
|
|
]),
|
|
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)),
|
|
Payload::RouteOrigin(v6_origin(
|
|
Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0),
|
|
32,
|
|
48,
|
|
64498,
|
|
)),
|
|
]),
|
|
];
|
|
let session_ids = [410u16, 411u16, 412u16];
|
|
let serials = [100u32, 200u32, 300u32];
|
|
|
|
let d0 = Delta::new(
|
|
100,
|
|
vec![Payload::RouteOrigin(v4_origin(192, 0, 2, 0, 24, 24, 64496))],
|
|
vec![],
|
|
);
|
|
let d2 = Delta::new(
|
|
300,
|
|
vec![Payload::RouteOrigin(v6_origin(
|
|
Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0),
|
|
32,
|
|
48,
|
|
64498,
|
|
))],
|
|
vec![],
|
|
);
|
|
|
|
store
|
|
.save_cache_state_versioned(
|
|
CacheAvailability::Ready,
|
|
&snapshots,
|
|
&session_ids,
|
|
&serials,
|
|
&[Some(&d0), None, Some(&d2)],
|
|
&[Some((100, 100)), None, Some((300, 300))],
|
|
&[false, false, false],
|
|
)
|
|
.unwrap();
|
|
|
|
assert_eq!(store.get_availability().unwrap(), Some(CacheAvailability::Ready));
|
|
|
|
for version in 0u8..=2 {
|
|
let idx = version as usize;
|
|
let loaded_snapshot = store
|
|
.get_snapshot_for_version(version)
|
|
.unwrap()
|
|
.expect("snapshot should exist");
|
|
let loaded_session_id = store
|
|
.get_session_id_for_version(version)
|
|
.unwrap()
|
|
.expect("session_id should exist");
|
|
let loaded_serial = store
|
|
.get_serial_for_version(version)
|
|
.unwrap()
|
|
.expect("serial should exist");
|
|
|
|
assert!(snapshots[idx].same_content(&loaded_snapshot));
|
|
assert_eq!(loaded_session_id, session_ids[idx]);
|
|
assert_eq!(loaded_serial, serials[idx]);
|
|
}
|
|
|
|
assert_eq!(store.get_delta_window_for_version(0).unwrap(), Some((100, 100)));
|
|
assert_eq!(store.get_delta_window_for_version(1).unwrap(), None);
|
|
assert_eq!(store.get_delta_window_for_version(2).unwrap(), Some((300, 300)));
|
|
assert_eq!(
|
|
store.get_delta_for_version(0, 100).unwrap().map(|d| d.serial()),
|
|
Some(100)
|
|
);
|
|
assert!(store.get_delta_for_version(1, 200).unwrap().is_none());
|
|
assert_eq!(
|
|
store.get_delta_for_version(2, 300).unwrap().map(|d| d.serial()),
|
|
Some(300)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn store_db_versioned_delta_window_wraparound_is_isolated_by_version() {
|
|
let dir = tempfile::tempdir().unwrap();
|
|
let store = RtrStore::open(dir.path()).unwrap();
|
|
let snapshots = std::array::from_fn(|_| Snapshot::empty());
|
|
let session_ids = [600u16, 601u16, 602u16];
|
|
let serials = [0u32, 0u32, 0u32];
|
|
|
|
let d_max = Delta::new(
|
|
u32::MAX,
|
|
vec![Payload::RouteOrigin(v4_origin(192, 0, 2, 0, 24, 24, 64496))],
|
|
vec![],
|
|
);
|
|
let d_zero = Delta::new(
|
|
0,
|
|
vec![Payload::RouteOrigin(v4_origin(198, 51, 100, 0, 24, 24, 64497))],
|
|
vec![],
|
|
);
|
|
let d_one = Delta::new(
|
|
1,
|
|
vec![Payload::RouteOrigin(v4_origin(203, 0, 113, 0, 24, 24, 64498))],
|
|
vec![],
|
|
);
|
|
let d_v1_only = Delta::new(
|
|
0,
|
|
vec![Payload::RouteOrigin(v4_origin(10, 0, 0, 0, 24, 24, 64500))],
|
|
vec![],
|
|
);
|
|
|
|
store
|
|
.save_cache_state_versioned(
|
|
CacheAvailability::Ready,
|
|
&snapshots,
|
|
&session_ids,
|
|
&serials,
|
|
&[None, None, Some(&d_max)],
|
|
&[None, None, None],
|
|
&[false, false, false],
|
|
)
|
|
.unwrap();
|
|
store
|
|
.save_cache_state_versioned(
|
|
CacheAvailability::Ready,
|
|
&snapshots,
|
|
&session_ids,
|
|
&serials,
|
|
&[None, None, Some(&d_zero)],
|
|
&[None, None, None],
|
|
&[false, false, false],
|
|
)
|
|
.unwrap();
|
|
store
|
|
.save_cache_state_versioned(
|
|
CacheAvailability::Ready,
|
|
&snapshots,
|
|
&session_ids,
|
|
&serials,
|
|
&[None, None, Some(&d_one)],
|
|
&[None, None, None],
|
|
&[false, false, false],
|
|
)
|
|
.unwrap();
|
|
store
|
|
.save_cache_state_versioned(
|
|
CacheAvailability::Ready,
|
|
&snapshots,
|
|
&session_ids,
|
|
&serials,
|
|
&[None, Some(&d_v1_only), None],
|
|
&[None, None, None],
|
|
&[false, false, false],
|
|
)
|
|
.unwrap();
|
|
|
|
let v2_loaded = store.load_delta_window_for_version(2, u32::MAX, 1).unwrap();
|
|
assert_eq!(
|
|
v2_loaded.iter().map(Delta::serial).collect::<Vec<_>>(),
|
|
vec![u32::MAX, 0, 1]
|
|
);
|
|
|
|
let v1_loaded = store.load_delta_window_for_version(1, 0, 0).unwrap();
|
|
assert_eq!(v1_loaded.iter().map(Delta::serial).collect::<Vec<_>>(), vec![0]);
|
|
assert_eq!(v1_loaded[0].announced().len(), 1);
|
|
}
|
|
|
|
#[test]
|
|
fn store_db_versioned_clear_window_affects_only_target_version() {
|
|
let dir = tempfile::tempdir().unwrap();
|
|
let store = RtrStore::open(dir.path()).unwrap();
|
|
|
|
let snapshots = [
|
|
Snapshot::from_payloads(vec![Payload::RouteOrigin(v4_origin(
|
|
192, 0, 2, 0, 24, 24, 64496,
|
|
))]),
|
|
Snapshot::from_payloads(vec![Payload::RouteOrigin(v4_origin(
|
|
198, 51, 100, 0, 24, 24, 64497,
|
|
))]),
|
|
Snapshot::from_payloads(vec![Payload::RouteOrigin(v4_origin(
|
|
203, 0, 113, 0, 24, 24, 64498,
|
|
))]),
|
|
];
|
|
let session_ids = [420u16, 421u16, 422u16];
|
|
let serials = [10u32, 20u32, 30u32];
|
|
let d0 = Delta::new(
|
|
10,
|
|
vec![Payload::RouteOrigin(v4_origin(192, 0, 2, 0, 24, 24, 64496))],
|
|
vec![],
|
|
);
|
|
let d2 = Delta::new(
|
|
30,
|
|
vec![Payload::RouteOrigin(v4_origin(203, 0, 113, 0, 24, 24, 64498))],
|
|
vec![],
|
|
);
|
|
|
|
store
|
|
.save_cache_state_versioned(
|
|
CacheAvailability::Ready,
|
|
&snapshots,
|
|
&session_ids,
|
|
&serials,
|
|
&[Some(&d0), None, Some(&d2)],
|
|
&[Some((10, 10)), None, Some((30, 30))],
|
|
&[false, false, false],
|
|
)
|
|
.unwrap();
|
|
|
|
store
|
|
.save_cache_state_versioned(
|
|
CacheAvailability::Ready,
|
|
&snapshots,
|
|
&session_ids,
|
|
&serials,
|
|
&[None, None, None],
|
|
&[None, None, None],
|
|
&[true, false, false],
|
|
)
|
|
.unwrap();
|
|
|
|
assert_eq!(store.get_delta_window_for_version(0).unwrap(), None);
|
|
assert!(store.get_delta_for_version(0, 10).unwrap().is_none());
|
|
|
|
assert_eq!(store.get_delta_window_for_version(2).unwrap(), Some((30, 30)));
|
|
assert_eq!(
|
|
store.get_delta_for_version(2, 30).unwrap().map(|d| d.serial()),
|
|
Some(30)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn store_db_versioned_prunes_outside_window() {
|
|
let dir = tempfile::tempdir().unwrap();
|
|
let store = RtrStore::open(dir.path()).unwrap();
|
|
|
|
let snapshots = std::array::from_fn(|_| {
|
|
Snapshot::from_payloads(vec![Payload::RouteOrigin(v4_origin(
|
|
192, 0, 2, 0, 24, 24, 64496,
|
|
))])
|
|
});
|
|
let session_ids = [500u16, 501u16, 502u16];
|
|
let serials = [102u32, 0u32, 0u32];
|
|
let d100 = Delta::new(
|
|
100,
|
|
vec![Payload::RouteOrigin(v4_origin(10, 0, 0, 0, 24, 24, 65001))],
|
|
vec![],
|
|
);
|
|
let d101 = Delta::new(
|
|
101,
|
|
vec![Payload::RouteOrigin(v4_origin(10, 0, 1, 0, 24, 24, 65002))],
|
|
vec![],
|
|
);
|
|
let d102 = Delta::new(
|
|
102,
|
|
vec![Payload::RouteOrigin(v4_origin(10, 0, 2, 0, 24, 24, 65003))],
|
|
vec![],
|
|
);
|
|
|
|
store
|
|
.save_cache_state_versioned(
|
|
CacheAvailability::Ready,
|
|
&snapshots,
|
|
&session_ids,
|
|
&serials,
|
|
&[Some(&d100), None, None],
|
|
&[Some((100, 100)), None, None],
|
|
&[false, false, false],
|
|
)
|
|
.unwrap();
|
|
store
|
|
.save_cache_state_versioned(
|
|
CacheAvailability::Ready,
|
|
&snapshots,
|
|
&session_ids,
|
|
&serials,
|
|
&[Some(&d101), None, None],
|
|
&[Some((100, 101)), None, None],
|
|
&[false, false, false],
|
|
)
|
|
.unwrap();
|
|
store
|
|
.save_cache_state_versioned(
|
|
CacheAvailability::Ready,
|
|
&snapshots,
|
|
&session_ids,
|
|
&serials,
|
|
&[Some(&d102), None, None],
|
|
&[Some((102, 102)), None, None],
|
|
&[false, false, false],
|
|
)
|
|
.unwrap();
|
|
|
|
assert!(store.get_delta_for_version(0, 100).unwrap().is_none());
|
|
assert!(store.get_delta_for_version(0, 101).unwrap().is_none());
|
|
assert_eq!(
|
|
store.get_delta_for_version(0, 102).unwrap().map(|d| d.serial()),
|
|
Some(102)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn store_db_versioned_load_delta_window_requires_complete_range() {
|
|
let dir = tempfile::tempdir().unwrap();
|
|
let store = RtrStore::open(dir.path()).unwrap();
|
|
let snapshots = std::array::from_fn(|_| Snapshot::empty());
|
|
let session_ids = [700u16, 701u16, 702u16];
|
|
let serials = [0u32, 0u32, 0u32];
|
|
|
|
let d11 = Delta::new(
|
|
11,
|
|
vec![Payload::RouteOrigin(v4_origin(198, 51, 100, 0, 24, 24, 64497))],
|
|
vec![],
|
|
);
|
|
store
|
|
.save_cache_state_versioned(
|
|
CacheAvailability::Ready,
|
|
&snapshots,
|
|
&session_ids,
|
|
&serials,
|
|
&[None, Some(&d11), None],
|
|
&[None, None, None],
|
|
&[false, false, false],
|
|
)
|
|
.unwrap();
|
|
|
|
let err = store.load_delta_window_for_version(1, 10, 11).unwrap_err();
|
|
assert!(err
|
|
.to_string()
|
|
.contains("delta window starts at 10, but first persisted delta is Some(11)"));
|
|
}
|