Added unit test for DevTools' ephemeral port support.
[chromium-blink-merge.git] / content / child / resource_dispatcher_unittest.cc
blob6f48b709cded72994c4b1a0aa36ad5eae0da3f1f
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include <string>
6 #include <vector>
8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/process/process.h"
11 #include "base/process/process_handle.h"
12 #include "base/run_loop.h"
13 #include "content/child/request_extra_data.h"
14 #include "content/child/request_info.h"
15 #include "content/child/resource_dispatcher.h"
16 #include "content/common/resource_messages.h"
17 #include "content/common/service_worker/service_worker_types.h"
18 #include "content/public/child/request_peer.h"
19 #include "content/public/common/resource_response.h"
20 #include "net/base/net_errors.h"
21 #include "net/http/http_response_headers.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 #include "webkit/child/resource_loader_bridge.h"
24 #include "webkit/common/appcache/appcache_interfaces.h"
26 using webkit_glue::ResourceLoaderBridge;
28 namespace content {
30 static const char test_page_url[] = "http://www.google.com/";
31 static const char test_page_headers[] =
32 "HTTP/1.1 200 OK\nContent-Type:text/html\n\n";
33 static const char test_page_mime_type[] = "text/html";
34 static const char test_page_charset[] = "";
35 static const char test_page_contents[] =
36 "<html><head><title>Google</title></head><body><h1>Google</h1></body></html>";
37 static const uint32 test_page_contents_len = arraysize(test_page_contents) - 1;
39 // Listens for request response data and stores it so that it can be compared
40 // to the reference data.
41 class TestRequestCallback : public RequestPeer {
42 public:
43 TestRequestCallback() : complete_(false) {
46 virtual void OnUploadProgress(uint64 position, uint64 size) OVERRIDE {
49 virtual bool OnReceivedRedirect(const GURL& new_url,
50 const GURL& new_first_party_for_cookies,
51 const ResourceResponseInfo& info) OVERRIDE {
52 return true;
55 virtual void OnReceivedResponse(const ResourceResponseInfo& info) OVERRIDE {
58 virtual void OnDownloadedData(int len, int encoded_data_length) OVERRIDE {
61 virtual void OnReceivedData(const char* data,
62 int data_length,
63 int encoded_data_length) OVERRIDE {
64 EXPECT_FALSE(complete_);
65 data_.append(data, data_length);
66 total_encoded_data_length_ += encoded_data_length;
69 virtual void OnCompletedRequest(
70 int error_code,
71 bool was_ignored_by_handler,
72 bool stale_copy_in_cache,
73 const std::string& security_info,
74 const base::TimeTicks& completion_time,
75 int64 total_transfer_size) OVERRIDE {
76 EXPECT_FALSE(complete_);
77 complete_ = true;
80 bool complete() const {
81 return complete_;
83 const std::string& data() const {
84 return data_;
86 int total_encoded_data_length() const {
87 return total_encoded_data_length_;
90 private:
91 bool complete_;
92 std::string data_;
93 int total_encoded_data_length_;
97 // Sets up the message sender override for the unit test
98 class ResourceDispatcherTest : public testing::Test, public IPC::Sender {
99 public:
100 // Emulates IPC send operations (IPC::Sender) by adding
101 // pending messages to the queue.
102 virtual bool Send(IPC::Message* msg) OVERRIDE {
103 message_queue_.push_back(IPC::Message(*msg));
104 delete msg;
105 return true;
108 // Emulates the browser process and processes the pending IPC messages,
109 // returning the hardcoded file contents.
110 void ProcessMessages() {
111 while (!message_queue_.empty()) {
112 ResourceHostMsg_RequestResource::Param params;
113 ASSERT_TRUE(ResourceHostMsg_RequestResource::Read(
114 &message_queue_[0], &params));
115 int request_id = params.b;
116 ResourceHostMsg_Request request = params.c;
118 // check values
119 EXPECT_EQ(test_page_url, request.url.spec());
121 // received response message
122 ResourceResponseHead response;
123 std::string raw_headers(test_page_headers);
124 std::replace(raw_headers.begin(), raw_headers.end(), '\n', '\0');
125 response.headers = new net::HttpResponseHeaders(raw_headers);
126 response.mime_type = test_page_mime_type;
127 response.charset = test_page_charset;
128 dispatcher_->OnReceivedResponse(request_id, response);
130 // received data message with the test contents
131 base::SharedMemory shared_mem;
132 EXPECT_TRUE(shared_mem.CreateAndMapAnonymous(test_page_contents_len));
133 char* put_data_here = static_cast<char*>(shared_mem.memory());
134 memcpy(put_data_here, test_page_contents, test_page_contents_len);
135 base::SharedMemoryHandle dup_handle;
136 EXPECT_TRUE(shared_mem.GiveToProcess(
137 base::Process::Current().handle(), &dup_handle));
138 dispatcher_->OnSetDataBuffer(request_id, dup_handle,
139 test_page_contents_len, 0);
140 dispatcher_->OnReceivedData(request_id, 0, test_page_contents_len,
141 test_page_contents_len);
143 message_queue_.erase(message_queue_.begin());
145 // read the ack message.
146 Tuple1<int> request_ack;
147 ASSERT_TRUE(ResourceHostMsg_DataReceived_ACK::Read(
148 &message_queue_[0], &request_ack));
150 ASSERT_EQ(request_ack.a, request_id);
152 message_queue_.erase(message_queue_.begin());
156 protected:
157 // testing::Test
158 virtual void SetUp() OVERRIDE {
159 dispatcher_.reset(new ResourceDispatcher(this));
161 virtual void TearDown() OVERRIDE {
162 dispatcher_.reset();
165 ResourceLoaderBridge* CreateBridge() {
166 RequestInfo request_info;
167 request_info.method = "GET";
168 request_info.url = GURL(test_page_url);
169 request_info.first_party_for_cookies = GURL(test_page_url);
170 request_info.referrer = GURL();
171 request_info.headers = std::string();
172 request_info.load_flags = 0;
173 request_info.requestor_pid = 0;
174 request_info.request_type = ResourceType::SUB_RESOURCE;
175 request_info.appcache_host_id = appcache::kNoHostId;
176 request_info.routing_id = 0;
177 RequestExtraData extra_data;
178 request_info.extra_data = &extra_data;
180 return dispatcher_->CreateBridge(request_info);
183 std::vector<IPC::Message> message_queue_;
184 static scoped_ptr<ResourceDispatcher> dispatcher_;
187 /*static*/
188 scoped_ptr<ResourceDispatcher> ResourceDispatcherTest::dispatcher_;
190 // Does a simple request and tests that the correct data is received.
191 TEST_F(ResourceDispatcherTest, RoundTrip) {
192 TestRequestCallback callback;
193 scoped_ptr<ResourceLoaderBridge> bridge(CreateBridge());
195 bridge->Start(&callback);
197 ProcessMessages();
199 // FIXME(brettw) when the request complete messages are actually handledo
200 // and dispatched, uncomment this.
201 //EXPECT_TRUE(callback.complete());
202 //EXPECT_STREQ(test_page_contents, callback.data().c_str());
203 //EXPECT_EQ(test_page_contents_len, callback.total_encoded_data_length());
206 // Tests that the request IDs are straight when there are multiple requests.
207 TEST_F(ResourceDispatcherTest, MultipleRequests) {
208 // FIXME
211 // Tests that the cancel method prevents other messages from being received
212 TEST_F(ResourceDispatcherTest, Cancel) {
213 // FIXME
216 TEST_F(ResourceDispatcherTest, Cookies) {
217 // FIXME
220 TEST_F(ResourceDispatcherTest, SerializedPostData) {
221 // FIXME
224 // This class provides functionality to validate whether the ResourceDispatcher
225 // object honors the deferred loading contract correctly, i.e. if deferred
226 // loading is enabled it should queue up any responses received. If deferred
227 // loading is enabled/disabled in the context of a dispatched message, other
228 // queued messages should not be dispatched until deferred load is turned off.
229 class DeferredResourceLoadingTest : public ResourceDispatcherTest,
230 public RequestPeer {
231 public:
232 DeferredResourceLoadingTest()
233 : defer_loading_(false) {
236 virtual bool Send(IPC::Message* msg) OVERRIDE {
237 delete msg;
238 return true;
241 void InitMessages() {
242 set_defer_loading(true);
244 ResourceResponseHead response_head;
245 response_head.error_code = net::OK;
247 dispatcher_->OnMessageReceived(
248 ResourceMsg_ReceivedResponse(0, response_head));
250 // Duplicate the shared memory handle so both the test and the callee can
251 // close their copy.
252 base::SharedMemoryHandle duplicated_handle;
253 EXPECT_TRUE(shared_handle_.ShareToProcess(base::GetCurrentProcessHandle(),
254 &duplicated_handle));
256 dispatcher_->OnMessageReceived(
257 ResourceMsg_SetDataBuffer(0, duplicated_handle, 100, 0));
258 dispatcher_->OnMessageReceived(ResourceMsg_DataReceived(0, 0, 100, 100));
260 set_defer_loading(false);
263 // RequestPeer methods.
264 virtual void OnUploadProgress(uint64 position, uint64 size) OVERRIDE {
267 virtual bool OnReceivedRedirect(const GURL& new_url,
268 const GURL& new_first_party_for_cookies,
269 const ResourceResponseInfo& info) OVERRIDE {
270 return true;
273 virtual void OnReceivedResponse(const ResourceResponseInfo& info) OVERRIDE {
274 EXPECT_EQ(defer_loading_, false);
275 set_defer_loading(true);
278 virtual void OnDownloadedData(int len, int encoded_data_length) OVERRIDE {
281 virtual void OnReceivedData(const char* data,
282 int data_length,
283 int encoded_data_length) OVERRIDE {
284 EXPECT_EQ(defer_loading_, false);
285 set_defer_loading(false);
288 virtual void OnCompletedRequest(
289 int error_code,
290 bool was_ignored_by_handler,
291 bool stale_copy_in_cache,
292 const std::string& security_info,
293 const base::TimeTicks& completion_time,
294 int64 total_transfer_size) OVERRIDE {
297 protected:
298 virtual void SetUp() OVERRIDE {
299 ResourceDispatcherTest::SetUp();
300 EXPECT_TRUE(shared_handle_.CreateAnonymous(100));
303 virtual void TearDown() OVERRIDE {
304 shared_handle_.Close();
305 ResourceDispatcherTest::TearDown();
308 private:
309 void set_defer_loading(bool defer) {
310 defer_loading_ = defer;
311 dispatcher_->SetDefersLoading(0, defer);
314 bool defer_loading() const {
315 return defer_loading_;
318 bool defer_loading_;
319 base::SharedMemory shared_handle_;
322 TEST_F(DeferredResourceLoadingTest, DeferredLoadTest) {
323 base::MessageLoopForIO message_loop;
325 scoped_ptr<ResourceLoaderBridge> bridge(CreateBridge());
327 bridge->Start(this);
328 InitMessages();
330 // Dispatch deferred messages.
331 base::RunLoop().RunUntilIdle();
334 class TimeConversionTest : public ResourceDispatcherTest,
335 public RequestPeer {
336 public:
337 virtual bool Send(IPC::Message* msg) OVERRIDE {
338 delete msg;
339 return true;
342 void PerformTest(const ResourceResponseHead& response_head) {
343 scoped_ptr<ResourceLoaderBridge> bridge(CreateBridge());
344 bridge->Start(this);
346 dispatcher_->OnMessageReceived(
347 ResourceMsg_ReceivedResponse(0, response_head));
350 // RequestPeer methods.
351 virtual void OnUploadProgress(uint64 position, uint64 size) OVERRIDE {
354 virtual bool OnReceivedRedirect(const GURL& new_url,
355 const GURL& new_first_party_for_cookies,
356 const ResourceResponseInfo& info) OVERRIDE {
357 return true;
360 virtual void OnReceivedResponse(const ResourceResponseInfo& info) OVERRIDE {
361 response_info_ = info;
364 virtual void OnDownloadedData(int len, int encoded_data_length) OVERRIDE {
367 virtual void OnReceivedData(const char* data,
368 int data_length,
369 int encoded_data_length) OVERRIDE {
372 virtual void OnCompletedRequest(
373 int error_code,
374 bool was_ignored_by_handler,
375 bool stale_copy_in_cache,
376 const std::string& security_info,
377 const base::TimeTicks& completion_time,
378 int64 total_transfer_size) OVERRIDE {
381 const ResourceResponseInfo& response_info() const { return response_info_; }
383 private:
384 ResourceResponseInfo response_info_;
387 // TODO(simonjam): Enable this when 10829031 lands.
388 TEST_F(TimeConversionTest, DISABLED_ProperlyInitialized) {
389 ResourceResponseHead response_head;
390 response_head.error_code = net::OK;
391 response_head.request_start = base::TimeTicks::FromInternalValue(5);
392 response_head.response_start = base::TimeTicks::FromInternalValue(15);
393 response_head.load_timing.request_start_time = base::Time::Now();
394 response_head.load_timing.request_start =
395 base::TimeTicks::FromInternalValue(10);
396 response_head.load_timing.connect_timing.connect_start =
397 base::TimeTicks::FromInternalValue(13);
399 PerformTest(response_head);
401 EXPECT_LT(base::TimeTicks(), response_info().load_timing.request_start);
402 EXPECT_EQ(base::TimeTicks(),
403 response_info().load_timing.connect_timing.dns_start);
404 EXPECT_LE(response_head.load_timing.request_start,
405 response_info().load_timing.connect_timing.connect_start);
408 TEST_F(TimeConversionTest, PartiallyInitialized) {
409 ResourceResponseHead response_head;
410 response_head.error_code = net::OK;
411 response_head.request_start = base::TimeTicks::FromInternalValue(5);
412 response_head.response_start = base::TimeTicks::FromInternalValue(15);
414 PerformTest(response_head);
416 EXPECT_EQ(base::TimeTicks(), response_info().load_timing.request_start);
417 EXPECT_EQ(base::TimeTicks(),
418 response_info().load_timing.connect_timing.dns_start);
421 TEST_F(TimeConversionTest, NotInitialized) {
422 ResourceResponseHead response_head;
423 response_head.error_code = net::OK;
425 PerformTest(response_head);
427 EXPECT_EQ(base::TimeTicks(), response_info().load_timing.request_start);
428 EXPECT_EQ(base::TimeTicks(),
429 response_info().load_timing.connect_timing.dns_start);
432 } // namespace content