286 lines
12 KiB
C++
286 lines
12 KiB
C++
#include "network/HTTPDataSource.h"
|
||
#include <gtest/gtest.h>
|
||
#include <gmock/gmock.h>
|
||
#include "utils/Logger.h"
|
||
#include <set>
|
||
#include <memory>
|
||
#include <thread>
|
||
|
||
class HTTPDataSourceTest : public ::testing::Test {
|
||
protected:
|
||
void SetUp() override {}
|
||
void TearDown() override {}
|
||
};
|
||
|
||
TEST_F(HTTPDataSourceTest, BasicFunctionality) {
|
||
DataSourceConfig config;
|
||
config.position.host = "localhost";
|
||
config.position.port = 8081;
|
||
config.position.aircraft_path = "/openApi/getCurrentFlightPositions";
|
||
config.position.vehicle_path = "/openApi/getCurrentVehiclePositions";
|
||
config.position.auth.auth_required = true;
|
||
config.position.auth.auth_path = "/login";
|
||
config.position.auth.username = "dianxin";
|
||
config.position.auth.password = "dianxin@123";
|
||
config.position.timeout_ms = 5000;
|
||
config.position.read_timeout_ms = 2000;
|
||
config.position.refresh_interval_ms = 100;
|
||
|
||
HTTPDataSource source(config);
|
||
ASSERT_TRUE(source.connect()) << "连接失败";
|
||
|
||
std::vector<Aircraft> aircraft;
|
||
bool success = source.fetchPositionAircraftData(aircraft);
|
||
ASSERT_TRUE(success) << "获取航空器数据失败";
|
||
ASSERT_FALSE(aircraft.empty()) << "航空器数据为空";
|
||
|
||
std::vector<Vehicle> vehicles;
|
||
ASSERT_TRUE(source.fetchPositionVehicleData(vehicles)) << "获取车辆数据失败";
|
||
ASSERT_FALSE(vehicles.empty()) << "车辆数据为空";
|
||
}
|
||
|
||
TEST_F(HTTPDataSourceTest, AuthenticationFailure) {
|
||
DataSourceConfig config;
|
||
config.position.host = "localhost";
|
||
config.position.port = 8081;
|
||
config.position.aircraft_path = "/openApi/getCurrentFlightPositions";
|
||
config.position.vehicle_path = "/openApi/getCurrentVehiclePositions";
|
||
config.position.refresh_interval_ms = 1000;
|
||
config.position.timeout_ms = 1000;
|
||
config.position.read_timeout_ms = 500;
|
||
|
||
config.position.auth.auth_required = true;
|
||
config.position.auth.username = "wrong_user";
|
||
config.position.auth.password = "wrong_pass";
|
||
config.position.auth.auth_path = "/login";
|
||
|
||
HTTPDataSource source(config);
|
||
std::vector<Aircraft> aircraft;
|
||
EXPECT_FALSE(source.fetchPositionAircraftData(aircraft));
|
||
}
|
||
|
||
TEST_F(HTTPDataSourceTest, Reconnection) {
|
||
DataSourceConfig config;
|
||
config.position.host = "localhost";
|
||
config.position.port = 8081;
|
||
config.position.aircraft_path = "/openApi/getCurrentFlightPositions";
|
||
config.position.vehicle_path = "/openApi/getCurrentVehiclePositions";
|
||
config.position.refresh_interval_ms = 1000;
|
||
config.position.timeout_ms = 1000;
|
||
config.position.read_timeout_ms = 500;
|
||
|
||
config.position.auth.auth_required = true;
|
||
config.position.auth.username = "dianxin";
|
||
config.position.auth.password = "dianxin@123";
|
||
config.position.auth.auth_path = "/login";
|
||
|
||
HTTPDataSource source(config);
|
||
EXPECT_TRUE(source.connect());
|
||
|
||
std::vector<Aircraft> aircraft;
|
||
EXPECT_TRUE(source.fetchPositionAircraftData(aircraft));
|
||
|
||
source.disconnect();
|
||
EXPECT_TRUE(source.connect());
|
||
|
||
aircraft.clear();
|
||
EXPECT_TRUE(source.fetchPositionAircraftData(aircraft));
|
||
}
|
||
|
||
TEST_F(HTTPDataSourceTest, AuthenticationOnly) {
|
||
DataSourceConfig config;
|
||
config.position.host = "localhost";
|
||
config.position.port = 8081;
|
||
config.position.aircraft_path = "/openApi/getCurrentFlightPositions";
|
||
config.position.vehicle_path = "/openApi/getCurrentVehiclePositions";
|
||
config.position.refresh_interval_ms = 1000;
|
||
config.position.timeout_ms = 1000;
|
||
config.position.read_timeout_ms = 500;
|
||
|
||
config.position.auth.auth_required = true;
|
||
config.position.auth.username = "dianxin";
|
||
config.position.auth.password = "dianxin@123";
|
||
config.position.auth.auth_path = "/login";
|
||
|
||
HTTPDataSource source(config);
|
||
EXPECT_TRUE(source.connect());
|
||
|
||
std::vector<Aircraft> aircraft;
|
||
EXPECT_TRUE(source.fetchPositionAircraftData(aircraft));
|
||
}
|
||
|
||
TEST_F(HTTPDataSourceTest, TrafficLightSignals) {
|
||
DataSourceConfig config;
|
||
config.position.host = "localhost";
|
||
config.position.port = 8081;
|
||
config.position.aircraft_path = "/openApi/getCurrentFlightPositions";
|
||
config.position.vehicle_path = "/openApi/getCurrentVehiclePositions";
|
||
config.position.auth.auth_required = true;
|
||
config.position.auth.auth_path = "/login";
|
||
config.position.auth.username = "dianxin";
|
||
config.position.auth.password = "dianxin@123";
|
||
config.position.timeout_ms = 5000;
|
||
config.position.read_timeout_ms = 2000;
|
||
config.position.refresh_interval_ms = 100;
|
||
|
||
config.traffic_light.host = "localhost";
|
||
config.traffic_light.port = 8081;
|
||
config.traffic_light.signal_path = "/api/VehicleCommandInfo";
|
||
config.vehicle.host = "localhost";
|
||
config.vehicle.port = 8081;
|
||
config.vehicle.command_path = "/api/VehicleCommandInfo";
|
||
|
||
HTTPDataSource source(config);
|
||
ASSERT_TRUE(source.connect());
|
||
|
||
// 先获取车辆状态来初始化车辆
|
||
std::vector<Vehicle> vehicles;
|
||
ASSERT_TRUE(source.fetchPositionVehicleData(vehicles)) << "获取车辆状态失败";
|
||
ASSERT_FALSE(vehicles.empty()) << "车辆数据为空";
|
||
|
||
// 发送绿灯指令(优先级 2)
|
||
VehicleCommand green_command;
|
||
green_command.vehicleId = "QN001";
|
||
green_command.type = CommandType::SIGNAL;
|
||
green_command.reason = CommandReason::TRAFFIC_LIGHT;
|
||
green_command.signalState = SignalState::GREEN;
|
||
green_command.intersectionId = "INTERSECTION_001";
|
||
green_command.timestamp = std::chrono::duration_cast<std::chrono::microseconds>(
|
||
std::chrono::system_clock::now().time_since_epoch()).count();
|
||
ASSERT_TRUE(source.sendUnmannedVehicleCommand(green_command.vehicleId, green_command)) << "发送绿灯指令失败";
|
||
|
||
// 等待绿灯指令生效
|
||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||
|
||
// 发送红灯指令(优先级 4)
|
||
VehicleCommand red_command;
|
||
red_command.vehicleId = "QN001";
|
||
red_command.type = CommandType::SIGNAL;
|
||
red_command.reason = CommandReason::TRAFFIC_LIGHT;
|
||
red_command.signalState = SignalState::RED;
|
||
red_command.intersectionId = "INTERSECTION_001";
|
||
red_command.latitude = 36.36;
|
||
red_command.longitude = 120.08;
|
||
red_command.timestamp = std::chrono::duration_cast<std::chrono::microseconds>(
|
||
std::chrono::system_clock::now().time_since_epoch()).count();
|
||
ASSERT_TRUE(source.sendUnmannedVehicleCommand(red_command.vehicleId, red_command)) << "发送红灯指令失败";
|
||
|
||
// 等待红灯指令生效
|
||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||
|
||
|
||
// 最后发送绿灯指令
|
||
green_command.timestamp = std::chrono::duration_cast<std::chrono::microseconds>(
|
||
std::chrono::system_clock::now().time_since_epoch()).count();
|
||
ASSERT_TRUE(source.sendUnmannedVehicleCommand(green_command.vehicleId, green_command)) << "发送最终绿灯指令失败";
|
||
}
|
||
|
||
TEST_F(HTTPDataSourceTest, UnmannedVehicleCommand) {
|
||
DataSourceConfig config;
|
||
config.position.host = "localhost";
|
||
config.position.port = 8081;
|
||
config.position.aircraft_path = "/openApi/getCurrentFlightPositions";
|
||
config.position.vehicle_path = "/openApi/getCurrentVehiclePositions";
|
||
config.position.auth.auth_required = true;
|
||
config.position.auth.auth_path = "/login";
|
||
config.position.auth.username = "dianxin";
|
||
config.position.auth.password = "dianxin@123";
|
||
config.position.timeout_ms = 5000;
|
||
config.position.read_timeout_ms = 2000;
|
||
config.position.refresh_interval_ms = 100;
|
||
|
||
config.vehicle.host = "localhost";
|
||
config.vehicle.port = 8081;
|
||
config.vehicle.command_path = "/api/VehicleCommandInfo";
|
||
config.vehicle.auth.auth_required = true;
|
||
config.vehicle.auth.auth_path = "/login";
|
||
config.vehicle.auth.username = "dianxin";
|
||
config.vehicle.auth.password = "dianxin@123";
|
||
config.vehicle.timeout_ms = 5000;
|
||
config.vehicle.read_timeout_ms = 2000;
|
||
|
||
HTTPDataSource source(config);
|
||
ASSERT_TRUE(source.connect()) << "连接失败";
|
||
|
||
// 先获取车辆状态来初始化车辆
|
||
std::vector<Vehicle> vehicles;
|
||
ASSERT_TRUE(source.fetchPositionVehicleData(vehicles)) << "获取车辆状态失败";
|
||
ASSERT_FALSE(vehicles.empty()) << "车辆数据为空";
|
||
|
||
// 先发送 RESUME 指令清除所有状态
|
||
VehicleCommand resume_command;
|
||
resume_command.vehicleId = "QN001";
|
||
resume_command.type = CommandType::RESUME;
|
||
resume_command.reason = CommandReason::RESUME_TRAFFIC;
|
||
resume_command.timestamp = std::chrono::duration_cast<std::chrono::microseconds>(
|
||
std::chrono::system_clock::now().time_since_epoch()).count();
|
||
ASSERT_TRUE(source.sendUnmannedVehicleCommand(resume_command.vehicleId, resume_command)) << "发送恢复指令失败";
|
||
|
||
// 等待 RESUME 指令生效
|
||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||
|
||
// 发送 WARNING 指令(优先级 3)
|
||
VehicleCommand warning_command;
|
||
warning_command.vehicleId = "QN001";
|
||
warning_command.type = CommandType::WARNING;
|
||
warning_command.reason = CommandReason::AIRCRAFT_CROSSING;
|
||
warning_command.relativeSpeed = 50;
|
||
warning_command.relativeMotionX = 50;
|
||
warning_command.relativeMotionY = 50;
|
||
warning_command.timestamp = std::chrono::duration_cast<std::chrono::microseconds>(
|
||
std::chrono::system_clock::now().time_since_epoch()).count();
|
||
ASSERT_TRUE(source.sendUnmannedVehicleCommand(warning_command.vehicleId, warning_command)) << "发送预警指令失败";
|
||
|
||
// 等待 WARNING 指令生效
|
||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||
|
||
// 发送 ALERT 指令(优先级 5)
|
||
VehicleCommand alert_command;
|
||
alert_command.vehicleId = "QN001";
|
||
alert_command.type = CommandType::ALERT;
|
||
alert_command.reason = CommandReason::AIRCRAFT_CROSSING;
|
||
alert_command.relativeSpeed = 100;
|
||
alert_command.relativeMotionX = 100;
|
||
alert_command.relativeMotionY = 100;
|
||
alert_command.timestamp = std::chrono::duration_cast<std::chrono::microseconds>(
|
||
std::chrono::system_clock::now().time_since_epoch()).count();
|
||
ASSERT_TRUE(source.sendUnmannedVehicleCommand(alert_command.vehicleId, alert_command)) << "发送告警指令失败";
|
||
|
||
// 等待 ALERT 指令生效
|
||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||
|
||
// 最后发送 RESUME 指令清除状态
|
||
resume_command.timestamp = std::chrono::duration_cast<std::chrono::microseconds>(
|
||
std::chrono::system_clock::now().time_since_epoch()).count();
|
||
ASSERT_TRUE(source.sendUnmannedVehicleCommand(resume_command.vehicleId, resume_command)) << "发送最终恢复指令失败";
|
||
}
|
||
|
||
TEST_F(HTTPDataSourceTest, TrafficLightAndUnmannedAuthFailure) {
|
||
DataSourceConfig config;
|
||
config.traffic_light.host = "localhost";
|
||
config.traffic_light.port = 8081;
|
||
config.traffic_light.signal_path = "/api/VehicleCommandInfo";
|
||
config.traffic_light.auth.auth_required = true;
|
||
config.traffic_light.auth.username = "wrong_user";
|
||
config.traffic_light.auth.password = "wrong_pass";
|
||
|
||
config.vehicle.host = "localhost";
|
||
config.vehicle.port = 8081;
|
||
config.vehicle.command_path = "/api/VehicleCommandInfo";
|
||
config.vehicle.auth.auth_required = true;
|
||
config.vehicle.auth.username = "wrong_user";
|
||
config.vehicle.auth.password = "wrong_pass";
|
||
|
||
HTTPDataSource source(config);
|
||
|
||
std::vector<TrafficLightSignal> signals;
|
||
EXPECT_FALSE(source.fetchTrafficLightSignals(signals));
|
||
|
||
VehicleCommand command;
|
||
command.vehicleId = "TEST_VEHICLE_001";
|
||
command.type = CommandType::SIGNAL;
|
||
command.reason = CommandReason::RESUME_TRAFFIC;
|
||
command.signalState = SignalState::GREEN;
|
||
command.timestamp = 0;
|
||
EXPECT_FALSE(source.sendUnmannedVehicleCommand(command.vehicleId, command));
|
||
}
|