mirror of
https://gitlab.com/veilid/veilid.git
synced 2025-02-24 00:19:49 -05:00
Merge branch 'tek/165-test-serializers' into 'dev'
Round trip serialization/deserialization tests for RoutingTable See merge request veilid/veilid!19
This commit is contained in:
commit
d93c007d8a
@ -187,7 +187,7 @@ impl ConnectionTable {
|
|||||||
pub fn get_last_connection_by_remote(&self, remote: PeerAddress) -> Option<ConnectionHandle> {
|
pub fn get_last_connection_by_remote(&self, remote: PeerAddress) -> Option<ConnectionHandle> {
|
||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
|
|
||||||
let id = inner.ids_by_remote.get(&remote).map(|v| v[(v.len() - 1)])?;
|
let id = inner.ids_by_remote.get(&remote).map(|v| v[v.len() - 1])?;
|
||||||
let protocol_index = Self::protocol_to_index(remote.protocol_type());
|
let protocol_index = Self::protocol_to_index(remote.protocol_type());
|
||||||
let out = inner.conn_by_id[protocol_index].get(&id).unwrap();
|
let out = inner.conn_by_id[protocol_index].get(&id).unwrap();
|
||||||
Some(out.get_handle())
|
Some(out.get_handle())
|
||||||
|
@ -13,6 +13,8 @@ mod stats_accounting;
|
|||||||
mod tasks;
|
mod tasks;
|
||||||
mod types;
|
mod types;
|
||||||
|
|
||||||
|
pub mod tests;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use crate::crypto::*;
|
use crate::crypto::*;
|
||||||
@ -55,6 +57,8 @@ pub struct LowLevelPortInfo {
|
|||||||
}
|
}
|
||||||
pub type RoutingTableEntryFilter<'t> =
|
pub type RoutingTableEntryFilter<'t> =
|
||||||
Box<dyn FnMut(&RoutingTableInner, Option<Arc<BucketEntry>>) -> bool + Send + 't>;
|
Box<dyn FnMut(&RoutingTableInner, Option<Arc<BucketEntry>>) -> bool + Send + 't>;
|
||||||
|
pub type SerializedBuckets = Vec<Vec<u8>>;
|
||||||
|
pub type SerializedBucketMap = BTreeMap<CryptoKind, SerializedBuckets>;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
||||||
pub struct RoutingTableHealth {
|
pub struct RoutingTableHealth {
|
||||||
@ -290,14 +294,14 @@ impl RoutingTable {
|
|||||||
debug!("finished routing table terminate");
|
debug!("finished routing table terminate");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serialize routing table to table store
|
/// Serialize the routing table.
|
||||||
async fn save_buckets(&self) -> EyreResult<()> {
|
fn serialized_buckets(&self) -> EyreResult<(SerializedBucketMap, SerializedBuckets)> {
|
||||||
// Since entries are shared by multiple buckets per cryptokind
|
// Since entries are shared by multiple buckets per cryptokind
|
||||||
// we need to get the list of all unique entries when serializing
|
// we need to get the list of all unique entries when serializing
|
||||||
let mut all_entries: Vec<Arc<BucketEntry>> = Vec::new();
|
let mut all_entries: Vec<Arc<BucketEntry>> = Vec::new();
|
||||||
|
|
||||||
// Serialize all buckets and get map of entries
|
// Serialize all buckets and get map of entries
|
||||||
let mut serialized_bucket_map: BTreeMap<CryptoKind, Vec<Vec<u8>>> = BTreeMap::new();
|
let mut serialized_bucket_map: SerializedBucketMap = BTreeMap::new();
|
||||||
{
|
{
|
||||||
let mut entry_map: HashMap<*const BucketEntry, u32> = HashMap::new();
|
let mut entry_map: HashMap<*const BucketEntry, u32> = HashMap::new();
|
||||||
let inner = &*self.inner.read();
|
let inner = &*self.inner.read();
|
||||||
@ -319,6 +323,13 @@ impl RoutingTable {
|
|||||||
all_entry_bytes.push(entry_bytes);
|
all_entry_bytes.push(entry_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok((serialized_bucket_map, all_entry_bytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write the serialized routing table to the table store.
|
||||||
|
async fn save_buckets(&self) -> EyreResult<()> {
|
||||||
|
let (serialized_bucket_map, all_entry_bytes) = self.serialized_buckets()?;
|
||||||
|
|
||||||
let table_store = self.unlocked_inner.network_manager().table_store();
|
let table_store = self.unlocked_inner.network_manager().table_store();
|
||||||
let tdb = table_store.open("routing_table", 1).await?;
|
let tdb = table_store.open("routing_table", 1).await?;
|
||||||
let dbx = tdb.transact();
|
let dbx = tdb.transact();
|
||||||
@ -333,24 +344,34 @@ impl RoutingTable {
|
|||||||
dbx.commit().await?;
|
dbx.commit().await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deserialize routing table from table store
|
/// Deserialize routing table from table store
|
||||||
async fn load_buckets(&self) -> EyreResult<()> {
|
async fn load_buckets(&self) -> EyreResult<()> {
|
||||||
// Deserialize bucket map and all entries from the table store
|
// Deserialize bucket map and all entries from the table store
|
||||||
let tstore = self.unlocked_inner.network_manager().table_store();
|
let tstore = self.unlocked_inner.network_manager().table_store();
|
||||||
let tdb = tstore.open("routing_table", 1).await?;
|
let tdb = tstore.open("routing_table", 1).await?;
|
||||||
let Some(serialized_bucket_map): Option<BTreeMap<CryptoKind, Vec<Vec<u8>>>> = tdb.load_rkyv(0, b"serialized_bucket_map").await? else {
|
let Some(serialized_bucket_map): Option<SerializedBucketMap> = tdb.load_rkyv(0, b"serialized_bucket_map").await? else {
|
||||||
log_rtab!(debug "no bucket map in saved routing table");
|
log_rtab!(debug "no bucket map in saved routing table");
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
let Some(all_entry_bytes): Option<Vec<Vec<u8>>> = tdb.load_rkyv(0, b"all_entry_bytes").await? else {
|
let Some(all_entry_bytes): Option<SerializedBuckets> = tdb.load_rkyv(0, b"all_entry_bytes").await? else {
|
||||||
log_rtab!(debug "no all_entry_bytes in saved routing table");
|
log_rtab!(debug "no all_entry_bytes in saved routing table");
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
// Reconstruct all entries
|
// Reconstruct all entries
|
||||||
let inner = &mut *self.inner.write();
|
let inner = &mut *self.inner.write();
|
||||||
|
self.populate_routing_table(inner, serialized_bucket_map, all_entry_bytes)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write the deserialized table store data to the routing table.
|
||||||
|
pub fn populate_routing_table(
|
||||||
|
&self,
|
||||||
|
inner: &mut RoutingTableInner,
|
||||||
|
serialized_bucket_map: SerializedBucketMap,
|
||||||
|
all_entry_bytes: SerializedBuckets,
|
||||||
|
) -> EyreResult<()> {
|
||||||
let mut all_entries: Vec<Arc<BucketEntry>> = Vec::with_capacity(all_entry_bytes.len());
|
let mut all_entries: Vec<Arc<BucketEntry>> = Vec::with_capacity(all_entry_bytes.len());
|
||||||
for entry_bytes in all_entry_bytes {
|
for entry_bytes in all_entry_bytes {
|
||||||
let entryinner =
|
let entryinner =
|
||||||
|
1
veilid-core/src/routing_table/tests/mod.rs
Normal file
1
veilid-core/src/routing_table/tests/mod.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub mod test_serialize;
|
84
veilid-core/src/routing_table/tests/test_serialize.rs
Normal file
84
veilid-core/src/routing_table/tests/test_serialize.rs
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
use crate::*;
|
||||||
|
|
||||||
|
fn fake_routing_table() -> routing_table::RoutingTable {
|
||||||
|
let veilid_config = VeilidConfig::new();
|
||||||
|
let block_store = BlockStore::new(veilid_config.clone());
|
||||||
|
let protected_store = ProtectedStore::new(veilid_config.clone());
|
||||||
|
let table_store = TableStore::new(veilid_config.clone(), protected_store.clone());
|
||||||
|
let crypto = Crypto::new(
|
||||||
|
veilid_config.clone(),
|
||||||
|
table_store.clone(),
|
||||||
|
protected_store.clone(),
|
||||||
|
);
|
||||||
|
let storage_manager = storage_manager::StorageManager::new(
|
||||||
|
veilid_config.clone(),
|
||||||
|
crypto.clone(),
|
||||||
|
protected_store.clone(),
|
||||||
|
table_store.clone(),
|
||||||
|
block_store.clone(),
|
||||||
|
);
|
||||||
|
let network_manager = network_manager::NetworkManager::new(
|
||||||
|
veilid_config.clone(),
|
||||||
|
storage_manager,
|
||||||
|
protected_store.clone(),
|
||||||
|
table_store.clone(),
|
||||||
|
block_store.clone(),
|
||||||
|
crypto.clone(),
|
||||||
|
);
|
||||||
|
routing_table::RoutingTable::new(network_manager)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn test_routingtable_buckets_round_trip() {
|
||||||
|
let original = fake_routing_table();
|
||||||
|
let copy = fake_routing_table();
|
||||||
|
original.init().await.unwrap();
|
||||||
|
copy.init().await.unwrap();
|
||||||
|
|
||||||
|
// Add lots of routes to `original` here to exercise all various types.
|
||||||
|
|
||||||
|
let (serialized_bucket_map, all_entry_bytes) = original.serialized_buckets().unwrap();
|
||||||
|
|
||||||
|
copy.populate_routing_table(
|
||||||
|
&mut copy.inner.write(),
|
||||||
|
serialized_bucket_map,
|
||||||
|
all_entry_bytes,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let original_inner = &*original.inner.read();
|
||||||
|
let copy_inner = &*copy.inner.read();
|
||||||
|
|
||||||
|
let routing_table_keys: Vec<_> = original_inner.buckets.keys().clone().collect();
|
||||||
|
let copy_keys: Vec<_> = copy_inner.buckets.keys().clone().collect();
|
||||||
|
|
||||||
|
assert_eq!(routing_table_keys.len(), copy_keys.len());
|
||||||
|
|
||||||
|
for crypto in routing_table_keys {
|
||||||
|
// The same keys are present in the original and copy RoutingTables.
|
||||||
|
let original_buckets = original_inner.buckets.get(&crypto).unwrap();
|
||||||
|
let copy_buckets = copy_inner.buckets.get(&crypto).unwrap();
|
||||||
|
|
||||||
|
// Recurse into RoutingTable.inner.buckets
|
||||||
|
for (left_buckets, right_buckets) in original_buckets.iter().zip(copy_buckets.iter()) {
|
||||||
|
// Recurse into RoutingTable.inner.buckets.entries
|
||||||
|
for ((left_crypto, left_entries), (right_crypto, right_entries)) in
|
||||||
|
left_buckets.entries().zip(right_buckets.entries())
|
||||||
|
{
|
||||||
|
assert_eq!(left_crypto, right_crypto);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
format!("{:?}", left_entries),
|
||||||
|
format!("{:?}", right_entries)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Even if these are mocks, we should still practice good hygiene.
|
||||||
|
original.terminate().await;
|
||||||
|
copy.terminate().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn test_all() {
|
||||||
|
test_routingtable_buckets_round_trip().await;
|
||||||
|
}
|
@ -12,3 +12,5 @@ use super::*;
|
|||||||
pub use common::*;
|
pub use common::*;
|
||||||
pub use crypto::tests::*;
|
pub use crypto::tests::*;
|
||||||
pub use network_manager::tests::*;
|
pub use network_manager::tests::*;
|
||||||
|
pub use routing_table::tests::*;
|
||||||
|
pub use veilid_api::tests::*;
|
||||||
|
@ -2,13 +2,16 @@
|
|||||||
#![cfg(not(target_arch = "wasm32"))]
|
#![cfg(not(target_arch = "wasm32"))]
|
||||||
use crate::crypto::tests::*;
|
use crate::crypto::tests::*;
|
||||||
use crate::network_manager::tests::*;
|
use crate::network_manager::tests::*;
|
||||||
|
use crate::routing_table;
|
||||||
use crate::tests::common::*;
|
use crate::tests::common::*;
|
||||||
|
use crate::veilid_api;
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub async fn run_all_tests() {
|
pub async fn run_all_tests() {
|
||||||
|
// iOS and Android tests also run these.
|
||||||
info!("TEST: test_host_interface");
|
info!("TEST: test_host_interface");
|
||||||
test_host_interface::test_all().await;
|
test_host_interface::test_all().await;
|
||||||
info!("TEST: test_types");
|
info!("TEST: test_types");
|
||||||
@ -29,6 +32,10 @@ pub async fn run_all_tests() {
|
|||||||
test_crypto::test_all().await;
|
test_crypto::test_all().await;
|
||||||
info!("TEST: test_envelope_receipt");
|
info!("TEST: test_envelope_receipt");
|
||||||
test_envelope_receipt::test_all().await;
|
test_envelope_receipt::test_all().await;
|
||||||
|
info!("TEST: veilid_api::test_serialize");
|
||||||
|
veilid_api::tests::test_serialize_rkyv::test_all().await;
|
||||||
|
info!("TEST: routing_table::test_serialize");
|
||||||
|
routing_table::tests::test_serialize::test_all().await;
|
||||||
|
|
||||||
info!("Finished unit tests");
|
info!("Finished unit tests");
|
||||||
}
|
}
|
||||||
@ -163,5 +170,22 @@ cfg_if! {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[serial]
|
||||||
|
fn run_test_serialize_rkyv() {
|
||||||
|
setup();
|
||||||
|
block_on(async {
|
||||||
|
veilid_api::tests::test_serialize_rkyv::test_all().await;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[serial]
|
||||||
|
fn run_test_routing_table_serialize() {
|
||||||
|
setup();
|
||||||
|
block_on(async {
|
||||||
|
routing_table::tests::test_serialize::test_all().await;
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,8 @@ mod routing_context;
|
|||||||
mod serialize_helpers;
|
mod serialize_helpers;
|
||||||
mod types;
|
mod types;
|
||||||
|
|
||||||
|
pub mod tests;
|
||||||
|
|
||||||
pub use api::*;
|
pub use api::*;
|
||||||
pub use debug::*;
|
pub use debug::*;
|
||||||
pub use error::*;
|
pub use error::*;
|
||||||
|
1
veilid-core/src/veilid_api/tests/mod.rs
Normal file
1
veilid-core/src/veilid_api/tests/mod.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub mod test_serialize_rkyv;
|
16
veilid-core/src/veilid_api/tests/test_serialize_rkyv.rs
Normal file
16
veilid-core/src/veilid_api/tests/test_serialize_rkyv.rs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
use crate::*;
|
||||||
|
|
||||||
|
pub async fn test_simple_string() {
|
||||||
|
let plain = "basic string".to_string();
|
||||||
|
let serialized = b"basic string\x0c\x00\x00\x00\xf4\xff\xff\xff".to_vec();
|
||||||
|
|
||||||
|
let a = to_rkyv(&plain);
|
||||||
|
assert_eq!(a.unwrap(), serialized);
|
||||||
|
|
||||||
|
let b = from_rkyv::<String>(serialized);
|
||||||
|
assert_eq!(b.unwrap(), plain);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn test_all() {
|
||||||
|
test_simple_string().await;
|
||||||
|
}
|
@ -89,3 +89,15 @@ async fn exec_test_envelope_receipt() {
|
|||||||
setup();
|
setup();
|
||||||
test_envelope_receipt::test_all().await;
|
test_envelope_receipt::test_all().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
async fn veilid_api__test_serialize_rkyv() {
|
||||||
|
setup();
|
||||||
|
veilid_api::test_serialize_rkyv::test_all().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
async fn routing_table__test_serialize() {
|
||||||
|
setup();
|
||||||
|
routing_table::test_serialize::test_all().await;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user