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(); } | |
373 | catch(...) | |
374 | { throw; } | |
375 | ||
376 | BOOST_CHECK_EQUAL(string("timeout exceeded"),errormsg); | |
45a2ebc9 GE |
377 | } |
378 | } | |
307b5e74 | 379 | } |
45a2ebc9 | 380 | |
307b5e74 TJ |
381 | BOOST_AUTO_TEST_CASE(CommandSlowResponse) |
382 | { | |
383 | switch(child_pid=fork()) | |
45a2ebc9 | 384 | { |
307b5e74 | 385 | case -1: |
45a2ebc9 | 386 | { |
307b5e74 TJ |
387 | BOOST_FAIL("fork error"); |
388 | break; | |
389 | } | |
390 | case 0: | |
391 | // child | |
392 | { | |
393 | try | |
45a2ebc9 | 394 | { |
307b5e74 | 395 | socket_server ss("./socket"); |
45a2ebc9 | 396 | |
307b5e74 TJ |
397 | ostringstream hello; |
398 | hello << "T2Nv" << PROTOCOL_VERSION << ';'; | |
399 | int byteordercheck=1; | |
400 | hello.write((char*)&byteordercheck,sizeof(byteordercheck)); | |
401 | hello << ';'; | |
45a2ebc9 | 402 | |
307b5e74 | 403 | ss.add_callback(new_connection,bind(&test_timeout::CommandSlowResponse::send_hello, boost::ref(*this), hello.str(),&ss, _1)); |
45a2ebc9 | 404 | |
307b5e74 TJ |
405 | // max 10 sec |
406 | for (int i=0; i < 10; i++) | |
407 | { | |
408 | ss.fill_buffer(1000000); | |
45a2ebc9 | 409 | |
307b5e74 TJ |
410 | string data; |
411 | unsigned int cid; | |
412 | ||
413 | if(ss.get_packet(data,cid)) | |
414 | { | |
415 | // create a valid packet & send | |
416 | string response="abcdefghijklmnopqrstuvwxyz"; | |
417 | packet_size_indicator psize=htonl(response.size()); | |
418 | std::string send_data(response); | |
419 | send_data.insert(0,(char*)&psize,sizeof(packet_size_indicator)); | |
420 | send_slow_raw_socket(send_data,&ss,cid); | |
45a2ebc9 GE |
421 | } |
422 | } | |
307b5e74 TJ |
423 | } catch(...) |
424 | { | |
425 | std::cerr << "exception in child. ignoring\n"; | |
45a2ebc9 GE |
426 | } |
427 | ||
307b5e74 TJ |
428 | // don't call atexit and stuff |
429 | _exit(0); | |
430 | } | |
45a2ebc9 | 431 | |
307b5e74 TJ |
432 | default: |
433 | // parent | |
434 | { | |
435 | string data; | |
45a2ebc9 | 436 | |
307b5e74 TJ |
437 | // wait till server is up |
438 | sleep(1); | |
439 | socket_client_connection sc("./socket"); | |
45a2ebc9 | 440 | |
307b5e74 TJ |
441 | command_client cc(&sc,1000000,1000000); |
442 | result_container rc; | |
45a2ebc9 | 443 | |
307b5e74 | 444 | string errormsg; |
45a2ebc9 | 445 | |
307b5e74 TJ |
446 | try |
447 | { | |
448 | cc.send_command(new testfunc2_cmd("hello"),rc); | |
45a2ebc9 | 449 | } |
307b5e74 TJ |
450 | catch(t2n_transfer_error &e) |
451 | { errormsg=e.what(); } | |
452 | catch(...) | |
453 | { throw; } | |
454 | ||
455 | BOOST_CHECK_EQUAL(string("timeout exceeded"),errormsg); | |
45a2ebc9 GE |
456 | } |
457 | } | |
307b5e74 | 458 | } |
45a2ebc9 | 459 | |
307b5e74 TJ |
460 | BOOST_AUTO_TEST_CASE(DisconnectOnWrite) |
461 | { | |
462 | switch(child_pid=fork()) | |
c7857475 | 463 | { |
307b5e74 | 464 | case -1: |
c7857475 | 465 | { |
307b5e74 TJ |
466 | BOOST_FAIL("fork error"); |
467 | break; | |
468 | } | |
469 | case 0: | |
470 | // child | |
471 | { | |
472 | try | |
c7857475 | 473 | { |
307b5e74 | 474 | socket_server ss("./socket"); |
c7857475 | 475 | |
307b5e74 TJ |
476 | // bail out as soon as we get something |
477 | ss.fill_buffer(-1); | |
478 | } catch(...) | |
479 | { | |
480 | std::cerr << "exception in child. ignoring\n"; | |
c7857475 GE |
481 | } |
482 | ||
307b5e74 TJ |
483 | // don't call atexit and stuff |
484 | _exit(0); | |
485 | } | |
c7857475 | 486 | |
307b5e74 TJ |
487 | default: |
488 | // parent | |
489 | { | |
490 | string data; | |
c7857475 | 491 | |
307b5e74 TJ |
492 | // don't kill us on broken pipe |
493 | signal(SIGPIPE, SIG_IGN); | |
c7857475 | 494 | |
307b5e74 TJ |
495 | // wait till server is up |
496 | sleep(1); | |
497 | socket_client_connection sc("./socket"); | |
c7857475 | 498 | |
307b5e74 | 499 | string errormsg; |
c7857475 | 500 | |
307b5e74 | 501 | string huge(5000000,'x'); |
c7857475 | 502 | |
307b5e74 TJ |
503 | try |
504 | { | |
505 | sc.write(huge); | |
c7857475 | 506 | } |
307b5e74 TJ |
507 | catch(t2n_transfer_error &e) |
508 | { errormsg=e.what(); } | |
509 | catch(...) | |
510 | { throw; } | |
511 | ||
512 | BOOST_CHECK_EQUAL(string("write() returned Broken pipe"),errormsg); | |
c7857475 GE |
513 | } |
514 | } | |
307b5e74 | 515 | } |
c7857475 | 516 | |
307b5e74 TJ |
517 | BOOST_AUTO_TEST_CASE(WriteTwice) |
518 | { | |
519 | switch(child_pid=fork()) | |
039e52da | 520 | { |
307b5e74 | 521 | case -1: |
039e52da | 522 | { |
307b5e74 TJ |
523 | BOOST_FAIL("fork error"); |
524 | break; | |
525 | } | |
526 | case 0: | |
527 | // child | |
528 | { | |
529 | try | |
039e52da | 530 | { |
307b5e74 | 531 | socket_server ss("./socket"); |
039e52da | 532 | |
307b5e74 TJ |
533 | // bail out as soon as we get something |
534 | ss.fill_buffer(-1); | |
535 | ss.fill_buffer(-1); | |
536 | } catch(...) | |
537 | { | |
538 | std::cerr << "exception in child. ignoring\n"; | |
039e52da GE |
539 | } |
540 | ||
307b5e74 TJ |
541 | // don't call atexit and stuff |
542 | _exit(0); | |
543 | } | |
039e52da | 544 | |
307b5e74 TJ |
545 | default: |
546 | // parent | |
547 | { | |
548 | string data; | |
039e52da | 549 | |
307b5e74 TJ |
550 | // don't kill us on broken pipe |
551 | signal(SIGPIPE, SIG_IGN); | |
039e52da | 552 | |
307b5e74 TJ |
553 | // wait till server is up |
554 | sleep(1); | |
555 | socket_client_connection sc("./socket"); | |
039e52da | 556 | |
307b5e74 | 557 | string errormsg; |
039e52da | 558 | |
307b5e74 | 559 | sc.write("somedata"); |
039e52da | 560 | |
307b5e74 | 561 | sleep(1); |
039e52da | 562 | |
307b5e74 TJ |
563 | // server should disconnect now |
564 | try | |
565 | { | |
566 | sc.write("other data(2)"); | |
567 | sleep(1); | |
568 | sc.write("other data(3)"); | |
039e52da | 569 | } |
307b5e74 TJ |
570 | catch(t2n_transfer_error &e) |
571 | { errormsg=e.what(); } | |
572 | catch(...) | |
573 | { throw; } | |
574 | ||
575 | BOOST_CHECK_EQUAL(string("write() returned Broken pipe"),errormsg); | |
039e52da GE |
576 | } |
577 | } | |
307b5e74 | 578 | } |
039e52da | 579 | |
307b5e74 TJ |
580 | BOOST_AUTO_TEST_CASE(DisconnectOnRead) |
581 | { | |
582 | pid_t pid2; | |
c7857475 | 583 | |
307b5e74 TJ |
584 | switch(child_pid=fork()) |
585 | { | |
586 | case -1: | |
587 | { | |
588 | BOOST_FAIL("fork error"); | |
589 | break; | |
590 | } | |
591 | case 0: | |
592 | // child | |
c7857475 | 593 | { |
307b5e74 | 594 | try |
c7857475 | 595 | { |
307b5e74 TJ |
596 | // wait till server is up |
597 | sleep(1); | |
598 | ||
599 | socket_client_connection sc("./socket"); | |
600 | ||
601 | // this is an evil hack to get access to real_write, don't ever do this in an app!!! | |
602 | real_write_client_connection *rwc=(real_write_client_connection*)≻ | |
603 | rwc->real_write(string(10000,'x')); | |
604 | } catch(...) | |
c7857475 | 605 | { |
307b5e74 TJ |
606 | std::cerr << "exception in child. ignoring\n"; |
607 | } | |
c7857475 | 608 | |
307b5e74 TJ |
609 | // don't call atexit and stuff |
610 | _exit(0); | |
611 | } | |
c7857475 | 612 | |
307b5e74 TJ |
613 | default: |
614 | // parent | |
615 | { | |
616 | // don't kill us on broken pipe | |
617 | signal(SIGPIPE, SIG_IGN); | |
c7857475 | 618 | |
307b5e74 TJ |
619 | socket_server ss("./socket"); |
620 | ||
621 | time_t t0 = time(NULL); | |
c7857475 | 622 | |
307b5e74 TJ |
623 | // max 5 sec |
624 | while (time(NULL) < t0 + 5 ) | |
c7857475 | 625 | { |
307b5e74 | 626 | ss.fill_buffer(1000000); |
c7857475 | 627 | |
307b5e74 TJ |
628 | string data; |
629 | ss.get_packet(data); | |
630 | } | |
c7857475 | 631 | |
307b5e74 | 632 | // are we still alive and able to process data? |
c7857475 | 633 | |
307b5e74 TJ |
634 | switch(pid2=fork()) |
635 | { | |
636 | case -1: | |
c7857475 | 637 | { |
307b5e74 TJ |
638 | BOOST_FAIL("fork error"); |
639 | break; | |
c7857475 | 640 | } |
307b5e74 TJ |
641 | case 0: |
642 | // child | |
c7857475 | 643 | { |
307b5e74 | 644 | try |
c7857475 | 645 | { |
307b5e74 TJ |
646 | socket_client_connection *sc=new socket_client_connection("./socket"); |
647 | sc->write(string(10000,'x')); | |
648 | // socket is closed regularly | |
649 | delete sc; | |
650 | } catch(...) | |
c7857475 | 651 | { |
307b5e74 | 652 | std::cerr << "exception in child. ignoring\n"; |
c7857475 GE |
653 | } |
654 | ||
307b5e74 TJ |
655 | // don't run regular cleanup, otherwise cppunit stuff gets called |
656 | _exit(0); | |
657 | } | |
c7857475 | 658 | |
307b5e74 TJ |
659 | default: |
660 | // parent | |
661 | { | |
662 | string received; | |
c7857475 | 663 | |
307b5e74 | 664 | t0 = time(NULL); |
c7857475 | 665 | |
307b5e74 TJ |
666 | // max 10 sec |
667 | while (time(NULL) < t0 + 10 ) | |
668 | { | |
669 | ss.fill_buffer(1000000); | |
c7857475 | 670 | |
307b5e74 TJ |
671 | if (ss.get_packet(received)) |
672 | break; | |
c7857475 | 673 | } |
307b5e74 TJ |
674 | |
675 | BOOST_CHECK_EQUAL(string(10000,'x'),received); | |
c7857475 GE |
676 | } |
677 | } | |
678 | } | |
679 | } | |
307b5e74 TJ |
680 | kill(pid2,SIGKILL); |
681 | } | |
c7857475 | 682 | |
307b5e74 TJ |
683 | BOOST_AUTO_TEST_CASE(BreakAccept) |
684 | { | |
685 | pid_t pid2; | |
c7857475 | 686 | |
307b5e74 TJ |
687 | switch(child_pid=fork()) |
688 | { | |
689 | case -1: | |
c7857475 | 690 | { |
307b5e74 TJ |
691 | BOOST_FAIL("fork error"); |
692 | break; | |
693 | } | |
694 | case 0: | |
695 | // child | |
696 | { | |
697 | try | |
c7857475 | 698 | { |
307b5e74 TJ |
699 | // wait till server is really up and waiting |
700 | sleep(2); | |
c7857475 | 701 | |
307b5e74 TJ |
702 | // connect with very tight timeout and only 1 retry |
703 | socket_client_connection sc("./socket",50,1); | |
704 | } catch(...) | |
705 | { | |
706 | std::cerr << "exception in child. ignoring\n"; | |
c7857475 GE |
707 | } |
708 | ||
307b5e74 TJ |
709 | // don't call atexit and stuff |
710 | _exit(0); | |
711 | } | |
c7857475 | 712 | |
307b5e74 TJ |
713 | default: |
714 | // parent | |
715 | { | |
716 | // don't kill us on broken pipe | |
717 | signal(SIGPIPE, SIG_IGN); | |
c7857475 | 718 | |
307b5e74 | 719 | socket_server ss("./socket"); |
c7857475 | 720 | |
307b5e74 TJ |
721 | // server is "working" while client wants to connect |
722 | sleep(5); | |
c7857475 | 723 | |
307b5e74 | 724 | time_t t0 = time(NULL); |
c7857475 | 725 | |
307b5e74 TJ |
726 | // max 5 sec |
727 | while (time(NULL) < t0 + 5 ) | |
728 | { | |
729 | ss.fill_buffer(1000000); | |
c7857475 | 730 | |
307b5e74 TJ |
731 | string data; |
732 | ss.get_packet(data); | |
733 | } | |
c7857475 | 734 | |
307b5e74 TJ |
735 | // are we still alive and able to process data? |
736 | ||
737 | switch(pid2=fork()) | |
738 | { | |
739 | case -1: | |
c7857475 | 740 | { |
307b5e74 TJ |
741 | BOOST_FAIL("fork error"); |
742 | break; | |
743 | } | |
744 | case 0: | |
745 | // child | |
746 | { | |
747 | try | |
c7857475 | 748 | { |
307b5e74 TJ |
749 | socket_client_connection *sc=new socket_client_connection("./socket"); |
750 | sc->write(string(10000,'x')); | |
751 | delete sc; | |
752 | // socket is closed regularly | |
753 | } catch(...) | |
c7857475 | 754 | { |
307b5e74 | 755 | std::cerr << "exception in child. ignoring\n"; |
c7857475 GE |
756 | } |
757 | ||
307b5e74 TJ |
758 | // don't run regular cleanup, otherwise cppunit stuff gets called |
759 | _exit(0); | |
760 | } | |
c7857475 | 761 | |
307b5e74 TJ |
762 | default: |
763 | // parent | |
764 | { | |
765 | string received; | |
c7857475 | 766 | |
307b5e74 | 767 | t0 = time(NULL); |
c7857475 | 768 | |
307b5e74 TJ |
769 | // max 10 sec |
770 | while (time(NULL) < t0 + 10 ) | |
771 | { | |
772 | ss.fill_buffer(1000000); | |
c7857475 | 773 | |
307b5e74 TJ |
774 | if (ss.get_packet(received)) |
775 | break; | |
c7857475 | 776 | } |
307b5e74 TJ |
777 | |
778 | BOOST_CHECK_EQUAL(string(10000,'x'),received); | |
c7857475 GE |
779 | } |
780 | } | |
781 | } | |
782 | } | |
307b5e74 TJ |
783 | kill(pid2,SIGKILL); |
784 | } | |
45a2ebc9 | 785 | |
307b5e74 | 786 | BOOST_AUTO_TEST_SUITE_END() |