docu
[libt2n] / test / callback.cpp
1 /***************************************************************************
2  *   Copyright (C) 2004 by Intra2net AG                                    *
3  *   info@intra2net.com                                                    *
4  *                                                                         *
5  ***************************************************************************/
6
7 #include <sys/types.h>
8 #include <unistd.h>
9 #include <errno.h>
10 #include <signal.h>
11 #include <stdio.h>
12
13 #include <iostream>
14 #include <string>
15 #include <sstream>
16 #include <stdexcept>
17 #include <vector>
18
19 #include <boost/bind.hpp>
20
21 #include <cppunit/extensions/TestFactoryRegistry.h>
22 #include <cppunit/ui/text/TestRunner.h>
23 #include <cppunit/extensions/HelperMacros.h>
24
25 #include <socket_client.hxx>
26 #include <socket_server.hxx>
27
28 using namespace std;
29 using namespace libt2n;
30 using namespace CppUnit;
31
32 class test_callback : public TestFixture
33 {
34     CPPUNIT_TEST_SUITE(test_callback);
35
36     CPPUNIT_TEST(ServerNewConnCallback);
37     CPPUNIT_TEST(ServerConnClosedCallback);
38     CPPUNIT_TEST(ServerConnDeletedCallback);
39     CPPUNIT_TEST(ServerCallbackOrder);
40     CPPUNIT_TEST(ClientConnClosedCallback);
41     CPPUNIT_TEST(ClientConnDeletedCallback);
42
43     CPPUNIT_TEST_SUITE_END();
44
45     std::vector<bool> callback_done;
46
47     public:
48
49     void setUp()
50     {
51         callback_done.resize(__events_end);
52     }
53
54     void tearDown()
55     {
56         callback_done.clear();
57     }
58
59     void callback_func(callback_event_type ev, int conn_id)
60     {
61         // we don't care for the conn_id, we just mark the callback as done
62         if (callback_done[ev])
63             throw runtime_error("callback already done for this event");
64
65         callback_done[ev]=true;
66     }
67
68     void ServerNewConnCallback()
69     {
70         pid_t pid;
71
72         switch(pid=fork())
73         {
74             case -1:
75             {
76                 CPPUNIT_FAIL("fork error");
77                 break;
78             }
79             case 0:
80             // child
81             {
82                 string data;
83                 // wait till server is up
84                 sleep(1);
85
86                 {
87                     socket_client_connection sc("./socket");
88
89                     sc.write("ABC");
90
91                     // wait half a sec
92                     sc.fill_buffer(500000);
93                     sc.get_packet(data);
94
95                     // close the connection
96                 }
97
98                 // don't call atexit and stuff
99                 _exit(0);
100             }
101
102             default:
103             // parent
104             {
105                 socket_server ss("./socket");
106
107                 ss.add_callback(new_connection,bind(&test_callback::callback_func, boost::ref(*this), new_connection, _1));
108
109                 // max 3 sec
110                 for (int i=0; i < 3; i++)
111                 {
112                     ss.fill_buffer(1000000);
113
114                     string data;
115                     unsigned int cid;
116                     if(ss.get_packet(data,cid))
117                     {
118                         server_connection* con=ss.get_connection(cid);
119                         con->write("XYZ");
120                     }
121                 }
122                 CPPUNIT_ASSERT_EQUAL(true,static_cast<bool>(callback_done[new_connection]));
123                 CPPUNIT_ASSERT_EQUAL(false,static_cast<bool>(callback_done[connection_closed]));
124                 CPPUNIT_ASSERT_EQUAL(false,static_cast<bool>(callback_done[connection_deleted]));
125             }
126         }
127     }
128
129     void ServerConnClosedCallback()
130     {
131         pid_t pid;
132
133         switch(pid=fork())
134         {
135             case -1:
136             {
137                 CPPUNIT_FAIL("fork error");
138                 break;
139             }
140             case 0:
141             // child
142             {
143                 string data;
144                 // wait till server is up
145                 sleep(1);
146
147                 {
148                     socket_client_connection sc("./socket");
149
150                     sc.write("ABC");
151
152                     // wait half a sec
153                     sc.fill_buffer(500000);
154                     sc.get_packet(data);
155
156                     // close the connection
157                 }
158
159                 // don't call atexit and stuff
160                 _exit(0);
161             }
162
163             default:
164             // parent
165             {
166                 socket_server ss("./socket");
167
168                 ss.add_callback(connection_closed,bind(&test_callback::callback_func, boost::ref(*this), connection_closed, _1));
169
170                 // max 3 sec
171                 for (int i=0; i < 3; i++)
172                 {
173                     ss.fill_buffer(1000000);
174
175                     string data;
176                     unsigned int cid;
177                     if(ss.get_packet(data,cid))
178                     {
179                         server_connection* con=ss.get_connection(cid);
180                         con->write("XYZ");
181                     }
182                 }
183                 CPPUNIT_ASSERT_EQUAL(false,static_cast<bool>(callback_done[new_connection]));
184                 CPPUNIT_ASSERT_EQUAL(true,static_cast<bool>(callback_done[connection_closed]));
185                 CPPUNIT_ASSERT_EQUAL(false,static_cast<bool>(callback_done[connection_deleted]));
186             }
187         }
188     }
189
190     void ServerConnDeletedCallback()
191     {
192         pid_t pid;
193
194         switch(pid=fork())
195         {
196             case -1:
197             {
198                 CPPUNIT_FAIL("fork error");
199                 break;
200             }
201             case 0:
202             // child
203             {
204                 string data;
205                 // wait till server is up
206                 sleep(1);
207
208                 {
209                     socket_client_connection sc("./socket");
210
211                     sc.write("ABC");
212
213                     // wait half a sec
214                     sc.fill_buffer(500000);
215                     sc.get_packet(data);
216
217                     // close the connection
218                 }
219
220                 // don't call atexit and stuff
221                 _exit(0);
222             }
223
224             default:
225             // parent
226             {
227                 socket_server ss("./socket");
228
229                 ss.add_callback(connection_deleted,bind(&test_callback::callback_func, boost::ref(*this), connection_deleted, _1));
230
231                 // max 3 sec
232                 for (int i=0; i < 3; i++)
233                 {
234                     ss.fill_buffer(1000000);
235
236                     string data;
237                     unsigned int cid;
238                     if(ss.get_packet(data,cid))
239                     {
240                         server_connection* con=ss.get_connection(cid);
241                         con->write("XYZ");
242                     }
243                     ss.cleanup();
244                 }
245                 ss.cleanup();
246
247                 CPPUNIT_ASSERT_EQUAL(false,static_cast<bool>(callback_done[new_connection]));
248                 CPPUNIT_ASSERT_EQUAL(false,static_cast<bool>(callback_done[connection_closed]));
249                 CPPUNIT_ASSERT_EQUAL(true,static_cast<bool>(callback_done[connection_deleted]));
250             }
251         }
252     }
253
254     void ServerCallbackOrder()
255     {
256         pid_t pid;
257
258         switch(pid=fork())
259         {
260             case -1:
261             {
262                 CPPUNIT_FAIL("fork error");
263                 break;
264             }
265             case 0:
266             // child
267             {
268                 string data;
269                 // wait till server is up
270                 sleep(1);
271
272                 {
273                     socket_client_connection sc("./socket");
274
275                     sc.write("1");
276
277                     // wait half a sec
278                     sc.fill_buffer(500000);
279                     sc.get_packet(data);
280
281                     sc.write("2");
282
283                     // close the connection
284                 }
285
286                 // don't call atexit and stuff
287                 _exit(0);
288             }
289
290             default:
291             // parent
292             {
293                 socket_server ss("./socket");
294
295                 ss.add_callback(connection_closed,bind(&test_callback::callback_func, boost::ref(*this), connection_closed, _1));
296                 ss.add_callback(connection_deleted,bind(&test_callback::callback_func, boost::ref(*this), connection_deleted, _1));
297
298                 bool got_1=false;
299
300                 for (int i=0; i < 4; i++)
301                 {
302                     ss.fill_buffer(500000);
303
304                     string data;
305                     unsigned int cid;
306                     if(!got_1 && ss.get_packet(data,cid))
307                     {
308                         server_connection* con=ss.get_connection(cid);
309                         con->write("XYZ");
310                         got_1=true;
311                         // don't call get_packet anymore
312                     }
313                     ss.cleanup();
314                 }
315                 ss.cleanup();
316
317                 CPPUNIT_ASSERT_EQUAL(true,static_cast<bool>(callback_done[connection_closed]));
318                 CPPUNIT_ASSERT_EQUAL(false,static_cast<bool>(callback_done[connection_deleted]));
319
320                 for (int i=0; i < 4; i++)
321                 {
322                     ss.fill_buffer(500000);
323
324                     string data;
325                     unsigned int cid;
326                     ss.get_packet(data,cid);
327                     ss.cleanup();
328                 }
329                 ss.cleanup();
330
331                 CPPUNIT_ASSERT_EQUAL(true,static_cast<bool>(callback_done[connection_closed]));
332                 CPPUNIT_ASSERT_EQUAL(true,static_cast<bool>(callback_done[connection_deleted]));
333             }
334         }
335     }
336
337     void ClientConnClosedCallback()
338     {
339         pid_t pid;
340
341         switch(pid=fork())
342         {
343             case -1:
344             {
345                 CPPUNIT_FAIL("fork error");
346                 break;
347             }
348             case 0:
349             // child
350             {
351                 socket_server ss("./socket");
352
353                 // max 3 sec
354                 for (int i=0; i < 3; i++)
355                 {
356                     ss.fill_buffer(1000000);
357
358                     string data;
359                     unsigned int cid;
360                     if(ss.get_packet(data,cid))
361                         break;
362                 }
363                 // don't call atexit and stuff
364                 _exit(0);
365             }
366
367             default:
368             // parent
369             {
370                 string data;
371                 // wait till server is up
372                 sleep(1);
373
374                 socket_client_connection sc("./socket");
375
376                 sc.add_callback(connection_closed,bind(&test_callback::callback_func, boost::ref(*this), connection_closed, 0));
377
378                 sc.write("ABC");
379
380                 // wait half a sec
381                 sc.fill_buffer(500000);
382                 sc.get_packet(data);
383
384                 CPPUNIT_ASSERT_EQUAL(false,static_cast<bool>(callback_done[new_connection]));
385                 CPPUNIT_ASSERT_EQUAL(true,static_cast<bool>(callback_done[connection_closed]));
386                 CPPUNIT_ASSERT_EQUAL(false,static_cast<bool>(callback_done[connection_deleted]));
387             }
388         }
389     }
390
391     void ClientConnDeletedCallback()
392     {
393         pid_t pid;
394
395         switch(pid=fork())
396         {
397             case -1:
398             {
399                 CPPUNIT_FAIL("fork error");
400                 break;
401             }
402             case 0:
403             // child
404             {
405                 socket_server ss("./socket");
406
407                 // max 3 sec
408                 for (int i=0; i < 3; i++)
409                 {
410                     ss.fill_buffer(1000000);
411
412                     string data;
413                     unsigned int cid;
414                     if(ss.get_packet(data,cid))
415                         break;
416                 }
417                 // don't call atexit and stuff
418                 _exit(0);
419             }
420
421             default:
422             // parent
423             {
424                 string data;
425                 // wait till server is up
426                 sleep(1);
427
428                 {
429                     socket_client_connection sc("./socket");
430
431                     sc.add_callback(connection_deleted,bind(&test_callback::callback_func, boost::ref(*this), connection_deleted, 0));
432
433                     sc.write("ABC");
434
435                     // wait half a sec
436                     sc.fill_buffer(500000);
437                     sc.get_packet(data);
438                 }
439
440                 CPPUNIT_ASSERT_EQUAL(false,static_cast<bool>(callback_done[new_connection]));
441                 CPPUNIT_ASSERT_EQUAL(false,static_cast<bool>(callback_done[connection_closed]));
442                 CPPUNIT_ASSERT_EQUAL(true,static_cast<bool>(callback_done[connection_deleted]));
443             }
444         }
445     }
446 };
447
448 CPPUNIT_TEST_SUITE_REGISTRATION(test_callback);