1 // Copyright 2014 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. 4 5 #include "chrome/browser/bitmap_fetcher/bitmap_fetcher_service.h" 6 7 #include "chrome/browser/bitmap_fetcher/bitmap_fetcher.h" 8 #include "chrome/test/base/testing_profile.h" 9 #include "testing/gtest/include/gtest/gtest.h" 10 11 namespace { 12 13 class TestNotificationInterface { 14 public: 15 virtual ~TestNotificationInterface() {} 16 virtual void OnImageChanged() = 0; 17 virtual void OnRequestFinished() = 0; 18 }; 19 20 class TestObserver : public BitmapFetcherService::Observer { 21 public: 22 explicit TestObserver(TestNotificationInterface* target) : target_(target) {} 23 virtual ~TestObserver() { target_->OnRequestFinished(); } 24 25 virtual void OnImageChanged(BitmapFetcherService::RequestId request_id, 26 const SkBitmap& answers_image) OVERRIDE { 27 target_->OnImageChanged(); 28 } 29 30 TestNotificationInterface* target_; 31 }; 32 33 class TestService : public BitmapFetcherService { 34 public: 35 explicit TestService(content::BrowserContext* context) 36 : BitmapFetcherService(context) {} 37 virtual ~TestService() {} 38 39 // Create a fetcher, but don't start downloading. That allows side-stepping 40 // the decode step, which requires a utility process. 41 virtual chrome::BitmapFetcher* CreateFetcher(const GURL& url) OVERRIDE { 42 return new chrome::BitmapFetcher(url, this); 43 } 44 }; 45 46 } // namespace 47 48 class BitmapFetcherServiceTest : public testing::Test, 49 public TestNotificationInterface { 50 public: 51 virtual void SetUp() OVERRIDE { 52 service_.reset(new TestService(&profile_)); 53 requestsFinished_ = 0; 54 imagesChanged_ = 0; 55 url1_ = GURL("http://example.org/sample-image-1.png"); 56 url2_ = GURL("http://example.org/sample-image-2.png"); 57 } 58 59 const ScopedVector<BitmapFetcherRequest>& requests() { 60 return service_->requests_; 61 } 62 const ScopedVector<chrome::BitmapFetcher>& active_fetchers() { 63 return service_->active_fetchers_; 64 } 65 size_t cache_size() { return service_->cache_.size(); } 66 67 virtual void OnImageChanged() OVERRIDE { imagesChanged_++; } 68 69 virtual void OnRequestFinished() OVERRIDE { requestsFinished_++; } 70 71 // Simulate finishing a URL fetch and decode for the given fetcher. 72 void CompleteFetch(const GURL& url) { 73 const chrome::BitmapFetcher* fetcher = service_->FindFetcherForUrl(url); 74 ASSERT_TRUE(NULL != fetcher); 75 76 // Create a non-empty bitmap. 77 SkBitmap image; 78 image.allocN32Pixels(2, 2); 79 image.eraseColor(SK_ColorGREEN); 80 81 const_cast<chrome::BitmapFetcher*>(fetcher)->OnImageDecoded(NULL, image); 82 } 83 84 void FailFetch(const GURL& url) { 85 const chrome::BitmapFetcher* fetcher = service_->FindFetcherForUrl(url); 86 ASSERT_TRUE(NULL != fetcher); 87 const_cast<chrome::BitmapFetcher*>(fetcher) 88 ->OnImageDecoded(NULL, SkBitmap()); 89 } 90 91 protected: 92 scoped_ptr<BitmapFetcherService> service_; 93 94 int imagesChanged_; 95 int requestsFinished_; 96 97 GURL url1_; 98 GURL url2_; 99 100 private: 101 TestingProfile profile_; 102 }; 103 104 TEST_F(BitmapFetcherServiceTest, RequestInvalidUrl) { 105 const BitmapFetcherService::RequestId invalid_request_id = 106 BitmapFetcherService::REQUEST_ID_INVALID; 107 GURL invalid_url; 108 ASSERT_FALSE(invalid_url.is_valid()); 109 110 BitmapFetcherService::RequestId request_id = 111 service_->RequestImage(invalid_url, new TestObserver(this)); 112 EXPECT_EQ(invalid_request_id, request_id); 113 } 114 115 TEST_F(BitmapFetcherServiceTest, CancelInvalidRequest) { 116 service_->CancelRequest(BitmapFetcherService::REQUEST_ID_INVALID); 117 service_->CancelRequest(23); 118 } 119 120 TEST_F(BitmapFetcherServiceTest, OnlyFirstRequestCreatesFetcher) { 121 EXPECT_EQ(0U, active_fetchers().size()); 122 123 service_->RequestImage(url1_, new TestObserver(this)); 124 EXPECT_EQ(1U, active_fetchers().size()); 125 126 service_->RequestImage(url1_, new TestObserver(this)); 127 EXPECT_EQ(1U, active_fetchers().size()); 128 } 129 130 TEST_F(BitmapFetcherServiceTest, CompletedFetchNotifiesAllObservers) { 131 service_->RequestImage(url1_, new TestObserver(this)); 132 service_->RequestImage(url1_, new TestObserver(this)); 133 service_->RequestImage(url1_, new TestObserver(this)); 134 service_->RequestImage(url1_, new TestObserver(this)); 135 EXPECT_EQ(1U, active_fetchers().size()); 136 EXPECT_EQ(4U, requests().size()); 137 138 CompleteFetch(url1_); 139 EXPECT_EQ(4, imagesChanged_); 140 EXPECT_EQ(4, requestsFinished_); 141 } 142 143 TEST_F(BitmapFetcherServiceTest, CancelRequest) { 144 service_->RequestImage(url1_, new TestObserver(this)); 145 service_->RequestImage(url1_, new TestObserver(this)); 146 BitmapFetcherService::RequestId requestId = 147 service_->RequestImage(url2_, new TestObserver(this)); 148 service_->RequestImage(url1_, new TestObserver(this)); 149 service_->RequestImage(url1_, new TestObserver(this)); 150 EXPECT_EQ(5U, requests().size()); 151 152 service_->CancelRequest(requestId); 153 EXPECT_EQ(4U, requests().size()); 154 155 CompleteFetch(url2_); 156 EXPECT_EQ(0, imagesChanged_); 157 158 CompleteFetch(url1_); 159 EXPECT_EQ(4, imagesChanged_); 160 } 161 162 TEST_F(BitmapFetcherServiceTest, FailedRequestsDontEnterCache) { 163 service_->RequestImage(url1_, new TestObserver(this)); 164 service_->RequestImage(url2_, new TestObserver(this)); 165 EXPECT_EQ(0U, cache_size()); 166 167 CompleteFetch(url1_); 168 EXPECT_EQ(1U, cache_size()); 169 170 FailFetch(url2_); 171 EXPECT_EQ(1U, cache_size()); 172 } 173