cloud_external_data_manager_base_unittest.cc revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
1// Copyright 2013 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/policy/cloud_external_data_manager_base.h" 6 7#include <map> 8#include <string> 9 10#include "base/bind.h" 11#include "base/bind_helpers.h" 12#include "base/files/scoped_temp_dir.h" 13#include "base/message_loop/message_loop.h" 14#include "base/message_loop/message_loop_proxy.h" 15#include "base/run_loop.h" 16#include "base/sha1.h" 17#include "base/stl_util.h" 18#include "base/strings/string_number_conversions.h" 19#include "base/test/test_simple_task_runner.h" 20#include "base/values.h" 21#include "chrome/browser/chromeos/policy/cloud_external_data_store.h" 22#include "chrome/browser/policy/cloud/mock_cloud_policy_store.h" 23#include "chrome/browser/policy/cloud/resource_cache.h" 24#include "chrome/browser/policy/external_data_fetcher.h" 25#include "chrome/browser/policy/policy_map.h" 26#include "chrome/browser/policy/policy_types.h" 27#include "net/url_request/test_url_fetcher_factory.h" 28#include "net/url_request/url_fetcher.h" 29#include "net/url_request/url_fetcher_delegate.h" 30#include "net/url_request/url_request_test_util.h" 31#include "policy/policy_constants.h" 32#include "testing/gtest/include/gtest/gtest.h" 33#include "url/gurl.h" 34 35namespace policy { 36 37namespace { 38 39// A string policy. 40const char kStringPolicy[] = "StringPolicy"; 41// A policy that may reference up to 10 bytes of external data. 42const char k10BytePolicy[] = "10BytePolicy"; 43// A policy that may reference up to 20 bytes of external data. 44const char k20BytePolicy[] = "20BytePolicy"; 45// A nonexistent policy. 46const char kUnknownPolicy[] = "UnknownPolicy"; 47 48const char k10BytePolicyURL[] = "http://localhost/10_bytes"; 49const char k20BytePolicyURL[] = "http://localhost/20_bytes"; 50 51const char k10ByteData[] = "10 bytes.."; 52const char k20ByteData[] = "20 bytes............"; 53 54const PolicyDefinitionList::Entry kPolicyDefinitionListEntries[] = { 55 { kStringPolicy, base::Value::TYPE_STRING, false, 1, 0 }, 56 { k10BytePolicy, base::Value::TYPE_DICTIONARY, false, 2, 10 }, 57 { k20BytePolicy, base::Value::TYPE_DICTIONARY, false, 3, 20 }, 58}; 59 60const PolicyDefinitionList kPolicyDefinitionList = { 61 kPolicyDefinitionListEntries, 62 kPolicyDefinitionListEntries + arraysize(kPolicyDefinitionListEntries), 63}; 64 65const char kCacheKey[] = "data"; 66 67// A variant of net::FakeURLFetcherFactory that makes it an error to request a 68// fetcher for an unknown URL. 69class FakeURLFetcherFactory : public net::FakeURLFetcherFactory { 70 public: 71 FakeURLFetcherFactory(); 72 virtual ~FakeURLFetcherFactory(); 73 74 // net::FakeURLFetcherFactory: 75 virtual net::URLFetcher* CreateURLFetcher( 76 int id, 77 const GURL& url, 78 net::URLFetcher::RequestType request_type, 79 net::URLFetcherDelegate* delegate) OVERRIDE; 80 81 private: 82 DISALLOW_COPY_AND_ASSIGN(FakeURLFetcherFactory); 83}; 84 85FakeURLFetcherFactory::FakeURLFetcherFactory() 86 : net::FakeURLFetcherFactory(NULL) { 87} 88 89FakeURLFetcherFactory::~FakeURLFetcherFactory() { 90} 91 92net::URLFetcher* FakeURLFetcherFactory::CreateURLFetcher( 93 int id, 94 const GURL& url, 95 net::URLFetcher::RequestType request_type, 96 net::URLFetcherDelegate* delegate) { 97 net::URLFetcher* fetcher = net::FakeURLFetcherFactory::CreateURLFetcher( 98 id, url, request_type, delegate); 99 EXPECT_TRUE(fetcher); 100 return fetcher; 101} 102 103} // namespace 104 105class CloudExternalDataManagerBaseTest : public testing::Test { 106 protected: 107 CloudExternalDataManagerBaseTest(); 108 109 virtual void SetUp() OVERRIDE; 110 virtual void TearDown() OVERRIDE; 111 112 void SetUpExternalDataManager(); 113 114 scoped_ptr<base::DictionaryValue> ConstructMetadata(const std::string& url, 115 const std::string& hash); 116 void SetExternalDataReference(const std::string& policy, 117 scoped_ptr<base::DictionaryValue> metadata); 118 119 ExternalDataFetcher::FetchCallback ConstructFetchCallback(int id); 120 void ResetCallbackData(); 121 122 void OnFetchDone(int id, scoped_ptr<std::string> data); 123 124 void FetchAll(); 125 126 void SetFakeResponse(const std::string& url, 127 const std::string& repsonse_data, 128 bool success); 129 130 base::MessageLoop message_loop_; 131 base::ScopedTempDir temp_dir_; 132 scoped_ptr<ResourceCache> resource_cache_; 133 MockCloudPolicyStore cloud_policy_store_; 134 scoped_refptr<net::TestURLRequestContextGetter> request_content_getter_; 135 FakeURLFetcherFactory fetcher_factory_; 136 137 scoped_ptr<CloudExternalDataManagerBase> external_data_manager_; 138 139 std::map<int, std::string*> callback_data_; 140 141 DISALLOW_COPY_AND_ASSIGN(CloudExternalDataManagerBaseTest); 142}; 143 144CloudExternalDataManagerBaseTest::CloudExternalDataManagerBaseTest() { 145} 146 147void CloudExternalDataManagerBaseTest::SetUp() { 148 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 149 resource_cache_.reset(new ResourceCache(temp_dir_.path(), 150 message_loop_.message_loop_proxy())); 151 SetUpExternalDataManager(); 152 153 // Set |kStringPolicy| to a string value. 154 cloud_policy_store_.policy_map_.Set(kStringPolicy, 155 POLICY_LEVEL_MANDATORY, 156 POLICY_SCOPE_USER, 157 new base::StringValue(std::string()), 158 NULL); 159 // Make |k10BytePolicy| reference 10 bytes of external data. 160 SetExternalDataReference( 161 k10BytePolicy, 162 ConstructMetadata(k10BytePolicyURL, base::SHA1HashString(k10ByteData))); 163 // Make |k20BytePolicy| reference 20 bytes of external data. 164 SetExternalDataReference( 165 k20BytePolicy, 166 ConstructMetadata(k20BytePolicyURL, base::SHA1HashString(k20ByteData))); 167 cloud_policy_store_.NotifyStoreLoaded(); 168 169 request_content_getter_ = new net::TestURLRequestContextGetter( 170 base::MessageLoopProxy::current()); 171} 172 173void CloudExternalDataManagerBaseTest::TearDown() { 174 external_data_manager_.reset(); 175 base::RunLoop().RunUntilIdle(); 176 ResetCallbackData(); 177} 178 179void CloudExternalDataManagerBaseTest::SetUpExternalDataManager() { 180 external_data_manager_.reset(new CloudExternalDataManagerBase( 181 &kPolicyDefinitionList, 182 message_loop_.message_loop_proxy(), 183 message_loop_.message_loop_proxy())); 184 external_data_manager_->SetExternalDataStore(make_scoped_ptr( 185 new CloudExternalDataStore(kCacheKey, 186 message_loop_.message_loop_proxy(), 187 resource_cache_.get()))); 188 external_data_manager_->SetPolicyStore(&cloud_policy_store_); 189} 190 191scoped_ptr<base::DictionaryValue> 192 CloudExternalDataManagerBaseTest::ConstructMetadata( 193 const std::string& url, 194 const std::string& hash) { 195 scoped_ptr<base::DictionaryValue> metadata(new base::DictionaryValue); 196 metadata->SetStringWithoutPathExpansion("url", url); 197 metadata->SetStringWithoutPathExpansion("hash", base::HexEncode(hash.c_str(), 198 hash.size())); 199 return metadata.Pass(); 200} 201 202void CloudExternalDataManagerBaseTest::SetExternalDataReference( 203 const std::string& policy, 204 scoped_ptr<base::DictionaryValue> metadata) { 205 cloud_policy_store_.policy_map_.Set( 206 policy, 207 POLICY_LEVEL_MANDATORY, 208 POLICY_SCOPE_USER, 209 metadata.release(), 210 new ExternalDataFetcher( 211 external_data_manager_->weak_factory_.GetWeakPtr(), policy)); 212} 213 214ExternalDataFetcher::FetchCallback 215CloudExternalDataManagerBaseTest::ConstructFetchCallback(int id) { 216 return base::Bind(&CloudExternalDataManagerBaseTest::OnFetchDone, 217 base::Unretained(this), 218 id); 219} 220 221void CloudExternalDataManagerBaseTest::ResetCallbackData() { 222 STLDeleteValues(&callback_data_); 223} 224 225void CloudExternalDataManagerBaseTest::OnFetchDone( 226 int id, 227 scoped_ptr<std::string> data) { 228 delete callback_data_[id]; 229 callback_data_[id] = data.release(); 230} 231 232void CloudExternalDataManagerBaseTest::FetchAll() { 233 external_data_manager_->FetchAll(); 234} 235 236void CloudExternalDataManagerBaseTest::SetFakeResponse( 237 const std::string& url, 238 const std::string& response_data, 239 bool success) { 240 fetcher_factory_.SetFakeResponse(GURL(url), response_data, success); 241} 242 243// Verifies that when no valid external data reference has been set for a 244// policy, the attempt to retrieve the external data fails immediately. 245TEST_F(CloudExternalDataManagerBaseTest, FailToFetchInvalid) { 246 external_data_manager_->Connect(request_content_getter_); 247 248 // Attempt to retrieve external data for |kStringPolicy|, which is a string 249 // policy that does not reference any external data. 250 external_data_manager_->Fetch(kStringPolicy, ConstructFetchCallback(0)); 251 base::RunLoop().RunUntilIdle(); 252 EXPECT_EQ(1u, callback_data_.size()); 253 EXPECT_TRUE(callback_data_.find(0) != callback_data_.end()); 254 EXPECT_FALSE(callback_data_[0]); 255 ResetCallbackData(); 256 257 // Attempt to retrieve external data for |kUnknownPolicy|, which is not a 258 // known policy. 259 external_data_manager_->Fetch(kUnknownPolicy, ConstructFetchCallback(1)); 260 base::RunLoop().RunUntilIdle(); 261 EXPECT_EQ(1u, callback_data_.size()); 262 EXPECT_TRUE(callback_data_.find(1) != callback_data_.end()); 263 EXPECT_FALSE(callback_data_[1]); 264 ResetCallbackData(); 265 266 // Set an invalid external data reference for |k10BytePolicy|. 267 SetExternalDataReference(k10BytePolicy, 268 ConstructMetadata(std::string(), std::string())); 269 cloud_policy_store_.NotifyStoreLoaded(); 270 271 // Attempt to retrieve external data for |k10BytePolicy|, which now has an 272 // invalid reference. 273 external_data_manager_->Fetch(k10BytePolicy, ConstructFetchCallback(2)); 274 base::RunLoop().RunUntilIdle(); 275 EXPECT_EQ(1u, callback_data_.size()); 276 EXPECT_TRUE(callback_data_.find(2) != callback_data_.end()); 277 EXPECT_FALSE(callback_data_[2]); 278 ResetCallbackData(); 279} 280 281// Verifies that external data referenced by a policy is downloaded and cached 282// when first requested. Subsequent requests are served from the cache without 283// further download attempts. 284TEST_F(CloudExternalDataManagerBaseTest, DownloadAndCache) { 285 // Serve valid external data for |k10BytePolicy|. 286 SetFakeResponse(k10BytePolicyURL, k10ByteData, true); 287 external_data_manager_->Connect(request_content_getter_); 288 289 // Retrieve external data for |k10BytePolicy|. Verify that a download happens 290 // and the callback is invoked with the downloaded data. 291 external_data_manager_->Fetch(k10BytePolicy, ConstructFetchCallback(0)); 292 base::RunLoop().RunUntilIdle(); 293 EXPECT_EQ(1u, callback_data_.size()); 294 ASSERT_TRUE(callback_data_[0]); 295 EXPECT_EQ(k10ByteData, *callback_data_[0]); 296 ResetCallbackData(); 297 298 // Stop serving external data for |k10BytePolicy|. 299 fetcher_factory_.ClearFakeResponses(); 300 301 // Retrieve external data for |k10BytePolicy| again. Verify that no download 302 // is attempted but the callback is still invoked with the expected data, 303 // served from the cache. 304 external_data_manager_->Fetch(k10BytePolicy, ConstructFetchCallback(1)); 305 base::RunLoop().RunUntilIdle(); 306 EXPECT_EQ(1u, callback_data_.size()); 307 ASSERT_TRUE(callback_data_[1]); 308 EXPECT_EQ(k10ByteData, *callback_data_[1]); 309 ResetCallbackData(); 310 311 // Explicitly tell the external_data_manager_ to not make any download 312 // attempts. 313 external_data_manager_->Disconnect(); 314 315 // Retrieve external data for |k10BytePolicy| again. Verify that even though 316 // downloads are not allowed, the callback is still invoked with the expected 317 // data, served from the cache. 318 external_data_manager_->Fetch(k10BytePolicy, ConstructFetchCallback(2)); 319 base::RunLoop().RunUntilIdle(); 320 EXPECT_EQ(1u, callback_data_.size()); 321 ASSERT_TRUE(callback_data_[2]); 322 EXPECT_EQ(k10ByteData, *callback_data_[2]); 323 ResetCallbackData(); 324 325 // Verify that the downloaded data is present in the cache. 326 external_data_manager_.reset(); 327 base::RunLoop().RunUntilIdle(); 328 std::string data; 329 EXPECT_TRUE(CloudExternalDataStore(kCacheKey, 330 message_loop_.message_loop_proxy(), 331 resource_cache_.get()).Load( 332 k10BytePolicy, base::SHA1HashString(k10ByteData), 10, &data)); 333 EXPECT_EQ(k10ByteData, data); 334} 335 336// Verifies that a request to download and cache all external data referenced by 337// policies is carried out correctly. Subsequent requests for the data are 338// served from the cache without further download attempts. 339TEST_F(CloudExternalDataManagerBaseTest, DownloadAndCacheAll) { 340 // Serve valid external data for |k10BytePolicy| and |k20BytePolicy|. 341 SetFakeResponse(k10BytePolicyURL, k10ByteData, true); 342 SetFakeResponse(k20BytePolicyURL, k20ByteData, true); 343 external_data_manager_->Connect(request_content_getter_); 344 345 // Request that external data referenced by all policies be downloaded. 346 FetchAll(); 347 base::RunLoop().RunUntilIdle(); 348 349 // Stop serving external data for |k10BytePolicy| and |k20BytePolicy|. 350 fetcher_factory_.ClearFakeResponses(); 351 352 // Retrieve external data for |k10BytePolicy| and |k20BytePolicy|. Verify that 353 // no downloads are attempted but the callbacks are still invoked with the 354 // expected data, served from the cache. 355 external_data_manager_->Fetch(k10BytePolicy, ConstructFetchCallback(0)); 356 external_data_manager_->Fetch(k20BytePolicy, ConstructFetchCallback(1)); 357 base::RunLoop().RunUntilIdle(); 358 EXPECT_EQ(2u, callback_data_.size()); 359 ASSERT_TRUE(callback_data_[0]); 360 EXPECT_EQ(k10ByteData, *callback_data_[0]); 361 ASSERT_TRUE(callback_data_[1]); 362 EXPECT_EQ(k20ByteData, *callback_data_[1]); 363 ResetCallbackData(); 364 365 // Explicitly tell the external_data_manager_ to not make any download 366 // attempts. 367 external_data_manager_->Disconnect(); 368 369 // Retrieve external data for |k10BytePolicy| and |k20BytePolicy|. Verify that 370 // even though downloads are not allowed, the callbacks are still invoked with 371 // the expected data, served from the cache. 372 external_data_manager_->Fetch(k10BytePolicy, ConstructFetchCallback(2)); 373 external_data_manager_->Fetch(k20BytePolicy, ConstructFetchCallback(3)); 374 base::RunLoop().RunUntilIdle(); 375 EXPECT_EQ(2u, callback_data_.size()); 376 ASSERT_TRUE(callback_data_[2]); 377 EXPECT_EQ(k10ByteData, *callback_data_[2]); 378 ASSERT_TRUE(callback_data_[3]); 379 EXPECT_EQ(k20ByteData, *callback_data_[3]); 380 ResetCallbackData(); 381 382 // Verify that the downloaded data is present in the cache. 383 external_data_manager_.reset(); 384 base::RunLoop().RunUntilIdle(); 385 CloudExternalDataStore cache(kCacheKey, 386 message_loop_.message_loop_proxy(), 387 resource_cache_.get()); 388 std::string data; 389 EXPECT_TRUE(cache.Load(k10BytePolicy, base::SHA1HashString(k10ByteData), 10, 390 &data)); 391 EXPECT_EQ(k10ByteData, data); 392 EXPECT_TRUE(cache.Load(k20BytePolicy, base::SHA1HashString(k20ByteData), 20, 393 &data)); 394 EXPECT_EQ(k20ByteData, data); 395} 396 397// Verifies that when the external data referenced by a policy is not present in 398// the cache and downloads are not allowed, a request to retrieve the data is 399// enqueued and carried out when downloads become possible. 400TEST_F(CloudExternalDataManagerBaseTest, DownloadAfterConnect) { 401 // Attempt to retrieve external data for |k10BytePolicy|. Verify that the 402 // callback is not invoked as the request remains pending. 403 external_data_manager_->Fetch(k10BytePolicy, ConstructFetchCallback(0)); 404 base::RunLoop().RunUntilIdle(); 405 EXPECT_TRUE(callback_data_.empty()); 406 ResetCallbackData(); 407 408 // Serve valid external data for |k10BytePolicy| and allow the 409 // external_data_manager_ to perform downloads. 410 SetFakeResponse(k10BytePolicyURL, k10ByteData, true); 411 external_data_manager_->Connect(request_content_getter_); 412 413 // Verify that a download happens and the callback is invoked with the 414 // downloaded data. 415 base::RunLoop().RunUntilIdle(); 416 EXPECT_EQ(1u, callback_data_.size()); 417 ASSERT_TRUE(callback_data_[0]); 418 EXPECT_EQ(k10ByteData, *callback_data_[0]); 419 ResetCallbackData(); 420} 421 422// Verifies that when the external data referenced by a policy is not present in 423// the cache and cannot be downloaded at this time, a request to retrieve the 424// data is enqueued to be retried later. 425TEST_F(CloudExternalDataManagerBaseTest, DownloadError) { 426 // Make attempts to download the external data for |k20BytePolicy| fail with 427 // an error. 428 SetFakeResponse(k20BytePolicyURL, std::string(), false); 429 external_data_manager_->Connect(request_content_getter_); 430 431 // Attempt to retrieve external data for |k20BytePolicy|. Verify that the 432 // callback is not invoked as the download attempt fails and the request 433 // remains pending. 434 external_data_manager_->Fetch(k20BytePolicy, ConstructFetchCallback(0)); 435 base::RunLoop().RunUntilIdle(); 436 EXPECT_TRUE(callback_data_.empty()); 437 ResetCallbackData(); 438 439 // Modify the external data reference for |k20BytePolicy|, allowing the 440 // download to be retried immediately. 441 SetExternalDataReference( 442 k20BytePolicy, 443 ConstructMetadata(k20BytePolicyURL, base::SHA1HashString(k10ByteData))); 444 cloud_policy_store_.NotifyStoreLoaded(); 445 446 // Attempt to retrieve external data for |k20BytePolicy| again. Verify that 447 // no callback is invoked still as the download attempt fails again and the 448 // request remains pending. 449 external_data_manager_->Fetch(k20BytePolicy, ConstructFetchCallback(1)); 450 base::RunLoop().RunUntilIdle(); 451 EXPECT_TRUE(callback_data_.empty()); 452 ResetCallbackData(); 453 454 // Modify the external data reference for |k20BytePolicy|, allowing the 455 // download to be retried immediately. 456 SetExternalDataReference( 457 k20BytePolicy, 458 ConstructMetadata(k20BytePolicyURL, base::SHA1HashString(k20ByteData))); 459 cloud_policy_store_.NotifyStoreLoaded(); 460 461 // Serve external data for |k20BytePolicy| that does not match the hash 462 // specified in its current external data reference. 463 SetFakeResponse(k20BytePolicyURL, k10ByteData, true); 464 465 // Attempt to retrieve external data for |k20BytePolicy| again. Verify that 466 // no callback is invoked still as the downloaded succeeds but returns data 467 // that does not match the external data reference. 468 external_data_manager_->Fetch(k20BytePolicy, ConstructFetchCallback(2)); 469 base::RunLoop().RunUntilIdle(); 470 EXPECT_TRUE(callback_data_.empty()); 471 ResetCallbackData(); 472 473 // Modify the external data reference for |k20BytePolicy|, allowing the 474 // download to be retried immediately. The external data reference now matches 475 // the data being served. 476 SetExternalDataReference( 477 k20BytePolicy, 478 ConstructMetadata(k20BytePolicyURL, base::SHA1HashString(k10ByteData))); 479 cloud_policy_store_.NotifyStoreLoaded(); 480 481 // Attempt to retrieve external data for |k20BytePolicy| again. Verify that 482 // the current callback and the three previously enqueued callbacks are 483 // invoked with the downloaded data now. 484 external_data_manager_->Fetch(k20BytePolicy, ConstructFetchCallback(3)); 485 base::RunLoop().RunUntilIdle(); 486 EXPECT_EQ(4u, callback_data_.size()); 487 ASSERT_TRUE(callback_data_[0]); 488 EXPECT_EQ(k10ByteData, *callback_data_[0]); 489 ASSERT_TRUE(callback_data_[1]); 490 EXPECT_EQ(k10ByteData, *callback_data_[1]); 491 ASSERT_TRUE(callback_data_[2]); 492 EXPECT_EQ(k10ByteData, *callback_data_[2]); 493 ASSERT_TRUE(callback_data_[3]); 494 EXPECT_EQ(k10ByteData, *callback_data_[3]); 495 ResetCallbackData(); 496} 497 498// Verifies that when the external data referenced by a policy is present in the 499// cache, a request to retrieve it is served from the cache without any download 500// attempts. 501TEST_F(CloudExternalDataManagerBaseTest, LoadFromCache) { 502 // Store valid external data for |k10BytePolicy| in the cache. 503 external_data_manager_.reset(); 504 base::RunLoop().RunUntilIdle(); 505 EXPECT_TRUE(CloudExternalDataStore(kCacheKey, 506 message_loop_.message_loop_proxy(), 507 resource_cache_.get()).Store( 508 k10BytePolicy, base::SHA1HashString(k10ByteData), k10ByteData)); 509 510 // Instantiate an external_data_manager_ that uses the primed cache. 511 SetUpExternalDataManager(); 512 external_data_manager_->Connect(request_content_getter_); 513 514 // Retrieve external data for |k10BytePolicy|. Verify that no download is 515 // attempted but the callback is still invoked with the expected data, served 516 // from the cache. 517 external_data_manager_->Fetch(k10BytePolicy, ConstructFetchCallback(0)); 518 base::RunLoop().RunUntilIdle(); 519 EXPECT_EQ(1u, callback_data_.size()); 520 ASSERT_TRUE(callback_data_[0]); 521 EXPECT_EQ(k10ByteData, *callback_data_[0]); 522 ResetCallbackData(); 523} 524 525// Verifies that cache entries which do not correspond to the external data 526// referenced by any policy are pruned on startup. 527TEST_F(CloudExternalDataManagerBaseTest, PruneCacheOnStartup) { 528 external_data_manager_.reset(); 529 base::RunLoop().RunUntilIdle(); 530 scoped_ptr<CloudExternalDataStore> 531 cache(new CloudExternalDataStore(kCacheKey, 532 message_loop_.message_loop_proxy(), 533 resource_cache_.get())); 534 // Store valid external data for |k10BytePolicy| in the cache. 535 EXPECT_TRUE(cache->Store(k10BytePolicy, 536 base::SHA1HashString(k10ByteData), 537 k10ByteData)); 538 // Store external data for |k20BytePolicy| that does not match the hash in its 539 // external data reference. 540 EXPECT_TRUE(cache->Store(k20BytePolicy, 541 base::SHA1HashString(k10ByteData), 542 k10ByteData)); 543 // Store external data for |kUnknownPolicy|, which is not a known policy and 544 // therefore, cannot be referencing any external data. 545 EXPECT_TRUE(cache->Store(kUnknownPolicy, 546 base::SHA1HashString(k10ByteData), 547 k10ByteData)); 548 cache.reset(); 549 550 // Instantiate and destroy an ExternalDataManager that uses the primed cache. 551 SetUpExternalDataManager(); 552 external_data_manager_.reset(); 553 base::RunLoop().RunUntilIdle(); 554 555 cache.reset(new CloudExternalDataStore(kCacheKey, 556 message_loop_.message_loop_proxy(), 557 resource_cache_.get())); 558 std::string data; 559 // Verify that the valid external data for |k10BytePolicy| is still in the 560 // cache. 561 EXPECT_TRUE(cache->Load(k10BytePolicy, base::SHA1HashString(k10ByteData), 562 10, &data)); 563 EXPECT_EQ(k10ByteData, data); 564 // Verify that the external data for |k20BytePolicy| and |kUnknownPolicy| has 565 // been pruned from the cache. 566 EXPECT_FALSE(cache->Load(k20BytePolicy, base::SHA1HashString(k10ByteData), 567 20, &data)); 568 EXPECT_FALSE(cache->Load(kUnknownPolicy, base::SHA1HashString(k10ByteData), 569 20, &data)); 570} 571 572// Verifies that when the external data referenced by a policy is present in the 573// cache and the reference changes, the old data is pruned from the cache. 574TEST_F(CloudExternalDataManagerBaseTest, PruneCacheOnChange) { 575 // Store valid external data for |k20BytePolicy| in the cache. 576 external_data_manager_.reset(); 577 base::RunLoop().RunUntilIdle(); 578 scoped_ptr<CloudExternalDataStore> 579 cache(new CloudExternalDataStore(kCacheKey, 580 message_loop_.message_loop_proxy(), 581 resource_cache_.get())); 582 EXPECT_TRUE(cache->Store(k20BytePolicy, 583 base::SHA1HashString(k20ByteData), 584 k20ByteData)); 585 cache.reset(); 586 587 // Instantiate an ExternalDataManager that uses the primed cache. 588 SetUpExternalDataManager(); 589 external_data_manager_->Connect(request_content_getter_); 590 591 // Modify the external data reference for |k20BytePolicy|. 592 SetExternalDataReference( 593 k20BytePolicy, 594 ConstructMetadata(k20BytePolicyURL, base::SHA1HashString(k10ByteData))); 595 cloud_policy_store_.NotifyStoreLoaded(); 596 597 // Verify that the old external data for |k20BytePolicy| has been pruned from 598 // the cache. 599 external_data_manager_.reset(); 600 base::RunLoop().RunUntilIdle(); 601 cache.reset(new CloudExternalDataStore(kCacheKey, 602 message_loop_.message_loop_proxy(), 603 resource_cache_.get())); 604 std::string data; 605 EXPECT_FALSE(cache->Load(k20BytePolicy, base::SHA1HashString(k20ByteData), 20, 606 &data)); 607} 608 609// Verifies that corrupt cache entries are detected and deleted when accessed. 610TEST_F(CloudExternalDataManagerBaseTest, CacheCorruption) { 611 external_data_manager_.reset(); 612 base::RunLoop().RunUntilIdle(); 613 scoped_ptr<CloudExternalDataStore> 614 cache(new CloudExternalDataStore(kCacheKey, 615 message_loop_.message_loop_proxy(), 616 resource_cache_.get())); 617 // Store external data for |k10BytePolicy| that exceeds the maximal external 618 // data size allowed for that policy. 619 EXPECT_TRUE(cache->Store(k10BytePolicy, 620 base::SHA1HashString(k20ByteData), 621 k20ByteData)); 622 // Store external data for |k20BytePolicy| that is corrupted and does not 623 // match the expected hash. 624 EXPECT_TRUE(cache->Store(k20BytePolicy, 625 base::SHA1HashString(k20ByteData), 626 k10ByteData)); 627 cache.reset(); 628 629 SetUpExternalDataManager(); 630 // Serve external data for |k10BytePolicy| that exceeds the maximal external 631 // data size allowed for that policy. 632 SetFakeResponse(k10BytePolicyURL, k20ByteData, true); 633 external_data_manager_->Connect(request_content_getter_); 634 635 // Modify the external data reference for |k10BytePolicy| to match the 636 // external data being served. 637 SetExternalDataReference( 638 k10BytePolicy, 639 ConstructMetadata(k10BytePolicyURL, base::SHA1HashString(k20ByteData))); 640 cloud_policy_store_.NotifyStoreLoaded(); 641 642 // Retrieve external data for |k10BytePolicy|. Verify that the callback is 643 // not invoked as the cached and downloaded external data exceed the maximal 644 // size allowed for this policy and the request remains pending. 645 external_data_manager_->Fetch(k10BytePolicy, ConstructFetchCallback(0)); 646 base::RunLoop().RunUntilIdle(); 647 EXPECT_TRUE(callback_data_.empty()); 648 ResetCallbackData(); 649 650 // Serve valid external data for |k20BytePolicy|. 651 SetFakeResponse(k20BytePolicyURL, k20ByteData, true); 652 653 // Retrieve external data for |k20BytePolicy|. Verify that the callback is 654 // invoked with the valid downloaded data, not the invalid data in the cache. 655 external_data_manager_->Fetch(k20BytePolicy, ConstructFetchCallback(1)); 656 base::RunLoop().RunUntilIdle(); 657 EXPECT_EQ(1u, callback_data_.size()); 658 ASSERT_TRUE(callback_data_[1]); 659 EXPECT_EQ(k20ByteData, *callback_data_[1]); 660 ResetCallbackData(); 661 662 external_data_manager_.reset(); 663 base::RunLoop().RunUntilIdle(); 664 cache.reset(new CloudExternalDataStore(kCacheKey, 665 message_loop_.message_loop_proxy(), 666 resource_cache_.get())); 667 std::string data; 668 // Verify that the invalid external data for |k10BytePolicy| has been pruned 669 // from the cache. Load() will return |false| in two cases: 670 // 1) The cache entry for |k10BytePolicy| has been pruned. 671 // 2) The cache entry for |k10BytePolicy| still exists but the cached data 672 // does not match the expected hash or exceeds the maximum size allowed. 673 // To test for the former, Load() is called with a maximum data size and hash 674 // that would allow the data originally written to the cache to be loaded. 675 // When this fails, it is certain that the original data is no longer present 676 // in the cache. 677 EXPECT_FALSE(cache->Load(k10BytePolicy, base::SHA1HashString(k20ByteData), 20, 678 &data)); 679 // Verify that the invalid external data for |k20BytePolicy| has been replaced 680 // with the downloaded valid data in the cache. 681 EXPECT_TRUE(cache->Load(k20BytePolicy, base::SHA1HashString(k20ByteData), 20, 682 &data)); 683 EXPECT_EQ(k20ByteData, data); 684} 685 686// Verifies that when the external data reference for a policy changes while a 687// download of the external data for that policy is pending, the download is 688// immediately retried using the new reference. 689TEST_F(CloudExternalDataManagerBaseTest, PolicyChangeWhileDownloadPending) { 690 // Make attempts to download the external data for |k10BytePolicy| and 691 // |k20BytePolicy| fail with an error. 692 SetFakeResponse(k10BytePolicyURL, std::string(), false); 693 SetFakeResponse(k20BytePolicyURL, std::string(), false); 694 external_data_manager_->Connect(request_content_getter_); 695 696 // Attempt to retrieve external data for |k10BytePolicy| and |k20BytePolicy|. 697 // Verify that no callbacks are invoked as the download attempts fail and the 698 // requests remain pending. 699 external_data_manager_->Fetch(k10BytePolicy, ConstructFetchCallback(0)); 700 external_data_manager_->Fetch(k20BytePolicy, ConstructFetchCallback(1)); 701 base::RunLoop().RunUntilIdle(); 702 EXPECT_TRUE(callback_data_.empty()); 703 ResetCallbackData(); 704 705 // Modify the external data reference for |k10BytePolicy| to be invalid. 706 // Verify that the callback is invoked as the policy no longer has a valid 707 // external data reference. 708 cloud_policy_store_.policy_map_.Erase(k10BytePolicy); 709 cloud_policy_store_.NotifyStoreLoaded(); 710 base::RunLoop().RunUntilIdle(); 711 EXPECT_EQ(1u, callback_data_.size()); 712 EXPECT_TRUE(callback_data_.find(0) != callback_data_.end()); 713 EXPECT_FALSE(callback_data_[0]); 714 ResetCallbackData(); 715 716 // Serve valid external data for |k20BytePolicy|. 717 fetcher_factory_.ClearFakeResponses(); 718 SetFakeResponse(k20BytePolicyURL, k10ByteData, true); 719 720 // Modify the external data reference for |k20BytePolicy| to match the 721 // external data now being served. Verify that the callback is invoked with 722 // the downloaded data. 723 SetExternalDataReference( 724 k20BytePolicy, 725 ConstructMetadata(k20BytePolicyURL, base::SHA1HashString(k10ByteData))); 726 cloud_policy_store_.NotifyStoreLoaded(); 727 base::RunLoop().RunUntilIdle(); 728 EXPECT_EQ(1u, callback_data_.size()); 729 ASSERT_TRUE(callback_data_[1]); 730 EXPECT_EQ(k10ByteData, *callback_data_[1]); 731 ResetCallbackData(); 732} 733 734} // namespace policy 735