1 #include "propertywatchtest.hpp" 2 3 #include "propertywatchimpl.hpp" 4 5 #include <array> 6 7 using namespace std::string_literals; 8 using namespace phosphor::dbus::monitoring; 9 10 const std::array<std::string, 4> paths = { 11 "/xyz/openbmc_project/testing/inst1"s, 12 "/xyz/openbmc_project/testing/inst2"s, 13 "/xyz/openbmc_project/testing/inst3"s, 14 "/xyz/openbmc_project/testing/inst4"s, 15 }; 16 17 const std::array<std::string, 2> interfaces = { 18 "xyz.openbmc_project.Iface1"s, 19 "xyz.openbmc_project.Iface2"s, 20 }; 21 22 const std::array<std::string, 2> properties = { 23 "Value1"s, 24 "Value2"s, 25 }; 26 27 const std::string meta; 28 29 std::array<std::tuple<any_ns::any, any_ns::any>, 8> storage = {}; 30 31 const PropertyIndex watchIndex = { 32 { 33 {PropertyIndex::key_type{paths[0], interfaces[0], properties[0]}, 34 PropertyIndex::mapped_type{meta, meta, storage[0]}}, 35 {PropertyIndex::key_type{paths[0], interfaces[1], properties[1]}, 36 PropertyIndex::mapped_type{meta, meta, storage[1]}}, 37 {PropertyIndex::key_type{paths[1], interfaces[0], properties[0]}, 38 PropertyIndex::mapped_type{meta, meta, storage[2]}}, 39 {PropertyIndex::key_type{paths[1], interfaces[1], properties[1]}, 40 PropertyIndex::mapped_type{meta, meta, storage[3]}}, 41 {PropertyIndex::key_type{paths[2], interfaces[0], properties[0]}, 42 PropertyIndex::mapped_type{meta, meta, storage[4]}}, 43 {PropertyIndex::key_type{paths[2], interfaces[1], properties[1]}, 44 PropertyIndex::mapped_type{meta, meta, storage[5]}}, 45 {PropertyIndex::key_type{paths[3], interfaces[0], properties[0]}, 46 PropertyIndex::mapped_type{meta, meta, storage[6]}}, 47 {PropertyIndex::key_type{paths[3], interfaces[1], properties[1]}, 48 PropertyIndex::mapped_type{meta, meta, storage[7]}}, 49 }, 50 }; 51 52 template <typename T> 53 struct ExpectedValues 54 { 55 }; 56 template <> 57 struct ExpectedValues<uint8_t> 58 { 59 static auto& get(size_t i) 60 { 61 static const std::array<uint8_t, 8> values = { 62 {0, 1, 2, 3, 4, 5, 6, 7}, 63 }; 64 return values[i]; 65 } 66 }; 67 68 template <> 69 struct ExpectedValues<uint16_t> 70 { 71 static auto& get(size_t i) 72 { 73 static const std::array<uint16_t, 8> values = { 74 {88, 77, 66, 55, 44, 33, 22, 11}, 75 }; 76 return values[i]; 77 } 78 }; 79 80 template <> 81 struct ExpectedValues<uint32_t> 82 { 83 static auto& get(size_t i) 84 { 85 static const std::array<uint32_t, 8> values = { 86 {0xffffffff, 1, 3, 0, 5, 7, 9, 0xffffffff}, 87 }; 88 return values[i]; 89 } 90 }; 91 92 template <> 93 struct ExpectedValues<uint64_t> 94 { 95 static auto& get(size_t i) 96 { 97 static const std::array<uint64_t, 8> values = { 98 {0xffffffffffffffff, 3, 7, 12234, 0, 3, 9, 0xffffffff}, 99 }; 100 return values[i]; 101 } 102 }; 103 104 template <> 105 struct ExpectedValues<std::string> 106 { 107 static auto& get(size_t i) 108 { 109 static const std::array<std::string, 8> values = { 110 {""s, "foo"s, "bar"s, "baz"s, "hello"s, "string", "\x2\x3", "\\"}, 111 }; 112 return values[i]; 113 } 114 }; 115 116 template <typename T> 117 void testStart() 118 { 119 using ::testing::_; 120 using ::testing::Return; 121 122 MockDBusInterface dbus; 123 MockDBusInterface::instance(dbus); 124 125 const std::vector<std::string> expectedMapperInterfaces; 126 PropertyWatchOfType<T, MockDBusInterface> watch(watchIndex); 127 128 auto ndx = static_cast<size_t>(0); 129 for (const auto& o : convert(watchIndex)) 130 { 131 const auto& path = o.first.get(); 132 const auto& interfaces = o.second; 133 std::vector<std::string> mapperResponse; 134 std::transform(interfaces.begin(), interfaces.end(), 135 std::back_inserter(mapperResponse), 136 // *INDENT-OFF* 137 [](const auto& item) { return item.first; }); 138 // *INDENT-ON* 139 EXPECT_CALL(dbus, mapperGetObject(MAPPER_BUSNAME, MAPPER_PATH, 140 MAPPER_INTERFACE, "GetObject", path, 141 expectedMapperInterfaces)) 142 .WillOnce(Return(GetObject({{"", mapperResponse}}))); 143 EXPECT_CALL( 144 dbus, fwdAddMatch( 145 sdbusplus::bus::match::rules::member("InterfacesAdded") + 146 sdbusplus::bus::match::rules::path(path) + 147 sdbusplus::bus::match::rules::interface( 148 "org.freedesktop.DBus.ObjectManager"), 149 _)); 150 for (const auto& i : interfaces) 151 { 152 const auto& interface = i.first.get(); 153 const auto& properties = i.second; 154 EXPECT_CALL( 155 dbus, 156 fwdAddMatch( 157 sdbusplus::bus::match::rules::member("PropertiesChanged") + 158 sdbusplus::bus::match::rules::path(path) + 159 sdbusplus::bus::match::rules::argN(0, interface) + 160 sdbusplus::bus::match::rules::interface( 161 "org.freedesktop.DBus.Properties"), 162 _)); 163 164 PropertiesChanged<T> serviceResponse; 165 for (const auto& p : properties) 166 { 167 serviceResponse[p] = ExpectedValues<T>::get(ndx); 168 ++ndx; 169 } 170 Expect<T>::getProperties(dbus, path, interface) 171 .WillOnce(Return(serviceResponse)); 172 } 173 } 174 175 watch.start(); 176 177 ndx = 0; 178 for (auto s : storage) 179 { 180 ASSERT_EQ(std::get<0>(s).empty(), false); 181 ASSERT_EQ(any_ns::any_cast<T>(s), ExpectedValues<T>::get(ndx)); 182 ++ndx; 183 } 184 185 // Make sure start logic only runs the first time. 186 watch.start(); 187 } 188 189 TEST(PropertyWatchTest, TestStart) 190 { 191 testStart<uint8_t>(); 192 testStart<uint16_t>(); 193 testStart<uint32_t>(); 194 testStart<uint64_t>(); 195 testStart<std::string>(); 196 } 197 198 MockDBusInterface* MockDBusInterface::ptr = nullptr; 199