libt2n: (gerd) finish server callbacks
[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(NewConnCallback);
37     CPPUNIT_TEST(ConnClosedCallback);
38     CPPUNIT_TEST(ConnDeletedCallback);
39     CPPUNIT_TEST(CallbackOrder);
40
41     CPPUNIT_TEST_SUITE_END();
42
43     std::vector<bool> callback_done;
44
45     public:
46
47     void setUp()
48     {
49         callback_done.resize(__events_end);
50     }
51
52     void tearDown()
53     {
54         callback_done.clear();
55     }
56
57     void callback_func(callback_event_type ev, int conn_id)
58     {
59         // we don't care for the conn_id, we just mark the callback as done
60         if (callback_done[ev])
61             throw runtime_error("callback already done for this event");
62
63         callback_done[ev]=true;
64     }
65
66     void NewConnCallback()
67     {
68         pid_t pid;
69
70         switch(pid=fork())
71         {
72             case -1:
73             {
74                 CPPUNIT_FAIL("fork error");
75                 break;
76             }
77             case 0:
78             // child
79             {
80                 string data;
81                 // wait till server is up
82                 sleep(1);
83
84                 {
85                     socket_client_connection sc("./socket");
86
87                     sc.write("ABC");
88
89                     // wait half a sec
90                     sc.fill_buffer(500000);
91                     sc.get_packet(data);
92
93                     // close the connection
94                 }
95
96                 // don't call atexit and stuff
97                 _exit(0);
98             }
99
100             default:
101             // parent
102             {
103                 socket_server ss("./socket");
104
105                 ss.add_callback(new_connection,bind(&test_callback::callback_func, boost::ref(*this), new_connection, _1));
106
107                 // max 3 sec
108                 for (int i=0; i < 3; i++)
109                 {
110                     ss.fill_buffer(1000000);
111
112                     string data;
113                     unsigned int cid;
114                     if(ss.get_packet(data,cid))
115                     {
116                         server_connection* con=ss.get_connection(cid);
117                         con->write("XYZ");
118                     }
119                 }
120                 CPPUNIT_ASSERT_EQUAL(true,static_cast<bool>(callback_done[new_connection]));
121                 CPPUNIT_ASSERT_EQUAL(false,static_cast<bool>(callback_done[connection_closed]));
122                 CPPUNIT_ASSERT_EQUAL(false,static_cast<bool>(callback_done[connection_deleted]));
123             }
124         }
125     }
126
127     void ConnClosedCallback()
128     {
129         pid_t pid;
130
131         switch(pid=fork())
132         {
133             case -1:
134             {
135                 CPPUNIT_FAIL("fork error");
136                 break;
137             }
138             case 0:
139             // child
140             {
141                 string data;
142                 // wait till server is up
143                 sleep(1);
144
145                 {
146                     socket_client_connection sc("./socket");
147
148                     sc.write("ABC");
149
150                     // wait half a sec
151                     sc.fill_buffer(500000);
152                     sc.get_packet(data);
153
154                     // close the connection
155                 }
156
157                 // don't call atexit and stuff
158                 _exit(0);
159             }
160
161             default:
162             // parent
163             {
164                 socket_server ss("./socket");
165
166                 ss.add_callback(connection_closed,bind(&test_callback::callback_func, boost::ref(*this), connection_closed, _1));
167
168                 // max 3 sec
169                 for (int i=0; i < 3; i++)
170                 {
171                     ss.fill_buffer(1000000);
172
173                     string data;
174                     unsigned int cid;
175                     if(ss.get_packet(data,cid))
176                     {
177                         server_connection* con=ss.get_connection(cid);
178                         con->write("XYZ");
179                     }
180                 }
181                 CPPUNIT_ASSERT_EQUAL(false,static_cast<bool>(callback_done[new_connection]));
182                 CPPUNIT_ASSERT_EQUAL(true,static_cast<bool>(callback_done[connection_closed]));
183                 CPPUNIT_ASSERT_EQUAL(false,static_cast<bool>(callback_done[connection_deleted]));
184             }
185         }
186     }
187
188     void ConnDeletedCallback()
189     {
190         pid_t pid;
191
192         switch(pid=fork())
193         {
194             case -1:
195             {
196                 CPPUNIT_FAIL("fork error");
197                 break;
198             }
199             case 0:
200             // child
201             {
202                 string data;
203                 // wait till server is up
204                 sleep(1);
205
206                 {
207                     socket_client_connection sc("./socket");
208
209                     sc.write("ABC");
210
211                     // wait half a sec
212                     sc.fill_buffer(500000);
213                     sc.get_packet(data);
214
215                     // close the connection
216                 }
217
218                 // don't call atexit and stuff
219                 _exit(0);
220             }
221
222             default:
223             // parent
224             {
225                 socket_server ss("./socket");
226
227                 ss.add_callback(connection_deleted,bind(&test_callback::callback_func, boost::ref(*this), connection_deleted, _1));
228
229                 // max 3 sec
230                 for (int i=0; i < 3; i++)
231                 {
232                     ss.fill_buffer(1000000);
233
234                     string data;
235                     unsigned int cid;
236                     if(ss.get_packet(data,cid))
237                     {
238                         server_connection* con=ss.get_connection(cid);
239                         con->write("XYZ");
240                     }
241                     ss.cleanup();
242                 }
243                 ss.cleanup();
244
245                 CPPUNIT_ASSERT_EQUAL(false,static_cast<bool>(callback_done[new_connection]));
246                 CPPUNIT_ASSERT_EQUAL(false,static_cast<bool>(callback_done[connection_closed]));
247                 CPPUNIT_ASSERT_EQUAL(true,static_cast<bool>(callback_done[connection_deleted]));
248             }
249         }
250     }
251
252     void CallbackOrder()
253     {
254         pid_t pid;
255
256         switch(pid=fork())
257         {
258             case -1:
259             {
260                 CPPUNIT_FAIL("fork error");
261                 break;
262             }
263             case 0:
264             // child
265             {
266                 string data;
267                 // wait till server is up
268                 sleep(1);
269
270                 {
271                     socket_client_connection sc("./socket");
272
273                     sc.write("1");
274
275                     // wait half a sec
276                     sc.fill_buffer(500000);
277                     sc.get_packet(data);
278
279                     sc.write("2");
280
281                     // close the connection
282                 }
283
284                 // don't call atexit and stuff
285                 _exit(0);
286             }
287
288             default:
289             // parent
290             {
291                 socket_server ss("./socket");
292
293                 ss.add_callback(connection_closed,bind(&test_callback::callback_func, boost::ref(*this), connection_closed, _1));
294                 ss.add_callback(connection_deleted,bind(&test_callback::callback_func, boost::ref(*this), connection_deleted, _1));
295
296                 bool got_1=false;
297
298                 for (int i=0; i < 4; i++)
299                 {
300                     ss.fill_buffer(500000);
301
302                     string data;
303                     unsigned int cid;
304                     if(!got_1 && ss.get_packet(data,cid))
305                     {
306                         server_connection* con=ss.get_connection(cid);
307                         con->write("XYZ");
308                         got_1=true;
309                         // don't call get_packet anymore
310                     }
311                     ss.cleanup();
312                 }
313                 ss.cleanup();
314
315                 CPPUNIT_ASSERT_EQUAL(true,static_cast<bool>(callback_done[connection_closed]));
316                 CPPUNIT_ASSERT_EQUAL(false,static_cast<bool>(callback_done[connection_deleted]));
317
318                 for (int i=0; i < 4; i++)
319                 {
320                     ss.fill_buffer(500000);
321
322                     string data;
323                     unsigned int cid;
324                     ss.get_packet(data,cid);
325                     ss.cleanup();
326                 }
327                 ss.cleanup();
328
329                 CPPUNIT_ASSERT_EQUAL(true,static_cast<bool>(callback_done[connection_closed]));
330                 CPPUNIT_ASSERT_EQUAL(true,static_cast<bool>(callback_done[connection_deleted]));
331             }
332         }
333     }
334
335 };
336
337 CPPUNIT_TEST_SUITE_REGISTRATION(test_callback);