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