use netspeed_cli::common;
use netspeed_cli::download::{self, build_test_url, extract_base_url};
use netspeed_cli::progress::Tracker;
use netspeed_cli::servers::{ping_test, select_best_server};
use netspeed_cli::types::Server;
use netspeed_cli::upload;
use reqwest::Client;
use std::sync::Arc;
use wiremock::matchers::{method, path_regex};
use wiremock::{Mock, MockServer, ResponseTemplate};
async fn create_mock_speedtest_server() -> MockServer {
let mock = MockServer::start().await;
Mock::given(method("GET"))
.and(path_regex(".*/latency\\.txt$"))
.respond_with(ResponseTemplate::new(200).set_body_string("OK"))
.mount(&mock)
.await;
Mock::given(method("GET"))
.and(path_regex(".*random.*"))
.respond_with(ResponseTemplate::new(200).set_body_bytes(vec![0u8; 1024 * 256]))
.mount(&mock)
.await;
Mock::given(method("POST"))
.and(path_regex(".*/upload\\.php$"))
.respond_with(ResponseTemplate::new(200).set_body_string("OK"))
.mount(&mock)
.await;
mock
}
#[tokio::test]
#[ignore = "requires local socket binding"]
async fn test_e2e_full_speedtest_flow() {
let mock = create_mock_speedtest_server().await;
let mock_url = mock.uri();
let server = Server {
id: "9999".to_string(),
url: format!("{mock_url}/upload.php"),
name: "E2E Test Server".to_string(),
sponsor: "Test ISP".to_string(),
country: "US".to_string(),
lat: 40.0,
lon: -74.0,
distance: 50.0,
};
let servers = vec![server.clone()];
let selected = select_best_server(&servers).expect("Should select server");
assert_eq!(selected.id, "9999");
let client = Client::builder()
.timeout(std::time::Duration::from_secs(10))
.build()
.expect("Should create client");
let ping_result = ping_test(&client, &selected)
.await
.expect("Ping should succeed");
let (avg_latency, _jitter, _packet_loss, _samples) = ping_result;
assert!(avg_latency > 0.0, "Latency should be positive");
assert!(avg_latency < 1000.0, "Local latency should be reasonable");
let progress = Arc::new(Tracker::with_target(
"Download",
indicatif::ProgressDrawTarget::hidden(),
));
let dl_result = download::run(&client, &selected, true, progress.clone())
.await
.expect("Download should succeed");
let (avg_download, peak_download, total_download_bytes, download_samples) = dl_result;
assert!(avg_download > 0.0, "Download speed should be positive");
assert!(
total_download_bytes > 0,
"Should have downloaded some bytes"
);
assert!(!download_samples.is_empty(), "Should have speed samples");
let _ = peak_download;
let progress = Arc::new(Tracker::with_target(
"Upload",
indicatif::ProgressDrawTarget::hidden(),
));
let ul_result = upload::run(&client, &selected, true, progress.clone())
.await
.expect("Upload should succeed");
let (avg_upload, peak_upload, total_upload_bytes, upload_samples) = ul_result;
assert!(avg_upload > 0.0, "Upload speed should be positive");
assert!(total_upload_bytes > 0, "Should have uploaded some bytes");
assert!(!upload_samples.is_empty(), "Should have speed samples");
let _ = peak_upload;
}
#[tokio::test]
#[ignore = "requires local socket binding"]
async fn test_e2e_download_only() {
let mock = create_mock_speedtest_server().await;
let server = Server {
id: "1".to_string(),
url: format!("{}/upload.php", mock.uri()),
name: "Test".to_string(),
sponsor: "Test".to_string(),
country: "US".to_string(),
lat: 0.0,
lon: 0.0,
distance: 0.0,
};
let client = Client::builder()
.timeout(std::time::Duration::from_secs(10))
.build()
.expect("Should create client");
let progress = Arc::new(Tracker::with_target(
"Download",
indicatif::ProgressDrawTarget::hidden(),
));
let result = download::run(&client, &server, true, progress).await;
assert!(result.is_ok());
let (avg, _peak, bytes, samples) = result.unwrap();
assert!(avg > 0.0);
assert!(bytes > 0);
assert!(!samples.is_empty());
}
#[tokio::test]
#[ignore = "requires local socket binding"]
async fn test_e2e_upload_only() {
let mock = create_mock_speedtest_server().await;
let server = Server {
id: "1".to_string(),
url: format!("{}/upload.php", mock.uri()),
name: "Test".to_string(),
sponsor: "Test".to_string(),
country: "US".to_string(),
lat: 0.0,
lon: 0.0,
distance: 0.0,
};
let client = Client::builder()
.timeout(std::time::Duration::from_secs(10))
.build()
.expect("Should create client");
let progress = Arc::new(Tracker::with_target(
"Upload",
indicatif::ProgressDrawTarget::hidden(),
));
let result = upload::run(&client, &server, true, progress).await;
assert!(result.is_ok());
let (avg, _peak, bytes, samples) = result.unwrap();
assert!(avg > 0.0);
assert!(bytes > 0);
assert!(!samples.is_empty());
}
#[test]
fn test_url_construction_e2e() {
let server_url = "http://localhost:8080/upload.php";
let base = extract_base_url(server_url);
assert_eq!(base, "http://localhost:8080");
let url0 = build_test_url(server_url, 0);
assert!(url0.ends_with("/random0.txt") || url0.starts_with("http://localhost:8080"));
}
#[test]
fn test_bandwidth_calculation_e2e() {
let bytes = 1_000_000u64;
let secs = 1.0f64;
let bps = common::calculate_bandwidth(bytes, secs);
assert!((bps - 8_000_000.0).abs() < f64::EPSILON); }