Skip to content

Commit

Permalink
Add tests for poll_server_for_new_certificates
Browse files Browse the repository at this point in the history
  • Loading branch information
TimeEngineer committed Nov 3, 2023
1 parent 363371a commit 3a5493a
Show file tree
Hide file tree
Showing 3 changed files with 260 additions and 4 deletions.
9 changes: 5 additions & 4 deletions libparsec/crates/client/src/certificates_ops/poll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,12 @@ pub(super) async fn poll_server_for_new_certificates(

// `latest_known_index` is useful to detect outdated `CertificatesUpdated`
// events given the server has already been polled in the meantime.
let offset = match (&last_index, latest_known_index) {
(last_index, Some(latest_known_index)) if *last_index >= latest_known_index => {
return Ok(*last_index)
let offset = match (last_index, latest_known_index) {
(last_index, Some(latest_known_index)) if last_index >= latest_known_index => {
return Ok(last_index)
}
// Certificate index starts at 1, so can be used as-is as offset
(last_index, _) => *last_index,
(last_index, _) => last_index,
};

// 2) We are missing some certificates, time to ask the server about them...
Expand Down Expand Up @@ -120,6 +120,7 @@ pub(super) async fn poll_server_for_new_certificates(
let outcome = ops
.add_certificates_batch(&store, new_offset, certificates)
.await?;

match outcome {
MaybeRedactedSwitch::NoSwitch => (),
// Unlike other profiles, Outsider is required to use the redacted
Expand Down
1 change: 1 addition & 0 deletions libparsec/crates/client/tests/unit/certificates_ops/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ mod add_sequester_authority_certificate;
mod add_user_certificate;
mod add_user_revoked_certificate;
mod add_user_update_certificate;
mod poll;
mod store;
mod utils;
254 changes: 254 additions & 0 deletions libparsec/crates/client/tests/unit/certificates_ops/poll.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
// Parsec Cloud (https://parsec.cloud) Copyright (c) BUSL-1.1 2016-present Scille SAS

use libparsec_client_connection::{
test_register_low_level_send_hook, test_register_send_hook, HeaderMap, ResponseMock, StatusCode,
};
use libparsec_protocol::authenticated_cmds;
use libparsec_tests_fixtures::prelude::*;
use libparsec_types::prelude::*;

use crate::certificates_ops::PollServerError;

use super::utils::certificates_ops_factory;

#[parsec_test(testbed = "minimal")]
async fn empty(env: &TestbedEnv) {
let alice = env.local_device("alice@dev1");

let ops = certificates_ops_factory(env, &alice).await;

test_register_send_hook(
&env.discriminant_dir,
move |req: authenticated_cmds::latest::certificate_get::Req| {
p_assert_eq!(req.offset, 0);

authenticated_cmds::latest::certificate_get::Rep::Ok {
certificates: vec![],
}
},
);

let index = ops.poll_server_for_new_certificates(None).await.unwrap();

p_assert_eq!(index, 0);

ops.stop().await;
}

#[parsec_test(testbed = "minimal")]
async fn user_certificate(env: &TestbedEnv) {
let alice = env.local_device("alice@dev1");

let ops = certificates_ops_factory(env, &alice).await;

let (_, alice_signed) = env.get_user_certificate("alice");

test_register_send_hook(
&env.discriminant_dir,
move |req: authenticated_cmds::latest::certificate_get::Req| {
p_assert_eq!(req.offset, 0);

authenticated_cmds::latest::certificate_get::Rep::Ok {
certificates: vec![alice_signed],
}
},
);

let index = ops.poll_server_for_new_certificates(None).await.unwrap();

p_assert_eq!(index, 1);

ops.stop().await;
}

#[parsec_test(testbed = "minimal")]
async fn certificates(env: &TestbedEnv) {
let alice = env.local_device("alice@dev1");

let ops = certificates_ops_factory(env, &alice).await;

let (_, alice_signed) = env.get_user_certificate("alice");
let (_, alice_dev1_signed) = env.get_device_certificate("alice@dev1");

test_register_send_hook(
&env.discriminant_dir,
move |req: authenticated_cmds::latest::certificate_get::Req| {
p_assert_eq!(req.offset, 0);

authenticated_cmds::latest::certificate_get::Rep::Ok {
certificates: vec![alice_signed, alice_dev1_signed],
}
},
);

let index = ops.poll_server_for_new_certificates(None).await.unwrap();

p_assert_eq!(index, 2);

ops.stop().await;
}

#[parsec_test(testbed = "minimal")]
async fn minimal(env: &TestbedEnv) {
let alice = env.local_device("alice@dev1");

let ops = certificates_ops_factory(env, &alice).await;
let certificates = env
.template
.certificates()
.map(|e| e.signed)
.collect::<Vec<_>>();
let expected_index = certificates.len() as IndexInt;

test_register_send_hook(
&env.discriminant_dir,
move |req: authenticated_cmds::latest::certificate_get::Req| {
p_assert_eq!(req.offset, 0);

authenticated_cmds::latest::certificate_get::Rep::Ok { certificates }
},
);

let index = ops.poll_server_for_new_certificates(None).await.unwrap();

p_assert_eq!(index, expected_index);

ops.stop().await;
}

#[parsec_test(testbed = "minimal")]
async fn nothing_to_poll(env: &TestbedEnv) {
let alice = env.local_device("alice@dev1");

let ops = certificates_ops_factory(env, &alice).await;
let certificates = env
.template
.certificates()
.map(|e| e.signed)
.collect::<Vec<_>>();
let next_offset = env.get_last_certificate_index();

test_register_send_hook(
&env.discriminant_dir,
move |req: authenticated_cmds::latest::certificate_get::Req| {
p_assert_eq!(req.offset, next_offset);

authenticated_cmds::latest::certificate_get::Rep::Ok {
certificates: vec![],
}
},
);

test_register_send_hook(
&env.discriminant_dir,
move |req: authenticated_cmds::latest::certificate_get::Req| {
p_assert_eq!(req.offset, 0);

authenticated_cmds::latest::certificate_get::Rep::Ok { certificates }
},
);

// Poll all
let last_index = ops.poll_server_for_new_certificates(None).await.unwrap();

// Nothing to poll
let index = ops
.poll_server_for_new_certificates(Some(last_index))
.await
.unwrap();

p_assert_eq!(index, last_index);

ops.stop().await;
}

#[parsec_test(testbed = "minimal")]
async fn invalid_certif_received(env: &TestbedEnv) {
let alice = env.local_device("alice@dev1");

let ops = certificates_ops_factory(env, &alice).await;

test_register_send_hook(
&env.discriminant_dir,
move |_: authenticated_cmds::latest::certificate_get::Req| {
authenticated_cmds::latest::certificate_get::Rep::Ok {
certificates: vec![Bytes::from_static(b"foo")],
}
},
);

let err = ops
.poll_server_for_new_certificates(None)
.await
.unwrap_err();

p_assert_matches!(err, PollServerError::InvalidCertificate(..));

ops.stop().await;
}

#[parsec_test(testbed = "minimal")]
async fn unknown_status(env: &TestbedEnv) {
let alice = env.local_device("alice@dev1");

let ops = certificates_ops_factory(env, &alice).await;

test_register_send_hook(
&env.discriminant_dir,
move |_: authenticated_cmds::latest::certificate_get::Req| {
authenticated_cmds::latest::certificate_get::Rep::UnknownStatus {
unknown_status: "".into(),
reason: None,
}
},
);

let err = ops
.poll_server_for_new_certificates(None)
.await
.unwrap_err();

p_assert_matches!(err, PollServerError::Internal(..));

ops.stop().await;
}

#[parsec_test(testbed = "minimal")]
async fn offline(env: &TestbedEnv) {
let alice = env.local_device("alice@dev1");

let ops = certificates_ops_factory(env, &alice).await;

let err = ops
.poll_server_for_new_certificates(None)
.await
.unwrap_err();

p_assert_matches!(err, PollServerError::Offline);

ops.stop().await;
}

#[parsec_test(testbed = "minimal")]
async fn invalid_response(env: &TestbedEnv) {
let alice = env.local_device("alice@dev1");

let ops = certificates_ops_factory(env, &alice).await;

test_register_low_level_send_hook(&env.discriminant_dir, |_request_builder| async {
Ok(ResponseMock::Mocked((
StatusCode::IM_A_TEAPOT,
HeaderMap::new(),
Bytes::new(),
)))
});

let err = ops
.poll_server_for_new_certificates(None)
.await
.unwrap_err();

p_assert_matches!(err, PollServerError::Internal(..));

ops.stop().await;
}

0 comments on commit 3a5493a

Please sign in to comment.