1 /* Copyright (c) 2015, 2021, Oracle and/or its affiliates.
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 <gtest/gtest.h>
24 #include <gmock/gmock.h>
25
26 #include "ngs/memory.h"
27 #include "ngs/ngs_error.h"
28 #include "mock/capabilities.h"
29
30
31 const int NUMBER_OF_HANDLERS = 4;
32 const char* NAMES[NUMBER_OF_HANDLERS] = {
33 "first",
34 "second",
35 "third",
36 "fourth"
37 };
38
39
40 using ::Mysqlx::Connection::Capabilities;
41 using ::Mysqlx::Connection::Capability;
42 using ::Mysqlx::Datatypes::Any;
43
44
45 namespace ngs
46 {
47
48 namespace test
49 {
50
51
52 using namespace ::testing;
53
54
55 class CapabilitiesConfiguratorTestSuite : public Test
56 {
57 public:
58 typedef ngs::shared_ptr<StrictMock<Mock_capability_handler> > Mock_ptr;
59
SetUp()60 void SetUp()
61 {
62 for(int i = 0; i < NUMBER_OF_HANDLERS; ++i)
63 {
64 mock_handlers.push_back(ngs::make_shared< StrictMock<Mock_capability_handler> >());
65 }
66
67 std::vector<Capability_handler_ptr> handlers(mock_handlers.begin(), mock_handlers.end());
68
69 std::for_each(mock_handlers.begin(), mock_handlers.end(), default_is_supported<false>);
70
71 sut.reset(new Capabilities_configurator(handlers));
72 }
73
74
75 template<bool Result>
expect_is_supported(Mock_ptr mock)76 static void expect_is_supported(Mock_ptr mock)
77 {
78 EXPECT_CALL(*mock, is_supported()).WillOnce(Return(Result));
79 }
80
81
82 template<bool Result>
default_is_supported(Mock_ptr mock)83 static void default_is_supported(Mock_ptr mock)
84 {
85 EXPECT_CALL(*mock, is_supported()).WillRepeatedly(Return(Result));
86 }
87
88
expect_get_capability(Mock_ptr mock)89 static void expect_get_capability(Mock_ptr mock)
90 {
91 EXPECT_CALL(*mock, get_void(_));
92 }
93
94
expect_commit(Mock_ptr mock)95 static void expect_commit(Mock_ptr mock)
96 {
97 EXPECT_CALL(*mock, commit_void());
98 }
99
100
assert_get(std::vector<Mock_ptr> & supported_handlers)101 void assert_get(std::vector<Mock_ptr> &supported_handlers)
102 {
103 std::for_each(supported_handlers.begin(), supported_handlers.end(), expect_is_supported<true>);
104 std::for_each(supported_handlers.begin(), supported_handlers.end(), expect_get_name(NAMES));
105 std::for_each(supported_handlers.begin(), supported_handlers.end(), expect_get_capability);
106
107 ngs::Memory_instrumented<Capabilities>::Unique_ptr cap(sut->get());
108 const Capabilities *null_cap = NULL;
109 ASSERT_NE(null_cap, cap.get());
110 ASSERT_EQ(static_cast<int>(supported_handlers.size()), cap->capabilities_size());
111
112 for(std::size_t i = 0; i < supported_handlers.size();i ++)
113 {
114 ASSERT_EQ(NAMES[i], cap->capabilities(static_cast<int>(i)).name());
115 }
116 }
117
118
add_capability(Capabilities & caps,const std::size_t mock_index)119 Capability &add_capability(Capabilities & caps, const std::size_t mock_index)
120 {
121 Capability *cap = caps.add_capabilities();
122
123 cap->set_name(NAMES[mock_index]);
124 cap->mutable_value()->mutable_scalar()->set_v_signed_int(mock_index);
125
126 return *cap;
127 }
128
129
add_capability_and_expect_it(Capabilities & caps,const std::size_t mock_index,const bool set_result)130 Capability &add_capability_and_expect_it(Capabilities & caps, const std::size_t mock_index, const bool set_result)
131 {
132 Capability &cap = add_capability(caps, mock_index);
133
134 EXPECT_CALL(*mock_handlers[mock_index], set(Ref(cap.value()))).WillOnce(Return(set_result));
135
136 return cap;
137 }
138
139
140 struct expect_get_name
141 {
142 template<std::size_t ELEMENTS>
expect_get_namengs::test::CapabilitiesConfiguratorTestSuite::expect_get_name143 expect_get_name(const char* (&names)[ELEMENTS])
144 : m_names(names), m_elements(ELEMENTS), m_current(0)
145 {
146 }
147
operator ()ngs::test::CapabilitiesConfiguratorTestSuite::expect_get_name148 void operator() (Mock_ptr mock)
149 {
150 EXPECT_CALL(*mock, name()).WillOnce(Return(get_next_name()));
151
152 }
153
get_next_namengs::test::CapabilitiesConfiguratorTestSuite::expect_get_name154 std::string get_next_name()
155 {
156 std::string result = m_names[m_current++];
157
158 if (m_current >= m_elements)
159 m_current = 0;
160
161 return result;
162 }
163
164 const char** m_names;
165 const std::size_t m_elements;
166 std::size_t m_current;
167 };
168
169
170 struct default_get_name : expect_get_name
171 {
172 template<std::size_t ELEMENTS>
default_get_namengs::test::CapabilitiesConfiguratorTestSuite::default_get_name173 default_get_name(const char* (&names)[ELEMENTS]): expect_get_name(names)
174 {
175 }
176
operator ()ngs::test::CapabilitiesConfiguratorTestSuite::default_get_name177 void operator() (Mock_ptr &mock)
178 {
179 EXPECT_CALL(*mock, name()).WillRepeatedly(Return(get_next_name()));
180 }
181 };
182
183
184 std::vector<Mock_ptr> mock_handlers;
185
186 ngs::unique_ptr<Capabilities_configurator> sut;
187 };
188
189
TEST_F(CapabilitiesConfiguratorTestSuite,get_doesNothing_whenEmpty)190 TEST_F(CapabilitiesConfiguratorTestSuite, get_doesNothing_whenEmpty)
191 {
192 std::vector<Mock_ptr> empty;
193
194 assert_get(empty);
195 }
196
197
TEST_F(CapabilitiesConfiguratorTestSuite,get_returnsAllCapabilities)198 TEST_F(CapabilitiesConfiguratorTestSuite, get_returnsAllCapabilities)
199 {
200 assert_get(mock_handlers);
201 }
202
203
TEST_F(CapabilitiesConfiguratorTestSuite,get_returnsOnlySupportedCaps)204 TEST_F(CapabilitiesConfiguratorTestSuite, get_returnsOnlySupportedCaps)
205 {
206 std::vector<Mock_ptr> supported_handlers;
207
208 supported_handlers.push_back(mock_handlers[0]);
209 supported_handlers.push_back(mock_handlers[NUMBER_OF_HANDLERS-1]);
210
211 assert_get(supported_handlers);
212 }
213
214
TEST_F(CapabilitiesConfiguratorTestSuite,prepareSet_errorErrorAndCommitDoesNothing_whenOneUnknownCapability)215 TEST_F(CapabilitiesConfiguratorTestSuite, prepareSet_errorErrorAndCommitDoesNothing_whenOneUnknownCapability)
216 {
217 ngs::unique_ptr<Capabilities> caps(new Capabilities());
218
219 Capability * cap = caps->add_capabilities();
220
221 cap->set_name("UNKNOWN");
222
223 std::for_each(mock_handlers.begin(), mock_handlers.end(), default_get_name(NAMES));
224
225 ASSERT_EQ(ER_X_CAPABILITY_NOT_FOUND, sut->prepare_set(*caps).error);
226
227 sut->commit();
228 }
229
230
TEST_F(CapabilitiesConfiguratorTestSuite,prepareSet_success_whenAllRequestedCapsSucceded)231 TEST_F(CapabilitiesConfiguratorTestSuite, prepareSet_success_whenAllRequestedCapsSucceded)
232 {
233 ngs::unique_ptr<Capabilities> caps(new Capabilities());
234 std::vector<Mock_ptr> supported_handlers;
235
236 std::for_each(mock_handlers.begin(), mock_handlers.end(), default_get_name(NAMES));
237
238 add_capability_and_expect_it(*caps, 0, true);
239 supported_handlers.push_back(mock_handlers[0]);
240
241 add_capability_and_expect_it(*caps, NUMBER_OF_HANDLERS-1, true);
242 supported_handlers.push_back(mock_handlers[NUMBER_OF_HANDLERS-1]);
243
244 ASSERT_FALSE(sut->prepare_set(*caps));
245
246 std::for_each(supported_handlers.begin(), supported_handlers.end(), expect_commit);
247 sut->commit();
248 }
249
TEST_F(CapabilitiesConfiguratorTestSuite,prepareSet_FailsAndCommitDoesNothing_whenAnyCapsFailsLast)250 TEST_F(CapabilitiesConfiguratorTestSuite, prepareSet_FailsAndCommitDoesNothing_whenAnyCapsFailsLast)
251 {
252 ngs::unique_ptr<Capabilities> caps(new Capabilities());
253 std::vector<Mock_ptr> supported_handlers;
254
255 std::for_each(mock_handlers.begin(), mock_handlers.end(), default_get_name(NAMES));
256
257 add_capability_and_expect_it(*caps, 0, true);
258 supported_handlers.push_back(mock_handlers[0]);
259
260 add_capability_and_expect_it(*caps, NUMBER_OF_HANDLERS-1, false);
261 supported_handlers.push_back(mock_handlers[NUMBER_OF_HANDLERS-1]);
262
263 ASSERT_EQ(ER_X_CAPABILITIES_PREPARE_FAILED, sut->prepare_set(*caps).error);
264
265 sut->commit();
266 }
267
268
TEST_F(CapabilitiesConfiguratorTestSuite,prepareSet_FailsAndCommitDoesNothing_whenAnyCapsFailsFirst)269 TEST_F(CapabilitiesConfiguratorTestSuite, prepareSet_FailsAndCommitDoesNothing_whenAnyCapsFailsFirst)
270 {
271 ngs::unique_ptr<Capabilities> caps(new Capabilities());
272 std::vector<Mock_ptr> supported_handlers;
273
274 std::for_each(mock_handlers.begin(), mock_handlers.end(), default_get_name(NAMES));
275
276 add_capability_and_expect_it(*caps, 0, false);
277 supported_handlers.push_back(mock_handlers[0]);
278
279 add_capability(*caps, NUMBER_OF_HANDLERS-1);
280 supported_handlers.push_back(mock_handlers[NUMBER_OF_HANDLERS-1]);
281
282 ASSERT_EQ(ER_X_CAPABILITIES_PREPARE_FAILED, sut->prepare_set(*caps).error);
283
284 sut->commit();
285 }
286
287
288 } // namespace test
289
290 } // namespace ngs
291