1 /*
2 * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License, version 2.0,
6 * as published by the Free Software Foundation.
7 *
8 * This program is also distributed with certain software (including
9 * but not limited to OpenSSL) that is licensed under separate terms,
10 * as designated in a particular file or component or in included license
11 * documentation. The authors of MySQL hereby grant you an additional
12 * permission to link the program and your derivative works with the
13 * separately licensed software that they have included with MySQL.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License, version 2.0, for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #include <gmock/gmock.h>
26 #include <gtest/gtest.h>
27 #include <stddef.h>
28 #ifndef _WIN32
29 #include <netdb.h>
30 #endif
31
32 #include <cstdint>
33
34 #include "my_io.h" // NOLINT(build/include_subdir)
35 #include "plugin/x/src/io/xpl_listener_tcp.h"
36 #include "unittest/gunit/xplugin/xpl/mock/ngs_general.h"
37
38 namespace xpl {
39 namespace test {
40
41 using namespace ::testing; // NOLINT(build/namespaces)
42
43 const char *const ADDRESS = "0.1.2.3";
44 const char *const ALL_INTERFACES_4 = "0.0.0.0";
45 const char *const ALL_INTERFACES_6 = "::";
46 const uint16_t PORT = 3030;
47 const char *const PORT_STRING = "3030";
48 const uint32_t PORT_TIMEOUT = 123;
49 const uint32_t BACKLOG = 122;
50 const my_socket SOCKET_OK = 10;
51 const int POSIX_OK = 0;
52 const int POSIX_FAILURE = -1;
53
54 MATCHER(EqInvalidSocket, "") {
55 return INVALID_SOCKET == mysql_socket_getfd(arg);
56 }
57
58 MATCHER_P(EqCastToCStr, expected, "") {
59 std::string force_string = expected;
60 return force_string == static_cast<char *>(arg);
61 }
62
63 class Listener_tcp_testsuite : public Test {
64 public:
SetUp()65 void SetUp() {
66 KEY_socket_x_tcpip = 1;
67
68 m_mock_factory = std::make_shared<StrictMock<Mock_factory>>();
69 m_mock_socket = std::make_shared<StrictMock<Mock_socket>>();
70 m_mock_system = std::make_shared<StrictMock<Mock_system>>();
71 m_mock_socket_invalid = std::make_shared<StrictMock<Mock_socket>>();
72
73 ASSERT_NO_FATAL_FAILURE(assert_verify_and_reinitailize_rules());
74 }
75
assert_verify_and_reinitailize_rules()76 void assert_verify_and_reinitailize_rules() {
77 ASSERT_TRUE(Mock::VerifyAndClearExpectations(m_mock_factory.get()));
78 ASSERT_TRUE(Mock::VerifyAndClearExpectations(m_mock_socket_invalid.get()));
79 ASSERT_TRUE(Mock::VerifyAndClearExpectations(m_mock_socket.get()));
80 ASSERT_TRUE(Mock::VerifyAndClearExpectations(m_mock_system.get()));
81
82 EXPECT_CALL(*m_mock_factory, create_system_interface())
83 .WillRepeatedly(Return(m_mock_system));
84 EXPECT_CALL(*m_mock_factory, create_socket(EqInvalidSocket()))
85 .WillRepeatedly(Return(m_mock_socket_invalid));
86 EXPECT_CALL(*m_mock_socket_invalid, get_socket_fd())
87 .WillRepeatedly(Return(INVALID_SOCKET));
88 EXPECT_CALL(*m_mock_socket, get_socket_fd())
89 .WillRepeatedly(Return(SOCKET_OK));
90 ON_CALL(*m_mock_system, get_socket_error_and_message(_, _))
91 .WillByDefault(DoAll(SetArgPointee<0>(0), SetArgPointee<1>("")));
92 }
93
make_sut(const std::string & interface,const uint32_t port=PORT,const uint32_t port_timeout=PORT_TIMEOUT)94 void make_sut(const std::string &interface, const uint32_t port = PORT,
95 const uint32_t port_timeout = PORT_TIMEOUT) {
96 m_resulting_bind_address = interface;
97 sut = std::make_shared<Listener_tcp>(
98 m_mock_factory, std::ref(m_resulting_bind_address), "", port,
99 port_timeout, std::ref(m_mock_socket_events), BACKLOG);
100 }
101
expect_create_socket(addrinfo & ai,const std::string & interface,const int family,const int64_t result=SOCKET_OK)102 void expect_create_socket(addrinfo &ai, const std::string &interface,
103 const int family,
104 const int64_t result = SOCKET_OK) {
105 make_sut(interface, PORT, PORT_TIMEOUT);
106
107 EXPECT_CALL(*m_mock_system,
108 getaddrinfo(StrEq(interface), StrEq(PORT_STRING), _, _))
109 .WillOnce(DoAll(SetArgPointee<3>(&ai), Return(POSIX_OK)));
110
111 EXPECT_CALL(*m_mock_socket, get_socket_fd()).WillOnce(Return(result));
112 EXPECT_CALL(*m_mock_factory,
113 create_socket(KEY_socket_x_tcpip, family, SOCK_STREAM, 0))
114 .WillOnce(Return(m_mock_socket));
115
116 #ifdef IPV6_V6ONLY
117 EXPECT_CALL(*m_mock_socket,
118 set_socket_opt(IPPROTO_IPV6, IPV6_V6ONLY, _, sizeof(int)))
119 .WillRepeatedly(Return(POSIX_OK));
120 #endif
121 }
122
expect_listen_socket(std::shared_ptr<Mock_socket> mock_socket,addrinfo & ai,const bool socket_events_listen=true)123 void expect_listen_socket(std::shared_ptr<Mock_socket> mock_socket,
124 addrinfo &ai,
125 const bool socket_events_listen = true) {
126 EXPECT_CALL(*mock_socket, set_socket_thread_owner());
127 EXPECT_CALL(*mock_socket,
128 bind(ai.ai_addr, static_cast<socklen_t>(ai.ai_addrlen)))
129 .WillOnce(Return(POSIX_OK));
130 EXPECT_CALL(*mock_socket, listen(BACKLOG)).WillOnce(Return(POSIX_OK));
131 std::shared_ptr<iface::Socket> socket_ptr = mock_socket;
132 EXPECT_CALL(m_mock_socket_events, listen(socket_ptr, _))
133 .WillOnce(Return(socket_events_listen));
134 }
135
get_ai_ipv6()136 struct addrinfo get_ai_ipv6() {
137 struct addrinfo result;
138 static struct sockaddr_in6 in6;
139
140 in6.sin6_family = result.ai_family = AF_INET6;
141 result.ai_socktype = 0;
142 result.ai_protocol = 0;
143 result.ai_addrlen = sizeof(in6);
144 result.ai_addr = reinterpret_cast<sockaddr *>(&in6);
145 result.ai_next = nullptr;
146
147 return result;
148 }
149
get_ai_ipv4()150 struct addrinfo get_ai_ipv4() {
151 struct addrinfo result;
152 static struct sockaddr_in in4;
153
154 in4.sin_family = result.ai_family = AF_INET;
155 result.ai_socktype = 0;
156 result.ai_protocol = 0;
157 result.ai_addrlen = sizeof(in4);
158 result.ai_addr = reinterpret_cast<sockaddr *>(&in4);
159 result.ai_next = nullptr;
160
161 return result;
162 }
163 std::string m_resulting_bind_address;
164
165 std::shared_ptr<Mock_socket> m_mock_socket;
166 std::shared_ptr<Mock_socket> m_mock_socket_invalid;
167 std::shared_ptr<Mock_system> m_mock_system;
168 StrictMock<Mock_socket_events> m_mock_socket_events;
169 std::shared_ptr<Mock_factory> m_mock_factory;
170
171 std::shared_ptr<Listener_tcp> sut;
172 };
173
TEST_F(Listener_tcp_testsuite,setup_listener_does_nothing_when_resolve_failes)174 TEST_F(Listener_tcp_testsuite,
175 setup_listener_does_nothing_when_resolve_failes) {
176 make_sut(ADDRESS);
177
178 EXPECT_CALL(*m_mock_system,
179 getaddrinfo(StrEq(ADDRESS), StrEq(PORT_STRING), _, _))
180 .WillOnce(Return(POSIX_FAILURE));
181
182 ASSERT_FALSE(sut->setup_listener(nullptr));
183 ASSERT_TRUE(sut->get_state().is(iface::Listener::State::k_stopped));
184 }
185
TEST_F(Listener_tcp_testsuite,setup_listener_does_resolved_IP6_and_IP4_localhost_when_asterisk_and_IP6_supported)186 TEST_F(
187 Listener_tcp_testsuite,
188 setup_listener_does_resolved_IP6_and_IP4_localhost_when_asterisk_and_IP6_supported) { // NOLINT(whitespace/line_length)
189 make_sut("*");
190
191 EXPECT_CALL(*m_mock_socket, get_socket_fd()).WillOnce(Return(SOCKET_OK));
192 EXPECT_CALL(*m_mock_factory,
193 create_socket(static_cast<PSI_socket_key>(PSI_NOT_INSTRUMENTED),
194 AF_INET6, SOCK_STREAM, 0))
195 .WillOnce(Return(m_mock_socket));
196
197 EXPECT_CALL(*m_mock_system,
198 getaddrinfo(StrEq(ALL_INTERFACES_6), StrEq(PORT_STRING), _, _))
199 .WillOnce(Return(POSIX_FAILURE));
200
201 EXPECT_CALL(*m_mock_system,
202 getaddrinfo(StrEq(ALL_INTERFACES_4), StrEq(PORT_STRING), _, _))
203 .WillOnce(Return(POSIX_FAILURE));
204
205 ASSERT_FALSE(sut->setup_listener(nullptr));
206 ASSERT_TRUE(sut->get_state().is(iface::Listener::State::k_stopped));
207 }
208
TEST_F(Listener_tcp_testsuite,setup_listener_does_resolved_IP4_localhost_when_asterisk_and_IP6_not_supported)209 TEST_F(
210 Listener_tcp_testsuite,
211 setup_listener_does_resolved_IP4_localhost_when_asterisk_and_IP6_not_supported) { // NOLINT(whitespace/line_length)
212 make_sut("*");
213
214 EXPECT_CALL(*m_mock_socket, get_socket_fd()).WillOnce(Return(INVALID_SOCKET));
215 EXPECT_CALL(*m_mock_factory,
216 create_socket(static_cast<PSI_socket_key>(PSI_NOT_INSTRUMENTED),
217 AF_INET6, SOCK_STREAM, 0))
218 .WillOnce(Return(m_mock_socket));
219
220 EXPECT_CALL(*m_mock_system,
221 getaddrinfo(StrEq(ALL_INTERFACES_4), StrEq(PORT_STRING), _, _))
222 .WillOnce(Return(POSIX_FAILURE));
223
224 ASSERT_FALSE(sut->setup_listener(nullptr));
225 ASSERT_TRUE(sut->get_state().is(iface::Listener::State::k_stopped));
226 }
227
228 struct TimeOutAndExpectedRetries {
TimeOutAndExpectedRetriesxpl::test::TimeOutAndExpectedRetries229 TimeOutAndExpectedRetries(const uint32_t timeout,
230 const uint32_t expected_retries)
231 : m_timeout(timeout), m_expected_retries(expected_retries) {}
232
233 uint32_t m_timeout;
234 uint32_t m_expected_retries;
235 };
236
237 class Listener_tcp_retry_testsuite
238 : public Listener_tcp_testsuite,
239 public WithParamInterface<TimeOutAndExpectedRetries> {};
240
TEST_P(Listener_tcp_retry_testsuite,setup_listener_retry_socket_allocation_when_it_is_in_use)241 TEST_P(Listener_tcp_retry_testsuite,
242 setup_listener_retry_socket_allocation_when_it_is_in_use) {
243 addrinfo ai = get_ai_ipv6();
244
245 make_sut(ALL_INTERFACES_6, PORT, GetParam().m_timeout);
246
247 EXPECT_CALL(*m_mock_system,
248 getaddrinfo(StrEq(ALL_INTERFACES_6), StrEq(PORT_STRING), _, _))
249 .WillOnce(DoAll(SetArgPointee<3>(&ai), Return(POSIX_OK)));
250
251 const int n = GetParam().m_expected_retries;
252
253 ON_CALL(*m_mock_system, get_socket_error_and_message(_, _))
254 .WillByDefault(DoAll(SetArgPointee<0>(0), SetArgPointee<1>("")));
255
256 EXPECT_CALL(*m_mock_socket, get_socket_fd())
257 .Times(n)
258 .WillRepeatedly(Return(INVALID_SOCKET));
259 EXPECT_CALL(*m_mock_factory,
260 create_socket(KEY_socket_x_tcpip, AF_INET6, SOCK_STREAM, 0))
261 .Times(n)
262 .WillRepeatedly(Return(m_mock_socket));
263 EXPECT_CALL(*m_mock_system, get_socket_error_and_message(_, _)).Times(n);
264 EXPECT_CALL(*m_mock_system, get_socket_errno())
265 .Times(n)
266 .WillRepeatedly(Return(SOCKET_EADDRINUSE));
267 EXPECT_CALL(*m_mock_system, sleep(Gt(0u))).Times(n);
268
269 EXPECT_CALL(*m_mock_system, freeaddrinfo(&ai));
270
271 ASSERT_FALSE(sut->setup_listener(nullptr));
272 ASSERT_TRUE(sut->get_state().is(iface::Listener::State::k_stopped));
273 }
274
275 INSTANTIATE_TEST_CASE_P(
276 Instantiation_tcp_retry_when_already_in_use, Listener_tcp_retry_testsuite,
277 Values(TimeOutAndExpectedRetries(0, 1), TimeOutAndExpectedRetries(1, 2),
278 TimeOutAndExpectedRetries(5, 3), TimeOutAndExpectedRetries(6, 3),
279 TimeOutAndExpectedRetries(7, 4),
280 TimeOutAndExpectedRetries(PORT_TIMEOUT, 10))); // 123, 10
281
TEST_F(Listener_tcp_testsuite,setup_listener_bind_failure)282 TEST_F(Listener_tcp_testsuite, setup_listener_bind_failure) {
283 addrinfo ai = get_ai_ipv6();
284
285 expect_create_socket(ai, ALL_INTERFACES_6, AF_INET6, SOCKET_OK);
286
287 EXPECT_CALL(*m_mock_socket,
288 set_socket_opt(SOL_SOCKET, SO_REUSEADDR, _, sizeof(int)))
289 .WillOnce(Return(POSIX_OK));
290 EXPECT_CALL(*m_mock_socket, set_socket_thread_owner());
291
292 EXPECT_CALL(*m_mock_socket, bind(ai.ai_addr, ai.ai_addrlen))
293 .WillOnce(Return(POSIX_FAILURE));
294 EXPECT_CALL(*m_mock_system, get_socket_error_and_message(_, _));
295 EXPECT_CALL(*m_mock_system, get_socket_errno())
296 .WillRepeatedly(Return(SOCKET_ETIMEDOUT));
297
298 EXPECT_CALL(*m_mock_system, freeaddrinfo(&ai));
299
300 ASSERT_FALSE(sut->setup_listener(nullptr));
301 ASSERT_TRUE(sut->get_state().is(iface::Listener::State::k_stopped));
302 }
303
TEST_F(Listener_tcp_testsuite,setup_listener_listen_failure)304 TEST_F(Listener_tcp_testsuite, setup_listener_listen_failure) {
305 addrinfo ai = get_ai_ipv6();
306
307 expect_create_socket(ai, ALL_INTERFACES_6, AF_INET6, SOCKET_OK);
308
309 EXPECT_CALL(*m_mock_socket,
310 set_socket_opt(SOL_SOCKET, SO_REUSEADDR, _,
311 static_cast<socklen_t>(sizeof(int))))
312 .WillOnce(Return(POSIX_OK));
313 EXPECT_CALL(*m_mock_socket, set_socket_thread_owner());
314 EXPECT_CALL(*m_mock_socket, bind(ai.ai_addr, ai.ai_addrlen))
315 .WillOnce(Return(POSIX_OK));
316
317 EXPECT_CALL(*m_mock_socket, listen(BACKLOG)).WillOnce(Return(POSIX_FAILURE));
318 EXPECT_CALL(*m_mock_system, get_socket_error_and_message(_, _));
319 EXPECT_CALL(*m_mock_system, get_socket_errno())
320 .WillRepeatedly(Return(SOCKET_ETIMEDOUT));
321
322 EXPECT_CALL(*m_mock_system, freeaddrinfo(&ai));
323
324 ASSERT_FALSE(sut->setup_listener(nullptr));
325 ASSERT_TRUE(sut->get_state().is(iface::Listener::State::k_stopped));
326 }
327
TEST_F(Listener_tcp_testsuite,setup_listener_ipv6_success)328 TEST_F(Listener_tcp_testsuite, setup_listener_ipv6_success) {
329 addrinfo ai = get_ai_ipv6();
330
331 expect_create_socket(ai, ALL_INTERFACES_6, AF_INET6, SOCKET_OK);
332
333 EXPECT_CALL(*m_mock_socket,
334 set_socket_opt(SOL_SOCKET, SO_REUSEADDR, _, sizeof(int)))
335 .WillOnce(Return(POSIX_OK));
336
337 expect_listen_socket(m_mock_socket, ai);
338
339 EXPECT_CALL(*m_mock_system, freeaddrinfo(&ai));
340
341 ASSERT_TRUE(sut->setup_listener(nullptr));
342 ASSERT_TRUE(sut->get_state().is(iface::Listener::State::k_prepared));
343
344 // SUT destructor
345 ASSERT_NO_FATAL_FAILURE(assert_verify_and_reinitailize_rules());
346 EXPECT_CALL(*m_mock_socket, close());
347 }
348
TEST_F(Listener_tcp_testsuite,setup_listener_ipv4_success)349 TEST_F(Listener_tcp_testsuite, setup_listener_ipv4_success) {
350 addrinfo ai = get_ai_ipv4();
351
352 expect_create_socket(ai, ALL_INTERFACES_4, AF_INET, SOCKET_OK);
353
354 EXPECT_CALL(*m_mock_socket,
355 set_socket_opt(SOL_SOCKET, SO_REUSEADDR, _, sizeof(int)))
356 .WillOnce(Return(POSIX_OK));
357
358 expect_listen_socket(m_mock_socket, ai);
359
360 EXPECT_CALL(*m_mock_system, freeaddrinfo(&ai));
361
362 ASSERT_TRUE(sut->setup_listener(nullptr));
363 ASSERT_TRUE(sut->get_state().is(iface::Listener::State::k_prepared));
364
365 // SUT destructor
366 ASSERT_NO_FATAL_FAILURE(assert_verify_and_reinitailize_rules());
367 EXPECT_CALL(*m_mock_socket, close());
368 }
369
TEST_F(Listener_tcp_testsuite,setup_listener_failure_when_socket_event_registry_failed)370 TEST_F(Listener_tcp_testsuite,
371 setup_listener_failure_when_socket_event_registry_failed) {
372 addrinfo ai = get_ai_ipv4();
373
374 expect_create_socket(ai, ALL_INTERFACES_4, AF_INET, SOCKET_OK);
375
376 EXPECT_CALL(*m_mock_socket,
377 set_socket_opt(SOL_SOCKET, SO_REUSEADDR, _, sizeof(int)))
378 .WillOnce(Return(POSIX_OK));
379
380 const bool socket_event_listen_failed = false;
381 expect_listen_socket(m_mock_socket, ai, socket_event_listen_failed);
382
383 EXPECT_CALL(*m_mock_system, freeaddrinfo(&ai));
384
385 ASSERT_FALSE(sut->setup_listener(nullptr));
386 ASSERT_TRUE(sut->get_state().is(iface::Listener::State::k_stopped));
387
388 // SUT destructor
389 ASSERT_NO_FATAL_FAILURE(assert_verify_and_reinitailize_rules());
390 }
391
TEST_F(Listener_tcp_testsuite,setup_listener_ipv4_and_ip6_addresses_successful_is_ip4)392 TEST_F(Listener_tcp_testsuite,
393 setup_listener_ipv4_and_ip6_addresses_successful_is_ip4) {
394 addrinfo ai4 = get_ai_ipv4();
395 addrinfo ai6 = get_ai_ipv6();
396
397 ai4.ai_next = &ai6;
398
399 expect_create_socket(ai4, ALL_INTERFACES_4, AF_INET, SOCKET_OK);
400
401 EXPECT_CALL(*m_mock_socket,
402 set_socket_opt(SOL_SOCKET, SO_REUSEADDR, _, sizeof(int)))
403 .WillOnce(Return(POSIX_OK));
404
405 expect_listen_socket(m_mock_socket, ai4);
406
407 EXPECT_CALL(*m_mock_system, freeaddrinfo(&ai4));
408
409 ASSERT_TRUE(sut->setup_listener(nullptr));
410 ASSERT_TRUE(sut->get_state().is(iface::Listener::State::k_prepared));
411
412 // SUT destructor
413 ASSERT_NO_FATAL_FAILURE(assert_verify_and_reinitailize_rules());
414 EXPECT_CALL(*m_mock_socket, close());
415 }
416
TEST_F(Listener_tcp_testsuite,setup_listener_ipv4_and_ip6_addresses_successful_is_ip4_beacause_it_is_always_first_to_try)417 TEST_F(
418 Listener_tcp_testsuite,
419 setup_listener_ipv4_and_ip6_addresses_successful_is_ip4_beacause_it_is_always_first_to_try) { // NOLINT(whitespace/line_length)
420 addrinfo ai4 = get_ai_ipv4();
421 addrinfo ai6 = get_ai_ipv6();
422
423 ai4.ai_next = &ai6;
424
425 expect_create_socket(ai4, ALL_INTERFACES_6, AF_INET, SOCKET_OK);
426
427 EXPECT_CALL(*m_mock_socket,
428 set_socket_opt(SOL_SOCKET, SO_REUSEADDR, _, sizeof(int)))
429 .WillOnce(Return(POSIX_OK));
430
431 expect_listen_socket(m_mock_socket, ai4);
432
433 EXPECT_CALL(*m_mock_system, freeaddrinfo(&ai4));
434
435 ASSERT_TRUE(sut->setup_listener(nullptr));
436 ASSERT_TRUE(sut->get_state().is(iface::Listener::State::k_prepared));
437
438 // SUT destructor
439 ASSERT_NO_FATAL_FAILURE(assert_verify_and_reinitailize_rules());
440 EXPECT_CALL(*m_mock_socket, close());
441 }
442
TEST_F(Listener_tcp_testsuite,setup_listener_ipv4_and_ip6_addresses_successful_is_ip6_at_retry)443 TEST_F(Listener_tcp_testsuite,
444 setup_listener_ipv4_and_ip6_addresses_successful_is_ip6_at_retry) {
445 addrinfo ai4 = get_ai_ipv4();
446 addrinfo ai6 = get_ai_ipv6();
447
448 ai4.ai_next = &ai6;
449
450 expect_create_socket(ai4, ALL_INTERFACES_6, AF_INET, INVALID_SOCKET);
451
452 std::shared_ptr<Mock_socket> mock_socket_ipv6(new StrictMock<Mock_socket>());
453 EXPECT_CALL(*mock_socket_ipv6, get_socket_fd()).WillOnce(Return(SOCKET_OK));
454 EXPECT_CALL(*m_mock_factory,
455 create_socket(KEY_socket_x_tcpip, AF_INET6, SOCK_STREAM, 0))
456 .WillOnce(Return(mock_socket_ipv6));
457
458 #ifdef IPV6_V6ONLY
459 EXPECT_CALL(*mock_socket_ipv6,
460 set_socket_opt(IPPROTO_IPV6, IPV6_V6ONLY, _, sizeof(int)))
461 .WillRepeatedly(Return(POSIX_OK));
462 #endif
463
464 EXPECT_CALL(*mock_socket_ipv6,
465 set_socket_opt(SOL_SOCKET, SO_REUSEADDR, _, sizeof(int)))
466 .WillOnce(Return(POSIX_OK));
467
468 expect_listen_socket(mock_socket_ipv6, ai6);
469
470 EXPECT_CALL(*m_mock_system, freeaddrinfo(&ai4));
471
472 ASSERT_TRUE(sut->setup_listener(nullptr));
473 ASSERT_TRUE(sut->get_state().is(iface::Listener::State::k_prepared));
474
475 // SUT destructor
476 ASSERT_NO_FATAL_FAILURE(assert_verify_and_reinitailize_rules());
477 EXPECT_CALL(*mock_socket_ipv6, close());
478 }
479
TEST_F(Listener_tcp_testsuite,setup_listener_success_evean_socket_opt_fails)480 TEST_F(Listener_tcp_testsuite, setup_listener_success_evean_socket_opt_fails) {
481 addrinfo ai = get_ai_ipv6();
482
483 expect_create_socket(ai, ALL_INTERFACES_6, AF_INET6, SOCKET_OK);
484
485 EXPECT_CALL(*m_mock_socket,
486 set_socket_opt(SOL_SOCKET, SO_REUSEADDR, _, sizeof(int)))
487 .WillOnce(Return(POSIX_FAILURE));
488 EXPECT_CALL(*m_mock_system, get_socket_errno());
489
490 expect_listen_socket(m_mock_socket, ai);
491
492 EXPECT_CALL(*m_mock_system, freeaddrinfo(&ai));
493
494 ASSERT_TRUE(sut->setup_listener(nullptr));
495 ASSERT_TRUE(sut->get_state().is(iface::Listener::State::k_prepared));
496
497 // SUT destructor
498 ASSERT_NO_FATAL_FAILURE(assert_verify_and_reinitailize_rules());
499 EXPECT_CALL(*m_mock_socket, close());
500 }
501
TEST_F(Listener_tcp_testsuite,close_listener_does_nothing_when_socket_not_started)502 TEST_F(Listener_tcp_testsuite,
503 close_listener_does_nothing_when_socket_not_started) {
504 make_sut(ALL_INTERFACES_6);
505
506 sut->close_listener();
507
508 // After stopping, start must not work !
509 sut->setup_listener(nullptr);
510 }
511
TEST_F(Listener_tcp_testsuite,loop_does_nothing_always)512 TEST_F(Listener_tcp_testsuite, loop_does_nothing_always) {
513 make_sut(ALL_INTERFACES_6);
514
515 sut->loop();
516 }
517
518 } // namespace test
519 } // namespace xpl
520