Skip to content

Commit d1fc055

Browse files
apskhemMr-Leshiy
andauthoredMar 18, 2025··
test(rust/signed-doc): Add integration test validating all functionalities against the spec (#229)
* feat: initial structure * feat: test modules * chore: move test from lib to tests * refactor: rename module * chore: minor refactor * chore: common * fix: roundtrip test * feat: dummy cat sign doc provider * feat: validate proposal doc * chore: fmtfix * feat: full test cases for proposal type * refactor: remove unused test module * feat: comment doc test * chore: lintfix * refactor: integration test modules * feat: multi sig validation * chore: fmtfix * cleanup * fix lint * fix spelling --------- Co-authored-by: Alex Pozhylenkov <[email protected]>
1 parent 698afa3 commit d1fc055

File tree

8 files changed

+429
-118
lines changed

8 files changed

+429
-118
lines changed
 

‎rust/catalyst-types/src/id_uri/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use role_index::RoleIndex;
2828
///
2929
/// Identity of Catalyst Registration.
3030
/// Optionally also identifies a specific Signed Document Key
31-
#[derive(Debug, Clone, PartialEq, Hash)]
31+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3232
#[allow(clippy::module_name_repetitions)]
3333
pub struct IdUri {
3434
/// Username

‎rust/signed_doc/src/lib.rs

-111
Original file line numberDiff line numberDiff line change
@@ -275,114 +275,3 @@ impl TryFrom<CatalystSignedDocument> for Vec<u8> {
275275
Ok(minicbor::to_vec(value)?)
276276
}
277277
}
278-
279-
#[cfg(test)]
280-
mod tests {
281-
use std::str::FromStr;
282-
283-
use ed25519_dalek::{SigningKey, VerifyingKey};
284-
use metadata::{ContentEncoding, ContentType};
285-
use rand::rngs::OsRng;
286-
287-
use super::*;
288-
use crate::{providers::VerifyingKeyProvider, validator::validate_signatures};
289-
290-
fn test_metadata() -> (UuidV7, UuidV4, serde_json::Value) {
291-
let alg = Algorithm::EdDSA;
292-
let uuid_v7 = UuidV7::new();
293-
let uuid_v4 = UuidV4::new();
294-
let section = "$".to_string();
295-
let collabs = vec!["Alex1".to_string(), "Alex2".to_string()];
296-
let content_type = ContentType::Json;
297-
let content_encoding = ContentEncoding::Brotli;
298-
299-
let metadata_fields = serde_json::json!({
300-
"alg": alg.to_string(),
301-
"content-type": content_type.to_string(),
302-
"content-encoding": content_encoding.to_string(),
303-
"type": uuid_v4.to_string(),
304-
"id": uuid_v7.to_string(),
305-
"ver": uuid_v7.to_string(),
306-
"ref": {"id": uuid_v7.to_string()},
307-
"reply": {"id": uuid_v7.to_string(), "ver": uuid_v7.to_string()},
308-
"template": {"id": uuid_v7.to_string()},
309-
"section": section,
310-
"collabs": collabs,
311-
"campaign_id": {"id": uuid_v7.to_string()},
312-
"election_id": uuid_v4.to_string(),
313-
"brand_id": {"id": uuid_v7.to_string()},
314-
"category_id": {"id": uuid_v7.to_string()},
315-
});
316-
(uuid_v7, uuid_v4, metadata_fields)
317-
}
318-
319-
#[test]
320-
fn catalyst_signed_doc_cbor_roundtrip_test() {
321-
let (uuid_v7, uuid_v4, metadata_fields) = test_metadata();
322-
let content = serde_json::to_vec(&serde_json::Value::Null).unwrap();
323-
324-
let doc = Builder::new()
325-
.with_json_metadata(metadata_fields.clone())
326-
.unwrap()
327-
.with_decoded_content(content.clone())
328-
.build();
329-
330-
assert!(!doc.problem_report().is_problematic());
331-
332-
let bytes: Vec<u8> = doc.try_into().unwrap();
333-
let decoded: CatalystSignedDocument = bytes.as_slice().try_into().unwrap();
334-
335-
assert_eq!(decoded.doc_type().unwrap(), uuid_v4);
336-
assert_eq!(decoded.doc_id().unwrap(), uuid_v7);
337-
assert_eq!(decoded.doc_ver().unwrap(), uuid_v7);
338-
assert_eq!(decoded.doc_content().decoded_bytes().unwrap(), &content);
339-
// TODO: after this test will be moved as a crate integration test, enable this
340-
// assertion assert_eq!(decoded.doc_meta(), metadata_fields.extra());
341-
}
342-
343-
struct Provider(anyhow::Result<Option<VerifyingKey>>);
344-
impl VerifyingKeyProvider for Provider {
345-
async fn try_get_key(
346-
&self, _kid: &IdUri,
347-
) -> anyhow::Result<Option<ed25519_dalek::VerifyingKey>> {
348-
let res = self.0.as_ref().map_err(|e| anyhow::anyhow!("{e}"))?;
349-
Ok(*res)
350-
}
351-
}
352-
353-
#[tokio::test]
354-
async fn signature_verification_test() {
355-
let mut csprng = OsRng;
356-
let sk: SigningKey = SigningKey::generate(&mut csprng);
357-
let content = serde_json::to_vec(&serde_json::Value::Null).unwrap();
358-
let pk = sk.verifying_key();
359-
360-
let kid_str = format!(
361-
"id.catalyst://cardano/{}/0/0",
362-
base64_url::encode(pk.as_bytes())
363-
);
364-
365-
let kid = IdUri::from_str(&kid_str).unwrap();
366-
let (_, _, metadata) = test_metadata();
367-
let signed_doc = Builder::new()
368-
.with_decoded_content(content)
369-
.with_json_metadata(metadata)
370-
.unwrap()
371-
.add_signature(sk.to_bytes(), kid.clone())
372-
.unwrap()
373-
.build();
374-
assert!(!signed_doc.problem_report().is_problematic());
375-
376-
assert!(
377-
validate_signatures(&signed_doc, &Provider(Err(anyhow::anyhow!("some error"))))
378-
.await
379-
.is_err()
380-
);
381-
assert!(validate_signatures(&signed_doc, &Provider(Ok(Some(pk))))
382-
.await
383-
.unwrap());
384-
assert!(!validate_signatures(&signed_doc, &Provider(Ok(None)))
385-
.await
386-
.unwrap());
387-
}
388-
}

‎rust/signed_doc/src/providers.rs

+31-6
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,28 @@ pub trait CatalystSignedDocumentProvider: Send + Sync {
2323
) -> impl Future<Output = anyhow::Result<Option<CatalystSignedDocument>>> + Send;
2424
}
2525

26-
#[cfg(test)]
27-
pub(crate) mod tests {
26+
pub mod tests {
27+
//! Simple providers implementation just for the testing purposes
28+
2829
use std::collections::HashMap;
2930

3031
use catalyst_types::uuid::Uuid;
3132

32-
use super::*;
33+
use super::{
34+
CatalystSignedDocument, CatalystSignedDocumentProvider, DocumentRef, IdUri, VerifyingKey,
35+
VerifyingKeyProvider,
36+
};
3337

34-
/// Index documents only by `id` field
38+
/// Simple testing implementation of `CatalystSignedDocumentProvider`
3539
#[derive(Default)]
36-
pub(crate) struct TestCatalystSignedDocumentProvider(HashMap<Uuid, CatalystSignedDocument>);
40+
pub struct TestCatalystSignedDocumentProvider(HashMap<Uuid, CatalystSignedDocument>);
3741

3842
impl TestCatalystSignedDocumentProvider {
39-
pub(crate) fn add_document(&mut self, doc: CatalystSignedDocument) -> anyhow::Result<()> {
43+
/// Inserts document into the `TestCatalystSignedDocumentProvider`
44+
///
45+
/// # Errors
46+
/// - Missing document id
47+
pub fn add_document(&mut self, doc: CatalystSignedDocument) -> anyhow::Result<()> {
4048
self.0.insert(doc.doc_id()?.uuid(), doc);
4149
Ok(())
4250
}
@@ -49,4 +57,21 @@ pub(crate) mod tests {
4957
Ok(self.0.get(&doc_ref.id.uuid()).cloned())
5058
}
5159
}
60+
61+
/// Simple testing implementation of `VerifyingKeyProvider`
62+
#[derive(Default)]
63+
pub struct TestVerifyingKeyProvider(HashMap<IdUri, VerifyingKey>);
64+
65+
impl TestVerifyingKeyProvider {
66+
/// Inserts public key into the `TestVerifyingKeyProvider`
67+
pub fn add_pk(&mut self, kid: IdUri, pk: VerifyingKey) {
68+
self.0.insert(kid, pk);
69+
}
70+
}
71+
72+
impl VerifyingKeyProvider for TestVerifyingKeyProvider {
73+
async fn try_get_key(&self, kid: &IdUri) -> anyhow::Result<Option<VerifyingKey>> {
74+
Ok(self.0.get(kid).copied())
75+
}
76+
}
5277
}

‎rust/signed_doc/tests/comment.rs

+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
//! Integration test for comment document validation part.
2+
3+
use catalyst_signed_doc::{providers::tests::TestCatalystSignedDocumentProvider, *};
4+
5+
mod common;
6+
7+
#[tokio::test]
8+
async fn test_valid_comment_doc() {
9+
let (proposal_doc, proposal_doc_id) =
10+
common::create_dummy_doc(doc_types::PROPOSAL_DOCUMENT_UUID_TYPE).unwrap();
11+
let (template_doc, template_doc_id) =
12+
common::create_dummy_doc(doc_types::COMMENT_TEMPLATE_UUID_TYPE).unwrap();
13+
14+
let uuid_v7 = UuidV7::new();
15+
let (doc, ..) = common::create_dummy_signed_doc(Some(serde_json::json!({
16+
"alg": Algorithm::EdDSA.to_string(),
17+
"content-type": ContentType::Json.to_string(),
18+
"content-encoding": ContentEncoding::Brotli.to_string(),
19+
"type": doc_types::COMMENT_DOCUMENT_UUID_TYPE,
20+
"id": uuid_v7.to_string(),
21+
"ver": uuid_v7.to_string(),
22+
"template": {
23+
"id": template_doc_id
24+
},
25+
"ref": {
26+
"id": proposal_doc_id
27+
}
28+
})))
29+
.unwrap();
30+
31+
let mut provider = TestCatalystSignedDocumentProvider::default();
32+
provider.add_document(template_doc).unwrap();
33+
provider.add_document(proposal_doc).unwrap();
34+
35+
let is_valid = validator::validate(&doc, &provider).await.unwrap();
36+
37+
assert!(is_valid);
38+
}
39+
40+
#[tokio::test]
41+
async fn test_valid_comment_doc_with_reply() {
42+
let empty_json = serde_json::to_vec(&serde_json::json!({})).unwrap();
43+
44+
let (proposal_doc, proposal_doc_id) =
45+
common::create_dummy_doc(doc_types::PROPOSAL_DOCUMENT_UUID_TYPE).unwrap();
46+
let (template_doc, template_doc_id) =
47+
common::create_dummy_doc(doc_types::COMMENT_TEMPLATE_UUID_TYPE).unwrap();
48+
49+
let comment_doc_id = UuidV7::new();
50+
let comment_doc = Builder::new()
51+
.with_json_metadata(serde_json::json!({
52+
"id": comment_doc_id,
53+
"type": doc_types::COMMENT_DOCUMENT_UUID_TYPE,
54+
"content-type": ContentType::Json.to_string(),
55+
"template": { "id": comment_doc_id.to_string() },
56+
"ref": {
57+
"id": proposal_doc_id
58+
},
59+
}))
60+
.unwrap()
61+
.with_decoded_content(empty_json.clone())
62+
.build();
63+
64+
let uuid_v7 = UuidV7::new();
65+
let (doc, ..) = common::create_dummy_signed_doc(Some(serde_json::json!({
66+
"alg": Algorithm::EdDSA.to_string(),
67+
"content-type": ContentType::Json.to_string(),
68+
"content-encoding": ContentEncoding::Brotli.to_string(),
69+
"type": doc_types::COMMENT_DOCUMENT_UUID_TYPE,
70+
"id": uuid_v7.to_string(),
71+
"ver": uuid_v7.to_string(),
72+
"template": {
73+
"id": template_doc_id
74+
},
75+
"ref": {
76+
"id": proposal_doc_id
77+
},
78+
"reply": {
79+
"id": comment_doc_id,
80+
"ver": uuid_v7
81+
}
82+
})))
83+
.unwrap();
84+
85+
let mut provider = TestCatalystSignedDocumentProvider::default();
86+
provider.add_document(template_doc).unwrap();
87+
provider.add_document(proposal_doc).unwrap();
88+
provider.add_document(comment_doc).unwrap();
89+
90+
let is_valid = validator::validate(&doc, &provider).await.unwrap();
91+
92+
assert!(is_valid);
93+
}
94+
95+
#[tokio::test]
96+
async fn test_invalid_comment_doc() {
97+
let (proposal_doc, _) =
98+
common::create_dummy_doc(doc_types::PROPOSAL_DOCUMENT_UUID_TYPE).unwrap();
99+
let (template_doc, template_doc_id) =
100+
common::create_dummy_doc(doc_types::COMMENT_TEMPLATE_UUID_TYPE).unwrap();
101+
102+
let uuid_v7 = UuidV7::new();
103+
let (doc, ..) = common::create_dummy_signed_doc(Some(serde_json::json!({
104+
"alg": Algorithm::EdDSA.to_string(),
105+
"content-type": ContentType::Json.to_string(),
106+
"content-encoding": ContentEncoding::Brotli.to_string(),
107+
"type": doc_types::COMMENT_DOCUMENT_UUID_TYPE,
108+
"id": uuid_v7.to_string(),
109+
"ver": uuid_v7.to_string(),
110+
"template": {
111+
"id": template_doc_id
112+
},
113+
// without ref
114+
"ref": serde_json::Value::Null
115+
})))
116+
.unwrap();
117+
118+
let mut provider = TestCatalystSignedDocumentProvider::default();
119+
provider.add_document(template_doc).unwrap();
120+
provider.add_document(proposal_doc).unwrap();
121+
122+
let is_valid = validator::validate(&doc, &provider).await.unwrap();
123+
124+
assert!(!is_valid);
125+
}

‎rust/signed_doc/tests/common/mod.rs

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
#![allow(dead_code)]
2+
3+
use std::str::FromStr;
4+
5+
use catalyst_signed_doc::*;
6+
7+
pub fn test_metadata() -> (UuidV7, UuidV4, serde_json::Value) {
8+
let uuid_v7 = UuidV7::new();
9+
let uuid_v4 = UuidV4::new();
10+
11+
let metadata_fields = serde_json::json!({
12+
"alg": Algorithm::EdDSA.to_string(),
13+
"content-type": ContentType::Json.to_string(),
14+
"content-encoding": ContentEncoding::Brotli.to_string(),
15+
"type": uuid_v4.to_string(),
16+
"id": uuid_v7.to_string(),
17+
"ver": uuid_v7.to_string(),
18+
"ref": {"id": uuid_v7.to_string()},
19+
"reply": {"id": uuid_v7.to_string(), "ver": uuid_v7.to_string()},
20+
"template": {"id": uuid_v7.to_string()},
21+
"section": "$".to_string(),
22+
"collabs": vec!["Alex1".to_string(), "Alex2".to_string()],
23+
"campaign_id": {"id": uuid_v7.to_string()},
24+
"election_id": uuid_v4.to_string(),
25+
"brand_id": {"id": uuid_v7.to_string()},
26+
"category_id": {"id": uuid_v7.to_string()},
27+
});
28+
29+
(uuid_v7, uuid_v4, metadata_fields)
30+
}
31+
32+
pub fn create_dummy_key_pair() -> anyhow::Result<(
33+
ed25519_dalek::SigningKey,
34+
ed25519_dalek::VerifyingKey,
35+
IdUri,
36+
)> {
37+
let sk = create_signing_key();
38+
let pk = sk.verifying_key();
39+
let kid = IdUri::from_str(&format!(
40+
"id.catalyst://cardano/{}/0/0",
41+
base64_url::encode(pk.as_bytes())
42+
))?;
43+
44+
Ok((sk, pk, kid))
45+
}
46+
47+
pub fn create_dummy_doc(doc_type_id: Uuid) -> anyhow::Result<(CatalystSignedDocument, UuidV7)> {
48+
let empty_json = serde_json::to_vec(&serde_json::json!({}))?;
49+
50+
let doc_id = UuidV7::new();
51+
52+
let doc = Builder::new()
53+
.with_json_metadata(serde_json::json!({
54+
"id": doc_id,
55+
"type": doc_type_id,
56+
"content-type": ContentType::Json.to_string(),
57+
"template": { "id": doc_id.to_string() }
58+
}))?
59+
.with_decoded_content(empty_json.clone())
60+
.build();
61+
62+
Ok((doc, doc_id))
63+
}
64+
65+
pub fn create_signing_key() -> ed25519_dalek::SigningKey {
66+
let mut csprng = rand::rngs::OsRng;
67+
ed25519_dalek::SigningKey::generate(&mut csprng)
68+
}
69+
70+
pub fn create_dummy_signed_doc(
71+
with_metadata: Option<serde_json::Value>,
72+
) -> anyhow::Result<(CatalystSignedDocument, ed25519_dalek::VerifyingKey, IdUri)> {
73+
let (sk, pk, kid) = create_dummy_key_pair()?;
74+
75+
let content = serde_json::to_vec(&serde_json::Value::Null)?;
76+
let (_, _, metadata) = test_metadata();
77+
78+
let signed_doc = Builder::new()
79+
.with_decoded_content(content)
80+
.with_json_metadata(with_metadata.unwrap_or(metadata))?
81+
.add_signature(sk.to_bytes(), kid.clone())?
82+
.build();
83+
84+
Ok((signed_doc, pk, kid))
85+
}

‎rust/signed_doc/tests/decoding.rs

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//! Integration test for COSE decoding part.
2+
3+
use catalyst_signed_doc::*;
4+
5+
mod common;
6+
7+
#[test]
8+
fn catalyst_signed_doc_cbor_roundtrip_test() {
9+
let (uuid_v7, uuid_v4, metadata_fields) = common::test_metadata();
10+
let content = serde_json::to_vec(&serde_json::Value::Null).unwrap();
11+
12+
let doc = Builder::new()
13+
.with_json_metadata(metadata_fields.clone())
14+
.unwrap()
15+
.with_decoded_content(content.clone())
16+
.build();
17+
18+
assert!(!doc.problem_report().is_problematic());
19+
20+
let bytes: Vec<u8> = doc.try_into().unwrap();
21+
let decoded: CatalystSignedDocument = bytes.as_slice().try_into().unwrap();
22+
let extra_fields: ExtraFields = serde_json::from_value(metadata_fields).unwrap();
23+
24+
assert_eq!(decoded.doc_type().unwrap(), uuid_v4);
25+
assert_eq!(decoded.doc_id().unwrap(), uuid_v7);
26+
assert_eq!(decoded.doc_ver().unwrap(), uuid_v7);
27+
assert_eq!(decoded.doc_content().decoded_bytes().unwrap(), &content);
28+
assert_eq!(decoded.doc_meta(), &extra_fields);
29+
}

‎rust/signed_doc/tests/proposal.rs

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
//! Integration test for proposal document validation part.
2+
3+
use catalyst_signed_doc::{providers::tests::TestCatalystSignedDocumentProvider, *};
4+
5+
mod common;
6+
7+
#[tokio::test]
8+
async fn test_valid_proposal_doc() {
9+
let (template_doc, template_doc_id) =
10+
common::create_dummy_doc(doc_types::PROPOSAL_TEMPLATE_UUID_TYPE).unwrap();
11+
12+
let uuid_v7 = UuidV7::new();
13+
let (doc, ..) = common::create_dummy_signed_doc(Some(serde_json::json!({
14+
"alg": Algorithm::EdDSA.to_string(),
15+
"content-type": ContentType::Json.to_string(),
16+
"content-encoding": ContentEncoding::Brotli.to_string(),
17+
"type": doc_types::PROPOSAL_DOCUMENT_UUID_TYPE,
18+
"id": uuid_v7.to_string(),
19+
"ver": uuid_v7.to_string(),
20+
"template": {
21+
"id": template_doc_id
22+
},
23+
})))
24+
.unwrap();
25+
26+
let mut provider = TestCatalystSignedDocumentProvider::default();
27+
provider.add_document(template_doc).unwrap();
28+
29+
let is_valid = validator::validate(&doc, &provider).await.unwrap();
30+
31+
assert!(is_valid);
32+
}
33+
34+
#[tokio::test]
35+
async fn test_valid_proposal_doc_with_empty_provider() {
36+
// dummy template doc to dummy provider
37+
let template_doc_id = UuidV7::new();
38+
39+
let uuid_v7 = UuidV7::new();
40+
let (doc, ..) = common::create_dummy_signed_doc(Some(serde_json::json!({
41+
"alg": Algorithm::EdDSA.to_string(),
42+
"content-type": ContentType::Json.to_string(),
43+
"content-encoding": ContentEncoding::Brotli.to_string(),
44+
"type": doc_types::PROPOSAL_DOCUMENT_UUID_TYPE,
45+
"id": uuid_v7.to_string(),
46+
"ver": uuid_v7.to_string(),
47+
"template": {
48+
"id": template_doc_id
49+
},
50+
})))
51+
.unwrap();
52+
53+
let provider = TestCatalystSignedDocumentProvider::default();
54+
55+
let is_valid = validator::validate(&doc, &provider).await.unwrap();
56+
57+
assert!(!is_valid);
58+
}
59+
60+
#[tokio::test]
61+
async fn test_invalid_proposal_doc() {
62+
let uuid_v7 = UuidV7::new();
63+
let (doc, ..) = common::create_dummy_signed_doc(Some(serde_json::json!({
64+
"alg": Algorithm::EdDSA.to_string(),
65+
"content-type": ContentType::Json.to_string(),
66+
"content-encoding": ContentEncoding::Brotli.to_string(),
67+
"type": doc_types::PROPOSAL_DOCUMENT_UUID_TYPE,
68+
"id": uuid_v7.to_string(),
69+
"ver": uuid_v7.to_string(),
70+
// without specifying template id
71+
"template": serde_json::Value::Null,
72+
})))
73+
.unwrap();
74+
75+
let provider = TestCatalystSignedDocumentProvider::default();
76+
77+
let is_valid = validator::validate(&doc, &provider).await.unwrap();
78+
79+
assert!(!is_valid);
80+
}

‎rust/signed_doc/tests/signature.rs

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
//! Integration test for signature validation part.
2+
3+
use catalyst_signed_doc::{providers::tests::TestVerifyingKeyProvider, *};
4+
5+
mod common;
6+
7+
#[tokio::test]
8+
async fn single_signature_validation_test() {
9+
let (signed_doc, pk, kid) = common::create_dummy_signed_doc(None).unwrap();
10+
assert!(!signed_doc.problem_report().is_problematic());
11+
12+
// case: has key
13+
let mut provider = TestVerifyingKeyProvider::default();
14+
provider.add_pk(kid.clone(), pk);
15+
assert!(validator::validate_signatures(&signed_doc, &provider)
16+
.await
17+
.is_ok_and(|v| v));
18+
19+
// case: empty provider
20+
assert!(
21+
validator::validate_signatures(&signed_doc, &TestVerifyingKeyProvider::default())
22+
.await
23+
.is_ok_and(|v| !v)
24+
);
25+
}
26+
27+
#[tokio::test]
28+
async fn multiple_signatures_validation_test() {
29+
let (sk1, pk1, kid1) = common::create_dummy_key_pair().unwrap();
30+
let (sk2, pk2, kid2) = common::create_dummy_key_pair().unwrap();
31+
let (sk3, pk3, kid3) = common::create_dummy_key_pair().unwrap();
32+
let (_, pk_n, kid_n) = common::create_dummy_key_pair().unwrap();
33+
34+
let signed_doc = Builder::new()
35+
.with_decoded_content(serde_json::to_vec(&serde_json::Value::Null).unwrap())
36+
.with_json_metadata(common::test_metadata().2)
37+
.unwrap()
38+
.add_signature(sk1.to_bytes(), kid1.clone())
39+
.unwrap()
40+
.add_signature(sk2.to_bytes(), kid2.clone())
41+
.unwrap()
42+
.add_signature(sk3.to_bytes(), kid3.clone())
43+
.unwrap()
44+
.build();
45+
46+
assert!(!signed_doc.problem_report().is_problematic());
47+
48+
// case: all signatures valid
49+
let mut provider = TestVerifyingKeyProvider::default();
50+
provider.add_pk(kid1.clone(), pk1);
51+
provider.add_pk(kid2.clone(), pk2);
52+
provider.add_pk(kid3.clone(), pk3);
53+
assert!(validator::validate_signatures(&signed_doc, &provider)
54+
.await
55+
.is_ok_and(|v| v));
56+
57+
// case: partially available signatures
58+
let mut provider = TestVerifyingKeyProvider::default();
59+
provider.add_pk(kid1.clone(), pk1);
60+
provider.add_pk(kid2.clone(), pk2);
61+
assert!(validator::validate_signatures(&signed_doc, &provider)
62+
.await
63+
.is_ok_and(|v| !v));
64+
65+
// case: with unrecognized provider
66+
let mut provider = TestVerifyingKeyProvider::default();
67+
provider.add_pk(kid_n.clone(), pk_n);
68+
assert!(validator::validate_signatures(&signed_doc, &provider)
69+
.await
70+
.is_ok_and(|v| !v));
71+
72+
// case: no valid signatures available
73+
assert!(
74+
validator::validate_signatures(&signed_doc, &TestVerifyingKeyProvider::default())
75+
.await
76+
.is_ok_and(|v| !v)
77+
);
78+
}

0 commit comments

Comments
 (0)
Please sign in to comment.