1036e30908748276b947c5b0edbc83289090e652
[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                 socket_server ss("./socket");
101
102                 ostringstream hello;
103                 hello << "T2Nv" << PROTOCOL_VERSION << ';';
104                 int byteordercheck=1;
105                 hello.write((char*)&byteordercheck,sizeof(byteordercheck));
106                 hello << ';';
107
108                 ss.add_callback(new_connection,bind(&test_hello::send_hello, boost::ref(*this), hello.str(),&ss, _1));
109
110                 // max 10 sec
111                 for (int i=0; i < 10; i++)
112                     ss.fill_buffer(1000000);
113                 // don't call atexit and stuff
114                 _exit(0);
115             }
116
117             default:
118             // parent
119             {
120                 string data;
121
122                 // wait till server is up
123                 sleep(1);
124                 socket_client_connection sc("./socket");
125                 command_client cc(&sc);
126             }
127         }
128     }
129
130     void BadTag()
131     {
132         switch(child_pid=fork())
133         {
134             case -1:
135             {
136                 CPPUNIT_FAIL("fork error");
137                 break;
138             }
139             case 0:
140             // child
141             {
142                 socket_server ss("./socket");
143
144                 ostringstream hello;
145                 hello << "XYZ 123";
146
147                 ss.add_callback(new_connection,bind(&test_hello::send_hello, boost::ref(*this), hello.str(),&ss, _1));
148
149                 // max 10 sec
150                 for (int i=0; i < 10; i++)
151                     ss.fill_buffer(1000000);
152                 // don't call atexit and stuff
153                 _exit(0);
154             }
155
156             default:
157             // parent
158             {
159                 string data;
160
161                 // wait till server is up
162                 sleep(1);
163                 socket_client_connection sc("./socket");
164
165                 command_client cc(&sc);
166
167                 t2n_exception* ep=cc.get_constuctor_exception();
168
169                 string errormsg;
170                 if (ep)
171                     errormsg=ep->what();
172
173                 CPPUNIT_ASSERT_EQUAL(string("illegal hello received (T2N)"),errormsg);
174             }
175         }
176     }
177
178     void BadVersion()
179     {
180         switch(child_pid=fork())
181         {
182             case -1:
183             {
184                 CPPUNIT_FAIL("fork error");
185                 break;
186             }
187             case 0:
188             // child
189             {
190                 socket_server ss("./socket");
191
192                 ostringstream hello;
193                 // lets hope we don't ever get near such a version number...
194                 hello << "T2Nv" << 4982271 << ';';
195                 int byteordercheck=1;
196                 hello.write((char*)&byteordercheck,sizeof(byteordercheck));
197                 hello << ';';
198
199                 ss.add_callback(new_connection,bind(&test_hello::send_hello, boost::ref(*this), hello.str(),&ss, _1));
200
201                 // max 10 sec
202                 for (int i=0; i < 10; i++)
203                     ss.fill_buffer(1000000);
204                 // don't call atexit and stuff
205                 _exit(0);
206             }
207
208             default:
209             // parent
210             {
211                 string data;
212
213                 // wait till server is up
214                 sleep(1);
215                 socket_client_connection sc("./socket");
216
217                 command_client cc(&sc);
218
219                 t2n_exception* ep=cc.get_constuctor_exception();
220
221                 string errormsg;
222                 if (ep)
223                     errormsg=ep->what();
224
225                 CPPUNIT_ASSERT_EQUAL(string("not compatible with the server protocol version"),errormsg);
226             }
227         }
228     }
229
230     void SeparatorMissing()
231     {
232         switch(child_pid=fork())
233         {
234             case -1:
235             {
236                 CPPUNIT_FAIL("fork error");
237                 break;
238             }
239             case 0:
240             // child
241             {
242                 socket_server ss("./socket");
243
244                 ostringstream hello;
245                 hello << "T2Nv" << PROTOCOL_VERSION;
246                 int byteordercheck=1;
247                 hello.write((char*)&byteordercheck,sizeof(byteordercheck));
248                 hello << ';';
249
250                 ss.add_callback(new_connection,bind(&test_hello::send_hello, boost::ref(*this), hello.str(),&ss, _1));
251
252                 // max 10 sec
253                 for (int i=0; i < 10; i++)
254                     ss.fill_buffer(1000000);
255                 // don't call atexit and stuff
256                 _exit(0);
257             }
258
259             default:
260             // parent
261             {
262                 string data;
263
264                 // wait till server is up
265                 sleep(1);
266                 socket_client_connection sc("./socket");
267
268                 command_client cc(&sc);
269
270                 t2n_exception* ep=cc.get_constuctor_exception();
271
272                 string errormsg;
273                 if (ep)
274                     errormsg=ep->what();
275
276                 CPPUNIT_ASSERT_EQUAL(string("illegal hello received (1. ;)"),errormsg);
277             }
278         }
279     }
280
281     void WrongByteOrder()
282     {
283         switch(child_pid=fork())
284         {
285             case -1:
286             {
287                 CPPUNIT_FAIL("fork error");
288                 break;
289             }
290             case 0:
291             // child
292             {
293                 socket_server ss("./socket");
294
295                 ostringstream hello;
296                 hello << "T2Nv" << PROTOCOL_VERSION << ';';
297                 int byteordercheck=1;
298                 int dst;
299                 char* si=(char*)&byteordercheck;
300                 char* di=(char*)&dst;
301
302                 di[0]=si[3];
303                 di[1]=si[2];
304                 di[2]=si[1];
305                 di[3]=si[0];
306
307                 hello.write((char*)&dst,sizeof(dst));
308                 hello << ';';
309
310                 ss.add_callback(new_connection,bind(&test_hello::send_hello, boost::ref(*this), hello.str(),&ss, _1));
311
312                 // max 10 sec
313                 for (int i=0; i < 10; i++)
314                     ss.fill_buffer(1000000);
315                 // don't call atexit and stuff
316                 _exit(0);
317             }
318
319             default:
320             // parent
321             {
322                 string data;
323
324                 // wait till server is up
325                 sleep(1);
326                 socket_client_connection sc("./socket");
327
328                 command_client cc(&sc);
329
330                 t2n_exception* ep=cc.get_constuctor_exception();
331
332                 string errormsg;
333                 if (ep)
334                     errormsg=ep->what();
335
336                 CPPUNIT_ASSERT_EQUAL(string("host byte order not matching"),errormsg);
337             }
338         }
339     }
340
341     void OtherServerBig()
342     {
343         switch(child_pid=fork())
344         {
345             case -1:
346             {
347                 CPPUNIT_FAIL("fork error");
348                 break;
349             }
350             case 0:
351             // child
352             {
353                 socket_server ss("./socket");
354
355                 ostringstream hello;
356                 // hmm, we got the wrong socket
357                 hello << "* OK intradev.net.lan Cyrus IMAP4 v2.2.13 server ready";
358
359                 ss.add_callback(new_connection,bind(&test_hello::send_raw_socket, boost::ref(*this), hello.str(),&ss, _1));
360
361                 // max 3 sec
362                 for (int i=0; i < 3; i++)
363                     ss.fill_buffer(1000000);
364                 // don't call atexit and stuff
365                 _exit(0);
366             }
367
368             default:
369             // parent
370             {
371                 string data;
372
373                 // wait till server is up
374                 sleep(1);
375                 socket_client_connection sc("./socket");
376
377                 command_client cc(&sc);
378
379                 t2n_exception* ep=cc.get_constuctor_exception();
380
381                 string errormsg;
382                 if (ep)
383                     errormsg=ep->what();
384
385                 CPPUNIT_ASSERT_EQUAL(string("illegal hello received (T2N)"),errormsg);
386             }
387         }
388     }
389
390     void OtherServerSmall()
391     {
392         switch(child_pid=fork())
393         {
394             case -1:
395             {
396                 CPPUNIT_FAIL("fork error");
397                 break;
398             }
399             case 0:
400             // child
401             {
402                 socket_server ss("./socket");
403
404                 ostringstream hello;
405                 // hmm, we got the wrong socket
406                 hello << "READY";
407
408                 ss.add_callback(new_connection,bind(&test_hello::send_raw_socket, boost::ref(*this), hello.str(),&ss, _1));
409
410                 // max 3 sec
411                 for (int i=0; i < 3; i++)
412                     ss.fill_buffer(1000000);
413                 // don't call atexit and stuff
414                 _exit(0);
415             }
416
417             default:
418             // parent
419             {
420                 string data;
421
422                 // wait till server is up
423                 sleep(1);
424                 socket_client_connection sc("./socket");
425
426                 command_client cc(&sc);
427
428                 t2n_exception* ep=cc.get_constuctor_exception();
429
430                 string errormsg;
431                 if (ep)
432                     errormsg=ep->what();
433
434                 CPPUNIT_ASSERT_EQUAL(string("illegal hello received (T2N)"),errormsg);
435             }
436         }
437     }
438
439 };
440
441 CPPUNIT_TEST_SUITE_REGISTRATION(test_hello);