use hmac::{Hmac, Mac}; use serde_json::json; use sgclaw::pipe::{Action, AgentMessage, BrowserMessage}; use sgclaw::security::sign_command; use sha2::Sha256; type HmacSha256 = Hmac; #[test] fn browser_submit_task_round_trip_uses_task_wire_format() { let raw = r#"{"type":"submit_task","instruction":"打开百度并搜索今日汇率"}"#; let message: BrowserMessage = serde_json::from_str(raw).unwrap(); assert_eq!( message, BrowserMessage::SubmitTask { instruction: "打开百度并搜索今日汇率".to_string(), } ); assert_eq!(serde_json::to_string(&message).unwrap(), raw); } #[test] fn agent_task_complete_and_log_entry_serialize_with_expected_tags() { let complete_raw = serde_json::to_string(&AgentMessage::TaskComplete { success: true, summary: "任务执行完成".to_string(), }) .unwrap(); let log_raw = serde_json::to_string(&AgentMessage::LogEntry { level: "info".to_string(), message: "click #submit".to_string(), }) .unwrap(); assert_eq!( complete_raw, r#"{"type":"task_complete","success":true,"summary":"任务执行完成"}"# ); assert_eq!( log_raw, r#"{"type":"log_entry","level":"info","message":"click #submit"}"# ); } #[test] fn sign_command_uses_newline_canonical_string_with_stable_json() { let session_key = vec![1, 2, 3, 4, 5, 6, 7, 8]; let params = json!({ "z": 9, "a": { "b": 2, "a": 1 } }); let canonical = r#"42 click {"a":{"a":1,"b":2},"z":9} oa.example.com"#; let mut mac = HmacSha256::new_from_slice(&session_key).unwrap(); mac.update(canonical.as_bytes()); let expected = hex::encode(mac.finalize().into_bytes()); let actual = sign_command(&session_key, 42, &Action::Click, ¶ms, "oa.example.com").unwrap(); assert_eq!(actual, expected); } #[test] fn sign_command_is_order_independent_for_object_params() { let session_key = vec![8, 7, 6, 5, 4, 3, 2, 1]; let params_a = json!({ "z": 9, "a": { "b": 2, "a": 1 } }); let params_b = json!({ "a": { "a": 1, "b": 2 }, "z": 9 }); let sig_a = sign_command( &session_key, 7, &Action::Navigate, ¶ms_a, "oa.example.com", ) .unwrap(); let sig_b = sign_command( &session_key, 7, &Action::Navigate, ¶ms_b, "oa.example.com", ) .unwrap(); assert_eq!(sig_a, sig_b); }