| 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 "chrome/browser/chromeos/gdata/gdata_cache_metadata.h" | |
| 6 | |
| 7 #include "base/file_util.h" | |
| 8 #include "base/scoped_temp_dir.h" | |
| 9 #include "chrome/browser/chromeos/gdata/drive.pb.h" | |
| 10 #include "chrome/browser/chromeos/gdata/gdata_test_util.h" | |
| 11 #include "chrome/browser/chromeos/gdata/gdata_util.h" | |
| 12 #include "testing/gtest/include/gtest/gtest.h" | |
| 13 | |
| 14 namespace gdata { | |
| 15 | |
| 16 class GDataCacheMetadataTest : public testing::Test { | |
| 17 public: | |
| 18 GDataCacheMetadataTest() {} | |
| 19 | |
| 20 virtual void SetUp() OVERRIDE { | |
| 21 // Create cache directories. | |
| 22 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | |
| 23 cache_paths_ = GDataCache::GetCachePaths(temp_dir_.path()); | |
| 24 ASSERT_TRUE(GDataCache::CreateCacheDirectories(cache_paths_)); | |
| 25 | |
| 26 persistent_directory_ = cache_paths_[GDataCache::CACHE_TYPE_PERSISTENT]; | |
| 27 tmp_directory_ = cache_paths_[GDataCache::CACHE_TYPE_TMP]; | |
| 28 pinned_directory_ = cache_paths_[GDataCache::CACHE_TYPE_PINNED]; | |
| 29 outgoing_directory_ = cache_paths_[GDataCache::CACHE_TYPE_OUTGOING]; | |
| 30 } | |
| 31 | |
| 32 virtual void TearDown() OVERRIDE { | |
| 33 metadata_.reset(); | |
| 34 } | |
| 35 | |
| 36 // Sets up the GDataCacheMetadata object. | |
| 37 void SetUpCacheMetadata() { | |
| 38 metadata_ = GDataCacheMetadata::CreateGDataCacheMetadata(NULL).Pass(); | |
| 39 metadata_->Initialize(cache_paths_); | |
| 40 } | |
| 41 | |
| 42 // Sets up the cache directories with various files, including stale | |
| 43 // symbolic links etc. Should be called before SetUpCacheMetadata(). | |
| 44 void SetUpCacheWithVariousFiles() { | |
| 45 // Create some files in persistent directory. | |
| 46 // | |
| 47 CreateFile(persistent_directory_.AppendASCII("id_foo.md5foo")); | |
| 48 CreateFile(persistent_directory_.AppendASCII("id_bar.local")); | |
| 49 // "id_baz" is dirty but does not have a symlink in outgoing | |
| 50 // directory. This file should be removed. | |
| 51 CreateFile(persistent_directory_.AppendASCII("id_baz.local")); | |
| 52 // "id_bad" is in persistent directory, but does not have a link in | |
| 53 // pinned directory. This file should be removed. | |
| 54 CreateFile(persistent_directory_.AppendASCII("id_bad.md5bad")); | |
| 55 // "id_symlink" is invalid, as symlink is not allowed here. This should | |
| 56 // be moreved. | |
| 57 CreateSymbolicLink(FilePath::FromUTF8Unsafe(util::kSymLinkToDevNull), | |
| 58 persistent_directory_.AppendASCII("id_symlink")); | |
| 59 | |
| 60 // Create some files in tmp directory. | |
| 61 // | |
| 62 CreateFile(tmp_directory_.AppendASCII("id_qux.md5qux")); | |
| 63 // "id_quux" is invalid as we shouldn't have a dirty file in "tmp". | |
| 64 CreateFile(tmp_directory_.AppendASCII("id_quux.local")); | |
| 65 // "id_symlink_tmp" is invalid, as symlink is not allowed here. This | |
| 66 // should be moreved. | |
| 67 CreateSymbolicLink(FilePath::FromUTF8Unsafe(util::kSymLinkToDevNull), | |
| 68 tmp_directory_.AppendASCII("id_symlink_tmp")); | |
| 69 | |
| 70 // Create symbolic links in pinned directory. | |
| 71 // | |
| 72 // "id_foo" is pinned, and present locally. | |
| 73 CreateSymbolicLink(persistent_directory_.AppendASCII("id_foo.md5foo"), | |
| 74 pinned_directory_.AppendASCII("id_foo")); | |
| 75 // "id_corge" is pinned, but not present locally. It's properly pointing | |
| 76 // to /dev/null. | |
| 77 CreateSymbolicLink(FilePath::FromUTF8Unsafe(util::kSymLinkToDevNull), | |
| 78 pinned_directory_.AppendASCII("id_corge")); | |
| 79 // "id_dangling" is pointing to a non-existent file. The symlink should | |
| 80 // be removed. | |
| 81 CreateSymbolicLink(persistent_directory_.AppendASCII("id_dangling.md5foo"), | |
| 82 pinned_directory_.AppendASCII("id_dangling")); | |
| 83 // "id_outside" is pointing to a file outside of persistent | |
| 84 // directory. The symlink should be removed. | |
| 85 CreateSymbolicLink(tmp_directory_.AppendASCII("id_qux.md5qux"), | |
| 86 pinned_directory_.AppendASCII("id_outside")); | |
| 87 // "id_not_symlink" is not a symlink. This should be removed. | |
| 88 CreateFile(pinned_directory_.AppendASCII("id_not_symlink")); | |
| 89 | |
| 90 // Create symbolic links in outgoing directory. | |
| 91 // | |
| 92 // "id_bar" is dirty and committed. | |
| 93 CreateSymbolicLink(persistent_directory_.AppendASCII("id_bar.local"), | |
| 94 outgoing_directory_.AppendASCII("id_bar")); | |
| 95 // "id_foo" is not dirty. This symlink should be removed. | |
| 96 CreateSymbolicLink(persistent_directory_.AppendASCII("id_foo.md5foo"), | |
| 97 outgoing_directory_.AppendASCII("id_foo")); | |
| 98 } | |
| 99 | |
| 100 // Create a file at |file_path|. | |
| 101 void CreateFile(const FilePath& file_path) { | |
| 102 const std::string kFoo = "foo"; | |
| 103 ASSERT_TRUE(file_util::WriteFile(file_path, kFoo.data(), kFoo.size())) | |
| 104 << ": " << file_path.value(); | |
| 105 } | |
| 106 | |
| 107 // Create an symlink to |target| at |symlink|. | |
| 108 void CreateSymbolicLink(const FilePath& target, const FilePath& symlink) { | |
| 109 ASSERT_TRUE(file_util::CreateSymbolicLink(target, symlink)) | |
| 110 << ": " << target.value() << ": " << symlink.value(); | |
| 111 } | |
| 112 | |
| 113 protected: | |
| 114 // Helper function to insert an item with key |resource_id| into |cache_map|. | |
| 115 // |md5| and |cache_state| are used to create the value CacheEntry. | |
| 116 void InsertIntoMap(GDataCacheMetadata::CacheMap* cache_map, | |
| 117 const std::string& resource_id, | |
| 118 const DriveCacheEntry& cache_entry) { | |
| 119 cache_map->insert(std::make_pair( | |
| 120 resource_id, cache_entry)); | |
| 121 } | |
| 122 | |
| 123 // Adds all entries in |cache_map| to the metadata storage. | |
| 124 void AddAllMapEntries(const GDataCacheMetadata::CacheMap& cache_map) { | |
| 125 for (GDataCacheMetadata::CacheMap::const_iterator iter = cache_map.begin(); | |
| 126 iter != cache_map.end(); ++iter) { | |
| 127 metadata_->AddOrUpdateCacheEntry(iter->first, iter->second); | |
| 128 } | |
| 129 } | |
| 130 | |
| 131 ScopedTempDir temp_dir_; | |
| 132 scoped_ptr<GDataCacheMetadata> metadata_; | |
| 133 std::vector<FilePath> cache_paths_; | |
| 134 FilePath persistent_directory_; | |
| 135 FilePath tmp_directory_; | |
| 136 FilePath pinned_directory_; | |
| 137 FilePath outgoing_directory_; | |
| 138 }; | |
| 139 | |
| 140 // Test all the methods of GDataCacheMetadata except for | |
| 141 // RemoveTemporaryFiles. | |
| 142 TEST_F(GDataCacheMetadataTest, CacheTest) { | |
| 143 SetUpCacheMetadata(); | |
| 144 | |
| 145 // Save an initial entry. | |
| 146 std::string test_resource_id("test_resource_id"); | |
| 147 std::string test_file_md5("test_file_md5"); | |
| 148 { | |
| 149 DriveCacheEntry new_cache_entry; | |
| 150 new_cache_entry.set_md5(test_file_md5); | |
| 151 new_cache_entry.set_is_present(true); | |
| 152 new_cache_entry.set_is_persistent(true); | |
| 153 metadata_->AddOrUpdateCacheEntry(test_resource_id, new_cache_entry); | |
| 154 } | |
| 155 | |
| 156 // Test that the entry can be retrieved. | |
| 157 DriveCacheEntry cache_entry; | |
| 158 ASSERT_TRUE(metadata_->GetCacheEntry( | |
| 159 test_resource_id, test_file_md5, &cache_entry)); | |
| 160 EXPECT_EQ(test_file_md5, cache_entry.md5()); | |
| 161 EXPECT_TRUE(cache_entry.is_present()); | |
| 162 EXPECT_TRUE(cache_entry.is_persistent()); | |
| 163 | |
| 164 // Empty md5 should also work. | |
| 165 ASSERT_TRUE(metadata_->GetCacheEntry( | |
| 166 test_resource_id, std::string(), &cache_entry)); | |
| 167 EXPECT_EQ(test_file_md5, cache_entry.md5()); | |
| 168 | |
| 169 // resource_id doesn't exist. | |
| 170 EXPECT_FALSE(metadata_->GetCacheEntry( | |
| 171 "not_found_resource_id", std::string(), &cache_entry)); | |
| 172 | |
| 173 // md5 doesn't match. | |
| 174 EXPECT_FALSE(metadata_->GetCacheEntry( | |
| 175 test_resource_id, "mismatch_md5", &cache_entry)); | |
| 176 | |
| 177 // Update all attributes. | |
| 178 test_file_md5 = "test_file_md5_2"; | |
| 179 { | |
| 180 DriveCacheEntry updated_cache_entry; | |
| 181 updated_cache_entry.set_md5(test_file_md5); | |
| 182 updated_cache_entry.set_is_pinned(true); | |
| 183 metadata_->AddOrUpdateCacheEntry(test_resource_id, updated_cache_entry); | |
| 184 } | |
| 185 | |
| 186 // Make sure the values took. | |
| 187 ASSERT_TRUE(metadata_->GetCacheEntry( | |
| 188 test_resource_id, test_file_md5, &cache_entry)); | |
| 189 EXPECT_EQ(test_file_md5, cache_entry.md5()); | |
| 190 EXPECT_TRUE(cache_entry.is_pinned()); | |
| 191 | |
| 192 // Empty m5 should work. | |
| 193 ASSERT_TRUE(metadata_->GetCacheEntry( | |
| 194 test_resource_id, std::string(), &cache_entry)); | |
| 195 EXPECT_EQ(test_file_md5, cache_entry.md5()); | |
| 196 | |
| 197 // Test dirty cache. | |
| 198 test_file_md5 = "test_file_md5_3"; | |
| 199 { | |
| 200 DriveCacheEntry new_cache_entry; | |
| 201 new_cache_entry.set_md5(test_file_md5); | |
| 202 new_cache_entry.set_is_dirty(true); | |
| 203 metadata_->AddOrUpdateCacheEntry(test_resource_id, new_cache_entry); | |
| 204 } | |
| 205 | |
| 206 // Make sure the values took. | |
| 207 ASSERT_TRUE(metadata_->GetCacheEntry( | |
| 208 test_resource_id, test_file_md5, &cache_entry)); | |
| 209 EXPECT_EQ(test_file_md5, cache_entry.md5()); | |
| 210 EXPECT_TRUE(cache_entry.is_dirty()); | |
| 211 | |
| 212 // Empty md5 should work. | |
| 213 ASSERT_TRUE(metadata_->GetCacheEntry( | |
| 214 test_resource_id, std::string(), &cache_entry)); | |
| 215 EXPECT_EQ(test_file_md5, cache_entry.md5()); | |
| 216 | |
| 217 // Mismatched md5 should also work for dirty entries. | |
| 218 ASSERT_TRUE(metadata_->GetCacheEntry( | |
| 219 test_resource_id, "mismatch_md5", &cache_entry)); | |
| 220 EXPECT_EQ(test_file_md5, cache_entry.md5()); | |
| 221 | |
| 222 // Remove the entry. | |
| 223 metadata_->RemoveCacheEntry(test_resource_id); | |
| 224 EXPECT_FALSE(metadata_->GetCacheEntry( | |
| 225 test_resource_id, std::string(), &cache_entry)); | |
| 226 | |
| 227 // Add another one. | |
| 228 test_resource_id = "test_resource_id_2"; | |
| 229 test_file_md5 = "test_file_md5_4"; | |
| 230 { | |
| 231 DriveCacheEntry new_cache_entry; | |
| 232 new_cache_entry.set_md5(test_file_md5); | |
| 233 new_cache_entry.set_is_present(true); | |
| 234 metadata_->AddOrUpdateCacheEntry(test_resource_id, new_cache_entry); | |
| 235 } | |
| 236 | |
| 237 // Make sure the values took. | |
| 238 ASSERT_TRUE(metadata_->GetCacheEntry( | |
| 239 test_resource_id, test_file_md5, &cache_entry)); | |
| 240 EXPECT_EQ(test_file_md5, cache_entry.md5()); | |
| 241 EXPECT_TRUE(cache_entry.is_present()); | |
| 242 } | |
| 243 | |
| 244 TEST_F(GDataCacheMetadataTest, Initialization) { | |
| 245 using file_util::PathExists; | |
| 246 using file_util::IsLink; | |
| 247 SetUpCacheWithVariousFiles(); | |
| 248 | |
| 249 // Some files are removed during cache initialization. Make sure these | |
| 250 // exist beforehand. | |
| 251 EXPECT_TRUE(PathExists(persistent_directory_.AppendASCII("id_baz.local"))); | |
| 252 EXPECT_TRUE(PathExists(persistent_directory_.AppendASCII("id_bad.md5bad"))); | |
| 253 EXPECT_TRUE(PathExists(tmp_directory_.AppendASCII("id_quux.local"))); | |
| 254 EXPECT_TRUE(PathExists(pinned_directory_.AppendASCII("id_not_symlink"))); | |
| 255 EXPECT_TRUE(IsLink(pinned_directory_.AppendASCII("id_dangling"))); | |
| 256 EXPECT_TRUE(IsLink(pinned_directory_.AppendASCII("id_outside"))); | |
| 257 EXPECT_TRUE(IsLink(outgoing_directory_.AppendASCII("id_foo"))); | |
| 258 EXPECT_TRUE(IsLink(persistent_directory_.AppendASCII("id_symlink"))); | |
| 259 EXPECT_TRUE(IsLink(tmp_directory_.AppendASCII("id_symlink_tmp"))); | |
| 260 | |
| 261 SetUpCacheMetadata(); | |
| 262 | |
| 263 // Check contents in "persistent" directory. | |
| 264 // | |
| 265 // "id_foo" is present and pinned. | |
| 266 DriveCacheEntry cache_entry; | |
| 267 ASSERT_TRUE(metadata_->GetCacheEntry("id_foo", "md5foo", &cache_entry)); | |
| 268 EXPECT_EQ("md5foo", cache_entry.md5()); | |
| 269 EXPECT_EQ(GDataCache::CACHE_TYPE_PERSISTENT, | |
| 270 GDataCache::GetSubDirectoryType(cache_entry)); | |
| 271 EXPECT_TRUE(test_util::CacheStatesEqual( | |
| 272 test_util::ToCacheEntry(test_util::TEST_CACHE_STATE_PRESENT | | |
| 273 test_util::TEST_CACHE_STATE_PINNED | | |
| 274 test_util::TEST_CACHE_STATE_PERSISTENT), | |
| 275 cache_entry)); | |
| 276 EXPECT_TRUE(PathExists(persistent_directory_.AppendASCII("id_foo.md5foo"))); | |
| 277 EXPECT_TRUE(PathExists(pinned_directory_.AppendASCII("id_foo"))); | |
| 278 // The invalid symlink in "outgoing" should be removed. | |
| 279 EXPECT_FALSE(PathExists(outgoing_directory_.AppendASCII("id_foo"))); | |
| 280 | |
| 281 // "id_bar" is present and dirty. | |
| 282 ASSERT_TRUE(metadata_->GetCacheEntry("id_bar", "", &cache_entry)); | |
| 283 EXPECT_EQ("local", cache_entry.md5()); | |
| 284 EXPECT_EQ(GDataCache::CACHE_TYPE_PERSISTENT, | |
| 285 GDataCache::GetSubDirectoryType(cache_entry)); | |
| 286 EXPECT_TRUE(test_util::CacheStatesEqual( | |
| 287 test_util::ToCacheEntry(test_util::TEST_CACHE_STATE_PRESENT | | |
| 288 test_util::TEST_CACHE_STATE_DIRTY | | |
| 289 test_util::TEST_CACHE_STATE_PERSISTENT), | |
| 290 cache_entry)); | |
| 291 EXPECT_TRUE(PathExists(persistent_directory_.AppendASCII("id_bar.local"))); | |
| 292 EXPECT_TRUE(PathExists(outgoing_directory_.AppendASCII("id_bar"))); | |
| 293 | |
| 294 // "id_baz" should be removed during cache initialization. | |
| 295 EXPECT_FALSE(metadata_->GetCacheEntry("id_baz", "", &cache_entry)); | |
| 296 EXPECT_FALSE(PathExists(persistent_directory_.AppendASCII("id_baz.local"))); | |
| 297 | |
| 298 // "id_bad" should be removed during cache initialization. | |
| 299 EXPECT_FALSE(metadata_->GetCacheEntry("id_bad", "md5bad", &cache_entry)); | |
| 300 EXPECT_FALSE(PathExists(persistent_directory_.AppendASCII("id_bad.md5bad"))); | |
| 301 | |
| 302 // "id_symlink" should be removed during cache initialization. | |
| 303 EXPECT_FALSE(metadata_->GetCacheEntry("id_symlink", "", &cache_entry)); | |
| 304 EXPECT_FALSE(PathExists(persistent_directory_.AppendASCII("id_symlink"))); | |
| 305 | |
| 306 // Check contents in "tmp" directory. | |
| 307 // | |
| 308 // "id_qux" is just present in tmp directory. | |
| 309 ASSERT_TRUE(metadata_->GetCacheEntry("id_qux", "md5qux", &cache_entry)); | |
| 310 EXPECT_EQ("md5qux", cache_entry.md5()); | |
| 311 EXPECT_EQ(GDataCache::CACHE_TYPE_TMP, | |
| 312 GDataCache::GetSubDirectoryType(cache_entry)); | |
| 313 EXPECT_TRUE(test_util::CacheStatesEqual( | |
| 314 test_util::ToCacheEntry(test_util::TEST_CACHE_STATE_PRESENT), | |
| 315 cache_entry)); | |
| 316 EXPECT_TRUE(PathExists(tmp_directory_.AppendASCII("id_qux.md5qux"))); | |
| 317 | |
| 318 // "id_quux" should be removed during cache initialization. | |
| 319 EXPECT_FALSE(metadata_->GetCacheEntry("id_quux", "md5qux", &cache_entry)); | |
| 320 EXPECT_FALSE(PathExists(pinned_directory_.AppendASCII("id_quux.local"))); | |
| 321 | |
| 322 // "id_symlink_tmp" should be removed during cache initialization. | |
| 323 EXPECT_FALSE(metadata_->GetCacheEntry("id_symlink_tmp", "", &cache_entry)); | |
| 324 EXPECT_FALSE(PathExists(pinned_directory_.AppendASCII("id_symlink_tmp"))); | |
| 325 | |
| 326 // Check contents in "pinned" directory. | |
| 327 // | |
| 328 // "id_corge" is pinned but not present. | |
| 329 ASSERT_TRUE(metadata_->GetCacheEntry("id_corge", "", &cache_entry)); | |
| 330 EXPECT_EQ("", cache_entry.md5()); | |
| 331 EXPECT_TRUE(test_util::CacheStatesEqual( | |
| 332 test_util::ToCacheEntry(test_util::TEST_CACHE_STATE_PINNED), | |
| 333 cache_entry)); | |
| 334 EXPECT_TRUE(IsLink(pinned_directory_.AppendASCII("id_corge"))); | |
| 335 | |
| 336 // "id_dangling" should be removed during cache initialization. | |
| 337 EXPECT_FALSE(metadata_->GetCacheEntry("id_dangling", "", &cache_entry)); | |
| 338 EXPECT_FALSE(IsLink(pinned_directory_.AppendASCII("id_dangling"))); | |
| 339 | |
| 340 // "id_outside" should be removed during cache initialization. | |
| 341 EXPECT_FALSE(metadata_->GetCacheEntry("id_outside", "", &cache_entry)); | |
| 342 EXPECT_FALSE(IsLink(pinned_directory_.AppendASCII("id_outside"))); | |
| 343 | |
| 344 // "id_not_symlink" should be removed during cache initialization. | |
| 345 EXPECT_FALSE(metadata_->GetCacheEntry("id_not_symlink", "", &cache_entry)); | |
| 346 EXPECT_FALSE(IsLink(pinned_directory_.AppendASCII("id_not_symlink"))); | |
| 347 } | |
| 348 | |
| 349 // Test GDataCacheMetadata::RemoveTemporaryFiles. | |
| 350 TEST_F(GDataCacheMetadataTest, RemoveTemporaryFilesTest) { | |
| 351 SetUpCacheMetadata(); | |
| 352 | |
| 353 GDataCacheMetadata::CacheMap cache_map; | |
| 354 { | |
| 355 DriveCacheEntry cache_entry; | |
| 356 cache_entry.set_md5("<md5>"); | |
| 357 cache_entry.set_is_present(true); | |
| 358 InsertIntoMap(&cache_map, "<resource_id_1>", cache_entry); | |
| 359 } | |
| 360 { | |
| 361 DriveCacheEntry cache_entry; | |
| 362 cache_entry.set_md5("<md5>"); | |
| 363 cache_entry.set_is_present(true); | |
| 364 cache_entry.set_is_persistent(true); | |
| 365 InsertIntoMap(&cache_map, "<resource_id_2>", cache_entry); | |
| 366 } | |
| 367 { | |
| 368 DriveCacheEntry cache_entry; | |
| 369 cache_entry.set_md5("<md5>"); | |
| 370 cache_entry.set_is_present(true); | |
| 371 cache_entry.set_is_persistent(true); | |
| 372 InsertIntoMap(&cache_map, "<resource_id_3>", cache_entry); | |
| 373 } | |
| 374 { | |
| 375 DriveCacheEntry cache_entry; | |
| 376 cache_entry.set_md5("<md5>"); | |
| 377 cache_entry.set_is_present(true); | |
| 378 InsertIntoMap(&cache_map, "<resource_id_4>", cache_entry); | |
| 379 } | |
| 380 | |
| 381 AddAllMapEntries(cache_map); | |
| 382 metadata_->RemoveTemporaryFiles(); | |
| 383 // resource 1 and 4 should be gone, as these are temporary. | |
| 384 DriveCacheEntry cache_entry; | |
| 385 EXPECT_FALSE(metadata_->GetCacheEntry("<resource_id_1>", "", &cache_entry)); | |
| 386 EXPECT_TRUE(metadata_->GetCacheEntry("<resource_id_2>", "", &cache_entry)); | |
| 387 EXPECT_TRUE(metadata_->GetCacheEntry("<resource_id_3>", "", &cache_entry)); | |
| 388 EXPECT_FALSE(metadata_->GetCacheEntry("<resource_id_4>", "", &cache_entry)); | |
| 389 } | |
| 390 | |
| 391 } // namespace gdata | |
| OLD | NEW |