comparison C++/tests/Socket/main.cpp @ 378:92457ea8f7e2

Socket: switch to more OO
author David Demelier <markand@malikania.fr>
date Fri, 19 Jun 2015 10:52:54 +0200
parents 2c6a4f468499
children 06b0f405c58f
comparison
equal deleted inserted replaced
377:4885cd4dfa33 378:92457ea8f7e2
74 }); 74 });
75 75
76 std::this_thread::sleep_for(100ms); 76 std::this_thread::sleep_for(100ms);
77 77
78 m_tclient = std::thread([this] () { 78 m_tclient = std::thread([this] () {
79 m_client.connect(Internet("127.0.0.1", 16000, AF_INET)); 79 m_client.connect(std::make_unique<Internet>("127.0.0.1", 16000, AF_INET));
80 80
81 ASSERT_EQ(SocketState::Connected, m_client.state()); 81 ASSERT_EQ(SocketState::Connected, m_client.state());
82 82
83 m_client.close(); 83 m_client.close();
84 }); 84 });
89 m_tserver = std::thread([this] () { 89 m_tserver = std::thread([this] () {
90 m_server.bind(Internet("*", 16000, AF_INET)); 90 m_server.bind(Internet("*", 16000, AF_INET));
91 m_server.listen(); 91 m_server.listen();
92 92
93 auto client = m_server.accept(); 93 auto client = m_server.accept();
94 auto msg = client.recv(512); 94 auto msg = client->recv(512);
95 95
96 ASSERT_EQ("hello world", msg); 96 ASSERT_EQ("hello world", msg);
97 97
98 client.send(msg); 98 client->send(msg);
99 client.close();
100
101 m_server.close();
102 }); 99 });
103 100
104 std::this_thread::sleep_for(100ms); 101 std::this_thread::sleep_for(100ms);
105 102
106 m_tclient = std::thread([this] () { 103 m_tclient = std::thread([this] () {
107 m_client.connect(Internet("127.0.0.1", 16000, AF_INET)); 104 m_client.connect(std::make_unique<Internet>("127.0.0.1", 16000, AF_INET));
108 m_client.send("hello world"); 105 m_client.send("hello world");
109 106
110 ASSERT_EQ("hello world", m_client.recv(512)); 107 ASSERT_EQ("hello world", m_client.recv(512));
111
112 m_client.close();
113 }); 108 });
114 } 109 }
115 110
116 /* -------------------------------------------------------- 111 /* --------------------------------------------------------
117 * UDP tests 112 * UDP tests
176 public: 171 public:
177 int m_callcount{0}; 172 int m_callcount{0};
178 bool m_added{false}; 173 bool m_added{false};
179 int m_flags{0}; 174 int m_flags{0};
180 175
181 inline void set(const SocketTable &, Socket sc, int flags, bool add) noexcept 176 inline void set(const SocketTable &, const std::shared_ptr<Socket> &sc, int flags, bool add) noexcept
182 { 177 {
183 m_callcount ++; 178 m_callcount ++;
184 m_added = add; 179 m_added = add;
185 m_flags |= flags; 180 m_flags |= flags;
186 } 181 }
187 182
188 inline void unset(const SocketTable &, Socket, int, bool) noexcept {} 183 inline void unset(const SocketTable &, const std::shared_ptr<Socket> &, int, bool) noexcept {}
189 std::vector<SocketStatus> wait(const SocketTable &table, int ms) {} 184 std::vector<SocketStatus> wait(const SocketTable &table, int ms) {}
190 }; 185 };
191 186
192 class TestBackendSetFail { 187 class TestBackendSetFail {
193 public: 188 public:
194 inline void set(const SocketTable &, Socket, int, bool) 189 inline void set(const SocketTable &, const std::shared_ptr<Socket> &, int, bool)
195 { 190 {
196 throw "fail"; 191 throw "fail";
197 } 192 }
198 193
199 inline void unset(const SocketTable &, Socket, int, bool) noexcept {} 194 inline void unset(const SocketTable &, const std::shared_ptr<Socket> &, int, bool) noexcept {}
200 std::vector<SocketStatus> wait(const SocketTable &table, int ms) {} 195 std::vector<SocketStatus> wait(const SocketTable &table, int ms) {}
201 }; 196 };
202 197
203 TEST(ListenerSet, initialAdd) 198 TEST(ListenerSet, initialAdd)
204 { 199 {
205 SocketListenerBase<TestBackendSet> listener; 200 SocketListenerBase<TestBackendSet> listener;
206 201
207 listener.set(Socket(0), SocketListener::Read); 202 listener.set(std::make_shared<Socket>(0), SocketListener::Read);
208 203
209 ASSERT_EQ(1U, listener.size()); 204 ASSERT_EQ(1U, listener.size());
210 ASSERT_EQ(1, listener.backend().m_callcount); 205 ASSERT_EQ(1, listener.backend().m_callcount);
211 ASSERT_TRUE(listener.backend().m_added); 206 ASSERT_TRUE(listener.backend().m_added);
212 ASSERT_TRUE(listener.backend().m_flags == SocketListener::Read); 207 ASSERT_TRUE(listener.backend().m_flags == SocketListener::Read);
213 } 208 }
214 209
215 TEST(ListenerSet, readThenWrite) 210 TEST(ListenerSet, readThenWrite)
216 { 211 {
217 SocketListenerBase<TestBackendSet> listener; 212 SocketListenerBase<TestBackendSet> listener;
218 Socket sc(0); 213 std::shared_ptr<Socket> sc = std::make_shared<Socket>(0);
219 214
220 listener.set(sc, SocketListener::Read); 215 listener.set(sc, SocketListener::Read);
221 listener.set(sc, SocketListener::Write); 216 listener.set(sc, SocketListener::Write);
222 217
223 ASSERT_EQ(1U, listener.size()); 218 ASSERT_EQ(1U, listener.size());
227 } 222 }
228 223
229 TEST(ListenerSet, allOneShot) 224 TEST(ListenerSet, allOneShot)
230 { 225 {
231 SocketListenerBase<TestBackendSet> listener; 226 SocketListenerBase<TestBackendSet> listener;
232 Socket sc(0); 227 std::shared_ptr<Socket> sc = std::make_shared<Socket>(0);
233 228
234 listener.set(sc, SocketListener::Read | SocketListener::Write); 229 listener.set(sc, SocketListener::Read | SocketListener::Write);
235 230
236 ASSERT_EQ(1U, listener.size()); 231 ASSERT_EQ(1U, listener.size());
237 ASSERT_EQ(1, listener.backend().m_callcount); 232 ASSERT_EQ(1, listener.backend().m_callcount);
240 } 235 }
241 236
242 TEST(ListenerSet, readTwice) 237 TEST(ListenerSet, readTwice)
243 { 238 {
244 SocketListenerBase<TestBackendSet> listener; 239 SocketListenerBase<TestBackendSet> listener;
245 Socket sc(0); 240 std::shared_ptr<Socket> sc = std::make_shared<Socket>(0);
246 241
247 listener.set(sc, SocketListener::Read); 242 listener.set(sc, SocketListener::Read);
248 listener.set(sc, SocketListener::Read); 243 listener.set(sc, SocketListener::Read);
249 244
250 ASSERT_EQ(1U, listener.size()); 245 ASSERT_EQ(1U, listener.size());
256 TEST(ListenerSet, failure) 251 TEST(ListenerSet, failure)
257 { 252 {
258 SocketListenerBase<TestBackendSetFail> listener; 253 SocketListenerBase<TestBackendSetFail> listener;
259 254
260 try { 255 try {
261 listener.set(Socket(0), SocketListener::Read); 256 listener.set(std::make_shared<Socket>(0), SocketListener::Read);
262 FAIL() << "exception expected"; 257 FAIL() << "exception expected";
263 } catch (...) { 258 } catch (...) {
264 } 259 }
265 260
266 ASSERT_EQ(0U, listener.size()); 261 ASSERT_EQ(0U, listener.size());
275 bool m_isset{false}; 270 bool m_isset{false};
276 bool m_isunset{false}; 271 bool m_isunset{false};
277 int m_flags{0}; 272 int m_flags{0};
278 bool m_removal{false}; 273 bool m_removal{false};
279 274
280 inline void set(const SocketTable &, Socket, int flags, bool) noexcept 275 inline void set(const SocketTable &, const std::shared_ptr<Socket> &, int flags, bool) noexcept
281 { 276 {
282 m_isset = true; 277 m_isset = true;
283 m_flags |= flags; 278 m_flags |= flags;
284 } 279 }
285 280
286 inline void unset(const SocketTable &, Socket, int flags, bool remove) noexcept 281 inline void unset(const SocketTable &, const std::shared_ptr<Socket> &, int flags, bool remove) noexcept
287 { 282 {
288 m_isunset = true; 283 m_isunset = true;
289 m_flags &= ~(flags); 284 m_flags &= ~(flags);
290 m_removal = remove; 285 m_removal = remove;
291 } 286 }
293 std::vector<SocketStatus> wait(const SocketTable &table, int ms) {} 288 std::vector<SocketStatus> wait(const SocketTable &table, int ms) {}
294 }; 289 };
295 290
296 class TestBackendUnsetFail { 291 class TestBackendUnsetFail {
297 public: 292 public:
298 inline void set(const SocketTable &, Socket, int, bool) noexcept {} 293 inline void set(const SocketTable &, const std::shared_ptr<Socket> &, int, bool) noexcept {}
299 294
300 inline void unset(const SocketTable &, Socket, int, bool) 295 inline void unset(const SocketTable &, const std::shared_ptr<Socket> &, int, bool)
301 { 296 {
302 throw "fail"; 297 throw "fail";
303 } 298 }
304 299
305 std::vector<SocketStatus> wait(const SocketTable &table, int ms) {} 300 std::vector<SocketStatus> wait(const SocketTable &table, int ms) {}
306 }; 301 };
307 302
308 TEST(ListenerUnsetRemove, unset) 303 TEST(ListenerUnsetRemove, unset)
309 { 304 {
310 SocketListenerBase<TestBackendUnset> listener; 305 SocketListenerBase<TestBackendUnset> listener;
311 Socket sc(0); 306 std::shared_ptr<Socket> sc = std::make_shared<Socket>(0);
312 307
313 listener.set(sc, SocketListener::Read); 308 listener.set(sc, SocketListener::Read);
314 listener.unset(sc, SocketListener::Read); 309 listener.unset(sc, SocketListener::Read);
315 310
316 ASSERT_EQ(0U, listener.size()); 311 ASSERT_EQ(0U, listener.size());
321 } 316 }
322 317
323 TEST(ListenerUnsetRemove, unsetOne) 318 TEST(ListenerUnsetRemove, unsetOne)
324 { 319 {
325 SocketListenerBase<TestBackendUnset> listener; 320 SocketListenerBase<TestBackendUnset> listener;
326 Socket sc(0); 321 std::shared_ptr<Socket> sc = std::make_shared<Socket>(0);
327 322
328 listener.set(sc, SocketListener::Read | SocketListener::Write); 323 listener.set(sc, SocketListener::Read | SocketListener::Write);
329 listener.unset(sc, SocketListener::Read); 324 listener.unset(sc, SocketListener::Read);
330 325
331 ASSERT_EQ(1U, listener.size()); 326 ASSERT_EQ(1U, listener.size());
336 } 331 }
337 332
338 TEST(ListenerUnsetRemove, unsetAll) 333 TEST(ListenerUnsetRemove, unsetAll)
339 { 334 {
340 SocketListenerBase<TestBackendUnset> listener; 335 SocketListenerBase<TestBackendUnset> listener;
341 Socket sc(0); 336 std::shared_ptr<Socket> sc = std::make_shared<Socket>(0);
342 337
343 listener.set(sc, SocketListener::Read | SocketListener::Write); 338 listener.set(sc, SocketListener::Read | SocketListener::Write);
344 listener.unset(sc, SocketListener::Read); 339 listener.unset(sc, SocketListener::Read);
345 listener.unset(sc, SocketListener::Write); 340 listener.unset(sc, SocketListener::Write);
346 341
352 } 347 }
353 348
354 TEST(ListenerUnsetRemove, remove) 349 TEST(ListenerUnsetRemove, remove)
355 { 350 {
356 SocketListenerBase<TestBackendUnset> listener; 351 SocketListenerBase<TestBackendUnset> listener;
357 Socket sc(0); 352 std::shared_ptr<Socket> sc = std::make_shared<Socket>(0);
358 353
359 listener.set(sc, SocketListener::Read | SocketListener::Write); 354 listener.set(sc, SocketListener::Read | SocketListener::Write);
360 listener.remove(sc); 355 listener.remove(sc);
361 356
362 ASSERT_EQ(0U, listener.size()); 357 ASSERT_EQ(0U, listener.size());
367 } 362 }
368 363
369 TEST(ListenerUnsetRemove, failure) 364 TEST(ListenerUnsetRemove, failure)
370 { 365 {
371 SocketListenerBase<TestBackendUnsetFail> listener; 366 SocketListenerBase<TestBackendUnsetFail> listener;
372 Socket sc(0); 367 std::shared_ptr<Socket> sc = std::make_shared<Socket>(0);
373 368
374 listener.set(sc, SocketListener::Read | SocketListener::Write); 369 listener.set(sc, SocketListener::Read | SocketListener::Write);
375 370
376 try { 371 try {
377 listener.remove(sc); 372 listener.remove(sc);
388 * -------------------------------------------------------- */ 383 * -------------------------------------------------------- */
389 384
390 class ListenerTest : public testing::Test { 385 class ListenerTest : public testing::Test {
391 protected: 386 protected:
392 SocketListenerBase<backend::Select> m_listener; 387 SocketListenerBase<backend::Select> m_listener;
393 SocketTcp m_masterTcp{AF_INET, 0}; 388 std::shared_ptr<SocketTcp> m_masterTcp;
394 SocketTcp m_clientTcp{AF_INET, 0}; 389 std::shared_ptr<SocketTcp> m_clientTcp;
395 390
396 std::thread m_tserver; 391 std::thread m_tserver;
397 std::thread m_tclient; 392 std::thread m_tclient;
398 393
399 public: 394 public:
400 ListenerTest() 395 ListenerTest()
401 { 396 : m_masterTcp{std::make_shared<SocketTcp>(AF_INET, 0)}
402 m_masterTcp.set(SOL_SOCKET, SO_REUSEADDR, 1); 397 , m_clientTcp{std::make_shared<SocketTcp>(AF_INET, 0)}
403 m_masterTcp.bind(Internet("*", 16000, AF_INET)); 398 {
404 m_masterTcp.listen(); 399 m_masterTcp->set(SOL_SOCKET, SO_REUSEADDR, 1);
400 m_masterTcp->bind(Internet("*", 16000, AF_INET));
401 m_masterTcp->listen();
405 } 402 }
406 403
407 ~ListenerTest() 404 ~ListenerTest()
408 { 405 {
409 if (m_tserver.joinable()) { 406 if (m_tserver.joinable()) {
419 { 416 {
420 m_tserver = std::thread([this] () { 417 m_tserver = std::thread([this] () {
421 try { 418 try {
422 m_listener.set(m_masterTcp, SocketListener::Read); 419 m_listener.set(m_masterTcp, SocketListener::Read);
423 m_listener.wait(); 420 m_listener.wait();
424 m_masterTcp.accept(); 421 m_masterTcp->accept();
425 m_masterTcp.close(); 422 m_masterTcp->close();
426 } catch (const std::exception &ex) { 423 } catch (const std::exception &ex) {
427 FAIL() << ex.what(); 424 FAIL() << ex.what();
428 } 425 }
429 }); 426 });
430 427
431 std::this_thread::sleep_for(100ms); 428 std::this_thread::sleep_for(100ms);
432 429
433 m_tclient = std::thread([this] () { 430 m_tclient = std::thread([this] () {
434 m_clientTcp.connect(Internet("127.0.0.1", 16000, AF_INET)); 431 m_clientTcp->connect(std::make_unique<Internet>("127.0.0.1", 16000, AF_INET));
435 }); 432 });
436 } 433 }
437 434
438 TEST_F(ListenerTest, recv) 435 TEST_F(ListenerTest, recv)
439 { 436 {
440 m_tserver = std::thread([this] () { 437 m_tserver = std::thread([this] () {
441 try { 438 try {
442 m_listener.set(m_masterTcp, SocketListener::Read); 439 m_listener.set(m_masterTcp, SocketListener::Read);
443 m_listener.wait(); 440 m_listener.wait();
444 441
445 auto sc = m_masterTcp.accept(); 442 auto sc = m_masterTcp->accept();
446 443
447 ASSERT_EQ("hello", sc.recv(512)); 444 ASSERT_EQ("hello", sc->recv(512));
448
449 m_masterTcp.close();
450 } catch (const std::exception &ex) { 445 } catch (const std::exception &ex) {
451 FAIL() << ex.what(); 446 FAIL() << ex.what();
452 } 447 }
453 }); 448 });
454 449
455 std::this_thread::sleep_for(100ms); 450 std::this_thread::sleep_for(100ms);
456 451
457 m_tclient = std::thread([this] () { 452 m_tclient = std::thread([this] () {
458 m_clientTcp.connect(Internet("127.0.0.1", 16000, AF_INET)); 453 m_clientTcp->connect(std::make_unique<Internet>("127.0.0.1", 16000, AF_INET));
459 m_clientTcp.send("hello"); 454 m_clientTcp->send("hello");
460 }); 455 });
461 } 456 }
462 457
463 /* -------------------------------------------------------- 458 /* --------------------------------------------------------
464 * Non-blocking connect 459 * Non-blocking connect
485 if (m_tclient.joinable()) 480 if (m_tclient.joinable())
486 m_tclient.join(); 481 m_tclient.join();
487 } 482 }
488 }; 483 };
489 484
490 TEST_F(NonBlockingConnectTest, success)
491 {
492 m_server.set(SOL_SOCKET, SO_REUSEADDR, 1);
493 m_server.bind(Internet("*", 16000, AF_INET));
494 m_server.listen();
495
496 m_tserver = std::thread([this] () {
497 SocketTcp client = m_server.accept();
498
499 std::this_thread::sleep_for(100ms);
500
501 m_server.close();
502 client.close();
503 });
504
505 std::this_thread::sleep_for(100ms);
506
507 m_tclient = std::thread([this] () {
508 try {
509 m_client.waitConnect(Internet("127.0.0.1", 16000, AF_INET), 3000);
510 } catch (const SocketError &error) {
511 FAIL() << error.function() << ": " << error.what();
512 }
513
514 ASSERT_EQ(SocketState::Connected, m_client.state());
515
516 m_client.close();
517 });
518 }
519
520 TEST_F(NonBlockingConnectTest, fail)
521 {
522 /*
523 * /!\ If you find a way to test this locally please tell me /!\
524 */
525 m_tclient = std::thread([this] () {
526 try {
527 m_client.waitConnect(Internet("google.fr", 9000, AF_INET), 100);
528
529 FAIL() << "Expected exception, got success";
530 } catch (const SocketError &error) {
531 ASSERT_EQ(SocketError::Timeout, error.code());
532 }
533
534 m_client.close();
535 });
536 }
537
538 /* -------------------------------------------------------- 485 /* --------------------------------------------------------
539 * TCP accept 486 * TCP accept
540 * -------------------------------------------------------- */ 487 * -------------------------------------------------------- */
541 488
542 class TcpAcceptTest : public testing::Test { 489 class TcpAcceptTest : public testing::Test {
562 if (m_tclient.joinable()) 509 if (m_tclient.joinable())
563 m_tclient.join(); 510 m_tclient.join();
564 } 511 }
565 }; 512 };
566 513
567 TEST_F(TcpAcceptTest, blockingWaitSuccess)
568 {
569 m_tserver = std::thread([this] () {
570 try {
571 m_server.waitAccept(3000).close();
572 } catch (const SocketError &error) {
573 FAIL() << error.what();
574 }
575
576 m_server.close();
577 });
578
579 std::this_thread::sleep_for(100ms);
580
581 m_tclient = std::thread([this] () {
582 m_client.connect(Internet("127.0.0.1", 16000, AF_INET));
583 m_client.close();
584 });
585 }
586
587 TEST_F(TcpAcceptTest, nonBlockingWaitSuccess)
588 {
589 m_tserver = std::thread([this] () {
590 try {
591 m_server.setBlockMode(false);
592 m_server.waitAccept(3000).close();
593 } catch (const SocketError &error) {
594 FAIL() << error.what();
595 }
596
597 m_server.close();
598 });
599
600 std::this_thread::sleep_for(100ms);
601
602 m_tclient = std::thread([this] () {
603 m_client.connect(Internet("127.0.0.1", 16000, AF_INET));
604 m_client.close();
605 });
606 }
607
608 TEST_F(TcpAcceptTest, nonBlockingWaitFail)
609 {
610 // No client, no accept
611 try {
612 m_server.setBlockMode(false);
613 m_server.waitAccept(100).close();
614
615 FAIL() << "Expected exception, got success";
616 } catch (const SocketError &error) {
617 ASSERT_EQ(SocketError::Timeout, error.code());
618 }
619
620 m_server.close();
621 }
622
623 /* -------------------------------------------------------- 514 /* --------------------------------------------------------
624 * TCP recv 515 * TCP recv
625 * -------------------------------------------------------- */ 516 * -------------------------------------------------------- */
626 517
627 class TcpRecvTest : public testing::Test { 518 class TcpRecvTest : public testing::Test {
650 }; 541 };
651 542
652 TEST_F(TcpRecvTest, blockingSuccess) 543 TEST_F(TcpRecvTest, blockingSuccess)
653 { 544 {
654 m_tserver = std::thread([this] () { 545 m_tserver = std::thread([this] () {
655 SocketTcp client = m_server.accept(); 546 auto client = m_server.accept();
656 547
657 ASSERT_EQ("hello", client.recv(32)); 548 ASSERT_EQ("hello", client->recv(32));
658
659 client.close();
660 m_server.close();
661 }); 549 });
662 550
663 std::this_thread::sleep_for(100ms); 551 std::this_thread::sleep_for(100ms);
664 552
665 m_tclient = std::thread([this] () { 553 m_tclient = std::thread([this] () {
666 m_client.connect(Internet("127.0.0.1", 16000, AF_INET)); 554 m_client.connect(std::make_unique<Internet>("127.0.0.1", 16000, AF_INET));
667 m_client.send("hello");
668 m_client.close();
669 });
670 }
671
672 TEST_F(TcpRecvTest, blockingWaitSuccess)
673 {
674 m_tserver = std::thread([this] () {
675 SocketTcp client = m_server.accept();
676
677 ASSERT_EQ("hello", client.waitRecv(32, 3000));
678
679 client.close();
680 m_server.close();
681 });
682
683 std::this_thread::sleep_for(100ms);
684
685 m_tclient = std::thread([this] () {
686 m_client.connect(Internet("127.0.0.1", 16000, AF_INET));
687 m_client.send("hello");
688 m_client.close();
689 });
690 }
691
692 TEST_F(TcpRecvTest, nonBlockingWaitSuccess)
693 {
694 m_tserver = std::thread([this] () {
695 SocketTcp client = m_server.accept();
696
697 client.setBlockMode(false);
698
699 ASSERT_EQ("hello", client.waitRecv(32, 3000));
700
701 client.close();
702 m_server.close();
703 });
704
705 std::this_thread::sleep_for(100ms);
706
707 m_tclient = std::thread([this] () {
708 m_client.connect(Internet("127.0.0.1", 16000, AF_INET));
709 m_client.send("hello"); 555 m_client.send("hello");
710 m_client.close(); 556 m_client.close();
711 }); 557 });
712 } 558 }
713 559
721 }; 567 };
722 568
723 TEST_F(SslTest, connect) 569 TEST_F(SslTest, connect)
724 { 570 {
725 try { 571 try {
726 client.connect(Internet("google.fr", 443, AF_INET)); 572 client.connect(std::make_unique<Internet>("google.fr", 443, AF_INET));
727 client.close(); 573 client.close();
728 } catch (const SocketError &error) { 574 } catch (const SocketError &error) {
729 FAIL() << error.what(); 575 FAIL() << error.what();
730 } 576 }
731 } 577 }
732 578
733 TEST_F(SslTest, recv) 579 TEST_F(SslTest, recv)
734 { 580 {
735 try { 581 try {
736 client.connect(Internet("google.fr", 443, AF_INET)); 582 client.connect(std::make_unique<Internet>("google.fr", 443, AF_INET));
737 client.send("GET / HTTP/1.0\r\n\r\n"); 583 client.send("GET / HTTP/1.0\r\n\r\n");
738 584
739 std::string msg = client.recv(512); 585 std::string msg = client.recv(512);
740 std::string content = msg.substr(0, 18); 586 std::string content = msg.substr(0, 18);
741 587