2 Copyright (C) 2004 by Intra2net AG
4 The software in this package is distributed under the GNU General
5 Public License version 2 (with a special exception described below).
7 A copy of GNU General Public License (GPL) is included in this distribution,
8 in the file COPYING.GPL.
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.
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.
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.
22 #include <sys/types.h>
34 #include <cppunit/extensions/TestFactoryRegistry.h>
35 #include <cppunit/ui/text/TestRunner.h>
36 #include <cppunit/extensions/HelperMacros.h>
38 #include <socket_client.hxx>
39 #include <socket_server.hxx>
46 using namespace libt2n;
47 using namespace CppUnit;
49 // this is an evil hack to get access to real_write, don't ever do this in an app!!!
50 class real_write_connection: public socket_server_connection
53 void real_write(const std::string& data)
54 { socket_write(data); }
57 class test_reconnect : public TestFixture
59 CPPUNIT_TEST_SUITE(test_reconnect);
61 CPPUNIT_TEST(simple_reconnect);
62 CPPUNIT_TEST(reconnect_with_close);
63 CPPUNIT_TEST(reconnect_buffer_complete);
64 CPPUNIT_TEST(reconnect_buffer_several_complete);
65 CPPUNIT_TEST(reconnect_buffer_no_incomplete1);
66 CPPUNIT_TEST(reconnect_buffer_no_incomplete2);
68 CPPUNIT_TEST_SUITE_END();
79 // make sure the server-child is dead before the next test runs
80 kill(child_pid,SIGKILL);
84 void send_raw_socket(string hello_string, socket_server* ss, int conn_id)
86 socket_server_connection *ssc=dynamic_cast<socket_server_connection*>(ss->get_connection(conn_id));
88 // this is an evil hack to get access to real_write, don't ever do this in an app!!!
89 real_write_connection *rwc=(real_write_connection*)ssc;
90 rwc->real_write(hello_string);
93 void simple_reconnect()
95 switch(child_pid=fork())
99 CPPUNIT_FAIL("fork error");
107 socket_server ss("./socket");
109 time_t t0 = time(NULL);
112 while (time(NULL) < t0 + 10 )
114 ss.fill_buffer(1000000);
119 if(ss.get_packet(data,cid))
121 server_connection* con=ss.get_connection(cid);
127 con->write(string().insert(0,100,'X'));
129 con->write(string().insert(0,100,'Y'));
134 std::cerr << "exception in child. ignoring\n";
137 // don't call atexit and stuff
144 // don't kill us on broken pipe
145 signal(SIGPIPE, SIG_IGN);
147 // wait till server is up
149 socket_client_connection sc("./socket");
155 while (!sc.get_packet(data))
156 sc.fill_buffer(1000000);
162 while (!sc.get_packet(data))
163 sc.fill_buffer(1000000);
165 CPPUNIT_ASSERT_EQUAL(string().insert(0,100,'X'),data);
170 void reconnect_with_close()
172 switch(child_pid=fork())
176 CPPUNIT_FAIL("fork error");
184 socket_server ss("./socket");
186 time_t t0 = time(NULL);
189 while (time(NULL) < t0 + 10 )
191 ss.fill_buffer(1000000);
196 if(ss.get_packet(data,cid))
198 server_connection* con=ss.get_connection(cid);
204 con->write(string().insert(0,100,'X'));
206 con->write(string().insert(0,100,'Y'));
211 std::cerr << "exception in child. ignoring\n";
214 // don't call atexit and stuff
221 // don't kill us on broken pipe
222 signal(SIGPIPE, SIG_IGN);
224 // wait till server is up
226 socket_client_connection sc("./socket");
232 while (!sc.get_packet(data))
233 sc.fill_buffer(1000000);
244 while (!sc.get_packet(data))
245 sc.fill_buffer(1000000);
247 CPPUNIT_ASSERT_EQUAL(string().insert(0,100,'X'),data);
252 void reconnect_buffer_complete()
254 switch(child_pid=fork())
258 CPPUNIT_FAIL("fork error");
266 socket_server ss("./socket");
268 time_t t0 = time(NULL);
271 while (time(NULL) < t0 + 10 )
273 ss.fill_buffer(1000000);
278 if(ss.get_packet(data,cid))
280 server_connection* con=ss.get_connection(cid);
286 con->write(string().insert(0,100,'X'));
291 std::cerr << "exception in child. ignoring\n";
294 // don't call atexit and stuff
301 // don't kill us on broken pipe
302 signal(SIGPIPE, SIG_IGN);
304 // wait till server is up
306 socket_client_connection sc("./socket");
312 while (!sc.packet_available())
313 sc.fill_buffer(1000000);
317 CPPUNIT_ASSERT_EQUAL_MESSAGE("packet not there",true,sc.get_packet(data));
319 CPPUNIT_ASSERT_EQUAL_MESSAGE("data incorrect",string().insert(0,100,'X'),data);
324 void reconnect_buffer_several_complete()
328 switch(child_pid=fork())
332 CPPUNIT_FAIL("fork error");
340 socket_server ss("./socket");
342 time_t t0 = time(NULL);
345 while (time(NULL) < t0 + 10 )
347 ss.fill_buffer(1000000);
352 if(ss.get_packet(data,cid))
354 server_connection* con=ss.get_connection(cid);
361 for (int i=0; i<packets; i++)
362 con->write(string().insert(0,100,'X'));
368 std::cerr << "exception in child. ignoring\n";
371 // don't call atexit and stuff
378 // don't kill us on broken pipe
379 signal(SIGPIPE, SIG_IGN);
381 // wait till server is up
383 socket_client_connection sc("./socket");
387 // retrieve packets for 3 seconds
388 time_t t0 = time(NULL);
391 while (time(NULL) < t0 + 3 )
392 sc.fill_buffer(1000000);
394 // we now should have packets complete packets in the buffer
398 // are these packets still there?
400 for (int i=0; i < packets; i++)
405 os << "packet " << i << " not there";
407 CPPUNIT_ASSERT_EQUAL_MESSAGE(os.str(),true,sc.get_packet(data));
410 os << "packet " << i << " incorrect";
412 CPPUNIT_ASSERT_EQUAL_MESSAGE(os.str(),string().insert(0,100,'X'),data);
418 void reconnect_buffer_no_incomplete1()
420 switch(child_pid=fork())
424 CPPUNIT_FAIL("fork error");
432 socket_server ss("./socket");
434 time_t t0 = time(NULL);
437 while (time(NULL) < t0 + 10 )
439 ss.fill_buffer(1000000);
444 if(ss.get_packet(data,cid))
446 server_connection* con=ss.get_connection(cid);
453 con->write(string().insert(0,100,'X'));
454 send_raw_socket("aaaab",&ss,cid);
460 std::cerr << "exception in child. ignoring\n";
463 // don't call atexit and stuff
470 // don't kill us on broken pipe
471 signal(SIGPIPE, SIG_IGN);
473 // wait till server is up
475 socket_client_connection sc("./socket");
479 // retrieve packets for 3 seconds
480 time_t t0 = time(NULL);
483 while (time(NULL) < t0 + 3 )
484 sc.fill_buffer(1000000);
486 // we now should have one complete packet and some stuff in the buffer
491 CPPUNIT_ASSERT_EQUAL_MESSAGE("no incomplete packet",true,(sc.peek_packet(data))>0);
495 CPPUNIT_ASSERT_EQUAL_MESSAGE("incomplete packet not removed",0,(int)sc.peek_packet(data));
500 void reconnect_buffer_no_incomplete2()
502 switch(child_pid=fork())
506 CPPUNIT_FAIL("fork error");
514 socket_server ss("./socket");
516 time_t t0 = time(NULL);
519 while (time(NULL) < t0 + 10 )
521 ss.fill_buffer(1000000);
526 if(ss.get_packet(data,cid))
528 server_connection* con=ss.get_connection(cid);
535 con->write(string().insert(0,100,'X'));
537 string blob=string().insert(0,100,'Y');
539 // one byte will be missing...
540 int size=blob.size()+1;
541 char sizetransfer[sizeof(int)+1];
542 memcpy(sizetransfer,(void*)&size,sizeof(int));
543 sizetransfer[sizeof(int)+1]=0;
545 string packet=string(sizetransfer)+blob;
547 send_raw_socket(packet,&ss,cid);
553 std::cerr << "exception in child. ignoring\n";
556 // don't call atexit and stuff
563 // don't kill us on broken pipe
564 signal(SIGPIPE, SIG_IGN);
566 // wait till server is up
568 socket_client_connection sc("./socket");
572 // retrieve packets for 3 seconds
573 time_t t0 = time(NULL);
576 while (time(NULL) < t0 + 3 )
577 sc.fill_buffer(1000000);
579 // we now should have one complete packet and some stuff in the buffer
585 CPPUNIT_ASSERT_EQUAL_MESSAGE("packet not there",true,sc.get_packet(data));
586 CPPUNIT_ASSERT_EQUAL_MESSAGE("data incorrect",string().insert(0,100,'X'),data);
588 CPPUNIT_ASSERT_EQUAL_MESSAGE("incomplete packet not removed",0,(int)sc.peek_packet(data));
595 CPPUNIT_TEST_SUITE_REGISTRATION(test_reconnect);