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