libt2n: (tomj) fixed call of virtual function close() from destructor, fixed return...
[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                 {
142                     socket_server ss("./socket");
143                     command_server cs(ss);
144
145                     // handle new connection and just one command
146                     cs.handle(10000000);
147                     cs.handle(10000000);
148                 }
149                 // close socket, create new one
150                 {
151                     socket_server ss("./socket");
152                     ss.set_logging(&cerr,debug);
153                     command_server cs(ss);
154
155                     // max 30 sec
156                     for (int i=0; i < 30; i++)
157                         cs.handle(1000000);
158                 }
159
160                 // don't call atexit and stuff
161                 _exit(0);
162             }
163
164             default:
165             // parent
166             {
167                 // don't kill us on broken pipe
168                 signal(SIGPIPE, SIG_IGN);
169
170                 // wait till server is up
171                 sleep(1);
172                 socket_client_connection sc("./socket");
173                 sc.set_logging(&cerr,debug);
174                 command_client cc(&sc);
175
176                 result_container rc;
177                 cc.send_command(new newserver_cmd(1),rc);
178
179                 // very short sleep to make sure new server socket is up
180                 usleep(10000);
181
182                 // still has connection to the old server-socket
183                 string errormsg;
184
185                 try
186                 {
187                     sc.write("some stuff");
188                 }
189                 catch(t2n_transfer_error &e)
190                     { errormsg=e.what(); }
191                 catch(...)
192                     { throw; }
193
194                 CPPUNIT_ASSERT_EQUAL(string("write() returned Bad file descriptor"),errormsg);
195             }
196         }
197     }
198 };
199
200 CPPUNIT_TEST_SUITE_REGISTRATION(test_newserver);