Changed one more homepage link
[libt2n] / test / hello.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
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
33 using namespace std;
34 using namespace libt2n;
35 using namespace CppUnit;
36
37 // this is an evil hack to get access to real_write, don't ever do this in an app!!!
38 class real_write_connection: public socket_server_connection
39 {
40     public:
41         void real_write(const std::string& data)
42             { socket_write(data); }
43 };
44
45 class 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);
54     CPPUNIT_TEST(OtherServerBig);
55     CPPUNIT_TEST(OtherServerSmall);
56
57     CPPUNIT_TEST_SUITE_END();
58
59     pid_t child_pid;
60
61     public:
62
63     void setUp()
64     { }
65
66     void tearDown()
67     {
68         // make sure the server-child is dead before the next test runs
69         kill(child_pid,SIGKILL);
70         sleep(1);
71     }
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     {
90         switch(child_pid=fork())
91         {
92             case -1:
93             {
94                 CPPUNIT_FAIL("fork error");
95                 break;
96             }
97             case 0:
98             // child
99             {
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                 }
119
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");
132                 command_client cc(&sc);
133             }
134         }
135     }
136
137     void BadTag()
138     {
139         switch(child_pid=fork())
140         {
141             case -1:
142             {
143                 CPPUNIT_FAIL("fork error");
144                 break;
145             }
146             case 0:
147             // child
148             {
149                 try
150                 {
151                     socket_server ss("./socket");
152
153                     ostringstream hello;
154                     hello << "XYZ 123";
155
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                 }
165
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
179                 command_client cc(&sc);
180
181                 t2n_exception* ep=cc.get_constuctor_exception();
182
183                 string errormsg;
184                 if (ep)
185                     errormsg=ep->what();
186
187                 CPPUNIT_ASSERT_EQUAL(string("illegal hello received (T2N)"),errormsg);
188             }
189         }
190     }
191
192     void BadVersion()
193     {
194         switch(child_pid=fork())
195         {
196             case -1:
197             {
198                 CPPUNIT_FAIL("fork error");
199                 break;
200             }
201             case 0:
202             // child
203             {
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                 }
224
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
238                 command_client cc(&sc);
239
240                 t2n_exception* ep=cc.get_constuctor_exception();
241
242                 string errormsg;
243                 if (ep)
244                     errormsg=ep->what();
245
246                 CPPUNIT_ASSERT_EQUAL(string("not compatible with the server protocol version"),errormsg);
247             }
248         }
249     }
250
251     void SeparatorMissing()
252     {
253         switch(child_pid=fork())
254         {
255             case -1:
256             {
257                 CPPUNIT_FAIL("fork error");
258                 break;
259             }
260             case 0:
261             // child
262             {
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                 }
282
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
296                 command_client cc(&sc);
297
298                 t2n_exception* ep=cc.get_constuctor_exception();
299
300                 string errormsg;
301                 if (ep)
302                     errormsg=ep->what();
303
304                 CPPUNIT_ASSERT_EQUAL(string("illegal hello received (1. ;)"),errormsg);
305             }
306         }
307     }
308
309     void WrongByteOrder()
310     {
311         switch(child_pid=fork())
312         {
313             case -1:
314             {
315                 CPPUNIT_FAIL("fork error");
316                 break;
317             }
318             case 0:
319             // child
320             {
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                 }
349
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
363                 command_client cc(&sc);
364
365                 t2n_exception* ep=cc.get_constuctor_exception();
366
367                 string errormsg;
368                 if (ep)
369                     errormsg=ep->what();
370
371                 CPPUNIT_ASSERT_EQUAL(string("host byte order not matching"),errormsg);
372             }
373         }
374     }
375
376     void OtherServerBig()
377     {
378         switch(child_pid=fork())
379         {
380             case -1:
381             {
382                 CPPUNIT_FAIL("fork error");
383                 break;
384             }
385             case 0:
386             // child
387             {
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";
395
396                     ss.add_callback(new_connection,bind(&test_hello::send_raw_socket, boost::ref(*this), hello.str(),&ss, _1));
397
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                 }
405
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
419                 command_client cc(&sc);
420
421                 t2n_exception* ep=cc.get_constuctor_exception();
422
423                 string errormsg;
424                 if (ep)
425                     errormsg=ep->what();
426
427                 CPPUNIT_ASSERT_EQUAL(string("illegal hello received (T2N)"),errormsg);
428             }
429         }
430     }
431
432     void OtherServerSmall()
433     {
434         switch(child_pid=fork())
435         {
436             case -1:
437             {
438                 CPPUNIT_FAIL("fork error");
439                 break;
440             }
441             case 0:
442             // child
443             {
444                 try
445                 {
446                     socket_server ss("./socket");
447
448                     ostringstream hello;
449                     // hmm, we got the wrong socket
450                     hello << "READY";
451
452                     ss.add_callback(new_connection,bind(&test_hello::send_raw_socket, boost::ref(*this), hello.str(),&ss, _1));
453
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                 }
461
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
475                 command_client cc(&sc);
476
477                 t2n_exception* ep=cc.get_constuctor_exception();
478
479                 string errormsg;
480                 if (ep)
481                     errormsg=ep->what();
482
483                 CPPUNIT_ASSERT_EQUAL(string("illegal hello received (T2N)"),errormsg);
484             }
485         }
486     }
487
488 };
489
490 CPPUNIT_TEST_SUITE_REGISTRATION(test_hello);