Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 <string> | |
| 6 #include <vector> | |
| 7 | |
| 8 #include "base/bind.h" | |
| 9 #include "base/file_path.h" | |
| 10 #include "base/file_util.h" | |
| 11 #include "base/json/json_file_value_serializer.h" | |
| 12 #include "base/memory/scoped_ptr.h" | |
| 13 #include "base/message_loop.h" | |
| 14 #include "base/path_service.h" | |
| 15 #include "base/scoped_temp_dir.h" | |
| 16 #include "base/stringprintf.h" | |
| 17 #include "base/threading/sequenced_worker_pool.h" | |
| 18 #include "base/values.h" | |
| 19 #include "chrome/browser/chromeos/cros/cros_library.h" | |
| 20 #include "chrome/browser/chromeos/gdata/drive.pb.h" | |
| 21 #include "chrome/browser/chromeos/gdata/drive_api_parser.h" | |
| 22 #include "chrome/browser/chromeos/gdata/drive_webapps_registry.h" | |
| 23 #include "chrome/browser/chromeos/gdata/gdata_file_system.h" | |
| 24 #include "chrome/browser/chromeos/gdata/gdata_test_util.h" | |
| 25 #include "chrome/browser/chromeos/gdata/gdata_uploader.h" | |
| 26 #include "chrome/browser/chromeos/gdata/gdata_util.h" | |
| 27 #include "chrome/browser/chromeos/gdata/mock_directory_change_observer.h" | |
| 28 #include "chrome/browser/chromeos/gdata/mock_drive_cache_observer.h" | |
| 29 #include "chrome/browser/chromeos/gdata/mock_drive_service.h" | |
| 30 #include "chrome/browser/chromeos/gdata/stale_cache_files_remover.h" | |
| 31 #include "chrome/common/chrome_paths.h" | |
| 32 #include "chrome/test/base/testing_profile.h" | |
| 33 #include "content/public/browser/browser_thread.h" | |
| 34 #include "content/public/test/test_browser_thread.h" | |
| 35 #include "testing/gmock/include/gmock/gmock.h" | |
| 36 #include "testing/gtest/include/gtest/gtest.h" | |
| 37 | |
| 38 using ::testing::AtLeast; | |
| 39 using ::testing::Eq; | |
| 40 using ::testing::NotNull; | |
| 41 using ::testing::Return; | |
| 42 using ::testing::StrictMock; | |
| 43 using ::testing::_; | |
| 44 | |
| 45 namespace gdata { | |
| 46 namespace { | |
| 47 | |
| 48 const int64 kLotsOfSpace = kMinFreeSpace * 10; | |
| 49 | |
| 50 // Callback for DriveCache::StoreOnUIThread used in RemoveStaleCacheFiles test. | |
| 51 // Verifies that the result is not an error. | |
| 52 void VerifyCacheFileState(GDataFileError error, | |
| 53 const std::string& resource_id, | |
| 54 const std::string& md5) { | |
| 55 EXPECT_EQ(GDATA_FILE_OK, error); | |
| 56 } | |
| 57 | |
| 58 void GetEntryInfoByPathCallback( | |
|
satorux1
2012/08/28 15:38:02
I thought we had this in gdata_test_util.h. If so,
yoshiki
2012/08/28 18:11:44
Thanks, I didn't know that. Done.
| |
| 59 GDataFileError* error_out, | |
| 60 scoped_ptr<DriveEntryProto>* entry_proto_out, | |
| 61 GDataFileError error_in, | |
| 62 scoped_ptr<DriveEntryProto> entry_proto_in) { | |
| 63 *error_out = error_in; | |
| 64 *entry_proto_out = entry_proto_in.Pass(); | |
| 65 } | |
| 66 | |
| 67 void GetEntryInfoByResourceIdCallback( | |
|
satorux1
2012/08/28 15:38:02
ditto.
yoshiki
2012/08/28 18:11:44
Done.
| |
| 68 GDataFileError* error_out, | |
| 69 scoped_ptr<DriveEntryProto>* entry_proto_out, | |
| 70 GDataFileError error_in, | |
| 71 const FilePath& gdata_file_path, | |
| 72 scoped_ptr<DriveEntryProto> entry_proto_in) { | |
| 73 *error_out = error_in; | |
| 74 *entry_proto_out = entry_proto_in.Pass(); | |
| 75 } | |
| 76 | |
| 77 // Returns the absolute path for a test file stored under | |
| 78 // chrome/test/data/chromeos/gdata. | |
| 79 FilePath GetTestFilePath(const FilePath::StringType& base_name) { | |
| 80 FilePath path; | |
| 81 std::string error; | |
| 82 PathService::Get(chrome::DIR_TEST_DATA, &path); | |
| 83 path = path.AppendASCII("chromeos") | |
| 84 .AppendASCII("gdata") | |
| 85 .AppendASCII(base_name.c_str()); | |
| 86 EXPECT_TRUE(file_util::PathExists(path)) << | |
| 87 "Couldn't find " << path.value(); | |
| 88 return path; | |
| 89 } | |
| 90 | |
| 91 // Loads a test JSON file as a base::Value. | |
| 92 base::Value* LoadJSONFile(const std::string& base_name) { | |
| 93 FilePath path = GetTestFilePath(base_name); | |
| 94 | |
| 95 std::string error; | |
| 96 JSONFileValueSerializer serializer(path); | |
| 97 base::Value* value = serializer.Deserialize(NULL, &error); | |
| 98 EXPECT_TRUE(value) << | |
| 99 "Parse error " << path.value() << ": " << error; | |
| 100 return value; | |
| 101 } | |
| 102 | |
| 103 } // namespace | |
| 104 | |
| 105 class MockFreeDiskSpaceGetter : public FreeDiskSpaceGetterInterface { | |
|
satorux1
2012/08/28 15:38:02
do we define the same mock class elsewhere? if so,
yoshiki
2012/08/28 18:11:44
Done. Moved to gdata_test_util.h
| |
| 106 public: | |
| 107 virtual ~MockFreeDiskSpaceGetter() {} | |
| 108 MOCK_CONST_METHOD0(AmountOfFreeDiskSpace, int64()); | |
| 109 }; | |
| 110 | |
| 111 class MockGDataUploader : public GDataUploaderInterface { | |
|
satorux1
2012/08/28 15:38:02
ditto.
yoshiki
2012/08/28 18:11:44
Done. Moved to gdata_test_util.h
| |
| 112 public: | |
| 113 virtual ~MockGDataUploader() {} | |
| 114 // This function is not mockable by gmock. | |
| 115 virtual int UploadNewFile( | |
| 116 scoped_ptr<UploadFileInfo> upload_file_info) OVERRIDE { | |
| 117 const int kUploadId = 123; | |
| 118 return kUploadId; | |
| 119 } | |
| 120 | |
| 121 // This function is not mockable by gmock. | |
| 122 virtual int StreamExistingFile( | |
| 123 scoped_ptr<UploadFileInfo> upload_file_info) OVERRIDE { return 0; } | |
| 124 | |
| 125 MOCK_METHOD6(UploadExistingFile, | |
| 126 int(const GURL& upload_location, | |
| 127 const FilePath& gdata_file_path, | |
| 128 const FilePath& local_file_path, | |
| 129 int64 file_size, | |
| 130 const std::string& content_type, | |
| 131 const UploadFileInfo::UploadCompletionCallback& callback)); | |
| 132 | |
| 133 MOCK_METHOD2(UpdateUpload, void(int upload_id, | |
| 134 content::DownloadItem* download)); | |
| 135 MOCK_CONST_METHOD1(GetUploadedBytes, int64(int upload_id)); | |
| 136 }; | |
| 137 | |
| 138 class MockDriveWebAppsRegistry : public DriveWebAppsRegistryInterface { | |
|
satorux1
2012/08/28 15:38:02
ditto.
yoshiki
2012/08/28 18:11:44
Done. Moved to gdata_test_util.h
| |
| 139 public: | |
| 140 virtual ~MockDriveWebAppsRegistry() {} | |
| 141 | |
| 142 MOCK_METHOD3(GetWebAppsForFile, void(const FilePath& file, | |
| 143 const std::string& mime_type, | |
| 144 ScopedVector<DriveWebAppInfo>* apps)); | |
| 145 MOCK_METHOD1(GetExtensionsForWebStoreApp, | |
| 146 std::set<std::string>(const std::string& web_store_id)); | |
| 147 MOCK_METHOD1(UpdateFromFeed, void(const AccountMetadataFeed& metadata)); | |
| 148 MOCK_METHOD1(UpdateFromApplicationList, void(const AppList& applist)); | |
| 149 }; | |
| 150 | |
| 151 class StaleCacheFileRemover : public testing::Test { | |
|
satorux1
2012/08/28 15:38:02
StaleCacheFilesRemoverTest
yoshiki
2012/08/28 18:11:44
Done.
| |
| 152 protected: | |
| 153 StaleCacheFileRemover() | |
| 154 : ui_thread_(content::BrowserThread::UI, &message_loop_), | |
| 155 io_thread_(content::BrowserThread::IO), | |
| 156 cache_(NULL), | |
| 157 file_system_(NULL), | |
| 158 mock_drive_service_(NULL), | |
| 159 mock_webapps_registry_(NULL), | |
| 160 root_feed_changestamp_(0) { | |
| 161 } | |
| 162 | |
| 163 virtual void SetUp() OVERRIDE { | |
| 164 chromeos::CrosLibrary::Initialize(true /* use_stub */); | |
| 165 io_thread_.StartIOThread(); | |
| 166 | |
| 167 profile_.reset(new TestingProfile); | |
| 168 | |
| 169 // Allocate and keep a pointer to the mock, and inject it into the | |
| 170 // GDataFileSystem object, which will own the mock object. | |
| 171 mock_drive_service_ = new StrictMock<MockDriveService>; | |
| 172 | |
| 173 EXPECT_CALL(*mock_drive_service_, Initialize(profile_.get())).Times(1); | |
| 174 | |
| 175 // Likewise, this will be owned by GDataFileSystem. | |
| 176 mock_free_disk_space_checker_ = new StrictMock<MockFreeDiskSpaceGetter>; | |
| 177 SetFreeDiskSpaceGetterForTesting(mock_free_disk_space_checker_); | |
| 178 | |
| 179 scoped_refptr<base::SequencedWorkerPool> pool = | |
| 180 content::BrowserThread::GetBlockingPool(); | |
| 181 blocking_task_runner_ = | |
| 182 pool->GetSequencedTaskRunner(pool->GetSequenceToken()); | |
| 183 | |
| 184 cache_ = DriveCache::CreateDriveCacheOnUIThread( | |
| 185 DriveCache::GetCacheRootPath(profile_.get()), blocking_task_runner_); | |
| 186 | |
| 187 mock_uploader_.reset(new StrictMock<MockGDataUploader>); | |
| 188 mock_webapps_registry_.reset(new StrictMock<MockDriveWebAppsRegistry>); | |
| 189 | |
| 190 ASSERT_FALSE(file_system_); | |
| 191 file_system_ = new GDataFileSystem(profile_.get(), | |
| 192 cache_, | |
| 193 mock_drive_service_, | |
| 194 mock_uploader_.get(), | |
| 195 mock_webapps_registry_.get(), | |
| 196 blocking_task_runner_); | |
| 197 | |
| 198 mock_cache_observer_.reset(new StrictMock<MockDriveCacheObserver>); | |
| 199 cache_->AddObserver(mock_cache_observer_.get()); | |
| 200 | |
| 201 mock_directory_observer_.reset(new StrictMock<MockDirectoryChangeObserver>); | |
| 202 file_system_->AddObserver(mock_directory_observer_.get()); | |
| 203 | |
| 204 file_system_->Initialize(); | |
| 205 cache_->RequestInitializeOnUIThreadForTesting(); | |
| 206 | |
| 207 stale_cache_files_remover_.reset(new StaleCacheFilesRemover(file_system_, | |
| 208 cache_)); | |
| 209 | |
| 210 test_util::RunBlockingPoolTask(); | |
| 211 } | |
| 212 | |
| 213 virtual void TearDown() OVERRIDE { | |
| 214 ASSERT_TRUE(file_system_); | |
| 215 stale_cache_files_remover_.reset(); | |
| 216 EXPECT_CALL(*mock_drive_service_, CancelAll()).Times(1); | |
| 217 delete file_system_; | |
| 218 file_system_ = NULL; | |
| 219 delete mock_drive_service_; | |
| 220 mock_drive_service_ = NULL; | |
| 221 SetFreeDiskSpaceGetterForTesting(NULL); | |
| 222 cache_->DestroyOnUIThread(); | |
| 223 // The cache destruction requires to post a task to the blocking pool. | |
| 224 test_util::RunBlockingPoolTask(); | |
| 225 | |
| 226 profile_.reset(NULL); | |
| 227 chromeos::CrosLibrary::Shutdown(); | |
| 228 } | |
| 229 | |
| 230 // Loads test json file as root ("/drive") element. | |
| 231 void LoadRootFeedDocument(const std::string& filename) { | |
| 232 LoadChangeFeed(filename, 0); | |
| 233 } | |
| 234 | |
| 235 void LoadChangeFeed(const std::string& filename, | |
|
satorux1
2012/08/28 15:38:02
if this is used elsewhere, please put this in gdat
yoshiki
2012/08/28 18:11:44
Moved it to test_util and removed LoadChangeFeed()
| |
| 236 int largest_changestamp) { | |
| 237 std::string error; | |
| 238 scoped_ptr<Value> document(LoadJSONFile(filename)); | |
| 239 ASSERT_TRUE(document.get()); | |
| 240 ASSERT_TRUE(document->GetType() == Value::TYPE_DICTIONARY); | |
| 241 scoped_ptr<DocumentFeed> document_feed( | |
| 242 DocumentFeed::ExtractAndParse(*document)); | |
| 243 ASSERT_TRUE(document_feed.get()); | |
| 244 std::vector<DocumentFeed*> feed_list; | |
| 245 feed_list.push_back(document_feed.get()); | |
| 246 ASSERT_TRUE(UpdateContent(feed_list, largest_changestamp)); | |
| 247 } | |
| 248 | |
| 249 // Updates the content of directory under |directory_path| with parsed feed | |
| 250 // |value|. | |
| 251 bool UpdateContent(const std::vector<DocumentFeed*>& list, | |
| 252 int largest_changestamp) { | |
| 253 GURL unused; | |
| 254 return file_system_->UpdateFromFeedForTesting( | |
| 255 list, | |
| 256 largest_changestamp, | |
| 257 root_feed_changestamp_++) == GDATA_FILE_OK; | |
| 258 } | |
| 259 | |
| 260 MessageLoopForUI message_loop_; | |
| 261 // The order of the test threads is important, do not change the order. | |
| 262 // See also content/browser/browser_thread_impl.cc. | |
| 263 content::TestBrowserThread ui_thread_; | |
| 264 content::TestBrowserThread io_thread_; | |
| 265 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_; | |
| 266 scoped_ptr<TestingProfile> profile_; | |
| 267 DriveCache* cache_; | |
| 268 scoped_ptr<StrictMock<MockGDataUploader> > mock_uploader_; | |
| 269 GDataFileSystem* file_system_; | |
| 270 StrictMock<MockDriveService>* mock_drive_service_; | |
| 271 scoped_ptr<StrictMock<MockDriveWebAppsRegistry> > mock_webapps_registry_; | |
| 272 StrictMock<MockFreeDiskSpaceGetter>* mock_free_disk_space_checker_; | |
| 273 scoped_ptr<StrictMock<MockDriveCacheObserver> > mock_cache_observer_; | |
| 274 scoped_ptr<StrictMock<MockDirectoryChangeObserver> > mock_directory_observer_; | |
| 275 scoped_ptr<StaleCacheFilesRemover> stale_cache_files_remover_; | |
| 276 | |
| 277 int root_feed_changestamp_; | |
| 278 }; | |
| 279 | |
| 280 TEST_F(StaleCacheFileRemover, RemoveStaleCacheFiles) { | |
| 281 FilePath dummy_file = GetTestFilePath("root_feed.json"); | |
| 282 std::string resource_id("pdf:1a2b3c"); | |
| 283 std::string md5("abcdef0123456789"); | |
| 284 | |
| 285 EXPECT_CALL(*mock_free_disk_space_checker_, AmountOfFreeDiskSpace()) | |
| 286 .Times(AtLeast(1)).WillRepeatedly(Return(kLotsOfSpace)); | |
| 287 | |
| 288 // Create a stale cache file. | |
| 289 cache_->StoreOnUIThread(resource_id, md5, dummy_file, | |
| 290 DriveCache::FILE_OPERATION_COPY, | |
| 291 base::Bind(&gdata::VerifyCacheFileState)); | |
| 292 test_util::RunBlockingPoolTask(); | |
| 293 | |
| 294 // Verify that the cache file exists. | |
| 295 FilePath path = cache_->GetCacheFilePath(resource_id, | |
| 296 md5, | |
| 297 DriveCache::CACHE_TYPE_TMP, | |
| 298 DriveCache::CACHED_FILE_FROM_SERVER); | |
| 299 EXPECT_TRUE(file_util::PathExists(path)); | |
| 300 | |
| 301 // Verify that the corresponding file entry doesn't exist. | |
| 302 EXPECT_CALL(*mock_drive_service_, GetAccountMetadata(_)).Times(1); | |
| 303 EXPECT_CALL(*mock_drive_service_, GetDocuments(Eq(GURL()), _, "", _, _)) | |
| 304 .Times(1); | |
| 305 EXPECT_CALL(*mock_webapps_registry_, UpdateFromFeed(_)).Times(1); | |
| 306 | |
| 307 GDataFileError error(GDATA_FILE_OK); | |
| 308 scoped_ptr<DriveEntryProto> entry_proto; | |
| 309 file_system_->GetEntryInfoByResourceId( | |
| 310 resource_id, | |
| 311 base::Bind(&GetEntryInfoByResourceIdCallback, | |
| 312 &error, | |
| 313 &entry_proto)); | |
| 314 test_util::RunBlockingPoolTask(); | |
| 315 EXPECT_EQ(GDATA_FILE_ERROR_NOT_FOUND, error); | |
| 316 | |
| 317 file_system_->GetEntryInfoByPath( | |
| 318 path, | |
| 319 base::Bind(&GetEntryInfoByPathCallback, | |
| 320 &error, | |
| 321 &entry_proto)); | |
| 322 test_util::RunBlockingPoolTask(); | |
| 323 EXPECT_EQ(GDATA_FILE_ERROR_NOT_FOUND, error); | |
| 324 EXPECT_FALSE(entry_proto.get()); | |
| 325 | |
| 326 // Load a root feed. | |
| 327 LoadRootFeedDocument("root_feed.json"); | |
| 328 | |
| 329 // Wait for StaleCacheFilesRemover to finish cleaning up the stale file. | |
| 330 test_util::RunBlockingPoolTask(); | |
| 331 | |
| 332 // Verify that the cache file is deleted. | |
| 333 path = cache_->GetCacheFilePath(resource_id, | |
| 334 md5, | |
| 335 DriveCache::CACHE_TYPE_TMP, | |
| 336 DriveCache::CACHED_FILE_FROM_SERVER); | |
| 337 EXPECT_FALSE(file_util::PathExists(path)); | |
| 338 } | |
| 339 | |
| 340 } // namespace gdata | |
| OLD | NEW |