Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / download / download_status_updater_unittest.cc
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.
4
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"
15
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::_;
24
25 class TestDownloadStatusUpdater : public DownloadStatusUpdater {
26  public:
27   TestDownloadStatusUpdater() : notification_count_(0),
28                                 acceptable_notification_item_(NULL) {
29   }
30   void SetAcceptableNotificationItem(content::DownloadItem* item) {
31     acceptable_notification_item_ = item;
32   }
33   size_t NotificationCount() {
34     return notification_count_;
35   }
36  protected:
37   void UpdateAppIconDownloadProgress(content::DownloadItem* download) override {
38     ++notification_count_;
39     if (acceptable_notification_item_)
40       EXPECT_EQ(acceptable_notification_item_, download);
41   }
42  private:
43   size_t notification_count_;
44   content::DownloadItem* acceptable_notification_item_;
45 };
46
47 class DownloadStatusUpdaterTest : public testing::Test {
48  public:
49   DownloadStatusUpdaterTest()
50       : updater_(new TestDownloadStatusUpdater()),
51         ui_thread_(content::BrowserThread::UI, &loop_) {}
52
53   ~DownloadStatusUpdaterTest() override {
54     for (size_t mgr_idx = 0; mgr_idx < managers_.size(); ++mgr_idx) {
55       EXPECT_CALL(*Manager(mgr_idx), RemoveObserver(_));
56     }
57
58     delete updater_;
59     updater_ = NULL;
60     VerifyAndClearExpectations();
61
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());
66
67     loop_.RunUntilIdle();  // Allow DownloadManager destruction.
68   }
69
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);
78     }
79   }
80
81   void SetObserver(content::DownloadManager::Observer* observer) {
82     manager_observers_[manager_observer_index_] = observer;
83   }
84
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);
91     }
92     EXPECT_CALL(*mgr, AddObserver(_))
93         .WillOnce(WithArg<0>(Invoke(
94             this, &DownloadStatusUpdaterTest::SetObserver)));
95     updater_->AddManager(mgr);
96   }
97
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];
102
103     if (manager_items_.size() <= static_cast<size_t>(manager_index))
104       manager_items_.resize(manager_index+1);
105
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);
115     }
116     EXPECT_CALL(*manager, GetAllDownloads(_))
117         .WillRepeatedly(SetArgPointee<0>(manager_items_[manager_index]));
118   }
119
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];
124   }
125
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]);
134   }
135
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);
147   }
148
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);
155   }
156
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);
166   }
167
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_;
173
174   std::vector<content::DownloadManager::Observer*> manager_observers_;
175
176   // Pointer so we can verify that destruction triggers appropriate
177   // changes.
178   TestDownloadStatusUpdater *updater_;
179
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_;
186 };
187
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);
195 }
196
197 // Test updater with null manager.
198 TEST_F(DownloadStatusUpdaterTest, OneManagerNoItems) {
199   SetupManagers(1);
200   AddItems(0, 0, 0);
201   LinkManager(0);
202   VerifyAndClearExpectations();
203
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);
211 }
212
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);
219
220   // Prime items
221   SetItemValues(0, 0, 10, 20, false);
222   SetItemValues(0, 1, 50, 60, false);
223   SetItemValues(0, 2, 90, 90, false);
224
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);
230
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);
237
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]);
243
244   EXPECT_TRUE(updater_->GetProgress(&progress, &download_count));
245   EXPECT_FLOAT_EQ((50+150)/(60+200.0f), progress);
246   EXPECT_EQ(2, download_count);
247 }
248
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);
255
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());
260
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());
266
267   // Second item completes!
268   updater_->SetAcceptableNotificationItem(Item(0, 1));
269   CompleteItem(0, 1);
270   ++expected_notifications;
271   ASSERT_EQ(expected_notifications, updater_->NotificationCount());
272
273   // First item completes.
274   updater_->SetAcceptableNotificationItem(Item(0, 0));
275   CompleteItem(0, 0);
276   ++expected_notifications;
277   ASSERT_EQ(expected_notifications, updater_->NotificationCount());
278
279   updater_->SetAcceptableNotificationItem(NULL);
280 }
281
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);
287
288   // Prime items
289   SetItemValues(0, 0, 10, 20, false);
290   SetItemValues(0, 1, 50, -1, false);
291
292   float progress = -1;
293   int download_count = -1;
294   EXPECT_FALSE(updater_->GetProgress(&progress, &download_count));
295 }
296
297 // Test many null managers.
298 TEST_F(DownloadStatusUpdaterTest, ManyManagersNoItems) {
299   SetupManagers(1);
300   AddItems(0, 0, 0);
301   LinkManager(0);
302
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);
308 }
309
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);
317
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);
323 }
324
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);
332
333   SetItemValues(0, 0, 10, 20, false);
334   SetItemValues(0, 1, 50, 60, false);
335   SetItemValues(1, 0, 80, 90, false);
336
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);
342 }