| #include <array> |
| #include "propertywatchimpl.hpp" |
| #include "propertywatchtest.hpp" |
| |
| using namespace std::string_literals; |
| using namespace phosphor::dbus::monitoring; |
| |
| const std::array<std::string, 4> paths = |
| { |
| "/xyz/openbmc_project/testing/inst1"s, |
| "/xyz/openbmc_project/testing/inst2"s, |
| "/xyz/openbmc_project/testing/inst3"s, |
| "/xyz/openbmc_project/testing/inst4"s, |
| }; |
| |
| const std::array<std::string, 2> interfaces = |
| { |
| "xyz.openbmc_project.Iface1"s, |
| "xyz.openbmc_project.Iface2"s, |
| }; |
| |
| const std::array<std::string, 2> properties = |
| { |
| "Value1"s, |
| "Value2"s, |
| }; |
| |
| const std::string meta; |
| |
| std::array<any_ns::any, 8> storage = { }; |
| |
| const PropertyIndex watchIndex = |
| { |
| { |
| { |
| PropertyIndex::key_type{paths[0], interfaces[0], properties[0]}, |
| PropertyIndex::mapped_type{meta, meta, storage[0]} |
| }, |
| { |
| PropertyIndex::key_type{paths[0], interfaces[1], properties[1]}, |
| PropertyIndex::mapped_type{meta, meta, storage[1]} |
| }, |
| { |
| PropertyIndex::key_type{paths[1], interfaces[0], properties[0]}, |
| PropertyIndex::mapped_type{meta, meta, storage[2]} |
| }, |
| { |
| PropertyIndex::key_type{paths[1], interfaces[1], properties[1]}, |
| PropertyIndex::mapped_type{meta, meta, storage[3]} |
| }, |
| { |
| PropertyIndex::key_type{paths[2], interfaces[0], properties[0]}, |
| PropertyIndex::mapped_type{meta, meta, storage[4]} |
| }, |
| { |
| PropertyIndex::key_type{paths[2], interfaces[1], properties[1]}, |
| PropertyIndex::mapped_type{meta, meta, storage[5]} |
| }, |
| { |
| PropertyIndex::key_type{paths[3], interfaces[0], properties[0]}, |
| PropertyIndex::mapped_type{meta, meta, storage[6]} |
| }, |
| { |
| PropertyIndex::key_type{paths[3], interfaces[1], properties[1]}, |
| PropertyIndex::mapped_type{meta, meta, storage[7]} |
| }, |
| }, |
| }; |
| |
| template <typename T> struct ExpectedValues {}; |
| template <> struct ExpectedValues<uint8_t> |
| { |
| static auto& get(size_t i) |
| { |
| static const std::array<uint8_t, 8> values = |
| { |
| {0, 1, 2, 3, 4, 5, 6, 7}, |
| }; |
| return values[i]; |
| } |
| }; |
| |
| template <> struct ExpectedValues<uint16_t> |
| { |
| static auto& get(size_t i) |
| { |
| static const std::array<uint16_t, 8> values = |
| { |
| {88, 77, 66, 55, 44, 33, 22, 11}, |
| }; |
| return values[i]; |
| } |
| }; |
| |
| template <> struct ExpectedValues<uint32_t> |
| { |
| static auto& get(size_t i) |
| { |
| static const std::array<uint32_t, 8> values = |
| { |
| {0xffffffff, 1, 3, 0, 5, 7, 9, 0xffffffff}, |
| }; |
| return values[i]; |
| } |
| }; |
| |
| template <> struct ExpectedValues<uint64_t> |
| { |
| static auto& get(size_t i) |
| { |
| static const std::array<uint64_t, 8> values = |
| { |
| {0xffffffffffffffff, 3, 7, 12234, 0, 3, 9, 0xffffffff}, |
| }; |
| return values[i]; |
| } |
| }; |
| |
| template <> struct ExpectedValues<std::string> |
| { |
| static auto& get(size_t i) |
| { |
| static const std::array<std::string, 8> values = |
| { |
| {""s, "foo"s, "bar"s, "baz"s, "hello"s, "string", "\x2\x3", "\\"}, |
| }; |
| return values[i]; |
| } |
| }; |
| |
| template <typename T> |
| void testStart() |
| { |
| using ::testing::Return; |
| using ::testing::_; |
| |
| MockDBusInterface dbus; |
| MockDBusInterface::instance(dbus); |
| |
| const std::vector<std::string> expectedMapperInterfaces; |
| PropertyWatchOfType<T, MockDBusInterface> watch(watchIndex); |
| |
| auto ndx = static_cast<size_t>(0); |
| for (const auto& o : convert(watchIndex)) |
| { |
| const auto& path = o.first.get(); |
| const auto& interfaces = o.second; |
| std::vector<std::string> mapperResponse; |
| std::transform( |
| interfaces.begin(), |
| interfaces.end(), |
| std::back_inserter(mapperResponse), |
| // *INDENT-OFF* |
| [](const auto & item) |
| { |
| return item.first; |
| }); |
| // *INDENT-ON* |
| EXPECT_CALL( |
| dbus, |
| mapperGetObject( |
| MAPPER_BUSNAME, |
| MAPPER_PATH, |
| MAPPER_INTERFACE, |
| "GetObject", |
| path, |
| expectedMapperInterfaces)) |
| .WillOnce(Return(GetObject({{"", mapperResponse}}))); |
| EXPECT_CALL( |
| dbus, |
| fwdAddMatch( |
| sdbusplus::bus::match::rules::member("InterfacesAdded") + |
| sdbusplus::bus::match::rules::path(path) + |
| sdbusplus::bus::match::rules::interface( |
| "org.freedesktop.DBus.ObjectManager"), |
| _)); |
| for (const auto& i : interfaces) |
| { |
| const auto& interface = i.first.get(); |
| const auto& properties = i.second; |
| EXPECT_CALL( |
| dbus, |
| fwdAddMatch( |
| sdbusplus::bus::match::rules::member("PropertiesChanged") + |
| sdbusplus::bus::match::rules::path(path) + |
| sdbusplus::bus::match::rules::argN(0, interface) + |
| sdbusplus::bus::match::rules::interface( |
| "org.freedesktop.DBus.Properties"), |
| _)); |
| |
| PropertiesChanged<T> serviceResponse; |
| for (const auto& p : properties) |
| { |
| serviceResponse[p] = ExpectedValues<T>::get(ndx); |
| ++ndx; |
| } |
| Expect<T>::getProperties(dbus, path, interface) |
| .WillOnce(Return(serviceResponse)); |
| } |
| } |
| |
| watch.start(); |
| |
| ndx = 0; |
| for (auto s : storage) |
| { |
| ASSERT_EQ(s.empty(), false); |
| ASSERT_EQ(any_ns::any_cast<T>(s), ExpectedValues<T>::get(ndx)); |
| ++ndx; |
| } |
| |
| // Make sure start logic only runs the first time. |
| watch.start(); |
| } |
| |
| TEST(PropertyWatchTest, TestStart) |
| { |
| testStart<uint8_t>(); |
| testStart<uint16_t>(); |
| testStart<uint32_t>(); |
| testStart<uint64_t>(); |
| testStart<std::string>(); |
| } |
| |
| MockDBusInterface* MockDBusInterface::ptr = nullptr; |