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