#include #include "alert_manager.hpp" #include #include // 辅助类:用于捕获标准输出和标准错误输出 class StreamCapture { public: StreamCapture() : old_cout_(std::cout.rdbuf()), old_cerr_(std::cerr.rdbuf()) { std::cout.rdbuf(ss_cout_.rdbuf()); std::cerr.rdbuf(ss_cerr_.rdbuf()); } ~StreamCapture() { std::cout.rdbuf(old_cout_); std::cerr.rdbuf(old_cerr_); } std::string getCout() const { return ss_cout_.str(); } std::string getCerr() const { return ss_cerr_.str(); } private: std::stringstream ss_cout_; std::stringstream ss_cerr_; std::streambuf* old_cout_; std::streambuf* old_cerr_; }; // 测试夹具:为每个测试用例创建独立的 AlertManager 实例 class AlertManagerTest : public ::testing::Test { protected: void SetUp() override { manager.initialize(); } void TearDown() override { manager.resetAllAlerts(); } AlertManager manager; }; // ==================== checkAltitudeAlert 测试 ==================== // 正常输入测试:高度在阈值范围内,不应触发任何预警 TEST_F(AlertManagerTest, testCheckAltitudeAlertNormalRange) { StreamCapture capture; // 默认阈值:上限100.0,下限-50.0 // 测试正常高度 50.0 manager.checkAltitudeAlert(50.0f, 1000); EXPECT_FALSE(manager.hasActiveAlerts()); EXPECT_FALSE(manager.hasUnacknowledgedAlerts()); // 测试接近上限但未超过 manager.checkAltitudeAlert(99.9f, 1001); EXPECT_FALSE(manager.hasActiveAlerts()); // 测试接近下限但未低于 manager.checkAltitudeAlert(-49.9f, 1002); EXPECT_FALSE(manager.hasActiveAlerts()); } // 边界值测试:高度刚好等于阈值,不应触发预警 TEST_F(AlertManagerTest, testCheckAltitudeAlertAtThreshold) { StreamCapture capture; // 测试高度等于上限 manager.checkAltitudeAlert(100.0f, 2000); EXPECT_FALSE(manager.hasActiveAlerts()); // 测试高度等于下限 manager.checkAltitudeAlert(-50.0f, 2001); EXPECT_FALSE(manager.hasActiveAlerts()); } // 边界值测试:高度超过上限,应触发 ALTITUDE_UPPER 预警 TEST_F(AlertManagerTest, testCheckAltitudeAlertExceedsUpper) { StreamCapture capture; // 高度超过上限 manager.checkAltitudeAlert(150.0f, 3000); EXPECT_TRUE(manager.hasActiveAlerts()); EXPECT_TRUE(manager.hasUnacknowledgedAlerts()); auto activeAlerts = manager.getActiveAlerts(); ASSERT_EQ(1, activeAlerts.size()); EXPECT_EQ(AlertType::ALTITUDE_UPPER, activeAlerts[0].type); EXPECT_EQ(AlertStatus::ACTIVE, activeAlerts[0].status); EXPECT_EQ(3000, activeAlerts[0].trigger_time); // 验证输出包含预警信息 std::string coutOutput = capture.getCout(); EXPECT_NE(std::string::npos, coutOutput.find("高度上限预警")); EXPECT_NE(std::string::npos, coutOutput.find("150")); } // 边界值测试:高度低于下限,应触发 ALTITUDE_LOWER 预警 TEST_F(AlertManagerTest, testCheckAltitudeAlertBelowLower) { StreamCapture capture; // 高度低于下限 manager.checkAltitudeAlert(-100.0f, 4000); EXPECT_TRUE(manager.hasActiveAlerts()); EXPECT_TRUE(manager.hasUnacknowledgedAlerts()); auto activeAlerts = manager.getActiveAlerts(); ASSERT_EQ(1, activeAlerts.size()); EXPECT_EQ(AlertType::ALTITUDE_LOWER, activeAlerts[0].type); EXPECT_EQ(AlertStatus::ACTIVE, activeAlerts[0].status); EXPECT_EQ(4000, activeAlerts[0].trigger_time); // 验证输出包含预警信息 std::string coutOutput = capture.getCout(); EXPECT_NE(std::string::npos, coutOutput.find("高度下限预警")); EXPECT_NE(std::string::npos, coutOutput.find("-100")); } // 特殊场景测试:高度超过上限后恢复正常,预警应解除 TEST_F(AlertManagerTest, testCheckAltitudeAlertUpperResolved) { StreamCapture capture; // 先触发上限预警 manager.checkAltitudeAlert(150.0f, 5000); EXPECT_TRUE(manager.hasActiveAlerts()); // 高度恢复正常 manager.checkAltitudeAlert(80.0f, 5001); // 预警应被解决 EXPECT_FALSE(manager.hasActiveAlerts()); EXPECT_FALSE(manager.hasUnacknowledgedAlerts()); // 验证历史记录中存在已解决的预警 auto history = manager.getAlertHistory(10); bool foundResolved = false; for (const auto& alert : history) { if (alert.type == AlertType::ALTITUDE_UPPER && alert.status == AlertStatus::RESOLVED) { foundResolved = true; break; } } EXPECT_TRUE(foundResolved); } // 特殊场景测试:高度低于下限后恢复正常,预警应解除 TEST_F(AlertManagerTest, testCheckAltitudeAlertLowerResolved) { StreamCapture capture; // 先触发下限预警 manager.checkAltitudeAlert(-100.0f, 6000); EXPECT_TRUE(manager.hasActiveAlerts()); // 高度恢复正常 manager.checkAltitudeAlert(0.0f, 6001); // 预警应被解决 EXPECT_FALSE(manager.hasActiveAlerts()); EXPECT_FALSE(manager.hasUnacknowledgedAlerts()); // 验证历史记录 auto history = manager.getAlertHistory(10); bool foundResolved = false; for (const auto& alert : history) { if (alert.type == AlertType::ALTITUDE_LOWER && alert.status == AlertStatus::RESOLVED) { foundResolved = true; break; } } EXPECT_TRUE(foundResolved); } // 特殊场景测试:同时超过上下限(理论上不可能,但测试逻辑完整性) TEST_F(AlertManagerTest, testCheckAltitudeAlertBothThresholds) { StreamCapture capture; // 修改阈值使上下限重叠(通过 setAltitudeThresholds 会校验,这里直接测试逻辑) // 注意:此测试仅验证 checkAltitudeAlert 的逻辑,不依赖阈值设置 // 先触发上限预警 manager.checkAltitudeAlert(150.0f, 7000); EXPECT_TRUE(manager.hasActiveAlerts()); // 再触发下限预警(此时高度低于下限) manager.checkAltitudeAlert(-100.0f, 7001); // 应有 2 个活动预警 auto activeAlerts = manager.getActiveAlerts(); EXPECT_EQ(2, activeAlerts.size()); } // 异常输入测试:高度为 NaN(如果支持) TEST_F(AlertManagerTest, testCheckAltitudeAlertNaN) { StreamCapture capture; // 使用 NaN 值(如果编译器支持) float nanValue = std::numeric_limits::quiet_NaN(); // NaN 与任何值的比较结果都是 false,因此不会触发预警 manager.checkAltitudeAlert(nanValue, 8000); // 不应触发任何预警 EXPECT_FALSE(manager.hasActiveAlerts()); } // 异常输入测试:高度为无穷大 TEST_F(AlertManagerTest, testCheckAltitudeAlertInfinity) { StreamCapture capture; float infValue = std::numeric_limits::infinity(); // 正无穷应触发上限预警 manager.checkAltitudeAlert(infValue, 9000); EXPECT_TRUE(manager.hasActiveAlerts()); auto activeAlerts = manager.getActiveAlerts(); ASSERT_EQ(1, activeAlerts.size()); EXPECT_EQ(AlertType::ALTITUDE_UPPER, activeAlerts[0].type); } // 异常输入测试:高度为负无穷 TEST_F(AlertManagerTest, testCheckAltitudeAlertNegativeInfinity) { StreamCapture capture; float negInfValue = -std::numeric_limits::infinity(); // 负无穷应触下限预警 manager.checkAltitudeAlert(negInfValue, 10000); EXPECT_TRUE(manager.hasActiveAlerts()); auto activeAlerts = manager.getActiveAlerts(); ASSERT_EQ(1, activeAlerts.size()); EXPECT_EQ(AlertType::ALTITUDE_LOWER, activeAlerts[0].type); } // 特殊场景测试:时间戳为 0 TEST_F(AlertManagerTest, testCheckAltitudeAlertTimestampZero) { StreamCapture capture; // 时间戳为 0 不应影响预警逻辑 manager.checkAltitudeAlert(150.0f, 0); EXPECT_TRUE(manager.hasActiveAlerts()); auto activeAlerts = manager.getActiveAlerts(); ASSERT_EQ(1, activeAlerts.size()); EXPECT_EQ(0, activeAlerts[0].trigger_time); } // 特殊场景测试:连续多次触发同一预警,不应重复触发 TEST_F(AlertManagerTest, testCheckAltitudeAlertDuplicateTrigger) { StreamCapture capture; // 第一次触发 manager.checkAltitudeAlert(150.0f, 11000); EXPECT_TRUE(manager.hasActiveAlerts()); // 第二次触发(高度仍然超过上限) manager.checkAltitudeAlert(200.0f, 11001); // 应仍只有 1 个活动预警 auto activeAlerts = manager.getActiveAlerts(); ASSERT_EQ(1, activeAlerts.size()); // 验证历史记录中只有 1 次触发 auto history = manager.getAlertHistory(10); int triggerCount = 0; for (const auto& alert : history) { if (alert.type == AlertType::ALTITUDE_UPPER && alert.status == AlertStatus::ACTIVE) { triggerCount++; } } EXPECT_EQ(1, triggerCount); } // ==================== setAltitudeThresholds 测试 ==================== // 正常输入测试:设置有效的上下限阈值 TEST_F(AlertManagerTest, testSetAltitudeThresholdsValid) { StreamCapture capture; manager.setAltitudeThresholds(200.0f, -100.0f); // 验证输出 std::string coutOutput = capture.getCout(); EXPECT_NE(std::string::npos, coutOutput.find("预警阈值已更新")); EXPECT_NE(std::string::npos, coutOutput.find("200")); EXPECT_NE(std::string::npos, coutOutput.find("-100")); // 验证新阈值生效 manager.checkAltitudeAlert(150.0f, 12000); EXPECT_FALSE(manager.hasActiveAlerts()); manager.checkAltitudeAlert(250.0f, 12001); EXPECT_TRUE(manager.hasActiveAlerts()); } // 边界值测试:设置上限等于下限(非法) TEST_F(AlertManagerTest, testSetAltitudeThresholdsEqual) { StreamCapture capture; manager.setAltitudeThresholds(100.0f, 100.0f); // 验证错误输出 std::string cerrOutput = capture.getCerr(); EXPECT_NE(std::string::npos, cerrOutput.find("上限阈值必须大于下限阈值")); // 验证阈值未改变 manager.checkAltitudeAlert(150.0f, 13000); EXPECT_TRUE(manager.hasActiveAlerts()); } // 异常输入测试:设置上限小于下限(非法) TEST_F(AlertManagerTest, testSetAltitudeThresholdsUpperLessThanLower) { StreamCapture capture; manager.setAltitudeThresholds(-50.0f, 100.0f); // 验证错误输出 std::string cerrOutput = capture.getCerr(); EXPECT_NE(std::string::npos, cerrOutput.find("上限阈值必须大于下限阈值")); // 验证阈值未改变 manager.checkAltitudeAlert(150.0f, 14000); EXPECT_TRUE(manager.hasActiveAlerts()); } // 边界值测试:设置非常大的阈值范围 TEST_F(AlertManagerTest, testSetAltitudeThresholdsLargeRange) { StreamCapture capture; float largeUpper = 1000000.0f; float largeLower = -1000000.0f; manager.setAltitudeThresholds(largeUpper, largeLower); // 验证阈值设置成功 manager.checkAltitudeAlert(500000.0f, 15000); EXPECT_FALSE(manager.hasActiveAlerts()); manager.checkAltitudeAlert(2000000.0f, 15001); EXPECT_TRUE(manager.hasActiveAlerts()); } // 边界值测试:设置非常小的阈值范围 TEST_F(AlertManagerTest, testSetAltitudeThresholdsSmallRange) { StreamCapture capture; float smallUpper = 0.001f; float smallLower = -0.001f; manager.setAltitudeThresholds(smallUpper, smallLower); // 验证阈值设置成功 manager.checkAltitudeAlert(0.0005f, 16000); EXPECT_FALSE(manager.hasActiveAlerts()); manager.checkAltitudeAlert(0.002f, 16001); EXPECT_TRUE(manager.hasActiveAlerts()); } // 特殊场景测试:设置阈值后,原有的活动预警应被重置 TEST_F(AlertManagerTest, testSetAltitudeThresholdsResetsAlerts) { StreamCapture capture; // 先触发一个预警 manager.checkAltitudeAlert(150.0f, 17000); EXPECT_TRUE(manager.hasActiveAlerts()); // 修改阈值 manager.setAltitudeThresholds(200.0f, -100.0f); // 原有的预警应被重置(解决) EXPECT_FALSE(manager.hasActiveAlerts()); // 验证历史记录中存在已解决的预警 auto history = manager.getAlertHistory(10); bool foundResolved = false; for (const auto& alert : history) { if (alert.type == AlertType::ALTITUDE_UPPER && alert.status == AlertStatus::RESOLVED) { foundResolved = true; break; } } EXPECT_TRUE(foundResolved); } // 特殊场景测试:连续设置阈值,验证状态一致性 TEST_F(AlertManagerTest, testSetAltitudeThresholdsMultipleTimes) { StreamCapture capture; // 第一次设置 manager.setAltitudeThresholds(200.0f, -100.0f); // 触发预警 manager.checkAltitudeAlert(250.0f, 18000); EXPECT_TRUE(manager.hasActiveAlerts()); // 第二次设置 manager.setAltitudeThresholds(300.0f, -200.0f); // 原有预警被重置 EXPECT_FALSE(manager.hasActiveAlerts()); // 新阈值下,原来的高度不再触发预警 manager.checkAltitudeAlert(250.0f, 18001); EXPECT_FALSE(manager.hasActiveAlerts()); } // 特殊场景测试:设置阈值后立即检查高度 TEST_F(AlertManagerTest, testSetAltitudeThresholdsImmediateCheck) { StreamCapture capture; // 设置新阈值 manager.setAltitudeThresholds(50.0f, -10.0f); // 立即检查高度,应触发预警 manager.checkAltitudeAlert(60.0f, 19000); EXPECT_TRUE(manager.hasActiveAlerts()); auto activeAlerts = manager.getActiveAlerts(); ASSERT_EQ(1, activeAlerts.size()); EXPECT_EQ(AlertType::ALTITUDE_UPPER, activeAlerts[0].type); }