libt2n: (tomj) added exception handling to every child after fork(). This is needed...
[libt2n] / test / hello.cpp
CommitLineData
04d86ba4
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
18#include <boost/bind.hpp>
19
20#include <cppunit/extensions/TestFactoryRegistry.h>
21#include <cppunit/ui/text/TestRunner.h>
22#include <cppunit/extensions/HelperMacros.h>
23
24#include <t2n_exception.hxx>
25#include <socket_client.hxx>
26#include <socket_server.hxx>
27#include <command_client.hxx>
28
29#ifdef HAVE_CONFIG_H
30#include <config.h>
31#endif
32
33using namespace std;
34using namespace libt2n;
35using namespace CppUnit;
36
37// this is an evil hack to get access to real_write, don't ever do this in an app!!!
38class real_write_connection: public socket_server_connection
39{
40 public:
41 void real_write(const std::string& data)
42 { socket_write(data); }
43};
44
45class test_hello : public TestFixture
46{
47 CPPUNIT_TEST_SUITE(test_hello);
48
49 CPPUNIT_TEST(HelloOk);
50 CPPUNIT_TEST(BadTag);
51 CPPUNIT_TEST(BadVersion);
52 CPPUNIT_TEST(SeparatorMissing);
53 CPPUNIT_TEST(WrongByteOrder);
b604df5f
GE
54 CPPUNIT_TEST(OtherServerBig);
55 CPPUNIT_TEST(OtherServerSmall);
04d86ba4
GE
56
57 CPPUNIT_TEST_SUITE_END();
58
b5922184
GE
59 pid_t child_pid;
60
04d86ba4
GE
61 public:
62
63 void setUp()
64 { }
65
66 void tearDown()
b5922184
GE
67 {
68 // make sure the server-child is dead before the next test runs
69 kill(child_pid,SIGKILL);
70 sleep(1);
71 }
04d86ba4
GE
72
73 void send_hello(string hello_string, socket_server* ss, int conn_id)
74 {
75 server_connection *sc=ss->get_connection(conn_id);
76 sc->write(hello_string);
77 }
78
79 void send_raw_socket(string hello_string, socket_server* ss, int conn_id)
80 {
81 socket_server_connection *ssc=dynamic_cast<socket_server_connection*>(ss->get_connection(conn_id));
82
83 // this is an evil hack to get access to real_write, don't ever do this in an app!!!
84 real_write_connection *rwc=(real_write_connection*)ssc;
85 rwc->real_write(hello_string);
86 }
87
88 void HelloOk()
89 {
b5922184 90 switch(child_pid=fork())
04d86ba4
GE
91 {
92 case -1:
93 {
94 CPPUNIT_FAIL("fork error");
95 break;
96 }
97 case 0:
98 // child
99 {
441d41fe
TJ
100 try
101 {
102 socket_server ss("./socket");
103
104 ostringstream hello;
105 hello << "T2Nv" << PROTOCOL_VERSION << ';';
106 int byteordercheck=1;
107 hello.write((char*)&byteordercheck,sizeof(byteordercheck));
108 hello << ';';
109
110 ss.add_callback(new_connection,bind(&test_hello::send_hello, boost::ref(*this), hello.str(),&ss, _1));
111
112 // max 10 sec
113 for (int i=0; i < 10; i++)
114 ss.fill_buffer(1000000);
115 } catch(...)
116 {
117 std::cerr << "exception in child. ignoring\n";
118 }
04d86ba4 119
04d86ba4
GE
120 // don't call atexit and stuff
121 _exit(0);
122 }
123
124 default:
125 // parent
126 {
127 string data;
128
129 // wait till server is up
130 sleep(1);
131 socket_client_connection sc("./socket");
fb3345ad 132 command_client cc(&sc);
04d86ba4
GE
133 }
134 }
135 }
136
137 void BadTag()
138 {
b5922184 139 switch(child_pid=fork())
04d86ba4
GE
140 {
141 case -1:
142 {
143 CPPUNIT_FAIL("fork error");
144 break;
145 }
146 case 0:
147 // child
148 {
441d41fe
TJ
149 try
150 {
151 socket_server ss("./socket");
04d86ba4 152
441d41fe
TJ
153 ostringstream hello;
154 hello << "XYZ 123";
04d86ba4 155
441d41fe
TJ
156 ss.add_callback(new_connection,bind(&test_hello::send_hello, boost::ref(*this), hello.str(),&ss, _1));
157
158 // max 10 sec
159 for (int i=0; i < 10; i++)
160 ss.fill_buffer(1000000);
161 } catch(...)
162 {
163 std::cerr << "exception in child. ignoring\n";
164 }
04d86ba4 165
04d86ba4
GE
166 // don't call atexit and stuff
167 _exit(0);
168 }
169
170 default:
171 // parent
172 {
173 string data;
174
175 // wait till server is up
176 sleep(1);
177 socket_client_connection sc("./socket");
178
b5922184
GE
179 command_client cc(&sc);
180
181 t2n_exception* ep=cc.get_constuctor_exception();
04d86ba4 182
b5922184
GE
183 string errormsg;
184 if (ep)
185 errormsg=ep->what();
04d86ba4
GE
186
187 CPPUNIT_ASSERT_EQUAL(string("illegal hello received (T2N)"),errormsg);
188 }
189 }
190 }
191
192 void BadVersion()
193 {
b5922184 194 switch(child_pid=fork())
04d86ba4
GE
195 {
196 case -1:
197 {
198 CPPUNIT_FAIL("fork error");
199 break;
200 }
201 case 0:
202 // child
203 {
441d41fe
TJ
204 try
205 {
206 socket_server ss("./socket");
207
208 ostringstream hello;
209 // lets hope we don't ever get near such a version number...
210 hello << "T2Nv" << 4982271 << ';';
211 int byteordercheck=1;
212 hello.write((char*)&byteordercheck,sizeof(byteordercheck));
213 hello << ';';
214
215 ss.add_callback(new_connection,bind(&test_hello::send_hello, boost::ref(*this), hello.str(),&ss, _1));
216
217 // max 10 sec
218 for (int i=0; i < 10; i++)
219 ss.fill_buffer(1000000);
220 } catch(...)
221 {
222 std::cerr << "exception in child. ignoring\n";
223 }
04d86ba4 224
04d86ba4
GE
225 // don't call atexit and stuff
226 _exit(0);
227 }
228
229 default:
230 // parent
231 {
232 string data;
233
234 // wait till server is up
235 sleep(1);
236 socket_client_connection sc("./socket");
237
b5922184 238 command_client cc(&sc);
04d86ba4 239
b5922184
GE
240 t2n_exception* ep=cc.get_constuctor_exception();
241
242 string errormsg;
243 if (ep)
244 errormsg=ep->what();
04d86ba4
GE
245
246 CPPUNIT_ASSERT_EQUAL(string("not compatible with the server protocol version"),errormsg);
247 }
248 }
249 }
250
251 void SeparatorMissing()
252 {
b5922184 253 switch(child_pid=fork())
04d86ba4
GE
254 {
255 case -1:
256 {
257 CPPUNIT_FAIL("fork error");
258 break;
259 }
260 case 0:
261 // child
262 {
441d41fe
TJ
263 try
264 {
265 socket_server ss("./socket");
266
267 ostringstream hello;
268 hello << "T2Nv" << PROTOCOL_VERSION;
269 int byteordercheck=1;
270 hello.write((char*)&byteordercheck,sizeof(byteordercheck));
271 hello << ';';
272
273 ss.add_callback(new_connection,bind(&test_hello::send_hello, boost::ref(*this), hello.str(),&ss, _1));
274
275 // max 10 sec
276 for (int i=0; i < 10; i++)
277 ss.fill_buffer(1000000);
278 } catch(...)
279 {
280 std::cerr << "exception in child. ignoring\n";
281 }
04d86ba4 282
04d86ba4
GE
283 // don't call atexit and stuff
284 _exit(0);
285 }
286
287 default:
288 // parent
289 {
290 string data;
291
292 // wait till server is up
293 sleep(1);
294 socket_client_connection sc("./socket");
295
b5922184 296 command_client cc(&sc);
04d86ba4 297
b5922184
GE
298 t2n_exception* ep=cc.get_constuctor_exception();
299
300 string errormsg;
301 if (ep)
302 errormsg=ep->what();
04d86ba4
GE
303
304 CPPUNIT_ASSERT_EQUAL(string("illegal hello received (1. ;)"),errormsg);
305 }
306 }
307 }
308
309 void WrongByteOrder()
310 {
b5922184 311 switch(child_pid=fork())
04d86ba4
GE
312 {
313 case -1:
314 {
315 CPPUNIT_FAIL("fork error");
316 break;
317 }
318 case 0:
319 // child
320 {
441d41fe
TJ
321 try
322 {
323 socket_server ss("./socket");
324
325 ostringstream hello;
326 hello << "T2Nv" << PROTOCOL_VERSION << ';';
327 int byteordercheck=1;
328 int dst;
329 char* si=(char*)&byteordercheck;
330 char* di=(char*)&dst;
331
332 di[0]=si[3];
333 di[1]=si[2];
334 di[2]=si[1];
335 di[3]=si[0];
336
337 hello.write((char*)&dst,sizeof(dst));
338 hello << ';';
339
340 ss.add_callback(new_connection,bind(&test_hello::send_hello, boost::ref(*this), hello.str(),&ss, _1));
341
342 // max 10 sec
343 for (int i=0; i < 10; i++)
344 ss.fill_buffer(1000000);
345 } catch(...)
346 {
347 std::cerr << "exception in child. ignoring\n";
348 }
04d86ba4 349
04d86ba4
GE
350 // don't call atexit and stuff
351 _exit(0);
352 }
353
354 default:
355 // parent
356 {
357 string data;
358
359 // wait till server is up
360 sleep(1);
361 socket_client_connection sc("./socket");
362
b5922184 363 command_client cc(&sc);
04d86ba4 364
b5922184
GE
365 t2n_exception* ep=cc.get_constuctor_exception();
366
367 string errormsg;
368 if (ep)
369 errormsg=ep->what();
04d86ba4
GE
370
371 CPPUNIT_ASSERT_EQUAL(string("host byte order not matching"),errormsg);
372 }
373 }
374 }
375
b604df5f 376 void OtherServerBig()
04d86ba4 377 {
b5922184 378 switch(child_pid=fork())
04d86ba4
GE
379 {
380 case -1:
381 {
382 CPPUNIT_FAIL("fork error");
383 break;
384 }
385 case 0:
386 // child
387 {
441d41fe
TJ
388 try
389 {
390 socket_server ss("./socket");
391
392 ostringstream hello;
393 // hmm, we got the wrong socket
394 hello << "* OK intradev.net.lan Cyrus IMAP4 v2.2.13 server ready";
04d86ba4 395
441d41fe 396 ss.add_callback(new_connection,bind(&test_hello::send_raw_socket, boost::ref(*this), hello.str(),&ss, _1));
04d86ba4 397
441d41fe
TJ
398 // max 3 sec
399 for (int i=0; i < 3; i++)
400 ss.fill_buffer(1000000);
401 } catch(...)
402 {
403 std::cerr << "exception in child. ignoring\n";
404 }
04d86ba4 405
04d86ba4
GE
406 // don't call atexit and stuff
407 _exit(0);
408 }
409
410 default:
411 // parent
412 {
413 string data;
414
415 // wait till server is up
416 sleep(1);
417 socket_client_connection sc("./socket");
418
b5922184
GE
419 command_client cc(&sc);
420
421 t2n_exception* ep=cc.get_constuctor_exception();
04d86ba4 422
b5922184
GE
423 string errormsg;
424 if (ep)
425 errormsg=ep->what();
04d86ba4
GE
426
427 CPPUNIT_ASSERT_EQUAL(string("illegal hello received (T2N)"),errormsg);
428 }
429 }
430 }
431
b604df5f
GE
432 void OtherServerSmall()
433 {
b5922184 434 switch(child_pid=fork())
b604df5f
GE
435 {
436 case -1:
437 {
438 CPPUNIT_FAIL("fork error");
439 break;
440 }
441 case 0:
442 // child
443 {
441d41fe
TJ
444 try
445 {
446 socket_server ss("./socket");
447
448 ostringstream hello;
449 // hmm, we got the wrong socket
450 hello << "READY";
b604df5f 451
441d41fe 452 ss.add_callback(new_connection,bind(&test_hello::send_raw_socket, boost::ref(*this), hello.str(),&ss, _1));
b604df5f 453
441d41fe
TJ
454 // max 3 sec
455 for (int i=0; i < 3; i++)
456 ss.fill_buffer(1000000);
457 } catch(...)
458 {
459 std::cerr << "exception in child. ignoring\n";
460 }
b604df5f 461
b604df5f
GE
462 // don't call atexit and stuff
463 _exit(0);
464 }
465
466 default:
467 // parent
468 {
469 string data;
470
471 // wait till server is up
472 sleep(1);
473 socket_client_connection sc("./socket");
474
b5922184 475 command_client cc(&sc);
b604df5f 476
b5922184
GE
477 t2n_exception* ep=cc.get_constuctor_exception();
478
479 string errormsg;
480 if (ep)
481 errormsg=ep->what();
b604df5f
GE
482
483 CPPUNIT_ASSERT_EQUAL(string("illegal hello received (T2N)"),errormsg);
484 }
485 }
486 }
487
04d86ba4
GE
488};
489
490CPPUNIT_TEST_SUITE_REGISTRATION(test_hello);