From fe7d95ed7bc5ed90c4d850b0200909877ee0121e Mon Sep 17 00:00:00 2001 From: Simon Paitrault Date: Mon, 20 Nov 2023 17:51:42 +0100 Subject: [PATCH] test: adding certificate precedence ordering (#375) Signed-off-by: Simon Paitrault --- .../tests/grpc/certificate_precedence.rs | 122 ++++++++++++++++++ crates/topos-tce-api/tests/grpc/mod.rs | 1 + crates/topos-tce-api/tests/runtime.rs | 2 + 3 files changed, 125 insertions(+) create mode 100644 crates/topos-tce-api/tests/grpc/certificate_precedence.rs create mode 100644 crates/topos-tce-api/tests/grpc/mod.rs diff --git a/crates/topos-tce-api/tests/grpc/certificate_precedence.rs b/crates/topos-tce-api/tests/grpc/certificate_precedence.rs new file mode 100644 index 000000000..676bf4dcc --- /dev/null +++ b/crates/topos-tce-api/tests/grpc/certificate_precedence.rs @@ -0,0 +1,122 @@ +use base64ct::{Base64, Encoding}; +use rstest::rstest; +use std::sync::Arc; +use test_log::test; +use tokio_stream::Stream; +use topos_api::grpc::tce::v1::{GetLastPendingCertificatesRequest, LastPendingCertificate}; +use topos_core::uci::Certificate; +use topos_tce_api::RuntimeEvent; +use topos_test_sdk::{ + certificates::create_certificate_chain, + constants::{SOURCE_SUBNET_ID_1, TARGET_SUBNET_ID_1}, + storage::{create_fullnode_store, create_validator_store, storage_client}, + tce::public_api::{broadcast_stream, create_public_api, PublicApiContext}, +}; + +use topos_tce_storage::{types::CertificateDeliveredWithPositions, validator::ValidatorStore}; + +#[rstest] +#[test(tokio::test)] +async fn fetch_latest_pending_certificates() { + let fullnode_store = create_fullnode_store(vec![]).await; + let validator_store: Arc = + create_validator_store(vec![], futures::future::ready(fullnode_store.clone())).await; + + let (tx, rx): ( + _, + tokio::sync::broadcast::Receiver, + ) = tokio::sync::broadcast::channel(10); + + let (mut api_context, _) = create_public_api( + storage_client(vec![]), + broadcast_stream(), + futures::future::ready(validator_store.clone()), + ) + .await; + let mut client = api_context.api_client; + let certificates = create_certificate_chain(SOURCE_SUBNET_ID_1, &[TARGET_SUBNET_ID_1], 2); + + let expected = certificates[1].certificate.clone(); + + assert!(validator_store + .insert_pending_certificate(&certificates[1].certificate) + .unwrap() + .is_none()); + + assert!(validator_store + .insert_pending_certificate(&certificates[0].certificate) + .unwrap() + .is_some()); + + let mut res = client + .get_last_pending_certificates(GetLastPendingCertificatesRequest { + subnet_ids: vec![SOURCE_SUBNET_ID_1.into()], + }) + .await + .unwrap() + .into_inner(); + + let res: LastPendingCertificate = res + .last_pending_certificate + .remove(&Base64::encode_string(SOURCE_SUBNET_ID_1.as_array())) + .unwrap(); + + let res: Certificate = res.value.unwrap().try_into().unwrap(); + + assert_eq!(res, expected); +} + +#[rstest] +#[test(tokio::test)] +async fn fetch_latest_pending_certificates_with_conflicts() { + let fullnode_store = create_fullnode_store(vec![]).await; + let validator_store: Arc = + create_validator_store(vec![], futures::future::ready(fullnode_store.clone())).await; + + let (tx, rx): ( + _, + tokio::sync::broadcast::Receiver, + ) = tokio::sync::broadcast::channel(10); + + let (mut api_context, _) = create_public_api( + storage_client(vec![]), + broadcast_stream(), + futures::future::ready(validator_store.clone()), + ) + .await; + let mut client = api_context.api_client; + let mut certificates = create_certificate_chain(SOURCE_SUBNET_ID_1, &[TARGET_SUBNET_ID_1], 3); + + certificates[2].certificate.prev_id = certificates[1].certificate.prev_id; + + let expected = certificates[2].certificate.clone(); + + for certificate in certificates.iter().skip(1) { + assert!(validator_store + .insert_pending_certificate(&certificate.certificate) + .unwrap() + .is_none()); + } + + assert!(validator_store + .insert_pending_certificate(&certificates[0].certificate) + .unwrap() + .is_some()); + + let mut res = client + .get_last_pending_certificates(GetLastPendingCertificatesRequest { + subnet_ids: vec![SOURCE_SUBNET_ID_1.into()], + }) + .await + .unwrap() + .into_inner(); + + let res: LastPendingCertificate = res + .last_pending_certificate + .remove(&Base64::encode_string(SOURCE_SUBNET_ID_1.as_array())) + .unwrap(); + + let res: Certificate = res.value.unwrap().try_into().unwrap(); + + assert_eq!(res, expected); +} diff --git a/crates/topos-tce-api/tests/grpc/mod.rs b/crates/topos-tce-api/tests/grpc/mod.rs new file mode 100644 index 000000000..769ba1e4e --- /dev/null +++ b/crates/topos-tce-api/tests/grpc/mod.rs @@ -0,0 +1 @@ +mod certificate_precedence; diff --git a/crates/topos-tce-api/tests/runtime.rs b/crates/topos-tce-api/tests/runtime.rs index 2b2e294be..0357e8811 100644 --- a/crates/topos-tce-api/tests/runtime.rs +++ b/crates/topos-tce-api/tests/runtime.rs @@ -29,6 +29,8 @@ use topos_test_sdk::networking::get_available_addr; use topos_test_sdk::storage::{create_fullnode_store, create_validator_store, storage_client}; use topos_test_sdk::tce::public_api::{broadcast_stream, create_public_api, PublicApiContext}; +mod grpc; + #[rstest] #[timeout(Duration::from_secs(4))] #[test(tokio::test)]