use ntrip_core::{NtripClient, NtripConfig, NtripVersion};
use std::time::Duration;
#[tokio::test]
#[ignore = "requires network access"]
async fn test_rtk2go_sourcetable() {
let config = NtripConfig::new("rtk2go.com", 2101, "");
let table = NtripClient::get_sourcetable(&config)
.await
.expect("Failed to fetch sourcetable");
assert!(!table.streams.is_empty(), "Sourcetable should have streams");
assert!(!table.casters.is_empty(), "Sourcetable should have casters");
println!("RTK2go has {} streams", table.streams.len());
assert!(table.streams.len() > 100, "RTK2go should have >100 streams");
}
#[tokio::test]
#[ignore = "requires network access"]
async fn test_euref_sourcetable() {
let config = NtripConfig::new("euref-ip.net", 2101, "");
let table = NtripClient::get_sourcetable(&config)
.await
.expect("Failed to fetch sourcetable");
assert!(!table.streams.is_empty(), "Sourcetable should have streams");
println!("EUREF has {} streams", table.streams.len());
}
#[tokio::test]
#[ignore = "requires network access"]
async fn test_centipede_sourcetable() {
let config = NtripConfig::new("caster.centipede.fr", 2101, "");
let table = NtripClient::get_sourcetable(&config)
.await
.expect("Failed to fetch sourcetable");
assert!(!table.streams.is_empty(), "Sourcetable should have streams");
println!("Centipede has {} streams", table.streams.len());
}
#[tokio::test]
#[ignore = "requires network access"]
async fn test_snip_demo_sourcetable() {
let config = NtripConfig::new("ntrip.use-snip.com", 2101, "");
let table = NtripClient::get_sourcetable(&config)
.await
.expect("Failed to fetch sourcetable");
println!("SNIP Demo has {} streams", table.streams.len());
assert!(
!table.streams.is_empty() || !table.casters.is_empty(),
"SNIP should have streams or caster entries"
);
}
#[tokio::test]
#[ignore = "requires network access"]
async fn test_igs_sourcetable() {
let config = NtripConfig::new("igs-ip.net", 2101, "");
let table = NtripClient::get_sourcetable(&config)
.await
.expect("Failed to fetch sourcetable");
assert!(!table.streams.is_empty(), "Sourcetable should have streams");
println!("IGS has {} streams", table.streams.len());
}
#[tokio::test]
#[ignore = "requires network access"]
async fn test_nearest_mountpoint() {
let config = NtripConfig::new("rtk2go.com", 2101, "");
let table = NtripClient::get_sourcetable(&config)
.await
.expect("Failed to fetch sourcetable");
let nearest = table.nearest_rtcm_stream(-27.47, 153.02);
assert!(nearest.is_some(), "Should find a nearest stream");
let (stream, dist) = nearest.unwrap();
println!(
"Nearest to Brisbane: {} at {:.1} km",
stream.mountpoint, dist
);
assert!(stream.is_rtcm(), "Nearest should be an RTCM stream");
}
#[tokio::test]
#[ignore = "requires network access and valid mountpoint"]
async fn test_v1_connection() {
let config = NtripConfig::new("rtk2go.com", 2101, "Laguna01")
.with_credentials("test@example.com", "none")
.with_version(NtripVersion::V1);
let mut client = NtripClient::new(config).expect("Failed to create client");
if let Ok(()) = client.connect().await {
let mut buf = [0u8; 4096];
let result =
tokio::time::timeout(Duration::from_secs(5), client.read_chunk(&mut buf)).await;
match result {
Ok(Ok(n)) => {
println!("Received {} bytes via NTRIP v1", n);
assert!(n > 0, "Should receive some data");
}
Ok(Err(e)) => println!("Read error (may be expected): {}", e),
Err(_) => println!("Timeout (mountpoint may be offline)"),
}
}
}
#[tokio::test]
#[ignore = "requires network access and valid mountpoint"]
async fn test_v2_connection() {
let config = NtripConfig::new("rtk2go.com", 2101, "Laguna01")
.with_credentials("test@example.com", "none")
.with_version(NtripVersion::V2);
let mut client = NtripClient::new(config).expect("Failed to create client");
if let Ok(()) = client.connect().await {
let mut buf = [0u8; 4096];
let result =
tokio::time::timeout(Duration::from_secs(5), client.read_chunk(&mut buf)).await;
match result {
Ok(Ok(n)) => {
println!("Received {} bytes via NTRIP v2", n);
assert!(n > 0, "Should receive some data");
}
Ok(Err(e)) => println!("Read error (may be expected): {}", e),
Err(_) => println!("Timeout (mountpoint may be offline)"),
}
}
}
#[tokio::test]
#[ignore = "requires network access and valid mountpoint"]
async fn test_auto_protocol_detection() {
let config = NtripConfig::new("rtk2go.com", 2101, "Laguna01")
.with_credentials("test@example.com", "none")
.with_version(NtripVersion::Auto);
let mut client = NtripClient::new(config).expect("Failed to create client");
if let Ok(()) = client.connect().await {
println!("Connected with auto-detect");
assert!(client.is_connected());
}
}
#[tokio::test]
#[ignore = "requires network access"]
async fn test_rtk2go_dynamic_connection() {
let config = NtripConfig::new("rtk2go.com", 2101, "");
let table = NtripClient::get_sourcetable(&config)
.await
.expect("Failed to fetch sourcetable");
let nearest = table.nearest_rtcm_stream(40.71, -74.01);
let mountpoint = match nearest {
Some((stream, dist)) => {
println!(
"Found mountpoint '{}' at {:.1} km from New York",
stream.mountpoint, dist
);
stream.mountpoint.clone()
}
None => {
let first_rtcm = table.streams.iter().find(|s| s.is_rtcm());
match first_rtcm {
Some(stream) => {
println!("Using first RTCM stream: {}", stream.mountpoint);
stream.mountpoint.clone()
}
None => {
panic!("No RTCM streams found in RTK2go sourcetable");
}
}
}
};
let config = NtripConfig::new("rtk2go.com", 2101, &mountpoint)
.with_credentials("ntrip-core-test@example.com", "none")
.with_timeout(10)
.without_reconnect();
let mut client = NtripClient::new(config).expect("Failed to create client");
match client.connect().await {
Ok(()) => {
println!("Successfully connected to {}", mountpoint);
assert!(client.is_connected());
let mut buf = [0u8; 4096];
let result =
tokio::time::timeout(Duration::from_secs(5), client.read_chunk(&mut buf)).await;
match result {
Ok(Ok(n)) => {
println!("Received {} bytes of RTCM data from {}", n, mountpoint);
assert!(n > 0, "Should receive some data");
}
Ok(Err(e)) => {
println!("Read error (mountpoint may be inactive): {}", e);
}
Err(_) => {
println!("Timeout waiting for data (mountpoint may be inactive)");
}
}
}
Err(e) => {
println!(
"Could not connect to {} (may be offline): {}",
mountpoint, e
);
}
}
}
#[tokio::test]
#[ignore = "requires network access"]
async fn test_centipede_dynamic_connection() {
let config = NtripConfig::new("caster.centipede.fr", 2101, "");
let table = NtripClient::get_sourcetable(&config)
.await
.expect("Failed to fetch sourcetable");
let nearest = table.nearest_rtcm_stream(48.86, 2.35);
let mountpoint = match nearest {
Some((stream, dist)) => {
println!(
"Found Centipede mountpoint '{}' at {:.1} km from Paris",
stream.mountpoint, dist
);
stream.mountpoint.clone()
}
None => {
panic!("No RTCM streams found in Centipede sourcetable");
}
};
let config = NtripConfig::new("caster.centipede.fr", 2101, &mountpoint)
.with_timeout(10)
.without_reconnect();
let mut client = NtripClient::new(config).expect("Failed to create client");
match client.connect().await {
Ok(()) => {
println!("Successfully connected to Centipede/{}", mountpoint);
assert!(client.is_connected());
let mut buf = [0u8; 4096];
let result =
tokio::time::timeout(Duration::from_secs(5), client.read_chunk(&mut buf)).await;
match result {
Ok(Ok(n)) => {
println!("Received {} bytes from Centipede/{}", n, mountpoint);
assert!(n > 0);
}
Ok(Err(e)) => println!("Read error: {}", e),
Err(_) => println!("Timeout (mountpoint may be inactive)"),
}
}
Err(e) => {
println!("Could not connect to Centipede/{}: {}", mountpoint, e);
}
}
}
#[tokio::test]
#[ignore = "requires network access and AUSCORS credentials"]
async fn test_tls_sourcetable() {
let config = NtripConfig::new("ntrip.data.gnss.ga.gov.au", 443, "").with_tls();
let result = NtripClient::get_sourcetable(&config).await;
match result {
Ok(table) => println!("Got {} streams from AUSCORS", table.streams.len()),
Err(e) => println!("Expected error without credentials: {}", e),
}
}
#[tokio::test]
async fn test_connection_failure() {
let config = NtripConfig::new("10.255.255.1", 2101, "TEST")
.with_timeout(2)
.without_reconnect();
let mut client = NtripClient::new(config).expect("Failed to create client");
let result = client.connect().await;
assert!(result.is_err(), "Should fail to connect");
let err = result.unwrap_err();
let err_str = format!("{}", err);
assert!(
err_str.contains("timed out")
|| err_str.contains("Failed to connect")
|| err_str.contains("Connection refused")
|| err_str.contains("Network is unreachable"),
"Unexpected error: {}",
err
);
println!("Connection failed as expected: {}", err);
}
#[test]
fn test_config_validation() {
let config = NtripConfig::new("", 2101, "TEST");
assert!(config.validate().is_err());
let config = NtripConfig::new("example.com", 0, "TEST");
assert!(config.validate().is_err());
let config = NtripConfig::new("example.com", 2101, "TEST");
assert!(config.validate().is_ok());
}