added a simple IPC unit test
[wxWidgets.git] / tests / net / ipc.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: tests/net/ipc.cpp
3 // Purpose: IPC classes unit tests
4 // Author: Vadim Zeitlin
5 // RCS-ID: $Id$
6 // Copyright: (c) 2008 Vadim Zeitlin
7 // Licence: wxWidgets licence
8 ///////////////////////////////////////////////////////////////////////////////
9
10 // For compilers that support precompilation, includes "wx/wx.h".
11 // and "wx/cppunit.h"
12 #include "testprec.h"
13
14 #ifdef __BORLANDC__
15 #pragma hdrstop
16 #endif
17
18 // for all others, include the necessary headers
19 #ifndef WX_PRECOMP
20 #endif
21
22 // this test needs threads as it runs the test server in a secondary thread
23 #if wxUSE_THREADS
24
25 #include "wx/ipc.h"
26 #include "wx/thread.h"
27
28 namespace
29 {
30
31 const char *IPC_TEST_PORT = "4242";
32 const char *IPC_TEST_TOPIC = "IPC TEST";
33
34 } // anonymous namespace
35
36 // ----------------------------------------------------------------------------
37 // test connection class used by IPCTestServer
38 // ----------------------------------------------------------------------------
39
40 class IPCTestConnection : public wxConnection
41 {
42 public:
43 IPCTestConnection() { }
44
45 virtual bool OnExec(const wxString& topic, const wxString& data)
46 {
47 if ( topic != IPC_TEST_TOPIC )
48 return false;
49
50 return data == "Date";
51 }
52
53 private:
54 DECLARE_NO_COPY_CLASS(IPCTestConnection)
55 };
56
57 // ----------------------------------------------------------------------------
58 // event dispatching thread class
59 // ----------------------------------------------------------------------------
60
61 class EventThread : public wxThread
62 {
63 public:
64 EventThread()
65 : wxThread(wxTHREAD_JOINABLE)
66 {
67 Create();
68 Run();
69 }
70
71 protected:
72 virtual void *Entry()
73 {
74 wxTheApp->MainLoop();
75
76 return NULL;
77 }
78
79 DECLARE_NO_COPY_CLASS(EventThread)
80 };
81
82 // ----------------------------------------------------------------------------
83 // test server class
84 // ----------------------------------------------------------------------------
85
86 class IPCTestServer : public wxServer
87 {
88 public:
89 IPCTestServer()
90 {
91 m_conn = NULL;
92
93 // we must call this from the main thread
94 wxSocketBase::Initialize();
95
96 // we need event dispatching to work for IPC server to work
97 m_thread = new EventThread;
98
99 Create(IPC_TEST_PORT);
100 }
101
102 virtual ~IPCTestServer()
103 {
104 wxTheApp->ExitMainLoop();
105
106 m_thread->Wait();
107 delete m_thread;
108 m_thread = NULL;
109
110 wxSocketBase::Shutdown();
111 }
112
113 virtual wxConnectionBase *OnAcceptConnection(const wxString& topic)
114 {
115 if ( topic != IPC_TEST_TOPIC )
116 return NULL;
117
118 m_conn = new IPCTestConnection;
119 return m_conn;
120 }
121
122 private:
123 EventThread *m_thread;
124 IPCTestConnection *m_conn;
125
126 DECLARE_NO_COPY_CLASS(IPCTestServer)
127 };
128
129 static IPCTestServer *gs_server = NULL;
130
131 // ----------------------------------------------------------------------------
132 // test client class
133 // ----------------------------------------------------------------------------
134
135 class IPCTestClient : public wxClient
136 {
137 public:
138 IPCTestClient()
139 {
140 m_conn = NULL;
141 }
142
143 virtual ~IPCTestClient()
144 {
145 Disconnect();
146 }
147
148 bool
149 Connect(const wxString& host, const wxString& service, const wxString& topic)
150 {
151 m_conn = MakeConnection(host, service, topic);
152
153 return m_conn != NULL;
154 }
155
156 void Disconnect()
157 {
158 if ( m_conn )
159 {
160 delete m_conn;
161 m_conn = NULL;
162 }
163 }
164
165 wxConnectionBase& GetConn() const
166 {
167 CPPUNIT_ASSERT( m_conn );
168
169 return *m_conn;
170 }
171
172 private:
173 wxConnectionBase *m_conn;
174
175 DECLARE_NO_COPY_CLASS(IPCTestClient)
176 };
177
178 static IPCTestClient gs_client;
179
180 // ----------------------------------------------------------------------------
181 // the test code itself
182 // ----------------------------------------------------------------------------
183
184 class IPCTestCase : public CppUnit::TestCase
185 {
186 public:
187 IPCTestCase() { }
188
189 private:
190 CPPUNIT_TEST_SUITE( IPCTestCase );
191 CPPUNIT_TEST( Connect );
192 CPPUNIT_TEST( Execute );
193 CPPUNIT_TEST( Disconnect );
194 CPPUNIT_TEST_SUITE_END();
195
196 void Connect();
197 void Execute();
198 void Disconnect();
199
200 DECLARE_NO_COPY_CLASS(IPCTestCase)
201 };
202
203 // this test is not enabled by default because it requires an IPC server to run
204 //CPPUNIT_TEST_SUITE_REGISTRATION( IPCTestCase );
205 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( IPCTestCase, "IPCTestCase" );
206
207 void IPCTestCase::Connect()
208 {
209 gs_server = new IPCTestServer;
210
211 // connecting to the wrong port should fail
212 CPPUNIT_ASSERT( !gs_client.Connect("localhost", "2424", IPC_TEST_TOPIC) );
213
214 // connecting using an unsupported topic should fail (unless the server
215 // expects a ROT-13'd topic name...)
216 CPPUNIT_ASSERT( !gs_client.Connect("localhost", IPC_TEST_PORT, "VCP GRFG") );
217
218 // connecting to the right port on the right topic should succeed
219 CPPUNIT_ASSERT( gs_client.Connect("localhost", IPC_TEST_PORT, IPC_TEST_TOPIC) );
220 }
221
222 void IPCTestCase::Execute()
223 {
224 wxConnectionBase& conn = gs_client.GetConn();
225
226 const wxString s("Date");
227 CPPUNIT_ASSERT( conn.Execute(s) );
228 CPPUNIT_ASSERT( conn.Execute(s.mb_str(), s.length() + 1) );
229
230 char bytes[] = { 1, 2, 3 };
231 CPPUNIT_ASSERT( conn.Execute(bytes, WXSIZEOF(bytes)) );
232 }
233
234 void IPCTestCase::Disconnect()
235 {
236 gs_client.Disconnect();
237
238 if ( gs_server )
239 {
240 delete gs_server;
241 gs_server = NULL;
242 }
243 }
244
245 #endif // wxUSE_THREADS