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