blob: a1a32da2e79fef1cf9ae57fd472e8b94fe08954a [file] [log] [blame]
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/message_loop.h"
#include "base/scoped_ptr.h"
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/renderer_host/global_request_id.h"
#include "chrome/browser/renderer_host/resource_dispatcher_host_request_info.h"
#include "chrome/browser/renderer_host/resource_handler.h"
#include "chrome/browser/renderer_host/resource_queue.h"
#include "googleurl/src/gurl.h"
#include "net/url_request/url_request.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
const char kTestUrl[] = "data:text/plain,Hello World!";
class DummyResourceHandler : public ResourceHandler {
public:
DummyResourceHandler() {
}
bool OnUploadProgress(int request_id, uint64 position, uint64 size) {
NOTREACHED();
return true;
}
virtual bool OnRequestRedirected(int request_id, const GURL& url,
ResourceResponse* response,
bool* defer) {
NOTREACHED();
return true;
}
virtual bool OnResponseStarted(int request_id,
ResourceResponse* response) {
NOTREACHED();
return true;
}
virtual bool OnWillStart(int request_id, const GURL& url, bool* defer) {
NOTREACHED();
return true;
}
virtual bool OnWillRead(int request_id,
net::IOBuffer** buf,
int* buf_size,
int min_size) {
NOTREACHED();
return true;
}
virtual bool OnReadCompleted(int request_id, int* bytes_read) {
NOTREACHED();
return true;
}
virtual bool OnResponseCompleted(int request_id,
const net::URLRequestStatus& status,
const std::string& security_info) {
NOTREACHED();
return true;
}
virtual void OnRequestClosed() {
}
private:
DISALLOW_COPY_AND_ASSIGN(DummyResourceHandler);
};
ResourceDispatcherHostRequestInfo* GetRequestInfo(int request_id) {
return new ResourceDispatcherHostRequestInfo(
new DummyResourceHandler(), ChildProcessInfo::RENDER_PROCESS, 0, 0,
request_id, "null", "null", ResourceType::MAIN_FRAME,
0, false, false, false, -1, -1);
}
void InitializeQueue(ResourceQueue* queue, ResourceQueueDelegate* delegate) {
ResourceQueue::DelegateSet delegate_set;
delegate_set.insert(delegate);
queue->Initialize(delegate_set);
}
void InitializeQueue(ResourceQueue* queue,
ResourceQueueDelegate* delegate1,
ResourceQueueDelegate* delegate2) {
ResourceQueue::DelegateSet delegate_set;
delegate_set.insert(delegate1);
delegate_set.insert(delegate2);
queue->Initialize(delegate_set);
}
class NeverDelayingDelegate : public ResourceQueueDelegate {
public:
NeverDelayingDelegate() {
}
virtual bool ShouldDelayRequest(
net::URLRequest* request,
const ResourceDispatcherHostRequestInfo& request_info,
const GlobalRequestID& request_id) {
return false;
}
virtual void WillShutdownResourceQueue() {
}
private:
DISALLOW_COPY_AND_ASSIGN(NeverDelayingDelegate);
};
class AlwaysDelayingDelegate : public ResourceQueueDelegate {
public:
explicit AlwaysDelayingDelegate(ResourceQueue* resource_queue)
: resource_queue_(resource_queue) {
}
virtual bool ShouldDelayRequest(
net::URLRequest* request,
const ResourceDispatcherHostRequestInfo& request_info,
const GlobalRequestID& request_id) {
delayed_requests_.push_back(request_id);
return true;
}
virtual void WillShutdownResourceQueue() {
resource_queue_ = NULL;
}
void StartDelayedRequests() {
if (!resource_queue_)
return;
for (RequestList::iterator i = delayed_requests_.begin();
i != delayed_requests_.end(); ++i) {
resource_queue_->StartDelayedRequest(this, *i);
}
}
private:
typedef std::vector<GlobalRequestID> RequestList;
ResourceQueue* resource_queue_;
RequestList delayed_requests_;
DISALLOW_COPY_AND_ASSIGN(AlwaysDelayingDelegate);
};
class ResourceQueueTest : public testing::Test,
public net::URLRequest::Delegate {
public:
ResourceQueueTest()
: response_started_count_(0),
message_loop_(MessageLoop::TYPE_IO),
ui_thread_(BrowserThread::UI, &message_loop_),
io_thread_(BrowserThread::IO, &message_loop_) {
}
virtual void OnResponseStarted(net::URLRequest* request) {
response_started_count_++;
// We're not going to do anything more with the request. Cancel it now
// to avoid leaking net::URLRequestJob.
request->Cancel();
}
virtual void OnReadCompleted(net::URLRequest* request, int bytes_read) {
}
protected:
int response_started_count_;
private:
MessageLoop message_loop_;
BrowserThread ui_thread_;
BrowserThread io_thread_;
};
TEST_F(ResourceQueueTest, Basic) {
// Test the simplest lifycycle of ResourceQueue.
ResourceQueue queue;
queue.Initialize(ResourceQueue::DelegateSet());
queue.Shutdown();
}
TEST_F(ResourceQueueTest, NeverDelayingDelegate) {
ResourceQueue queue;
NeverDelayingDelegate delegate;
InitializeQueue(&queue, &delegate);
net::URLRequest request(GURL(kTestUrl), this);
scoped_ptr<ResourceDispatcherHostRequestInfo> request_info(GetRequestInfo(0));
EXPECT_EQ(0, response_started_count_);
queue.AddRequest(&request, *request_info.get());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(1, response_started_count_);
queue.Shutdown();
}
TEST_F(ResourceQueueTest, AlwaysDelayingDelegate) {
ResourceQueue queue;
AlwaysDelayingDelegate delegate(&queue);
InitializeQueue(&queue, &delegate);
net::URLRequest request(GURL(kTestUrl), this);
scoped_ptr<ResourceDispatcherHostRequestInfo> request_info(GetRequestInfo(0));
EXPECT_EQ(0, response_started_count_);
queue.AddRequest(&request, *request_info.get());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(0, response_started_count_);
delegate.StartDelayedRequests();
MessageLoop::current()->RunAllPending();
EXPECT_EQ(1, response_started_count_);
queue.Shutdown();
}
TEST_F(ResourceQueueTest, AlwaysDelayingDelegateAfterShutdown) {
ResourceQueue queue;
AlwaysDelayingDelegate delegate(&queue);
InitializeQueue(&queue, &delegate);
net::URLRequest request(GURL(kTestUrl), this);
scoped_ptr<ResourceDispatcherHostRequestInfo> request_info(GetRequestInfo(0));
EXPECT_EQ(0, response_started_count_);
queue.AddRequest(&request, *request_info.get());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(0, response_started_count_);
queue.Shutdown();
delegate.StartDelayedRequests();
MessageLoop::current()->RunAllPending();
EXPECT_EQ(0, response_started_count_);
}
TEST_F(ResourceQueueTest, TwoDelegates) {
ResourceQueue queue;
AlwaysDelayingDelegate always_delaying_delegate(&queue);
NeverDelayingDelegate never_delaying_delegate;
InitializeQueue(&queue, &always_delaying_delegate, &never_delaying_delegate);
net::URLRequest request(GURL(kTestUrl), this);
scoped_ptr<ResourceDispatcherHostRequestInfo> request_info(GetRequestInfo(0));
EXPECT_EQ(0, response_started_count_);
queue.AddRequest(&request, *request_info.get());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(0, response_started_count_);
always_delaying_delegate.StartDelayedRequests();
MessageLoop::current()->RunAllPending();
EXPECT_EQ(1, response_started_count_);
queue.Shutdown();
}
TEST_F(ResourceQueueTest, RemoveRequest) {
ResourceQueue queue;
AlwaysDelayingDelegate delegate(&queue);
InitializeQueue(&queue, &delegate);
net::URLRequest request(GURL(kTestUrl), this);
scoped_ptr<ResourceDispatcherHostRequestInfo> request_info(GetRequestInfo(0));
GlobalRequestID request_id(request_info->child_id(),
request_info->request_id());
EXPECT_EQ(0, response_started_count_);
queue.AddRequest(&request, *request_info.get());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(0, response_started_count_);
queue.RemoveRequest(request_id);
delegate.StartDelayedRequests();
MessageLoop::current()->RunAllPending();
EXPECT_EQ(0, response_started_count_);
queue.Shutdown();
MessageLoop::current()->RunAllPending();
EXPECT_EQ(0, response_started_count_);
}
} // namespace