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