#include "gtest/gtest.h" #include "alert_manager.hpp" #include #include // Mock time function for deterministic testing uint32_t mock_timestamp = 1640995200; // 2022-01-01 00:00:00 UTC // Mock the time function to return a fixed value uint32_t getMockTimestamp() { return mock_timestamp; } // Override the triggerAlert and updateAlertStatus methods for testing void AlertManager::triggerAlert(AlertType type, uint32_t timestamp, const std::string& description) { AlertInfo alert; alert.type = type; alert.status = AlertStatus::ACTIVE; alert.trigger_time = timestamp; alert.description = description; alerts_[type] = alert; addToHistory(alert); } void AlertManager::updateAlertStatus(AlertType type, AlertStatus new_status, uint32_t timestamp) { auto it = alerts_.find(type); if (it == alerts_.end()) { return; } AlertInfo& alert = it->second; alert.status = new_status; switch (new_status) { case AlertStatus::ACKNOWLEDGED: alert.acknowledge_time = timestamp; break; case AlertStatus::RESOLVED: alert.resolve_time = timestamp; break; default: break; } // Update history for (auto& hist_alert : alert_history_) { if (hist_alert.type == type && hist_alert.trigger_time == alert.trigger_time) { hist_alert = alert; break; } } } // Test fixture for AlertManager class AlertManagerTest : public ::testing::Test { protected: std::unique_ptr alert_manager_; void SetUp() override { alert_manager_ = std::make_unique(); mock_timestamp = 1640995200; } void TearDown() override { alert_manager_->clearHistory(); } }; // Test checkAltitudeAlert with normal input TEST_F(AlertManagerTest, testCheckAltitudeAlertNormalInput) { // Arrange const float altitude = 120.0f; const uint32_t timestamp = getMockTimestamp(); alert_manager_->setAltitudeThresholds(100.0f, -50.0f); // Act alert_manager_->checkAltitudeAlert(altitude, timestamp); // Assert EXPECT_TRUE(alert_manager_->hasActiveAlerts()); auto active_alerts = alert_manager_->getActiveAlerts(); EXPECT_EQ(active_alerts.size(), 1); EXPECT_EQ(active_alerts[0].type, AlertType::ALTITUDE_UPPER); EXPECT_EQ(active_alerts[0].status, AlertStatus::ACTIVE); EXPECT_EQ(active_alerts[0].trigger_time, timestamp); EXPECT_EQ(active_alerts[0].description, "高度超过上限阈值:当前120米 > 阈值100米"); } // Test checkAltitudeAlert when altitude is within bounds TEST_F(AlertManagerTest, testCheckAltitudeAlertWithinBounds) { // Arrange const float altitude = 80.0f; const uint32_t timestamp = getMockTimestamp(); alert_manager_->setAltitudeThresholds(100.0f, -50.0f); // Act alert_manager_->checkAltitudeAlert(altitude, timestamp); // Assert EXPECT_FALSE(alert_manager_->hasActiveAlerts()); EXPECT_EQ(alert_manager_->getActiveAlerts().size(), 0); } // Test checkAltitudeAlert when altitude crosses lower threshold TEST_F(AlertManagerTest, testCheckAltitudeAlertLowerThresholdCrossed) { // Arrange const float altitude = -60.0f; const uint32_t timestamp = getMockTimestamp(); alert_manager_->setAltitudeThresholds(100.0f, -50.0f); // Act alert_manager_->checkAltitudeAlert(altitude, timestamp); // Assert EXPECT_TRUE(alert_manager_->hasActiveAlerts()); auto active_alerts = alert_manager_->getActiveAlerts(); EXPECT_EQ(active_alerts.size(), 1); EXPECT_EQ(active_alerts[0].type, AlertType::ALTITUDE_LOWER); EXPECT_EQ(active_alerts[0].status, AlertStatus::ACTIVE); EXPECT_EQ(active_alerts[0].trigger_time, timestamp); EXPECT_EQ(active_alerts[0].description, "高度低于下限阈值:当前-60米 < 阈值-50米"); } // Test setAltitudeThresholds with valid inputs TEST_F(AlertManagerTest, testSetAltitudeThresholdsValidInputs) { // Arrange const float upper = 150.0f; const float lower = -70.0f; // Act alert_manager_->setAltitudeThresholds(upper, lower); // Assert EXPECT_FLOAT_EQ(alert_manager_->getUpperThreshold(), upper); EXPECT_FLOAT_EQ(alert_manager_->getLowerThreshold(), lower); EXPECT_FALSE(alert_manager_->hasActiveAlerts()); } // Test setAltitudeThresholds with invalid inputs (upper <= lower) TEST_F(AlertManagerTest, testSetAltitudeThresholdsInvalidInputs) { // Arrange const float upper = 50.0f; const float lower = 100.0f; // Act & Assert EXPECT_NO_THROW(alert_manager_->setAltitudeThresholds(upper, lower)); EXPECT_TRUE(alert_manager_->hasActiveAlerts()); EXPECT_EQ(alert_manager_->getActiveAlerts().size(), 0); } // Test checkAltitudeAlert after threshold change TEST_F(AlertManagerTest, testCheckAltitudeAlertAfterThresholdChange) { // Arrange const float altitude = 120.0f; const uint32_t timestamp = getMockTimestamp(); alert_manager_->setAltitudeThresholds(100.0f, -50.0f); // Act alert_manager_->checkAltitudeAlert(altitude, timestamp); // Assert EXPECT_TRUE(alert_manager_->hasActiveAlerts()); auto active_alerts = alert_manager_->getActiveAlerts(); EXPECT_EQ(active_alerts.size(), 1); EXPECT_EQ(active_alerts[0].type, AlertType::ALTITUDE_UPPER); // Change threshold to allow altitude to be valid alert_manager_->setAltitudeThresholds(130.0f, -50.0f); // Re-check alert_manager_->checkAltitudeAlert(altitude, timestamp + 1); // Assert that alert is resolved EXPECT_FALSE(alert_manager_->hasActiveAlerts()); } // Test checkAltitudeAlert with zero altitude TEST_F(AlertManagerTest, testCheckAltitudeAlertZeroAltitude) { // Arrange const float altitude = 0.0f; const uint32_t timestamp = getMockTimestamp(); alert_manager_->setAltitudeThresholds(100.0f, -50.0f); // Act alert_manager_->checkAltitudeAlert(altitude, timestamp); // Assert EXPECT_FALSE(alert_manager_->hasActiveAlerts()); EXPECT_EQ(alert_manager_->getActiveAlerts().size(), 0); } // Test checkAltitudeAlert with extreme values TEST_F(AlertManagerTest, testCheckAltitudeAlertExtremeValues) { // Arrange const float altitude = 1e6f; // Very high const uint32_t timestamp = getMockTimestamp(); alert_manager_->setAltitudeThresholds(100.0f, -50.0f); // Act alert_manager_->checkAltitudeAlert(altitude, timestamp); // Assert EXPECT_TRUE(alert_manager_->hasActiveAlerts()); auto active_alerts = alert_manager_->getActiveAlerts(); EXPECT_EQ(active_alerts.size(), 1); EXPECT_EQ(active_alerts[0].type, AlertType::ALTITUDE_UPPER); EXPECT_EQ(active_alerts[0].status, AlertStatus::ACTIVE); EXPECT_EQ(active_alerts[0].trigger_time, timestamp); EXPECT_NE(active_alerts[0].description.find("1e+06"), std::string::npos); } // Test setAltitudeThresholds with equal values TEST_F(AlertManagerTest, testSetAltitudeThresholdsEqualValues) { // Arrange const float upper = 100.0f; const float lower = 100.0f; // Act & Assert EXPECT_NO_THROW(alert_manager_->setAltitudeThresholds(upper, lower)); EXPECT_TRUE(alert_manager_->hasActiveAlerts()); EXPECT_EQ(alert_manager_->getActiveAlerts().size(), 0); } // Test checkAltitudeAlert with negative altitude below lower threshold TEST_F(AlertManagerTest, testCheckAltitudeAlertNegativeBelowLower) { // Arrange const float altitude = -100.0f; const uint32_t timestamp = getMockTimestamp(); alert_manager_->setAltitudeThresholds(100.0f, -50.0f); // Act alert_manager_->checkAltitudeAlert(altitude, timestamp); // Assert EXPECT_TRUE(alert_manager_->hasActiveAlerts()); auto active_alerts = alert_manager_->getActiveAlerts(); EXPECT_EQ(active_alerts.size(), 1); EXPECT_EQ(active_alerts[0].type, AlertType::ALTITUDE_LOWER); EXPECT_EQ(active_alerts[0].status, AlertStatus::ACTIVE); EXPECT_EQ(active_alerts[0].trigger_time, timestamp); EXPECT_EQ(active_alerts[0].description, "高度低于下限阈值:当前-100米 < 阈值-50米"); } // Test checkAltitudeAlert with altitude exactly at upper threshold TEST_F(AlertManagerTest, testCheckAltitudeAlertAtUpperThreshold) { // Arrange const float altitude = 100.0f; const uint32_t timestamp = getMockTimestamp(); alert_manager_->setAltitudeThresholds(100.0f, -50.0f); // Act alert_manager_->checkAltitudeAlert(altitude, timestamp); // Assert EXPECT_FALSE(alert_manager_->hasActiveAlerts()); EXPECT_EQ(alert_manager_->getActiveAlerts().size(), 0); } // Test checkAltitudeAlert with altitude exactly at lower threshold TEST_F(AlertManagerTest, testCheckAltitudeAlertAtLowerThreshold) { // Arrange const float altitude = -50.0f; const uint32_t timestamp = getMockTimestamp(); alert_manager_->setAltitudeThresholds(100.0f, -50.0f); // Act alert_manager_->checkAltitudeAlert(altitude, timestamp); // Assert EXPECT_FALSE(alert_manager_->hasActiveAlerts()); EXPECT_EQ(alert_manager_->getActiveAlerts().size(), 0); }