1 /* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License, version 2.0,
5  as published by the Free Software Foundation.
6 
7  This program is also distributed with certain software (including
8  but not limited to OpenSSL) that is licensed under separate terms,
9  as designated in a particular file or component or in included license
10  documentation.  The authors of MySQL hereby grant you an additional
11  permission to link the program and your derivative works with the
12  separately licensed software that they have included with MySQL.
13 
14  This program is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  GNU General Public License, version 2.0, for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with this program; if not, write to the Free Software
21  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
22 
23 #include "my_config.h"
24 
25 #include <gmock/gmock.h>
26 #include <gtest/gtest.h>
27 
28 #include "plugin/x/src/account_verification_handler.h"
29 #include "plugin/x/src/capabilities/handler_auth_mech.h"
30 #include "plugin/x/src/capabilities/handler_client_interactive.h"
31 #include "plugin/x/src/capabilities/handler_connection_attributes.h"
32 #include "plugin/x/src/capabilities/handler_tls.h"
33 #include "plugin/x/src/sql_user_require.h"
34 #include "unittest/gunit/xplugin/xpl/assert_error_code.h"
35 #include "unittest/gunit/xplugin/xpl/mock/capabilities.h"
36 #include "unittest/gunit/xplugin/xpl/mock/ngs_general.h"
37 #include "unittest/gunit/xplugin/xpl/mock/session.h"
38 #include "unittest/gunit/xplugin/xpl/mysqlx_pb_wrapper.h"
39 
40 namespace xpl {
41 
42 namespace test {
43 
44 using ::testing::_;
45 using ::testing::Return;
46 using ::testing::ReturnRef;
47 using ::testing::SetArgPointee;
48 using ::testing::StrictMock;
49 using ::testing::Test;
50 using ::testing::WithParamInterface;
51 using xpl::test::Mock_authentication_container;
52 
53 class CapabilityHanderTlsTestSuite : public Test {
54  public:
CapabilityHanderTlsTestSuite()55   CapabilityHanderTlsTestSuite() : sut(mock_client) {
56     EXPECT_CALL(mock_client, connection())
57         .WillRepeatedly(ReturnRef(mock_connection));
58     EXPECT_CALL(mock_client, server()).WillRepeatedly(ReturnRef(mock_server));
59     EXPECT_CALL(mock_server, ssl_context())
60         .WillRepeatedly(Return(&mock_ssl_context));
61   }
62 
63   StrictMock<Mock_vio> mock_connection;
64   StrictMock<Mock_client> mock_client;
65   StrictMock<Mock_ssl_context> mock_ssl_context;
66   StrictMock<Mock_server> mock_server;
67 
68   Capability_tls sut;
69 };
70 
TEST_F(CapabilityHanderTlsTestSuite,isSupported_returnsCurrentConnectionOption_on_supported_connection_type)71 TEST_F(
72     CapabilityHanderTlsTestSuite,
73     isSupported_returnsCurrentConnectionOption_on_supported_connection_type) {
74   EXPECT_CALL(mock_ssl_context, has_ssl())
75       .WillOnce(Return(true))
76       .WillOnce(Return(false));
77   EXPECT_CALL(mock_connection, get_type())
78       .WillOnce(Return(xpl::Connection_tcpip))
79       .WillOnce(Return(xpl::Connection_tcpip));
80 
81   ASSERT_TRUE(sut.is_supported());
82   ASSERT_FALSE(sut.is_supported());
83 }
84 
TEST_F(CapabilityHanderTlsTestSuite,isSupported_returnsFailure_on_unsupported_connection_type)85 TEST_F(CapabilityHanderTlsTestSuite,
86        isSupported_returnsFailure_on_unsupported_connection_type) {
87   EXPECT_CALL(mock_ssl_context, has_ssl())
88       .WillOnce(Return(true))
89       .WillOnce(Return(false));
90   EXPECT_CALL(mock_connection, get_type())
91       .WillOnce(Return(xpl::Connection_namedpipe))
92       .WillOnce(Return(xpl::Connection_namedpipe));
93 
94   ASSERT_FALSE(sut.is_supported());
95   ASSERT_FALSE(sut.is_supported());
96 }
97 
TEST_F(CapabilityHanderTlsTestSuite,name_returnsTls_always)98 TEST_F(CapabilityHanderTlsTestSuite, name_returnsTls_always) {
99   ASSERT_STREQ("tls", sut.name().c_str());
100 }
101 
TEST_F(CapabilityHanderTlsTestSuite,get_returnsCurrentConnectionOption_always)102 TEST_F(CapabilityHanderTlsTestSuite,
103        get_returnsCurrentConnectionOption_always) {
104   const bool expected_result = true;
105   ::Mysqlx::Datatypes::Any any;
106 
107   EXPECT_CALL(mock_connection, get_type())
108       .WillOnce(Return(xpl::Connection_type::Connection_tls));
109 
110   sut.get(&any);
111 
112   ASSERT_EQ(::Mysqlx::Datatypes::Any::SCALAR, any.type());
113   ASSERT_EQ(::Mysqlx::Datatypes::Scalar::V_BOOL, any.scalar().type());
114   ASSERT_EQ(expected_result, any.scalar().v_bool());
115 }
116 
117 class Set_params {
118  public:
119   template <typename T>
Set_params(T any,bool tls)120   Set_params(T any, bool tls) : m_tls_active(tls) {
121     m_any = Any{Scalar{any}};
122 
123     m_tls_active = tls;
124   }
125 
126   Any m_any;
127   bool m_tls_active;
128 };
129 
operator <<(::std::ostream & os,const Set_params & set_param)130 ::std::ostream &operator<<(::std::ostream &os, const Set_params &set_param) {
131   return os << "tls-active:" << set_param.m_tls_active << std::endl;
132 }
133 
134 class SuccessSetCapabilityHanderTlsTestSuite
135     : public CapabilityHanderTlsTestSuite,
136       public WithParamInterface<Set_params> {
137  public:
138 };
139 
TEST_P(SuccessSetCapabilityHanderTlsTestSuite,get_success_forValidParametersAndTlsSupportedOnTcpip)140 TEST_P(SuccessSetCapabilityHanderTlsTestSuite,
141        get_success_forValidParametersAndTlsSupportedOnTcpip) {
142   auto s = GetParam();
143 
144   EXPECT_CALL(mock_ssl_context, has_ssl()).WillOnce(Return(true));
145   EXPECT_CALL(mock_connection, get_type())
146       .WillRepeatedly(Return(xpl::Connection_tcpip));
147 
148   ASSERT_EQ(ER_X_SUCCESS, sut.set(s.m_any).error);
149 
150   EXPECT_CALL(mock_client, activate_tls_void());
151 
152   sut.commit();
153 }
154 
TEST_P(SuccessSetCapabilityHanderTlsTestSuite,get_failure_forValidParametersAndTlsSupportedOnNamedPipe)155 TEST_P(SuccessSetCapabilityHanderTlsTestSuite,
156        get_failure_forValidParametersAndTlsSupportedOnNamedPipe) {
157   Set_params s = GetParam();
158 
159   EXPECT_CALL(mock_ssl_context, has_ssl()).WillOnce(Return(true));
160   EXPECT_CALL(mock_connection, get_type())
161       .WillRepeatedly(Return(xpl::Connection_namedpipe));
162 
163   ASSERT_EQ(ER_X_CAPABILITIES_PREPARE_FAILED, sut.set(s.m_any).error);
164 }
165 
TEST_P(SuccessSetCapabilityHanderTlsTestSuite,get_failure_forValidParametersAndTlsIsntSupported)166 TEST_P(SuccessSetCapabilityHanderTlsTestSuite,
167        get_failure_forValidParametersAndTlsIsntSupported) {
168   Set_params s = GetParam();
169 
170   EXPECT_CALL(mock_ssl_context, has_ssl()).WillOnce(Return(false));
171   EXPECT_CALL(mock_connection, get_type())
172       .WillRepeatedly(Return(xpl::Connection_tcpip));
173 
174   ASSERT_EQ(ER_X_CAPABILITIES_PREPARE_FAILED, sut.set(s.m_any).error);
175 }
176 
177 INSTANTIATE_TEST_CASE_P(
178     SuccessInstantiation, SuccessSetCapabilityHanderTlsTestSuite,
179     ::testing::Values(Set_params(true, false), Set_params(1, false),
180                       Set_params(2, false), Set_params(3u, false),
181                       Set_params(1.0, false)));
182 
183 class FaildSetCapabilityHanderTlsTestSuite
184     : public SuccessSetCapabilityHanderTlsTestSuite {};
185 
TEST_P(FaildSetCapabilityHanderTlsTestSuite,get_failure_forValidParameters)186 TEST_P(FaildSetCapabilityHanderTlsTestSuite, get_failure_forValidParameters) {
187   Set_params s = GetParam();
188 
189   EXPECT_CALL(mock_connection, get_type())
190       .WillRepeatedly(
191           Return(s.m_tls_active ? xpl::Connection_tls : xpl::Connection_tcpip));
192 
193   ASSERT_EQ(ER_X_CAPABILITIES_PREPARE_FAILED, sut.set(s.m_any).error);
194 
195   sut.commit();
196 }
197 
198 INSTANTIATE_TEST_CASE_P(
199     FaildInstantiationAlreadySet, FaildSetCapabilityHanderTlsTestSuite,
200     ::testing::Values(Set_params(true, true), Set_params(1, true),
201                       Set_params(2, true), Set_params(3u, true),
202                       Set_params(1.0, true)));
203 
204 INSTANTIATE_TEST_CASE_P(
205     FaildInstantiationCantDisable, FaildSetCapabilityHanderTlsTestSuite,
206     ::testing::Values(Set_params(false, true), Set_params(0, true),
207                       Set_params(0u, true), Set_params(0.0, true)));
208 
209 INSTANTIATE_TEST_CASE_P(FaildInstantiationAlreadyDisabled,
210                         FaildSetCapabilityHanderTlsTestSuite,
211                         ::testing::Values(Set_params(0, false),
212                                           Set_params(false, false)));
213 
214 class CapabilityHanderAuthMechTestSuite : public Test {
215  public:
CapabilityHanderAuthMechTestSuite()216   CapabilityHanderAuthMechTestSuite() : sut(mock_client) {
217     mock_server = std::make_shared<StrictMock<Mock_server>>();
218 
219     EXPECT_CALL(mock_client, connection())
220         .WillRepeatedly(ReturnRef(mock_connection));
221     EXPECT_CALL(mock_client, server()).WillRepeatedly(ReturnRef(*mock_server));
222   }
223 
224   std::shared_ptr<StrictMock<Mock_server>> mock_server;
225 
226   StrictMock<Mock_vio> mock_connection;
227   StrictMock<Mock_client> mock_client;
228 
229   Capability_auth_mech sut;
230 };
231 
TEST_F(CapabilityHanderAuthMechTestSuite,isSupported_returnsTrue_always)232 TEST_F(CapabilityHanderAuthMechTestSuite, isSupported_returnsTrue_always) {
233   ASSERT_TRUE(sut.is_supported());
234 }
235 
TEST_F(CapabilityHanderAuthMechTestSuite,set_returnsFalse_always)236 TEST_F(CapabilityHanderAuthMechTestSuite, set_returnsFalse_always) {
237   Set_params set(1, false);
238 
239   ASSERT_EQ(ER_X_CAPABILITIES_PREPARE_FAILED, sut.set(set.m_any).error);
240 }
241 
TEST_F(CapabilityHanderAuthMechTestSuite,commit_doesNothing_always)242 TEST_F(CapabilityHanderAuthMechTestSuite, commit_doesNothing_always) {
243   sut.commit();
244 }
245 
TEST_F(CapabilityHanderAuthMechTestSuite,name)246 TEST_F(CapabilityHanderAuthMechTestSuite, name) {
247   ASSERT_STREQ("authentication.mechanisms", sut.name().c_str());
248 }
249 
TEST_F(CapabilityHanderAuthMechTestSuite,get_doesNothing_whenEmptySetReceive)250 TEST_F(CapabilityHanderAuthMechTestSuite, get_doesNothing_whenEmptySetReceive) {
251   std::vector<std::string> names{};
252   ::Mysqlx::Datatypes::Any any;
253   Mock_authentication_container mock_auth;
254 
255   EXPECT_CALL(*mock_server, get_authentications())
256       .WillOnce(ReturnRef(mock_auth));
257 
258   EXPECT_CALL(mock_auth, get_authentication_mechanisms(&mock_client))
259       .WillOnce(Return(names));
260   sut.get(&any);
261 
262   ASSERT_EQ(::Mysqlx::Datatypes::Any::ARRAY, any.type());
263   EXPECT_EQ(0, any.array().value_size());
264 }
265 
TEST_F(CapabilityHanderAuthMechTestSuite,get_returnAuthMethodsFromServer_always)266 TEST_F(CapabilityHanderAuthMechTestSuite,
267        get_returnAuthMethodsFromServer_always) {
268   std::vector<std::string> names{"first", "second"};
269   ::Mysqlx::Datatypes::Any any;
270 
271   StrictMock<Mock_authentication_container> mock_auth;
272 
273   EXPECT_CALL(*mock_server, get_authentications())
274       .WillOnce(ReturnRef(mock_auth));
275 
276   EXPECT_CALL(mock_auth, get_authentication_mechanisms(_))
277       .WillOnce(Return(names));
278 
279   sut.get(&any);
280 
281   ASSERT_EQ(::Mysqlx::Datatypes::Any::ARRAY, any.type());
282   ASSERT_EQ(static_cast<int>(names.size()), any.array().value_size());
283 
284   for (std::size_t i = 0; i < names.size(); ++i) {
285     const auto &a = any.array().value(static_cast<int>(i));
286 
287     ASSERT_EQ(::Mysqlx::Datatypes::Any::SCALAR, a.type());
288     ASSERT_EQ(::Mysqlx::Datatypes::Scalar::V_STRING, a.scalar().type());
289     ASSERT_STREQ(names[i].c_str(), a.scalar().v_string().value().c_str());
290   }
291 }
292 
293 class Capability_hander_client_interactive_test_suite : public Test {
294  public:
295   Capability_hander_client_interactive_test_suite() = default;
296 
SetUp()297   void SetUp() {
298     EXPECT_CALL(mock_client, is_interactive()).WillOnce(Return(false));
299     sut.reset(new Capability_client_interactive(mock_client));
300   }
301 
302   std::unique_ptr<Capability_client_interactive> sut;
303   StrictMock<Mock_client> mock_client;
304 };
305 
TEST_F(Capability_hander_client_interactive_test_suite,is_supported_returns_true_always)306 TEST_F(Capability_hander_client_interactive_test_suite,
307        is_supported_returns_true_always) {
308   ASSERT_TRUE(sut->is_supported());
309 }
310 
TEST_F(Capability_hander_client_interactive_test_suite,name_returns_client_interactive_always)311 TEST_F(Capability_hander_client_interactive_test_suite,
312        name_returns_client_interactive_always) {
313   ASSERT_STREQ("client.interactive", sut->name().c_str());
314 }
315 
TEST_F(Capability_hander_client_interactive_test_suite,get_when_client_is_interactive)316 TEST_F(Capability_hander_client_interactive_test_suite,
317        get_when_client_is_interactive) {
318   EXPECT_CALL(mock_client, is_interactive()).WillOnce(Return(true));
319   sut.reset(new Capability_client_interactive(mock_client));
320 
321   const bool expected_result = true;
322   ::Mysqlx::Datatypes::Any any;
323 
324   sut->get(&any);
325 
326   ASSERT_EQ(::Mysqlx::Datatypes::Any::SCALAR, any.type());
327   ASSERT_EQ(::Mysqlx::Datatypes::Scalar::V_BOOL, any.scalar().type());
328   ASSERT_EQ(expected_result, any.scalar().v_bool());
329 }
330 
TEST_F(Capability_hander_client_interactive_test_suite,get_when_client_is_not_interactive)331 TEST_F(Capability_hander_client_interactive_test_suite,
332        get_when_client_is_not_interactive) {
333   EXPECT_CALL(mock_client, is_interactive()).WillOnce(Return(false));
334   sut.reset(new Capability_client_interactive(mock_client));
335 
336   const bool expected_result = false;
337   ::Mysqlx::Datatypes::Any any;
338 
339   sut->get(&any);
340 
341   ASSERT_EQ(::Mysqlx::Datatypes::Any::SCALAR, any.type());
342   ASSERT_EQ(::Mysqlx::Datatypes::Scalar::V_BOOL, any.scalar().type());
343   ASSERT_EQ(expected_result, any.scalar().v_bool());
344 }
345 
TEST_F(Capability_hander_client_interactive_test_suite,set_and_commit_valid_type)346 TEST_F(Capability_hander_client_interactive_test_suite,
347        set_and_commit_valid_type) {
348   Any any{Scalar{true}};
349 
350   ASSERT_EQ(ER_X_SUCCESS, sut->set(any).error);
351 
352   EXPECT_CALL(mock_client, set_is_interactive(true));
353 
354   sut->commit();
355 }
356 
TEST_F(Capability_hander_client_interactive_test_suite,set_and_commit_invalid_type)357 TEST_F(Capability_hander_client_interactive_test_suite,
358        set_and_commit_invalid_type) {
359   Any any{Scalar{"invalid"}};
360 
361   ASSERT_EQ(ER_X_CAPABILITIES_PREPARE_FAILED, sut->set(any).error);
362 
363   EXPECT_CALL(mock_client, set_is_interactive(false));
364 
365   sut->commit();
366 }
367 
368 class Capability_handler_connection_attributes : public Test {
369  public:
SetUp()370   void SetUp() override {
371     ASSERT_EQ(ER_X_CAPABILITIES_PREPARE_FAILED, m_sut.set(m_any).error);
372   }
373 
374   Any m_any;
375   Capability_connection_attributes m_sut;
376 };
377 
TEST_F(Capability_handler_connection_attributes,is_supported)378 TEST_F(Capability_handler_connection_attributes, is_supported) {
379   ASSERT_TRUE(m_sut.is_supported());
380 }
381 
TEST_F(Capability_handler_connection_attributes,set_invalid_capability_empty_object)382 TEST_F(Capability_handler_connection_attributes,
383        set_invalid_capability_empty_object) {
384   const auto empty_obj = Any::Object{};
385   m_any = Any{empty_obj};
386   ASSERT_EQ(ER_X_CAPABILITIES_PREPARE_FAILED, m_sut.set(m_any).error);
387 }
TEST_F(Capability_handler_connection_attributes,set_invalid_capability_empty_field)388 TEST_F(Capability_handler_connection_attributes,
389        set_invalid_capability_empty_field) {
390   const Any::Object::Fld field{};
391   const Any::Object obj{field};
392   m_any = Any{obj};
393   ASSERT_EQ(ER_X_CAPABILITIES_PREPARE_FAILED, m_sut.set(m_any).error);
394 }
395 
TEST_F(Capability_handler_connection_attributes,set_invalid_capability_field_with_empty_value)396 TEST_F(Capability_handler_connection_attributes,
397        set_invalid_capability_field_with_empty_value) {
398   const Any::Object::Fld field{"some_key", {}};
399   const Any::Object obj{field};
400   m_any = Any{obj};
401   ASSERT_EQ(ER_X_CAPABILITIES_PREPARE_FAILED, m_sut.set(m_any).error);
402 }
403 
TEST_F(Capability_handler_connection_attributes,set_invalid_capability_field_with_empty_scalar)404 TEST_F(Capability_handler_connection_attributes,
405        set_invalid_capability_field_with_empty_scalar) {
406   Scalar empty_scalar;
407   Any value{empty_scalar};
408   const Any::Object::Fld field{"some_key", value};
409   const Any::Object obj{field};
410   m_any = Any{obj};
411   ASSERT_EQ(ER_X_BAD_CONNECTION_SESSION_ATTRIBUTE_TYPE, m_sut.set(m_any).error);
412 }
413 
TEST_F(Capability_handler_connection_attributes,set_invalid_capability_field_with_scalar_other_than_string)414 TEST_F(Capability_handler_connection_attributes,
415        set_invalid_capability_field_with_scalar_other_than_string) {
416   Scalar scalar{true};
417   Any value{scalar};
418   const Any::Object::Fld field{"some_key", value};
419   const Any::Object obj{field};
420   m_any = Any{obj};
421   ASSERT_EQ(ER_X_BAD_CONNECTION_SESSION_ATTRIBUTE_TYPE, m_sut.set(m_any).error);
422 }
423 
TEST_F(Capability_handler_connection_attributes,set_invalid_capability_field_with_empty_string_scalar)424 TEST_F(Capability_handler_connection_attributes,
425        set_invalid_capability_field_with_empty_string_scalar) {
426   ::Mysqlx::Datatypes::Object obj;
427   ::Mysqlx::Datatypes::Any value;
428   ::Mysqlx::Datatypes::Scalar scalar;
429   ::Mysqlx::Datatypes::Scalar_String empty_scalar_string;
430   scalar.mutable_v_string()->CopyFrom(empty_scalar_string);
431   value.mutable_scalar()->CopyFrom(scalar);
432   auto field = obj.add_fld();
433   field->set_key("some_key");
434   field->mutable_value()->CopyFrom(value);
435   ::Mysqlx::Datatypes::Any any;
436   any.mutable_obj()->CopyFrom(obj);
437   ASSERT_EQ(ER_X_BAD_CONNECTION_SESSION_ATTRIBUTE_TYPE, m_sut.set(any).error);
438 }
439 
TEST_F(Capability_handler_connection_attributes,set_invalid_capability_field_without_a_key)440 TEST_F(Capability_handler_connection_attributes,
441        set_invalid_capability_field_without_a_key) {
442   ::Mysqlx::Datatypes::Object obj;
443   ::Mysqlx::Datatypes::Any value;
444   ::Mysqlx::Datatypes::Scalar scalar;
445   ::Mysqlx::Datatypes::Scalar_String scalar_string;
446   scalar_string.set_value("some value");
447   scalar.mutable_v_string()->CopyFrom(scalar_string);
448   value.mutable_scalar()->CopyFrom(scalar);
449   auto field = obj.add_fld();
450   field->mutable_value()->CopyFrom(value);
451   ::Mysqlx::Datatypes::Any any;
452   any.mutable_obj()->CopyFrom(obj);
453   ASSERT_EQ(ER_X_CAPABILITIES_PREPARE_FAILED, m_sut.set(any).error);
454 }
455 
TEST_F(Capability_handler_connection_attributes,key_max_size_exceeded)456 TEST_F(Capability_handler_connection_attributes, key_max_size_exceeded) {
457   Scalar::String scalar_string{"some value"};
458   Scalar scalar{scalar_string};
459   Any value{scalar};
460   std::string long_string(128, 'x');
461   const Any::Object::Fld field{long_string, value};
462   const Any::Object obj{field};
463   m_any = Any{obj};
464   ASSERT_EQ(ER_X_BAD_CONNECTION_SESSION_ATTRIBUTE_KEY_LENGTH,
465             m_sut.set(m_any).error);
466 }
467 
TEST_F(Capability_handler_connection_attributes,empty_key)468 TEST_F(Capability_handler_connection_attributes, empty_key) {
469   Scalar::String scalar_string{"some value"};
470   Scalar scalar{scalar_string};
471   Any value{scalar};
472   const Any::Object::Fld field{"", value};
473   const Any::Object obj{field};
474   m_any = Any{obj};
475   ASSERT_EQ(ER_X_BAD_CONNECTION_SESSION_ATTRIBUTE_EMPTY_KEY,
476             m_sut.set(m_any).error);
477 }
478 
TEST_F(Capability_handler_connection_attributes,value_max_size_exceeded)479 TEST_F(Capability_handler_connection_attributes, value_max_size_exceeded) {
480   std::string long_string(2048, 'x');
481   Scalar::String long_scalar_string{long_string};
482   Scalar scalar{long_scalar_string};
483   Any value{scalar};
484   const Any::Object::Fld field{"some key", value};
485   const Any::Object obj{field};
486   m_any = Any{obj};
487   ASSERT_EQ(ER_X_BAD_CONNECTION_SESSION_ATTRIBUTE_VALUE_LENGTH,
488             m_sut.set(m_any).error);
489 }
490 
TEST_F(Capability_handler_connection_attributes,set_one_key_value_pair)491 TEST_F(Capability_handler_connection_attributes, set_one_key_value_pair) {
492   Scalar::String scalar_string{"some value"};
493   Scalar scalar{scalar_string};
494   Any value{scalar};
495   const Any::Object::Fld field{"some key", value};
496   const Any::Object obj{field};
497   m_any = Any{obj};
498   ASSERT_EQ(ER_X_SUCCESS, m_sut.set(m_any).error);
499 }
500 
TEST_F(Capability_handler_connection_attributes,set_two_key_value_pairs)501 TEST_F(Capability_handler_connection_attributes, set_two_key_value_pairs) {
502   Scalar::String scalar_string1{"some value"};
503   Scalar::String scalar_string2{"other value"};
504   Scalar scalar1{scalar_string1};
505   Scalar scalar2{scalar_string1};
506   Any value1{scalar1};
507   Any value2{scalar2};
508   const Any::Object::Fld field1{"some key", value1};
509   const Any::Object::Fld field2{"other key", value2};
510   const Any::Object obj{{field1, field2}};
511   m_any = Any{obj};
512   ASSERT_EQ(ER_X_SUCCESS, m_sut.set(m_any).error);
513 }
514 
515 }  // namespace test
516 
517 }  // namespace xpl
518