use did_common::did_doc::{
DidDocument, DidDocumentBuilder, PublicKeyBuilder, PublicKeyEncoded, PublicKeyType, Service,
ServiceEndpoint, VerificationMethod,
};
fn json_parse(input: &str) -> json::JsonValue {
did_common::json_parse(input).unwrap()
}
#[test]
fn parse_did_doc_with_missing_context() {
assert_eq!(
DidDocument::parse(&json_parse(
r#"
{
"id": "did:example:21tDAKCERh95uGgKbJNHYp"
}
"#
)),
Err("missing DID context")
);
}
#[test]
fn parse_did_doc_with_invalid_context() {
assert_eq!(
DidDocument::parse(&json_parse(
r#"
{
"@context": "https://w3id.org/security/v1",
"id": "did:example:21tDAKCERh95uGgKbJNHYp"
}
"#
)),
Err("invalid DID context")
);
}
#[test]
fn parse_did_doc_with_missing_subject() {
assert_eq!(
DidDocument::parse(&json_parse(
r#"
{
"@context": "https://www.w3.org/2019/did/v1"
}
"#
)),
Err("missing DID subject")
);
}
#[test]
fn parse_did_doc_with_invalid_subject() {
assert_eq!(
DidDocument::parse(&json_parse(
r#"
{
"@context": "https://www.w3.org/2019/did/v1",
"id": "foobar"
}
"#
)),
Err("invalid DID subject")
);
}
#[test]
fn parse_minimal_did_doc() {
assert_eq!(
DidDocument::parse(&json_parse(
r#"
{
"@context": "https://www.w3.org/2019/did/v1",
"id": "did:example:21tDAKCERh95uGgKbJNHYp"
}
"#
)),
Ok(DidDocumentBuilder::new("did:example:21tDAKCERh95uGgKbJNHYp").build())
);
}
#[test]
fn parse_did_doc_with_invalid_created() {
assert_eq!(
DidDocument::parse(&json_parse(
r#"
{
"@context": "https://www.w3.org/2019/did/v1",
"id": "did:example:21tDAKCERh95uGgKbJNHYp",
"created": "2002-10-32T17:00:00"
}
"#
)),
Err("invalid created timestamp")
);
}
#[test]
fn parse_did_doc_with_created() {
assert_eq!(
DidDocument::parse(&json_parse(
r#"
{
"@context": "https://www.w3.org/2019/did/v1",
"id": "did:example:21tDAKCERh95uGgKbJNHYp",
"created": "2002-10-10T17:00:00Z"
}
"#
)),
Ok(
DidDocumentBuilder::new("did:example:21tDAKCERh95uGgKbJNHYp")
.created_on("2002-10-10T17:00:00Z")
.build()
)
);
}
#[test]
fn parse_did_doc_with_invalid_updated() {
assert_eq!(
DidDocument::parse(&json_parse(
r#"
{
"@context": "https://www.w3.org/2019/did/v1",
"id": "did:example:21tDAKCERh95uGgKbJNHYp",
"updated": "2002-10-32T17:00:00"
}
"#
)),
Err("invalid updated timestamp")
);
}
#[test]
fn parse_did_doc_with_updated() {
assert_eq!(
DidDocument::parse(&json_parse(
r#"
{
"@context": "https://www.w3.org/2019/did/v1",
"id": "did:example:21tDAKCERh95uGgKbJNHYp",
"updated": "2002-10-10T17:00:00Z"
}
"#
)),
Ok(
DidDocumentBuilder::new("did:example:21tDAKCERh95uGgKbJNHYp")
.updated_on("2002-10-10T17:00:00Z")
.build()
)
);
}
#[test]
fn parse_did_doc_with_pub_keys() {
assert_eq!(
DidDocument::parse(&json_parse(
r#"
{
"@context": "https://www.w3.org/2019/did/v1",
"id": "did:example:123456789abcdefghi",
"publicKey": [
{
"id": "did:example:123456789abcdefghi#keys-1",
"type": "RsaVerificationKey2018",
"controller": "did:example:123456789abcdefghi",
"publicKeyPem": "-----BEGIN PUBLIC KEY...END PUBLIC KEY-----\r\n"
}, {
"id": "did:example:123456789abcdefghi#keys-2",
"type": "Ed25519VerificationKey2018",
"controller": "did:example:pqrstuvwxyz0987654321",
"publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
}, {
"id": "did:example:123456789abcdefghi#keys-3",
"type": "Secp256k1VerificationKey2018",
"controller": "did:example:123456789abcdefghi",
"publicKeyHex": "02b97c30de767f084ce3080168ee293053ba33b235d7116a3263d29f1450936b71"
}
]
}
"#
)),
Ok(
DidDocumentBuilder::new("did:example:123456789abcdefghi")
.with_pubkeys(vec![
PublicKeyBuilder::new(
"did:example:123456789abcdefghi#keys-1",
PublicKeyType::Rsa,
"did:example:123456789abcdefghi"
)
.with_encoded_key(PublicKeyEncoded::Pem(
"-----BEGIN PUBLIC KEY...END PUBLIC KEY-----\r\n"
))
.build(),
PublicKeyBuilder::new(
"did:example:123456789abcdefghi#keys-2",
PublicKeyType::Ed25519,
"did:example:pqrstuvwxyz0987654321"
)
.with_encoded_key(PublicKeyEncoded::Base58(
"H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
))
.build(),
PublicKeyBuilder::new(
"did:example:123456789abcdefghi#keys-3",
PublicKeyType::EcdsaSecp256k1,
"did:example:123456789abcdefghi"
)
.with_encoded_key(PublicKeyEncoded::Hex(
"02b97c30de767f084ce3080168ee293053ba33b235d7116a3263d29f1450936b71"
))
.build()
])
.build()
)
);
}
#[test]
fn parse_did_doc_with_auth_reference_verif_method() {
assert_eq!(
DidDocument::parse(&json_parse(
r#"
{
"@context": "https://www.w3.org/2019/did/v1",
"id": "did:example:123456789abcdefghi",
"authentication": [ "did:example:123456789abcdefghi#keys-1" ],
"publicKey": [
{
"id": "did:example:123456789abcdefghi#keys-1",
"type": "RsaVerificationKey2018",
"controller": "did:example:123456789abcdefghi",
"publicKeyPem": "-----BEGIN PUBLIC KEY...END PUBLIC KEY-----\r\n"
}
]
}
"#
)),
Ok(DidDocumentBuilder::new("did:example:123456789abcdefghi")
.with_authentication(vec![VerificationMethod::Reference(
"did:example:123456789abcdefghi#keys-1"
)])
.with_pubkeys(vec![PublicKeyBuilder::new(
"did:example:123456789abcdefghi#keys-1",
PublicKeyType::Rsa,
"did:example:123456789abcdefghi"
)
.with_encoded_key(PublicKeyEncoded::Pem(
"-----BEGIN PUBLIC KEY...END PUBLIC KEY-----\r\n"
))
.build()])
.build())
);
}
#[test]
fn parse_did_doc_with_unknown_auth_reference() {
assert_eq!(
DidDocument::parse(&json_parse(
r#"
{
"@context": "https://www.w3.org/2019/did/v1",
"id": "did:example:123456789abcdefghi",
"authentication": [ "did:example:123456789abcdefghi#keys-1" ]
}
"#
)),
Err("unknown reference verification method")
);
}
#[test]
fn parse_did_doc_with_auth_embedded_verif_method() {
assert_eq!(
DidDocument::parse(&json_parse(
r#"
{
"@context": "https://www.w3.org/2019/did/v1",
"id": "did:example:123456789abcdefghi",
"authentication": [
{
"id": "did:example:123456789abcdefghi#keys-2",
"type": "Ed25519VerificationKey2018",
"controller": "did:example:123456789abcdefghi",
"publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
}
]
}
"#
)),
Ok(DidDocumentBuilder::new("did:example:123456789abcdefghi")
.with_authentication(vec![VerificationMethod::Embedded(
PublicKeyBuilder::new(
"did:example:123456789abcdefghi#keys-2",
PublicKeyType::Ed25519,
"did:example:123456789abcdefghi"
)
.with_encoded_key(PublicKeyEncoded::Base58(
"H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
))
.build(),
)])
.build())
);
}
#[test]
fn parse_did_doc_with_duplicate_id_from_auth_embedded() {
assert_eq!(
DidDocument::parse(&json_parse(
r#"
{
"@context": "https://www.w3.org/2019/did/v1",
"id": "did:example:123456789abcdefghi",
"authentication": [
{
"id": "did:example:123456789abcdefghi#keys-2",
"type": "Ed25519VerificationKey2018",
"controller": "did:example:123456789abcdefghi",
"publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
}
],
"publicKey": [
{
"id": "did:example:123456789abcdefghi#keys-2",
"type": "Ed25519VerificationKey2018",
"controller": "did:example:pqrstuvwxyz0987654321",
"publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
}
]
}
"#
)),
Err("duplicate public key id from embedded verification method")
);
}
#[test]
fn parse_did_doc_with_service_uri_endpoints() {
assert_eq!(
DidDocument::parse(&json_parse(
r#"
{
"@context": "https://www.w3.org/2019/did/v1",
"id": "did:example:123456789abcdefghi",
"service": [{
"id": "did:example:123456789abcdefghi#openid",
"type": "OpenIdConnectVersion1.0Service",
"serviceEndpoint": "https://openid.example.com/"
}, {
"id": "did:example:123456789abcdefghi#vcr",
"type": "CredentialRepositoryService",
"serviceEndpoint": "https://repository.example.com/service/8377464"
}, {
"id": "did:example:123456789abcdefghi#xdi",
"type": "XdiService",
"serviceEndpoint": "https://xdi.example.com/8377464"
}, {
"id": "did:example:123456789abcdefghi#agent",
"type": "AgentService",
"serviceEndpoint": "https://agent.example.com/8377464"
}]
}
"#
)),
Ok(DidDocumentBuilder::new("did:example:123456789abcdefghi")
.with_services(vec![
Service::new(
"did:example:123456789abcdefghi#openid",
"OpenIdConnectVersion1.0Service",
ServiceEndpoint::Uri("https://openid.example.com/")
),
Service::new(
"did:example:123456789abcdefghi#vcr",
"CredentialRepositoryService",
ServiceEndpoint::Uri("https://repository.example.com/service/8377464")
),
Service::new(
"did:example:123456789abcdefghi#xdi",
"XdiService",
ServiceEndpoint::Uri("https://xdi.example.com/8377464")
),
Service::new(
"did:example:123456789abcdefghi#agent",
"AgentService",
ServiceEndpoint::Uri("https://agent.example.com/8377464")
),
])
.build())
);
}
#[test]
fn parse_did_doc_with_service_object_endpoint() {
assert_eq!(
DidDocument::parse(&json_parse(
r#"
{
"@context": "https://www.w3.org/2019/did/v1",
"id": "did:example:123456789abcdefghi",
"service": [
{
"id": "did:example:123456789abcdefghi#hub",
"type": "IdentityHub",
"publicKey": "did:example:123456789abcdefghi#key-1",
"serviceEndpoint": {
"@context": "https://schema.identity.foundation/hub",
"type": "UserHubEndpoint",
"instances": ["did:example:456", "did:example:789"]
}
}
]
}
"#
)),
Err("invalid service endpoint JSON-LD object : unimplemented")
);
}