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