use qslib::com::{ConnectionType, QSConnection};
use qslib::commands::*;
use std::time::Duration;
use tokio_stream::StreamExt;
const TCP_HOST: &str = "localhost";
const TCP_PORT: u16 = 7000;
const SSL_HOST: &str = "localhost";
const SSL_PORT: u16 = 7443;
const TEST_PASSWORD: &str = "correctpassword";
async fn connect_authenticated(host: &str, port: u16, conn_type: ConnectionType) -> QSConnection {
let conn = QSConnection::connect(host, port, conn_type)
.await
.expect("Failed to connect");
conn.authenticate(TEST_PASSWORD)
.await
.expect("Failed to authenticate");
conn.set_access_level(AccessLevel::Observer)
.await
.expect("Failed to set access level");
conn
}
#[tokio::test]
#[ignore]
async fn test_simulator_tcp_connection() {
let connection = QSConnection::connect(TCP_HOST, TCP_PORT, ConnectionType::TCP).await;
assert!(connection.is_ok(), "TCP connection failed: {:?}", connection.err());
let conn = connection.unwrap();
assert!(conn.is_connected().await, "Connection should be active");
assert_eq!(conn.connection_type, ConnectionType::TCP);
assert!(conn.ready_message.args.get("product").is_some(), "Missing product in ready message");
assert!(conn.ready_message.args.get("version").is_some(), "Missing version in ready message");
}
#[tokio::test]
#[ignore]
async fn test_simulator_ssl_connection() {
let connection = QSConnection::connect(SSL_HOST, SSL_PORT, ConnectionType::SSL).await;
assert!(connection.is_ok(), "SSL connection failed: {:?}", connection.err());
let conn = connection.unwrap();
assert!(conn.is_connected().await, "Connection should be active");
assert_eq!(conn.connection_type, ConnectionType::SSL);
}
#[tokio::test]
#[ignore]
async fn test_simulator_auto_tcp() {
let connection = QSConnection::connect(TCP_HOST, TCP_PORT, ConnectionType::Auto).await;
assert!(connection.is_ok(), "Auto TCP connection failed: {:?}", connection.err());
let conn = connection.unwrap();
assert_eq!(conn.connection_type, ConnectionType::TCP);
}
#[tokio::test]
#[ignore]
async fn test_simulator_auto_ssl() {
let connection = QSConnection::connect(SSL_HOST, SSL_PORT, ConnectionType::Auto).await;
assert!(connection.is_ok(), "Auto SSL connection failed: {:?}", connection.err());
let conn = connection.unwrap();
assert_eq!(conn.connection_type, ConnectionType::SSL);
}
#[tokio::test]
#[ignore]
async fn test_simulator_connection_timeout() {
let connection = QSConnection::connect_with_timeout(
TCP_HOST,
TCP_PORT,
ConnectionType::TCP,
Duration::from_secs(10),
).await;
assert!(connection.is_ok(), "Connection with timeout failed: {:?}", connection.err());
}
#[tokio::test]
#[ignore]
async fn test_simulator_help_command() {
let connection = QSConnection::connect(TCP_HOST, TCP_PORT, ConnectionType::TCP)
.await
.expect("Failed to connect");
let mut response = connection
.send_command_bytes(b"HELP?")
.await
.expect("Failed to send command");
let result = response.get_response().await;
assert!(result.is_ok(), "HELP? command failed: {:?}", result.err());
}
#[tokio::test]
#[ignore]
async fn test_simulator_power_query() {
let connection = connect_authenticated(TCP_HOST, TCP_PORT, ConnectionType::TCP).await;
let response = PowerQuery
.send(&connection)
.await
.expect("Failed to send power query")
.receive_response()
.await;
assert!(response.is_ok(), "Power query failed: {:?}", response.err());
let power_status = response.unwrap();
assert!(power_status.is_ok(), "Power query returned error: {:?}", power_status.err());
}
#[tokio::test]
#[ignore]
async fn test_simulator_access_level_query() {
let connection = QSConnection::connect(TCP_HOST, TCP_PORT, ConnectionType::TCP)
.await
.expect("Failed to connect");
let response = AccessLevelQuery
.send(&connection)
.await
.expect("Failed to send access level query")
.receive_response()
.await;
assert!(response.is_ok(), "Access level query failed: {:?}", response.err());
}
#[tokio::test]
#[ignore]
async fn test_simulator_authentication() {
let connection = QSConnection::connect(TCP_HOST, TCP_PORT, ConnectionType::TCP)
.await
.expect("Failed to connect");
let auth_result = connection.authenticate(TEST_PASSWORD).await;
assert!(auth_result.is_ok(), "Authentication failed: {:?}", auth_result.err());
let set_result = connection.set_access_level(AccessLevel::Controller).await;
assert!(set_result.is_ok(), "Failed to set Controller after auth: {:?}", set_result.err());
let level = connection.get_access_level().await.expect("Failed to get access level");
assert!(matches!(level, AccessLevel::Controller), "Expected Controller, got {:?}", level);
}
#[tokio::test]
#[ignore]
async fn test_simulator_authentication_wrong_password() {
let connection = QSConnection::connect(TCP_HOST, TCP_PORT, ConnectionType::TCP)
.await
.expect("Failed to connect");
let auth_result = connection.authenticate("wrongpassword").await;
assert!(auth_result.is_err(), "Authentication with wrong password should fail");
}
#[tokio::test]
#[ignore]
async fn test_simulator_set_access_level() {
let connection = QSConnection::connect(TCP_HOST, TCP_PORT, ConnectionType::TCP)
.await
.expect("Failed to connect");
let response = AccessLevelSet::level(AccessLevel::Observer)
.send(&connection)
.await
.expect("Failed to send access level set")
.receive_response()
.await;
println!("Access level set response: {:?}", response);
let verify = AccessLevelQuery
.send(&connection)
.await
.expect("Failed to send verification query")
.receive_response()
.await;
assert!(verify.is_ok(), "Verification query failed: {:?}", verify.err());
}
#[tokio::test]
#[ignore]
async fn test_simulator_controller_access() {
let connection = QSConnection::connect(TCP_HOST, TCP_PORT, ConnectionType::TCP)
.await
.expect("Failed to connect");
connection.authenticate(TEST_PASSWORD)
.await
.expect("Failed to authenticate");
let result = connection.set_access_level(AccessLevel::Controller).await;
assert!(result.is_ok(), "Failed to set Controller access: {:?}", result.err());
let level = connection.get_access_level().await.expect("Failed to get access level");
assert!(matches!(level, AccessLevel::Controller), "Expected Controller, got {:?}", level);
}
#[tokio::test]
#[ignore]
async fn test_simulator_log_subscription() {
let connection = connect_authenticated(TCP_HOST, TCP_PORT, ConnectionType::TCP).await;
Subscribe::topic("Temperature").send(&connection).await.unwrap();
let mut stream = connection.subscribe_log(&["Temperature"]).await;
let timeout = tokio::time::timeout(Duration::from_secs(5), stream.next()).await;
assert!(timeout.is_ok(), "Timed out waiting for log messages");
let message = timeout.unwrap();
assert!(message.is_some(), "Should receive at least one log message");
}
#[tokio::test]
#[ignore]
async fn test_simulator_run_title_no_run() {
let connection = connect_authenticated(TCP_HOST, TCP_PORT, ConnectionType::TCP).await;
let result = connection.get_current_run_name().await;
assert!(result.is_ok(), "Run title query failed: {:?}", result.err());
let run_name = result.unwrap();
println!("Current run name: {:?}", run_name);
}
#[tokio::test]
#[ignore]
async fn test_simulator_temperature_setpoints() {
let connection = connect_authenticated(TCP_HOST, TCP_PORT, ConnectionType::TCP).await;
let result = connection.get_current_temperature_setpoints().await;
assert!(result.is_ok(), "Temperature setpoints query failed: {:?}", result.err());
let (zones, fans, cover) = result.unwrap();
assert_eq!(zones.len(), 6, "Should have 6 zone temperatures");
assert!(!fans.is_empty(), "Should have fan temperatures");
assert!(cover > 0.0 && cover < 200.0, "Cover temperature {} seems unreasonable", cover);
}
#[tokio::test]
#[ignore]
async fn test_simulator_file_list() {
let connection = connect_authenticated(TCP_HOST, TCP_PORT, ConnectionType::TCP).await;
let result = connection.get_expfile_list("*").await;
println!("File list result: {:?}", result);
}
#[tokio::test]
#[ignore]
async fn test_simulator_concurrent_commands() {
let connection = connect_authenticated(TCP_HOST, TCP_PORT, ConnectionType::TCP).await;
let power_fut = PowerQuery.send(&connection);
let access_fut = AccessLevelQuery.send(&connection);
let (power_resp, access_resp) = tokio::join!(power_fut, access_fut);
let mut power = power_resp.expect("Power query send failed");
let mut access = access_resp.expect("Access query send failed");
let (power_result, access_result) = tokio::join!(
power.receive_response(),
access.receive_response()
);
assert!(power_result.is_ok(), "Power query failed: {:?}", power_result.err());
assert!(access_result.is_ok(), "Access query failed: {:?}", access_result.err());
}
#[tokio::test]
#[ignore]
async fn test_simulator_raw_command() {
let connection = connect_authenticated(TCP_HOST, TCP_PORT, ConnectionType::TCP).await;
let mut response = connection
.send_command_bytes(b"RUNTitle?")
.await
.expect("Failed to send command");
let result = response.get_response().await;
assert!(result.is_ok(), "Raw command failed: {:?}", result.err());
}
#[tokio::test]
#[ignore]
async fn test_simulator_ssl_commands() {
let connection = connect_authenticated(SSL_HOST, SSL_PORT, ConnectionType::SSL).await;
let response = PowerQuery
.send(&connection)
.await
.expect("Failed to send command")
.receive_response()
.await;
assert!(response.is_ok(), "SSL command failed: {:?}", response.err());
}
#[tokio::test]
#[ignore]
async fn test_simulator_reconnection() {
let conn1 = QSConnection::connect(TCP_HOST, TCP_PORT, ConnectionType::TCP)
.await
.expect("First connection failed");
assert!(conn1.is_connected().await);
let conn2 = QSConnection::connect(TCP_HOST, TCP_PORT, ConnectionType::TCP)
.await
.expect("Second connection failed");
assert!(conn2.is_connected().await);
let r1 = conn1.send_command_bytes(b"HELP?").await;
let r2 = conn2.send_command_bytes(b"HELP?").await;
assert!(r1.is_ok(), "First connection command failed");
assert!(r2.is_ok(), "Second connection command failed");
}
#[tokio::test]
#[ignore]
async fn test_simulator_wrong_port_type() {
let result = QSConnection::connect(TCP_HOST, TCP_PORT, ConnectionType::SSL).await;
assert!(result.is_err(), "SSL connection to TCP port should fail");
}