1 #include "dbus_environment.hpp" 2 #include "helpers.hpp" 3 #include "mocks/json_storage_mock.hpp" 4 #include "mocks/trigger_factory_mock.hpp" 5 #include "mocks/trigger_mock.hpp" 6 #include "params/trigger_params.hpp" 7 #include "trigger.hpp" 8 #include "trigger_manager.hpp" 9 #include "utils/conversion_trigger.hpp" 10 #include "utils/transform.hpp" 11 12 using namespace testing; 13 14 class TestTriggerManager : public Test 15 { 16 public: 17 std::pair<boost::system::error_code, std::string> 18 addTrigger(const TriggerParams& params) 19 { 20 const auto sensorInfos = 21 utils::fromLabeledSensorsInfo(params.sensors()); 22 23 std::promise<std::pair<boost::system::error_code, std::string>> 24 addTriggerPromise; 25 DbusEnvironment::getBus()->async_method_call( 26 [&addTriggerPromise](boost::system::error_code ec, 27 const std::string& path) { 28 addTriggerPromise.set_value({ec, path}); 29 }, 30 DbusEnvironment::serviceName(), TriggerManager::triggerManagerPath, 31 TriggerManager::triggerManagerIfaceName, "AddTrigger", 32 params.name(), params.isDiscrete(), params.logToJournal(), 33 params.logToRedfish(), params.updateReport(), sensorInfos, 34 params.reportNames(), 35 std::visit(utils::FromLabeledThresholdParamConversion(), 36 params.thresholdParams())); 37 return DbusEnvironment::waitForFuture(addTriggerPromise.get_future()); 38 } 39 40 std::unique_ptr<TriggerManager> makeTriggerManager() 41 { 42 return std::make_unique<TriggerManager>( 43 std::move(triggerFactoryMockPtr), std::move(storageMockPtr), 44 DbusEnvironment::getObjServer()); 45 } 46 47 void SetUp() override 48 { 49 sut = makeTriggerManager(); 50 } 51 52 std::unique_ptr<StorageMock> storageMockPtr = 53 std::make_unique<NiceMock<StorageMock>>(); 54 StorageMock& storageMock = *storageMockPtr; 55 std::unique_ptr<TriggerFactoryMock> triggerFactoryMockPtr = 56 std::make_unique<NiceMock<TriggerFactoryMock>>(); 57 TriggerFactoryMock& triggerFactoryMock = *triggerFactoryMockPtr; 58 std::unique_ptr<TriggerMock> triggerMockPtr = 59 std::make_unique<NiceMock<TriggerMock>>(TriggerParams().name()); 60 TriggerMock& triggerMock = *triggerMockPtr; 61 std::unique_ptr<TriggerManager> sut; 62 MockFunction<void(std::string)> checkPoint; 63 }; 64 65 TEST_F(TestTriggerManager, addTrigger) 66 { 67 triggerFactoryMock.expectMake(TriggerParams(), Ref(*sut), Ref(storageMock)) 68 .WillOnce(Return(ByMove(std::move(triggerMockPtr)))); 69 70 auto [ec, path] = addTrigger(TriggerParams()); 71 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success)); 72 EXPECT_THAT(path, Eq(triggerMock.getPath())); 73 } 74 75 TEST_F(TestTriggerManager, addTriggerWithDiscreteThresholds) 76 { 77 TriggerParams triggerParamsDiscrete; 78 auto thresholds = std::vector<discrete::LabeledThresholdParam>{ 79 {"discrete_threshold1", discrete::Severity::ok, 10, 11.0}, 80 {"discrete_threshold2", discrete::Severity::warning, 10, 12.0}, 81 {"discrete_threshold3", discrete::Severity::critical, 10, 13.0}}; 82 83 triggerParamsDiscrete.thresholdParams(thresholds).isDiscrete(true); 84 85 auto [ec, path] = addTrigger(triggerParamsDiscrete); 86 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success)); 87 EXPECT_THAT(path, Eq(triggerMock.getPath())); 88 } 89 90 TEST_F(TestTriggerManager, addDiscreteTriggerWithoutThresholds) 91 { 92 TriggerParams triggerParamsDiscrete; 93 auto thresholds = std::vector<discrete::LabeledThresholdParam>(); 94 95 triggerParamsDiscrete.thresholdParams(thresholds).isDiscrete(true); 96 97 auto [ec, path] = addTrigger(triggerParamsDiscrete); 98 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success)); 99 EXPECT_THAT(path, Eq(triggerMock.getPath())); 100 } 101 102 TEST_F(TestTriggerManager, DISABLED_failToAddTriggerTwice) 103 { 104 triggerFactoryMock.expectMake(TriggerParams(), Ref(*sut), Ref(storageMock)) 105 .WillOnce(Return(ByMove(std::move(triggerMockPtr)))); 106 107 addTrigger(TriggerParams()); 108 109 auto [ec, path] = addTrigger(TriggerParams()); 110 EXPECT_THAT(ec.value(), Eq(boost::system::errc::file_exists)); 111 EXPECT_THAT(path, Eq(std::string())); 112 } 113 114 TEST_F(TestTriggerManager, DISABLED_failToAddTriggerWhenMaxTriggerIsReached) 115 { 116 auto triggerParams = TriggerParams(); 117 118 triggerFactoryMock.expectMake(std::nullopt, Ref(*sut), Ref(storageMock)) 119 .Times(TriggerManager::maxTriggers); 120 121 for (size_t i = 0; i < TriggerManager::maxTriggers; i++) 122 { 123 triggerParams.name(TriggerParams().name() + std::to_string(i)); 124 125 auto [ec, path] = addTrigger(triggerParams); 126 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success)); 127 } 128 129 triggerParams.name(TriggerParams().name() + 130 std::to_string(TriggerManager::maxTriggers)); 131 auto [ec, path] = addTrigger(triggerParams); 132 EXPECT_THAT(ec.value(), Eq(boost::system::errc::too_many_files_open)); 133 EXPECT_THAT(path, Eq(std::string())); 134 } 135 136 TEST_F(TestTriggerManager, removeTrigger) 137 { 138 { 139 InSequence seq; 140 triggerFactoryMock 141 .expectMake(TriggerParams(), Ref(*sut), Ref(storageMock)) 142 .WillOnce(Return(ByMove(std::move(triggerMockPtr)))); 143 EXPECT_CALL(triggerMock, Die()); 144 EXPECT_CALL(checkPoint, Call("end")); 145 } 146 147 addTrigger(TriggerParams()); 148 sut->removeTrigger(&triggerMock); 149 checkPoint.Call("end"); 150 } 151 152 TEST_F(TestTriggerManager, removingTriggerThatIsNotInContainerHasNoEffect) 153 { 154 { 155 InSequence seq; 156 EXPECT_CALL(checkPoint, Call("end")); 157 EXPECT_CALL(triggerMock, Die()); 158 } 159 160 sut->removeTrigger(&triggerMock); 161 checkPoint.Call("end"); 162 } 163 164 TEST_F(TestTriggerManager, removingSameTriggerTwiceHasNoSideEffect) 165 { 166 { 167 InSequence seq; 168 triggerFactoryMock 169 .expectMake(TriggerParams(), Ref(*sut), Ref(storageMock)) 170 .WillOnce(Return(ByMove(std::move(triggerMockPtr)))); 171 EXPECT_CALL(triggerMock, Die()); 172 EXPECT_CALL(checkPoint, Call("end")); 173 } 174 175 addTrigger(TriggerParams()); 176 sut->removeTrigger(&triggerMock); 177 sut->removeTrigger(&triggerMock); 178 checkPoint.Call("end"); 179 } 180 181 class TestTriggerManagerStorage : public TestTriggerManager 182 { 183 public: 184 using FilePath = interfaces::JsonStorage::FilePath; 185 using DirectoryPath = interfaces::JsonStorage::DirectoryPath; 186 187 void SetUp() override 188 { 189 ON_CALL(storageMock, list()) 190 .WillByDefault(Return(std::vector<FilePath>{ 191 {FilePath("trigger1")}, {FilePath("trigger2")}})); 192 193 ON_CALL(storageMock, load(FilePath("trigger1"))) 194 .WillByDefault(InvokeWithoutArgs([this] { return data1; })); 195 196 data2["Name"] = "Trigger2"; 197 ON_CALL(storageMock, load(FilePath("trigger2"))) 198 .WillByDefault(InvokeWithoutArgs([this] { return data2; })); 199 } 200 201 nlohmann::json data1 = nlohmann::json{ 202 {"Version", Trigger::triggerVersion}, 203 {"Name", TriggerParams().name()}, 204 {"ThresholdParamsDiscriminator", 205 TriggerParams().thresholdParams().index()}, 206 {"IsDiscrete", TriggerParams().isDiscrete()}, 207 {"LogToJournal", TriggerParams().logToJournal()}, 208 {"LogToRedfish", TriggerParams().logToRedfish()}, 209 {"UpdateReport", TriggerParams().updateReport()}, 210 {"ThresholdParams", utils::labeledThresholdParamsToJson( 211 TriggerParams().thresholdParams())}, 212 {"ReportNames", TriggerParams().reportNames()}, 213 {"Sensors", TriggerParams().sensors()}}; 214 215 nlohmann::json data2 = data1; 216 }; 217 218 TEST_F(TestTriggerManagerStorage, triggerManagerCtorAddTriggerFromStorage) 219 { 220 triggerFactoryMock.expectMake(TriggerParams(), _, Ref(storageMock)); 221 triggerFactoryMock.expectMake(TriggerParams().name("Trigger2"), _, 222 Ref(storageMock)); 223 EXPECT_CALL(storageMock, remove(_)).Times(0); 224 225 sut = makeTriggerManager(); 226 } 227 228 TEST_F(TestTriggerManagerStorage, 229 triggerManagerCtorRemoveDiscreteTriggerFromStorage) 230 { 231 LabeledTriggerThresholdParams thresholdParams = 232 std::vector<discrete::LabeledThresholdParam>{ 233 {"userId1", discrete::Severity::warning, 15, 10.0}, 234 {"userId2", discrete::Severity::critical, 5, 20.0}}; 235 236 data1["ThresholdParamsDiscriminator"] = thresholdParams.index(); 237 238 data1["ThresholdParams"] = 239 utils::labeledThresholdParamsToJson(thresholdParams); 240 241 EXPECT_CALL(storageMock, remove(FilePath("trigger1"))).Times(0); 242 243 sut = makeTriggerManager(); 244 } 245 246 TEST_F(TestTriggerManagerStorage, 247 triggerManagerCtorRemoveDiscreteTriggerFromStorage2) 248 { 249 data1["IsDiscrete"] = true; 250 251 EXPECT_CALL(storageMock, remove(FilePath("trigger1"))).Times(0); 252 253 sut = makeTriggerManager(); 254 } 255 256 TEST_F(TestTriggerManagerStorage, 257 triggerManagerCtorAddProperRemoveInvalidTriggerFromStorage) 258 { 259 data1["Version"] = Trigger::triggerVersion - 1; 260 261 triggerFactoryMock.expectMake(TriggerParams().name("Trigger2"), _, 262 Ref(storageMock)); 263 EXPECT_CALL(storageMock, remove(FilePath("trigger1"))); 264 265 sut = makeTriggerManager(); 266 } 267