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

Side by Side Diff: components/doodle/doodle_service_unittest.cc

Issue 2886443002: [Doodle] Move image fetching from LogoBridge to DoodleService (Closed)
Patch Set: build Created 3 years, 7 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
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 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 "components/doodle/doodle_service.h" 5 #include "components/doodle/doodle_service.h"
6 6
7 #include <memory> 7 #include <memory>
8 #include <utility> 8 #include <utility>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/memory/ptr_util.h" 12 #include "base/memory/ptr_util.h"
13 #include "base/memory/ref_counted.h" 13 #include "base/memory/ref_counted.h"
14 #include "base/test/histogram_tester.h" 14 #include "base/test/histogram_tester.h"
15 #include "base/test/mock_callback.h"
15 #include "base/test/simple_test_tick_clock.h" 16 #include "base/test/simple_test_tick_clock.h"
16 #include "base/test/test_mock_time_task_runner.h" 17 #include "base/test/test_mock_time_task_runner.h"
17 #include "base/threading/thread_task_runner_handle.h" 18 #include "base/threading/thread_task_runner_handle.h"
18 #include "base/time/time.h" 19 #include "base/time/time.h"
20 #include "components/image_fetcher/core/image_fetcher.h"
21 #include "components/image_fetcher/core/request_metadata.h"
19 #include "components/prefs/testing_pref_service.h" 22 #include "components/prefs/testing_pref_service.h"
20 #include "testing/gmock/include/gmock/gmock.h" 23 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gtest/include/gtest/gtest.h" 24 #include "testing/gtest/include/gtest/gtest.h"
25 #include "ui/gfx/geometry/size.h"
26 #include "ui/gfx/image/image.h"
27 #include "ui/gfx/image/image_unittest_util.h"
22 28
29 using image_fetcher::ImageFetcher;
30 using image_fetcher::RequestMetadata;
31 using testing::_;
23 using testing::Eq; 32 using testing::Eq;
24 using testing::StrictMock; 33 using testing::StrictMock;
34 using testing::Not;
25 35
26 namespace doodle { 36 namespace doodle {
27 37
28 namespace { 38 namespace {
29 39
30 class FakeDoodleFetcher : public DoodleFetcher { 40 class FakeDoodleFetcher : public DoodleFetcher {
31 public: 41 public:
32 FakeDoodleFetcher() = default; 42 FakeDoodleFetcher() = default;
33 ~FakeDoodleFetcher() override = default; 43 ~FakeDoodleFetcher() override = default;
34 44
(...skipping 18 matching lines...) Expand all
53 std::vector<FinishedCallback> callbacks_; 63 std::vector<FinishedCallback> callbacks_;
54 }; 64 };
55 65
56 class MockDoodleObserver : public DoodleService::Observer { 66 class MockDoodleObserver : public DoodleService::Observer {
57 public: 67 public:
58 MOCK_METHOD1(OnDoodleConfigUpdated, 68 MOCK_METHOD1(OnDoodleConfigUpdated,
59 void(const base::Optional<DoodleConfig>&)); 69 void(const base::Optional<DoodleConfig>&));
60 MOCK_METHOD1(OnDoodleConfigRevalidated, void(bool)); 70 MOCK_METHOD1(OnDoodleConfigRevalidated, void(bool));
61 }; 71 };
62 72
73 class FakeImageFetcher : public ImageFetcher {
74 public:
75 FakeImageFetcher() = default;
76 ~FakeImageFetcher() override {
77 // To make sure we didn't receive an unexpected image request.
78 CHECK(!HasPendingRequest());
fhorschig 2017/05/15 13:54:35 s/CHECK/DCHECK? Also: do we really want a crash he
Marc Treib 2017/05/15 14:25:22 CHECK or DCHECK doesn't really make a difference,
79 }
80
81 void SetImageFetcherDelegate(image_fetcher::ImageFetcherDelegate*) override {
fhorschig 2017/05/15 13:54:35 Why not "// Ignored"? (I am not sure, a test shoul
Marc Treib 2017/05/15 14:25:22 Well, if someone calls this, then they expect some
82 NOTREACHED();
83 }
84
85 void SetDataUseServiceName(DataUseServiceName) override {
86 // Ignored.
87 }
88
89 void SetImageDownloadLimit(base::Optional<int64_t>) override {
90 // Ignored.
91 }
92
93 void SetDesiredImageFrameSize(const gfx::Size&) override { NOTREACHED(); }
fhorschig 2017/05/15 13:54:35 Again, why not "// Ignored"?
Marc Treib 2017/05/15 14:25:22 Eh.. same argument as above, though I guess here i
94
95 void StartOrQueueNetworkRequest(
96 const std::string& id,
97 const GURL& url,
98 const ImageFetcherCallback& callback) override {
99 // For simplicity, the fake doesn't support multiple concurrent requests.
100 CHECK(!HasPendingRequest());
fhorschig 2017/05/15 13:54:35 nit: s/CHECK/DCHECK?
Marc Treib 2017/05/15 14:25:22 Done.
101
102 pending_id_ = id;
103 pending_url_ = url;
104 pending_callback_ = callback;
105 }
106
107 image_fetcher::ImageDecoder* GetImageDecoder() override {
108 NOTREACHED();
109 return nullptr;
110 }
111
112 bool HasPendingRequest() const { return !pending_callback_.is_null(); }
113
114 const GURL& pending_url() const { return pending_url_; }
115
116 void RespondToPendingRequest(const gfx::Image& image) {
117 CHECK(HasPendingRequest());
fhorschig 2017/05/15 13:54:35 nit: s/CHECK/DCHECK?
Marc Treib 2017/05/15 14:25:22 Done.
118
119 RequestMetadata metadata;
120 metadata.http_response_code = 200;
121 pending_callback_.Run(pending_id_, image, metadata);
122
123 pending_id_.clear();
124 pending_url_ = GURL();
125 pending_callback_.Reset();
126 }
127
128 private:
129 std::string pending_id_;
130 GURL pending_url_;
131 ImageFetcherCallback pending_callback_;
132 };
133
63 DoodleConfig CreateConfig(DoodleType type) { 134 DoodleConfig CreateConfig(DoodleType type) {
64 return DoodleConfig(type, DoodleImage(GURL("https://doodle.com/image.jpg"))); 135 return DoodleConfig(type, DoodleImage(GURL("https://doodle.com/image.jpg")));
65 } 136 }
66 137
138 MATCHER(IsEmptyImage, "") {
139 return arg.IsEmpty();
140 }
141
67 } // namespace 142 } // namespace
68 143
69 class DoodleServiceTest : public testing::Test { 144 class DoodleServiceTest : public testing::Test {
70 public: 145 public:
71 DoodleServiceTest() 146 DoodleServiceTest()
72 : task_runner_(new base::TestMockTimeTaskRunner()), 147 : task_runner_(new base::TestMockTimeTaskRunner()),
73 task_runner_handle_(task_runner_), 148 task_runner_handle_(task_runner_),
74 tick_clock_(task_runner_->GetMockTickClock()), 149 tick_clock_(task_runner_->GetMockTickClock()),
75 fetcher_(nullptr), 150 fetcher_(nullptr),
76 expiry_timer_(nullptr) { 151 expiry_timer_(nullptr) {
77 DoodleService::RegisterProfilePrefs(pref_service_.registry()); 152 DoodleService::RegisterProfilePrefs(pref_service_.registry());
78 153
79 task_runner_->FastForwardBy(base::TimeDelta::FromHours(12345)); 154 task_runner_->FastForwardBy(base::TimeDelta::FromHours(12345));
80 155
81 // Set the minimum refresh interval to 0 by default, so tests don't have to 156 // Set the minimum refresh interval to 0 by default, so tests don't have to
82 // worry about it. The tests that care set it explicitly. 157 // worry about it. The tests that care set it explicitly.
83 RecreateServiceWithZeroRefreshInterval(); 158 RecreateServiceWithZeroRefreshInterval();
84 } 159 }
85 160
86 void DestroyService() { service_ = nullptr; } 161 void DestroyService() {
162 fetcher_ = nullptr;
163 expiry_timer_ = nullptr;
164 image_fetcher_ = nullptr;
fhorschig 2017/05/15 13:54:35 This could be a good place to ASSERT HasPendingReq
Marc Treib 2017/05/15 14:25:22 Yup, moved the ASSERT here. IMO the name is fine t
165
166 service_ = nullptr;
167 }
87 168
88 void RecreateServiceWithZeroRefreshInterval() { 169 void RecreateServiceWithZeroRefreshInterval() {
89 RecreateService(/*min_refresh_interval=*/base::TimeDelta()); 170 RecreateService(/*min_refresh_interval=*/base::TimeDelta());
90 } 171 }
91 172
92 void RecreateService(base::Optional<base::TimeDelta> refresh_interval) { 173 void RecreateService(base::Optional<base::TimeDelta> refresh_interval) {
93 auto expiry_timer = base::MakeUnique<base::OneShotTimer>(tick_clock_.get()); 174 auto expiry_timer = base::MakeUnique<base::OneShotTimer>(tick_clock_.get());
94 expiry_timer->SetTaskRunner(task_runner_); 175 expiry_timer->SetTaskRunner(task_runner_);
95 expiry_timer_ = expiry_timer.get(); 176 expiry_timer_ = expiry_timer.get();
96 177
97 auto fetcher = base::MakeUnique<FakeDoodleFetcher>(); 178 auto fetcher = base::MakeUnique<FakeDoodleFetcher>();
98 fetcher_ = fetcher.get(); 179 fetcher_ = fetcher.get();
99 180
181 auto image_fetcher = base::MakeUnique<FakeImageFetcher>();
182 image_fetcher_ = image_fetcher.get();
183
100 service_ = base::MakeUnique<DoodleService>( 184 service_ = base::MakeUnique<DoodleService>(
101 &pref_service_, std::move(fetcher), std::move(expiry_timer), 185 &pref_service_, std::move(fetcher), std::move(expiry_timer),
102 task_runner_->GetMockClock(), task_runner_->GetMockTickClock(), 186 task_runner_->GetMockClock(), task_runner_->GetMockTickClock(),
103 refresh_interval); 187 refresh_interval, std::move(image_fetcher));
104 } 188 }
105 189
106 DoodleService* service() { return service_.get(); } 190 DoodleService* service() { return service_.get(); }
107 FakeDoodleFetcher* fetcher() { return fetcher_; } 191 FakeDoodleFetcher* fetcher() { return fetcher_; }
192 FakeImageFetcher* image_fetcher() { return image_fetcher_; }
108 193
109 base::TestMockTimeTaskRunner* task_runner() { return task_runner_.get(); } 194 base::TestMockTimeTaskRunner* task_runner() { return task_runner_.get(); }
110 195
111 private: 196 private:
112 TestingPrefServiceSimple pref_service_; 197 TestingPrefServiceSimple pref_service_;
113 198
114 scoped_refptr<base::TestMockTimeTaskRunner> task_runner_; 199 scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
115 base::ThreadTaskRunnerHandle task_runner_handle_; 200 base::ThreadTaskRunnerHandle task_runner_handle_;
116 std::unique_ptr<base::TickClock> tick_clock_; 201 std::unique_ptr<base::TickClock> tick_clock_;
117 202
118 std::unique_ptr<DoodleService> service_; 203 std::unique_ptr<DoodleService> service_;
119 204
120 // Weak, owned by the service. 205 // Weak, owned by the service.
121 FakeDoodleFetcher* fetcher_; 206 FakeDoodleFetcher* fetcher_;
122 base::OneShotTimer* expiry_timer_; 207 base::OneShotTimer* expiry_timer_;
208 FakeImageFetcher* image_fetcher_;
123 }; 209 };
124 210
125 TEST_F(DoodleServiceTest, FetchesConfigOnRefresh) { 211 TEST_F(DoodleServiceTest, FetchesConfigOnRefresh) {
126 ASSERT_THAT(service()->config(), Eq(base::nullopt)); 212 ASSERT_THAT(service()->config(), Eq(base::nullopt));
127 213
128 // Request a refresh of the doodle config. 214 // Request a refresh of the doodle config.
129 service()->Refresh(); 215 service()->Refresh();
130 // The request should have arrived at the fetcher. 216 // The request should have arrived at the fetcher.
131 EXPECT_THAT(fetcher()->num_pending_callbacks(), Eq(1u)); 217 EXPECT_THAT(fetcher()->num_pending_callbacks(), Eq(1u));
132 218
(...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 676
591 // Fast-forward time so that the config expires. 677 // Fast-forward time so that the config expires.
592 task_runner()->FastForwardBy(base::TimeDelta::FromHours(1)); 678 task_runner()->FastForwardBy(base::TimeDelta::FromHours(1));
593 ASSERT_THAT(service()->config(), Eq(base::nullopt)); 679 ASSERT_THAT(service()->config(), Eq(base::nullopt));
594 680
595 // This should not have resulted in any metrics being emitted. 681 // This should not have resulted in any metrics being emitted.
596 histograms.ExpectTotalCount("Doodle.ConfigDownloadOutcome", 0); 682 histograms.ExpectTotalCount("Doodle.ConfigDownloadOutcome", 0);
597 histograms.ExpectTotalCount("Doodle.ConfigDownloadTime", 0); 683 histograms.ExpectTotalCount("Doodle.ConfigDownloadTime", 0);
598 } 684 }
599 685
686 TEST_F(DoodleServiceTest, GetImageWithEmptyConfigReturnsImmediately) {
687 ASSERT_THAT(service()->config(), Eq(base::nullopt));
688
689 base::MockCallback<DoodleService::ImageCallback> callback;
690 EXPECT_CALL(callback, Run(IsEmptyImage()));
691
692 service()->GetImage(callback.Get());
fhorschig 2017/05/15 13:54:35 ASSERT_FALSE(HasPendingRequest) might ensure this
Marc Treib 2017/05/15 14:25:22 Er.. what? Anyway, that assert happens during Tea
693 }
694
695 TEST_F(DoodleServiceTest, GetImageFetchesLargeImage) {
696 service()->Refresh();
697 DoodleConfig config = CreateConfig(DoodleType::SIMPLE);
698 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE,
699 base::TimeDelta::FromHours(1), config);
700 ASSERT_THAT(service()->config(), Eq(config));
701
702 base::MockCallback<DoodleService::ImageCallback> callback;
703 service()->GetImage(callback.Get());
704
705 EXPECT_EQ(config.large_image.url, image_fetcher()->pending_url());
706
707 EXPECT_CALL(callback, Run(Not(IsEmptyImage())));
708 gfx::Image image = gfx::test::CreateImage(1, 1);
709 image_fetcher()->RespondToPendingRequest(image);
fhorschig 2017/05/15 13:54:35 ASSERT_TRUE(HasPendingRequest) before that would h
Marc Treib 2017/05/15 14:25:22 Done.
710 }
711
712 TEST_F(DoodleServiceTest, GetImageFetchesCTAImage) {
713 service()->Refresh();
714 DoodleConfig config = CreateConfig(DoodleType::SIMPLE);
715 // Set a CTA image, which should take precedence over the regular image.
716 config.large_image.is_animated_gif = true;
717 config.large_cta_image = DoodleImage(GURL("https://doodle.com/cta.jpg"));
718 config.large_cta_image->is_cta = true;
719 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE,
720 base::TimeDelta::FromHours(1), config);
721 ASSERT_THAT(service()->config(), Eq(config));
722
723 base::MockCallback<DoodleService::ImageCallback> callback;
724 service()->GetImage(callback.Get());
725
726 // If the doodle has a CTA image, that should loaded instead of the regular
727 // large image.
728 EXPECT_EQ(config.large_cta_image->url, image_fetcher()->pending_url());
729
730 EXPECT_CALL(callback, Run(Not(IsEmptyImage())));
731 gfx::Image image = gfx::test::CreateImage(1, 1);
732 image_fetcher()->RespondToPendingRequest(image);
fhorschig 2017/05/15 13:54:35 again ASSERT_FALSE(HasPendingRequest)?
Marc Treib 2017/05/15 14:25:22 ASSERT_TRUE :) but done.
733 }
734
600 } // namespace doodle 735 } // namespace doodle
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698