resource_fetcher_unittest.cc revision 72a454cd3513ac24fbdd0e0cb9ad70b86a99b801
1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "webkit/glue/resource_fetcher.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/callback.h" 83345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/message_loop.h" 972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/timer.h" 1072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" 1172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h" 1272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "webkit/glue/unittest_test_server.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "webkit/tools/test_shell/simple_resource_loader_bridge.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "webkit/tools/test_shell/test_shell_test.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebFrame; 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebURLResponse; 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing webkit_glue::ResourceFetcher; 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing webkit_glue::ResourceFetcherWithTimeout; 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass ResourceFetcherTests : public TestShellTest { 253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick protected: 263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick UnittestTestServer test_server_; 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kMaxWaitTimeMs = 5000; 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass FetcherDelegate { 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FetcherDelegate() 3472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen : completed_(false), 3572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen timed_out_(false) { 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Start a repeating timer waiting for the download to complete. The 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // callback has to be a static function, so we hold on to our instance. 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FetcherDelegate::instance_ = this; 3972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen StartTimer(); 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ResourceFetcher::Callback* NewCallback() { 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ::NewCallback(this, &FetcherDelegate::OnURLFetchComplete); 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen virtual void OnURLFetchComplete(const WebURLResponse& response, 4772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const std::string& data) { 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch response_ = response; 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data_ = data; 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch completed_ = true; 5172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen timer_.Stop(); 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->Quit(); 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool completed() const { return completed_; } 5672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen bool timed_out() const { return timed_out_; } 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string data() const { return data_; } 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const WebURLResponse& response() const { return response_; } 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Wait for the request to complete or timeout. We use a loop here b/c the 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // testing infrastructure (test_shell) can generate spurious calls to the 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // MessageLoop's Quit method. 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void WaitForResponse() { 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (!completed() && !timed_out()) 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->Run(); 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 6972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen void StartTimer() { 7072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen timer_.Start(base::TimeDelta::FromMilliseconds(kMaxWaitTimeMs), 7172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this, 7272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen &FetcherDelegate::TimerFired); 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void TimerFired() { 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_FALSE(completed_); 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen timed_out_ = true; 7972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen MessageLoop::current()->Quit(); 8072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen FAIL() << "fetch timed out"; 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static FetcherDelegate* instance_; 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 8672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::OneShotTimer<FetcherDelegate> timer_; 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool completed_; 8872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen bool timed_out_; 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WebURLResponse response_; 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string data_; 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochFetcherDelegate* FetcherDelegate::instance_ = NULL; 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Test a fetch from the test server. 96731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Flaky, http://crbug.com/51622. 97731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickTEST_F(ResourceFetcherTests, FLAKY_ResourceFetcherDownload) { 983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASSERT_TRUE(test_server_.Start()); 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WebFrame* frame = test_shell_->webView()->mainFrame(); 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GURL url(test_server_.GetURL("files/test_shell/index.html")); 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate); 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcher( 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url, frame, delegate->NewCallback())); 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate->WaitForResponse(); 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(delegate->completed()); 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(delegate->response().httpStatusCode(), 200); 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string text = delegate->data(); 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(text.find("What is this page?") != std::string::npos); 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Test 404 response. 1153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick url = test_server_.GetURL("files/thisfiledoesntexist.html"); 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate.reset(new FetcherDelegate); 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch fetcher.reset(new ResourceFetcher(url, frame, delegate->NewCallback())); 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate->WaitForResponse(); 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(delegate->completed()); 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(delegate->response().httpStatusCode(), 404); 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(delegate->data().find("Not Found.") != std::string::npos); 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 126731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Flaky, http://crbug.com/51622. 127731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickTEST_F(ResourceFetcherTests, FLAKY_ResourceFetcherDidFail) { 1283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASSERT_TRUE(test_server_.Start()); 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WebFrame* frame = test_shell_->webView()->mainFrame(); 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Try to fetch a page on a site that doesn't exist. 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL url("http://localhost:1339/doesnotexist"); 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate); 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcher( 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url, frame, delegate->NewCallback())); 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate->WaitForResponse(); 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When we fail, we still call the Delegate callback but we pass in empty 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // values. 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(delegate->completed()); 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(delegate->response().isNull()); 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(delegate->data(), std::string()); 14572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EXPECT_FALSE(delegate->timed_out()); 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(ResourceFetcherTests, ResourceFetcherTimeout) { 1493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASSERT_TRUE(test_server_.Start()); 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WebFrame* frame = test_shell_->webView()->mainFrame(); 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Grab a page that takes at least 1 sec to respond, but set the fetcher to 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // timeout in 0 sec. 1553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GURL url(test_server_.GetURL("slow?1")); 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate); 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcherWithTimeout( 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url, frame, 0, delegate->NewCallback())); 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate->WaitForResponse(); 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When we timeout, we still call the Delegate callback but we pass in empty 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // values. 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(delegate->completed()); 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(delegate->response().isNull()); 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(delegate->data(), std::string()); 16772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EXPECT_FALSE(delegate->timed_out()); 16872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 16972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 17072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenclass EvilFetcherDelegate : public FetcherDelegate { 17172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen public: 17272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen void SetFetcher(ResourceFetcher* fetcher) { 17372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen fetcher_.reset(fetcher); 17472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 17572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 17672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen void OnURLFetchComplete(const WebURLResponse& response, 17772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const std::string& data) { 17872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Destroy the ResourceFetcher here. We are testing that upon returning 17972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // to the ResourceFetcher that it does not crash. 18072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen fetcher_.reset(); 18172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen FetcherDelegate::OnURLFetchComplete(response, data); 18272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 18372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 18472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen private: 18572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen scoped_ptr<ResourceFetcher> fetcher_; 18672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}; 18772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 18872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenTEST_F(ResourceFetcherTests, ResourceFetcherDeletedInCallback) { 18972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ASSERT_TRUE(test_server_.Start()); 19072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 19172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen WebFrame* frame = test_shell_->webView()->mainFrame(); 19272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 19372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Grab a page that takes at least 1 sec to respond, but set the fetcher to 19472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // timeout in 0 sec. 19572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen GURL url(test_server_.GetURL("slow?1")); 19672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen scoped_ptr<EvilFetcherDelegate> delegate(new EvilFetcherDelegate); 19772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcherWithTimeout( 19872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen url, frame, 0, delegate->NewCallback())); 19972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen delegate->SetFetcher(fetcher.release()); 20072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 20172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen delegate->WaitForResponse(); 20272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EXPECT_FALSE(delegate->timed_out()); 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace 206