make the test really use the event loop in its second half (this already was the...
[wxWidgets.git] / tests / net / socket.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: tests/net/socket.cpp
3 // Purpose: wxSocket unit tests
4 // Author: Vadim Zeitlin
5 // RCS-ID: $Id$
6 // Copyright: (c) 2008 Vadim Zeitlin
7 // Licence: wxWidgets licence
8 ///////////////////////////////////////////////////////////////////////////////
9
10 /*
11 IMPORTANT NOTE: the environment variable WX_TEST_SERVER must be set to the
12 hostname of the server to use for the tests below, if it is not set all
13 tests are silently skipped (rationale: this makes it possible to run the
14 test in the restricted environments (e.g. sandboxes) without any network
15 connectivity).
16 */
17
18 // For compilers that support precompilation, includes "wx/wx.h".
19 // and "wx/cppunit.h"
20 #include "testprec.h"
21
22 #ifdef __BORLANDC__
23 #pragma hdrstop
24 #endif
25
26 #if wxUSE_SOCKETS
27
28 #include "wx/socket.h"
29 #include "wx/evtloop.h"
30 #include <memory>
31
32 typedef std::auto_ptr<wxSockAddress> wxSockAddressPtr;
33 typedef std::auto_ptr<wxSocketClient> wxSocketClientPtr;
34
35 static wxString gs_serverHost(wxGetenv("WX_TEST_SERVER"));
36
37 class SocketTestCase : public CppUnit::TestCase
38 {
39 public:
40 SocketTestCase() { }
41
42 private:
43 // we need to repeat the tests twice as the sockets behave differently when
44 // there is an active event loop and without it
45 #define ALL_SOCKET_TESTS() \
46 CPPUNIT_TEST( BlockingConnect ); \
47 CPPUNIT_TEST( NonblockingConnect ); \
48 CPPUNIT_TEST( ReadNormal ); \
49 CPPUNIT_TEST( ReadBlock ); \
50 CPPUNIT_TEST( ReadNowait ); \
51 CPPUNIT_TEST( ReadWaitall )
52
53 CPPUNIT_TEST_SUITE( SocketTestCase );
54 ALL_SOCKET_TESTS();
55 CPPUNIT_TEST( PseudoTest_SetUseEventLoop );
56 ALL_SOCKET_TESTS();
57 CPPUNIT_TEST_SUITE_END();
58
59 // helper event loop class which sets itself as active only if we pass it
60 // true in ctor
61 class SocketTestEventLoop : public wxEventLoop
62 {
63 public:
64 SocketTestEventLoop(bool useLoop)
65 {
66 m_useLoop = useLoop;
67 if ( useLoop )
68 SetActive(this);
69 }
70
71 virtual ~SocketTestEventLoop()
72 {
73 if ( m_useLoop )
74 SetActive(NULL);
75 }
76
77 private:
78 bool m_useLoop;
79 };
80
81 // get the address to connect to, if NULL is returned it means that the
82 // test is disabled and shouldn't run at all
83 wxSockAddressPtr GetServer() const;
84
85 // get the socket to read HTTP reply from, returns NULL if the test is
86 // disabled
87 wxSocketClientPtr GetHTTPSocket(int flags = wxSOCKET_NONE) const;
88
89 void PseudoTest_SetUseEventLoop() { ms_useLoop = true; }
90
91 void BlockingConnect();
92 void NonblockingConnect();
93 void ReadNormal();
94 void ReadBlock();
95 void ReadNowait();
96 void ReadWaitall();
97
98 static bool ms_useLoop;
99
100 DECLARE_NO_COPY_CLASS(SocketTestCase)
101 };
102
103 bool SocketTestCase::ms_useLoop = false;
104
105 CPPUNIT_TEST_SUITE_REGISTRATION( SocketTestCase );
106 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( SocketTestCase, "SocketTestCase" );
107
108 wxSockAddressPtr SocketTestCase::GetServer() const
109 {
110 if ( gs_serverHost.empty() )
111 return wxSockAddressPtr();
112
113 wxIPV4address *addr = new wxIPV4address;
114 addr->Hostname(gs_serverHost);
115 addr->Service("www");
116
117 return wxSockAddressPtr(addr);
118 }
119
120 wxSocketClientPtr SocketTestCase::GetHTTPSocket(int flags) const
121 {
122 wxSockAddressPtr addr = GetServer();
123 if ( !addr.get() )
124 return wxSocketClientPtr();
125
126 wxSocketClient *sock = new wxSocketClient(flags);
127 sock->SetTimeout(1);
128 CPPUNIT_ASSERT( sock->Connect(*addr) );
129
130 const wxString httpGetRoot =
131 "GET / HTTP/1.1\r\n"
132 "Host: " + gs_serverHost + "\r\n"
133 "\r\n";
134
135 sock->Write(httpGetRoot.ToAscii(), httpGetRoot.length());
136
137 return wxSocketClientPtr(sock);
138 }
139
140 void SocketTestCase::BlockingConnect()
141 {
142 wxSockAddressPtr addr = GetServer();
143 if ( !addr.get() )
144 return;
145
146 wxSocketClient sock;
147 CPPUNIT_ASSERT( sock.Connect(*addr) );
148 }
149
150 void SocketTestCase::NonblockingConnect()
151 {
152 wxSockAddressPtr addr = GetServer();
153 if ( !addr.get() )
154 return;
155
156 SocketTestEventLoop loop(ms_useLoop);
157
158 wxSocketClient sock;
159 sock.Connect(*addr, false);
160 sock.WaitOnConnect(10);
161
162 CPPUNIT_ASSERT( sock.IsConnected() );
163 }
164
165 void SocketTestCase::ReadNormal()
166 {
167 SocketTestEventLoop loop(ms_useLoop);
168
169 wxSocketClientPtr sock(GetHTTPSocket());
170 if ( !sock.get() )
171 return;
172
173 char bufSmall[128];
174 sock->Read(bufSmall, WXSIZEOF(bufSmall));
175
176 CPPUNIT_ASSERT_EQUAL( wxSOCKET_NOERROR, sock->LastError() );
177 CPPUNIT_ASSERT_EQUAL( WXSIZEOF(bufSmall), sock->LastCount() );
178
179
180 char bufBig[102400];
181 sock->Read(bufBig, WXSIZEOF(bufBig));
182
183 CPPUNIT_ASSERT_EQUAL( wxSOCKET_NOERROR, sock->LastError() );
184 CPPUNIT_ASSERT( WXSIZEOF(bufBig) >= sock->LastCount() );
185 }
186
187 void SocketTestCase::ReadBlock()
188 {
189 wxSocketClientPtr sock(GetHTTPSocket(wxSOCKET_BLOCK));
190 if ( !sock.get() )
191 return;
192
193 char bufSmall[128];
194 sock->Read(bufSmall, WXSIZEOF(bufSmall));
195
196 CPPUNIT_ASSERT_EQUAL( wxSOCKET_NOERROR, sock->LastError() );
197 CPPUNIT_ASSERT_EQUAL( WXSIZEOF(bufSmall), sock->LastCount() );
198
199
200 char bufBig[102400];
201 sock->Read(bufBig, WXSIZEOF(bufBig));
202
203 CPPUNIT_ASSERT_EQUAL( wxSOCKET_NOERROR, sock->LastError() );
204 CPPUNIT_ASSERT( WXSIZEOF(bufBig) >= sock->LastCount() );
205 }
206
207 void SocketTestCase::ReadNowait()
208 {
209 wxSocketClientPtr sock(GetHTTPSocket(wxSOCKET_NOWAIT));
210 if ( !sock.get() )
211 return;
212
213 char buf[1024];
214 sock->Read(buf, WXSIZEOF(buf));
215 if ( sock->LastError() != wxSOCKET_WOULDBLOCK )
216 {
217 CPPUNIT_ASSERT_EQUAL( wxSOCKET_NOERROR, sock->LastError() );
218 }
219 }
220
221 void SocketTestCase::ReadWaitall()
222 {
223 SocketTestEventLoop loop(ms_useLoop);
224
225 wxSocketClientPtr sock(GetHTTPSocket(wxSOCKET_WAITALL));
226 if ( !sock.get() )
227 return;
228
229 char buf[128];
230 sock->Read(buf, WXSIZEOF(buf));
231
232 CPPUNIT_ASSERT_EQUAL( wxSOCKET_NOERROR, sock->LastError() );
233 CPPUNIT_ASSERT_EQUAL( WXSIZEOF(buf), sock->LastCount() );
234 }
235
236 #endif // wxUSE_SOCKETS