| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 <stddef.h> | 5 #include <stddef.h> |
| 6 | 6 |
| 7 #include "base/memory/scoped_vector.h" | 7 #include <memory> |
| 8 |
| 9 #include "base/memory/ptr_util.h" |
| 8 #include "base/memory/weak_ptr.h" | 10 #include "base/memory/weak_ptr.h" |
| 9 #include "base/message_loop/message_loop.h" | 11 #include "base/message_loop/message_loop.h" |
| 10 #include "base/run_loop.h" | 12 #include "base/run_loop.h" |
| 11 #include "base/stl_util.h" | |
| 12 #include "chrome/browser/download/download_status_updater.h" | 13 #include "chrome/browser/download/download_status_updater.h" |
| 13 #include "content/public/test/mock_download_item.h" | 14 #include "content/public/test/mock_download_item.h" |
| 14 #include "content/public/test/mock_download_manager.h" | 15 #include "content/public/test/mock_download_manager.h" |
| 15 #include "content/public/test/test_browser_thread.h" | 16 #include "content/public/test/test_browser_thread.h" |
| 16 #include "testing/gmock/include/gmock/gmock.h" | 17 #include "testing/gmock/include/gmock/gmock.h" |
| 17 #include "testing/gtest/include/gtest/gtest.h" | 18 #include "testing/gtest/include/gtest/gtest.h" |
| 18 | 19 |
| 19 using testing::AtLeast; | 20 using testing::AtLeast; |
| 20 using testing::Invoke; | 21 using testing::Invoke; |
| 21 using testing::Mock; | 22 using testing::Mock; |
| 22 using testing::Return; | 23 using testing::Return; |
| 23 using testing::SetArgPointee; | 24 using testing::SetArgPointee; |
| 24 using testing::StrictMock; | 25 using testing::StrictMock; |
| 25 using testing::WithArg; | 26 using testing::WithArg; |
| 26 using testing::_; | 27 using testing::_; |
| 27 | 28 |
| 28 class TestDownloadStatusUpdater : public DownloadStatusUpdater { | 29 class TestDownloadStatusUpdater : public DownloadStatusUpdater { |
| 29 public: | 30 public: |
| 30 TestDownloadStatusUpdater() : notification_count_(0), | 31 TestDownloadStatusUpdater() |
| 31 acceptable_notification_item_(NULL) { | 32 : notification_count_(0), acceptable_notification_item_(nullptr) {} |
| 32 } | |
| 33 void SetAcceptableNotificationItem(content::DownloadItem* item) { | 33 void SetAcceptableNotificationItem(content::DownloadItem* item) { |
| 34 acceptable_notification_item_ = item; | 34 acceptable_notification_item_ = item; |
| 35 } | 35 } |
| 36 size_t NotificationCount() { | 36 size_t NotificationCount() { |
| 37 return notification_count_; | 37 return notification_count_; |
| 38 } | 38 } |
| 39 protected: | 39 protected: |
| 40 void UpdateAppIconDownloadProgress(content::DownloadItem* download) override { | 40 void UpdateAppIconDownloadProgress(content::DownloadItem* download) override { |
| 41 ++notification_count_; | 41 ++notification_count_; |
| 42 if (acceptable_notification_item_) | 42 if (acceptable_notification_item_) |
| 43 EXPECT_EQ(acceptable_notification_item_, download); | 43 EXPECT_EQ(acceptable_notification_item_, download); |
| 44 } | 44 } |
| 45 private: | 45 private: |
| 46 size_t notification_count_; | 46 size_t notification_count_; |
| 47 content::DownloadItem* acceptable_notification_item_; | 47 content::DownloadItem* acceptable_notification_item_; |
| 48 }; | 48 }; |
| 49 | 49 |
| 50 class DownloadStatusUpdaterTest : public testing::Test { | 50 class DownloadStatusUpdaterTest : public testing::Test { |
| 51 public: | 51 public: |
| 52 DownloadStatusUpdaterTest() | 52 DownloadStatusUpdaterTest() |
| 53 : updater_(new TestDownloadStatusUpdater()), | 53 : updater_(new TestDownloadStatusUpdater()), |
| 54 ui_thread_(content::BrowserThread::UI, &loop_) {} | 54 ui_thread_(content::BrowserThread::UI, &loop_) {} |
| 55 | 55 |
| 56 ~DownloadStatusUpdaterTest() override { | 56 ~DownloadStatusUpdaterTest() override { |
| 57 for (size_t mgr_idx = 0; mgr_idx < managers_.size(); ++mgr_idx) { | 57 for (size_t mgr_idx = 0; mgr_idx < managers_.size(); ++mgr_idx) { |
| 58 EXPECT_CALL(*Manager(mgr_idx), RemoveObserver(_)); | 58 EXPECT_CALL(*Manager(mgr_idx), RemoveObserver(_)); |
| 59 } | 59 } |
| 60 | 60 |
| 61 delete updater_; | 61 delete updater_; |
| 62 updater_ = NULL; | 62 updater_ = nullptr; |
| 63 VerifyAndClearExpectations(); | 63 VerifyAndClearExpectations(); |
| 64 | 64 |
| 65 managers_.clear(); | 65 managers_.clear(); |
| 66 for (std::vector<Items>::iterator it = manager_items_.begin(); | 66 manager_items_.clear(); |
| 67 it != manager_items_.end(); ++it) | 67 all_owned_items_.clear(); |
| 68 base::STLDeleteContainerPointers(it->begin(), it->end()); | |
| 69 | 68 |
| 70 base::RunLoop().RunUntilIdle(); // Allow DownloadManager destruction. | 69 base::RunLoop().RunUntilIdle(); // Allow DownloadManager destruction. |
| 71 } | 70 } |
| 72 | 71 |
| 73 protected: | 72 protected: |
| 74 // Attach some number of DownloadManagers to the updater. | 73 // Attach some number of DownloadManagers to the updater. |
| 75 void SetupManagers(int manager_count) { | 74 void SetupManagers(int manager_count) { |
| 76 DCHECK_EQ(0U, managers_.size()); | 75 DCHECK_EQ(0U, managers_.size()); |
| 77 for (int i = 0; i < manager_count; ++i) { | 76 for (int i = 0; i < manager_count; ++i) { |
| 78 content::MockDownloadManager* mgr = | 77 managers_.push_back( |
| 79 new StrictMock<content::MockDownloadManager>; | 78 base::MakeUnique<StrictMock<content::MockDownloadManager>>()); |
| 80 managers_.push_back(mgr); | |
| 81 } | 79 } |
| 82 } | 80 } |
| 83 | 81 |
| 84 void SetObserver(content::DownloadManager::Observer* observer) { | 82 void SetObserver(content::DownloadManager::Observer* observer) { |
| 85 manager_observers_[manager_observer_index_] = observer; | 83 manager_observers_[manager_observer_index_] = observer; |
| 86 } | 84 } |
| 87 | 85 |
| 88 // Hook the specified manager into the updater. | 86 // Hook the specified manager into the updater. |
| 89 void LinkManager(int i) { | 87 void LinkManager(int i) { |
| 90 content::MockDownloadManager* mgr = managers_[i]; | 88 content::MockDownloadManager* mgr = managers_[i].get(); |
| 91 manager_observer_index_ = i; | 89 manager_observer_index_ = i; |
| 92 while (manager_observers_.size() <= static_cast<size_t>(i)) { | 90 while (manager_observers_.size() <= static_cast<size_t>(i)) { |
| 93 manager_observers_.push_back(NULL); | 91 manager_observers_.push_back(nullptr); |
| 94 } | 92 } |
| 95 EXPECT_CALL(*mgr, AddObserver(_)) | 93 EXPECT_CALL(*mgr, AddObserver(_)) |
| 96 .WillOnce(WithArg<0>(Invoke( | 94 .WillOnce(WithArg<0>(Invoke( |
| 97 this, &DownloadStatusUpdaterTest::SetObserver))); | 95 this, &DownloadStatusUpdaterTest::SetObserver))); |
| 98 updater_->AddManager(mgr); | 96 updater_->AddManager(mgr); |
| 99 } | 97 } |
| 100 | 98 |
| 101 // Add some number of Download items to a particular manager. | 99 // Add some number of Download items to a particular manager. |
| 102 void AddItems(int manager_index, int item_count, int in_progress_count) { | 100 void AddItems(int manager_index, int item_count, int in_progress_count) { |
| 103 DCHECK_GT(managers_.size(), static_cast<size_t>(manager_index)); | 101 DCHECK_GT(managers_.size(), static_cast<size_t>(manager_index)); |
| 104 content::MockDownloadManager* manager = managers_[manager_index]; | 102 content::MockDownloadManager* manager = managers_[manager_index].get(); |
| 105 | 103 |
| 106 if (manager_items_.size() <= static_cast<size_t>(manager_index)) | 104 if (manager_items_.size() <= static_cast<size_t>(manager_index)) |
| 107 manager_items_.resize(manager_index+1); | 105 manager_items_.resize(manager_index+1); |
| 108 | 106 |
| 109 std::vector<content::DownloadItem*> item_list; | 107 std::vector<content::DownloadItem*> item_list; |
| 110 for (int i = 0; i < item_count; ++i) { | 108 for (int i = 0; i < item_count; ++i) { |
| 111 content::MockDownloadItem* item = | 109 std::unique_ptr<content::MockDownloadItem> item = |
| 112 new StrictMock<content::MockDownloadItem>; | 110 base::MakeUnique<StrictMock<content::MockDownloadItem>>(); |
| 113 content::DownloadItem::DownloadState state = | 111 content::DownloadItem::DownloadState state = |
| 114 i < in_progress_count ? content::DownloadItem::IN_PROGRESS | 112 i < in_progress_count ? content::DownloadItem::IN_PROGRESS |
| 115 : content::DownloadItem::CANCELLED; | 113 : content::DownloadItem::CANCELLED; |
| 116 EXPECT_CALL(*item, GetState()).WillRepeatedly(Return(state)); | 114 EXPECT_CALL(*item, GetState()).WillRepeatedly(Return(state)); |
| 117 manager_items_[manager_index].push_back(item); | 115 manager_items_[manager_index].push_back(item.get()); |
| 116 all_owned_items_.push_back(std::move(item)); |
| 118 } | 117 } |
| 119 EXPECT_CALL(*manager, GetAllDownloads(_)) | 118 EXPECT_CALL(*manager, GetAllDownloads(_)) |
| 120 .WillRepeatedly(SetArgPointee<0>(manager_items_[manager_index])); | 119 .WillRepeatedly(SetArgPointee<0>(manager_items_[manager_index])); |
| 121 } | 120 } |
| 122 | 121 |
| 123 // Return the specified manager. | 122 // Return the specified manager. |
| 124 content::MockDownloadManager* Manager(int manager_index) { | 123 content::MockDownloadManager* Manager(int manager_index) { |
| 125 DCHECK_GT(managers_.size(), static_cast<size_t>(manager_index)); | 124 DCHECK_GT(managers_.size(), static_cast<size_t>(manager_index)); |
| 126 return managers_[manager_index]; | 125 return managers_[manager_index].get(); |
| 127 } | 126 } |
| 128 | 127 |
| 129 // Return the specified item. | 128 // Return the specified item. |
| 130 content::MockDownloadItem* Item(int manager_index, int item_index) { | 129 content::MockDownloadItem* Item(int manager_index, int item_index) { |
| 131 DCHECK_GT(manager_items_.size(), static_cast<size_t>(manager_index)); | 130 DCHECK_GT(manager_items_.size(), static_cast<size_t>(manager_index)); |
| 132 DCHECK_GT(manager_items_[manager_index].size(), | 131 DCHECK_GT(manager_items_[manager_index].size(), |
| 133 static_cast<size_t>(item_index)); | 132 static_cast<size_t>(item_index)); |
| 134 // All DownloadItems in manager_items_ are MockDownloadItems. | 133 // All DownloadItems in manager_items_ are MockDownloadItems. |
| 135 return static_cast<content::MockDownloadItem*>( | 134 return static_cast<content::MockDownloadItem*>( |
| 136 manager_items_[manager_index][item_index]); | 135 manager_items_[manager_index][item_index]); |
| 137 } | 136 } |
| 138 | 137 |
| 139 // Set return values relevant to |DownloadStatusUpdater::GetProgress()| | 138 // Set return values relevant to |DownloadStatusUpdater::GetProgress()| |
| 140 // for the specified item. | 139 // for the specified item. |
| 141 void SetItemValues(int manager_index, int item_index, | 140 void SetItemValues(int manager_index, int item_index, |
| 142 int received_bytes, int total_bytes, bool notify) { | 141 int received_bytes, int total_bytes, bool notify) { |
| 143 content::MockDownloadItem* item(Item(manager_index, item_index)); | 142 content::MockDownloadItem* item(Item(manager_index, item_index)); |
| 144 EXPECT_CALL(*item, GetReceivedBytes()) | 143 EXPECT_CALL(*item, GetReceivedBytes()) |
| 145 .WillRepeatedly(Return(received_bytes)); | 144 .WillRepeatedly(Return(received_bytes)); |
| 146 EXPECT_CALL(*item, GetTotalBytes()) | 145 EXPECT_CALL(*item, GetTotalBytes()) |
| 147 .WillRepeatedly(Return(total_bytes)); | 146 .WillRepeatedly(Return(total_bytes)); |
| 148 if (notify) | 147 if (notify) |
| 149 updater_->OnDownloadUpdated(managers_[manager_index], item); | 148 updater_->OnDownloadUpdated(managers_[manager_index].get(), item); |
| 150 } | 149 } |
| 151 | 150 |
| 152 // Transition specified item to completed. | 151 // Transition specified item to completed. |
| 153 void CompleteItem(int manager_index, int item_index) { | 152 void CompleteItem(int manager_index, int item_index) { |
| 154 content::MockDownloadItem* item(Item(manager_index, item_index)); | 153 content::MockDownloadItem* item(Item(manager_index, item_index)); |
| 155 EXPECT_CALL(*item, GetState()) | 154 EXPECT_CALL(*item, GetState()) |
| 156 .WillRepeatedly(Return(content::DownloadItem::COMPLETE)); | 155 .WillRepeatedly(Return(content::DownloadItem::COMPLETE)); |
| 157 updater_->OnDownloadUpdated(managers_[manager_index], item); | 156 updater_->OnDownloadUpdated(managers_[manager_index].get(), item); |
| 158 } | 157 } |
| 159 | 158 |
| 160 // Verify and clear all mocks expectations. | 159 // Verify and clear all mocks expectations. |
| 161 void VerifyAndClearExpectations() { | 160 void VerifyAndClearExpectations() { |
| 162 for (ScopedVector<content::MockDownloadManager>::iterator it | 161 for (const auto& manager : managers_) |
| 163 = managers_.begin(); it != managers_.end(); ++it) | 162 Mock::VerifyAndClearExpectations(manager.get()); |
| 164 Mock::VerifyAndClearExpectations(*it); | 163 for (auto it = manager_items_.begin(); it != manager_items_.end(); ++it) |
| 165 for (std::vector<Items>::iterator it = manager_items_.begin(); | 164 for (auto sit = it->begin(); sit != it->end(); ++sit) |
| 166 it != manager_items_.end(); ++it) | |
| 167 for (Items::iterator sit = it->begin(); sit != it->end(); ++sit) | |
| 168 Mock::VerifyAndClearExpectations(*sit); | 165 Mock::VerifyAndClearExpectations(*sit); |
| 169 } | 166 } |
| 170 | 167 |
| 171 ScopedVector<content::MockDownloadManager> managers_; | 168 // The mocked download managers. |
| 172 // DownloadItem so that it can be assigned to the result of SearchDownloads. | 169 std::vector<std::unique_ptr<content::MockDownloadManager>> managers_; |
| 173 typedef std::vector<content::DownloadItem*> Items; | 170 // The download items being downloaded by those managers in |managers_|. The |
| 174 std::vector<Items> manager_items_; | 171 // top-level vector is the manager index, and the inner vector is the list of |
| 172 // items of that manager. The inner vector is a vector<DownloadItem*> for |
| 173 // compatibility with the return value of DownloadManager::GetAllDownloads(). |
| 174 std::vector<std::vector<content::DownloadItem*>> manager_items_; |
| 175 // An owning container for items in |manager_items_|. |
| 176 std::vector<std::unique_ptr<content::DownloadItem>> all_owned_items_; |
| 175 int manager_observer_index_; | 177 int manager_observer_index_; |
| 176 | 178 |
| 177 std::vector<content::DownloadManager::Observer*> manager_observers_; | 179 std::vector<content::DownloadManager::Observer*> manager_observers_; |
| 178 | 180 |
| 179 // Pointer so we can verify that destruction triggers appropriate | 181 // Pointer so we can verify that destruction triggers appropriate |
| 180 // changes. | 182 // changes. |
| 181 TestDownloadStatusUpdater *updater_; | 183 TestDownloadStatusUpdater* updater_; |
| 182 | 184 |
| 183 // Thread so that the DownloadManager (which is a DeleteOnUIThread | 185 // Thread so that the DownloadManager (which is a DeleteOnUIThread |
| 184 // object) can be deleted. | 186 // object) can be deleted. |
| 185 // TODO(rdsmith): This can be removed when the DownloadManager | 187 // TODO(rdsmith): This can be removed when the DownloadManager |
| 186 // is no longer required to be deleted on the UI thread. | 188 // is no longer required to be deleted on the UI thread. |
| 187 base::MessageLoop loop_; | 189 base::MessageLoop loop_; |
| 188 content::TestBrowserThread ui_thread_; | 190 content::TestBrowserThread ui_thread_; |
| 189 }; | 191 }; |
| 190 | 192 |
| 191 // Test null updater. | 193 // Test null updater. |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 235 // properly. | 237 // properly. |
| 236 CompleteItem(0, 0); | 238 CompleteItem(0, 0); |
| 237 EXPECT_TRUE(updater_->GetProgress(&progress, &download_count)); | 239 EXPECT_TRUE(updater_->GetProgress(&progress, &download_count)); |
| 238 EXPECT_FLOAT_EQ(50/60.0f, progress); | 240 EXPECT_FLOAT_EQ(50/60.0f, progress); |
| 239 EXPECT_EQ(1, download_count); | 241 EXPECT_EQ(1, download_count); |
| 240 | 242 |
| 241 // Add a new item to manager and confirm progress is updated properly. | 243 // Add a new item to manager and confirm progress is updated properly. |
| 242 AddItems(0, 1, 1); | 244 AddItems(0, 1, 1); |
| 243 SetItemValues(0, 3, 150, 200, false); | 245 SetItemValues(0, 3, 150, 200, false); |
| 244 manager_observers_[0]->OnDownloadCreated( | 246 manager_observers_[0]->OnDownloadCreated( |
| 245 managers_[0], manager_items_[0][manager_items_[0].size()-1]); | 247 managers_[0].get(), manager_items_[0][manager_items_[0].size() - 1]); |
| 246 | 248 |
| 247 EXPECT_TRUE(updater_->GetProgress(&progress, &download_count)); | 249 EXPECT_TRUE(updater_->GetProgress(&progress, &download_count)); |
| 248 EXPECT_FLOAT_EQ((50+150)/(60+200.0f), progress); | 250 EXPECT_FLOAT_EQ((50+150)/(60+200.0f), progress); |
| 249 EXPECT_EQ(2, download_count); | 251 EXPECT_EQ(2, download_count); |
| 250 } | 252 } |
| 251 | 253 |
| 252 // Test to ensure that the download progress notification is called correctly. | 254 // Test to ensure that the download progress notification is called correctly. |
| 253 TEST_F(DownloadStatusUpdaterTest, ProgressNotification) { | 255 TEST_F(DownloadStatusUpdaterTest, ProgressNotification) { |
| 254 size_t expected_notifications = updater_->NotificationCount(); | 256 size_t expected_notifications = updater_->NotificationCount(); |
| 255 SetupManagers(1); | 257 SetupManagers(1); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 272 CompleteItem(0, 1); | 274 CompleteItem(0, 1); |
| 273 ++expected_notifications; | 275 ++expected_notifications; |
| 274 ASSERT_EQ(expected_notifications, updater_->NotificationCount()); | 276 ASSERT_EQ(expected_notifications, updater_->NotificationCount()); |
| 275 | 277 |
| 276 // First item completes. | 278 // First item completes. |
| 277 updater_->SetAcceptableNotificationItem(Item(0, 0)); | 279 updater_->SetAcceptableNotificationItem(Item(0, 0)); |
| 278 CompleteItem(0, 0); | 280 CompleteItem(0, 0); |
| 279 ++expected_notifications; | 281 ++expected_notifications; |
| 280 ASSERT_EQ(expected_notifications, updater_->NotificationCount()); | 282 ASSERT_EQ(expected_notifications, updater_->NotificationCount()); |
| 281 | 283 |
| 282 updater_->SetAcceptableNotificationItem(NULL); | 284 updater_->SetAcceptableNotificationItem(nullptr); |
| 283 } | 285 } |
| 284 | 286 |
| 285 // Confirm we recognize the situation where we have an unknown size. | 287 // Confirm we recognize the situation where we have an unknown size. |
| 286 TEST_F(DownloadStatusUpdaterTest, UnknownSize) { | 288 TEST_F(DownloadStatusUpdaterTest, UnknownSize) { |
| 287 SetupManagers(1); | 289 SetupManagers(1); |
| 288 AddItems(0, 2, 2); | 290 AddItems(0, 2, 2); |
| 289 LinkManager(0); | 291 LinkManager(0); |
| 290 | 292 |
| 291 // Prime items | 293 // Prime items |
| 292 SetItemValues(0, 0, 10, 20, false); | 294 SetItemValues(0, 0, 10, 20, false); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 SetItemValues(0, 0, 10, 20, false); | 338 SetItemValues(0, 0, 10, 20, false); |
| 337 SetItemValues(0, 1, 50, 60, false); | 339 SetItemValues(0, 1, 50, 60, false); |
| 338 SetItemValues(1, 0, 80, 90, false); | 340 SetItemValues(1, 0, 80, 90, false); |
| 339 | 341 |
| 340 float progress = -1; | 342 float progress = -1; |
| 341 int download_count = -1; | 343 int download_count = -1; |
| 342 EXPECT_TRUE(updater_->GetProgress(&progress, &download_count)); | 344 EXPECT_TRUE(updater_->GetProgress(&progress, &download_count)); |
| 343 EXPECT_FLOAT_EQ((10+50+80)/(20.0f+60+90), progress); | 345 EXPECT_FLOAT_EQ((10+50+80)/(20.0f+60+90), progress); |
| 344 EXPECT_EQ(3, download_count); | 346 EXPECT_EQ(3, download_count); |
| 345 } | 347 } |
| OLD | NEW |