2025-09-08 19:28:44 +00:00
|
|
|
|
use wasm_bindgen::prelude::*;
|
2025-09-09 09:42:12 +00:00
|
|
|
|
use wasm_bindgen_futures::spawn_local;
|
|
|
|
|
|
use socktop_connector::{ConnectorConfig, AgentRequest, SocktopConnector};
|
2025-09-08 19:28:44 +00:00
|
|
|
|
|
2025-09-09 09:42:12 +00:00
|
|
|
|
// Import the `console.log` function from the Web API
|
2025-09-08 19:28:44 +00:00
|
|
|
|
#[wasm_bindgen]
|
|
|
|
|
|
extern "C" {
|
|
|
|
|
|
#[wasm_bindgen(js_namespace = console)]
|
|
|
|
|
|
fn log(s: &str);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Define a macro for easier console logging
|
|
|
|
|
|
macro_rules! console_log {
|
|
|
|
|
|
($($t:tt)*) => (log(&format_args!($($t)*).to_string()))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// This is the main entry point called from JavaScript
|
|
|
|
|
|
#[wasm_bindgen]
|
2025-09-09 20:43:45 +00:00
|
|
|
|
pub fn test_socktop_connector(server_url: Option<String>) {
|
2025-09-08 19:28:44 +00:00
|
|
|
|
console_error_panic_hook::set_once();
|
|
|
|
|
|
|
2025-09-09 20:43:45 +00:00
|
|
|
|
// Use provided URL or default
|
|
|
|
|
|
let url = server_url.unwrap_or_else(|| "ws://localhost:3000/ws".to_string());
|
|
|
|
|
|
|
2025-09-09 09:42:12 +00:00
|
|
|
|
console_log!("🦀 Starting WASM connector test...");
|
2025-09-09 20:43:45 +00:00
|
|
|
|
console_log!("🌐 Connecting to: {}", url);
|
2025-09-08 19:28:44 +00:00
|
|
|
|
|
2025-09-09 09:42:12 +00:00
|
|
|
|
// Test 1: Create configuration
|
2025-09-09 20:43:45 +00:00
|
|
|
|
let config = ConnectorConfig::new(&url);
|
2025-09-09 09:42:12 +00:00
|
|
|
|
console_log!("✅ Config created: {}", config.url);
|
2025-09-08 19:28:44 +00:00
|
|
|
|
|
|
|
|
|
|
// Test 2: Test configuration methods
|
|
|
|
|
|
let config_with_protocols = config
|
|
|
|
|
|
.clone()
|
|
|
|
|
|
.with_protocols(vec!["socktop".to_string(), "v1".to_string()]);
|
|
|
|
|
|
console_log!("✅ Config with protocols: {:?}", config_with_protocols.ws_protocols);
|
|
|
|
|
|
|
2025-09-09 09:42:12 +00:00
|
|
|
|
let config_with_version = config_with_protocols.with_version("13".to_string());
|
2025-09-08 19:28:44 +00:00
|
|
|
|
console_log!("✅ Config with version: {:?}", config_with_version.ws_version);
|
2025-09-09 09:42:12 +00:00
|
|
|
|
|
2025-09-08 19:28:44 +00:00
|
|
|
|
// Test 3: Create request types
|
2025-09-09 09:42:12 +00:00
|
|
|
|
let _metrics_request = AgentRequest::Metrics;
|
|
|
|
|
|
let _disks_request = AgentRequest::Disks;
|
|
|
|
|
|
let _processes_request = AgentRequest::Processes;
|
|
|
|
|
|
console_log!("✅ AgentRequest types created");
|
2025-09-08 19:28:44 +00:00
|
|
|
|
|
2025-09-09 09:42:12 +00:00
|
|
|
|
// Test 4: Test serialization
|
|
|
|
|
|
if let Ok(json) = serde_json::to_string(&AgentRequest::Metrics) {
|
|
|
|
|
|
console_log!("✅ Serialization works: {}", json);
|
2025-09-08 19:28:44 +00:00
|
|
|
|
}
|
2025-09-09 09:42:12 +00:00
|
|
|
|
|
|
|
|
|
|
// Test 5: WebSocket connection test
|
|
|
|
|
|
console_log!("🌐 Testing WebSocket connection...");
|
|
|
|
|
|
|
|
|
|
|
|
spawn_local(async move {
|
|
|
|
|
|
test_websocket_connection(config_with_version).await;
|
|
|
|
|
|
|
|
|
|
|
|
console_log!("");
|
|
|
|
|
|
console_log!("🎉 socktop_connector WASM Test Results:");
|
|
|
|
|
|
console_log!("✅ ConnectorConfig API works in WASM");
|
|
|
|
|
|
console_log!("✅ AgentRequest types work in WASM");
|
|
|
|
|
|
console_log!("✅ SocktopConnector compiles for WASM");
|
|
|
|
|
|
console_log!("✅ Connection stays alive with regular requests");
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async fn test_websocket_connection(config: ConnectorConfig) {
|
|
|
|
|
|
console_log!("📡 Connecting to agent...");
|
2025-09-08 19:28:44 +00:00
|
|
|
|
|
2025-09-09 09:42:12 +00:00
|
|
|
|
let mut connector = SocktopConnector::new(config);
|
2025-09-08 19:28:44 +00:00
|
|
|
|
|
2025-09-09 09:42:12 +00:00
|
|
|
|
match connector.connect().await {
|
|
|
|
|
|
Ok(()) => {
|
|
|
|
|
|
console_log!("✅ Connected!");
|
2025-09-08 19:28:44 +00:00
|
|
|
|
|
2025-09-09 09:42:12 +00:00
|
|
|
|
// Test continuous monitoring (5 rounds)
|
|
|
|
|
|
for round in 1..=5 {
|
|
|
|
|
|
console_log!("🔄 Round {}/5 - Requesting metrics...", round);
|
|
|
|
|
|
|
|
|
|
|
|
// Request metrics (mimicking TUI behavior)
|
|
|
|
|
|
match connector.request(AgentRequest::Metrics).await {
|
|
|
|
|
|
Ok(response) => {
|
|
|
|
|
|
match &response {
|
|
|
|
|
|
socktop_connector::AgentResponse::Metrics(metrics) => {
|
|
|
|
|
|
console_log!("✅ Round {} - CPU: {:.1}%, Mem: {:.1}%, Host: {}",
|
|
|
|
|
|
round,
|
|
|
|
|
|
metrics.cpu_total,
|
|
|
|
|
|
(metrics.mem_used as f64 / metrics.mem_total as f64) * 100.0,
|
|
|
|
|
|
metrics.hostname
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
// Show JSON summary for each round (clean, collapsible)
|
|
|
|
|
|
if let Ok(json_str) = serde_json::to_string_pretty(&response) {
|
|
|
|
|
|
console_log!("📊 Round {} JSON ({} chars):", round, json_str.len());
|
|
|
|
|
|
console_log!("{}", json_str);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
_ => console_log!("📊 Round {} - Received non-metrics response", round),
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
Err(e) => {
|
|
|
|
|
|
console_log!("❌ Round {} failed: {}", round, e);
|
|
|
|
|
|
console_log!("🔍 Error details: {:?}", e);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Every other round, also test disks and processes
|
|
|
|
|
|
if round % 2 == 0 {
|
|
|
|
|
|
console_log!("💾 Round {} - Requesting disk info...", round);
|
|
|
|
|
|
match connector.request(AgentRequest::Disks).await {
|
|
|
|
|
|
Ok(response) => {
|
|
|
|
|
|
match &response {
|
|
|
|
|
|
socktop_connector::AgentResponse::Disks(disks) => {
|
|
|
|
|
|
console_log!("✅ Round {} - Got {} disks", round, disks.len());
|
|
|
|
|
|
for disk in disks.iter().take(3) { // Show first 3 disks
|
|
|
|
|
|
let used_gb = (disk.total - disk.available) / 1024 / 1024 / 1024;
|
|
|
|
|
|
let total_gb = disk.total / 1024 / 1024 / 1024;
|
|
|
|
|
|
console_log!(" 💿 {}: {}/{} GB used", disk.name, used_gb, total_gb);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
_ => console_log!("❌ Round {} - Unexpected disk response type", round),
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
Err(e) => console_log!("❌ Round {} - Disk request failed: {}", round, e),
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
console_log!("⚙️ Round {} - Requesting process info...", round);
|
|
|
|
|
|
match connector.request(AgentRequest::Processes).await {
|
|
|
|
|
|
Ok(response) => {
|
|
|
|
|
|
match &response {
|
|
|
|
|
|
socktop_connector::AgentResponse::Processes(processes) => {
|
|
|
|
|
|
console_log!("✅ Round {} - Process count: {}, Top processes: {}",
|
|
|
|
|
|
round,
|
|
|
|
|
|
processes.process_count,
|
|
|
|
|
|
processes.top_processes.len()
|
|
|
|
|
|
);
|
|
|
|
|
|
if processes.top_processes.is_empty() {
|
|
|
|
|
|
console_log!("ℹ️ No top processes in response (process_count: {})", processes.process_count);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
for process in processes.top_processes.iter().take(3) { // Show top 3 processes
|
|
|
|
|
|
console_log!(" ⚙️ {}: {:.1}% CPU, {} MB",
|
|
|
|
|
|
process.name,
|
|
|
|
|
|
process.cpu_usage,
|
|
|
|
|
|
process.mem_bytes / 1024 / 1024
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
_ => console_log!("❌ Round {} - Unexpected process response type", round),
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
Err(e) => console_log!("❌ Round {} - Process request failed: {}", round, e),
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Wait 1 second between rounds
|
|
|
|
|
|
if round < 5 {
|
|
|
|
|
|
console_log!("⏱️ Waiting 1 second...");
|
|
|
|
|
|
let promise = js_sys::Promise::new(&mut |resolve, _| {
|
|
|
|
|
|
let closure = wasm_bindgen::closure::Closure::once(move || resolve.call0(&wasm_bindgen::JsValue::UNDEFINED));
|
|
|
|
|
|
web_sys::window()
|
|
|
|
|
|
.unwrap()
|
|
|
|
|
|
.set_timeout_with_callback_and_timeout_and_arguments_0(
|
|
|
|
|
|
closure.as_ref().unchecked_ref(),
|
|
|
|
|
|
1000, // 1 second delay
|
|
|
|
|
|
)
|
|
|
|
|
|
.unwrap();
|
|
|
|
|
|
closure.forget();
|
|
|
|
|
|
});
|
|
|
|
|
|
let _ = wasm_bindgen_futures::JsFuture::from(promise).await;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
console_log!("");
|
|
|
|
|
|
console_log!("🎉 Test completed successfully!");
|
|
|
|
|
|
|
|
|
|
|
|
// Clean disconnect
|
|
|
|
|
|
match connector.disconnect().await {
|
|
|
|
|
|
Ok(()) => console_log!("✅ Disconnected"),
|
|
|
|
|
|
Err(e) => console_log!("⚠️ Disconnect error: {}", e),
|
2025-09-08 19:28:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-09-09 09:42:12 +00:00
|
|
|
|
Err(e) => {
|
|
|
|
|
|
console_log!("❌ Connection failed: {}", e);
|
|
|
|
|
|
console_log!("💡 Make sure socktop_agent is running on localhost:3000");
|
|
|
|
|
|
}
|
2025-09-08 19:28:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|