#include #include #include "collector/DataCollector.h" #include "config/AirportBounds.h" #include "spatial/CoordinateConverter.h" #include "utils/Logger.h" #include "network/MessageTypes.h" #include "core/System.h" // 创建一个 Mock DataSource 类 class MockDataSource : public DataSource { public: MOCK_METHOD0(connect, bool()); MOCK_METHOD0(disconnect, void()); MOCK_CONST_METHOD0(isAvailable, bool()); MOCK_METHOD1(fetchPositionAircraftData, bool(std::vector&)); MOCK_METHOD1(fetchPositionVehicleData, bool(std::vector&)); MOCK_METHOD1(fetchTrafficLightSignals, bool(std::vector&)); MOCK_METHOD2(sendUnmannedVehicleCommand, bool(const std::string&, const VehicleCommand&)); MOCK_METHOD2(fetchUnmannedVehicleStatus, bool(const std::string&, std::string&)); }; // 创建测试专用的 AirportBounds 类 class TestAirportBounds : public AirportBounds { public: using AirportBounds::AirportBounds; // 继承构造函数 void setBounds(const Bounds& bounds) { this->airportBounds_ = bounds; } void setReferencePoint(const Vector2D& point) { this->referencePoint_ = point; } void setRotationAngle(double angle) { this->rotationAngle_ = angle * M_PI / 180.0; // 转换为弧度 } protected: using AirportBounds::airportBounds_; using AirportBounds::referencePoint_; using AirportBounds::rotationAngle_; }; class DataCollectorTest : public ::testing::Test { protected: void SetUp() override { // 设置日志级别 Logger::setLogLevel(LogLevel::DEBUG); // 初始化系统配置 SystemConfig::instance().load("config/system_config.json"); // 创建测试实例 bounds_ = std::make_unique(); // 设置机场边界参数 bounds_->setReferencePoint(Vector2D{0, 0}); // 世界坐标系中的参考点 bounds_->setRotationAngle(68.53); // 与 airport_bounds.json 保持一致 bounds_->setBounds(Bounds(-100, -200, 800, 400)); // 与 airport_bounds.json 保持一致 // 初始化坐标转换器 const auto& refPoint = SystemConfig::instance().airport.reference_point; CoordinateConverter::instance().setReferencePoint(refPoint.latitude, refPoint.longitude); collector = std::make_unique(*bounds_); mockSource = std::make_shared<::testing::NiceMock>(); collector->setDataSource(mockSource); // 初始化配置 dataSourceConfig_.position.refresh_interval_ms = 100; dataSourceConfig_.position.timeout_ms = 5000; // 添加连接超时配置 dataSourceConfig_.position.read_timeout_ms = 2000; // 添加读取超时配置 dataSourceConfig_.vehicle.refresh_interval_ms = 100; dataSourceConfig_.vehicle.timeout_ms = 5000; dataSourceConfig_.vehicle.read_timeout_ms = 2000; dataSourceConfig_.traffic_light.refresh_interval_ms = 100; dataSourceConfig_.traffic_light.timeout_ms = 5000; dataSourceConfig_.traffic_light.read_timeout_ms = 2000; WarnConfig warnConfig; warnConfig.warning_interval_ms = 500; // 设置警告间隔 EXPECT_TRUE(collector->initialize(dataSourceConfig_, warnConfig)); } void TearDown() override { collector.reset(); } // 创建测试用的航空器 Aircraft createTestAircraft(const std::string& id, double lat, double lon) { Aircraft aircraft; aircraft.id = id; aircraft.flightNo = id; aircraft.geo.latitude = lat; aircraft.geo.longitude = lon; aircraft.timestamp = std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()).count(); return aircraft; } // 创建测试用的车辆 Vehicle createTestVehicle(const std::string& id, double lat, double lon) { Vehicle vehicle; vehicle.id = id; vehicle.vehicleNo = id; vehicle.geo.latitude = lat; vehicle.geo.longitude = lon; vehicle.timestamp = std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()).count(); return vehicle; } // 创建测试用的红绿灯信号 TrafficLightSignal createTestTrafficLight(const std::string& id, int state) { TrafficLightSignal signal; signal.trafficLightId = id; signal.ns_status = static_cast(state); signal.ew_status = static_cast(state); signal.timestamp = std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()).count(); return signal; } // 创建边界内的航空器 Aircraft createOutOfBoundsAircraft(const std::string& id) { // 计算偏移量,考虑机场旋转角度 double angle = 68.53 * M_PI / 180.0; // 转换为弧度 double offset = 0.027; // 约 3km double lat_offset = offset * std::cos(angle); double lon_offset = offset * std::sin(angle); const auto& refPoint = SystemConfig::instance().airport.reference_point; return createTestAircraft(id, refPoint.latitude + lat_offset, refPoint.longitude + lon_offset); } // 创建边界内的车辆 Vehicle createOutOfBoundsVehicle(const std::string& id) { // 计算偏移量,考虑机场旋转角度 double angle = 68.53 * M_PI / 180.0; // 转换为弧度 double offset = 0.0225; // 约 2.5km double lat_offset = -offset * std::cos(angle); // 负值表示向相反方向偏移 double lon_offset = -offset * std::sin(angle); const auto& refPoint = SystemConfig::instance().airport.reference_point; return createTestVehicle(id, refPoint.latitude + lat_offset, refPoint.longitude + lon_offset); } std::unique_ptr collector; std::shared_ptr mockSource; std::unique_ptr bounds_; std::unique_ptr converter_; DataSourceConfig dataSourceConfig_; }; // 修改初始化测试用例 TEST_F(DataCollectorTest, Initialization) { DataSourceConfig dataSourceConfig; // 设置位置数据配置 dataSourceConfig.position.host = "localhost"; dataSourceConfig.position.port = 8080; dataSourceConfig.position.aircraft_path = "/api/getCurrentFlightPositions"; dataSourceConfig.position.refresh_interval_ms = 1000; dataSourceConfig.position.timeout_ms = 5000; dataSourceConfig.position.read_timeout_ms = 2000; WarnConfig warnConfig; warnConfig.warning_interval_ms = 1000; warnConfig.log_interval_ms = 2000; EXPECT_TRUE(collector->initialize(dataSourceConfig, warnConfig)); } // 测试数据采集 TEST_F(DataCollectorTest, DataCollectionTest) { // 设置数据源配置 DataSourceConfig config; // 设置位置数据配置 config.position.host = "localhost"; config.position.port = 8080; config.position.refresh_interval_ms = 100; config.position.timeout_ms = 1000; config.position.read_timeout_ms = 500; // 设置无人车数据配置 config.vehicle.host = "localhost"; config.vehicle.port = 8081; config.vehicle.refresh_interval_ms = 100; config.vehicle.timeout_ms = 1000; config.vehicle.read_timeout_ms = 500; // 设置红绿灯数据配置 config.traffic_light.host = "localhost"; config.traffic_light.port = 8082; config.traffic_light.refresh_interval_ms = 100; config.traffic_light.timeout_ms = 1000; config.traffic_light.read_timeout_ms = 500; WarnConfig warnConfig; warnConfig.warning_interval_ms = 200; collector->initialize(config, warnConfig); std::vector testAircraft = { createTestAircraft("TEST1", 36.354483470, 120.08502054), // 参考点,转换后是 (0, 0) createTestAircraft("TEST2", 36.354483470 + 0.0002 * std::cos(68.53 * M_PI / 180.0), 120.08502054 + 0.0002 * std::sin(68.53 * M_PI / 180.0)) // 沿机场方向偏移约 20m }; std::vector testVehicles = { createTestVehicle("VEH1", 36.354483470, 120.08502054), // 参考点,转换后是 (0, 0) createTestVehicle("VEH2", 36.354483470 - 0.0002 * std::cos(68.53 * M_PI / 180.0), 120.08502054 - 0.0002 * std::sin(68.53 * M_PI / 180.0)) // 沿机场方向反向偏移约 20m }; std::vector testSignals = { createTestTrafficLight("TL001", 0), createTestTrafficLight("TL002", 1) }; // 设置 Mock 数据返回 EXPECT_CALL(*mockSource, fetchPositionAircraftData(::testing::_)) .WillRepeatedly(::testing::DoAll( ::testing::SetArgReferee<0>(testAircraft), ::testing::Return(true) )); EXPECT_CALL(*mockSource, fetchPositionVehicleData(::testing::_)) .WillRepeatedly(::testing::DoAll( ::testing::SetArgReferee<0>(testVehicles), ::testing::Return(true) )); EXPECT_CALL(*mockSource, fetchTrafficLightSignals(::testing::_)) .WillRepeatedly(::testing::DoAll( ::testing::SetArgReferee<0>(testSignals), ::testing::Return(true) )); std::string testStatus = "NORMAL"; EXPECT_CALL(*mockSource, fetchUnmannedVehicleStatus(::testing::_, ::testing::_)) .WillRepeatedly(::testing::DoAll( ::testing::SetArgReferee<1>(testStatus), ::testing::Return(true) )); // 启动数据采集 collector->start(); // 等待数据更新(至少 1000ms,确保数据被采集) std::this_thread::sleep_for(std::chrono::milliseconds(1000)); // 获取最新数据 auto [aircraft, vehicles, traffic_lights] = collector->getLatestData(); auto [aircraft_ts, vehicle_ts, traffic_light_ts] = collector->getLastUpdateTimestamps(); // 验证数据 EXPECT_EQ(aircraft.size(), 2); if (!aircraft.empty()) { EXPECT_EQ(aircraft[0].flightNo, "TEST1"); EXPECT_EQ(aircraft[1].flightNo, "TEST2"); } EXPECT_EQ(vehicles.size(), 2); if (!vehicles.empty()) { EXPECT_EQ(vehicles[0].vehicleNo, "VEH1"); EXPECT_EQ(vehicles[1].vehicleNo, "VEH2"); } EXPECT_EQ(traffic_lights.size(), 2); if (!traffic_lights.empty()) { EXPECT_EQ(traffic_lights[0].trafficLightId, "TL001"); EXPECT_EQ(traffic_lights[1].trafficLightId, "TL002"); } // 验证时间戳 EXPECT_GT(aircraft_ts, 0); EXPECT_GT(vehicle_ts, 0); EXPECT_GT(traffic_light_ts, 0); // 停止数据采集 collector->stop(); } // 测试数据采集循环 TEST_F(DataCollectorTest, DataCollectionLoop) { std::vector testAircraft = { createTestAircraft("TEST1", 36.354483470, 120.08502054) // 参考点 }; std::vector testVehicles = { createTestVehicle("VEH1", 36.354483470, 120.08502054) // 参考点 }; // 设置 Mock 数据返回 EXPECT_CALL(*mockSource, fetchPositionAircraftData(::testing::_)) .WillRepeatedly(::testing::DoAll( ::testing::SetArgReferee<0>(testAircraft), ::testing::Return(true) )); EXPECT_CALL(*mockSource, fetchPositionVehicleData(::testing::_)) .WillRepeatedly(::testing::DoAll( ::testing::SetArgReferee<0>(testVehicles), ::testing::Return(true) )); // 启动采集 collector->start(); // 等待数据采集 std::this_thread::sleep_for(std::chrono::seconds(2)); // 停止采集 collector->stop(); // 验证数据 auto aircraft = collector->getAircraftData(); EXPECT_EQ(aircraft.size(), 1); auto vehicles = collector->getVehicleData(); EXPECT_EQ(vehicles.size(), 1); } // 测试错误处理 TEST_F(DataCollectorTest, ErrorHandling) { // 设置 Mock 返回错误 EXPECT_CALL(*mockSource, fetchPositionAircraftData(::testing::_)) .WillRepeatedly(::testing::Return(false)); EXPECT_CALL(*mockSource, fetchPositionVehicleData(::testing::_)) .WillRepeatedly(::testing::Return(false)); // 启动数据采集 collector->start(); // 等待数据更新(至少三个采集周期) std::this_thread::sleep_for(std::chrono::milliseconds( dataSourceConfig_.position.refresh_interval_ms * 3)); // 获取最新数据 auto [aircraft, vehicles, traffic_lights] = collector->getLatestData(); // 验证数据为空 EXPECT_TRUE(aircraft.empty()); EXPECT_TRUE(vehicles.empty()); // 停止数据采集 collector->stop(); } // 测试红绿灯信号获取 TEST_F(DataCollectorTest, TrafficLightSignalsTest) { std::vector testSignals = { createTestTrafficLight("TL001", 0), // RED = 0 createTestTrafficLight("TL002", 1), // GREEN = 1 createTestTrafficLight("TL003", 2) // YELLOW = 2 }; // 设置 Mock 数据返回 EXPECT_CALL(*mockSource, fetchTrafficLightSignals(::testing::_)) .WillRepeatedly(::testing::DoAll( ::testing::SetArgReferee<0>(testSignals), ::testing::Return(true) )); // 启动数据采集 collector->start(); // 等待数据更新(至少三个采集周期) std::this_thread::sleep_for(std::chrono::milliseconds( dataSourceConfig_.position.refresh_interval_ms * 3)); // 验证数据 auto signals = collector->getTrafficLightSignals(); EXPECT_EQ(signals.size(), 3); if (signals.size() >= 3) { EXPECT_EQ(signals[0].trafficLightId, "TL001"); EXPECT_EQ(signals[0].ns_status, SignalStatus::RED); // RED = 0 EXPECT_EQ(signals[1].trafficLightId, "TL002"); EXPECT_EQ(signals[1].ns_status, SignalStatus::GREEN); // GREEN = 1 } // 停止数据采集 collector->stop(); } // 测试红绿灯信号错误处理 TEST_F(DataCollectorTest, TrafficLightSignalsErrorTest) { // 设置 Mock 返回错误 EXPECT_CALL(*mockSource, fetchTrafficLightSignals(::testing::_)) .WillRepeatedly(::testing::Return(false)); // 启动数据采集 collector->start(); // 等待数据更新(至少三个采集周期) std::this_thread::sleep_for(std::chrono::milliseconds( dataSourceConfig_.position.refresh_interval_ms * 3)); // 验证数据为空 auto signals = collector->getTrafficLightSignals(); EXPECT_TRUE(signals.empty()); // 停止数据采集 collector->stop(); } // 测试连接健康检查和超时告警 TEST_F(DataCollectorTest, ConnectionHealthAndTimeout) { DataSourceConfig dataSourceConfig; // 设置位置数据配置 dataSourceConfig.position.host = "localhost"; dataSourceConfig.position.port = 8080; dataSourceConfig.position.timeout_ms = 1000; // 1秒超时 dataSourceConfig.position.read_timeout_ms = 500; // 0.5秒读取超时 dataSourceConfig.position.refresh_interval_ms = 100; // 100ms刷新间隔 WarnConfig warnConfig; warnConfig.warning_interval_ms = 500; // 500ms告警间隔 collector->initialize(dataSourceConfig, warnConfig); // 模拟连接健康检查失败 EXPECT_CALL(*mockSource, isAvailable()) .WillRepeatedly(::testing::Return(false)); // 模拟数据获取失败 EXPECT_CALL(*mockSource, fetchPositionAircraftData(::testing::_)) .WillRepeatedly(::testing::Return(false)); EXPECT_CALL(*mockSource, fetchPositionVehicleData(::testing::_)) .WillRepeatedly(::testing::Return(false)); // 启动采集 collector->start(); // 等待超过超时时间 std::this_thread::sleep_for(std::chrono::milliseconds(1500)); // 停止采集 collector->stop(); // 验证数据为空 auto aircraft = collector->getAircraftData(); EXPECT_TRUE(aircraft.empty()); auto vehicles = collector->getVehicleData(); EXPECT_TRUE(vehicles.empty()); } // 测试连接恢复 TEST_F(DataCollectorTest, ConnectionRecovery) { DataSourceConfig config; // 设置位置数据配置 config.position.host = "localhost"; config.position.port = 8080; config.position.refresh_interval_ms = 100; config.position.timeout_ms = 1000; config.position.read_timeout_ms = 500; // 设置无人车数据配置 config.vehicle.host = "localhost"; config.vehicle.port = 8081; config.vehicle.refresh_interval_ms = 100; config.vehicle.timeout_ms = 1000; config.vehicle.read_timeout_ms = 500; // 设置红绿灯数据配置 config.traffic_light.host = "localhost"; config.traffic_light.port = 8082; config.traffic_light.refresh_interval_ms = 100; config.traffic_light.timeout_ms = 1000; config.traffic_light.read_timeout_ms = 500; WarnConfig warnConfig; warnConfig.warning_interval_ms = 200; collector->initialize(config, warnConfig); std::vector testAircraft = { createTestAircraft("TEST1", 36.354483470, 120.08502054) // 参考点 }; // 设置 Mock 行为: 前两次失败,然后成功 EXPECT_CALL(*mockSource, fetchPositionAircraftData(::testing::_)) .WillOnce(::testing::Return(false)) .WillOnce(::testing::Return(false)) .WillRepeatedly(::testing::DoAll( ::testing::SetArgReferee<0>(testAircraft), ::testing::Return(true) )); // 添加车辆数据的 mock 行为 std::vector testVehicles; EXPECT_CALL(*mockSource, fetchPositionVehicleData(::testing::_)) .WillOnce(::testing::Return(false)) .WillOnce(::testing::Return(false)) .WillRepeatedly(::testing::DoAll( ::testing::SetArgReferee<0>(testVehicles), ::testing::Return(true) )); // 设置无人车数据 Mock 行为 std::string testStatus = "NORMAL"; EXPECT_CALL(*mockSource, fetchUnmannedVehicleStatus(::testing::_, ::testing::_)) .WillOnce(::testing::Return(false)) .WillOnce(::testing::Return(false)) .WillRepeatedly(::testing::DoAll( ::testing::SetArgReferee<1>(testStatus), ::testing::Return(true) )); // 设置红绿灯数据 Mock 行为 std::vector testSignals = { createTestTrafficLight("TL001", 0) }; EXPECT_CALL(*mockSource, fetchTrafficLightSignals(::testing::_)) .WillOnce(::testing::Return(false)) .WillOnce(::testing::Return(false)) .WillRepeatedly(::testing::DoAll( ::testing::SetArgReferee<0>(testSignals), ::testing::Return(true) )); // 启动数据采集 collector->start(); // 等待足够长的时间以确保连接恢复 std::this_thread::sleep_for(std::chrono::milliseconds(1000)); // 获取最新数据 auto [aircraft, vehicles, traffic_lights] = collector->getLatestData(); // 验证数据 EXPECT_EQ(aircraft.size(), 1); if (!aircraft.empty()) { EXPECT_EQ(aircraft[0].flightNo, "TEST1"); } // 验证红绿灯数据 EXPECT_EQ(traffic_lights.size(), 1); if (!traffic_lights.empty()) { EXPECT_EQ(traffic_lights[0].trafficLightId, "TL001"); } // 停止数据采集 collector->stop(); } // 测试长连接下的数据获取 TEST_F(DataCollectorTest, LongConnectionDataFetch) { DataSourceConfig dataSourceConfig; // 设置位置数据配置 dataSourceConfig.position.host = "localhost"; dataSourceConfig.position.port = 8080; dataSourceConfig.position.refresh_interval_ms = 100; dataSourceConfig.position.timeout_ms = 1000; dataSourceConfig.position.read_timeout_ms = 500; collector->initialize(dataSourceConfig, WarnConfig{}); std::vector testAircraft = { createTestAircraft("TEST1", 36.354483470, 120.08502054), // 参考点,转换后是 (0, 0) createTestAircraft("TEST2", 36.354483470 + 0.0002 * std::cos(68.53 * M_PI / 180.0), 120.08502054 + 0.0002 * std::sin(68.53 * M_PI / 180.0)) // 沿机场方向偏移约 20m }; std::vector testVehicles = { createTestVehicle("VEH1", 36.354483470, 120.08502054), // 参考点,转换后是 (0, 0) createTestVehicle("VEH2", 36.354483470 - 0.0002 * std::cos(68.53 * M_PI / 180.0), 120.08502054 - 0.0002 * std::sin(68.53 * M_PI / 180.0)) // 沿机场方向反向偏移约 20m }; std::vector testSignals = { createTestTrafficLight("TL001", 0) }; // 模拟连接保持可用 EXPECT_CALL(*mockSource, isAvailable()) .WillRepeatedly(::testing::Return(true)); // 模拟多次成功获取数据 EXPECT_CALL(*mockSource, fetchPositionAircraftData(::testing::_)) .Times(::testing::AtLeast(3)) .WillRepeatedly(::testing::DoAll( ::testing::SetArgReferee<0>(testAircraft), ::testing::Return(true) )); // 添加其他数据源的 mock 行为 EXPECT_CALL(*mockSource, fetchPositionVehicleData(::testing::_)) .WillRepeatedly(::testing::DoAll( ::testing::SetArgReferee<0>(testVehicles), ::testing::Return(true) )); EXPECT_CALL(*mockSource, fetchTrafficLightSignals(::testing::_)) .WillRepeatedly(::testing::DoAll( ::testing::SetArgReferee<0>(testSignals), ::testing::Return(true) )); // 添加无人车状态获取的 mock 行为 std::string testStatus = "NORMAL"; EXPECT_CALL(*mockSource, fetchUnmannedVehicleStatus(::testing::_, ::testing::_)) .WillRepeatedly(::testing::DoAll( ::testing::SetArgReferee<1>(testStatus), ::testing::Return(true) )); // 启动采集 collector->start(); // 等待多个刷新周期 std::this_thread::sleep_for(std::chrono::milliseconds(500)); // 增加等待时间确保执行次数 // 验证数据 auto aircraft = collector->getAircraftData(); EXPECT_FALSE(aircraft.empty()); if (!aircraft.empty()) { EXPECT_EQ(aircraft[0].flightNo, "TEST1"); } auto vehicles = collector->getVehicleData(); EXPECT_FALSE(vehicles.empty()); if (!vehicles.empty()) { EXPECT_EQ(vehicles[0].vehicleNo, "VEH1"); } auto signals = collector->getTrafficLightSignals(); EXPECT_FALSE(signals.empty()); if (!signals.empty()) { EXPECT_EQ(signals[0].trafficLightId, "TL001"); } // 停止采集 collector->stop(); } TEST_F(DataCollectorTest, InitializeWithTimeoutConfig) { DataSourceConfig config; // 设置位置数据配置 config.position.host = "localhost"; config.position.port = 8080; config.position.timeout_ms = 5000; // 连接超时 5 秒 config.position.read_timeout_ms = 2000; // 读取超时 2 秒 config.position.refresh_interval_ms = 100; WarnConfig warnConfig; warnConfig.warning_interval_ms = 500; EXPECT_NO_THROW(collector->initialize(config, warnConfig)); } TEST_F(DataCollectorTest, TimeoutWarningTest) { DataSourceConfig config; // 设置位置数据配置 config.position.host = "localhost"; config.position.port = 8080; config.position.timeout_ms = 1000; // 连接超时 1 秒 config.position.read_timeout_ms = 500; // 读取超时 0.5 秒 config.position.refresh_interval_ms = 100; WarnConfig warnConfig; warnConfig.warning_interval_ms = 200; // 警告间隔 0.2 秒 collector->initialize(config, warnConfig); // 模拟连接成功但读取超时 EXPECT_CALL(*mockSource, isAvailable()) .WillRepeatedly(::testing::Return(true)); EXPECT_CALL(*mockSource, fetchPositionAircraftData(::testing::_)) .WillRepeatedly(::testing::Return(false)); // 持续读取超时 // 启动采集 collector->start(); // 等待足够长的时间以触发多次警告 std::this_thread::sleep_for(std::chrono::milliseconds(1000)); // 停止采集 collector->stop(); } // 测试超时警告机制 TEST_F(DataCollectorTest, TimeoutWarningMechanism) { DataSourceConfig config; // 设置位置数据配置 config.position.host = "localhost"; config.position.port = 8080; config.position.timeout_ms = 200; // 连接超时 200ms config.position.read_timeout_ms = 100; // 读取超时 100ms config.position.refresh_interval_ms = 10; WarnConfig warnConfig; warnConfig.warning_interval_ms = 50; // 警告间隔 50ms // 创建一个计数器来记录收到的警告数量 int warningCount = 0; // 创建一个 mock System 来捕获警告 class MockSystem : public System { public: MOCK_METHOD1(broadcastTimeoutWarning, void(const network::TimeoutWarningMessage&)); }; auto mockSystem = std::make_shared(); // 设置期望接收到超时警告 EXPECT_CALL(*mockSystem, broadcastTimeoutWarning(::testing::_)) .WillRepeatedly(::testing::Invoke([&warningCount](const network::TimeoutWarningMessage& warning) { warningCount++; // 验证警告消息的内容 EXPECT_THAT(warning.source, ::testing::AnyOf( ::testing::StrEq("position"), ::testing::StrEq("unmanned"), ::testing::StrEq("traffic_light") )); EXPECT_GT(warning.elapsed_ms, 0); })); // 设置 mock system 到 collector collector->setSystem(mockSystem); collector->initialize(config, warnConfig); // 启动采集器 collector->start(); // 模拟所有数据源获取失败 EXPECT_CALL(*mockSource, fetchPositionAircraftData(::testing::_)) .WillRepeatedly(::testing::Return(false)); EXPECT_CALL(*mockSource, fetchPositionVehicleData(::testing::_)) .WillRepeatedly(::testing::Return(false)); EXPECT_CALL(*mockSource, fetchTrafficLightSignals(::testing::_)) .WillRepeatedly(::testing::Return(false)); // 等待足够长的时间以确保警告被发送 std::this_thread::sleep_for(std::chrono::milliseconds(300)); // 停止采集器 collector->stop(); // 验证是否收到了警告 EXPECT_GT(warningCount, 0); } // 测试读取超时机制 TEST_F(DataCollectorTest, ReadTimeoutMechanism) { DataSourceConfig config; // 设置位置数据配置 config.position.host = "localhost"; config.position.port = 8080; config.position.timeout_ms = 1000; // 连接超时 1000ms config.position.read_timeout_ms = 500; // 读取超时 500ms config.position.refresh_interval_ms = 100; // 设置无人车数据配置 config.vehicle.host = "localhost"; config.vehicle.port = 8081; config.vehicle.timeout_ms = 1000; config.vehicle.read_timeout_ms = 500; config.vehicle.refresh_interval_ms = 100; // 设置红绿灯数据配置 config.traffic_light.host = "localhost"; config.traffic_light.port = 8082; config.traffic_light.timeout_ms = 1000; config.traffic_light.read_timeout_ms = 500; config.traffic_light.refresh_interval_ms = 100; WarnConfig warnConfig; warnConfig.warning_interval_ms = 200; // 警告间隔 200ms // 创建一个计数器来记录收到的警告数量 int warningCount = 0; // 创建一个 mock System 来捕获警告 class MockSystem : public System { public: MOCK_METHOD1(broadcastTimeoutWarning, void(const network::TimeoutWarningMessage&)); }; auto mockSystem = std::make_shared(); // 设置期望接收到超时警告 EXPECT_CALL(*mockSystem, broadcastTimeoutWarning(::testing::_)) .WillRepeatedly(::testing::Invoke([&warningCount](const network::TimeoutWarningMessage& warning) { warningCount++; // 验证警告消息的内容 EXPECT_THAT(warning.source, ::testing::AnyOf( ::testing::StrEq("position"), ::testing::StrEq("unmanned"), ::testing::StrEq("traffic_light") )); EXPECT_GT(warning.elapsed_ms, 0); EXPECT_TRUE(warning.is_read_timeout); })); // 设置 mock system 到 collector collector->setSystem(mockSystem); collector->initialize(config, warnConfig); // 启动采集器 collector->start(); // 模拟所有数据源获取失败 EXPECT_CALL(*mockSource, fetchPositionAircraftData(::testing::_)) .WillRepeatedly(::testing::Return(false)); EXPECT_CALL(*mockSource, fetchPositionVehicleData(::testing::_)) .WillRepeatedly(::testing::Return(false)); EXPECT_CALL(*mockSource, fetchTrafficLightSignals(::testing::_)) .WillRepeatedly(::testing::Return(false)); EXPECT_CALL(*mockSource, fetchUnmannedVehicleStatus(::testing::_, ::testing::_)) .WillRepeatedly(::testing::Return(false)); // 等待足够长的时间以确保警告被发送 std::this_thread::sleep_for(std::chrono::milliseconds(1500)); // 停止采集器 collector->stop(); // 验证是否收到了警告 EXPECT_GT(warningCount, 0); } // 添加新的测试用例:测试边界外数据过滤 TEST_F(DataCollectorTest, OutOfBoundsDataFiltering) { DataSourceConfig dataSourceConfig; WarnConfig warnConfig; EXPECT_TRUE(collector->initialize(dataSourceConfig, warnConfig)); // 创建测试数据:混合边界内外的数据 const auto& refPoint = SystemConfig::instance().airport.reference_point; // 创建边界内的航空器 std::vector testAircraft = { createTestAircraft("IN_BOUNDS_1", refPoint.latitude, refPoint.longitude), // 参考点 createTestAircraft("IN_BOUNDS_2", refPoint.latitude + 0.001 * std::cos(68.53 * M_PI / 180.0), // 沿机场方向偏移约 100m refPoint.longitude + 0.001 * std::sin(68.53 * M_PI / 180.0)), createOutOfBoundsAircraft("OUT_BOUNDS_1"), // 边界外偏移约 3km createOutOfBoundsAircraft("OUT_BOUNDS_2") // 边界外偏移约 3km }; // 创建边界内的车辆 std::vector testVehicles = { createTestVehicle("VEH_IN_1", refPoint.latitude, refPoint.longitude), // 参考点 createTestVehicle("VEH_IN_2", refPoint.latitude + 0.001 * std::cos(68.53 * M_PI / 180.0), // 沿机场方向偏移约 100m refPoint.longitude + 0.001 * std::sin(68.53 * M_PI / 180.0)), createOutOfBoundsVehicle("VEH_OUT_1"), // 边界外偏移约 2.5km createOutOfBoundsVehicle("VEH_OUT_2") // 边界外偏移约 2.5km }; // 设置 Mock 数据返回 EXPECT_CALL(*mockSource, fetchPositionAircraftData(::testing::_)) .WillOnce(::testing::DoAll( ::testing::SetArgReferee<0>(testAircraft), ::testing::Return(true) )); EXPECT_CALL(*mockSource, fetchPositionVehicleData(::testing::_)) .WillOnce(::testing::DoAll( ::testing::SetArgReferee<0>(testVehicles), ::testing::Return(true) )); // 执行刷新 collector->fetchPositionData(); // 验证过滤结果 const auto& filteredAircraft = collector->getAircraftData(); const auto& filteredVehicles = collector->getVehicleData(); // 检查过滤后的数量 EXPECT_EQ(filteredAircraft.size(), 2) << "应该只保留2架在边界内的航空器"; EXPECT_EQ(filteredVehicles.size(), 2) << "应该只保留2辆在边界内的车辆"; // 检查保留的是正确的航空器 if (filteredAircraft.size() >= 2) { EXPECT_EQ(filteredAircraft[0].flightNo, "IN_BOUNDS_1"); EXPECT_EQ(filteredAircraft[1].flightNo, "IN_BOUNDS_2"); } // 检查保留的是正确的车辆 if (filteredVehicles.size() >= 2) { EXPECT_EQ(filteredVehicles[0].vehicleNo, "VEH_IN_1"); EXPECT_EQ(filteredVehicles[1].vehicleNo, "VEH_IN_2"); } }