socket.cpp 7.0 KB

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