Commit | Line | Data |
---|---|---|
45a2ebc9 GE |
1 | /*************************************************************************** |
2 | * Copyright (C) 2004 by Intra2net AG * | |
3 | * info@intra2net.com * | |
4 | * * | |
5 | ***************************************************************************/ | |
6 | ||
7 | #include <sys/types.h> | |
8 | #include <unistd.h> | |
9 | #include <errno.h> | |
10 | #include <signal.h> | |
11 | #include <stdio.h> | |
12 | ||
13 | #include <iostream> | |
14 | #include <string> | |
15 | #include <sstream> | |
16 | #include <stdexcept> | |
17 | ||
18 | #include <boost/bind.hpp> | |
19 | ||
20 | #include <cppunit/extensions/TestFactoryRegistry.h> | |
21 | #include <cppunit/ui/text/TestRunner.h> | |
22 | #include <cppunit/extensions/HelperMacros.h> | |
23 | ||
24 | #include <boost/archive/binary_oarchive.hpp> | |
25 | #include <boost/archive/binary_iarchive.hpp> | |
26 | #include <boost/archive/xml_oarchive.hpp> | |
27 | #include <boost/archive/xml_iarchive.hpp> | |
28 | #include <boost/serialization/serialization.hpp> | |
29 | ||
30 | #include <container.hxx> | |
31 | #include <socket_client.hxx> | |
32 | #include <socket_server.hxx> | |
33 | #include <command_client.hxx> | |
34 | #include <command_server.hxx> | |
35 | ||
36 | #ifdef HAVE_CONFIG_H | |
37 | #include <config.h> | |
38 | #endif | |
39 | ||
40 | using namespace std; | |
41 | using namespace libt2n; | |
42 | using namespace CppUnit; | |
43 | ||
44 | string testfunc2(const string& str) | |
45 | { | |
46 | if (str=="throw") | |
47 | throw libt2n::t2n_runtime_error("throw me around"); | |
48 | string ret(str); | |
49 | ret+=", testfunc() was here"; | |
50 | return ret; | |
51 | } | |
52 | ||
53 | class testfunc2_res : public libt2n::result | |
54 | { | |
55 | private: | |
56 | string res; | |
57 | ||
58 | friend class boost::serialization::access; | |
59 | template<class Archive> | |
60 | void serialize(Archive & ar, const unsigned int version) | |
61 | { | |
62 | ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::result); | |
63 | ar & BOOST_SERIALIZATION_NVP(res); | |
64 | } | |
65 | ||
66 | public: | |
67 | testfunc2_res() | |
68 | { } | |
69 | ||
70 | testfunc2_res(const string& str) | |
71 | { | |
72 | res=str; | |
73 | } | |
74 | ||
75 | string get_data() | |
76 | { | |
77 | return res; | |
78 | } | |
79 | }; | |
80 | ||
81 | ||
82 | class testfunc2_cmd : public libt2n::command | |
83 | { | |
84 | private: | |
85 | string param; | |
86 | ||
87 | friend class boost::serialization::access; | |
88 | template<class Archive> | |
89 | void serialize(Archive & ar, const unsigned int version) | |
90 | { | |
91 | ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::command); | |
92 | ar & BOOST_SERIALIZATION_NVP(param); | |
93 | } | |
94 | ||
95 | public: | |
96 | testfunc2_cmd() | |
97 | { } | |
98 | ||
99 | testfunc2_cmd(const string& str) | |
100 | { | |
101 | param=str; | |
102 | } | |
103 | ||
104 | libt2n::result* operator()() | |
105 | { | |
106 | return new testfunc2_res(testfunc2(param)); | |
107 | } | |
108 | }; | |
109 | ||
110 | #include <boost/serialization/export.hpp> | |
111 | ||
112 | BOOST_CLASS_EXPORT(testfunc2_cmd) | |
113 | BOOST_CLASS_EXPORT(testfunc2_res) | |
114 | ||
115 | // this is an evil hack to get access to real_write, don't ever do this in an app!!! | |
116 | class real_write_connection: public socket_server_connection | |
117 | { | |
118 | public: | |
119 | void real_write(const std::string& data) | |
120 | { socket_write(data); } | |
121 | }; | |
122 | ||
c7857475 GE |
123 | // this is an evil hack to get access to real_write, don't ever do this in an app!!! |
124 | class real_write_client_connection: public socket_client_connection | |
125 | { | |
126 | public: | |
127 | void real_write(const std::string& data) | |
128 | { socket_write(data); } | |
129 | }; | |
130 | ||
45a2ebc9 GE |
131 | class test_timeout : public TestFixture |
132 | { | |
133 | CPPUNIT_TEST_SUITE(test_timeout); | |
134 | ||
c7857475 | 135 | CPPUNIT_TEST(ConnectTimeout); |
45a2ebc9 GE |
136 | CPPUNIT_TEST(HelloTimeoutNothing); |
137 | CPPUNIT_TEST(HelloTimeoutSlowData); | |
138 | CPPUNIT_TEST(CommandTimeout); | |
139 | CPPUNIT_TEST(CommandSlowResponse); | |
c7857475 | 140 | CPPUNIT_TEST(DisconnectOnWrite); |
039e52da | 141 | CPPUNIT_TEST(WriteTwice); |
c7857475 GE |
142 | CPPUNIT_TEST(DisconnectOnRead); |
143 | CPPUNIT_TEST(BreakAccept); | |
45a2ebc9 GE |
144 | |
145 | CPPUNIT_TEST_SUITE_END(); | |
146 | ||
b5922184 GE |
147 | pid_t child_pid; |
148 | ||
45a2ebc9 GE |
149 | public: |
150 | ||
151 | typedef uint32_t packet_size_indicator; | |
152 | ||
153 | void setUp() | |
154 | { } | |
155 | ||
156 | void tearDown() | |
b5922184 GE |
157 | { |
158 | // make sure the server-child is dead before the next test runs | |
159 | kill(child_pid,SIGKILL); | |
160 | sleep(1); | |
161 | } | |
45a2ebc9 GE |
162 | |
163 | void send_hello(string hello_string, socket_server* ss, unsigned int conn_id) | |
164 | { | |
165 | server_connection *sc=ss->get_connection(conn_id); | |
166 | sc->write(hello_string); | |
167 | } | |
168 | ||
169 | void send_slow_raw_socket(string data, socket_server* ss, unsigned int conn_id) | |
170 | { | |
171 | socket_server_connection *ssc=dynamic_cast<socket_server_connection*>(ss->get_connection(conn_id)); | |
172 | ||
173 | // this is an evil hack to get access to real_write, don't ever do this in an app!!! | |
174 | real_write_connection *rwc=(real_write_connection*)ssc; | |
175 | ||
176 | // we write one char each 0.2 sec | |
177 | for (int pos=0; pos < data.size(); pos++) | |
178 | { | |
179 | string onebyte; | |
180 | onebyte+=data[pos]; | |
181 | rwc->real_write(onebyte); | |
182 | usleep(200000); | |
183 | } | |
184 | } | |
185 | ||
c7857475 GE |
186 | void ConnectTimeout() |
187 | { | |
b5922184 | 188 | switch(child_pid=fork()) |
c7857475 GE |
189 | { |
190 | case -1: | |
191 | { | |
192 | CPPUNIT_FAIL("fork error"); | |
193 | break; | |
194 | } | |
195 | case 0: | |
196 | // child | |
197 | { | |
441d41fe TJ |
198 | try |
199 | { | |
200 | socket_server ss("./socket"); | |
201 | } catch(...) | |
202 | { | |
203 | std::cerr << "exception in child. ignoring\n"; | |
204 | } | |
c7857475 GE |
205 | |
206 | // don't call atexit and stuff | |
207 | _exit(0); | |
208 | } | |
209 | ||
210 | default: | |
211 | // parent | |
212 | { | |
213 | string data; | |
214 | ||
215 | // wait till server is up | |
216 | sleep(1); | |
217 | ||
218 | string errormsg; | |
219 | ||
fb3345ad | 220 | socket_client_connection sc("./socket"); |
c7857475 | 221 | |
b5922184 GE |
222 | CPPUNIT_ASSERT_EQUAL_MESSAGE("connection not closed",true,sc.connection::is_closed()); |
223 | ||
224 | CPPUNIT_ASSERT_EQUAL_MESSAGE("wrong errormessage",string("no more retries left after connect error"),sc.get_last_error_msg()); | |
c7857475 GE |
225 | } |
226 | } | |
227 | } | |
228 | ||
45a2ebc9 GE |
229 | void HelloTimeoutNothing() |
230 | { | |
b5922184 | 231 | switch(child_pid=fork()) |
45a2ebc9 GE |
232 | { |
233 | case -1: | |
234 | { | |
235 | CPPUNIT_FAIL("fork error"); | |
236 | break; | |
237 | } | |
238 | case 0: | |
239 | // child | |
240 | { | |
441d41fe TJ |
241 | try |
242 | { | |
243 | socket_server ss("./socket"); | |
244 | ||
245 | // max 10 sec | |
246 | for (int i=0; i < 10; i++) | |
247 | ss.fill_buffer(1000000); | |
248 | } catch(...) | |
249 | { | |
250 | std::cerr << "exception in child. ignoring\n"; | |
251 | } | |
45a2ebc9 | 252 | |
45a2ebc9 GE |
253 | // don't call atexit and stuff |
254 | _exit(0); | |
255 | } | |
256 | ||
257 | default: | |
258 | // parent | |
259 | { | |
260 | string data; | |
261 | ||
262 | // wait till server is up | |
263 | sleep(1); | |
264 | socket_client_connection sc("./socket"); | |
b5922184 | 265 | command_client cc(&sc,1000000,1000000); |
45a2ebc9 | 266 | |
b5922184 | 267 | t2n_exception* ep=cc.get_constuctor_exception(); |
45a2ebc9 | 268 | |
b5922184 GE |
269 | string errormsg; |
270 | if (ep) | |
271 | errormsg=ep->what(); | |
45a2ebc9 GE |
272 | |
273 | CPPUNIT_ASSERT_EQUAL(string("timeout exceeded"),errormsg); | |
274 | } | |
275 | } | |
276 | } | |
277 | ||
278 | void HelloTimeoutSlowData() | |
279 | { | |
b5922184 | 280 | switch(child_pid=fork()) |
45a2ebc9 GE |
281 | { |
282 | case -1: | |
283 | { | |
284 | CPPUNIT_FAIL("fork error"); | |
285 | break; | |
286 | } | |
287 | case 0: | |
288 | // child | |
289 | { | |
441d41fe TJ |
290 | try |
291 | { | |
292 | socket_server ss("./socket"); | |
45a2ebc9 | 293 | |
441d41fe TJ |
294 | // create a valid packet |
295 | ostringstream hello; | |
296 | hello << "T2Nv" << PROTOCOL_VERSION << ';'; | |
297 | int byteordercheck=1; | |
298 | hello.write((char*)&byteordercheck,sizeof(byteordercheck)); | |
299 | hello << ';'; | |
45a2ebc9 | 300 | |
441d41fe TJ |
301 | packet_size_indicator psize=htonl(hello.str().size()); |
302 | std::string send_data(hello.str()); | |
303 | send_data.insert(0,(char*)&psize,sizeof(packet_size_indicator)); | |
45a2ebc9 | 304 | |
441d41fe TJ |
305 | ss.add_callback(new_connection,bind(&test_timeout::send_slow_raw_socket, boost::ref(*this), send_data,&ss, _1)); |
306 | ||
307 | // max 10 sec | |
308 | for (int i=0; i < 10; i++) | |
309 | ss.fill_buffer(1000000); | |
310 | } catch(...) | |
311 | { | |
312 | std::cerr << "exception in child. ignoring\n"; | |
313 | } | |
45a2ebc9 | 314 | |
45a2ebc9 GE |
315 | // don't call atexit and stuff |
316 | _exit(0); | |
317 | } | |
318 | ||
319 | default: | |
320 | // parent | |
321 | { | |
322 | string data; | |
323 | ||
324 | // wait till server is up | |
325 | sleep(1); | |
326 | socket_client_connection sc("./socket"); | |
b5922184 | 327 | command_client cc(&sc,1000000,1000000); |
45a2ebc9 | 328 | |
b5922184 | 329 | t2n_exception* ep=cc.get_constuctor_exception(); |
45a2ebc9 | 330 | |
b5922184 GE |
331 | string errormsg; |
332 | if (ep) | |
333 | errormsg=ep->what(); | |
45a2ebc9 GE |
334 | |
335 | CPPUNIT_ASSERT_EQUAL(string("timeout exceeded"),errormsg); | |
336 | } | |
337 | } | |
338 | } | |
339 | ||
340 | void CommandTimeout() | |
341 | { | |
b5922184 | 342 | switch(child_pid=fork()) |
45a2ebc9 GE |
343 | { |
344 | case -1: | |
345 | { | |
346 | CPPUNIT_FAIL("fork error"); | |
347 | break; | |
348 | } | |
349 | case 0: | |
350 | // child | |
351 | { | |
441d41fe TJ |
352 | try |
353 | { | |
354 | socket_server ss("./socket"); | |
45a2ebc9 | 355 | |
441d41fe TJ |
356 | ostringstream hello; |
357 | hello << "T2Nv" << PROTOCOL_VERSION << ';'; | |
358 | int byteordercheck=1; | |
359 | hello.write((char*)&byteordercheck,sizeof(byteordercheck)); | |
360 | hello << ';'; | |
45a2ebc9 | 361 | |
441d41fe TJ |
362 | ss.add_callback(new_connection,bind(&test_timeout::send_hello, boost::ref(*this), hello.str(),&ss, _1)); |
363 | ||
364 | // max 10 sec | |
365 | for (int i=0; i < 10; i++) | |
366 | ss.fill_buffer(1000000); | |
367 | } catch(...) | |
368 | { | |
369 | std::cerr << "exception in child. ignoring\n"; | |
370 | } | |
45a2ebc9 | 371 | |
45a2ebc9 GE |
372 | // don't call atexit and stuff |
373 | _exit(0); | |
374 | } | |
375 | ||
376 | default: | |
377 | // parent | |
378 | { | |
379 | string data; | |
380 | ||
381 | // wait till server is up | |
382 | sleep(1); | |
383 | socket_client_connection sc("./socket"); | |
384 | ||
fb3345ad | 385 | command_client cc(&sc,1000000,1000000); |
45a2ebc9 GE |
386 | result_container rc; |
387 | ||
388 | string errormsg; | |
389 | ||
390 | try | |
391 | { | |
392 | cc.send_command(new testfunc2_cmd("hello"),rc); | |
393 | } | |
394 | catch(t2n_transfer_error &e) | |
395 | { errormsg=e.what(); } | |
396 | catch(...) | |
397 | { throw; } | |
398 | ||
399 | CPPUNIT_ASSERT_EQUAL(string("timeout exceeded"),errormsg); | |
400 | } | |
401 | } | |
402 | } | |
403 | ||
404 | void CommandSlowResponse() | |
405 | { | |
b5922184 | 406 | switch(child_pid=fork()) |
45a2ebc9 GE |
407 | { |
408 | case -1: | |
409 | { | |
410 | CPPUNIT_FAIL("fork error"); | |
411 | break; | |
412 | } | |
413 | case 0: | |
414 | // child | |
415 | { | |
441d41fe TJ |
416 | try |
417 | { | |
418 | socket_server ss("./socket"); | |
45a2ebc9 | 419 | |
441d41fe TJ |
420 | ostringstream hello; |
421 | hello << "T2Nv" << PROTOCOL_VERSION << ';'; | |
422 | int byteordercheck=1; | |
423 | hello.write((char*)&byteordercheck,sizeof(byteordercheck)); | |
424 | hello << ';'; | |
45a2ebc9 | 425 | |
441d41fe | 426 | ss.add_callback(new_connection,bind(&test_timeout::send_hello, boost::ref(*this), hello.str(),&ss, _1)); |
45a2ebc9 | 427 | |
441d41fe TJ |
428 | // max 10 sec |
429 | for (int i=0; i < 10; i++) | |
430 | { | |
431 | ss.fill_buffer(1000000); | |
45a2ebc9 | 432 | |
441d41fe TJ |
433 | string data; |
434 | unsigned int cid; | |
45a2ebc9 | 435 | |
441d41fe TJ |
436 | if(ss.get_packet(data,cid)) |
437 | { | |
438 | // create a valid packet & send | |
439 | string response="abcdefghijklmnopqrstuvwxyz"; | |
440 | packet_size_indicator psize=htonl(response.size()); | |
441 | std::string send_data(response); | |
442 | send_data.insert(0,(char*)&psize,sizeof(packet_size_indicator)); | |
443 | send_slow_raw_socket(send_data,&ss,cid); | |
444 | } | |
45a2ebc9 | 445 | } |
441d41fe TJ |
446 | } catch(...) |
447 | { | |
448 | std::cerr << "exception in child. ignoring\n"; | |
45a2ebc9 | 449 | } |
441d41fe | 450 | |
45a2ebc9 GE |
451 | // don't call atexit and stuff |
452 | _exit(0); | |
453 | } | |
454 | ||
455 | default: | |
456 | // parent | |
457 | { | |
458 | string data; | |
459 | ||
460 | // wait till server is up | |
461 | sleep(1); | |
462 | socket_client_connection sc("./socket"); | |
463 | ||
fb3345ad | 464 | command_client cc(&sc,1000000,1000000); |
45a2ebc9 GE |
465 | result_container rc; |
466 | ||
467 | string errormsg; | |
468 | ||
469 | try | |
470 | { | |
471 | cc.send_command(new testfunc2_cmd("hello"),rc); | |
472 | } | |
473 | catch(t2n_transfer_error &e) | |
474 | { errormsg=e.what(); } | |
475 | catch(...) | |
476 | { throw; } | |
477 | ||
478 | CPPUNIT_ASSERT_EQUAL(string("timeout exceeded"),errormsg); | |
479 | } | |
480 | } | |
481 | } | |
482 | ||
c7857475 GE |
483 | void DisconnectOnWrite() |
484 | { | |
b5922184 | 485 | switch(child_pid=fork()) |
c7857475 GE |
486 | { |
487 | case -1: | |
488 | { | |
489 | CPPUNIT_FAIL("fork error"); | |
490 | break; | |
491 | } | |
492 | case 0: | |
493 | // child | |
494 | { | |
441d41fe TJ |
495 | try |
496 | { | |
497 | socket_server ss("./socket"); | |
498 | ||
499 | // bail out as soon as we get something | |
500 | ss.fill_buffer(-1); | |
501 | } catch(...) | |
502 | { | |
503 | std::cerr << "exception in child. ignoring\n"; | |
504 | } | |
c7857475 | 505 | |
c7857475 GE |
506 | // don't call atexit and stuff |
507 | _exit(0); | |
508 | } | |
509 | ||
510 | default: | |
511 | // parent | |
512 | { | |
513 | string data; | |
514 | ||
515 | // don't kill us on broken pipe | |
516 | signal(SIGPIPE, SIG_IGN); | |
517 | ||
518 | // wait till server is up | |
519 | sleep(1); | |
520 | socket_client_connection sc("./socket"); | |
521 | ||
522 | string errormsg; | |
523 | ||
e72e07f3 | 524 | string huge(5000000,'x'); |
c7857475 GE |
525 | |
526 | try | |
527 | { | |
528 | sc.write(huge); | |
529 | } | |
530 | catch(t2n_transfer_error &e) | |
531 | { errormsg=e.what(); } | |
532 | catch(...) | |
533 | { throw; } | |
534 | ||
535 | CPPUNIT_ASSERT_EQUAL(string("write() returned Broken pipe"),errormsg); | |
536 | } | |
537 | } | |
538 | } | |
539 | ||
039e52da GE |
540 | void WriteTwice() |
541 | { | |
542 | switch(child_pid=fork()) | |
543 | { | |
544 | case -1: | |
545 | { | |
546 | CPPUNIT_FAIL("fork error"); | |
547 | break; | |
548 | } | |
549 | case 0: | |
550 | // child | |
551 | { | |
441d41fe TJ |
552 | try |
553 | { | |
554 | socket_server ss("./socket"); | |
555 | ||
556 | // bail out as soon as we get something | |
557 | ss.fill_buffer(-1); | |
558 | ss.fill_buffer(-1); | |
559 | } catch(...) | |
560 | { | |
561 | std::cerr << "exception in child. ignoring\n"; | |
562 | } | |
039e52da | 563 | |
039e52da GE |
564 | // don't call atexit and stuff |
565 | _exit(0); | |
566 | } | |
567 | ||
568 | default: | |
569 | // parent | |
570 | { | |
571 | string data; | |
572 | ||
573 | // don't kill us on broken pipe | |
574 | signal(SIGPIPE, SIG_IGN); | |
575 | ||
576 | // wait till server is up | |
577 | sleep(1); | |
578 | socket_client_connection sc("./socket"); | |
579 | ||
580 | string errormsg; | |
581 | ||
582 | sc.write("somedata"); | |
583 | ||
584 | sleep(1); | |
585 | ||
586 | // server should disconnect now | |
587 | try | |
588 | { | |
589 | sc.write("other data"); | |
590 | } | |
591 | catch(t2n_transfer_error &e) | |
592 | { errormsg=e.what(); } | |
593 | catch(...) | |
594 | { throw; } | |
595 | ||
596 | CPPUNIT_ASSERT_EQUAL(string("write() returned Broken pipe"),errormsg); | |
597 | } | |
598 | } | |
599 | } | |
600 | ||
c7857475 GE |
601 | void DisconnectOnRead() |
602 | { | |
b5922184 | 603 | pid_t pid2; |
c7857475 | 604 | |
b5922184 | 605 | switch(child_pid=fork()) |
c7857475 GE |
606 | { |
607 | case -1: | |
608 | { | |
609 | CPPUNIT_FAIL("fork error"); | |
610 | break; | |
611 | } | |
612 | case 0: | |
613 | // child | |
614 | { | |
441d41fe TJ |
615 | try |
616 | { | |
617 | // wait till server is up | |
618 | sleep(1); | |
c7857475 | 619 | |
441d41fe | 620 | socket_client_connection sc("./socket"); |
c7857475 | 621 | |
441d41fe TJ |
622 | // this is an evil hack to get access to real_write, don't ever do this in an app!!! |
623 | real_write_client_connection *rwc=(real_write_client_connection*)≻ | |
624 | rwc->real_write(string(10000,'x')); | |
625 | } catch(...) | |
626 | { | |
627 | std::cerr << "exception in child. ignoring\n"; | |
628 | } | |
c7857475 GE |
629 | |
630 | // don't call atexit and stuff | |
631 | _exit(0); | |
632 | } | |
633 | ||
634 | default: | |
635 | // parent | |
636 | { | |
637 | // don't kill us on broken pipe | |
638 | signal(SIGPIPE, SIG_IGN); | |
639 | ||
640 | socket_server ss("./socket"); | |
641 | ||
642 | time_t t0 = time(NULL); | |
643 | ||
644 | // max 5 sec | |
645 | while (time(NULL) < t0 + 5 ) | |
646 | { | |
647 | ss.fill_buffer(1000000); | |
648 | ||
649 | string data; | |
650 | ss.get_packet(data); | |
651 | } | |
652 | ||
653 | // are we still alive and able to process data? | |
654 | ||
fb3345ad | 655 | switch(pid2=fork()) |
c7857475 GE |
656 | { |
657 | case -1: | |
658 | { | |
659 | CPPUNIT_FAIL("fork error"); | |
660 | break; | |
661 | } | |
662 | case 0: | |
663 | // child | |
664 | { | |
441d41fe TJ |
665 | try |
666 | { | |
667 | socket_client_connection *sc=new socket_client_connection("./socket"); | |
668 | sc->write(string(10000,'x')); | |
669 | // socket is closed regularly | |
670 | delete sc; | |
671 | } catch(...) | |
672 | { | |
673 | std::cerr << "exception in child. ignoring\n"; | |
674 | } | |
c7857475 GE |
675 | |
676 | // don't run regular cleanup, otherwise cppunit stuff gets called | |
677 | _exit(0); | |
678 | } | |
679 | ||
680 | default: | |
681 | // parent | |
682 | { | |
683 | string received; | |
684 | ||
685 | t0 = time(NULL); | |
686 | ||
687 | // max 10 sec | |
688 | while (time(NULL) < t0 + 10 ) | |
689 | { | |
690 | ss.fill_buffer(1000000); | |
691 | ||
692 | if (ss.get_packet(received)) | |
693 | break; | |
694 | } | |
695 | ||
696 | CPPUNIT_ASSERT_EQUAL(string(10000,'x'),received); | |
697 | } | |
698 | } | |
699 | } | |
700 | } | |
fb3345ad | 701 | kill(pid2,SIGKILL); |
c7857475 GE |
702 | } |
703 | ||
704 | void BreakAccept() | |
705 | { | |
b5922184 | 706 | pid_t pid2; |
c7857475 | 707 | |
b5922184 | 708 | switch(child_pid=fork()) |
c7857475 GE |
709 | { |
710 | case -1: | |
711 | { | |
712 | CPPUNIT_FAIL("fork error"); | |
713 | break; | |
714 | } | |
715 | case 0: | |
716 | // child | |
717 | { | |
441d41fe TJ |
718 | try |
719 | { | |
720 | // wait till server is really up and waiting | |
721 | sleep(2); | |
c7857475 | 722 | |
441d41fe TJ |
723 | // connect with very tight timeout and only 1 retry |
724 | socket_client_connection sc("./socket",50,1); | |
725 | } catch(...) | |
726 | { | |
727 | std::cerr << "exception in child. ignoring\n"; | |
728 | } | |
c7857475 GE |
729 | |
730 | // don't call atexit and stuff | |
731 | _exit(0); | |
732 | } | |
733 | ||
734 | default: | |
735 | // parent | |
736 | { | |
737 | // don't kill us on broken pipe | |
738 | signal(SIGPIPE, SIG_IGN); | |
739 | ||
740 | socket_server ss("./socket"); | |
741 | ||
742 | // server is "working" while client wants to connect | |
743 | sleep(5); | |
744 | ||
745 | time_t t0 = time(NULL); | |
746 | ||
747 | // max 5 sec | |
748 | while (time(NULL) < t0 + 5 ) | |
749 | { | |
750 | ss.fill_buffer(1000000); | |
751 | ||
752 | string data; | |
753 | ss.get_packet(data); | |
754 | } | |
755 | ||
756 | // are we still alive and able to process data? | |
757 | ||
fb3345ad | 758 | switch(pid2=fork()) |
c7857475 GE |
759 | { |
760 | case -1: | |
761 | { | |
762 | CPPUNIT_FAIL("fork error"); | |
763 | break; | |
764 | } | |
765 | case 0: | |
766 | // child | |
767 | { | |
441d41fe TJ |
768 | try |
769 | { | |
770 | socket_client_connection *sc=new socket_client_connection("./socket"); | |
771 | sc->write(string(10000,'x')); | |
772 | delete sc; | |
773 | // socket is closed regularly | |
774 | } catch(...) | |
775 | { | |
776 | std::cerr << "exception in child. ignoring\n"; | |
777 | } | |
c7857475 GE |
778 | |
779 | // don't run regular cleanup, otherwise cppunit stuff gets called | |
780 | _exit(0); | |
781 | } | |
782 | ||
783 | default: | |
784 | // parent | |
785 | { | |
786 | string received; | |
787 | ||
788 | t0 = time(NULL); | |
789 | ||
790 | // max 10 sec | |
791 | while (time(NULL) < t0 + 10 ) | |
792 | { | |
793 | ss.fill_buffer(1000000); | |
794 | ||
795 | if (ss.get_packet(received)) | |
796 | break; | |
797 | } | |
798 | ||
799 | CPPUNIT_ASSERT_EQUAL(string(10000,'x'),received); | |
800 | } | |
801 | } | |
802 | } | |
803 | } | |
fb3345ad | 804 | kill(pid2,SIGKILL); |
c7857475 | 805 | } |
45a2ebc9 GE |
806 | }; |
807 | ||
808 | CPPUNIT_TEST_SUITE_REGISTRATION(test_timeout); |