blob: 1df64fb0c2bb07797ae5944e712f8d84a993bd7e [file] [log] [blame]
Brad Bishop13fd8722017-05-15 12:44:01 -04001#include "propertywatchtest.hpp"
2
Patrick Venture3d6d3182018-08-31 09:33:09 -07003#include "propertywatchimpl.hpp"
4
5#include <array>
Matthew Barth39c82152019-10-17 15:47:29 -05006#include <functional>
Patrick Venture3d6d3182018-08-31 09:33:09 -07007
Brad Bishop13fd8722017-05-15 12:44:01 -04008using namespace std::string_literals;
9using namespace phosphor::dbus::monitoring;
10
Brad Bishopd1eac882018-03-29 10:34:05 -040011const std::array<std::string, 4> paths = {
Brad Bishop13fd8722017-05-15 12:44:01 -040012 "/xyz/openbmc_project/testing/inst1"s,
13 "/xyz/openbmc_project/testing/inst2"s,
14 "/xyz/openbmc_project/testing/inst3"s,
15 "/xyz/openbmc_project/testing/inst4"s,
16};
17
Brad Bishopd1eac882018-03-29 10:34:05 -040018const std::array<std::string, 2> interfaces = {
Brad Bishop13fd8722017-05-15 12:44:01 -040019 "xyz.openbmc_project.Iface1"s,
20 "xyz.openbmc_project.Iface2"s,
21};
22
Brad Bishopd1eac882018-03-29 10:34:05 -040023const std::array<std::string, 2> properties = {
Brad Bishop13fd8722017-05-15 12:44:01 -040024 "Value1"s,
25 "Value2"s,
26};
27
28const std::string meta;
29
Patrick Williams26dc0bc2022-06-16 17:06:18 -050030std::array<std::tuple<std::any, std::any>, 8> storage = {};
Brad Bishop13fd8722017-05-15 12:44:01 -040031
Brad Bishopd1eac882018-03-29 10:34:05 -040032const PropertyIndex watchIndex = {
Brad Bishop13fd8722017-05-15 12:44:01 -040033 {
Brad Bishopd1eac882018-03-29 10:34:05 -040034 {PropertyIndex::key_type{paths[0], interfaces[0], properties[0]},
35 PropertyIndex::mapped_type{meta, meta, storage[0]}},
36 {PropertyIndex::key_type{paths[0], interfaces[1], properties[1]},
37 PropertyIndex::mapped_type{meta, meta, storage[1]}},
38 {PropertyIndex::key_type{paths[1], interfaces[0], properties[0]},
39 PropertyIndex::mapped_type{meta, meta, storage[2]}},
40 {PropertyIndex::key_type{paths[1], interfaces[1], properties[1]},
41 PropertyIndex::mapped_type{meta, meta, storage[3]}},
42 {PropertyIndex::key_type{paths[2], interfaces[0], properties[0]},
43 PropertyIndex::mapped_type{meta, meta, storage[4]}},
44 {PropertyIndex::key_type{paths[2], interfaces[1], properties[1]},
45 PropertyIndex::mapped_type{meta, meta, storage[5]}},
46 {PropertyIndex::key_type{paths[3], interfaces[0], properties[0]},
47 PropertyIndex::mapped_type{meta, meta, storage[6]}},
48 {PropertyIndex::key_type{paths[3], interfaces[1], properties[1]},
49 PropertyIndex::mapped_type{meta, meta, storage[7]}},
Brad Bishop13fd8722017-05-15 12:44:01 -040050 },
51};
52
Patrick Venture3d6d3182018-08-31 09:33:09 -070053template <typename T>
Matthew Barth52881362019-10-17 15:40:43 -050054struct Values
George Liu3fe976c2022-06-21 09:37:04 +080055{};
Patrick Venture3d6d3182018-08-31 09:33:09 -070056template <>
Matthew Barth52881362019-10-17 15:40:43 -050057struct Values<uint8_t>
Brad Bishop13fd8722017-05-15 12:44:01 -040058{
59 static auto& get(size_t i)
60 {
Brad Bishopd1eac882018-03-29 10:34:05 -040061 static const std::array<uint8_t, 8> values = {
Brad Bishop13fd8722017-05-15 12:44:01 -040062 {0, 1, 2, 3, 4, 5, 6, 7},
63 };
64 return values[i];
65 }
66};
67
Patrick Venture3d6d3182018-08-31 09:33:09 -070068template <>
Matthew Barth52881362019-10-17 15:40:43 -050069struct Values<uint16_t>
Brad Bishop13fd8722017-05-15 12:44:01 -040070{
71 static auto& get(size_t i)
72 {
Brad Bishopd1eac882018-03-29 10:34:05 -040073 static const std::array<uint16_t, 8> values = {
Brad Bishop13fd8722017-05-15 12:44:01 -040074 {88, 77, 66, 55, 44, 33, 22, 11},
75 };
76 return values[i];
77 }
78};
79
Patrick Venture3d6d3182018-08-31 09:33:09 -070080template <>
Matthew Barth52881362019-10-17 15:40:43 -050081struct Values<uint32_t>
Brad Bishop13fd8722017-05-15 12:44:01 -040082{
83 static auto& get(size_t i)
84 {
Brad Bishopd1eac882018-03-29 10:34:05 -040085 static const std::array<uint32_t, 8> values = {
Brad Bishop13fd8722017-05-15 12:44:01 -040086 {0xffffffff, 1, 3, 0, 5, 7, 9, 0xffffffff},
87 };
88 return values[i];
89 }
90};
91
Patrick Venture3d6d3182018-08-31 09:33:09 -070092template <>
Matthew Barth52881362019-10-17 15:40:43 -050093struct Values<uint64_t>
Brad Bishop13fd8722017-05-15 12:44:01 -040094{
95 static auto& get(size_t i)
96 {
Brad Bishopd1eac882018-03-29 10:34:05 -040097 static const std::array<uint64_t, 8> values = {
Brad Bishop13fd8722017-05-15 12:44:01 -040098 {0xffffffffffffffff, 3, 7, 12234, 0, 3, 9, 0xffffffff},
99 };
100 return values[i];
101 }
102};
103
Patrick Venture3d6d3182018-08-31 09:33:09 -0700104template <>
Matthew Barth52881362019-10-17 15:40:43 -0500105struct Values<std::string>
Brad Bishop13fd8722017-05-15 12:44:01 -0400106{
107 static auto& get(size_t i)
108 {
Brad Bishopd1eac882018-03-29 10:34:05 -0400109 static const std::array<std::string, 8> values = {
Brad Bishop13fd8722017-05-15 12:44:01 -0400110 {""s, "foo"s, "bar"s, "baz"s, "hello"s, "string", "\x2\x3", "\\"},
111 };
112 return values[i];
113 }
114};
115
Patrick Venture3d6d3182018-08-31 09:33:09 -0700116template <typename T>
Patrick Williams26dc0bc2022-06-16 17:06:18 -0500117void nonFilteredCheck(const std::any& value, const size_t ndx)
Matthew Barth39c82152019-10-17 15:47:29 -0500118{
Patrick Williams26dc0bc2022-06-16 17:06:18 -0500119 ASSERT_EQ(value.has_value(), true);
120 ASSERT_EQ(std::any_cast<T>(value), Values<T>::get(ndx));
Matthew Barth39c82152019-10-17 15:47:29 -0500121}
122
123template <typename T>
Matthew Barth9b502142019-10-17 15:53:53 -0500124struct FilteredValues
George Liu3fe976c2022-06-21 09:37:04 +0800125{};
Matthew Barth9b502142019-10-17 15:53:53 -0500126
127template <>
128struct FilteredValues<uint8_t>
129{
130 static auto& opFilters()
131 {
132 static std::unique_ptr<OperandFilters<uint8_t>> filters =
133 std::make_unique<OperandFilters<uint8_t>>(
134 std::vector<std::function<bool(uint8_t)>>{
135 [](const auto& value) { return value < 4; }});
136 return filters;
137 }
138 static auto& expected(size_t i)
139 {
Patrick Williams26dc0bc2022-06-16 17:06:18 -0500140 static const std::array<std::any, 8> values = {
141 {std::any(uint8_t(0)), std::any(uint8_t(1)), std::any(uint8_t(2)),
142 std::any(uint8_t(3)), std::any(), std::any(), std::any(),
143 std::any()}};
Matthew Barth9b502142019-10-17 15:53:53 -0500144 return values[i];
145 }
146};
147
148template <>
149struct FilteredValues<uint16_t>
150{
151 static auto& opFilters()
152 {
153 static std::unique_ptr<OperandFilters<uint16_t>> filters =
154 std::make_unique<OperandFilters<uint16_t>>(
155 std::vector<std::function<bool(uint16_t)>>{
156 [](const auto& value) { return value > 44; },
157 [](const auto& value) { return value != 88; }});
158 return filters;
159 }
160 static auto& expected(size_t i)
161 {
Patrick Williams26dc0bc2022-06-16 17:06:18 -0500162 static const std::array<std::any, 8> values = {
163 {std::any(), std::any(uint16_t(77)), std::any(uint16_t(66)),
164 std::any(uint16_t(55)), std::any(), std::any(), std::any(),
165 std::any()}};
Matthew Barth9b502142019-10-17 15:53:53 -0500166 return values[i];
167 }
168};
169
170template <>
171struct FilteredValues<uint32_t>
172{
173 static auto& opFilters()
174 {
175 static std::unique_ptr<OperandFilters<uint32_t>> filters =
176 std::make_unique<OperandFilters<uint32_t>>(
177 std::vector<std::function<bool(uint32_t)>>{
178 [](const auto& value) { return value != 0xffffffff; },
179 [](const auto& value) { return value != 0; }});
180 return filters;
181 }
182 static auto& expected(size_t i)
183 {
Patrick Williams26dc0bc2022-06-16 17:06:18 -0500184 static const std::array<std::any, 8> values = {
185 {std::any(), std::any(uint32_t(1)), std::any(uint32_t(3)),
186 std::any(), std::any(uint32_t(5)), std::any(uint32_t(7)),
187 std::any(uint32_t(9)), std::any()}};
Matthew Barth9b502142019-10-17 15:53:53 -0500188 return values[i];
189 }
190};
191
192template <>
193struct FilteredValues<uint64_t>
194{
195 static auto& opFilters()
196 {
197 static std::unique_ptr<OperandFilters<uint64_t>> filters =
198 std::make_unique<OperandFilters<uint64_t>>(
199 std::vector<std::function<bool(uint64_t)>>{
200 [](const auto& value) { return (value % 3) != 0; }});
201 return filters;
202 }
203 static auto& expected(size_t i)
204 {
Patrick Williams26dc0bc2022-06-16 17:06:18 -0500205 static const std::array<std::any, 8> values = {
206 {std::any(), std::any(), std::any(uint64_t(7)), std::any(),
207 std::any(), std::any(), std::any(), std::any()}};
Matthew Barth9b502142019-10-17 15:53:53 -0500208 return values[i];
209 }
210};
211
212template <>
213struct FilteredValues<std::string>
214{
215 static auto& opFilters()
216 {
217 static std::unique_ptr<OperandFilters<std::string>> filters =
218 std::make_unique<OperandFilters<std::string>>(
219 std::vector<std::function<bool(std::string)>>{
220 [](const auto& value) { return value != ""s; },
221 [](const auto& value) { return value != "string"s; }});
222 return filters;
223 }
224 static auto& expected(size_t i)
225 {
Patrick Williams26dc0bc2022-06-16 17:06:18 -0500226 static const std::array<std::any, 8> values = {
227 {std::any(), std::any("foo"s), std::any("bar"s), std::any("baz"s),
228 std::any("hello"s), std::any(), std::any("\x2\x3"s),
229 std::any("\\"s)}};
Matthew Barth9b502142019-10-17 15:53:53 -0500230 return values[i];
231 }
232};
233
234template <typename T>
Patrick Williams26dc0bc2022-06-16 17:06:18 -0500235void filteredCheck(const std::any& value, const size_t ndx)
Matthew Barth9b502142019-10-17 15:53:53 -0500236{
Patrick Williams26dc0bc2022-06-16 17:06:18 -0500237 ASSERT_EQ(value.has_value(), FilteredValues<T>::expected(ndx).has_value());
238 if (value.has_value())
Matthew Barth9b502142019-10-17 15:53:53 -0500239 {
Patrick Williams26dc0bc2022-06-16 17:06:18 -0500240 ASSERT_EQ(std::any_cast<T>(value),
241 std::any_cast<T>(FilteredValues<T>::expected(ndx)));
Matthew Barth9b502142019-10-17 15:53:53 -0500242 }
243}
244
245template <typename T>
Patrick Williams26dc0bc2022-06-16 17:06:18 -0500246void testStart(std::function<void(const std::any&, const size_t)>&& checkState,
247 OperandFilters<T>* opFilters = nullptr)
Brad Bishop13fd8722017-05-15 12:44:01 -0400248{
Brad Bishop13fd8722017-05-15 12:44:01 -0400249 using ::testing::_;
Patrick Ventureac803952018-08-31 09:28:31 -0700250 using ::testing::Return;
Brad Bishop13fd8722017-05-15 12:44:01 -0400251
252 MockDBusInterface dbus;
253 MockDBusInterface::instance(dbus);
254
255 const std::vector<std::string> expectedMapperInterfaces;
Lei YU98d64622022-05-24 19:11:23 +0800256 PropertyWatchOfType<T, MockDBusInterface> watch(watchIndex, false,
257 opFilters);
Brad Bishop13fd8722017-05-15 12:44:01 -0400258
259 auto ndx = static_cast<size_t>(0);
260 for (const auto& o : convert(watchIndex))
261 {
262 const auto& path = o.first.get();
263 const auto& interfaces = o.second;
264 std::vector<std::string> mapperResponse;
Brad Bishopd1eac882018-03-29 10:34:05 -0400265 std::transform(interfaces.begin(), interfaces.end(),
266 std::back_inserter(mapperResponse),
267 // *INDENT-OFF*
268 [](const auto& item) { return item.first; });
Brad Bishop13fd8722017-05-15 12:44:01 -0400269 // *INDENT-ON*
Brad Bishopd1eac882018-03-29 10:34:05 -0400270 EXPECT_CALL(dbus, mapperGetObject(MAPPER_BUSNAME, MAPPER_PATH,
271 MAPPER_INTERFACE, "GetObject", path,
272 expectedMapperInterfaces))
273 .WillOnce(Return(GetObject({{"", mapperResponse}})));
Brad Bishop13fd8722017-05-15 12:44:01 -0400274 EXPECT_CALL(
Brad Bishopd1eac882018-03-29 10:34:05 -0400275 dbus, fwdAddMatch(
Matthew Barthf79fc092019-10-10 14:01:04 -0500276 sdbusplus::bus::match::rules::interfacesAdded(path), _));
Brad Bishop13fd8722017-05-15 12:44:01 -0400277 for (const auto& i : interfaces)
278 {
279 const auto& interface = i.first.get();
280 const auto& properties = i.second;
281 EXPECT_CALL(
282 dbus,
Matthew Barthf79fc092019-10-10 14:01:04 -0500283 fwdAddMatch(sdbusplus::bus::match::rules::propertiesChanged(
284 path, interface),
285 _));
Brad Bishop13fd8722017-05-15 12:44:01 -0400286
287 PropertiesChanged<T> serviceResponse;
288 for (const auto& p : properties)
289 {
Matthew Barth52881362019-10-17 15:40:43 -0500290 serviceResponse[p] = Values<T>::get(ndx);
Brad Bishop13fd8722017-05-15 12:44:01 -0400291 ++ndx;
292 }
293 Expect<T>::getProperties(dbus, path, interface)
Brad Bishopd1eac882018-03-29 10:34:05 -0400294 .WillOnce(Return(serviceResponse));
Brad Bishop13fd8722017-05-15 12:44:01 -0400295 }
296 }
297
298 watch.start();
299
300 ndx = 0;
301 for (auto s : storage)
302 {
Matthew Barth39c82152019-10-17 15:47:29 -0500303 checkState(std::get<valueIndex>(s), ndx);
Brad Bishop13fd8722017-05-15 12:44:01 -0400304 ++ndx;
305 }
306
307 // Make sure start logic only runs the first time.
308 watch.start();
309}
310
311TEST(PropertyWatchTest, TestStart)
312{
Matthew Barth39c82152019-10-17 15:47:29 -0500313 testStart<uint8_t>(nonFilteredCheck<uint8_t>);
314 testStart<uint16_t>(nonFilteredCheck<uint16_t>);
315 testStart<uint32_t>(nonFilteredCheck<uint32_t>);
316 testStart<uint64_t>(nonFilteredCheck<uint64_t>);
317 testStart<std::string>(nonFilteredCheck<std::string>);
Brad Bishop13fd8722017-05-15 12:44:01 -0400318}
319
Matthew Barth9b502142019-10-17 15:53:53 -0500320TEST(PropertyWatchTest, TestFilters)
321{
322 testStart<uint8_t>(filteredCheck<uint8_t>,
323 FilteredValues<uint8_t>::opFilters().get());
324 testStart<uint16_t>(filteredCheck<uint16_t>,
325 FilteredValues<uint16_t>::opFilters().get());
326 testStart<uint32_t>(filteredCheck<uint32_t>,
327 FilteredValues<uint32_t>::opFilters().get());
328 testStart<uint64_t>(filteredCheck<uint64_t>,
329 FilteredValues<uint64_t>::opFilters().get());
330 testStart<std::string>(filteredCheck<std::string>,
331 FilteredValues<std::string>::opFilters().get());
332}
333
Brad Bishop13fd8722017-05-15 12:44:01 -0400334MockDBusInterface* MockDBusInterface::ptr = nullptr;