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