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