Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consolidate test vectors, add nextest filter #288

Merged
merged 4 commits into from
Aug 16, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ jobs:
- name: Run Rust Tests
run: |
mkdir -p test-results
cargo nextest run --profile ci --config-file ./nextest.toml
cargo nextest run --profile ci --config-file ./nextest.toml -E 'test(test_vectors::)'
- name: Modify testsuite name in XML for test runner consumption
run: |
sed -i '' 's/<testsuite name="web5"/<testsuite name="Web5TestVectorsProtocolTest"/' target/nextest/ci/junit.xml
Expand All @@ -252,4 +252,4 @@ jobs:
uses: actions/upload-artifact@v3
with:
name: rust-test-results
path: test-results/rust-test-results.xml
path: test-results/rust-test-results.xml
52 changes: 0 additions & 52 deletions crates/web5/src/credentials/presentation_definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,55 +238,3 @@ impl JsonSchemaBuilder {
})
}
}

#[cfg(test)]
mod tests {
use std::collections::HashSet;

use crate::test_helpers::TestVectorFile;

use super::PresentationDefinition;

#[derive(Debug, serde::Deserialize)]
struct VectorInput {
#[serde(rename = "presentationDefinition")]
pub presentation_definition: PresentationDefinition,
#[serde(rename = "credentialJwts")]
pub credential_jwts: Vec<String>,
}

#[derive(Debug, serde::Deserialize)]
struct VectorOutput {
#[serde(rename = "selectedCredentials")]
pub selected_credentials: Vec<String>,
}

#[test]
#[ignore] // TODO temporarily ignoring, because web5-spec test vectors use did:key which isn't supported
fn test_web5_spec_test_vectors() {
let path = "presentation_exchange/select_credentials.json";
let vectors: TestVectorFile<VectorInput, VectorOutput> =
TestVectorFile::load_from_path(path);

for vector in vectors.vectors {
let presentation_definition = vector.input.presentation_definition;
let vc_jwts = vector.input.credential_jwts;
let error_msg = format!(
"Selected Credential test vector ({}) should not have thrown error",
vector.description
);

let selected_credentials = presentation_definition
.select_credentials(&vc_jwts)
.expect(&error_msg);

let set1: HashSet<_> = selected_credentials.iter().collect();
let set2: HashSet<_> = vector.output.selected_credentials.iter().collect();
assert_eq!(
set1, set2,
"Vectors do not contain the same elements: {}",
error_msg
);
}
}
}
62 changes: 0 additions & 62 deletions crates/web5/src/dids/methods/did_dht/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,65 +311,3 @@ mod tests {
assert_eq!(resolved_document, did_dht.document)
}
}

#[cfg(test)]
mod web5_test_vectors_did_dht {
use crate::dids::resolution::resolution_metadata::ResolutionMetadataError;
use crate::{
dids::resolution::resolution_metadata::ResolutionMetadata, test_helpers::TestVectorFile,
};

#[derive(Debug, PartialEq, serde::Deserialize)]
struct VectorInput {
#[serde(rename = "didUri")]
did_uri: String,
}

#[derive(Debug, PartialEq, serde::Deserialize)]
struct VectorOutput {
#[serde(rename = "didResolutionMetadata")]
did_resolution_metadata: ResolutionMetadata,
}

#[test]
fn resolve() {
let path = "did_dht/resolve.json";
let vectors: TestVectorFile<VectorInput, VectorOutput> =
TestVectorFile::load_from_path(path);

for vector in vectors.vectors {
let vector_input = vector.input;
let vector_output = &vector.output;

// As a replay attack protection protocol, if the same DID is doing a GET request within 5 minutes of each other, instead of a 404 it will start returning a 429.
// to get around this for our test we just create a new DID that is not published to get a fresh 404 for this error code
if let Some(ResolutionMetadataError::NotFound) =
vector_output.did_resolution_metadata.error
{
// TODO: According to the did dht spec a 404 should be returned when trying to resolve a DID that does not exists. Currently it incorrectly returns a 429 even on the first call.
// Uncomment this code block when resolved - https://github.com/TBD54566975/web5-rs/issues/286
continue;

// let private_jwk = Ed25519Generator::generate();
// let identity_key = ed25519::to_public_jwk(&private_jwk);
// let did_dht =
// DidDht::from_identity_key(identity_key.clone()).expect("Should create did:dht");
//
// vector_input = VectorInput{
// did_uri: did_dht.did.uri,
// };
}

let resolution_result = super::DidDht::resolve(&vector_input.did_uri);

let metadata_error = resolution_result.resolution_metadata.error.as_ref();
let expected_error = vector_output.did_resolution_metadata.error.as_ref();

assert_eq!(
metadata_error, expected_error,
"Document resolution metadata does not match. Expected '{:?}' but got '{:?}'.",
expected_error, metadata_error
);
}
}
}
68 changes: 0 additions & 68 deletions crates/web5/src/dids/methods/did_jwk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,71 +115,3 @@ impl DidJwk {
}
}
}

#[cfg(test)]
mod web5_test_vectors_did_jwk {
use crate::{
dids::{
data_model::document::Document,
resolution::{
document_metadata::DocumentMetadata, resolution_metadata::ResolutionMetadata,
},
},
test_helpers::TestVectorFile,
};

#[derive(Debug, PartialEq, serde::Deserialize)]
struct VectorOutput {
#[serde(rename = "@context")]
context: String,
#[serde(rename = "didDocument")]
did_document: Option<Document>,
#[serde(rename = "didDocumentMetadata")]
did_document_metadata: DocumentMetadata,
#[serde(rename = "didResolutionMetadata")]
did_resolution_metadata: ResolutionMetadata,
}

#[test]
fn resolve() {
let path = "did_jwk/resolve.json";
let vectors: TestVectorFile<String, VectorOutput> = TestVectorFile::load_from_path(path);

for vector in vectors.vectors {
let did_uri = vector.input;
let resolution_result = super::DidJwk::resolve(&did_uri);

let all_none = vector.output.did_document_metadata.created.is_none()
&& vector.output.did_document_metadata.updated.is_none()
&& vector.output.did_document_metadata.deactivated.is_none()
&& vector.output.did_document_metadata.next_update.is_none()
&& vector.output.did_document_metadata.version_id.is_none()
&& vector
.output
.did_document_metadata
.next_version_id
.is_none()
&& vector.output.did_document_metadata.equivalent_id.is_none()
&& vector.output.did_document_metadata.canonical_id.is_none();

let vector_document_metadata = if all_none {
None
} else {
Some(vector.output.did_document_metadata.clone())
};

assert_eq!(
resolution_result.resolution_metadata, vector.output.did_resolution_metadata,
"Resolution metadata does not match."
);
assert_eq!(
resolution_result.document, vector.output.did_document,
"DID Document does not match."
);
assert_eq!(
resolution_result.document_metadata, vector_document_metadata,
"Document metadata does not match."
);
}
}
}
2 changes: 2 additions & 0 deletions crates/web5/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ pub mod rfc3339;

#[cfg(test)]
mod test_helpers;
#[cfg(test)]
mod test_vectors;
30 changes: 1 addition & 29 deletions crates/web5/src/test_helpers.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,4 @@
use serde::de::DeserializeOwned;
use std::{fs, path::PathBuf, sync::Mutex};

#[derive(Debug, serde::Deserialize)]
pub struct TestVector<I, O> {
pub description: String,
pub input: I,
pub output: O,
}

#[derive(Debug, serde::Deserialize)]
pub struct TestVectorFile<I, O> {
#[allow(dead_code)]
pub description: String,
pub vectors: Vec<TestVector<I, O>>,
}

impl<I, O> TestVectorFile<I, O> {
pub fn load_from_path(file_path: &str) -> TestVectorFile<I, O>
where
I: DeserializeOwned,
O: DeserializeOwned,
{
let mut vector_path = PathBuf::from("../../web5-spec/test-vectors/");
vector_path.push(file_path);
let data = fs::read_to_string(vector_path).unwrap();
serde_json::from_str(&data).unwrap()
}
}
use std::{fs, sync::Mutex};

#[macro_export]
macro_rules! test_name {
Expand Down
Loading
Loading