Wludzik, Jozef | 76833cb | 2020-12-21 14:42:41 +0100 | [diff] [blame] | 1 | #include "dbus_environment.hpp" |
| 2 | #include "helpers.hpp" |
Cezary Zwolak | a4e6761 | 2021-02-18 13:16:16 +0100 | [diff] [blame^] | 3 | #include "mocks/json_storage_mock.hpp" |
Wludzik, Jozef | 76833cb | 2020-12-21 14:42:41 +0100 | [diff] [blame] | 4 | #include "mocks/trigger_manager_mock.hpp" |
| 5 | #include "params/trigger_params.hpp" |
| 6 | #include "trigger.hpp" |
| 7 | #include "utils/set_exception.hpp" |
| 8 | |
| 9 | using namespace testing; |
| 10 | using namespace std::literals::string_literals; |
| 11 | |
Cezary Zwolak | a4e6761 | 2021-02-18 13:16:16 +0100 | [diff] [blame^] | 12 | static constexpr size_t expectedTriggerVersion = 0; |
| 13 | |
Wludzik, Jozef | 76833cb | 2020-12-21 14:42:41 +0100 | [diff] [blame] | 14 | class TestTrigger : public Test |
| 15 | { |
| 16 | public: |
| 17 | TriggerParams triggerParams; |
| 18 | |
| 19 | std::unique_ptr<TriggerManagerMock> triggerManagerMockPtr = |
| 20 | std::make_unique<NiceMock<TriggerManagerMock>>(); |
Cezary Zwolak | a4e6761 | 2021-02-18 13:16:16 +0100 | [diff] [blame^] | 21 | testing::NiceMock<StorageMock> storageMock; |
Wludzik, Jozef | 76833cb | 2020-12-21 14:42:41 +0100 | [diff] [blame] | 22 | std::unique_ptr<Trigger> sut; |
| 23 | |
| 24 | void SetUp() override |
| 25 | { |
Cezary Zwolak | a4e6761 | 2021-02-18 13:16:16 +0100 | [diff] [blame^] | 26 | sut = makeTrigger(triggerParams); |
| 27 | } |
| 28 | |
| 29 | std::unique_ptr<Trigger> makeTrigger(const TriggerParams& params) |
| 30 | { |
| 31 | return std::make_unique<Trigger>( |
Wludzik, Jozef | 76833cb | 2020-12-21 14:42:41 +0100 | [diff] [blame] | 32 | DbusEnvironment::getIoc(), DbusEnvironment::getObjServer(), |
Cezary Zwolak | a4e6761 | 2021-02-18 13:16:16 +0100 | [diff] [blame^] | 33 | params.name(), params.isDiscrete(), params.logToJournal(), |
| 34 | params.logToRedfish(), params.updateReport(), params.sensors(), |
| 35 | params.reportNames(), params.thresholdParams(), |
Wludzik, Jozef | 1477fe6 | 2021-01-02 11:56:10 +0100 | [diff] [blame] | 36 | std::vector<std::shared_ptr<interfaces::Threshold>>{}, |
Cezary Zwolak | a4e6761 | 2021-02-18 13:16:16 +0100 | [diff] [blame^] | 37 | *triggerManagerMockPtr, storageMock); |
| 38 | } |
| 39 | |
| 40 | static interfaces::JsonStorage::FilePath to_file_path(std::string name) |
| 41 | { |
| 42 | return interfaces::JsonStorage::FilePath( |
| 43 | std::to_string(std::hash<std::string>{}(name))); |
Wludzik, Jozef | 76833cb | 2020-12-21 14:42:41 +0100 | [diff] [blame] | 44 | } |
| 45 | |
| 46 | template <class T> |
| 47 | static T getProperty(const std::string& path, const std::string& property) |
| 48 | { |
Ed Tanous | 0e7ae5d | 2021-02-23 14:06:49 -0800 | [diff] [blame] | 49 | auto propertyPromise = std::promise<T>(); |
| 50 | auto propertyFuture = propertyPromise.get_future(); |
Wludzik, Jozef | 76833cb | 2020-12-21 14:42:41 +0100 | [diff] [blame] | 51 | sdbusplus::asio::getProperty<T>( |
| 52 | *DbusEnvironment::getBus(), DbusEnvironment::serviceName(), path, |
| 53 | Trigger::triggerIfaceName, property, |
Ed Tanous | 0e7ae5d | 2021-02-23 14:06:49 -0800 | [diff] [blame] | 54 | [&propertyPromise](const boost::system::error_code& ec, T t) { |
| 55 | if (ec) |
| 56 | { |
| 57 | utils::setException(propertyPromise, "GetProperty failed"); |
| 58 | return; |
| 59 | } |
| 60 | propertyPromise.set_value(t); |
| 61 | }); |
| 62 | return DbusEnvironment::waitForFuture(std::move(propertyFuture)); |
Wludzik, Jozef | 76833cb | 2020-12-21 14:42:41 +0100 | [diff] [blame] | 63 | } |
| 64 | |
Cezary Zwolak | a4e6761 | 2021-02-18 13:16:16 +0100 | [diff] [blame^] | 65 | template <class T> |
| 66 | static boost::system::error_code setProperty(const std::string& path, |
| 67 | const std::string& property, |
| 68 | const T& newValue) |
| 69 | { |
| 70 | auto setPromise = std::promise<boost::system::error_code>(); |
| 71 | auto setFuture = setPromise.get_future(); |
| 72 | |
| 73 | sdbusplus::asio::setProperty( |
| 74 | *DbusEnvironment::getBus(), DbusEnvironment::serviceName(), path, |
| 75 | Trigger::triggerIfaceName, property, std::move(newValue), |
| 76 | [setPromise = |
| 77 | std::move(setPromise)](boost::system::error_code ec) mutable { |
| 78 | setPromise.set_value(ec); |
| 79 | }); |
| 80 | return DbusEnvironment::waitForFuture(std::move(setFuture)); |
| 81 | } |
| 82 | |
Wludzik, Jozef | 76833cb | 2020-12-21 14:42:41 +0100 | [diff] [blame] | 83 | boost::system::error_code deleteTrigger(const std::string& path) |
| 84 | { |
| 85 | std::promise<boost::system::error_code> methodPromise; |
| 86 | DbusEnvironment::getBus()->async_method_call( |
| 87 | [&methodPromise](boost::system::error_code ec) { |
| 88 | methodPromise.set_value(ec); |
| 89 | }, |
| 90 | DbusEnvironment::serviceName(), path, Trigger::deleteIfaceName, |
| 91 | "Delete"); |
| 92 | return DbusEnvironment::waitForFuture(methodPromise.get_future()); |
| 93 | } |
| 94 | }; |
| 95 | |
| 96 | TEST_F(TestTrigger, checkIfPropertiesAreSet) |
| 97 | { |
Cezary Zwolak | a4e6761 | 2021-02-18 13:16:16 +0100 | [diff] [blame^] | 98 | EXPECT_THAT(getProperty<bool>(sut->getPath(), "Persistent"), Eq(true)); |
Wludzik, Jozef | 76833cb | 2020-12-21 14:42:41 +0100 | [diff] [blame] | 99 | EXPECT_THAT(getProperty<bool>(sut->getPath(), "Discrete"), |
| 100 | Eq(triggerParams.isDiscrete())); |
| 101 | EXPECT_THAT(getProperty<bool>(sut->getPath(), "LogToJournal"), |
| 102 | Eq(triggerParams.logToJournal())); |
| 103 | EXPECT_THAT(getProperty<bool>(sut->getPath(), "LogToRedfish"), |
| 104 | Eq(triggerParams.logToRedfish())); |
| 105 | EXPECT_THAT(getProperty<bool>(sut->getPath(), "UpdateReport"), |
| 106 | Eq(triggerParams.updateReport())); |
| 107 | EXPECT_THAT((getProperty<std::vector< |
| 108 | std::pair<sdbusplus::message::object_path, std::string>>>( |
| 109 | sut->getPath(), "Sensors")), |
| 110 | Eq(triggerParams.sensors())); |
| 111 | EXPECT_THAT( |
| 112 | getProperty<std::vector<std::string>>(sut->getPath(), "ReportNames"), |
| 113 | Eq(triggerParams.reportNames())); |
| 114 | EXPECT_THAT( |
| 115 | getProperty<TriggerThresholdParams>(sut->getPath(), "Thresholds"), |
Wludzik, Jozef | 1477fe6 | 2021-01-02 11:56:10 +0100 | [diff] [blame] | 116 | Eq(triggerParams.thresholdParams())); |
Wludzik, Jozef | 76833cb | 2020-12-21 14:42:41 +0100 | [diff] [blame] | 117 | } |
| 118 | |
| 119 | TEST_F(TestTrigger, deleteTrigger) |
| 120 | { |
Cezary Zwolak | a4e6761 | 2021-02-18 13:16:16 +0100 | [diff] [blame^] | 121 | EXPECT_CALL(storageMock, remove(to_file_path(sut->getName()))); |
Wludzik, Jozef | 76833cb | 2020-12-21 14:42:41 +0100 | [diff] [blame] | 122 | EXPECT_CALL(*triggerManagerMockPtr, removeTrigger(sut.get())); |
| 123 | auto ec = deleteTrigger(sut->getPath()); |
| 124 | EXPECT_THAT(ec, Eq(boost::system::errc::success)); |
| 125 | } |
| 126 | |
| 127 | TEST_F(TestTrigger, deletingNonExistingTriggerReturnInvalidRequestDescriptor) |
| 128 | { |
| 129 | auto ec = deleteTrigger(Trigger::triggerDir + "NonExisting"s); |
| 130 | EXPECT_THAT(ec.value(), Eq(EBADR)); |
| 131 | } |
Cezary Zwolak | a4e6761 | 2021-02-18 13:16:16 +0100 | [diff] [blame^] | 132 | |
| 133 | TEST_F(TestTrigger, settingPersistencyToFalseRemovesReportFromStorage) |
| 134 | { |
| 135 | EXPECT_CALL(storageMock, remove(to_file_path(sut->getName()))); |
| 136 | |
| 137 | bool persistent = false; |
| 138 | EXPECT_THAT(setProperty(sut->getPath(), "Persistent", persistent).value(), |
| 139 | Eq(boost::system::errc::success)); |
| 140 | EXPECT_THAT(getProperty<bool>(sut->getPath(), "Persistent"), |
| 141 | Eq(persistent)); |
| 142 | } |
| 143 | |
| 144 | class TestTriggerErrors : public TestTrigger |
| 145 | { |
| 146 | public: |
| 147 | void SetUp() override |
| 148 | {} |
| 149 | |
| 150 | nlohmann::json storedConfiguration; |
| 151 | }; |
| 152 | |
| 153 | TEST_F(TestTriggerErrors, throwingExceptionDoesNotStoreTriggerReportNames) |
| 154 | { |
| 155 | EXPECT_CALL(storageMock, store(_, _)) |
| 156 | .WillOnce(Throw(std::runtime_error("Generic error!"))); |
| 157 | |
| 158 | sut = makeTrigger(triggerParams); |
| 159 | |
| 160 | EXPECT_THAT(getProperty<bool>(sut->getPath(), "Persistent"), Eq(false)); |
| 161 | } |
| 162 | |
| 163 | TEST_F(TestTriggerErrors, creatingTriggerThrowsExceptionWhenNameIsInvalid) |
| 164 | { |
| 165 | EXPECT_CALL(storageMock, store(_, _)).Times(0); |
| 166 | |
| 167 | EXPECT_THROW(makeTrigger(triggerParams.name("inv?lidName")), |
| 168 | sdbusplus::exception::SdBusError); |
| 169 | } |
| 170 | |
| 171 | class TestTriggerStore : public TestTrigger |
| 172 | { |
| 173 | public: |
| 174 | void SetUp() override |
| 175 | { |
| 176 | ON_CALL(storageMock, store(_, _)) |
| 177 | .WillByDefault(SaveArg<1>(&storedConfiguration)); |
| 178 | |
| 179 | sut = makeTrigger(triggerParams); |
| 180 | } |
| 181 | |
| 182 | nlohmann::json storedConfiguration; |
| 183 | }; |
| 184 | |
| 185 | TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerVersion) |
| 186 | { |
| 187 | ASSERT_THAT(storedConfiguration.at("Version"), Eq(expectedTriggerVersion)); |
| 188 | } |
| 189 | |
| 190 | TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerName) |
| 191 | { |
| 192 | ASSERT_THAT(storedConfiguration.at("Name"), Eq(triggerParams.name())); |
| 193 | } |
| 194 | |
| 195 | TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerIsDiscrete) |
| 196 | { |
| 197 | ASSERT_THAT(storedConfiguration.at("IsDiscrete"), |
| 198 | Eq(triggerParams.isDiscrete())); |
| 199 | } |
| 200 | |
| 201 | TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerLogToJournal) |
| 202 | { |
| 203 | ASSERT_THAT(storedConfiguration.at("LogToJournal"), |
| 204 | Eq(triggerParams.logToRedfish())); |
| 205 | } |
| 206 | |
| 207 | TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerLogToRedfish) |
| 208 | { |
| 209 | ASSERT_THAT(storedConfiguration.at("LogToRedfish"), |
| 210 | Eq(triggerParams.logToRedfish())); |
| 211 | } |
| 212 | |
| 213 | TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerUpdateReport) |
| 214 | { |
| 215 | ASSERT_THAT(storedConfiguration.at("UpdateReport"), |
| 216 | Eq(triggerParams.updateReport())); |
| 217 | } |
| 218 | |
| 219 | TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerReportNames) |
| 220 | { |
| 221 | ASSERT_THAT(storedConfiguration.at("ReportNames"), |
| 222 | Eq(triggerParams.reportNames())); |
| 223 | } |
| 224 | |
| 225 | TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerSensors) |
| 226 | { |
| 227 | nlohmann::json expectedItem; |
| 228 | expectedItem["sensorPath"] = |
| 229 | "/xyz/openbmc_project/sensors/temperature/BMC_Temp"; |
| 230 | expectedItem["sensorMetadata"] = ""; |
| 231 | |
| 232 | ASSERT_THAT(storedConfiguration.at("Sensors"), ElementsAre(expectedItem)); |
| 233 | } |
| 234 | |
| 235 | TEST_F(TestTriggerStore, settingPersistencyToTrueStoresTriggerThresholdParams) |
| 236 | { |
| 237 | ASSERT_THAT(storedConfiguration.at("ThresholdParamsDiscriminator"), Eq(0)); |
| 238 | |
| 239 | nlohmann::json expectedItem0; |
| 240 | expectedItem0["type"] = 0; |
| 241 | expectedItem0["dwellTime"] = 10; |
| 242 | expectedItem0["direction"] = 1; |
| 243 | expectedItem0["thresholdValue"] = 0.0; |
| 244 | |
| 245 | nlohmann::json expectedItem1; |
| 246 | expectedItem1["type"] = 3; |
| 247 | expectedItem1["dwellTime"] = 10; |
| 248 | expectedItem1["direction"] = 2; |
| 249 | expectedItem1["thresholdValue"] = 90.0; |
| 250 | |
| 251 | ASSERT_THAT(storedConfiguration.at("ThresholdParams"), |
| 252 | ElementsAre(expectedItem0, expectedItem1)); |
| 253 | } |