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