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