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