Files
mcp-memory/stub/tests/e2e.rs
T

129 lines
4.1 KiB
Rust

use serde_json::{json, Value};
use std::io::{BufRead, BufReader, Read, Write};
use std::process::{Command, Stdio};
use std::time::Duration;
use std::sync::Arc;
use tokio::sync::Mutex;
fn send_message(stdin: &mut std::process::ChildStdin, msg: Value) {
let s = serde_json::to_string(&msg).unwrap();
let payload = format!("Content-Length: {}\r\n\r\n{}", s.len(), s);
stdin.write_all(payload.as_bytes()).unwrap();
stdin.flush().unwrap();
}
fn read_message(stdout: &mut std::process::ChildStdout) -> Option<Value> {
let mut reader = BufReader::new(stdout);
let mut length = 0;
loop {
let mut line = String::new();
if reader.read_line(&mut line).unwrap_or(0) == 0 {
return None;
}
let line = line.trim_end();
if line.is_empty() {
break;
}
if let Some(len_str) = line.strip_prefix("Content-Length: ") {
length = len_str.parse().unwrap_or(0);
}
}
if length == 0 {
return None;
}
let mut buf = vec![0u8; length];
reader.read_exact(&mut buf).unwrap();
let body_str = String::from_utf8_lossy(&buf);
Some(serde_json::from_str(&body_str).unwrap())
}
#[tokio::test]
async fn test_full_system_e2e_performance() {
let temp_dir = std::env::temp_dir().join(format!("mcp_e2e_{}", std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs()));
std::fs::create_dir_all(&temp_dir).unwrap();
let test_port = "3031"; // Use a distinct port
let server_exe = env!("CARGO_BIN_EXE_mcp-memory-server");
let nvim_exe = env!("CARGO_BIN_EXE_mcp-memory-win-nvim");
// 1. Start Server
let mut server = Command::new(server_exe)
.env("MCP_PORT", test_port)
.env("MCP_MEMORY_STORE_DIR", temp_dir.to_str().unwrap())
.stdout(Stdio::null())
.stderr(Stdio::null())
.spawn()
.expect("Failed to start server");
tokio::time::sleep(Duration::from_secs(2)).await;
// 2. Start Stub
let stub_exe = env!("CARGO_BIN_EXE_mcp-memory-stub");
let mut stub = Command::new(stub_exe)
.arg("--target")
.arg(format!("http://127.0.0.1:{}", test_port))
.env("MCP_MEMORY_STORE_DIR", temp_dir.to_str().unwrap())
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::null())
.spawn()
.expect("Failed to start stub");
let mut stub_stdin = stub.stdin.take().unwrap();
let mut stub_stdout = stub.stdout.take().unwrap();
// 3. Start Win-Nvim
let mut win_nvim = Command::new(&nvim_exe)
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::null())
.spawn()
.expect("Failed to start win-nvim");
let mut nvim_stdin = win_nvim.stdin.take().unwrap();
let mut nvim_stdout = win_nvim.stdout.take().unwrap();
// Send 100 concurrent-like sequential rapid requests to Stub
let start_time = std::time::Instant::now();
for i in 1..=100 {
let tools_req = json!({
"jsonrpc": "2.0",
"method": "tools/list",
"params": {},
"id": i
});
send_message(&mut stub_stdin, tools_req);
let resp = read_message(&mut stub_stdout).expect("Failed to read rapid response from stub");
assert_eq!(resp["id"], i);
}
let stub_duration = start_time.elapsed();
// Send 100 concurrent-like sequential rapid requests to Win-Nvim
let start_time_nvim = std::time::Instant::now();
for i in 1..=100 {
let tools_req = json!({
"jsonrpc": "2.0",
"method": "tools/list",
"params": {},
"id": i
});
send_message(&mut nvim_stdin, tools_req);
let resp = read_message(&mut nvim_stdout).expect("Failed to read rapid response from win-nvim");
assert_eq!(resp["id"], i);
}
let nvim_duration = start_time_nvim.elapsed();
println!("Stub 100 requests: {:?}", stub_duration);
println!("Win-Nvim 100 requests: {:?}", nvim_duration);
// Cleanup
let _ = stub.kill();
let _ = win_nvim.kill();
let _ = server.kill();
}