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