OLD | NEW |
| (Empty) |
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, 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, 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, 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, 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, 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, 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 | |
OLD | NEW |