//! The eight memory messages against byte-exact fixtures, each refusing an unknown key (M5a spec, //! section 7). Do not edit these or the fixtures. use proto::{ CallId, DataClass, Empty, Envelope, MemoryAdmin, MemoryAdminReply, MemoryBlockReply, MemoryCall, MemoryCommand, Message, Reindexed, SessionId, SessionUpdated, ToolRequest, }; const SESSION: &str = "mm-r0000000000000000000000001"; fn fixture(name: &str) -> String { let path = format!("{}/tests/fixtures/wire/{name}", env!("CARGO_MANIFEST_DIR")); let text = std::fs::read_to_string(&path).unwrap_or_else(|e| panic!("{path}: {e}")); text.trim_end_matches('\n').to_string() } /// The fixture must decode to `msg`, `msg` must encode to exactly the fixture's bytes, and the /// body must refuse an extra key. fn check(name: &str, id: u64, msg: Message) { let want = Envelope { v: 1, id, r#final: true, msg, }; let text = fixture(name); let got: Envelope = serde_json::from_str(&text).unwrap_or_else(|e| panic!("{name}: {e}")); assert_eq!(got, want, "{name}: decoded value"); assert_eq!( serde_json::to_string(&want).unwrap(), text, "{name}: encoded bytes" ); let extra = text.replacen("\"body\":{", "\"body\":{\"extra\":1,", 1); assert!( serde_json::from_str::(&extra).is_err(), "{name}: an unknown key is refused" ); } #[test] fn the_eight_messages() { check("memory_block.json", 1, Message::MemoryBlock(Empty {})); check( "memory_block_reply.json", 1, Message::MemoryBlockReply(MemoryBlockReply { text: "# soul.md\nYou are Boxmaker.\n\n# memory.md (0 of 2,200 characters)\n(empty)\n\n# user.md (0 of 1,375 characters)\n(empty)".to_string(), }), ); check( "session_updated.json", 1, Message::SessionUpdated(SessionUpdated { session: SessionId::new(SESSION).unwrap(), }), ); check( "memory_call.json", 3, Message::MemoryCall(MemoryCall { request: ToolRequest { session: SessionId::new(SESSION).unwrap(), call: CallId(3), tool: "memory".to_string(), arguments: r#"{"action":"note","text":"example.org says March."}"#.to_string(), }, taint: DataClass::Private, untrusted: true, }), ); check("reindex.json", 1, Message::Reindex(Empty {})); check( "reindexed.json", 1, Message::Reindexed(Reindexed { logs: 42, records: 1208, notes: 7, }), ); check( "memory_admin.json", 1, Message::MemoryAdmin(MemoryAdmin { command: MemoryCommand::Undo, arg: "2026-09-24-0007".to_string(), }), ); check( "memory_admin_reply.json", 1, Message::MemoryAdminReply(MemoryAdminReply { text: "undone: 2026-09-24-0007".to_string(), }), ); } #[test] fn every_command_has_its_name() { for (command, name) in [ (MemoryCommand::Log, "log"), (MemoryCommand::Undo, "undo"), (MemoryCommand::Pending, "pending"), (MemoryCommand::Accept, "accept"), (MemoryCommand::Reject, "reject"), ] { assert_eq!( serde_json::to_string(&command).unwrap(), format!("\"{name}\"") ); } }