Darin Petkov | e4b2702 | 2012-05-16 13:28:50 +0200 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium OS Authors. All rights reserved. |
Darin Petkov | e0a312e | 2011-07-20 13:45:28 -0700 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
Darin Petkov | e0a312e | 2011-07-20 13:45:28 -0700 | [diff] [blame] | 5 | #include "shill/dbus_properties.h" |
| 6 | |
Ben Chan | 0a3a3a5 | 2013-07-10 11:34:07 -0700 | [diff] [blame] | 7 | #include <limits> |
| 8 | |
| 9 | #include <gtest/gtest.h> |
| 10 | |
| 11 | using std::numeric_limits; |
Darin Petkov | e0a312e | 2011-07-20 13:45:28 -0700 | [diff] [blame] | 12 | using std::string; |
Jason Glasgow | 9c09e36 | 2012-04-18 15:16:29 -0400 | [diff] [blame] | 13 | using std::vector; |
Darin Petkov | e0a312e | 2011-07-20 13:45:28 -0700 | [diff] [blame] | 14 | using testing::Test; |
| 15 | |
| 16 | namespace shill { |
| 17 | |
Ben Chan | 0a3a3a5 | 2013-07-10 11:34:07 -0700 | [diff] [blame] | 18 | class DBusPropertiesTest : public Test {}; |
Darin Petkov | e4b2702 | 2012-05-16 13:28:50 +0200 | [diff] [blame] | 19 | |
Darin Petkov | 9893d9c | 2012-05-17 15:27:31 -0700 | [diff] [blame] | 20 | TEST_F(DBusPropertiesTest, ConvertPathsToRpcIdentifiers) { |
| 21 | static const char kOldTestPath[] = "/org/chromium/Something/Old"; |
| 22 | static const char kTestPath0[] = "/org/chromium/Something"; |
| 23 | static const char kTestPath1[] = "/org/chromium/Else"; |
| 24 | |
| 25 | RpcIdentifiers ids(1, kOldTestPath); |
| 26 | vector<DBus::Path> paths; |
| 27 | paths.push_back(kTestPath0); |
| 28 | paths.push_back(kTestPath1); |
| 29 | DBusProperties::ConvertPathsToRpcIdentifiers(paths, &ids); |
| 30 | ASSERT_EQ(2, ids.size()); |
| 31 | EXPECT_EQ(kTestPath0, ids[0]); |
| 32 | EXPECT_EQ(kTestPath1, ids[1]); |
| 33 | } |
| 34 | |
Darin Petkov | 25665aa | 2012-05-21 14:08:12 +0200 | [diff] [blame] | 35 | TEST_F(DBusPropertiesTest, ConvertKeyValueStoreToMap) { |
| 36 | static const char kStringKey[] = "StringKey"; |
| 37 | static const char kStringValue[] = "StringValue"; |
Ben Chan | 0a3a3a5 | 2013-07-10 11:34:07 -0700 | [diff] [blame] | 38 | static const char kStringsKey[] = "StringsKey"; |
| 39 | const vector<string> kStringsValue = {"StringsValue1", "StringsValue2"}; |
Darin Petkov | 25665aa | 2012-05-21 14:08:12 +0200 | [diff] [blame] | 40 | static const char kBoolKey[] = "BoolKey"; |
| 41 | const bool kBoolValue = true; |
| 42 | static const char kInt32Key[] = "Int32Key"; |
| 43 | const int32 kInt32Value = 123; |
| 44 | static const char kUint32Key[] = "Uint32Key"; |
| 45 | const uint32 kUint32Value = 654; |
| 46 | KeyValueStore store; |
| 47 | store.SetString(kStringKey, kStringValue); |
Ben Chan | 0a3a3a5 | 2013-07-10 11:34:07 -0700 | [diff] [blame] | 48 | store.SetStrings(kStringsKey, kStringsValue); |
Darin Petkov | 25665aa | 2012-05-21 14:08:12 +0200 | [diff] [blame] | 49 | store.SetBool(kBoolKey, kBoolValue); |
| 50 | store.SetInt(kInt32Key, kInt32Value); |
| 51 | store.SetUint(kUint32Key, kUint32Value); |
| 52 | DBusPropertiesMap props; |
| 53 | props["RandomKey"].writer().append_string("RandomValue"); |
| 54 | DBusProperties::ConvertKeyValueStoreToMap(store, &props); |
Ben Chan | 0a3a3a5 | 2013-07-10 11:34:07 -0700 | [diff] [blame] | 55 | EXPECT_EQ(5, props.size()); |
Darin Petkov | 25665aa | 2012-05-21 14:08:12 +0200 | [diff] [blame] | 56 | string string_value; |
| 57 | EXPECT_TRUE(DBusProperties::GetString(props, kStringKey, &string_value)); |
| 58 | EXPECT_EQ(kStringValue, string_value); |
Ben Chan | 0a3a3a5 | 2013-07-10 11:34:07 -0700 | [diff] [blame] | 59 | vector<string> strings_value; |
| 60 | EXPECT_TRUE(DBusProperties::GetStrings(props, kStringsKey, &strings_value)); |
| 61 | EXPECT_EQ(kStringsValue, strings_value); |
Darin Petkov | 25665aa | 2012-05-21 14:08:12 +0200 | [diff] [blame] | 62 | bool bool_value = !kBoolValue; |
| 63 | EXPECT_TRUE(DBusProperties::GetBool(props, kBoolKey, &bool_value)); |
| 64 | EXPECT_EQ(kBoolValue, bool_value); |
| 65 | int32 int32_value = ~kInt32Value; |
| 66 | EXPECT_TRUE(DBusProperties::GetInt32(props, kInt32Key, &int32_value)); |
| 67 | EXPECT_EQ(kInt32Value, int32_value); |
| 68 | uint32 uint32_value = ~kUint32Value; |
| 69 | EXPECT_TRUE(DBusProperties::GetUint32(props, kUint32Key, &uint32_value)); |
| 70 | EXPECT_EQ(kUint32Value, uint32_value); |
| 71 | } |
| 72 | |
Ben Chan | 0a3a3a5 | 2013-07-10 11:34:07 -0700 | [diff] [blame] | 73 | template <typename T> class DBusPropertiesGetterTest : public Test {}; |
| 74 | |
| 75 | template <typename DerivedT, typename ValueT, typename DBusT = ValueT> |
| 76 | struct TestTraits { |
| 77 | typedef ValueT ValueType; |
| 78 | typedef DBusT DBusType; |
| 79 | typedef bool (*GetterType)(const DBusPropertiesMap &properties, |
| 80 | const string &key, |
| 81 | ValueType *value); |
| 82 | |
| 83 | static DBusType GetTestValue() { return DerivedT::GetNewValue(); } |
| 84 | |
| 85 | static void CheckValueEqual(const ValueType &expected, |
| 86 | const ValueType &actual) { |
| 87 | EXPECT_EQ(expected, actual); |
| 88 | } |
| 89 | }; |
| 90 | |
| 91 | struct BoolTestTraits : public TestTraits<BoolTestTraits, bool> { |
| 92 | static bool GetOldValue() { return false; } |
| 93 | static bool GetNewValue() { return true; } |
| 94 | static constexpr GetterType kMethodUnderTest = &DBusProperties::GetBool; |
| 95 | }; |
| 96 | |
| 97 | template <typename DerivedT, typename ValueT> |
| 98 | struct IntTestTraits : public TestTraits<DerivedT, ValueT> { |
| 99 | static ValueT GetOldValue() { return numeric_limits<ValueT>::min(); } |
| 100 | static ValueT GetNewValue() { return numeric_limits<ValueT>::max(); } |
| 101 | }; |
| 102 | |
| 103 | struct Int16TestTraits : public IntTestTraits<Int16TestTraits, int16> { |
| 104 | static constexpr GetterType kMethodUnderTest = &DBusProperties::GetInt16; |
| 105 | }; |
| 106 | |
| 107 | struct Int32TestTraits : public IntTestTraits<Int32TestTraits, int32> { |
| 108 | static constexpr GetterType kMethodUnderTest = &DBusProperties::GetInt32; |
| 109 | }; |
| 110 | |
| 111 | struct Int64TestTraits : public IntTestTraits<Int64TestTraits, int64> { |
| 112 | static constexpr GetterType kMethodUnderTest = &DBusProperties::GetInt64; |
| 113 | }; |
| 114 | |
| 115 | struct Uint8TestTraits : public IntTestTraits<Uint8TestTraits, uint8> { |
| 116 | static constexpr GetterType kMethodUnderTest = &DBusProperties::GetUint8; |
| 117 | }; |
| 118 | |
| 119 | struct Uint16TestTraits : public IntTestTraits<Uint16TestTraits, uint16> { |
| 120 | static constexpr GetterType kMethodUnderTest = &DBusProperties::GetUint16; |
| 121 | }; |
| 122 | |
| 123 | struct Uint32TestTraits : public IntTestTraits<Uint32TestTraits, uint32> { |
| 124 | static constexpr GetterType kMethodUnderTest = &DBusProperties::GetUint32; |
| 125 | }; |
| 126 | |
| 127 | struct Uint64TestTraits : public IntTestTraits<Uint64TestTraits, uint64> { |
| 128 | static constexpr GetterType kMethodUnderTest = &DBusProperties::GetUint64; |
| 129 | }; |
| 130 | |
| 131 | struct DoubleTestTraits : public TestTraits<DoubleTestTraits, double> { |
| 132 | static double GetOldValue() { return -1.1; } |
| 133 | static double GetNewValue() { return 3.14; } |
| 134 | static constexpr GetterType kMethodUnderTest = &DBusProperties::GetDouble; |
| 135 | }; |
| 136 | |
| 137 | struct StringTestTraits : public TestTraits<StringTestTraits, string> { |
| 138 | static string GetOldValue() { return "old"; } |
| 139 | static string GetNewValue() { return "new"; } |
| 140 | static constexpr GetterType kMethodUnderTest = &DBusProperties::GetString; |
| 141 | }; |
| 142 | |
| 143 | struct StringsTestTraits |
| 144 | : public TestTraits<StringsTestTraits, vector<string>> { |
| 145 | static vector<string> GetOldValue() { return {"1", "2", "3"}; } |
| 146 | static vector<string> GetNewValue() { return {"a", "b"}; } |
| 147 | static constexpr GetterType kMethodUnderTest = &DBusProperties::GetStrings; |
| 148 | }; |
| 149 | |
| 150 | struct ObjectPathTestTraits |
| 151 | : public TestTraits<ObjectPathTestTraits, DBus::Path> { |
| 152 | static DBus::Path GetOldValue() { return "/old/path"; } |
| 153 | static DBus::Path GetNewValue() { return "/new/path"; } |
| 154 | static constexpr GetterType kMethodUnderTest = &DBusProperties::GetObjectPath; |
| 155 | }; |
| 156 | |
| 157 | struct RpcIdentifiersTestTraits : public TestTraits<RpcIdentifiersTestTraits, |
| 158 | RpcIdentifiers, |
| 159 | vector<DBus::Path>> { |
| 160 | static RpcIdentifiers GetOldValue() { return {"/device/1", "/service/2"}; } |
| 161 | static RpcIdentifiers GetNewValue() { return {"/obj/3", "/obj/4", "/obj/5"}; } |
| 162 | static vector<DBus::Path> GetTestValue() { |
| 163 | return {"/obj/3", "/obj/4", "/obj/5"}; |
| 164 | } |
| 165 | static constexpr GetterType kMethodUnderTest = |
| 166 | &DBusProperties::GetRpcIdentifiers; |
| 167 | }; |
| 168 | |
| 169 | struct DBusPropertiesMapTestTraits |
| 170 | : public TestTraits<DBusPropertiesMapTestTraits, DBusPropertiesMap> { |
| 171 | static DBusPropertiesMap GetOldValue() { |
| 172 | DBusPropertiesMap value; |
| 173 | value["OldKey"].writer().append_bool(false); |
| 174 | return value; |
| 175 | } |
| 176 | |
| 177 | static DBusPropertiesMap GetNewValue() { |
| 178 | DBusPropertiesMap value; |
| 179 | value["BoolKey"].writer().append_bool(true); |
| 180 | value["Int16Key"].writer().append_int16(numeric_limits<int16>::max()); |
| 181 | value["Int32Key"].writer().append_int32(numeric_limits<int32>::max()); |
| 182 | value["Int64Key"].writer().append_int64(numeric_limits<int64>::max()); |
| 183 | value["Uint8Key"].writer().append_byte(numeric_limits<uint8>::max()); |
| 184 | value["Uint16Key"].writer().append_uint16(numeric_limits<uint16>::max()); |
| 185 | value["Uint32Key"].writer().append_uint32(numeric_limits<uint32>::max()); |
| 186 | value["Uint64Key"].writer().append_uint64(numeric_limits<uint64>::max()); |
| 187 | value["DoubleKey"].writer().append_double(3.14); |
| 188 | value["StringKey"].writer().append_string("new"); |
| 189 | return value; |
| 190 | } |
| 191 | |
| 192 | template <typename T> |
| 193 | static void CheckDBusVariantEqual(const string &key, |
| 194 | const DBus::Variant &expected, |
| 195 | const DBus::Variant &actual) { |
| 196 | T expected_value = expected.operator T(); |
| 197 | T actual_value = actual.operator T(); |
| 198 | EXPECT_EQ(expected_value, actual_value) << "Value mismatch - key: " << key; |
| 199 | } |
| 200 | |
| 201 | static void CheckValueEqual(const DBusPropertiesMap &expected, |
| 202 | const DBusPropertiesMap &actual) { |
| 203 | ASSERT_EQ(expected.size(), actual.size()) << "Map size mismatch"; |
| 204 | |
| 205 | for (const auto &key_value_pair : expected) { |
| 206 | const string &key = key_value_pair.first; |
| 207 | |
| 208 | const auto &actual_it = actual.find(key); |
| 209 | ASSERT_TRUE(actual_it != actual.end()) << "Key '" << key << "' not found"; |
| 210 | |
| 211 | const DBus::Variant &actual_value = actual_it->second; |
| 212 | const DBus::Variant &expected_value = key_value_pair.second; |
| 213 | |
| 214 | string actual_signature = actual_value.signature(); |
| 215 | string expected_signature = expected_value.signature(); |
| 216 | ASSERT_EQ(expected_signature, actual_signature) |
| 217 | << "Value type mismatch - key: " << key; |
| 218 | |
| 219 | if (expected_signature == DBus::type<bool>::sig()) { |
| 220 | CheckDBusVariantEqual<bool>(key, expected_value, actual_value); |
| 221 | } else if (expected_signature == DBus::type<int16>::sig()) { |
| 222 | CheckDBusVariantEqual<int16>(key, expected_value, actual_value); |
| 223 | } else if (expected_signature == DBus::type<int32>::sig()) { |
| 224 | CheckDBusVariantEqual<int32>(key, expected_value, actual_value); |
| 225 | } else if (expected_signature == DBus::type<int64>::sig()) { |
| 226 | CheckDBusVariantEqual<int64>(key, expected_value, actual_value); |
| 227 | } else if (expected_signature == DBus::type<uint8>::sig()) { |
| 228 | CheckDBusVariantEqual<uint8>(key, expected_value, actual_value); |
| 229 | } else if (expected_signature == DBus::type<uint16>::sig()) { |
| 230 | CheckDBusVariantEqual<uint16>(key, expected_value, actual_value); |
| 231 | } else if (expected_signature == DBus::type<uint32>::sig()) { |
| 232 | CheckDBusVariantEqual<uint32>(key, expected_value, actual_value); |
| 233 | } else if (expected_signature == DBus::type<uint64>::sig()) { |
| 234 | CheckDBusVariantEqual<uint64>(key, expected_value, actual_value); |
| 235 | } else if (expected_signature == DBus::type<double>::sig()) { |
| 236 | CheckDBusVariantEqual<double>(key, expected_value, actual_value); |
| 237 | } else if (expected_signature == DBus::type<string>::sig()) { |
| 238 | CheckDBusVariantEqual<string>(key, expected_value, actual_value); |
| 239 | } else if (expected_signature == DBus::type<DBus::Path>::sig()) { |
| 240 | CheckDBusVariantEqual<DBus::Path>(key, expected_value, actual_value); |
| 241 | } else { |
| 242 | // TODO(benchan): Comparison of other types is not yet implemented. |
| 243 | FAIL() << "Value type '" << expected_signature << "' not implemented."; |
| 244 | } |
| 245 | } |
| 246 | } |
| 247 | |
| 248 | static constexpr GetterType kMethodUnderTest = |
| 249 | &DBusProperties::GetDBusPropertiesMap; |
| 250 | }; |
| 251 | |
| 252 | typedef testing::Types<BoolTestTraits, |
| 253 | Int16TestTraits, |
| 254 | Int32TestTraits, |
| 255 | Int64TestTraits, |
| 256 | Uint8TestTraits, |
| 257 | Uint16TestTraits, |
| 258 | Uint32TestTraits, |
| 259 | Uint64TestTraits, |
| 260 | DoubleTestTraits, |
| 261 | StringTestTraits, |
| 262 | StringsTestTraits, |
| 263 | ObjectPathTestTraits, |
| 264 | RpcIdentifiersTestTraits, |
| 265 | DBusPropertiesMapTestTraits> DBusPropertyValueTypes; |
| 266 | TYPED_TEST_CASE(DBusPropertiesGetterTest, DBusPropertyValueTypes); |
| 267 | |
| 268 | TYPED_TEST(DBusPropertiesGetterTest, GetValue) { |
| 269 | static const char kTestProperty[] = "TestProperty"; |
| 270 | const typename TypeParam::ValueType kOldValue = TypeParam::GetOldValue(); |
| 271 | const typename TypeParam::ValueType kNewValue = TypeParam::GetNewValue(); |
| 272 | const typename TypeParam::DBusType kTestValue = TypeParam::GetTestValue(); |
| 273 | typename TypeParam::ValueType value = kOldValue; |
| 274 | DBusPropertiesMap properties; |
| 275 | |
| 276 | // Property key is not found. |value| should remain the initial value. |
| 277 | EXPECT_FALSE(TypeParam::kMethodUnderTest(properties, kTestProperty, &value)); |
| 278 | TypeParam::CheckValueEqual(kOldValue, value); |
| 279 | |
| 280 | // Property value type mismatch. |value| should remain the initial value. |
| 281 | properties[kTestProperty].writer().append_fd(1); |
| 282 | EXPECT_FALSE(TypeParam::kMethodUnderTest(properties, kTestProperty, &value)); |
| 283 | TypeParam::CheckValueEqual(kOldValue, value); |
| 284 | |
| 285 | // Property key is found. |value| should be set to the test value. |
| 286 | properties.clear(); |
| 287 | DBus::MessageIter writer = properties[kTestProperty].writer(); |
| 288 | writer << kTestValue; |
| 289 | EXPECT_TRUE(TypeParam::kMethodUnderTest(properties, kTestProperty, &value)); |
| 290 | TypeParam::CheckValueEqual(kNewValue, value); |
| 291 | } |
| 292 | |
Darin Petkov | e0a312e | 2011-07-20 13:45:28 -0700 | [diff] [blame] | 293 | } // namespace shill |