Home | History | Annotate | Download | only in base
      1 /*
      2  *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include <string>
     12 #include "webrtc/base/asynchttprequest.h"
     13 #include "webrtc/base/gunit.h"
     14 #include "webrtc/base/httpserver.h"
     15 #include "webrtc/base/socketstream.h"
     16 #include "webrtc/base/thread.h"
     17 #include "webrtc/test/testsupport/gtest_disable.h"
     18 
     19 namespace rtc {
     20 
     21 static const SocketAddress kServerAddr("127.0.0.1", 0);
     22 static const SocketAddress kServerHostnameAddr("localhost", 0);
     23 static const char kServerGetPath[] = "/get";
     24 static const char kServerPostPath[] = "/post";
     25 static const char kServerResponse[] = "This is a test";
     26 
     27 class TestHttpServer : public HttpServer, public sigslot::has_slots<> {
     28  public:
     29   TestHttpServer(Thread* thread, const SocketAddress& addr) :
     30       socket_(thread->socketserver()->CreateAsyncSocket(addr.family(),
     31                                                         SOCK_STREAM)) {
     32     socket_->Bind(addr);
     33     socket_->Listen(5);
     34     socket_->SignalReadEvent.connect(this, &TestHttpServer::OnAccept);
     35   }
     36 
     37   SocketAddress address() const { return socket_->GetLocalAddress(); }
     38   void Close() const { socket_->Close(); }
     39 
     40  private:
     41   void OnAccept(AsyncSocket* socket) {
     42     AsyncSocket* new_socket = socket_->Accept(NULL);
     43     if (new_socket) {
     44       HandleConnection(new SocketStream(new_socket));
     45     }
     46   }
     47   rtc::scoped_ptr<AsyncSocket> socket_;
     48 };
     49 
     50 class AsyncHttpRequestTest : public testing::Test,
     51                              public sigslot::has_slots<> {
     52  public:
     53   AsyncHttpRequestTest()
     54       : started_(false),
     55         done_(false),
     56         server_(Thread::Current(), kServerAddr) {
     57     server_.SignalHttpRequest.connect(this, &AsyncHttpRequestTest::OnRequest);
     58   }
     59 
     60   bool started() const { return started_; }
     61   bool done() const { return done_; }
     62 
     63   AsyncHttpRequest* CreateGetRequest(const std::string& host, int port,
     64                                      const std::string& path) {
     65     rtc::AsyncHttpRequest* request =
     66         new rtc::AsyncHttpRequest("unittest");
     67     request->SignalWorkDone.connect(this,
     68         &AsyncHttpRequestTest::OnRequestDone);
     69     request->request().verb = rtc::HV_GET;
     70     request->set_host(host);
     71     request->set_port(port);
     72     request->request().path = path;
     73     request->response().document.reset(new MemoryStream());
     74     return request;
     75   }
     76   AsyncHttpRequest* CreatePostRequest(const std::string& host, int port,
     77                                       const std::string& path,
     78                                       const std::string content_type,
     79                                       StreamInterface* content) {
     80     rtc::AsyncHttpRequest* request =
     81         new rtc::AsyncHttpRequest("unittest");
     82     request->SignalWorkDone.connect(this,
     83         &AsyncHttpRequestTest::OnRequestDone);
     84     request->request().verb = rtc::HV_POST;
     85     request->set_host(host);
     86     request->set_port(port);
     87     request->request().path = path;
     88     request->request().setContent(content_type, content);
     89     request->response().document.reset(new MemoryStream());
     90     return request;
     91   }
     92 
     93   const TestHttpServer& server() const { return server_; }
     94 
     95  protected:
     96   void OnRequest(HttpServer* server, HttpServerTransaction* t) {
     97     started_ = true;
     98 
     99     if (t->request.path == kServerGetPath) {
    100       t->response.set_success("text/plain", new MemoryStream(kServerResponse));
    101     } else if (t->request.path == kServerPostPath) {
    102       // reverse the data and reply
    103       size_t size;
    104       StreamInterface* in = t->request.document.get();
    105       StreamInterface* out = new MemoryStream();
    106       in->GetSize(&size);
    107       for (size_t i = 0; i < size; ++i) {
    108         char ch;
    109         in->SetPosition(size - i - 1);
    110         in->Read(&ch, 1, NULL, NULL);
    111         out->Write(&ch, 1, NULL, NULL);
    112       }
    113       out->Rewind();
    114       t->response.set_success("text/plain", out);
    115     } else {
    116       t->response.set_error(404);
    117     }
    118     server_.Respond(t);
    119   }
    120   void OnRequestDone(SignalThread* thread) {
    121     done_ = true;
    122   }
    123 
    124  private:
    125   bool started_;
    126   bool done_;
    127   TestHttpServer server_;
    128 };
    129 
    130 TEST_F(AsyncHttpRequestTest, DISABLED_ON_MAC(TestGetSuccess)) {
    131   AsyncHttpRequest* req = CreateGetRequest(
    132       kServerHostnameAddr.hostname(), server().address().port(),
    133       kServerGetPath);
    134   EXPECT_FALSE(started());
    135   req->Start();
    136   EXPECT_TRUE_WAIT(started(), 5000);  // Should have started by now.
    137   EXPECT_TRUE_WAIT(done(), 5000);
    138   std::string response;
    139   EXPECT_EQ(200U, req->response().scode);
    140   ASSERT_TRUE(req->response().document);
    141   req->response().document->Rewind();
    142   req->response().document->ReadLine(&response);
    143   EXPECT_EQ(kServerResponse, response);
    144   req->Release();
    145 }
    146 
    147 TEST_F(AsyncHttpRequestTest, DISABLED_ON_MAC(TestGetNotFound)) {
    148   AsyncHttpRequest* req = CreateGetRequest(
    149       kServerHostnameAddr.hostname(), server().address().port(),
    150       "/bad");
    151   req->Start();
    152   EXPECT_TRUE_WAIT(done(), 5000);
    153   size_t size;
    154   EXPECT_EQ(404U, req->response().scode);
    155   ASSERT_TRUE(req->response().document);
    156   req->response().document->GetSize(&size);
    157   EXPECT_EQ(0U, size);
    158   req->Release();
    159 }
    160 
    161 TEST_F(AsyncHttpRequestTest, DISABLED_ON_MAC(TestGetToNonServer)) {
    162   AsyncHttpRequest* req = CreateGetRequest(
    163       "127.0.0.1", server().address().port(),
    164       kServerGetPath);
    165   // Stop the server before we send the request.
    166   server().Close();
    167   req->Start();
    168   EXPECT_TRUE_WAIT(done(), 10000);
    169   size_t size;
    170   EXPECT_EQ(500U, req->response().scode);
    171   ASSERT_TRUE(req->response().document);
    172   req->response().document->GetSize(&size);
    173   EXPECT_EQ(0U, size);
    174   req->Release();
    175 }
    176 
    177 TEST_F(AsyncHttpRequestTest, DISABLED_TestGetToInvalidHostname) {
    178   AsyncHttpRequest* req = CreateGetRequest(
    179       "invalid", server().address().port(),
    180       kServerGetPath);
    181   req->Start();
    182   EXPECT_TRUE_WAIT(done(), 5000);
    183   size_t size;
    184   EXPECT_EQ(500U, req->response().scode);
    185   ASSERT_TRUE(req->response().document);
    186   req->response().document->GetSize(&size);
    187   EXPECT_EQ(0U, size);
    188   req->Release();
    189 }
    190 
    191 TEST_F(AsyncHttpRequestTest, DISABLED_ON_MAC(TestPostSuccess)) {
    192   AsyncHttpRequest* req = CreatePostRequest(
    193       kServerHostnameAddr.hostname(), server().address().port(),
    194       kServerPostPath, "text/plain", new MemoryStream("abcd1234"));
    195   req->Start();
    196   EXPECT_TRUE_WAIT(done(), 5000);
    197   std::string response;
    198   EXPECT_EQ(200U, req->response().scode);
    199   ASSERT_TRUE(req->response().document);
    200   req->response().document->Rewind();
    201   req->response().document->ReadLine(&response);
    202   EXPECT_EQ("4321dcba", response);
    203   req->Release();
    204 }
    205 
    206 // Ensure that we shut down properly even if work is outstanding.
    207 TEST_F(AsyncHttpRequestTest, DISABLED_ON_MAC(TestCancel)) {
    208   AsyncHttpRequest* req = CreateGetRequest(
    209       kServerHostnameAddr.hostname(), server().address().port(),
    210       kServerGetPath);
    211   req->Start();
    212   req->Destroy(true);
    213 }
    214 
    215 TEST_F(AsyncHttpRequestTest, DISABLED_ON_MAC(TestGetSuccessDelay)) {
    216   AsyncHttpRequest* req = CreateGetRequest(
    217       kServerHostnameAddr.hostname(), server().address().port(),
    218       kServerGetPath);
    219   req->set_start_delay(10);  // Delay 10ms.
    220   req->Start();
    221   Thread::SleepMs(5);
    222   EXPECT_FALSE(started());  // Should not have started immediately.
    223   EXPECT_TRUE_WAIT(started(), 5000);  // Should have started by now.
    224   EXPECT_TRUE_WAIT(done(), 5000);
    225   std::string response;
    226   EXPECT_EQ(200U, req->response().scode);
    227   ASSERT_TRUE(req->response().document);
    228   req->response().document->Rewind();
    229   req->response().document->ReadLine(&response);
    230   EXPECT_EQ(kServerResponse, response);
    231   req->Release();
    232 }
    233 
    234 }  // namespace rtc
    235