369d635ccd73a19ee223387ff4a4510f15529c66
[libt2n] / test / newserver.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 <cppunit/extensions/TestFactoryRegistry.h>
19 #include <cppunit/ui/text/TestRunner.h>
20 #include <cppunit/extensions/HelperMacros.h>
21
22 #include <boost/archive/binary_oarchive.hpp>
23 #include <boost/archive/binary_iarchive.hpp>
24 #include <boost/archive/xml_oarchive.hpp>
25 #include <boost/archive/xml_iarchive.hpp>
26 #include <boost/serialization/serialization.hpp>
27
28 #include <container.hxx>
29 #include <socket_client.hxx>
30 #include <socket_server.hxx>
31 #include <command_client.hxx>
32 #include <command_server.hxx>
33
34 using namespace std;
35 using namespace CppUnit;
36
37 int newserver_func(int i)
38 {
39
40     return 1;
41 }
42
43 class newserver_res : public libt2n::result
44 {
45     private:
46         int res;
47
48         friend class boost::serialization::access;
49         template<class Archive>
50         void serialize(Archive & ar, const unsigned int version)
51         {
52             ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::result);
53             ar & BOOST_SERIALIZATION_NVP(res);
54         }
55
56     public:
57         newserver_res()
58             { }
59
60         newserver_res(int i)
61         {
62             res=i;
63         }
64
65         int get_data()
66         {
67             return res;
68         }
69 };
70
71
72 class newserver_cmd : public libt2n::command
73 {
74     private:
75         int param;
76
77         friend class boost::serialization::access;
78         template<class Archive>
79         void serialize(Archive & ar, const unsigned int version)
80         {
81             ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::command);
82             ar & BOOST_SERIALIZATION_NVP(param);
83         }
84
85     public:
86         newserver_cmd()
87             { }
88
89         newserver_cmd(int i)
90         {
91             param=i;
92         }
93
94         libt2n::result* operator()()
95         {
96             return new newserver_res(newserver_func(param));
97         }
98 };
99
100 #include <boost/serialization/export.hpp>
101
102 BOOST_CLASS_EXPORT(newserver_cmd)
103 BOOST_CLASS_EXPORT(newserver_res)
104
105 using namespace libt2n;
106
107 class test_newserver : public TestFixture
108 {
109     CPPUNIT_TEST_SUITE(test_newserver);
110
111     CPPUNIT_TEST(NewServerSocket);
112
113     CPPUNIT_TEST_SUITE_END();
114
115     pid_t child_pid;
116
117     public:
118
119     void setUp()
120     { }
121
122     void tearDown()
123     {
124         // make sure the server-child is dead before the next test runs
125         kill(child_pid,SIGKILL);
126         sleep(1);
127     }
128
129     void NewServerSocket()
130     {
131         switch(child_pid=fork())
132         {
133             case -1:
134             {
135                 CPPUNIT_FAIL("fork error");
136                 break;
137             }
138             case 0:
139             // child
140             {
141                 try
142                 {
143                     {
144                         socket_server ss("./socket");
145                         command_server cs(ss);
146
147                         // handle new connection and just one command
148                         cs.handle(10000000);
149                         cs.handle(10000000);
150                     }
151                     // close socket, create new one
152                     {
153                         socket_server ss("./socket");
154                         ss.set_logging(&cerr,debug);
155                         command_server cs(ss);
156
157                         // max 30 sec
158                         for (int i=0; i < 30; i++)
159                             cs.handle(1000000);
160                     }
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                 // don't kill us on broken pipe
174                 signal(SIGPIPE, SIG_IGN);
175
176                 // wait till server is up
177                 sleep(1);
178                 socket_client_connection sc("./socket");
179                 sc.set_logging(&cerr,debug);
180                 command_client cc(&sc);
181
182                 result_container rc;
183                 cc.send_command(new newserver_cmd(1),rc);
184
185                 // very short sleep to make sure new server socket is up
186                 usleep(10000);
187
188                 // still has connection to the old server-socket
189                 string errormsg;
190
191                 try
192                 {
193                     sc.write("some stuff");
194                 }
195                 catch(t2n_transfer_error &e)
196                     { errormsg=e.what(); }
197                 catch(...)
198                     { throw; }
199
200                 CPPUNIT_ASSERT_EQUAL(string("write() returned Bad file descriptor"),errormsg);
201             }
202         }
203     }
204 };
205
206 CPPUNIT_TEST_SUITE_REGISTRATION(test_newserver);