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