Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / download / download_status_updater_unittest.cc
blob0a83cb8df2258045f85f271ee9175e31f9c78e1f
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 "base/memory/scoped_vector.h"
6 #include "base/memory/weak_ptr.h"
7 #include "base/message_loop/message_loop.h"
8 #include "base/stl_util.h"
9 #include "chrome/browser/download/download_status_updater.h"
10 #include "content/public/test/mock_download_item.h"
11 #include "content/public/test/mock_download_manager.h"
12 #include "content/public/test/test_browser_thread.h"
13 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h"
16 using testing::AtLeast;
17 using testing::Invoke;
18 using testing::Mock;
19 using testing::Return;
20 using testing::SetArgPointee;
21 using testing::StrictMock;
22 using testing::WithArg;
23 using testing::_;
25 class TestDownloadStatusUpdater : public DownloadStatusUpdater {
26 public:
27 TestDownloadStatusUpdater() : notification_count_(0),
28 acceptable_notification_item_(NULL) {
30 void SetAcceptableNotificationItem(content::DownloadItem* item) {
31 acceptable_notification_item_ = item;
33 size_t NotificationCount() {
34 return notification_count_;
36 protected:
37 void UpdateAppIconDownloadProgress(content::DownloadItem* download) override {
38 ++notification_count_;
39 if (acceptable_notification_item_)
40 EXPECT_EQ(acceptable_notification_item_, download);
42 private:
43 size_t notification_count_;
44 content::DownloadItem* acceptable_notification_item_;
47 class DownloadStatusUpdaterTest : public testing::Test {
48 public:
49 DownloadStatusUpdaterTest()
50 : updater_(new TestDownloadStatusUpdater()),
51 ui_thread_(content::BrowserThread::UI, &loop_) {}
53 ~DownloadStatusUpdaterTest() override {
54 for (size_t mgr_idx = 0; mgr_idx < managers_.size(); ++mgr_idx) {
55 EXPECT_CALL(*Manager(mgr_idx), RemoveObserver(_));
58 delete updater_;
59 updater_ = NULL;
60 VerifyAndClearExpectations();
62 managers_.clear();
63 for (std::vector<Items>::iterator it = manager_items_.begin();
64 it != manager_items_.end(); ++it)
65 STLDeleteContainerPointers(it->begin(), it->end());
67 loop_.RunUntilIdle(); // Allow DownloadManager destruction.
70 protected:
71 // Attach some number of DownloadManagers to the updater.
72 void SetupManagers(int manager_count) {
73 DCHECK_EQ(0U, managers_.size());
74 for (int i = 0; i < manager_count; ++i) {
75 content::MockDownloadManager* mgr =
76 new StrictMock<content::MockDownloadManager>;
77 managers_.push_back(mgr);
81 void SetObserver(content::DownloadManager::Observer* observer) {
82 manager_observers_[manager_observer_index_] = observer;
85 // Hook the specified manager into the updater.
86 void LinkManager(int i) {
87 content::MockDownloadManager* mgr = managers_[i];
88 manager_observer_index_ = i;
89 while (manager_observers_.size() <= static_cast<size_t>(i)) {
90 manager_observers_.push_back(NULL);
92 EXPECT_CALL(*mgr, AddObserver(_))
93 .WillOnce(WithArg<0>(Invoke(
94 this, &DownloadStatusUpdaterTest::SetObserver)));
95 updater_->AddManager(mgr);
98 // Add some number of Download items to a particular manager.
99 void AddItems(int manager_index, int item_count, int in_progress_count) {
100 DCHECK_GT(managers_.size(), static_cast<size_t>(manager_index));
101 content::MockDownloadManager* manager = managers_[manager_index];
103 if (manager_items_.size() <= static_cast<size_t>(manager_index))
104 manager_items_.resize(manager_index+1);
106 std::vector<content::DownloadItem*> item_list;
107 for (int i = 0; i < item_count; ++i) {
108 content::MockDownloadItem* item =
109 new StrictMock<content::MockDownloadItem>;
110 content::DownloadItem::DownloadState state =
111 i < in_progress_count ? content::DownloadItem::IN_PROGRESS
112 : content::DownloadItem::CANCELLED;
113 EXPECT_CALL(*item, GetState()).WillRepeatedly(Return(state));
114 manager_items_[manager_index].push_back(item);
116 EXPECT_CALL(*manager, GetAllDownloads(_))
117 .WillRepeatedly(SetArgPointee<0>(manager_items_[manager_index]));
120 // Return the specified manager.
121 content::MockDownloadManager* Manager(int manager_index) {
122 DCHECK_GT(managers_.size(), static_cast<size_t>(manager_index));
123 return managers_[manager_index];
126 // Return the specified item.
127 content::MockDownloadItem* Item(int manager_index, int item_index) {
128 DCHECK_GT(manager_items_.size(), static_cast<size_t>(manager_index));
129 DCHECK_GT(manager_items_[manager_index].size(),
130 static_cast<size_t>(item_index));
131 // All DownloadItems in manager_items_ are MockDownloadItems.
132 return static_cast<content::MockDownloadItem*>(
133 manager_items_[manager_index][item_index]);
136 // Set return values relevant to |DownloadStatusUpdater::GetProgress()|
137 // for the specified item.
138 void SetItemValues(int manager_index, int item_index,
139 int received_bytes, int total_bytes, bool notify) {
140 content::MockDownloadItem* item(Item(manager_index, item_index));
141 EXPECT_CALL(*item, GetReceivedBytes())
142 .WillRepeatedly(Return(received_bytes));
143 EXPECT_CALL(*item, GetTotalBytes())
144 .WillRepeatedly(Return(total_bytes));
145 if (notify)
146 updater_->OnDownloadUpdated(managers_[manager_index], item);
149 // Transition specified item to completed.
150 void CompleteItem(int manager_index, int item_index) {
151 content::MockDownloadItem* item(Item(manager_index, item_index));
152 EXPECT_CALL(*item, GetState())
153 .WillRepeatedly(Return(content::DownloadItem::COMPLETE));
154 updater_->OnDownloadUpdated(managers_[manager_index], item);
157 // Verify and clear all mocks expectations.
158 void VerifyAndClearExpectations() {
159 for (ScopedVector<content::MockDownloadManager>::iterator it
160 = managers_.begin(); it != managers_.end(); ++it)
161 Mock::VerifyAndClearExpectations(*it);
162 for (std::vector<Items>::iterator it = manager_items_.begin();
163 it != manager_items_.end(); ++it)
164 for (Items::iterator sit = it->begin(); sit != it->end(); ++sit)
165 Mock::VerifyAndClearExpectations(*sit);
168 ScopedVector<content::MockDownloadManager> managers_;
169 // DownloadItem so that it can be assigned to the result of SearchDownloads.
170 typedef std::vector<content::DownloadItem*> Items;
171 std::vector<Items> manager_items_;
172 int manager_observer_index_;
174 std::vector<content::DownloadManager::Observer*> manager_observers_;
176 // Pointer so we can verify that destruction triggers appropriate
177 // changes.
178 TestDownloadStatusUpdater *updater_;
180 // Thread so that the DownloadManager (which is a DeleteOnUIThread
181 // object) can be deleted.
182 // TODO(rdsmith): This can be removed when the DownloadManager
183 // is no longer required to be deleted on the UI thread.
184 base::MessageLoop loop_;
185 content::TestBrowserThread ui_thread_;
188 // Test null updater.
189 TEST_F(DownloadStatusUpdaterTest, Basic) {
190 float progress = -1;
191 int download_count = -1;
192 EXPECT_TRUE(updater_->GetProgress(&progress, &download_count));
193 EXPECT_FLOAT_EQ(0.0f, progress);
194 EXPECT_EQ(0, download_count);
197 // Test updater with null manager.
198 TEST_F(DownloadStatusUpdaterTest, OneManagerNoItems) {
199 SetupManagers(1);
200 AddItems(0, 0, 0);
201 LinkManager(0);
202 VerifyAndClearExpectations();
204 float progress = -1;
205 int download_count = -1;
206 EXPECT_CALL(*managers_[0], GetAllDownloads(_))
207 .WillRepeatedly(SetArgPointee<0>(manager_items_[0]));
208 EXPECT_TRUE(updater_->GetProgress(&progress, &download_count));
209 EXPECT_FLOAT_EQ(0.0f, progress);
210 EXPECT_EQ(0, download_count);
213 // Test updater with non-null manager, including transition an item to
214 // |content::DownloadItem::COMPLETE| and adding a new item.
215 TEST_F(DownloadStatusUpdaterTest, OneManagerManyItems) {
216 SetupManagers(1);
217 AddItems(0, 3, 2);
218 LinkManager(0);
220 // Prime items
221 SetItemValues(0, 0, 10, 20, false);
222 SetItemValues(0, 1, 50, 60, false);
223 SetItemValues(0, 2, 90, 90, false);
225 float progress = -1;
226 int download_count = -1;
227 EXPECT_TRUE(updater_->GetProgress(&progress, &download_count));
228 EXPECT_FLOAT_EQ((10+50)/(20.0f+60), progress);
229 EXPECT_EQ(2, download_count);
231 // Transition one item to completed and confirm progress is updated
232 // properly.
233 CompleteItem(0, 0);
234 EXPECT_TRUE(updater_->GetProgress(&progress, &download_count));
235 EXPECT_FLOAT_EQ(50/60.0f, progress);
236 EXPECT_EQ(1, download_count);
238 // Add a new item to manager and confirm progress is updated properly.
239 AddItems(0, 1, 1);
240 SetItemValues(0, 3, 150, 200, false);
241 manager_observers_[0]->OnDownloadCreated(
242 managers_[0], manager_items_[0][manager_items_[0].size()-1]);
244 EXPECT_TRUE(updater_->GetProgress(&progress, &download_count));
245 EXPECT_FLOAT_EQ((50+150)/(60+200.0f), progress);
246 EXPECT_EQ(2, download_count);
249 // Test to ensure that the download progress notification is called correctly.
250 TEST_F(DownloadStatusUpdaterTest, ProgressNotification) {
251 size_t expected_notifications = updater_->NotificationCount();
252 SetupManagers(1);
253 AddItems(0, 2, 2);
254 LinkManager(0);
256 // Expect two notifications, one for each item; which item will come first
257 // isn't defined so it cannot be tested.
258 expected_notifications += 2;
259 ASSERT_EQ(expected_notifications, updater_->NotificationCount());
261 // Make progress on the first item.
262 updater_->SetAcceptableNotificationItem(Item(0, 0));
263 SetItemValues(0, 0, 10, 20, true);
264 ++expected_notifications;
265 ASSERT_EQ(expected_notifications, updater_->NotificationCount());
267 // Second item completes!
268 updater_->SetAcceptableNotificationItem(Item(0, 1));
269 CompleteItem(0, 1);
270 ++expected_notifications;
271 ASSERT_EQ(expected_notifications, updater_->NotificationCount());
273 // First item completes.
274 updater_->SetAcceptableNotificationItem(Item(0, 0));
275 CompleteItem(0, 0);
276 ++expected_notifications;
277 ASSERT_EQ(expected_notifications, updater_->NotificationCount());
279 updater_->SetAcceptableNotificationItem(NULL);
282 // Confirm we recognize the situation where we have an unknown size.
283 TEST_F(DownloadStatusUpdaterTest, UnknownSize) {
284 SetupManagers(1);
285 AddItems(0, 2, 2);
286 LinkManager(0);
288 // Prime items
289 SetItemValues(0, 0, 10, 20, false);
290 SetItemValues(0, 1, 50, -1, false);
292 float progress = -1;
293 int download_count = -1;
294 EXPECT_FALSE(updater_->GetProgress(&progress, &download_count));
297 // Test many null managers.
298 TEST_F(DownloadStatusUpdaterTest, ManyManagersNoItems) {
299 SetupManagers(1);
300 AddItems(0, 0, 0);
301 LinkManager(0);
303 float progress = -1;
304 int download_count = -1;
305 EXPECT_TRUE(updater_->GetProgress(&progress, &download_count));
306 EXPECT_FLOAT_EQ(0.0f, progress);
307 EXPECT_EQ(0, download_count);
310 // Test many managers with all items complete.
311 TEST_F(DownloadStatusUpdaterTest, ManyManagersEmptyItems) {
312 SetupManagers(2);
313 AddItems(0, 3, 0);
314 LinkManager(0);
315 AddItems(1, 3, 0);
316 LinkManager(1);
318 float progress = -1;
319 int download_count = -1;
320 EXPECT_TRUE(updater_->GetProgress(&progress, &download_count));
321 EXPECT_FLOAT_EQ(0.0f, progress);
322 EXPECT_EQ(0, download_count);
325 // Test many managers with some non-complete items.
326 TEST_F(DownloadStatusUpdaterTest, ManyManagersMixedItems) {
327 SetupManagers(2);
328 AddItems(0, 3, 2);
329 LinkManager(0);
330 AddItems(1, 3, 1);
331 LinkManager(1);
333 SetItemValues(0, 0, 10, 20, false);
334 SetItemValues(0, 1, 50, 60, false);
335 SetItemValues(1, 0, 80, 90, false);
337 float progress = -1;
338 int download_count = -1;
339 EXPECT_TRUE(updater_->GetProgress(&progress, &download_count));
340 EXPECT_FLOAT_EQ((10+50+80)/(20.0f+60+90), progress);
341 EXPECT_EQ(3, download_count);