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