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