1 #include <boost/container/flat_map.hpp> 2 #include <sdbusplus/unpack_properties.hpp> 3 4 #include <gmock/gmock.h> 5 6 namespace sdbusplus 7 { 8 9 using VariantType = std::variant<std::string, uint32_t, float, double>; 10 using ContainerTypes = 11 testing::Types<std::vector<std::pair<std::string, VariantType>>, 12 boost::container::flat_map<std::string, VariantType>, 13 std::map<std::string, VariantType>>; 14 15 template <typename Exception, typename F> 16 std::optional<Exception> captureException(F&& code) 17 { 18 try 19 { 20 code(); 21 } 22 catch (const Exception& e) 23 { 24 return e; 25 } 26 27 return std::nullopt; 28 } 29 30 template <typename Container> 31 struct UnpackPropertiesTest : public testing::Test 32 { 33 void SetUp() override 34 { 35 using namespace std::string_literals; 36 37 data.insert(data.end(), 38 std::make_pair("Key-1"s, VariantType("string"s))); 39 data.insert(data.end(), std::make_pair("Key-2"s, VariantType(42.f))); 40 data.insert(data.end(), std::make_pair("Key-3"s, VariantType(15.))); 41 } 42 43 Container data; 44 }; 45 46 TYPED_TEST_SUITE(UnpackPropertiesTest, ContainerTypes); 47 48 TYPED_TEST(UnpackPropertiesTest, returnsValueWhenKeyIsPresentAndTypeMatches) 49 { 50 using namespace testing; 51 52 std::string val1; 53 float val2 = 0.f; 54 double val3 = 0.; 55 56 unpackProperties(this->data, "Key-1", val1, "Key-2", val2, "Key-3", val3); 57 58 ASSERT_THAT(val1, Eq("string")); 59 ASSERT_THAT(val2, FloatEq(42.f)); 60 ASSERT_THAT(val3, DoubleEq(15.)); 61 } 62 63 TYPED_TEST(UnpackPropertiesTest, 64 unpackChangesOriginalDataWhenPassedAsNonConstReference) 65 { 66 using namespace testing; 67 68 std::string val1, val2; 69 70 unpackProperties(this->data, "Key-1", val1); 71 unpackProperties(this->data, "Key-1", val2); 72 73 ASSERT_THAT(val1, Eq("string")); 74 ASSERT_THAT(val2, Not(Eq("string"))); 75 } 76 77 TYPED_TEST(UnpackPropertiesTest, 78 unpackDoesntChangeOriginalDataWhenPassesAsConstReference) 79 { 80 using namespace testing; 81 82 std::string val1, val2; 83 84 unpackProperties(Const(this->data), "Key-1", val1); 85 unpackProperties(Const(this->data), "Key-1", val2); 86 87 ASSERT_THAT(val1, Eq("string")); 88 ASSERT_THAT(val2, Eq("string")); 89 } 90 91 TYPED_TEST(UnpackPropertiesTest, throwsErrorWhenKeyIsMissing) 92 { 93 using namespace testing; 94 95 std::string val1; 96 float val2 = 0.f; 97 double val3 = 0.; 98 99 auto error = captureException<exception::UnpackPropertyError>([&] { 100 unpackProperties(this->data, "Key-1", val1, "Key-4", val2, "Key-3", 101 val3); 102 }); 103 104 ASSERT_TRUE(error); 105 ASSERT_THAT(error->reason, 106 Eq(exception::UnpackPropertyError::reasonMissingProperty)); 107 ASSERT_THAT(error->propertyName, Eq("Key-4")); 108 } 109 110 TYPED_TEST(UnpackPropertiesTest, throwsErrorWhenTypeDoesntMatch) 111 { 112 using namespace testing; 113 114 std::string val1; 115 std::string val2; 116 double val3 = 0.; 117 118 auto error = captureException<exception::UnpackPropertyError>([&] { 119 unpackProperties(this->data, "Key-1", val1, "Key-2", val2, "Key-3", 120 val3); 121 }); 122 123 ASSERT_TRUE(error); 124 ASSERT_THAT(error->reason, 125 Eq(exception::UnpackPropertyError::reasonTypeNotMatched)); 126 ASSERT_THAT(error->propertyName, Eq("Key-2")); 127 } 128 129 TYPED_TEST(UnpackPropertiesTest, 130 returnsUndefinedValueForDuplicatedKeysWhenDataIsNonConstReference) 131 { 132 using namespace testing; 133 using namespace std::string_literals; 134 135 std::string val1; 136 float val2 = 0.f; 137 double val3 = 0.; 138 std::string val4; 139 140 unpackProperties(this->data, "Key-1", val1, "Key-2", val2, "Key-3", val3, 141 "Key-1", val4); 142 143 ASSERT_THAT(val1, Eq("string")); 144 ASSERT_THAT(val2, FloatEq(42.f)); 145 ASSERT_THAT(val3, DoubleEq(15.)); 146 ASSERT_THAT(val4, Not(Eq("string"))); 147 } 148 149 TYPED_TEST(UnpackPropertiesTest, 150 returnsValueForDuplicatedKeysWhenDataIsConstReference) 151 { 152 using namespace testing; 153 using namespace std::string_literals; 154 155 std::string val1; 156 float val2 = 0.f; 157 double val3 = 0.; 158 std::string val4; 159 160 unpackProperties(Const(this->data), "Key-1", val1, "Key-2", val2, "Key-3", 161 val3, "Key-1", val4); 162 163 ASSERT_THAT(val1, Eq("string")); 164 ASSERT_THAT(val2, FloatEq(42.f)); 165 ASSERT_THAT(val3, DoubleEq(15.)); 166 ASSERT_THAT(val4, Eq("string")); 167 } 168 169 struct UnpackPropertiesTest_ForVector : 170 public UnpackPropertiesTest< 171 std::vector<std::pair<std::string, VariantType>>> 172 {}; 173 174 TEST_F(UnpackPropertiesTest_ForVector, silentlyDiscardsDuplicatedKeyInData) 175 { 176 using namespace testing; 177 using namespace std::string_literals; 178 179 std::string val1; 180 float val2 = 0.f; 181 double val3 = 0.; 182 183 this->data.insert(this->data.end(), 184 std::make_pair("Key-1"s, VariantType("string2"s))); 185 186 unpackProperties(this->data, "Key-1", val1, "Key-2", val2, "Key-3", val3); 187 188 ASSERT_THAT(val1, Eq("string")); 189 ASSERT_THAT(val2, FloatEq(42.f)); 190 ASSERT_THAT(val3, DoubleEq(15.)); 191 } 192 193 } // namespace sdbusplus 194