Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / download / download_status_updater_unittest.cc
blob05410a6f09b5e9d541d61aa962c589dcf9080c64
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 virtual void UpdateAppIconDownloadProgress(
38 content::DownloadItem* download) OVERRIDE {
39 ++notification_count_;
40 if (acceptable_notification_item_)
41 EXPECT_EQ(acceptable_notification_item_, download);
43 private:
44 size_t notification_count_;
45 content::DownloadItem* acceptable_notification_item_;
48 class DownloadStatusUpdaterTest : public testing::Test {
49 public:
50 DownloadStatusUpdaterTest()
51 : updater_(new TestDownloadStatusUpdater()),
52 ui_thread_(content::BrowserThread::UI, &loop_) {}
54 virtual ~DownloadStatusUpdaterTest() {
55 for (size_t mgr_idx = 0; mgr_idx < managers_.size(); ++mgr_idx) {
56 EXPECT_CALL(*Manager(mgr_idx), RemoveObserver(_));
57 for (size_t item_idx = 0; item_idx < manager_items_[mgr_idx].size();
58 ++item_idx) {
59 EXPECT_CALL(*Item(mgr_idx, item_idx), RemoveObserver(_));
63 delete updater_;
64 updater_ = NULL;
65 VerifyAndClearExpectations();
67 managers_.clear();
68 for (std::vector<Items>::iterator it = manager_items_.begin();
69 it != manager_items_.end(); ++it)
70 STLDeleteContainerPointers(it->begin(), it->end());
72 loop_.RunUntilIdle(); // Allow DownloadManager destruction.
75 protected:
76 // Attach some number of DownloadManagers to the updater.
77 void SetupManagers(int manager_count) {
78 DCHECK_EQ(0U, managers_.size());
79 for (int i = 0; i < manager_count; ++i) {
80 content::MockDownloadManager* mgr =
81 new StrictMock<content::MockDownloadManager>;
82 managers_.push_back(mgr);
86 void SetObserver(content::DownloadManager::Observer* observer) {
87 manager_observers_[manager_observer_index_] = observer;
90 // Hook the specified manager into the updater.
91 void LinkManager(int i) {
92 content::MockDownloadManager* mgr = managers_[i];
93 manager_observer_index_ = i;
94 while (manager_observers_.size() <= static_cast<size_t>(i)) {
95 manager_observers_.push_back(NULL);
97 EXPECT_CALL(*mgr, AddObserver(_))
98 .WillOnce(WithArg<0>(Invoke(
99 this, &DownloadStatusUpdaterTest::SetObserver)));
100 updater_->AddManager(mgr);
103 // Add some number of Download items to a particular manager.
104 void AddItems(int manager_index, int item_count, int in_progress_count) {
105 DCHECK_GT(managers_.size(), static_cast<size_t>(manager_index));
106 content::MockDownloadManager* manager = managers_[manager_index];
108 if (manager_items_.size() <= static_cast<size_t>(manager_index))
109 manager_items_.resize(manager_index+1);
111 std::vector<content::DownloadItem*> item_list;
112 for (int i = 0; i < item_count; ++i) {
113 content::MockDownloadItem* item =
114 new StrictMock<content::MockDownloadItem>;
115 content::DownloadItem::DownloadState state =
116 i < in_progress_count ? content::DownloadItem::IN_PROGRESS
117 : content::DownloadItem::CANCELLED;
118 EXPECT_CALL(*item, GetState()).WillRepeatedly(Return(state));
119 EXPECT_CALL(*item, AddObserver(_))
120 .WillOnce(Return());
121 manager_items_[manager_index].push_back(item);
123 EXPECT_CALL(*manager, GetAllDownloads(_))
124 .WillRepeatedly(SetArgPointee<0>(manager_items_[manager_index]));
127 // Return the specified manager.
128 content::MockDownloadManager* Manager(int manager_index) {
129 DCHECK_GT(managers_.size(), static_cast<size_t>(manager_index));
130 return managers_[manager_index];
133 // Return the specified item.
134 content::MockDownloadItem* Item(int manager_index, int item_index) {
135 DCHECK_GT(manager_items_.size(), static_cast<size_t>(manager_index));
136 DCHECK_GT(manager_items_[manager_index].size(),
137 static_cast<size_t>(item_index));
138 // All DownloadItems in manager_items_ are MockDownloadItems.
139 return static_cast<content::MockDownloadItem*>(
140 manager_items_[manager_index][item_index]);
143 // Set return values relevant to |DownloadStatusUpdater::GetProgress()|
144 // for the specified item.
145 void SetItemValues(int manager_index, int item_index,
146 int received_bytes, int total_bytes, bool notify) {
147 content::MockDownloadItem* item(Item(manager_index, item_index));
148 EXPECT_CALL(*item, GetReceivedBytes())
149 .WillRepeatedly(Return(received_bytes));
150 EXPECT_CALL(*item, GetTotalBytes())
151 .WillRepeatedly(Return(total_bytes));
152 if (notify)
153 updater_->OnDownloadUpdated(managers_[manager_index], item);
156 // Transition specified item to completed.
157 void CompleteItem(int manager_index, int item_index) {
158 content::MockDownloadItem* item(Item(manager_index, item_index));
159 EXPECT_CALL(*item, GetState())
160 .WillRepeatedly(Return(content::DownloadItem::COMPLETE));
161 updater_->OnDownloadUpdated(managers_[manager_index], item);
164 // Verify and clear all mocks expectations.
165 void VerifyAndClearExpectations() {
166 for (ScopedVector<content::MockDownloadManager>::iterator it
167 = managers_.begin(); it != managers_.end(); ++it)
168 Mock::VerifyAndClearExpectations(*it);
169 for (std::vector<Items>::iterator it = manager_items_.begin();
170 it != manager_items_.end(); ++it)
171 for (Items::iterator sit = it->begin(); sit != it->end(); ++sit)
172 Mock::VerifyAndClearExpectations(*sit);
175 ScopedVector<content::MockDownloadManager> managers_;
176 // DownloadItem so that it can be assigned to the result of SearchDownloads.
177 typedef std::vector<content::DownloadItem*> Items;
178 std::vector<Items> manager_items_;
179 int manager_observer_index_;
181 std::vector<content::DownloadManager::Observer*> manager_observers_;
183 // Pointer so we can verify that destruction triggers appropriate
184 // changes.
185 TestDownloadStatusUpdater *updater_;
187 // Thread so that the DownloadManager (which is a DeleteOnUIThread
188 // object) can be deleted.
189 // TODO(rdsmith): This can be removed when the DownloadManager
190 // is no longer required to be deleted on the UI thread.
191 base::MessageLoop loop_;
192 content::TestBrowserThread ui_thread_;
195 // Test null updater.
196 TEST_F(DownloadStatusUpdaterTest, Basic) {
197 float progress = -1;
198 int download_count = -1;
199 EXPECT_TRUE(updater_->GetProgress(&progress, &download_count));
200 EXPECT_FLOAT_EQ(0.0f, progress);
201 EXPECT_EQ(0, download_count);
204 // Test updater with null manager.
205 TEST_F(DownloadStatusUpdaterTest, OneManagerNoItems) {
206 SetupManagers(1);
207 AddItems(0, 0, 0);
208 LinkManager(0);
209 VerifyAndClearExpectations();
211 float progress = -1;
212 int download_count = -1;
213 EXPECT_CALL(*managers_[0], GetAllDownloads(_))
214 .WillRepeatedly(SetArgPointee<0>(manager_items_[0]));
215 EXPECT_TRUE(updater_->GetProgress(&progress, &download_count));
216 EXPECT_FLOAT_EQ(0.0f, progress);
217 EXPECT_EQ(0, download_count);
220 // Test updater with non-null manager, including transition an item to
221 // |content::DownloadItem::COMPLETE| and adding a new item.
222 TEST_F(DownloadStatusUpdaterTest, OneManagerManyItems) {
223 SetupManagers(1);
224 AddItems(0, 3, 2);
225 LinkManager(0);
227 // Prime items
228 SetItemValues(0, 0, 10, 20, false);
229 SetItemValues(0, 1, 50, 60, false);
230 SetItemValues(0, 2, 90, 90, false);
232 float progress = -1;
233 int download_count = -1;
234 EXPECT_TRUE(updater_->GetProgress(&progress, &download_count));
235 EXPECT_FLOAT_EQ((10+50)/(20.0f+60), progress);
236 EXPECT_EQ(2, download_count);
238 // Transition one item to completed and confirm progress is updated
239 // properly.
240 CompleteItem(0, 0);
241 EXPECT_TRUE(updater_->GetProgress(&progress, &download_count));
242 EXPECT_FLOAT_EQ(50/60.0f, progress);
243 EXPECT_EQ(1, download_count);
245 // Add a new item to manager and confirm progress is updated properly.
246 AddItems(0, 1, 1);
247 SetItemValues(0, 3, 150, 200, false);
248 manager_observers_[0]->OnDownloadCreated(
249 managers_[0], manager_items_[0][manager_items_[0].size()-1]);
251 EXPECT_TRUE(updater_->GetProgress(&progress, &download_count));
252 EXPECT_FLOAT_EQ((50+150)/(60+200.0f), progress);
253 EXPECT_EQ(2, download_count);
256 // Test to ensure that the download progress notification is called correctly.
257 TEST_F(DownloadStatusUpdaterTest, ProgressNotification) {
258 size_t expected_notifications = updater_->NotificationCount();
259 SetupManagers(1);
260 AddItems(0, 2, 2);
261 LinkManager(0);
263 // Expect two notifications, one for each item; which item will come first
264 // isn't defined so it cannot be tested.
265 expected_notifications += 2;
266 ASSERT_EQ(expected_notifications, updater_->NotificationCount());
268 // Make progress on the first item.
269 updater_->SetAcceptableNotificationItem(Item(0, 0));
270 SetItemValues(0, 0, 10, 20, true);
271 ++expected_notifications;
272 ASSERT_EQ(expected_notifications, updater_->NotificationCount());
274 // Second item completes!
275 updater_->SetAcceptableNotificationItem(Item(0, 1));
276 CompleteItem(0, 1);
277 ++expected_notifications;
278 ASSERT_EQ(expected_notifications, updater_->NotificationCount());
280 // First item completes.
281 updater_->SetAcceptableNotificationItem(Item(0, 0));
282 CompleteItem(0, 0);
283 ++expected_notifications;
284 ASSERT_EQ(expected_notifications, updater_->NotificationCount());
286 updater_->SetAcceptableNotificationItem(NULL);
289 // Confirm we recognize the situation where we have an unknown size.
290 TEST_F(DownloadStatusUpdaterTest, UnknownSize) {
291 SetupManagers(1);
292 AddItems(0, 2, 2);
293 LinkManager(0);
295 // Prime items
296 SetItemValues(0, 0, 10, 20, false);
297 SetItemValues(0, 1, 50, -1, false);
299 float progress = -1;
300 int download_count = -1;
301 EXPECT_FALSE(updater_->GetProgress(&progress, &download_count));
304 // Test many null managers.
305 TEST_F(DownloadStatusUpdaterTest, ManyManagersNoItems) {
306 SetupManagers(1);
307 AddItems(0, 0, 0);
308 LinkManager(0);
310 float progress = -1;
311 int download_count = -1;
312 EXPECT_TRUE(updater_->GetProgress(&progress, &download_count));
313 EXPECT_FLOAT_EQ(0.0f, progress);
314 EXPECT_EQ(0, download_count);
317 // Test many managers with all items complete.
318 TEST_F(DownloadStatusUpdaterTest, ManyManagersEmptyItems) {
319 SetupManagers(2);
320 AddItems(0, 3, 0);
321 LinkManager(0);
322 AddItems(1, 3, 0);
323 LinkManager(1);
325 float progress = -1;
326 int download_count = -1;
327 EXPECT_TRUE(updater_->GetProgress(&progress, &download_count));
328 EXPECT_FLOAT_EQ(0.0f, progress);
329 EXPECT_EQ(0, download_count);
332 // Test many managers with some non-complete items.
333 TEST_F(DownloadStatusUpdaterTest, ManyManagersMixedItems) {
334 SetupManagers(2);
335 AddItems(0, 3, 2);
336 LinkManager(0);
337 AddItems(1, 3, 1);
338 LinkManager(1);
340 SetItemValues(0, 0, 10, 20, false);
341 SetItemValues(0, 1, 50, 60, false);
342 SetItemValues(1, 0, 80, 90, false);
344 float progress = -1;
345 int download_count = -1;
346 EXPECT_TRUE(updater_->GetProgress(&progress, &download_count));
347 EXPECT_FLOAT_EQ((10+50+80)/(20.0f+60+90), progress);
348 EXPECT_EQ(3, download_count);