use std::net::TcpStream;
use std::time::Duration;
const PROXY_ADDR: &str = "127.0.0.1:5432";
const ADMIN_ADDR: &str = "127.0.0.1:9090";
fn port_is_open(addr: &str, timeout: Duration) -> bool {
TcpStream::connect_timeout(
&addr.parse().expect("invalid socket address"),
timeout,
)
.is_ok()
}
#[test]
#[ignore]
fn test_proxy_starts() {
assert!(
port_is_open(PROXY_ADDR, Duration::from_secs(5)),
"Proxy should be listening on {}",
PROXY_ADDR,
);
}
#[test]
#[ignore]
fn test_proxy_health_endpoint() {
let mut stream = TcpStream::connect_timeout(
&ADMIN_ADDR.parse().expect("invalid admin address"),
Duration::from_secs(5),
)
.expect("Failed to connect to admin endpoint");
stream
.set_read_timeout(Some(Duration::from_secs(5)))
.unwrap();
stream
.set_write_timeout(Some(Duration::from_secs(5)))
.unwrap();
use std::io::{Read, Write};
let request = format!(
"GET /health HTTP/1.1\r\nHost: {}\r\nConnection: close\r\n\r\n",
ADMIN_ADDR
);
stream.write_all(request.as_bytes()).expect("Failed to send HTTP request");
let mut response = String::new();
stream
.read_to_string(&mut response)
.expect("Failed to read HTTP response");
assert!(
response.contains("200") || response.contains("ok") || response.contains("healthy"),
"Health endpoint should return a success response, got: {}",
&response[..response.len().min(200)],
);
}
#[test]
#[ignore]
fn test_proxy_accepts_connection() {
let stream = TcpStream::connect_timeout(
&PROXY_ADDR.parse().expect("invalid proxy address"),
Duration::from_secs(5),
)
.expect("Failed to connect to proxy");
stream
.set_read_timeout(Some(Duration::from_secs(5)))
.unwrap();
let peer = stream.peer_addr().expect("Should have a peer address");
assert_eq!(
peer.ip().to_string(),
"127.0.0.1",
"Should be connected to localhost proxy",
);
use std::io::{Read, Write};
let ssl_request: [u8; 8] = [0, 0, 0, 8, 0x04, 0xd2, 0x16, 0x2f];
if stream.try_clone().unwrap().write_all(&ssl_request).is_ok() {
let mut buf = [0u8; 1];
if let Ok(n) = stream.try_clone().unwrap().read(&mut buf) {
if n == 1 {
assert!(
buf[0] == b'N' || buf[0] == b'S',
"Expected SSL response byte 'N' or 'S', got: 0x{:02x}",
buf[0],
);
}
}
}
}
#[test]
fn test_proxy_config_types() {
use heliosdb_proxy::connection_pool::PoolConfig;
use heliosdb_proxy::{NodeEndpoint, NodeRole};
let config = PoolConfig {
min_connections: 5,
max_connections: 100,
..Default::default()
};
assert_eq!(config.max_connections, 100);
let node = NodeEndpoint::new("localhost", 5432).with_role(NodeRole::Primary);
assert_eq!(node.address(), "localhost:5432");
assert_eq!(node.role, NodeRole::Primary);
}
#[test]
fn test_node_id_uniqueness() {
use heliosdb_proxy::NodeId;
let ids: Vec<NodeId> = (0..100).map(|_| NodeId::new()).collect();
for i in 0..ids.len() {
for j in (i + 1)..ids.len() {
assert_ne!(ids[i], ids[j], "NodeId should be unique");
}
}
}