#[cfg(test)] mod tests { use crate::parser::StarParser; use crate::ser::{StarEncoder, StarSerializer}; use crate::types::{ RepoMstEntry, RepoMstNode, StarCommit, StarItem, StarMstEntry, StarMstNode, }; use cid::Cid; use serde_bytes::ByteBuf; use sha2::{Digest, Sha256}; fn create_test_cid(data: &[u8]) -> Cid { let hash = Sha256::digest(data); Cid::new_v1(0x71, cid::multihash::Multihash::wrap(0x12, &hash).unwrap()) } #[test] fn test_roundtrip_basic() { // 1. Create a dummy record // Use "bar" (sha256 starts with fc... -> 0 leading zeros -> height 0) let record_data = b"hello world"; let record_cid = create_test_cid(record_data); let key = b"bar".to_vec(); // 2. Create a dummy MST Node (Layer 0, implicit record) let node_entry = StarMstEntry { p: 0, k: ByteBuf::from(key.clone()), v: None, v_archived: Some(true), t: None, t_archived: None, }; let star_node = StarMstNode { l: None, l_archived: None, e: vec![node_entry], }; // 3. Manually compute the expected Node CID for verification let repo_entry = RepoMstEntry { p: 0, k: ByteBuf::from(key.clone()), v: record_cid, t: None, }; let repo_node = RepoMstNode { l: None, e: vec![repo_entry], }; let repo_bytes = serde_ipld_dagcbor::to_vec(&repo_node).unwrap(); let node_cid = create_test_cid(&repo_bytes); // 4. Create Commit let commit = StarCommit { did: "did:example:test".into(), version: 3, data: Some(node_cid), rev: "rev1".into(), prev: None, sig: None, }; // 5. Serialize to Buffer let mut buf = Vec::new(); StarEncoder::write_header(&commit, &mut buf).unwrap(); StarEncoder::write_node(&star_node, &mut buf).unwrap(); StarEncoder::write_record(record_data, &mut buf).unwrap(); // 6. Deserialize and Verify let mut parser = StarParser::new(); // Helper to mimic Decoder loop for tests fn parse_helper( parser: &mut StarParser, buf: &mut Vec, offset: &mut usize, ) -> Option { let (consumed, item) = parser.parse(&buf[*offset..]).unwrap(); *offset += consumed; item } let mut offset = 0; // Header let item1 = parse_helper(&mut parser, &mut buf, &mut offset).unwrap(); match item1 { StarItem::Commit(c) => assert_eq!(c, commit), _ => panic!("Expected commit"), } // Node let item2 = parse_helper(&mut parser, &mut buf, &mut offset).unwrap(); match item2 { StarItem::Node(n) => { assert_eq!(n.e[0].v, None); assert_eq!(n.e[0].v_archived, Some(true)); } _ => panic!("Expected node"), } // Record let item3 = parse_helper(&mut parser, &mut buf, &mut offset).unwrap(); match item3 { StarItem::Record { key: k, cid, content, } => { assert_eq!(k, key); assert_eq!(cid, record_cid); assert_eq!(content.unwrap(), record_data); } _ => panic!("Expected record"), } // Done assert!(parse_helper(&mut parser, &mut buf, &mut offset).is_none()); } #[test] fn test_verification_failure() { // 1. Create a dummy record let record_data = b"hello world"; let key = b"bar".to_vec(); // Height 0 // 2. Create STAR Node let node_entry = StarMstEntry { p: 0, k: ByteBuf::from(key.clone()), v: None, v_archived: Some(true), t: None, t_archived: None, }; let star_node = StarMstNode { l: None, l_archived: None, e: vec![node_entry], }; // 3. Create Commit with WRONG CID let wrong_cid = create_test_cid(b"garbage"); let commit = StarCommit { did: "did:example:test".into(), version: 3, data: Some(wrong_cid), rev: "rev1".into(), prev: None, sig: None, }; // 4. Serialize let mut buf = Vec::new(); StarEncoder::write_header(&commit, &mut buf).unwrap(); StarEncoder::write_node(&star_node, &mut buf).unwrap(); StarEncoder::write_record(record_data, &mut buf).unwrap(); // 5. Parse let mut parser = StarParser::new(); let mut offset = 0; fn parse_helper( parser: &mut StarParser, buf: &mut Vec, offset: &mut usize, ) -> Result, crate::error::StarError> { let (consumed, item) = parser.parse(&buf[*offset..])?; *offset += consumed; Ok(item) } parse_helper(&mut parser, &mut buf, &mut offset).unwrap(); // Header OK parse_helper(&mut parser, &mut buf, &mut offset).unwrap(); // Node OK parse_helper(&mut parser, &mut buf, &mut offset).unwrap(); // Record OK // 6. Trigger verification let result = parse_helper(&mut parser, &mut buf, &mut offset); assert!(result.is_err()); match result.unwrap_err() { crate::error::StarError::VerificationFailed { .. } => {} e => panic!("Expected VerificationFailed, got {:?}", e), } } #[test] fn test_strict_serializer() { // Test that strict serializer enforces constraints let mut buf = Vec::new(); let mut serializer = StarSerializer::new(&mut buf); // 1. Create invalid node (root empty) let invalid_node = StarMstNode { l: None, l_archived: None, e: vec![], }; // 2. Commit pointing to root let cid = create_test_cid(b"foo"); let commit = StarCommit { did: "did".into(), version: 3, data: Some(cid), rev: "1".into(), prev: None, sig: None, }; // Header OK serializer.write_header(&commit).unwrap(); // Node Fail let err = serializer.write_node(&invalid_node).unwrap_err(); match err { crate::error::StarError::InvalidStructure(msg) => { assert!(msg.contains("Root cannot be empty"), "Got message: {}", msg); } e => panic!("Expected InvalidStructure, got {:?}", e), } } }