MSW compilation fix after last commit
[wxWidgets.git] / tests / streams / socketstream.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: tests/streams/socketstream.cpp
3 // Purpose: Test wxSocketInputStream/wxSocketOutputStream
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 #include "wx/log.h"
21 #endif
22
23 #include "wx/gsocket.h"
24 #include "wx/socket.h"
25 #include "wx/sckstrm.h"
26 #include "wx/thread.h"
27
28 #include "bstream.h"
29
30 namespace
31 {
32
33 const int TEST_PORT_READ = 0x7778; // arbitrary, chosen because == "wx"
34 const int TEST_PORT_WRITE = 0x7779; // well, "wy"
35
36 // these cond and mutex are used to minimize the risk of the main thread
37 // Connect()-ing before this thread starts Accept()-ing connections but
38 // unfortunately we can't make this truly safe, see comment in
39 // SocketServerThread::Entry()
40 wxMutex gs_mutex;
41 wxCondition gs_cond(gs_mutex);
42 } // anonymous namespace
43
44 // return address for the given port on local host
45 static inline wxIPV4address LocalAddress(int port)
46 {
47 wxIPV4address addr;
48 addr.LocalHost();
49 addr.Service(port);
50
51 return addr;
52 }
53
54 // A thread which creates a listening socket on the specified port and executes
55 // the given function with each socket which connects to it
56 class SocketServerThread : public wxThread
57 {
58 public:
59 // port is the port to listen on and function will be called on each
60 // accepted socket
61 SocketServerThread(int port, void (*accept)(wxSocketBase&))
62 : wxThread(wxTHREAD_JOINABLE),
63 m_port(port),
64 m_accept(accept)
65 {
66 Create();
67 Run();
68 }
69
70 protected:
71 virtual void *Entry()
72 {
73 wxSocketServer srv(LocalAddress(m_port), wxSOCKET_REUSEADDR);
74
75 // FIXME: this is still not atomic, of course and the main thread could
76 // call Connect() before we have time to Accept() but there is
77 // no way to fix it with current API
78 {
79 wxMutexLocker lock(gs_mutex);
80 gs_cond.Signal();
81 }
82
83 wxSocketBase *socket = srv.Accept();
84 if ( socket )
85 (*m_accept)(*socket);
86
87 return NULL;
88 }
89
90 int m_port;
91 void (*m_accept)(wxSocketBase&);
92
93 DECLARE_NO_COPY_CLASS(SocketServerThread)
94 };
95
96 // The test case for socket streams
97 class socketStream :
98 public BaseStreamTestCase<wxSocketInputStream, wxSocketOutputStream>
99 {
100 public:
101 socketStream();
102 virtual ~socketStream();
103
104 virtual void setUp();
105 virtual void tearDown();
106
107 CPPUNIT_TEST_SUITE(socketStream);
108 // Base class stream tests the socketStream supports.
109 CPPUNIT_TEST(Input_GetC);
110
111 // This one fails because wxSocketInputStream::Eof() is not implemented
112 // correctly
113 //CPPUNIT_TEST(Input_Read);
114
115 // The other ones untested yet
116 #if 0
117 CPPUNIT_TEST(Input_Eof);
118 CPPUNIT_TEST(Input_LastRead);
119 CPPUNIT_TEST(Input_CanRead);
120 CPPUNIT_TEST(Input_Peek);
121 CPPUNIT_TEST(Input_Ungetch);
122
123 CPPUNIT_TEST(Output_PutC);
124 CPPUNIT_TEST(Output_Write);
125 CPPUNIT_TEST(Output_LastWrite);
126 #endif
127 CPPUNIT_TEST_SUITE_END();
128
129 private:
130 // Implement base class functions.
131 virtual wxSocketInputStream *DoCreateInStream();
132 virtual wxSocketOutputStream *DoCreateOutStream();
133
134 // socket thread functions
135 static void WriteSocket(wxSocketBase& socket)
136 {
137 socket.Write("hello, world!", 13);
138 }
139
140 static void ReadSocket(wxSocketBase& socket)
141 {
142 char ch;
143 while ( socket.Read(&ch, 1).LastCount() == 1 )
144 ;
145 }
146
147 wxSocketClient *m_readSocket,
148 *m_writeSocket;
149 wxThread *m_writeThread,
150 *m_readThread;
151 };
152
153 socketStream::socketStream()
154 {
155 m_readSocket =
156 m_writeSocket = NULL;
157
158 m_writeThread =
159 m_readThread = NULL;
160
161 GSocket_Init();
162 }
163
164 socketStream::~socketStream()
165 {
166 GSocket_Cleanup();
167 }
168
169 void socketStream::setUp()
170 {
171 // create the socket threads and wait until they are ready to accept
172 // connections (if we called Connect() before this happens, it would fail)
173 {
174 wxMutexLocker lock(gs_mutex);
175
176 m_writeThread =
177 new SocketServerThread(TEST_PORT_READ, &socketStream::WriteSocket);
178 CPPUNIT_ASSERT_EQUAL( wxCOND_NO_ERROR, gs_cond.Wait() );
179
180 m_readThread =
181 new SocketServerThread(TEST_PORT_WRITE, &socketStream::ReadSocket);
182 CPPUNIT_ASSERT_EQUAL( wxCOND_NO_ERROR, gs_cond.Wait() );
183 }
184
185 m_readSocket = new wxSocketClient;
186 m_readSocket->SetTimeout(3);
187 CPPUNIT_ASSERT( m_readSocket->Connect(LocalAddress(TEST_PORT_READ)) );
188
189 m_writeSocket = new wxSocketClient;
190 m_writeSocket->SetTimeout(3);
191 CPPUNIT_ASSERT( m_writeSocket->Connect(LocalAddress(TEST_PORT_WRITE)) );
192 }
193
194 void socketStream::tearDown()
195 {
196 wxDELETE(m_readSocket);
197 wxDELETE(m_writeSocket);
198
199 m_writeThread->Wait();
200 wxDELETE(m_writeThread);
201
202 m_readThread->Wait();
203 wxDELETE(m_readThread);
204 }
205
206 wxSocketInputStream *socketStream::DoCreateInStream()
207 {
208 wxSocketInputStream *pStrInStream = new wxSocketInputStream(*m_readSocket);
209 CPPUNIT_ASSERT(pStrInStream->IsOk());
210 return pStrInStream;
211 }
212
213 wxSocketOutputStream *socketStream::DoCreateOutStream()
214 {
215 wxSocketOutputStream *pStrOutStream = new wxSocketOutputStream(*m_writeSocket);
216 CPPUNIT_ASSERT(pStrOutStream->IsOk());
217 return pStrOutStream;
218 }
219
220 // Register the stream sub suite, by using some stream helper macro.
221 STREAM_TEST_SUBSUITE_NAMED_REGISTRATION(socketStream)