1 | // |
2 | // SocketTest.cpp |
3 | // |
4 | // Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. |
5 | // and Contributors. |
6 | // |
7 | // SPDX-License-Identifier: BSL-1.0 |
8 | // |
9 | |
10 | |
11 | #include "SocketTest.h" |
12 | #include "Poco/CppUnit/TestCaller.h" |
13 | #include "Poco/CppUnit/TestSuite.h" |
14 | #include "EchoServer.h" |
15 | #include "Poco/Net/StreamSocket.h" |
16 | #include "Poco/Net/ServerSocket.h" |
17 | #include "Poco/Net/SocketAddress.h" |
18 | #include "Poco/Net/NetException.h" |
19 | #include "Poco/Timespan.h" |
20 | #include "Poco/Stopwatch.h" |
21 | #include "Poco/Buffer.h" |
22 | #include "Poco/FIFOBuffer.h" |
23 | #include "Poco/Delegate.h" |
24 | #include "Poco/File.h" |
25 | #include <iostream> |
26 | |
27 | |
28 | using Poco::Net::Socket; |
29 | using Poco::Net::StreamSocket; |
30 | using Poco::Net::ServerSocket; |
31 | using Poco::Net::SocketAddress; |
32 | using Poco::Net::ConnectionRefusedException; |
33 | using Poco::Timespan; |
34 | using Poco::Stopwatch; |
35 | using Poco::TimeoutException; |
36 | using Poco::InvalidArgumentException; |
37 | using Poco::Buffer; |
38 | using Poco::FIFOBuffer; |
39 | using Poco::delegate; |
40 | |
41 | |
42 | SocketTest::SocketTest(const std::string& name): CppUnit::TestCase(name) |
43 | { |
44 | } |
45 | |
46 | |
47 | SocketTest::~SocketTest() |
48 | { |
49 | } |
50 | |
51 | |
52 | void SocketTest::testEcho() |
53 | { |
54 | EchoServer echoServer; |
55 | StreamSocket ss; |
56 | ss.connect(SocketAddress("127.0.0.1" , echoServer.port())); |
57 | int n = ss.sendBytes("hello" , 5); |
58 | assertTrue (n == 5); |
59 | char buffer[256]; |
60 | n = ss.receiveBytes(buffer, sizeof(buffer)); |
61 | assertTrue (n == 5); |
62 | assertTrue (std::string(buffer, n) == "hello" ); |
63 | ss.close(); |
64 | } |
65 | |
66 | |
67 | void SocketTest::testPoll() |
68 | { |
69 | EchoServer echoServer; |
70 | StreamSocket ss; |
71 | ss.connect(SocketAddress("127.0.0.1" , echoServer.port())); |
72 | Stopwatch sw; |
73 | sw.start(); |
74 | Timespan timeout(1000000); |
75 | assertTrue (!ss.poll(timeout, Socket::SELECT_READ)); |
76 | assertTrue (sw.elapsed() >= 900000); |
77 | sw.restart(); |
78 | assertTrue (ss.poll(timeout, Socket::SELECT_WRITE)); |
79 | assertTrue (sw.elapsed() < 100000); |
80 | ss.sendBytes("hello" , 5); |
81 | char buffer[256]; |
82 | sw.restart(); |
83 | assertTrue (ss.poll(timeout, Socket::SELECT_READ)); |
84 | assertTrue (sw.elapsed() < 100000); |
85 | int n = ss.receiveBytes(buffer, sizeof(buffer)); |
86 | assertTrue (n == 5); |
87 | assertTrue (std::string(buffer, n) == "hello" ); |
88 | ss.close(); |
89 | } |
90 | |
91 | |
92 | void SocketTest::testAvailable() |
93 | { |
94 | EchoServer echoServer; |
95 | StreamSocket ss; |
96 | ss.connect(SocketAddress("127.0.0.1" , echoServer.port())); |
97 | Timespan timeout(1000000); |
98 | ss.sendBytes("hello" , 5); |
99 | char buffer[256]; |
100 | assertTrue (ss.poll(timeout, Socket::SELECT_READ)); |
101 | int av = ss.available(); |
102 | assertTrue (av > 0 && av <= 5); |
103 | int n = ss.receiveBytes(buffer, sizeof(buffer)); |
104 | assertTrue (n == 5); |
105 | assertTrue (std::string(buffer, n) == "hello" ); |
106 | ss.close(); |
107 | } |
108 | |
109 | |
110 | void SocketTest::testFIFOBuffer() |
111 | { |
112 | Buffer<char> b(5); |
113 | b[0] = 'h'; |
114 | b[1] = 'e'; |
115 | b[2] = 'l'; |
116 | b[3] = 'l'; |
117 | b[4] = 'o'; |
118 | |
119 | FIFOBuffer f(5, true); |
120 | |
121 | f.readable += delegate(this, &SocketTest::onReadable); |
122 | f.writable += delegate(this, &SocketTest::onWritable); |
123 | |
124 | assertTrue (0 == _notToReadable); |
125 | assertTrue (0 == _readableToNot); |
126 | assertTrue (0 == _notToWritable); |
127 | assertTrue (0 == _writableToNot); |
128 | f.write(b); |
129 | assertTrue (1 == _notToReadable); |
130 | assertTrue (0 == _readableToNot); |
131 | assertTrue (0 == _notToWritable); |
132 | assertTrue (1 == _writableToNot); |
133 | |
134 | EchoServer echoServer; |
135 | StreamSocket ss; |
136 | ss.connect(SocketAddress("127.0.0.1" , echoServer.port())); |
137 | int n = ss.sendBytes(f); |
138 | assertTrue (n == 5); |
139 | assertTrue (1 == _notToReadable); |
140 | assertTrue (1 == _readableToNot); |
141 | assertTrue (1 == _notToWritable); |
142 | assertTrue (1 == _writableToNot); |
143 | assertTrue (f.isEmpty()); |
144 | |
145 | n = ss.receiveBytes(f); |
146 | assertTrue (n == 5); |
147 | |
148 | assertTrue (2 == _notToReadable); |
149 | assertTrue (1 == _readableToNot); |
150 | assertTrue (1 == _notToWritable); |
151 | assertTrue (2 == _writableToNot); |
152 | |
153 | assertTrue (f[0] == 'h'); |
154 | assertTrue (f[1] == 'e'); |
155 | assertTrue (f[2] == 'l'); |
156 | assertTrue (f[3] == 'l'); |
157 | assertTrue (f[4] == 'o'); |
158 | |
159 | f.readable -= delegate(this, &SocketTest::onReadable); |
160 | f.writable -= delegate(this, &SocketTest::onWritable); |
161 | |
162 | ss.close(); |
163 | } |
164 | |
165 | |
166 | void SocketTest::testConnect() |
167 | { |
168 | ServerSocket serv; |
169 | serv.bind(SocketAddress()); |
170 | serv.listen(); |
171 | StreamSocket ss; |
172 | Timespan timeout(250000); |
173 | ss.connect(SocketAddress("127.0.0.1" , serv.address().port()), timeout); |
174 | } |
175 | |
176 | |
177 | void SocketTest::testConnectRefused() |
178 | { |
179 | ServerSocket serv; |
180 | serv.bind(SocketAddress()); |
181 | serv.listen(); |
182 | Poco::UInt16 port = serv.address().port(); |
183 | serv.close(); |
184 | StreamSocket ss; |
185 | Timespan timeout(250000); |
186 | try |
187 | { |
188 | ss.connect(SocketAddress("127.0.0.1" , port)); |
189 | fail("connection refused - must throw" ); |
190 | } |
191 | catch (ConnectionRefusedException&) |
192 | { |
193 | } |
194 | } |
195 | |
196 | |
197 | void SocketTest::testConnectRefusedNB() |
198 | { |
199 | ServerSocket serv; |
200 | serv.bind(SocketAddress()); |
201 | serv.listen(); |
202 | Poco::UInt16 port = serv.address().port(); |
203 | serv.close(); |
204 | StreamSocket ss; |
205 | Timespan timeout(2, 0); |
206 | try |
207 | { |
208 | ss.connect(SocketAddress("127.0.0.1" , port), timeout); |
209 | fail("connection refused - must throw" ); |
210 | } |
211 | catch (TimeoutException&) |
212 | { |
213 | } |
214 | catch (ConnectionRefusedException&) |
215 | { |
216 | } |
217 | } |
218 | |
219 | |
220 | void SocketTest::testNonBlocking() |
221 | { |
222 | EchoServer echoServer; |
223 | StreamSocket ss; |
224 | ss.connect(SocketAddress("127.0.0.1" , echoServer.port())); |
225 | ss.setBlocking(false); |
226 | |
227 | Timespan timeout(1000000); |
228 | assertTrue (ss.poll(timeout, Socket::SELECT_WRITE)); |
229 | int n = ss.sendBytes("hello" , 5); |
230 | assertTrue (n == 5); |
231 | |
232 | char buffer[256]; |
233 | assertTrue (ss.poll(timeout, Socket::SELECT_READ)); |
234 | n = ss.receiveBytes(buffer, sizeof(buffer)); |
235 | assertTrue (n == 5); |
236 | assertTrue (std::string(buffer, n) == "hello" ); |
237 | ss.close(); |
238 | } |
239 | |
240 | |
241 | |
242 | void SocketTest::testAddress() |
243 | { |
244 | ServerSocket serv; |
245 | serv.bind(SocketAddress()); |
246 | serv.listen(); |
247 | StreamSocket ss; |
248 | ss.connect(SocketAddress("127.0.0.1" , serv.address().port())); |
249 | StreamSocket css = serv.acceptConnection(); |
250 | assertTrue (css.peerAddress().host() == ss.address().host()); |
251 | assertTrue (css.peerAddress().port() == ss.address().port()); |
252 | } |
253 | |
254 | |
255 | void SocketTest::testAssign() |
256 | { |
257 | ServerSocket serv; |
258 | StreamSocket ss1; |
259 | StreamSocket ss2; |
260 | |
261 | assertTrue (ss1 != ss2); |
262 | StreamSocket ss3(ss1); |
263 | assertTrue (ss1 == ss3); |
264 | ss3 = ss2; |
265 | assertTrue (ss1 != ss3); |
266 | assertTrue (ss2 == ss3); |
267 | |
268 | try |
269 | { |
270 | ss1 = serv; |
271 | fail("incompatible assignment - must throw" ); |
272 | } |
273 | catch (InvalidArgumentException&) |
274 | { |
275 | } |
276 | |
277 | try |
278 | { |
279 | StreamSocket ss4(serv); |
280 | fail("incompatible assignment - must throw" ); |
281 | } |
282 | catch (InvalidArgumentException&) |
283 | { |
284 | } |
285 | |
286 | try |
287 | { |
288 | serv = ss1; |
289 | fail("incompatible assignment - must throw" ); |
290 | } |
291 | catch (InvalidArgumentException&) |
292 | { |
293 | } |
294 | |
295 | try |
296 | { |
297 | ServerSocket serv2(ss1); |
298 | fail("incompatible assignment - must throw" ); |
299 | } |
300 | catch (InvalidArgumentException&) |
301 | { |
302 | } |
303 | } |
304 | |
305 | |
306 | void SocketTest::testTimeout() |
307 | { |
308 | EchoServer echoServer; |
309 | StreamSocket ss; |
310 | ss.connect(SocketAddress("127.0.0.1" , echoServer.port())); |
311 | |
312 | Timespan timeout0 = ss.getReceiveTimeout(); |
313 | Timespan timeout(250000); |
314 | ss.setReceiveTimeout(timeout); |
315 | Timespan timeout1 = ss.getReceiveTimeout(); |
316 | std::cout << "original receive timeout: " << timeout0.totalMicroseconds() << std::endl; |
317 | std::cout << "requested receive timeout: " << timeout.totalMicroseconds() << std::endl; |
318 | std::cout << "actual receive timeout: " << timeout1.totalMicroseconds() << std::endl; |
319 | |
320 | // some socket implementations adjust the timeout value |
321 | // assertTrue (ss.getReceiveTimeout() == timeout); |
322 | Stopwatch sw; |
323 | try |
324 | { |
325 | char buffer[256]; |
326 | sw.start(); |
327 | ss.receiveBytes(buffer, sizeof(buffer)); |
328 | fail("nothing to receive - must timeout" ); |
329 | } |
330 | catch (TimeoutException&) |
331 | { |
332 | } |
333 | assertTrue (sw.elapsed() < 1000000); |
334 | |
335 | timeout0 = ss.getSendTimeout(); |
336 | ss.setSendTimeout(timeout); |
337 | timeout1 = ss.getSendTimeout(); |
338 | std::cout << "original send timeout: " << timeout0.totalMicroseconds() << std::endl; |
339 | std::cout << "requested send timeout: " << timeout.totalMicroseconds() << std::endl; |
340 | std::cout << "actual send timeout: " << timeout1.totalMicroseconds() << std::endl; |
341 | // assertTrue (ss.getSendTimeout() == timeout); |
342 | } |
343 | |
344 | |
345 | void SocketTest::testBufferSize() |
346 | { |
347 | EchoServer echoServer; |
348 | SocketAddress sa("127.0.0.1" , 1234); |
349 | StreamSocket ss(sa.family()); |
350 | |
351 | int osz = ss.getSendBufferSize(); |
352 | int rsz = 32000; |
353 | ss.setSendBufferSize(rsz); |
354 | int asz = ss.getSendBufferSize(); |
355 | std::cout << "original send buffer size: " << osz << std::endl; |
356 | std::cout << "requested send buffer size: " << rsz << std::endl; |
357 | std::cout << "actual send buffer size: " << asz << std::endl; |
358 | |
359 | osz = ss.getReceiveBufferSize(); |
360 | ss.setReceiveBufferSize(rsz); |
361 | asz = ss.getReceiveBufferSize(); |
362 | std::cout << "original recv buffer size: " << osz << std::endl; |
363 | std::cout << "requested recv buffer size: " << rsz << std::endl; |
364 | std::cout << "actual recv buffer size: " << asz << std::endl; |
365 | } |
366 | |
367 | |
368 | void SocketTest::testOptions() |
369 | { |
370 | EchoServer echoServer; |
371 | StreamSocket ss; |
372 | ss.connect(SocketAddress("127.0.0.1" , echoServer.port())); |
373 | |
374 | ss.setLinger(true, 20); |
375 | bool f; |
376 | int t; |
377 | ss.getLinger(f, t); |
378 | assertTrue (f && t == 20); |
379 | ss.setLinger(false, 0); |
380 | ss.getLinger(f, t); |
381 | assertTrue (!f); |
382 | |
383 | ss.setNoDelay(true); |
384 | assertTrue (ss.getNoDelay()); |
385 | ss.setNoDelay(false); |
386 | assertTrue (!ss.getNoDelay()); |
387 | |
388 | ss.setKeepAlive(true); |
389 | assertTrue (ss.getKeepAlive()); |
390 | ss.setKeepAlive(false); |
391 | assertTrue (!ss.getKeepAlive()); |
392 | |
393 | ss.setOOBInline(true); |
394 | assertTrue (ss.getOOBInline()); |
395 | ss.setOOBInline(false); |
396 | assertTrue (!ss.getOOBInline()); |
397 | } |
398 | |
399 | |
400 | void SocketTest::testSelect() |
401 | { |
402 | Timespan timeout(250000); |
403 | |
404 | EchoServer echoServer; |
405 | StreamSocket ss; |
406 | ss.connect(SocketAddress("127.0.0.1" , echoServer.port())); |
407 | |
408 | Socket::SocketList readList; |
409 | Socket::SocketList writeList; |
410 | Socket::SocketList exceptList; |
411 | |
412 | readList.push_back(ss); |
413 | assertTrue (Socket::select(readList, writeList, exceptList, timeout) == 0); |
414 | assertTrue (readList.empty()); |
415 | assertTrue (writeList.empty()); |
416 | assertTrue (exceptList.empty()); |
417 | |
418 | ss.sendBytes("hello" , 5); |
419 | |
420 | ss.poll(timeout, Socket::SELECT_READ); |
421 | |
422 | readList.push_back(ss); |
423 | writeList.push_back(ss); |
424 | assertTrue (Socket::select(readList, writeList, exceptList, timeout) == 2); |
425 | assertTrue (!readList.empty()); |
426 | assertTrue (!writeList.empty()); |
427 | assertTrue (exceptList.empty()); |
428 | |
429 | char buffer[256]; |
430 | int n = ss.receiveBytes(buffer, sizeof(buffer)); |
431 | assertTrue (n == 5); |
432 | assertTrue (std::string(buffer, n) == "hello" ); |
433 | ss.close(); |
434 | } |
435 | |
436 | |
437 | void SocketTest::testSelect2() |
438 | { |
439 | Timespan timeout(100000); |
440 | |
441 | EchoServer echoServer1; |
442 | EchoServer echoServer2; |
443 | StreamSocket ss1(SocketAddress("127.0.0.1" , echoServer1.port())); |
444 | StreamSocket ss2(SocketAddress("127.0.0.1" , echoServer2.port())); |
445 | |
446 | Socket::SocketList readList; |
447 | Socket::SocketList writeList; |
448 | Socket::SocketList exceptList; |
449 | |
450 | readList.push_back(ss1); |
451 | readList.push_back(ss2); |
452 | assertTrue (Socket::select(readList, writeList, exceptList, timeout) == 0); |
453 | assertTrue (readList.empty()); |
454 | assertTrue (writeList.empty()); |
455 | assertTrue (exceptList.empty()); |
456 | |
457 | ss1.sendBytes("hello" , 5); |
458 | |
459 | ss1.poll(timeout, Socket::SELECT_READ); |
460 | |
461 | readList.push_back(ss1); |
462 | readList.push_back(ss2); |
463 | assertTrue (Socket::select(readList, writeList, exceptList, timeout) == 1); |
464 | |
465 | assertTrue (readList.size() == 1); |
466 | assertTrue (readList[0] == ss1); |
467 | assertTrue (writeList.empty()); |
468 | assertTrue (exceptList.empty()); |
469 | |
470 | char buffer[256]; |
471 | int n = ss1.receiveBytes(buffer, sizeof(buffer)); |
472 | assertTrue (n == 5); |
473 | |
474 | readList.clear(); |
475 | writeList.clear(); |
476 | exceptList.clear(); |
477 | writeList.push_back(ss1); |
478 | writeList.push_back(ss2); |
479 | assertTrue (Socket::select(readList, writeList, exceptList, timeout) == 2); |
480 | assertTrue (readList.empty()); |
481 | assertTrue (writeList.size() == 2); |
482 | assertTrue (writeList[0] == ss1); |
483 | assertTrue (writeList[1] == ss2); |
484 | assertTrue (exceptList.empty()); |
485 | |
486 | ss1.close(); |
487 | ss2.close(); |
488 | } |
489 | |
490 | |
491 | void SocketTest::testSelect3() |
492 | { |
493 | Socket::SocketList readList; |
494 | Socket::SocketList writeList; |
495 | Socket::SocketList exceptList; |
496 | Timespan timeout(1000); |
497 | |
498 | int rc = Socket::select(readList, writeList, exceptList, timeout); |
499 | assertTrue (rc == 0); |
500 | } |
501 | |
502 | |
503 | void SocketTest::testEchoUnixLocal() |
504 | { |
505 | #if defined(POCO_OS_FAMILY_UNIX) |
506 | #if POCO_OS == POCO_OS_ANDROID |
507 | Poco::File socketFile("/data/local/tmp/SocketTest.sock" ); |
508 | #else |
509 | Poco::File socketFile("/tmp/SocketTest.sock" ); |
510 | #endif |
511 | if (socketFile.exists()) socketFile.remove(); |
512 | SocketAddress localAddr(SocketAddress::UNIX_LOCAL, socketFile.path()); |
513 | EchoServer echoServer(localAddr); |
514 | StreamSocket ss(SocketAddress::UNIX_LOCAL); |
515 | ss.connect(localAddr); |
516 | int n = ss.sendBytes("hello" , 5); |
517 | assertTrue (n == 5); |
518 | char buffer[256]; |
519 | n = ss.receiveBytes(buffer, sizeof(buffer)); |
520 | assertTrue (n == 5); |
521 | assertTrue (std::string(buffer, n) == "hello" ); |
522 | ss.close(); |
523 | socketFile.remove(); |
524 | #endif |
525 | } |
526 | |
527 | void SocketTest::testEchoLinuxAbstract() |
528 | { |
529 | #if POCO_OS == POCO_OS_LINUX || POCO_OS == POCO_OS_ANDROID |
530 | std::string path("sock.pocoproject.org" ); |
531 | path.insert(0, 1, '\0'); |
532 | SocketAddress localAddr(SocketAddress::UNIX_LOCAL, path); |
533 | EchoServer echoServer(localAddr); |
534 | StreamSocket ss(SocketAddress::UNIX_LOCAL); |
535 | ss.connect(localAddr); |
536 | int n = ss.sendBytes("hello" , 5); |
537 | assertTrue(n == 5); |
538 | char buffer[256]; |
539 | n = ss.receiveBytes(buffer, sizeof(buffer)); |
540 | assertTrue(n == 5); |
541 | assertTrue(std::string(buffer, n) == "hello" ); |
542 | ss.close(); |
543 | #endif |
544 | } |
545 | |
546 | void SocketTest::onReadable(bool& b) |
547 | { |
548 | if (b) ++_notToReadable; |
549 | else ++_readableToNot; |
550 | }; |
551 | |
552 | |
553 | void SocketTest::onWritable(bool& b) |
554 | { |
555 | if (b) ++_notToWritable; |
556 | else ++_writableToNot; |
557 | } |
558 | |
559 | |
560 | void SocketTest::setUp() |
561 | { |
562 | _readableToNot = 0; |
563 | _notToReadable = 0; |
564 | _writableToNot = 0; |
565 | _notToWritable = 0; |
566 | } |
567 | |
568 | |
569 | void SocketTest::tearDown() |
570 | { |
571 | } |
572 | |
573 | |
574 | CppUnit::Test* SocketTest::suite() |
575 | { |
576 | CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("SocketTest" ); |
577 | |
578 | CppUnit_addTest(pSuite, SocketTest, testEcho); |
579 | CppUnit_addTest(pSuite, SocketTest, testPoll); |
580 | CppUnit_addTest(pSuite, SocketTest, testAvailable); |
581 | CppUnit_addTest(pSuite, SocketTest, testFIFOBuffer); |
582 | CppUnit_addTest(pSuite, SocketTest, testConnect); |
583 | CppUnit_addTest(pSuite, SocketTest, testConnectRefused); |
584 | CppUnit_addTest(pSuite, SocketTest, testConnectRefusedNB); |
585 | CppUnit_addTest(pSuite, SocketTest, testNonBlocking); |
586 | CppUnit_addTest(pSuite, SocketTest, testAddress); |
587 | CppUnit_addTest(pSuite, SocketTest, testAssign); |
588 | CppUnit_addTest(pSuite, SocketTest, testTimeout); |
589 | CppUnit_addTest(pSuite, SocketTest, testBufferSize); |
590 | CppUnit_addTest(pSuite, SocketTest, testOptions); |
591 | CppUnit_addTest(pSuite, SocketTest, testSelect); |
592 | CppUnit_addTest(pSuite, SocketTest, testSelect2); |
593 | CppUnit_addTest(pSuite, SocketTest, testSelect3); |
594 | CppUnit_addTest(pSuite, SocketTest, testEchoUnixLocal); |
595 | CppUnit_addTest(pSuite, SocketTest, testEchoLinuxAbstract); |
596 | |
597 | return pSuite; |
598 | } |
599 | |