#[cfg(disabled_until_green_phase)]
mod cli_command_tests {
use std::process::Command;
use std::str;
use std::sync::Arc;
async fn run_cli_command(args: &[&str]) -> Result<String, Box<dyn std::error::Error>> {
let output = Command::new("cargo")
.args(&["run", "--bin", "qudag", "--"])
.args(args)
.output()?;
if output.status.success() {
Ok(String::from_utf8(output.stdout)?)
} else {
Err(format!(
"Command failed: {}",
String::from_utf8_lossy(&output.stderr)
)
.into())
}
}
#[tokio::test]
async fn test_cli_start_command() {
let scenario = TestScenarioBuilder::new()
.add_node("test-cli-node".to_string())
.build()
.await;
let node = scenario.nodes.get("test-cli-node").unwrap();
node.start().await.expect("Failed to start node");
let status = node.get_status().await;
assert_eq!(status.state, "Running");
println!("Node started successfully:");
println!(" ID: {}", status.node_id);
println!(" State: {}", status.state);
println!(" Uptime: {} seconds", status.uptime);
}
#[tokio::test]
async fn test_cli_peer_management() {
let scenario = TestScenarioBuilder::new()
.add_node("peer-test-node".to_string())
.build()
.await;
let node = scenario.nodes.get("peer-test-node").unwrap();
node.start().await.expect("Failed to start node");
node.add_peer("192.168.1.50:8080".to_string())
.await
.expect("Failed to add peer");
let status = node.get_status().await;
assert_eq!(status.peers.len(), 1);
assert_eq!(status.peers[0].address, "192.168.1.50:8080");
let peer_id = status.peers[0].id.clone();
node.remove_peer(&peer_id)
.await
.expect("Failed to remove peer");
let status = node.get_status().await;
assert_eq!(status.peers.len(), 0);
println!("Peer management test completed successfully");
}
#[tokio::test]
async fn test_cli_network_stats() {
let scenario = TestScenarioBuilder::new()
.add_node("stats-node".to_string())
.build()
.await;
let node = scenario.nodes.get("stats-node").unwrap();
node.start().await.expect("Failed to start node");
node.add_peer("10.0.0.1:8080".to_string())
.await
.expect("Failed to add peer");
node.add_peer("10.0.0.2:8080".to_string())
.await
.expect("Failed to add peer");
node.simulate_activity().await;
let status = node.get_status().await;
let stats = &status.network_stats;
println!("Network Statistics:");
println!("==================");
println!(" Total Connections: {}", stats.total_connections);
println!(" Active Connections: {}", stats.active_connections);
println!(" Messages Sent: {}", stats.messages_sent);
println!(" Messages Received: {}", stats.messages_received);
println!(" Bytes Sent: {}", stats.bytes_sent);
println!(" Bytes Received: {}", stats.bytes_received);
println!(" Average Latency: {:.2} ms", stats.average_latency);
assert!(stats.active_connections > 0);
assert!(stats.messages_sent > 0);
assert!(stats.average_latency > 0.0);
}
#[tokio::test]
async fn test_cli_network_test_command() {
let scenario = TestScenarioBuilder::new()
.add_node("network-test-node".to_string())
.build()
.await;
let node = scenario.nodes.get("network-test-node").unwrap();
let rpc = MockRpcClient::new(node.clone());
let request = qudag_cli::rpc::RpcRequest {
id: uuid::Uuid::new_v4(),
method: "test_network".to_string(),
params: serde_json::Value::Null,
};
let response = rpc.process_request(request).await;
assert!(response.result.is_some());
if let Some(result) = response.result {
let test_results: Vec<qudag_cli::rpc::NetworkTestResult> =
serde_json::from_value(result).unwrap();
println!("Network Test Results:");
println!("====================");
for result in &test_results {
println!(" Peer ID: {}", result.peer_id);
println!(" Address: {}", result.address);
if result.reachable {
println!(" Status: ✓ Reachable");
if let Some(latency) = result.latency {
println!(" Latency: {:.1} ms", latency);
}
} else {
println!(" Status: ✗ Unreachable");
if let Some(error) = &result.error {
println!(" Error: {}", error);
}
}
println!();
}
assert_eq!(test_results.len(), 3);
assert!(test_results.iter().any(|r| r.reachable));
assert!(test_results.iter().any(|r| !r.reachable));
}
}
#[tokio::test]
async fn test_cli_status_command() {
let scenario = TestScenarioBuilder::new()
.add_node("status-node".to_string())
.build()
.await;
let node = scenario.nodes.get("status-node").unwrap();
node.start().await.expect("Failed to start node");
node.add_peer("peer1.example.com:8080".to_string())
.await
.expect("Failed to add peer");
node.simulate_activity().await;
let status = node.get_status().await;
println!("Node Status:");
println!("============");
println!(" Node ID: {}", status.node_id);
println!(" State: {}", status.state);
println!(" Uptime: {} seconds", status.uptime);
println!(" Connected Peers: {}", status.peers.len());
println!();
if !status.peers.is_empty() {
println!("Peer Information:");
for peer in &status.peers {
println!(" - ID: {}", peer.id);
println!(" Address: {}", peer.address);
println!(" Connected: {} seconds", peer.connected_duration);
println!(" Messages Sent: {}", peer.messages_sent);
println!(" Messages Received: {}", peer.messages_received);
}
println!();
}
println!("DAG Statistics:");
println!(" Vertices: {}", status.dag_stats.vertex_count);
println!(" Edges: {}", status.dag_stats.edge_count);
println!(" Tips: {}", status.dag_stats.tip_count);
println!(" Finalized Height: {}", status.dag_stats.finalized_height);
println!(
" Pending Transactions: {}",
status.dag_stats.pending_transactions
);
println!();
println!("Memory Usage:");
println!(" Current: {} bytes", status.memory_usage.current_usage);
println!(" Peak: {} bytes", status.memory_usage.peak_usage);
println!(
" Total Allocated: {} bytes",
status.memory_usage.total_allocated
);
assert_eq!(status.state, "Running");
assert_eq!(status.peers.len(), 1);
}
#[tokio::test]
async fn test_cli_error_scenarios() {
let scenario = TestScenarioBuilder::new()
.add_node("error-test-node".to_string())
.with_global_behavior(
"problematic_operation".to_string(),
MockBehavior {
should_succeed: false,
latency_ms: 0,
error_message: "Service temporarily unavailable".to_string(),
custom_response: None,
},
)
.build()
.await;
let node = scenario.nodes.get("error-test-node").unwrap();
let rpc = MockRpcClient::new(node.clone());
let request = qudag_cli::rpc::RpcRequest {
id: uuid::Uuid::new_v4(),
method: "problematic_operation".to_string(),
params: serde_json::Value::Null,
};
let response = rpc.process_request(request).await;
assert!(response.result.is_none());
assert!(response.error.is_some());
if let Some(error) = response.error {
println!("Error response received:");
println!(" Code: {}", error.code);
println!(" Message: {}", error.message);
assert_eq!(error.message, "Service temporarily unavailable");
}
node.start().await.expect("Failed to start node");
let result = node.start().await;
assert!(result.is_err());
println!("Double start error: {}", result.unwrap_err());
}
#[tokio::test]
async fn test_cli_concurrent_operations() {
let scenario = TestScenarioBuilder::new()
.add_node("concurrent-node".to_string())
.build()
.await;
let node = scenario.nodes.get("concurrent-node").unwrap();
let rpc = Arc::new(MockRpcClient::new(node.clone()));
node.start().await.expect("Failed to start node");
let mut handles = Vec::new();
for i in 0..10 {
let rpc_clone = rpc.clone();
let handle = tokio::spawn(async move {
let request = qudag_cli::rpc::RpcRequest {
id: uuid::Uuid::new_v4(),
method: "get_status".to_string(),
params: serde_json::Value::Null,
};
let response = rpc_clone.process_request(request).await;
(i, response.result.is_some())
});
handles.push(handle);
}
let results = futures::future::join_all(handles).await;
for result in results {
let (i, success) = result.expect("Task panicked");
assert!(success, "Request {} failed", i);
}
let history = rpc.get_request_history();
assert_eq!(history.len(), 10);
println!(
"Successfully processed {} concurrent requests",
history.len()
);
}
#[tokio::test]
async fn test_cli_complex_scenario() {
let scenario = TestScenarioBuilder::new()
.add_node("gateway".to_string())
.add_node("worker-1".to_string())
.add_node("worker-2".to_string())
.add_node("monitor".to_string())
.with_topology(NetworkTopology::Star {
center: "gateway".to_string(),
})
.with_global_behavior(
"heartbeat".to_string(),
MockBehavior {
should_succeed: true,
latency_ms: 5,
error_message: String::new(),
custom_response: Some(serde_json::json!({
"timestamp": chrono::Utc::now().timestamp(),
"status": "healthy"
})),
},
)
.build()
.await;
scenario
.start_all_nodes()
.await
.expect("Failed to start nodes");
let activity_duration = std::time::Duration::from_millis(500);
scenario.simulate_activity(activity_duration).await;
let stats = scenario.get_aggregate_stats().await;
println!("Complex Scenario Results:");
println!("========================");
println!(" Nodes: {}", scenario.nodes.len());
println!(" Total Connections: {}", stats.total_connections);
println!(" Active Connections: {}", stats.active_connections);
println!(
" Messages Exchanged: {}",
stats.messages_sent + stats.messages_received
);
println!(
" Data Transferred: {} KB",
(stats.bytes_sent + stats.bytes_received) / 1024
);
println!(" Average Latency: {:.2} ms", stats.average_latency);
let gateway = scenario.nodes.get("gateway").unwrap();
let gateway_peers = gateway.peers.read().await.len();
assert_eq!(gateway_peers, 3, "Gateway should have 3 peer connections");
for worker in ["worker-1", "worker-2", "monitor"] {
let node = scenario.nodes.get(worker).unwrap();
let peer_count = node.peers.read().await.len();
assert_eq!(
peer_count, 1,
"{} should have 1 peer connection to gateway",
worker
);
}
for (node_id, node) in &scenario.nodes {
let rpc = MockRpcClient::new(node.clone());
let status_request = qudag_cli::rpc::RpcRequest {
id: uuid::Uuid::new_v4(),
method: "get_status".to_string(),
params: serde_json::Value::Null,
};
let response = rpc.process_request(status_request).await;
assert!(
response.result.is_some(),
"Status request failed for {}",
node_id
);
let heartbeat_request = qudag_cli::rpc::RpcRequest {
id: uuid::Uuid::new_v4(),
method: "heartbeat".to_string(),
params: serde_json::Value::Null,
};
let response = rpc.process_request(heartbeat_request).await;
assert!(
response.result.is_some(),
"Heartbeat failed for {}",
node_id
);
if let Some(result) = response.result {
assert_eq!(result["status"], "healthy");
}
}
scenario
.stop_all_nodes()
.await
.expect("Failed to stop nodes");
println!("Complex scenario completed successfully");
}
}