Rust and WASM did-method-plc tools and structures
1//! Tests for DID document parsing and conversion 2 3use atproto_plc::{Did, DidDocument, PlcState, ServiceEndpoint}; 4use std::collections::HashMap; 5 6#[test] 7fn test_plc_state_validation() { 8 let mut state = PlcState::new(); 9 10 // Empty state should fail (no rotation keys) 11 assert!(state.validate().is_err()); 12 13 // Add rotation key 14 state 15 .rotation_keys 16 .push("did:key:zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6N".to_string()); 17 assert!(state.validate().is_ok()); 18 19 // Add duplicate rotation key 20 state 21 .rotation_keys 22 .push("did:key:zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6N".to_string()); 23 assert!(state.validate().is_err()); 24} 25 26#[test] 27fn test_plc_state_too_many_rotation_keys() { 28 let mut state = PlcState::new(); 29 30 // Add 6 rotation keys (max is 5) 31 for i in 0..6 { 32 state 33 .rotation_keys 34 .push(format!("did:key:zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6{}", i)); 35 } 36 37 assert!(state.validate().is_err()); 38} 39 40#[test] 41fn test_plc_state_too_many_verification_methods() { 42 let mut state = PlcState::new(); 43 state 44 .rotation_keys 45 .push("did:key:zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6N".to_string()); 46 47 // Add 11 verification methods (max is 10) 48 for i in 0..11 { 49 state.verification_methods.insert( 50 format!("key{}", i), 51 format!("did:key:zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn{}", i), 52 ); 53 } 54 55 assert!(state.validate().is_err()); 56} 57 58#[test] 59fn test_service_endpoint_validation() { 60 let valid = ServiceEndpoint::new( 61 "AtprotoPersonalDataServer".to_string(), 62 "https://pds.example.com".to_string(), 63 ); 64 assert!(valid.validate().is_ok()); 65 66 let empty_type = ServiceEndpoint::new(String::new(), "https://example.com".to_string()); 67 assert!(empty_type.validate().is_err()); 68 69 let empty_endpoint = ServiceEndpoint::new("SomeService".to_string(), String::new()); 70 assert!(empty_endpoint.validate().is_err()); 71} 72 73#[test] 74fn test_did_document_from_plc_state() { 75 let did = Did::parse("did:plc:ewvi7nxzyoun6zhxrhs64oiz").unwrap(); 76 let mut state = PlcState::new(); 77 78 state 79 .rotation_keys 80 .push("did:key:zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6N".to_string()); 81 82 state.verification_methods.insert( 83 "atproto".to_string(), 84 "did:key:zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169".to_string(), 85 ); 86 87 state 88 .also_known_as 89 .push("at://alice.bsky.social".to_string()); 90 91 state.services.insert( 92 "atproto_pds".to_string(), 93 ServiceEndpoint::new( 94 "AtprotoPersonalDataServer".to_string(), 95 "https://pds.example.com".to_string(), 96 ), 97 ); 98 99 let doc = state.to_did_document(&did); 100 101 assert_eq!(doc.id, did); 102 assert_eq!(doc.verification_method.len(), 1); 103 assert_eq!(doc.also_known_as.len(), 1); 104 assert_eq!(doc.service.len(), 1); 105 assert!(!doc.context.is_empty()); 106} 107 108#[test] 109fn test_did_document_serialization() { 110 let did = Did::parse("did:plc:ewvi7nxzyoun6zhxrhs64oiz").unwrap(); 111 let mut state = PlcState::new(); 112 state 113 .rotation_keys 114 .push("did:key:zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6N".to_string()); 115 116 let doc = state.to_did_document(&did); 117 118 // Serialize to JSON 119 let json = serde_json::to_string_pretty(&doc).unwrap(); 120 assert!(json.contains("\"@context\"")); 121 assert!(json.contains("did:plc:ewvi7nxzyoun6zhxrhs64oiz")); 122 123 // Deserialize back 124 let deserialized: DidDocument = serde_json::from_str(&json).unwrap(); 125 assert_eq!(doc, deserialized); 126} 127 128#[test] 129fn test_plc_state_serialization() { 130 let mut state = PlcState::new(); 131 state 132 .rotation_keys 133 .push("did:key:zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6N".to_string()); 134 135 // Serialize 136 let json = serde_json::to_string(&state).unwrap(); 137 assert!(json.contains("rotationKeys")); 138 139 // Deserialize 140 let deserialized: PlcState = serde_json::from_str(&json).unwrap(); 141 assert_eq!(state, deserialized); 142} 143 144#[test] 145fn test_did_document_to_plc_state_conversion() { 146 let did = Did::parse("did:plc:ewvi7nxzyoun6zhxrhs64oiz").unwrap(); 147 let mut original_state = PlcState::new(); 148 original_state 149 .rotation_keys 150 .push("did:key:zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6N".to_string()); 151 original_state.verification_methods.insert( 152 "atproto".to_string(), 153 "did:key:zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169".to_string(), 154 ); 155 156 // Convert to DID document and back 157 let doc = original_state.to_did_document(&did); 158 let converted_state = doc.to_plc_state().unwrap(); 159 160 // Note: rotation_keys are not stored in DID document, so they won't round-trip 161 assert_eq!( 162 original_state.verification_methods, 163 converted_state.verification_methods 164 ); 165}