speed-cli 1.0.0

Comprehensive multi-protocol network performance testing CLI (TCP, UDP, QUIC, HTTP/1.1, HTTP/2, h2c, HTTP/3)
//! End-to-end smoke test for the raw-QUIC server + client path.
//!
//! Binds a raw-QUIC endpoint on an ephemeral port, runs a short
//! download + upload, and asserts non-zero throughput.

use std::time::Duration;

use eyre::Result;
use speed_cli::TestType;
use speed_cli::performance::quic::client::run_quic_client;
use speed_cli::performance::quic::server::{QuicServerConfig, bind_quic, run_quic_server};
use speed_cli::report::{NetworkProtocol, QuicTestConfig, TestResult};
use speed_cli::utils::tls::TlsMaterial;
use tokio_util::sync::CancellationToken;

#[tokio::test]
async fn quic_download_and_upload_roundtrip() -> Result<()> {
    let cfg = QuicServerConfig {
        tls: TlsMaterial::self_signed()?,
        buffer_size: 65536,
    };
    let (endpoint, port) = bind_quic("127.0.0.1:0".parse().unwrap(), &cfg)?;

    let cancel = CancellationToken::new();
    let server_cancel = cancel.clone();
    let server_handle =
        tokio::spawn(async move { run_quic_server(endpoint, cfg, server_cancel).await });

    tokio::time::sleep(Duration::from_millis(200)).await;

    let config = QuicTestConfig::new(
        "127.0.0.1".to_string(),
        Some(port),
        2,
        2,
        TestType::Bidirectional,
        vec![65536usize],
    )
    .with_warmup(Duration::from_millis(0));

    let report = run_quic_client(config).await?;
    let result = match &report.result {
        TestResult::Network(net) => {
            assert!(matches!(net.protocol, NetworkProtocol::Quic));
            net
        }
        _ => panic!("expected NetworkTestResult"),
    };
    assert!(
        result.download.values().next().unwrap().bytes_transferred() > 0,
        "raw-QUIC download bytes must be > 0"
    );
    assert!(
        result.upload.values().next().unwrap().bytes_transferred() > 0,
        "raw-QUIC upload bytes must be > 0"
    );

    cancel.cancel();
    let join = tokio::time::timeout(Duration::from_secs(5), server_handle).await;
    assert!(join.is_ok(), "raw-QUIC server did not shut down within 5s");
    Ok(())
}