test sockets both with and without event loop
[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() { m_useLoop = false; }
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() { m_useLoop = true; }
90
91 void BlockingConnect();
92 void NonblockingConnect();
93 void ReadNormal();
94 void ReadBlock();
95 void ReadNowait();
96 void ReadWaitall();
97
98 bool m_useLoop;
99
100 DECLARE_NO_COPY_CLASS(SocketTestCase)
101 };
102
103 CPPUNIT_TEST_SUITE_REGISTRATION( SocketTestCase );
104 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( SocketTestCase, "SocketTestCase" );
105
106 wxSockAddressPtr SocketTestCase::GetServer() const
107 {
108 if ( gs_serverHost.empty() )
109 return wxSockAddressPtr();
110
111 wxIPV4address *addr = new wxIPV4address;
112 addr->Hostname(gs_serverHost);
113 addr->Service("www");
114
115 return wxSockAddressPtr(addr);
116 }
117
118 wxSocketClientPtr SocketTestCase::GetHTTPSocket(int flags) const
119 {
120 wxSockAddressPtr addr = GetServer();
121 if ( !addr.get() )
122 return wxSocketClientPtr();
123
124 wxSocketClient *sock = new wxSocketClient(flags);
125 sock->SetTimeout(1);
126 CPPUNIT_ASSERT( sock->Connect(*addr) );
127
128 const wxString httpGetRoot =
129 "GET / HTTP/1.1\r\n"
130 "Host: " + gs_serverHost + "\r\n"
131 "\r\n";
132
133 sock->Write(httpGetRoot.ToAscii(), httpGetRoot.length());
134
135 return wxSocketClientPtr(sock);
136 }
137
138 void SocketTestCase::BlockingConnect()
139 {
140 wxSockAddressPtr addr = GetServer();
141 if ( !addr.get() )
142 return;
143
144 wxSocketClient sock;
145 CPPUNIT_ASSERT( sock.Connect(*addr) );
146 }
147
148 void SocketTestCase::NonblockingConnect()
149 {
150 wxSockAddressPtr addr = GetServer();
151 if ( !addr.get() )
152 return;
153
154 SocketTestEventLoop loop(m_useLoop);
155
156 wxSocketClient sock;
157 sock.Connect(*addr, false);
158 sock.WaitOnConnect(10);
159
160 CPPUNIT_ASSERT( sock.IsConnected() );
161 }
162
163 void SocketTestCase::ReadNormal()
164 {
165 SocketTestEventLoop loop(m_useLoop);
166
167 wxSocketClientPtr sock(GetHTTPSocket());
168 if ( !sock.get() )
169 return;
170
171 char bufSmall[128];
172 sock->Read(bufSmall, WXSIZEOF(bufSmall));
173
174 CPPUNIT_ASSERT_EQUAL( wxSOCKET_NOERROR, sock->LastError() );
175 CPPUNIT_ASSERT_EQUAL( WXSIZEOF(bufSmall), sock->LastCount() );
176
177
178 char bufBig[102400];
179 sock->Read(bufBig, WXSIZEOF(bufBig));
180
181 CPPUNIT_ASSERT_EQUAL( wxSOCKET_NOERROR, sock->LastError() );
182 CPPUNIT_ASSERT( WXSIZEOF(bufBig) >= sock->LastCount() );
183 }
184
185 void SocketTestCase::ReadBlock()
186 {
187 wxSocketClientPtr sock(GetHTTPSocket(wxSOCKET_BLOCK));
188 if ( !sock.get() )
189 return;
190
191 char bufSmall[128];
192 sock->Read(bufSmall, WXSIZEOF(bufSmall));
193
194 CPPUNIT_ASSERT_EQUAL( wxSOCKET_NOERROR, sock->LastError() );
195 CPPUNIT_ASSERT_EQUAL( WXSIZEOF(bufSmall), sock->LastCount() );
196
197
198 char bufBig[102400];
199 sock->Read(bufBig, WXSIZEOF(bufBig));
200
201 CPPUNIT_ASSERT_EQUAL( wxSOCKET_NOERROR, sock->LastError() );
202 CPPUNIT_ASSERT( WXSIZEOF(bufBig) >= sock->LastCount() );
203 }
204
205 void SocketTestCase::ReadNowait()
206 {
207 wxSocketClientPtr sock(GetHTTPSocket(wxSOCKET_NOWAIT));
208 if ( !sock.get() )
209 return;
210
211 char buf[1024];
212 sock->Read(buf, WXSIZEOF(buf));
213 if ( sock->LastError() != wxSOCKET_WOULDBLOCK )
214 {
215 CPPUNIT_ASSERT_EQUAL( wxSOCKET_NOERROR, sock->LastError() );
216 }
217 }
218
219 void SocketTestCase::ReadWaitall()
220 {
221 SocketTestEventLoop loop(m_useLoop);
222
223 wxSocketClientPtr sock(GetHTTPSocket(wxSOCKET_WAITALL));
224 if ( !sock.get() )
225 return;
226
227 char buf[128];
228 sock->Read(buf, WXSIZEOF(buf));
229
230 CPPUNIT_ASSERT_EQUAL( wxSOCKET_NOERROR, sock->LastError() );
231 CPPUNIT_ASSERT_EQUAL( WXSIZEOF(buf), sock->LastCount() );
232 }
233
234 #endif // wxUSE_SOCKETS