xref: /openbmc/telemetry/tests/src/test_trigger.cpp (revision a4e6761643f2ff306d6928ea5537eb151fae79a0)
1 #include "dbus_environment.hpp"
2 #include "helpers.hpp"
3 #include "mocks/json_storage_mock.hpp"
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 
12 static constexpr size_t expectedTriggerVersion = 0;
13 
14 class TestTrigger : public Test
15 {
16   public:
17     TriggerParams triggerParams;
18 
19     std::unique_ptr<TriggerManagerMock> triggerManagerMockPtr =
20         std::make_unique<NiceMock<TriggerManagerMock>>();
21     testing::NiceMock<StorageMock> storageMock;
22     std::unique_ptr<Trigger> sut;
23 
24     void SetUp() override
25     {
26         sut = makeTrigger(triggerParams);
27     }
28 
29     std::unique_ptr<Trigger> makeTrigger(const TriggerParams& params)
30     {
31         return std::make_unique<Trigger>(
32             DbusEnvironment::getIoc(), DbusEnvironment::getObjServer(),
33             params.name(), params.isDiscrete(), params.logToJournal(),
34             params.logToRedfish(), params.updateReport(), params.sensors(),
35             params.reportNames(), params.thresholdParams(),
36             std::vector<std::shared_ptr<interfaces::Threshold>>{},
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)));
44     }
45 
46     template <class T>
47     static T getProperty(const std::string& path, const std::string& property)
48     {
49         auto propertyPromise = std::promise<T>();
50         auto propertyFuture = propertyPromise.get_future();
51         sdbusplus::asio::getProperty<T>(
52             *DbusEnvironment::getBus(), DbusEnvironment::serviceName(), path,
53             Trigger::triggerIfaceName, property,
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));
63     }
64 
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 
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 {
98     EXPECT_THAT(getProperty<bool>(sut->getPath(), "Persistent"), Eq(true));
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"),
116         Eq(triggerParams.thresholdParams()));
117 }
118 
119 TEST_F(TestTrigger, deleteTrigger)
120 {
121     EXPECT_CALL(storageMock, remove(to_file_path(sut->getName())));
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 }
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 }
254