Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(131)

Side by Side Diff: net/server/http_server_unittest.cc

Issue 212683006: HttpServer: allows sending raw response data for nontypical responses. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Unit tests involving response-checking. Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/server/http_server.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <vector> 5 #include <vector>
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
10 #include "base/format_macros.h" 10 #include "base/format_macros.h"
(...skipping 20 matching lines...) Expand all
31 #include "net/url_request/url_fetcher_delegate.h" 31 #include "net/url_request/url_fetcher_delegate.h"
32 #include "net/url_request/url_request_context.h" 32 #include "net/url_request/url_request_context.h"
33 #include "net/url_request/url_request_context_getter.h" 33 #include "net/url_request/url_request_context_getter.h"
34 #include "net/url_request/url_request_test_util.h" 34 #include "net/url_request/url_request_test_util.h"
35 #include "testing/gtest/include/gtest/gtest.h" 35 #include "testing/gtest/include/gtest/gtest.h"
36 36
37 namespace net { 37 namespace net {
38 38
39 namespace { 39 namespace {
40 40
41 int kMaxExpectedResponseLength = 2048;
mef 2014/03/27 15:03:45 const
gunsch 2014/03/27 15:52:39 Done.
42
41 void SetTimedOutAndQuitLoop(const base::WeakPtr<bool> timed_out, 43 void SetTimedOutAndQuitLoop(const base::WeakPtr<bool> timed_out,
42 const base::Closure& quit_loop_func) { 44 const base::Closure& quit_loop_func) {
43 if (timed_out) { 45 if (timed_out) {
44 *timed_out = true; 46 *timed_out = true;
45 quit_loop_func.Run(); 47 quit_loop_func.Run();
46 } 48 }
47 } 49 }
48 50
49 bool RunLoopWithTimeout(base::RunLoop* run_loop) { 51 bool RunLoopWithTimeout(base::RunLoop* run_loop) {
50 bool timed_out = false; 52 bool timed_out = false;
(...skipping 28 matching lines...) Expand all
79 return ERR_TIMED_OUT; 81 return ERR_TIMED_OUT;
80 return connect_result_; 82 return connect_result_;
81 } 83 }
82 84
83 void Send(const std::string& data) { 85 void Send(const std::string& data) {
84 write_buffer_ = 86 write_buffer_ =
85 new DrainableIOBuffer(new StringIOBuffer(data), data.length()); 87 new DrainableIOBuffer(new StringIOBuffer(data), data.length());
86 Write(); 88 Write();
87 } 89 }
88 90
91 bool Read(std::string* data) {
92 base::RunLoop run_loop;
93 Read(run_loop.QuitClosure());
94 bool success = RunLoopWithTimeout(&run_loop);
95 std::string io_buffer_contents(read_buffer_->data());
96 *data = io_buffer_contents.substr(0, bytes_received_);
97 return success;
98 }
99
89 private: 100 private:
90 void OnConnect(const base::Closure& quit_loop, int result) { 101 void OnConnect(const base::Closure& quit_loop, int result) {
91 connect_result_ = result; 102 connect_result_ = result;
92 quit_loop.Run(); 103 quit_loop.Run();
93 } 104 }
94 105
95 void Write() { 106 void Write() {
96 int result = socket_->Write( 107 int result = socket_->Write(
97 write_buffer_.get(), 108 write_buffer_.get(),
98 write_buffer_->BytesRemaining(), 109 write_buffer_->BytesRemaining(),
99 base::Bind(&TestHttpClient::OnWrite, base::Unretained(this))); 110 base::Bind(&TestHttpClient::OnWrite, base::Unretained(this)));
100 if (result != ERR_IO_PENDING) 111 if (result != ERR_IO_PENDING)
101 OnWrite(result); 112 OnWrite(result);
102 } 113 }
103 114
104 void OnWrite(int result) { 115 void OnWrite(int result) {
105 ASSERT_GT(result, 0); 116 ASSERT_GT(result, 0);
106 write_buffer_->DidConsume(result); 117 write_buffer_->DidConsume(result);
107 if (write_buffer_->BytesRemaining()) 118 if (write_buffer_->BytesRemaining())
108 Write(); 119 Write();
109 } 120 }
110 121
122 void Read(const base::Closure& quit_loop) {
123 read_buffer_ = new IOBufferWithSize(kMaxExpectedResponseLength);
124 int result = socket_->Read(read_buffer_, kMaxExpectedResponseLength,
mef 2014/03/27 15:03:45 nit: I believe kMaxExpectedResponseLength goes on
gunsch 2014/03/27 15:52:39 Done.
125 base::Bind(&TestHttpClient::OnRead,
126 base::Unretained(this),
127 quit_loop));
128 if (result != ERR_IO_PENDING)
129 OnRead(quit_loop, result);
130 }
131
132 void OnRead(const base::Closure& quit_loop, int result) {
133 bytes_received_ = result;
134 quit_loop.Run();
135 }
136
137 base::Closure run_loop_quit_func_;
Ryan Sleevi 2014/03/27 20:59:46 You shouldn't need this separate RunLoop helper. Y
gunsch 2014/03/27 23:41:17 Done, thanks for the tip. That's a lot simpler.
138 scoped_refptr<IOBufferWithSize> read_buffer_;
111 scoped_refptr<DrainableIOBuffer> write_buffer_; 139 scoped_refptr<DrainableIOBuffer> write_buffer_;
112 scoped_ptr<TCPClientSocket> socket_; 140 scoped_ptr<TCPClientSocket> socket_;
141 int bytes_received_;
113 int connect_result_; 142 int connect_result_;
114 }; 143 };
115 144
116 } // namespace 145 } // namespace
117 146
118 class HttpServerTest : public testing::Test, 147 class HttpServerTest : public testing::Test,
119 public HttpServer::Delegate { 148 public HttpServer::Delegate {
120 public: 149 public:
121 HttpServerTest() : quit_after_request_count_(0) {} 150 HttpServerTest() : quit_after_request_count_(0) {}
122 151
123 virtual void SetUp() OVERRIDE { 152 virtual void SetUp() OVERRIDE {
124 TCPListenSocketFactory socket_factory("127.0.0.1", 0); 153 TCPListenSocketFactory socket_factory("127.0.0.1", 0);
125 server_ = new HttpServer(socket_factory, this); 154 server_ = new HttpServer(socket_factory, this);
126 ASSERT_EQ(OK, server_->GetLocalAddress(&server_address_)); 155 ASSERT_EQ(OK, server_->GetLocalAddress(&server_address_));
127 } 156 }
128 157
129 virtual void OnHttpRequest(int connection_id, 158 virtual void OnHttpRequest(int connection_id,
130 const HttpServerRequestInfo& info) OVERRIDE { 159 const HttpServerRequestInfo& info) OVERRIDE {
131 requests_.push_back(info); 160 requests_.push_back(info);
161 connection_ids_.push_back(connection_id);
132 if (requests_.size() == quit_after_request_count_) 162 if (requests_.size() == quit_after_request_count_)
133 run_loop_quit_func_.Run(); 163 run_loop_quit_func_.Run();
134 } 164 }
135 165
136 virtual void OnWebSocketRequest(int connection_id, 166 virtual void OnWebSocketRequest(int connection_id,
137 const HttpServerRequestInfo& info) OVERRIDE { 167 const HttpServerRequestInfo& info) OVERRIDE {
138 NOTREACHED(); 168 NOTREACHED();
139 } 169 }
140 170
141 virtual void OnWebSocketMessage(int connection_id, 171 virtual void OnWebSocketMessage(int connection_id,
142 const std::string& data) OVERRIDE { 172 const std::string& data) OVERRIDE {
143 NOTREACHED(); 173 NOTREACHED();
144 } 174 }
145 175
146 virtual void OnClose(int connection_id) OVERRIDE {} 176 virtual void OnClose(int connection_id) OVERRIDE {}
mef 2014/03/27 15:03:45 Should it remove the |connection_id| from |connect
gunsch 2014/03/27 15:52:39 I lean towards _no_, to keep |requests_| and |conn
147 177
148 bool RunUntilRequestsReceived(size_t count) { 178 bool RunUntilRequestsReceived(size_t count) {
149 quit_after_request_count_ = count; 179 quit_after_request_count_ = count;
150 if (requests_.size() == count) 180 if (requests_.size() == count)
151 return true; 181 return true;
152 182
153 base::RunLoop run_loop; 183 base::RunLoop run_loop;
154 run_loop_quit_func_ = run_loop.QuitClosure(); 184 run_loop_quit_func_ = run_loop.QuitClosure();
155 bool success = RunLoopWithTimeout(&run_loop); 185 bool success = RunLoopWithTimeout(&run_loop);
156 run_loop_quit_func_.Reset(); 186 run_loop_quit_func_.Reset();
157 return success; 187 return success;
158 } 188 }
159 189
160 protected: 190 protected:
161 scoped_refptr<HttpServer> server_; 191 scoped_refptr<HttpServer> server_;
162 IPEndPoint server_address_; 192 IPEndPoint server_address_;
163 base::Closure run_loop_quit_func_; 193 base::Closure run_loop_quit_func_;
164 std::vector<HttpServerRequestInfo> requests_; 194 std::vector<HttpServerRequestInfo> requests_;
195 std::vector<int> connection_ids_;
165 196
166 private: 197 private:
167 size_t quit_after_request_count_; 198 size_t quit_after_request_count_;
168 }; 199 };
169 200
170 TEST_F(HttpServerTest, Request) { 201 TEST_F(HttpServerTest, Request) {
171 TestHttpClient client; 202 TestHttpClient client;
172 ASSERT_EQ(OK, client.ConnectAndWait(server_address_)); 203 ASSERT_EQ(OK, client.ConnectAndWait(server_address_));
173 client.Send("GET /test HTTP/1.1\r\n\r\n"); 204 client.Send("GET /test HTTP/1.1\r\n\r\n");
174 ASSERT_TRUE(RunUntilRequestsReceived(1)); 205 ASSERT_TRUE(RunUntilRequestsReceived(1));
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 &delegate)); 285 &delegate));
255 fetcher->SetRequestContext(request_context_getter.get()); 286 fetcher->SetRequestContext(request_context_getter.get());
256 fetcher->AddExtraRequestHeader( 287 fetcher->AddExtraRequestHeader(
257 base::StringPrintf("content-length:%d", 1 << 30)); 288 base::StringPrintf("content-length:%d", 1 << 30));
258 fetcher->Start(); 289 fetcher->Start();
259 290
260 ASSERT_TRUE(RunLoopWithTimeout(&run_loop)); 291 ASSERT_TRUE(RunLoopWithTimeout(&run_loop));
261 ASSERT_EQ(0u, requests_.size()); 292 ASSERT_EQ(0u, requests_.size());
262 } 293 }
263 294
295 TEST_F(HttpServerTest, Send200) {
296 TestHttpClient client;
297 ASSERT_EQ(OK, client.ConnectAndWait(server_address_));
298 client.Send("GET /test HTTP/1.1\r\n\r\n");
299 ASSERT_TRUE(RunUntilRequestsReceived(1));
300 server_->Send200(connection_ids_[0], "Response!", "text/plain");
301
302 std::string response;
303 ASSERT_TRUE(client.Read(&response));
304 ASSERT_TRUE(StartsWithASCII(response, "HTTP/1.1 200 OK", true));
305 ASSERT_TRUE(response.find("Response!") != std::string::npos);
306 }
307
308 TEST_F(HttpServerTest, SendRaw) {
309 TestHttpClient client;
310 ASSERT_EQ(OK, client.ConnectAndWait(server_address_));
311 client.Send("GET /test HTTP/1.1\r\n\r\n");
312 ASSERT_TRUE(RunUntilRequestsReceived(1));
313 server_->SendRaw(connection_ids_[0], "Raw Data ");
314 server_->SendRaw(connection_ids_[0], "More Data");
315 server_->SendRaw(connection_ids_[0], "Third Piece of Data");
316
317 std::string response;
318 ASSERT_TRUE(client.Read(&response));
mef 2014/03/27 15:03:45 Would it make sense to also test a scenario where
gunsch 2014/03/27 15:52:39 Sure, I extended the MultipleRequestsOnSameConnect
gunsch 2014/03/27 18:40:32 I just went ahead and made this a std::pair. I thi
319 ASSERT_EQ("Raw Data More DataThird Piece of Data", response);
320 }
321
264 namespace { 322 namespace {
265 323
266 class MockStreamListenSocket : public StreamListenSocket { 324 class MockStreamListenSocket : public StreamListenSocket {
267 public: 325 public:
268 MockStreamListenSocket(StreamListenSocket::Delegate* delegate) 326 MockStreamListenSocket(StreamListenSocket::Delegate* delegate)
269 : StreamListenSocket(kInvalidSocket, delegate) {} 327 : StreamListenSocket(kInvalidSocket, delegate) {}
270 328
271 virtual void Accept() OVERRIDE { NOTREACHED(); } 329 virtual void Accept() OVERRIDE { NOTREACHED(); }
272 330
273 private: 331 private:
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 client.Send("GET /test2 HTTP/1.1\r\n\r\n"); 369 client.Send("GET /test2 HTTP/1.1\r\n\r\n");
312 ASSERT_TRUE(RunUntilRequestsReceived(2)); 370 ASSERT_TRUE(RunUntilRequestsReceived(2));
313 ASSERT_EQ("/test2", requests_[1].path); 371 ASSERT_EQ("/test2", requests_[1].path);
314 372
315 client.Send("GET /test3 HTTP/1.1\r\n\r\n"); 373 client.Send("GET /test3 HTTP/1.1\r\n\r\n");
316 ASSERT_TRUE(RunUntilRequestsReceived(3)); 374 ASSERT_TRUE(RunUntilRequestsReceived(3));
317 ASSERT_EQ("/test3", requests_[2].path); 375 ASSERT_EQ("/test3", requests_[2].path);
318 } 376 }
319 377
320 } // namespace net 378 } // namespace net
OLDNEW
« no previous file with comments | « net/server/http_server.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698