90 lines
2.5 KiB
Rust
90 lines
2.5 KiB
Rust
use std::io::{Cursor, Result as IoResult, Write};
|
|
use std::sync::{Arc, Mutex};
|
|
use std::time::Duration;
|
|
|
|
use sgclaw::pipe::{
|
|
perform_handshake, Action, AgentMessage, BrowserPipeTool, StdioTransport, Timing,
|
|
};
|
|
use sgclaw::security::MacPolicy;
|
|
|
|
#[derive(Clone, Default)]
|
|
struct SharedBuffer {
|
|
inner: Arc<Mutex<Vec<u8>>>,
|
|
}
|
|
|
|
impl SharedBuffer {
|
|
fn snapshot(&self) -> String {
|
|
String::from_utf8(self.inner.lock().unwrap().clone()).unwrap()
|
|
}
|
|
}
|
|
|
|
impl Write for SharedBuffer {
|
|
fn write(&mut self, buf: &[u8]) -> IoResult<usize> {
|
|
self.inner.lock().unwrap().extend_from_slice(buf);
|
|
Ok(buf.len())
|
|
}
|
|
|
|
fn flush(&mut self) -> IoResult<()> {
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn handshake_and_command_flow_work_over_json_line_transport() {
|
|
let reader = Cursor::new(
|
|
concat!(
|
|
r#"{"type":"init","version":"1.0","hmac_seed":"0123456789abcdef","capabilities":["browser_action"]}"#,
|
|
"\n",
|
|
r#"{"type":"response","seq":1,"success":true,"data":{"text":"提交成功"},"aom_snapshot":[],"timing":{"queue_ms":2,"exec_ms":38}}"#,
|
|
"\n"
|
|
)
|
|
.as_bytes()
|
|
.to_vec(),
|
|
);
|
|
let writer = SharedBuffer::default();
|
|
let captured = writer.clone();
|
|
let transport = Arc::new(StdioTransport::new(reader, writer));
|
|
|
|
let handshake = perform_handshake(transport.as_ref(), Duration::from_secs(1)).unwrap();
|
|
let policy = MacPolicy::from_json_str(
|
|
r#"{
|
|
"version": "1.0",
|
|
"domains": { "allowed": ["oa.example.com"] },
|
|
"pipe_actions": {
|
|
"allowed": ["click", "type", "navigate", "getText"],
|
|
"blocked": []
|
|
}
|
|
}"#,
|
|
)
|
|
.unwrap();
|
|
let tool = BrowserPipeTool::new(transport, policy, handshake.session_key)
|
|
.with_response_timeout(Duration::from_secs(1));
|
|
|
|
let result = tool
|
|
.invoke(
|
|
Action::Click,
|
|
serde_json::json!({ "selector": "#submit" }),
|
|
"oa.example.com",
|
|
)
|
|
.unwrap();
|
|
let written = captured.snapshot();
|
|
|
|
assert_eq!(
|
|
result.timing,
|
|
Timing {
|
|
queue_ms: 2,
|
|
exec_ms: 38
|
|
}
|
|
);
|
|
assert!(written.contains(r#""type":"init_ack""#));
|
|
assert!(written.contains(r#""type":"command""#));
|
|
assert!(written.contains(r#""action":"click""#));
|
|
|
|
let lines: Vec<&str> = written.lines().collect();
|
|
let command: AgentMessage = serde_json::from_str(lines[1]).unwrap();
|
|
assert!(matches!(
|
|
command,
|
|
AgentMessage::Command { seq, .. } if seq == 1
|
|
));
|
|
}
|