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.
5 #include "chrome/browser/chromeos/policy/cloud_external_data_manager_base.h"
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/run_loop.h"
15 #include "base/stl_util.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/test/test_simple_task_runner.h"
18 #include "base/thread_task_runner_handle.h"
19 #include "base/values.h"
20 #include "chrome/browser/chromeos/policy/cloud_external_data_store.h"
21 #include "components/policy/core/common/cloud/mock_cloud_policy_store.h"
22 #include "components/policy/core/common/cloud/resource_cache.h"
23 #include "components/policy/core/common/external_data_fetcher.h"
24 #include "components/policy/core/common/policy_map.h"
25 #include "components/policy/core/common/policy_test_utils.h"
26 #include "components/policy/core/common/policy_types.h"
27 #include "crypto/sha2.h"
28 #include "net/http/http_status_code.h"
29 #include "net/url_request/test_url_fetcher_factory.h"
30 #include "net/url_request/url_fetcher.h"
31 #include "net/url_request/url_fetcher_delegate.h"
32 #include "net/url_request/url_request_status.h"
33 #include "net/url_request/url_request_test_util.h"
34 #include "testing/gtest/include/gtest/gtest.h"
42 const char kStringPolicy
[] = "StringPolicy";
43 // A policy that may reference up to 10 bytes of external data.
44 const char k10BytePolicy
[] = "10BytePolicy";
45 // A policy that may reference up to 20 bytes of external data.
46 const char k20BytePolicy
[] = "20BytePolicy";
47 // A nonexistent policy.
48 const char kUnknownPolicy
[] = "UnknownPolicy";
50 const char k10BytePolicyURL
[] = "http://localhost/10_bytes";
51 const char k20BytePolicyURL
[] = "http://localhost/20_bytes";
53 const char k10ByteData
[] = "10 bytes..";
54 const char k20ByteData
[] = "20 bytes............";
56 const PolicyDetails kPolicyDetails
[] = {
57 // is_deprecated is_device_policy id max_external_data_size
58 { false, false, 1, 0 },
59 { false, false, 2, 10 },
60 { false, false, 3, 20 },
63 const char kCacheKey
[] = "data";
65 // A variant of net::FakeURLFetcherFactory that makes it an error to request a
66 // fetcher for an unknown URL.
67 class FakeURLFetcherFactory
: public net::FakeURLFetcherFactory
{
69 FakeURLFetcherFactory();
70 ~FakeURLFetcherFactory() override
;
72 // net::FakeURLFetcherFactory:
73 scoped_ptr
<net::URLFetcher
> CreateURLFetcher(
76 net::URLFetcher::RequestType request_type
,
77 net::URLFetcherDelegate
* delegate
) override
;
80 DISALLOW_COPY_AND_ASSIGN(FakeURLFetcherFactory
);
83 FakeURLFetcherFactory::FakeURLFetcherFactory()
84 : net::FakeURLFetcherFactory(NULL
) {
87 FakeURLFetcherFactory::~FakeURLFetcherFactory() {
90 scoped_ptr
<net::URLFetcher
> FakeURLFetcherFactory::CreateURLFetcher(
93 net::URLFetcher::RequestType request_type
,
94 net::URLFetcherDelegate
* delegate
) {
95 scoped_ptr
<net::URLFetcher
> fetcher
=
96 net::FakeURLFetcherFactory::CreateURLFetcher(id
, url
, request_type
,
99 return fetcher
.Pass();
104 class CloudExternalDataManagerBaseTest
: public testing::Test
{
106 CloudExternalDataManagerBaseTest();
108 void SetUp() override
;
109 void TearDown() override
;
111 void SetUpExternalDataManager();
113 scoped_ptr
<base::DictionaryValue
> ConstructMetadata(const std::string
& url
,
114 const std::string
& hash
);
115 void SetExternalDataReference(const std::string
& policy
,
116 scoped_ptr
<base::DictionaryValue
> metadata
);
118 ExternalDataFetcher::FetchCallback
ConstructFetchCallback(int id
);
119 void ResetCallbackData();
121 void OnFetchDone(int id
, scoped_ptr
<std::string
> data
);
125 void SetFakeResponse(const std::string
& url
,
126 const std::string
& repsonse_data
,
127 net::HttpStatusCode response_code
,
128 net::URLRequestStatus::Status status
);
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_
;
137 scoped_ptr
<CloudExternalDataManagerBase
> external_data_manager_
;
139 std::map
<int, std::string
*> callback_data_
;
140 PolicyDetailsMap policy_details_
;
143 DISALLOW_COPY_AND_ASSIGN(CloudExternalDataManagerBaseTest
);
146 CloudExternalDataManagerBaseTest::CloudExternalDataManagerBaseTest() {
149 void CloudExternalDataManagerBaseTest::SetUp() {
150 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
151 resource_cache_
.reset(
152 new ResourceCache(temp_dir_
.path(), message_loop_
.task_runner()));
153 SetUpExternalDataManager();
155 // Set |kStringPolicy| to a string value.
156 cloud_policy_store_
.policy_map_
.Set(kStringPolicy
,
157 POLICY_LEVEL_MANDATORY
,
159 new base::StringValue(std::string()),
161 // Make |k10BytePolicy| reference 10 bytes of external data.
162 SetExternalDataReference(
164 ConstructMetadata(k10BytePolicyURL
,
165 crypto::SHA256HashString(k10ByteData
)));
166 // Make |k20BytePolicy| reference 20 bytes of external data.
167 SetExternalDataReference(
169 ConstructMetadata(k20BytePolicyURL
,
170 crypto::SHA256HashString(k20ByteData
)));
171 cloud_policy_store_
.NotifyStoreLoaded();
173 request_content_getter_
=
174 new net::TestURLRequestContextGetter(base::ThreadTaskRunnerHandle::Get());
176 policy_details_
.SetDetails(kStringPolicy
, &kPolicyDetails
[0]);
177 policy_details_
.SetDetails(k10BytePolicy
, &kPolicyDetails
[1]);
178 policy_details_
.SetDetails(k20BytePolicy
, &kPolicyDetails
[2]);
181 void CloudExternalDataManagerBaseTest::TearDown() {
182 external_data_manager_
.reset();
183 base::RunLoop().RunUntilIdle();
187 void CloudExternalDataManagerBaseTest::SetUpExternalDataManager() {
188 external_data_manager_
.reset(new CloudExternalDataManagerBase(
189 policy_details_
.GetCallback(), message_loop_
.task_runner(),
190 message_loop_
.task_runner()));
191 external_data_manager_
->SetExternalDataStore(
192 make_scoped_ptr(new CloudExternalDataStore(
193 kCacheKey
, message_loop_
.task_runner(), resource_cache_
.get())));
194 external_data_manager_
->SetPolicyStore(&cloud_policy_store_
);
197 scoped_ptr
<base::DictionaryValue
>
198 CloudExternalDataManagerBaseTest::ConstructMetadata(
199 const std::string
& url
,
200 const std::string
& hash
) {
201 scoped_ptr
<base::DictionaryValue
> metadata(new base::DictionaryValue
);
202 metadata
->SetStringWithoutPathExpansion("url", url
);
203 metadata
->SetStringWithoutPathExpansion("hash", base::HexEncode(hash
.c_str(),
205 return metadata
.Pass();
208 void CloudExternalDataManagerBaseTest::SetExternalDataReference(
209 const std::string
& policy
,
210 scoped_ptr
<base::DictionaryValue
> metadata
) {
211 cloud_policy_store_
.policy_map_
.Set(
213 POLICY_LEVEL_MANDATORY
,
216 new ExternalDataFetcher(
217 external_data_manager_
->weak_factory_
.GetWeakPtr(), policy
));
220 ExternalDataFetcher::FetchCallback
221 CloudExternalDataManagerBaseTest::ConstructFetchCallback(int id
) {
222 return base::Bind(&CloudExternalDataManagerBaseTest::OnFetchDone
,
223 base::Unretained(this),
227 void CloudExternalDataManagerBaseTest::ResetCallbackData() {
228 STLDeleteValues(&callback_data_
);
231 void CloudExternalDataManagerBaseTest::OnFetchDone(
233 scoped_ptr
<std::string
> data
) {
234 delete callback_data_
[id
];
235 callback_data_
[id
] = data
.release();
238 void CloudExternalDataManagerBaseTest::FetchAll() {
239 external_data_manager_
->FetchAll();
242 void CloudExternalDataManagerBaseTest::SetFakeResponse(
243 const std::string
& url
,
244 const std::string
& response_data
,
245 net::HttpStatusCode response_code
,
246 net::URLRequestStatus::Status status
) {
247 fetcher_factory_
.SetFakeResponse(
248 GURL(url
), response_data
, response_code
, status
);
251 // Verifies that when no valid external data reference has been set for a
252 // policy, the attempt to retrieve the external data fails immediately.
253 TEST_F(CloudExternalDataManagerBaseTest
, FailToFetchInvalid
) {
254 external_data_manager_
->Connect(request_content_getter_
);
256 // Attempt to retrieve external data for |kStringPolicy|, which is a string
257 // policy that does not reference any external data.
258 external_data_manager_
->Fetch(kStringPolicy
, ConstructFetchCallback(0));
259 base::RunLoop().RunUntilIdle();
260 EXPECT_EQ(1u, callback_data_
.size());
261 EXPECT_TRUE(callback_data_
.find(0) != callback_data_
.end());
262 EXPECT_FALSE(callback_data_
[0]);
265 // Attempt to retrieve external data for |kUnknownPolicy|, which is not a
267 external_data_manager_
->Fetch(kUnknownPolicy
, ConstructFetchCallback(1));
268 base::RunLoop().RunUntilIdle();
269 EXPECT_EQ(1u, callback_data_
.size());
270 EXPECT_TRUE(callback_data_
.find(1) != callback_data_
.end());
271 EXPECT_FALSE(callback_data_
[1]);
274 // Set an invalid external data reference for |k10BytePolicy|.
275 SetExternalDataReference(k10BytePolicy
,
276 ConstructMetadata(std::string(), std::string()));
277 cloud_policy_store_
.NotifyStoreLoaded();
279 // Attempt to retrieve external data for |k10BytePolicy|, which now has an
280 // invalid reference.
281 external_data_manager_
->Fetch(k10BytePolicy
, ConstructFetchCallback(2));
282 base::RunLoop().RunUntilIdle();
283 EXPECT_EQ(1u, callback_data_
.size());
284 EXPECT_TRUE(callback_data_
.find(2) != callback_data_
.end());
285 EXPECT_FALSE(callback_data_
[2]);
289 // Verifies that external data referenced by a policy is downloaded and cached
290 // when first requested. Subsequent requests are served from the cache without
291 // further download attempts.
292 TEST_F(CloudExternalDataManagerBaseTest
, DownloadAndCache
) {
293 // Serve valid external data for |k10BytePolicy|.
294 SetFakeResponse(k10BytePolicyURL
, k10ByteData
, net::HTTP_OK
,
295 net::URLRequestStatus::SUCCESS
);
296 external_data_manager_
->Connect(request_content_getter_
);
298 // Retrieve external data for |k10BytePolicy|. Verify that a download happens
299 // and the callback is invoked with the downloaded data.
300 external_data_manager_
->Fetch(k10BytePolicy
, ConstructFetchCallback(0));
301 base::RunLoop().RunUntilIdle();
302 EXPECT_EQ(1u, callback_data_
.size());
303 ASSERT_TRUE(callback_data_
[0]);
304 EXPECT_EQ(k10ByteData
, *callback_data_
[0]);
307 // Stop serving external data for |k10BytePolicy|.
308 fetcher_factory_
.ClearFakeResponses();
310 // Retrieve external data for |k10BytePolicy| again. Verify that no download
311 // is attempted but the callback is still invoked with the expected data,
312 // served from the cache.
313 external_data_manager_
->Fetch(k10BytePolicy
, ConstructFetchCallback(1));
314 base::RunLoop().RunUntilIdle();
315 EXPECT_EQ(1u, callback_data_
.size());
316 ASSERT_TRUE(callback_data_
[1]);
317 EXPECT_EQ(k10ByteData
, *callback_data_
[1]);
320 // Explicitly tell the external_data_manager_ to not make any download
322 external_data_manager_
->Disconnect();
324 // Retrieve external data for |k10BytePolicy| again. Verify that even though
325 // downloads are not allowed, the callback is still invoked with the expected
326 // data, served from the cache.
327 external_data_manager_
->Fetch(k10BytePolicy
, ConstructFetchCallback(2));
328 base::RunLoop().RunUntilIdle();
329 EXPECT_EQ(1u, callback_data_
.size());
330 ASSERT_TRUE(callback_data_
[2]);
331 EXPECT_EQ(k10ByteData
, *callback_data_
[2]);
334 // Verify that the downloaded data is present in the cache.
335 external_data_manager_
.reset();
336 base::RunLoop().RunUntilIdle();
338 EXPECT_TRUE(CloudExternalDataStore(kCacheKey
, message_loop_
.task_runner(),
339 resource_cache_
.get())
340 .Load(k10BytePolicy
, crypto::SHA256HashString(k10ByteData
),
342 EXPECT_EQ(k10ByteData
, data
);
345 // Verifies that a request to download and cache all external data referenced by
346 // policies is carried out correctly. Subsequent requests for the data are
347 // served from the cache without further download attempts.
348 TEST_F(CloudExternalDataManagerBaseTest
, DownloadAndCacheAll
) {
349 // Serve valid external data for |k10BytePolicy| and |k20BytePolicy|.
350 SetFakeResponse(k10BytePolicyURL
, k10ByteData
, net::HTTP_OK
,
351 net::URLRequestStatus::SUCCESS
);
352 SetFakeResponse(k20BytePolicyURL
, k20ByteData
, net::HTTP_OK
,
353 net::URLRequestStatus::SUCCESS
);
354 external_data_manager_
->Connect(request_content_getter_
);
356 // Request that external data referenced by all policies be downloaded.
358 base::RunLoop().RunUntilIdle();
360 // Stop serving external data for |k10BytePolicy| and |k20BytePolicy|.
361 fetcher_factory_
.ClearFakeResponses();
363 // Retrieve external data for |k10BytePolicy| and |k20BytePolicy|. Verify that
364 // no downloads are attempted but the callbacks are still invoked with the
365 // expected data, served from the cache.
366 external_data_manager_
->Fetch(k10BytePolicy
, ConstructFetchCallback(0));
367 external_data_manager_
->Fetch(k20BytePolicy
, ConstructFetchCallback(1));
368 base::RunLoop().RunUntilIdle();
369 EXPECT_EQ(2u, callback_data_
.size());
370 ASSERT_TRUE(callback_data_
[0]);
371 EXPECT_EQ(k10ByteData
, *callback_data_
[0]);
372 ASSERT_TRUE(callback_data_
[1]);
373 EXPECT_EQ(k20ByteData
, *callback_data_
[1]);
376 // Explicitly tell the external_data_manager_ to not make any download
378 external_data_manager_
->Disconnect();
380 // Retrieve external data for |k10BytePolicy| and |k20BytePolicy|. Verify that
381 // even though downloads are not allowed, the callbacks are still invoked with
382 // the expected data, served from the cache.
383 external_data_manager_
->Fetch(k10BytePolicy
, ConstructFetchCallback(2));
384 external_data_manager_
->Fetch(k20BytePolicy
, ConstructFetchCallback(3));
385 base::RunLoop().RunUntilIdle();
386 EXPECT_EQ(2u, callback_data_
.size());
387 ASSERT_TRUE(callback_data_
[2]);
388 EXPECT_EQ(k10ByteData
, *callback_data_
[2]);
389 ASSERT_TRUE(callback_data_
[3]);
390 EXPECT_EQ(k20ByteData
, *callback_data_
[3]);
393 // Verify that the downloaded data is present in the cache.
394 external_data_manager_
.reset();
395 base::RunLoop().RunUntilIdle();
396 CloudExternalDataStore
cache(kCacheKey
, message_loop_
.task_runner(),
397 resource_cache_
.get());
399 EXPECT_TRUE(cache
.Load(k10BytePolicy
,
400 crypto::SHA256HashString(k10ByteData
),
403 EXPECT_EQ(k10ByteData
, data
);
404 EXPECT_TRUE(cache
.Load(k20BytePolicy
,
405 crypto::SHA256HashString(k20ByteData
),
408 EXPECT_EQ(k20ByteData
, data
);
411 // Verifies that when the external data referenced by a policy is not present in
412 // the cache and downloads are not allowed, a request to retrieve the data is
413 // enqueued and carried out when downloads become possible.
414 TEST_F(CloudExternalDataManagerBaseTest
, DownloadAfterConnect
) {
415 // Attempt to retrieve external data for |k10BytePolicy|. Verify that the
416 // callback is not invoked as the request remains pending.
417 external_data_manager_
->Fetch(k10BytePolicy
, ConstructFetchCallback(0));
418 base::RunLoop().RunUntilIdle();
419 EXPECT_TRUE(callback_data_
.empty());
422 // Serve valid external data for |k10BytePolicy| and allow the
423 // external_data_manager_ to perform downloads.
424 SetFakeResponse(k10BytePolicyURL
, k10ByteData
, net::HTTP_OK
,
425 net::URLRequestStatus::SUCCESS
);
426 external_data_manager_
->Connect(request_content_getter_
);
428 // Verify that a download happens and the callback is invoked with the
430 base::RunLoop().RunUntilIdle();
431 EXPECT_EQ(1u, callback_data_
.size());
432 ASSERT_TRUE(callback_data_
[0]);
433 EXPECT_EQ(k10ByteData
, *callback_data_
[0]);
437 // Verifies that when the external data referenced by a policy is not present in
438 // the cache and cannot be downloaded at this time, a request to retrieve the
439 // data is enqueued to be retried later.
440 TEST_F(CloudExternalDataManagerBaseTest
, DownloadError
) {
441 // Make attempts to download the external data for |k20BytePolicy| fail with
443 SetFakeResponse(k20BytePolicyURL
, std::string(),
444 net::HTTP_INTERNAL_SERVER_ERROR
,
445 net::URLRequestStatus::FAILED
);
446 external_data_manager_
->Connect(request_content_getter_
);
448 // Attempt to retrieve external data for |k20BytePolicy|. Verify that the
449 // callback is not invoked as the download attempt fails and the request
451 external_data_manager_
->Fetch(k20BytePolicy
, ConstructFetchCallback(0));
452 base::RunLoop().RunUntilIdle();
453 EXPECT_TRUE(callback_data_
.empty());
456 // Modify the external data reference for |k20BytePolicy|, allowing the
457 // download to be retried immediately.
458 SetExternalDataReference(
460 ConstructMetadata(k20BytePolicyURL
,
461 crypto::SHA256HashString(k10ByteData
)));
462 cloud_policy_store_
.NotifyStoreLoaded();
464 // Attempt to retrieve external data for |k20BytePolicy| again. Verify that
465 // no callback is invoked still as the download attempt fails again and the
466 // request remains pending.
467 external_data_manager_
->Fetch(k20BytePolicy
, ConstructFetchCallback(1));
468 base::RunLoop().RunUntilIdle();
469 EXPECT_TRUE(callback_data_
.empty());
472 // Modify the external data reference for |k20BytePolicy|, allowing the
473 // download to be retried immediately.
474 SetExternalDataReference(
476 ConstructMetadata(k20BytePolicyURL
,
477 crypto::SHA256HashString(k20ByteData
)));
478 cloud_policy_store_
.NotifyStoreLoaded();
480 // Serve external data for |k20BytePolicy| that does not match the hash
481 // specified in its current external data reference.
482 SetFakeResponse(k20BytePolicyURL
, k10ByteData
, net::HTTP_OK
,
483 net::URLRequestStatus::SUCCESS
);
485 // Attempt to retrieve external data for |k20BytePolicy| again. Verify that
486 // no callback is invoked still as the downloaded succeeds but returns data
487 // that does not match the external data reference.
488 external_data_manager_
->Fetch(k20BytePolicy
, ConstructFetchCallback(2));
489 base::RunLoop().RunUntilIdle();
490 EXPECT_TRUE(callback_data_
.empty());
493 // Modify the external data reference for |k20BytePolicy|, allowing the
494 // download to be retried immediately. The external data reference now matches
495 // the data being served.
496 SetExternalDataReference(
498 ConstructMetadata(k20BytePolicyURL
,
499 crypto::SHA256HashString(k10ByteData
)));
500 cloud_policy_store_
.NotifyStoreLoaded();
502 // Attempt to retrieve external data for |k20BytePolicy| again. Verify that
503 // the current callback and the three previously enqueued callbacks are
504 // invoked with the downloaded data now.
505 external_data_manager_
->Fetch(k20BytePolicy
, ConstructFetchCallback(3));
506 base::RunLoop().RunUntilIdle();
507 EXPECT_EQ(4u, callback_data_
.size());
508 ASSERT_TRUE(callback_data_
[0]);
509 EXPECT_EQ(k10ByteData
, *callback_data_
[0]);
510 ASSERT_TRUE(callback_data_
[1]);
511 EXPECT_EQ(k10ByteData
, *callback_data_
[1]);
512 ASSERT_TRUE(callback_data_
[2]);
513 EXPECT_EQ(k10ByteData
, *callback_data_
[2]);
514 ASSERT_TRUE(callback_data_
[3]);
515 EXPECT_EQ(k10ByteData
, *callback_data_
[3]);
519 // Verifies that when the external data referenced by a policy is present in the
520 // cache, a request to retrieve it is served from the cache without any download
522 TEST_F(CloudExternalDataManagerBaseTest
, LoadFromCache
) {
523 // Store valid external data for |k10BytePolicy| in the cache.
524 external_data_manager_
.reset();
525 base::RunLoop().RunUntilIdle();
526 EXPECT_TRUE(CloudExternalDataStore(kCacheKey
, message_loop_
.task_runner(),
527 resource_cache_
.get())
528 .Store(k10BytePolicy
, crypto::SHA256HashString(k10ByteData
),
531 // Instantiate an external_data_manager_ that uses the primed cache.
532 SetUpExternalDataManager();
533 external_data_manager_
->Connect(request_content_getter_
);
535 // Retrieve external data for |k10BytePolicy|. Verify that no download is
536 // attempted but the callback is still invoked with the expected data, served
538 external_data_manager_
->Fetch(k10BytePolicy
, ConstructFetchCallback(0));
539 base::RunLoop().RunUntilIdle();
540 EXPECT_EQ(1u, callback_data_
.size());
541 ASSERT_TRUE(callback_data_
[0]);
542 EXPECT_EQ(k10ByteData
, *callback_data_
[0]);
546 // Verifies that cache entries which do not correspond to the external data
547 // referenced by any policy are pruned on startup.
548 TEST_F(CloudExternalDataManagerBaseTest
, PruneCacheOnStartup
) {
549 external_data_manager_
.reset();
550 base::RunLoop().RunUntilIdle();
551 scoped_ptr
<CloudExternalDataStore
> cache(new CloudExternalDataStore(
552 kCacheKey
, message_loop_
.task_runner(), resource_cache_
.get()));
553 // Store valid external data for |k10BytePolicy| in the cache.
554 EXPECT_TRUE(cache
->Store(k10BytePolicy
,
555 crypto::SHA256HashString(k10ByteData
),
557 // Store external data for |k20BytePolicy| that does not match the hash in its
558 // external data reference.
559 EXPECT_TRUE(cache
->Store(k20BytePolicy
,
560 crypto::SHA256HashString(k10ByteData
),
562 // Store external data for |kUnknownPolicy|, which is not a known policy and
563 // therefore, cannot be referencing any external data.
564 EXPECT_TRUE(cache
->Store(kUnknownPolicy
,
565 crypto::SHA256HashString(k10ByteData
),
569 // Instantiate and destroy an ExternalDataManager that uses the primed cache.
570 SetUpExternalDataManager();
571 external_data_manager_
.reset();
572 base::RunLoop().RunUntilIdle();
574 cache
.reset(new CloudExternalDataStore(kCacheKey
, message_loop_
.task_runner(),
575 resource_cache_
.get()));
577 // Verify that the valid external data for |k10BytePolicy| is still in the
579 EXPECT_TRUE(cache
->Load(k10BytePolicy
,
580 crypto::SHA256HashString(k10ByteData
),
583 EXPECT_EQ(k10ByteData
, data
);
584 // Verify that the external data for |k20BytePolicy| and |kUnknownPolicy| has
585 // been pruned from the cache.
586 EXPECT_FALSE(cache
->Load(k20BytePolicy
,
587 crypto::SHA256HashString(k10ByteData
),
590 EXPECT_FALSE(cache
->Load(kUnknownPolicy
,
591 crypto::SHA256HashString(k10ByteData
),
596 // Verifies that when the external data referenced by a policy is present in the
597 // cache and the reference changes, the old data is pruned from the cache.
598 TEST_F(CloudExternalDataManagerBaseTest
, PruneCacheOnChange
) {
599 // Store valid external data for |k20BytePolicy| in the cache.
600 external_data_manager_
.reset();
601 base::RunLoop().RunUntilIdle();
602 scoped_ptr
<CloudExternalDataStore
> cache(new CloudExternalDataStore(
603 kCacheKey
, message_loop_
.task_runner(), resource_cache_
.get()));
604 EXPECT_TRUE(cache
->Store(k20BytePolicy
,
605 crypto::SHA256HashString(k20ByteData
),
609 // Instantiate an ExternalDataManager that uses the primed cache.
610 SetUpExternalDataManager();
611 external_data_manager_
->Connect(request_content_getter_
);
613 // Modify the external data reference for |k20BytePolicy|.
614 SetExternalDataReference(
616 ConstructMetadata(k20BytePolicyURL
,
617 crypto::SHA256HashString(k10ByteData
)));
618 cloud_policy_store_
.NotifyStoreLoaded();
620 // Verify that the old external data for |k20BytePolicy| has been pruned from
622 external_data_manager_
.reset();
623 base::RunLoop().RunUntilIdle();
624 cache
.reset(new CloudExternalDataStore(kCacheKey
, message_loop_
.task_runner(),
625 resource_cache_
.get()));
627 EXPECT_FALSE(cache
->Load(k20BytePolicy
,
628 crypto::SHA256HashString(k20ByteData
),
633 // Verifies that corrupt cache entries are detected and deleted when accessed.
634 TEST_F(CloudExternalDataManagerBaseTest
, CacheCorruption
) {
635 external_data_manager_
.reset();
636 base::RunLoop().RunUntilIdle();
637 scoped_ptr
<CloudExternalDataStore
> cache(new CloudExternalDataStore(
638 kCacheKey
, message_loop_
.task_runner(), resource_cache_
.get()));
639 // Store external data for |k10BytePolicy| that exceeds the maximal external
640 // data size allowed for that policy.
641 EXPECT_TRUE(cache
->Store(k10BytePolicy
,
642 crypto::SHA256HashString(k20ByteData
),
644 // Store external data for |k20BytePolicy| that is corrupted and does not
645 // match the expected hash.
646 EXPECT_TRUE(cache
->Store(k20BytePolicy
,
647 crypto::SHA256HashString(k20ByteData
),
651 SetUpExternalDataManager();
652 // Serve external data for |k10BytePolicy| that exceeds the maximal external
653 // data size allowed for that policy.
654 SetFakeResponse(k10BytePolicyURL
, k20ByteData
, net::HTTP_OK
,
655 net::URLRequestStatus::SUCCESS
);
656 external_data_manager_
->Connect(request_content_getter_
);
658 // Modify the external data reference for |k10BytePolicy| to match the
659 // external data being served.
660 SetExternalDataReference(
662 ConstructMetadata(k10BytePolicyURL
,
663 crypto::SHA256HashString(k20ByteData
)));
664 cloud_policy_store_
.NotifyStoreLoaded();
666 // Retrieve external data for |k10BytePolicy|. Verify that the callback is
667 // not invoked as the cached and downloaded external data exceed the maximal
668 // size allowed for this policy and the request remains pending.
669 external_data_manager_
->Fetch(k10BytePolicy
, ConstructFetchCallback(0));
670 base::RunLoop().RunUntilIdle();
671 EXPECT_TRUE(callback_data_
.empty());
674 // Serve valid external data for |k20BytePolicy|.
675 SetFakeResponse(k20BytePolicyURL
, k20ByteData
, net::HTTP_OK
,
676 net::URLRequestStatus::SUCCESS
);
678 // Retrieve external data for |k20BytePolicy|. Verify that the callback is
679 // invoked with the valid downloaded data, not the invalid data in the cache.
680 external_data_manager_
->Fetch(k20BytePolicy
, ConstructFetchCallback(1));
681 base::RunLoop().RunUntilIdle();
682 EXPECT_EQ(1u, callback_data_
.size());
683 ASSERT_TRUE(callback_data_
[1]);
684 EXPECT_EQ(k20ByteData
, *callback_data_
[1]);
687 external_data_manager_
.reset();
688 base::RunLoop().RunUntilIdle();
689 cache
.reset(new CloudExternalDataStore(kCacheKey
, message_loop_
.task_runner(),
690 resource_cache_
.get()));
692 // Verify that the invalid external data for |k10BytePolicy| has been pruned
693 // from the cache. Load() will return |false| in two cases:
694 // 1) The cache entry for |k10BytePolicy| has been pruned.
695 // 2) The cache entry for |k10BytePolicy| still exists but the cached data
696 // does not match the expected hash or exceeds the maximum size allowed.
697 // To test for the former, Load() is called with a maximum data size and hash
698 // that would allow the data originally written to the cache to be loaded.
699 // When this fails, it is certain that the original data is no longer present
701 EXPECT_FALSE(cache
->Load(k10BytePolicy
,
702 crypto::SHA256HashString(k20ByteData
),
705 // Verify that the invalid external data for |k20BytePolicy| has been replaced
706 // with the downloaded valid data in the cache.
707 EXPECT_TRUE(cache
->Load(k20BytePolicy
,
708 crypto::SHA256HashString(k20ByteData
),
711 EXPECT_EQ(k20ByteData
, data
);
714 // Verifies that when the external data reference for a policy changes while a
715 // download of the external data for that policy is pending, the download is
716 // immediately retried using the new reference.
717 TEST_F(CloudExternalDataManagerBaseTest
, PolicyChangeWhileDownloadPending
) {
718 // Make attempts to download the external data for |k10BytePolicy| and
719 // |k20BytePolicy| fail with an error.
720 SetFakeResponse(k10BytePolicyURL
, std::string(),
721 net::HTTP_INTERNAL_SERVER_ERROR
,
722 net::URLRequestStatus::FAILED
);
723 SetFakeResponse(k20BytePolicyURL
, std::string(),
724 net::HTTP_INTERNAL_SERVER_ERROR
,
725 net::URLRequestStatus::FAILED
);
726 external_data_manager_
->Connect(request_content_getter_
);
728 // Attempt to retrieve external data for |k10BytePolicy| and |k20BytePolicy|.
729 // Verify that no callbacks are invoked as the download attempts fail and the
730 // requests remain pending.
731 external_data_manager_
->Fetch(k10BytePolicy
, ConstructFetchCallback(0));
732 external_data_manager_
->Fetch(k20BytePolicy
, ConstructFetchCallback(1));
733 base::RunLoop().RunUntilIdle();
734 EXPECT_TRUE(callback_data_
.empty());
737 // Modify the external data reference for |k10BytePolicy| to be invalid.
738 // Verify that the callback is invoked as the policy no longer has a valid
739 // external data reference.
740 cloud_policy_store_
.policy_map_
.Erase(k10BytePolicy
);
741 cloud_policy_store_
.NotifyStoreLoaded();
742 base::RunLoop().RunUntilIdle();
743 EXPECT_EQ(1u, callback_data_
.size());
744 EXPECT_TRUE(callback_data_
.find(0) != callback_data_
.end());
745 EXPECT_FALSE(callback_data_
[0]);
748 // Serve valid external data for |k20BytePolicy|.
749 fetcher_factory_
.ClearFakeResponses();
750 SetFakeResponse(k20BytePolicyURL
, k10ByteData
, net::HTTP_OK
,
751 net::URLRequestStatus::SUCCESS
);
753 // Modify the external data reference for |k20BytePolicy| to match the
754 // external data now being served. Verify that the callback is invoked with
755 // the downloaded data.
756 SetExternalDataReference(
758 ConstructMetadata(k20BytePolicyURL
,
759 crypto::SHA256HashString(k10ByteData
)));
760 cloud_policy_store_
.NotifyStoreLoaded();
761 base::RunLoop().RunUntilIdle();
762 EXPECT_EQ(1u, callback_data_
.size());
763 ASSERT_TRUE(callback_data_
[1]);
764 EXPECT_EQ(k10ByteData
, *callback_data_
[1]);
768 } // namespace policy