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
,
160 new base::StringValue(std::string()),
162 // Make |k10BytePolicy| reference 10 bytes of external data.
163 SetExternalDataReference(
165 ConstructMetadata(k10BytePolicyURL
,
166 crypto::SHA256HashString(k10ByteData
)));
167 // Make |k20BytePolicy| reference 20 bytes of external data.
168 SetExternalDataReference(
170 ConstructMetadata(k20BytePolicyURL
,
171 crypto::SHA256HashString(k20ByteData
)));
172 cloud_policy_store_
.NotifyStoreLoaded();
174 request_content_getter_
=
175 new net::TestURLRequestContextGetter(base::ThreadTaskRunnerHandle::Get());
177 policy_details_
.SetDetails(kStringPolicy
, &kPolicyDetails
[0]);
178 policy_details_
.SetDetails(k10BytePolicy
, &kPolicyDetails
[1]);
179 policy_details_
.SetDetails(k20BytePolicy
, &kPolicyDetails
[2]);
182 void CloudExternalDataManagerBaseTest::TearDown() {
183 external_data_manager_
.reset();
184 base::RunLoop().RunUntilIdle();
188 void CloudExternalDataManagerBaseTest::SetUpExternalDataManager() {
189 external_data_manager_
.reset(new CloudExternalDataManagerBase(
190 policy_details_
.GetCallback(), message_loop_
.task_runner(),
191 message_loop_
.task_runner()));
192 external_data_manager_
->SetExternalDataStore(
193 make_scoped_ptr(new CloudExternalDataStore(
194 kCacheKey
, message_loop_
.task_runner(), resource_cache_
.get())));
195 external_data_manager_
->SetPolicyStore(&cloud_policy_store_
);
198 scoped_ptr
<base::DictionaryValue
>
199 CloudExternalDataManagerBaseTest::ConstructMetadata(
200 const std::string
& url
,
201 const std::string
& hash
) {
202 scoped_ptr
<base::DictionaryValue
> metadata(new base::DictionaryValue
);
203 metadata
->SetStringWithoutPathExpansion("url", url
);
204 metadata
->SetStringWithoutPathExpansion("hash", base::HexEncode(hash
.c_str(),
206 return metadata
.Pass();
209 void CloudExternalDataManagerBaseTest::SetExternalDataReference(
210 const std::string
& policy
,
211 scoped_ptr
<base::DictionaryValue
> metadata
) {
212 cloud_policy_store_
.policy_map_
.Set(
214 POLICY_LEVEL_MANDATORY
,
218 new ExternalDataFetcher(
219 external_data_manager_
->weak_factory_
.GetWeakPtr(), policy
));
222 ExternalDataFetcher::FetchCallback
223 CloudExternalDataManagerBaseTest::ConstructFetchCallback(int id
) {
224 return base::Bind(&CloudExternalDataManagerBaseTest::OnFetchDone
,
225 base::Unretained(this),
229 void CloudExternalDataManagerBaseTest::ResetCallbackData() {
230 STLDeleteValues(&callback_data_
);
233 void CloudExternalDataManagerBaseTest::OnFetchDone(
235 scoped_ptr
<std::string
> data
) {
236 delete callback_data_
[id
];
237 callback_data_
[id
] = data
.release();
240 void CloudExternalDataManagerBaseTest::FetchAll() {
241 external_data_manager_
->FetchAll();
244 void CloudExternalDataManagerBaseTest::SetFakeResponse(
245 const std::string
& url
,
246 const std::string
& response_data
,
247 net::HttpStatusCode response_code
,
248 net::URLRequestStatus::Status status
) {
249 fetcher_factory_
.SetFakeResponse(
250 GURL(url
), response_data
, response_code
, status
);
253 // Verifies that when no valid external data reference has been set for a
254 // policy, the attempt to retrieve the external data fails immediately.
255 TEST_F(CloudExternalDataManagerBaseTest
, FailToFetchInvalid
) {
256 external_data_manager_
->Connect(request_content_getter_
);
258 // Attempt to retrieve external data for |kStringPolicy|, which is a string
259 // policy that does not reference any external data.
260 external_data_manager_
->Fetch(kStringPolicy
, ConstructFetchCallback(0));
261 base::RunLoop().RunUntilIdle();
262 EXPECT_EQ(1u, callback_data_
.size());
263 EXPECT_TRUE(callback_data_
.find(0) != callback_data_
.end());
264 EXPECT_FALSE(callback_data_
[0]);
267 // Attempt to retrieve external data for |kUnknownPolicy|, which is not a
269 external_data_manager_
->Fetch(kUnknownPolicy
, ConstructFetchCallback(1));
270 base::RunLoop().RunUntilIdle();
271 EXPECT_EQ(1u, callback_data_
.size());
272 EXPECT_TRUE(callback_data_
.find(1) != callback_data_
.end());
273 EXPECT_FALSE(callback_data_
[1]);
276 // Set an invalid external data reference for |k10BytePolicy|.
277 SetExternalDataReference(k10BytePolicy
,
278 ConstructMetadata(std::string(), std::string()));
279 cloud_policy_store_
.NotifyStoreLoaded();
281 // Attempt to retrieve external data for |k10BytePolicy|, which now has an
282 // invalid reference.
283 external_data_manager_
->Fetch(k10BytePolicy
, ConstructFetchCallback(2));
284 base::RunLoop().RunUntilIdle();
285 EXPECT_EQ(1u, callback_data_
.size());
286 EXPECT_TRUE(callback_data_
.find(2) != callback_data_
.end());
287 EXPECT_FALSE(callback_data_
[2]);
291 // Verifies that external data referenced by a policy is downloaded and cached
292 // when first requested. Subsequent requests are served from the cache without
293 // further download attempts.
294 TEST_F(CloudExternalDataManagerBaseTest
, DownloadAndCache
) {
295 // Serve valid external data for |k10BytePolicy|.
296 SetFakeResponse(k10BytePolicyURL
, k10ByteData
, net::HTTP_OK
,
297 net::URLRequestStatus::SUCCESS
);
298 external_data_manager_
->Connect(request_content_getter_
);
300 // Retrieve external data for |k10BytePolicy|. Verify that a download happens
301 // and the callback is invoked with the downloaded data.
302 external_data_manager_
->Fetch(k10BytePolicy
, ConstructFetchCallback(0));
303 base::RunLoop().RunUntilIdle();
304 EXPECT_EQ(1u, callback_data_
.size());
305 ASSERT_TRUE(callback_data_
[0]);
306 EXPECT_EQ(k10ByteData
, *callback_data_
[0]);
309 // Stop serving external data for |k10BytePolicy|.
310 fetcher_factory_
.ClearFakeResponses();
312 // Retrieve external data for |k10BytePolicy| again. Verify that no download
313 // is attempted but the callback is still invoked with the expected data,
314 // served from the cache.
315 external_data_manager_
->Fetch(k10BytePolicy
, ConstructFetchCallback(1));
316 base::RunLoop().RunUntilIdle();
317 EXPECT_EQ(1u, callback_data_
.size());
318 ASSERT_TRUE(callback_data_
[1]);
319 EXPECT_EQ(k10ByteData
, *callback_data_
[1]);
322 // Explicitly tell the external_data_manager_ to not make any download
324 external_data_manager_
->Disconnect();
326 // Retrieve external data for |k10BytePolicy| again. Verify that even though
327 // downloads are not allowed, the callback is still invoked with the expected
328 // data, served from the cache.
329 external_data_manager_
->Fetch(k10BytePolicy
, ConstructFetchCallback(2));
330 base::RunLoop().RunUntilIdle();
331 EXPECT_EQ(1u, callback_data_
.size());
332 ASSERT_TRUE(callback_data_
[2]);
333 EXPECT_EQ(k10ByteData
, *callback_data_
[2]);
336 // Verify that the downloaded data is present in the cache.
337 external_data_manager_
.reset();
338 base::RunLoop().RunUntilIdle();
340 EXPECT_TRUE(CloudExternalDataStore(kCacheKey
, message_loop_
.task_runner(),
341 resource_cache_
.get())
342 .Load(k10BytePolicy
, crypto::SHA256HashString(k10ByteData
),
344 EXPECT_EQ(k10ByteData
, data
);
347 // Verifies that a request to download and cache all external data referenced by
348 // policies is carried out correctly. Subsequent requests for the data are
349 // served from the cache without further download attempts.
350 TEST_F(CloudExternalDataManagerBaseTest
, DownloadAndCacheAll
) {
351 // Serve valid external data for |k10BytePolicy| and |k20BytePolicy|.
352 SetFakeResponse(k10BytePolicyURL
, k10ByteData
, net::HTTP_OK
,
353 net::URLRequestStatus::SUCCESS
);
354 SetFakeResponse(k20BytePolicyURL
, k20ByteData
, net::HTTP_OK
,
355 net::URLRequestStatus::SUCCESS
);
356 external_data_manager_
->Connect(request_content_getter_
);
358 // Request that external data referenced by all policies be downloaded.
360 base::RunLoop().RunUntilIdle();
362 // Stop serving external data for |k10BytePolicy| and |k20BytePolicy|.
363 fetcher_factory_
.ClearFakeResponses();
365 // Retrieve external data for |k10BytePolicy| and |k20BytePolicy|. Verify that
366 // no downloads are attempted but the callbacks are still invoked with the
367 // expected data, served from the cache.
368 external_data_manager_
->Fetch(k10BytePolicy
, ConstructFetchCallback(0));
369 external_data_manager_
->Fetch(k20BytePolicy
, ConstructFetchCallback(1));
370 base::RunLoop().RunUntilIdle();
371 EXPECT_EQ(2u, callback_data_
.size());
372 ASSERT_TRUE(callback_data_
[0]);
373 EXPECT_EQ(k10ByteData
, *callback_data_
[0]);
374 ASSERT_TRUE(callback_data_
[1]);
375 EXPECT_EQ(k20ByteData
, *callback_data_
[1]);
378 // Explicitly tell the external_data_manager_ to not make any download
380 external_data_manager_
->Disconnect();
382 // Retrieve external data for |k10BytePolicy| and |k20BytePolicy|. Verify that
383 // even though downloads are not allowed, the callbacks are still invoked with
384 // the expected data, served from the cache.
385 external_data_manager_
->Fetch(k10BytePolicy
, ConstructFetchCallback(2));
386 external_data_manager_
->Fetch(k20BytePolicy
, ConstructFetchCallback(3));
387 base::RunLoop().RunUntilIdle();
388 EXPECT_EQ(2u, callback_data_
.size());
389 ASSERT_TRUE(callback_data_
[2]);
390 EXPECT_EQ(k10ByteData
, *callback_data_
[2]);
391 ASSERT_TRUE(callback_data_
[3]);
392 EXPECT_EQ(k20ByteData
, *callback_data_
[3]);
395 // Verify that the downloaded data is present in the cache.
396 external_data_manager_
.reset();
397 base::RunLoop().RunUntilIdle();
398 CloudExternalDataStore
cache(kCacheKey
, message_loop_
.task_runner(),
399 resource_cache_
.get());
401 EXPECT_TRUE(cache
.Load(k10BytePolicy
,
402 crypto::SHA256HashString(k10ByteData
),
405 EXPECT_EQ(k10ByteData
, data
);
406 EXPECT_TRUE(cache
.Load(k20BytePolicy
,
407 crypto::SHA256HashString(k20ByteData
),
410 EXPECT_EQ(k20ByteData
, data
);
413 // Verifies that when the external data referenced by a policy is not present in
414 // the cache and downloads are not allowed, a request to retrieve the data is
415 // enqueued and carried out when downloads become possible.
416 TEST_F(CloudExternalDataManagerBaseTest
, DownloadAfterConnect
) {
417 // Attempt to retrieve external data for |k10BytePolicy|. Verify that the
418 // callback is not invoked as the request remains pending.
419 external_data_manager_
->Fetch(k10BytePolicy
, ConstructFetchCallback(0));
420 base::RunLoop().RunUntilIdle();
421 EXPECT_TRUE(callback_data_
.empty());
424 // Serve valid external data for |k10BytePolicy| and allow the
425 // external_data_manager_ to perform downloads.
426 SetFakeResponse(k10BytePolicyURL
, k10ByteData
, net::HTTP_OK
,
427 net::URLRequestStatus::SUCCESS
);
428 external_data_manager_
->Connect(request_content_getter_
);
430 // Verify that a download happens and the callback is invoked with the
432 base::RunLoop().RunUntilIdle();
433 EXPECT_EQ(1u, callback_data_
.size());
434 ASSERT_TRUE(callback_data_
[0]);
435 EXPECT_EQ(k10ByteData
, *callback_data_
[0]);
439 // Verifies that when the external data referenced by a policy is not present in
440 // the cache and cannot be downloaded at this time, a request to retrieve the
441 // data is enqueued to be retried later.
442 TEST_F(CloudExternalDataManagerBaseTest
, DownloadError
) {
443 // Make attempts to download the external data for |k20BytePolicy| fail with
445 SetFakeResponse(k20BytePolicyURL
, std::string(),
446 net::HTTP_INTERNAL_SERVER_ERROR
,
447 net::URLRequestStatus::FAILED
);
448 external_data_manager_
->Connect(request_content_getter_
);
450 // Attempt to retrieve external data for |k20BytePolicy|. Verify that the
451 // callback is not invoked as the download attempt fails and the request
453 external_data_manager_
->Fetch(k20BytePolicy
, ConstructFetchCallback(0));
454 base::RunLoop().RunUntilIdle();
455 EXPECT_TRUE(callback_data_
.empty());
458 // Modify the external data reference for |k20BytePolicy|, allowing the
459 // download to be retried immediately.
460 SetExternalDataReference(
462 ConstructMetadata(k20BytePolicyURL
,
463 crypto::SHA256HashString(k10ByteData
)));
464 cloud_policy_store_
.NotifyStoreLoaded();
466 // Attempt to retrieve external data for |k20BytePolicy| again. Verify that
467 // no callback is invoked still as the download attempt fails again and the
468 // request remains pending.
469 external_data_manager_
->Fetch(k20BytePolicy
, ConstructFetchCallback(1));
470 base::RunLoop().RunUntilIdle();
471 EXPECT_TRUE(callback_data_
.empty());
474 // Modify the external data reference for |k20BytePolicy|, allowing the
475 // download to be retried immediately.
476 SetExternalDataReference(
478 ConstructMetadata(k20BytePolicyURL
,
479 crypto::SHA256HashString(k20ByteData
)));
480 cloud_policy_store_
.NotifyStoreLoaded();
482 // Serve external data for |k20BytePolicy| that does not match the hash
483 // specified in its current external data reference.
484 SetFakeResponse(k20BytePolicyURL
, k10ByteData
, net::HTTP_OK
,
485 net::URLRequestStatus::SUCCESS
);
487 // Attempt to retrieve external data for |k20BytePolicy| again. Verify that
488 // no callback is invoked still as the downloaded succeeds but returns data
489 // that does not match the external data reference.
490 external_data_manager_
->Fetch(k20BytePolicy
, ConstructFetchCallback(2));
491 base::RunLoop().RunUntilIdle();
492 EXPECT_TRUE(callback_data_
.empty());
495 // Modify the external data reference for |k20BytePolicy|, allowing the
496 // download to be retried immediately. The external data reference now matches
497 // the data being served.
498 SetExternalDataReference(
500 ConstructMetadata(k20BytePolicyURL
,
501 crypto::SHA256HashString(k10ByteData
)));
502 cloud_policy_store_
.NotifyStoreLoaded();
504 // Attempt to retrieve external data for |k20BytePolicy| again. Verify that
505 // the current callback and the three previously enqueued callbacks are
506 // invoked with the downloaded data now.
507 external_data_manager_
->Fetch(k20BytePolicy
, ConstructFetchCallback(3));
508 base::RunLoop().RunUntilIdle();
509 EXPECT_EQ(4u, callback_data_
.size());
510 ASSERT_TRUE(callback_data_
[0]);
511 EXPECT_EQ(k10ByteData
, *callback_data_
[0]);
512 ASSERT_TRUE(callback_data_
[1]);
513 EXPECT_EQ(k10ByteData
, *callback_data_
[1]);
514 ASSERT_TRUE(callback_data_
[2]);
515 EXPECT_EQ(k10ByteData
, *callback_data_
[2]);
516 ASSERT_TRUE(callback_data_
[3]);
517 EXPECT_EQ(k10ByteData
, *callback_data_
[3]);
521 // Verifies that when the external data referenced by a policy is present in the
522 // cache, a request to retrieve it is served from the cache without any download
524 TEST_F(CloudExternalDataManagerBaseTest
, LoadFromCache
) {
525 // Store valid external data for |k10BytePolicy| in the cache.
526 external_data_manager_
.reset();
527 base::RunLoop().RunUntilIdle();
528 EXPECT_TRUE(CloudExternalDataStore(kCacheKey
, message_loop_
.task_runner(),
529 resource_cache_
.get())
530 .Store(k10BytePolicy
, crypto::SHA256HashString(k10ByteData
),
533 // Instantiate an external_data_manager_ that uses the primed cache.
534 SetUpExternalDataManager();
535 external_data_manager_
->Connect(request_content_getter_
);
537 // Retrieve external data for |k10BytePolicy|. Verify that no download is
538 // attempted but the callback is still invoked with the expected data, served
540 external_data_manager_
->Fetch(k10BytePolicy
, ConstructFetchCallback(0));
541 base::RunLoop().RunUntilIdle();
542 EXPECT_EQ(1u, callback_data_
.size());
543 ASSERT_TRUE(callback_data_
[0]);
544 EXPECT_EQ(k10ByteData
, *callback_data_
[0]);
548 // Verifies that cache entries which do not correspond to the external data
549 // referenced by any policy are pruned on startup.
550 TEST_F(CloudExternalDataManagerBaseTest
, PruneCacheOnStartup
) {
551 external_data_manager_
.reset();
552 base::RunLoop().RunUntilIdle();
553 scoped_ptr
<CloudExternalDataStore
> cache(new CloudExternalDataStore(
554 kCacheKey
, message_loop_
.task_runner(), resource_cache_
.get()));
555 // Store valid external data for |k10BytePolicy| in the cache.
556 EXPECT_TRUE(cache
->Store(k10BytePolicy
,
557 crypto::SHA256HashString(k10ByteData
),
559 // Store external data for |k20BytePolicy| that does not match the hash in its
560 // external data reference.
561 EXPECT_TRUE(cache
->Store(k20BytePolicy
,
562 crypto::SHA256HashString(k10ByteData
),
564 // Store external data for |kUnknownPolicy|, which is not a known policy and
565 // therefore, cannot be referencing any external data.
566 EXPECT_TRUE(cache
->Store(kUnknownPolicy
,
567 crypto::SHA256HashString(k10ByteData
),
571 // Instantiate and destroy an ExternalDataManager that uses the primed cache.
572 SetUpExternalDataManager();
573 external_data_manager_
.reset();
574 base::RunLoop().RunUntilIdle();
576 cache
.reset(new CloudExternalDataStore(kCacheKey
, message_loop_
.task_runner(),
577 resource_cache_
.get()));
579 // Verify that the valid external data for |k10BytePolicy| is still in the
581 EXPECT_TRUE(cache
->Load(k10BytePolicy
,
582 crypto::SHA256HashString(k10ByteData
),
585 EXPECT_EQ(k10ByteData
, data
);
586 // Verify that the external data for |k20BytePolicy| and |kUnknownPolicy| has
587 // been pruned from the cache.
588 EXPECT_FALSE(cache
->Load(k20BytePolicy
,
589 crypto::SHA256HashString(k10ByteData
),
592 EXPECT_FALSE(cache
->Load(kUnknownPolicy
,
593 crypto::SHA256HashString(k10ByteData
),
598 // Verifies that when the external data referenced by a policy is present in the
599 // cache and the reference changes, the old data is pruned from the cache.
600 TEST_F(CloudExternalDataManagerBaseTest
, PruneCacheOnChange
) {
601 // Store valid external data for |k20BytePolicy| in the cache.
602 external_data_manager_
.reset();
603 base::RunLoop().RunUntilIdle();
604 scoped_ptr
<CloudExternalDataStore
> cache(new CloudExternalDataStore(
605 kCacheKey
, message_loop_
.task_runner(), resource_cache_
.get()));
606 EXPECT_TRUE(cache
->Store(k20BytePolicy
,
607 crypto::SHA256HashString(k20ByteData
),
611 // Instantiate an ExternalDataManager that uses the primed cache.
612 SetUpExternalDataManager();
613 external_data_manager_
->Connect(request_content_getter_
);
615 // Modify the external data reference for |k20BytePolicy|.
616 SetExternalDataReference(
618 ConstructMetadata(k20BytePolicyURL
,
619 crypto::SHA256HashString(k10ByteData
)));
620 cloud_policy_store_
.NotifyStoreLoaded();
622 // Verify that the old external data for |k20BytePolicy| has been pruned from
624 external_data_manager_
.reset();
625 base::RunLoop().RunUntilIdle();
626 cache
.reset(new CloudExternalDataStore(kCacheKey
, message_loop_
.task_runner(),
627 resource_cache_
.get()));
629 EXPECT_FALSE(cache
->Load(k20BytePolicy
,
630 crypto::SHA256HashString(k20ByteData
),
635 // Verifies that corrupt cache entries are detected and deleted when accessed.
636 TEST_F(CloudExternalDataManagerBaseTest
, CacheCorruption
) {
637 external_data_manager_
.reset();
638 base::RunLoop().RunUntilIdle();
639 scoped_ptr
<CloudExternalDataStore
> cache(new CloudExternalDataStore(
640 kCacheKey
, message_loop_
.task_runner(), resource_cache_
.get()));
641 // Store external data for |k10BytePolicy| that exceeds the maximal external
642 // data size allowed for that policy.
643 EXPECT_TRUE(cache
->Store(k10BytePolicy
,
644 crypto::SHA256HashString(k20ByteData
),
646 // Store external data for |k20BytePolicy| that is corrupted and does not
647 // match the expected hash.
648 EXPECT_TRUE(cache
->Store(k20BytePolicy
,
649 crypto::SHA256HashString(k20ByteData
),
653 SetUpExternalDataManager();
654 // Serve external data for |k10BytePolicy| that exceeds the maximal external
655 // data size allowed for that policy.
656 SetFakeResponse(k10BytePolicyURL
, k20ByteData
, net::HTTP_OK
,
657 net::URLRequestStatus::SUCCESS
);
658 external_data_manager_
->Connect(request_content_getter_
);
660 // Modify the external data reference for |k10BytePolicy| to match the
661 // external data being served.
662 SetExternalDataReference(
664 ConstructMetadata(k10BytePolicyURL
,
665 crypto::SHA256HashString(k20ByteData
)));
666 cloud_policy_store_
.NotifyStoreLoaded();
668 // Retrieve external data for |k10BytePolicy|. Verify that the callback is
669 // not invoked as the cached and downloaded external data exceed the maximal
670 // size allowed for this policy and the request remains pending.
671 external_data_manager_
->Fetch(k10BytePolicy
, ConstructFetchCallback(0));
672 base::RunLoop().RunUntilIdle();
673 EXPECT_TRUE(callback_data_
.empty());
676 // Serve valid external data for |k20BytePolicy|.
677 SetFakeResponse(k20BytePolicyURL
, k20ByteData
, net::HTTP_OK
,
678 net::URLRequestStatus::SUCCESS
);
680 // Retrieve external data for |k20BytePolicy|. Verify that the callback is
681 // invoked with the valid downloaded data, not the invalid data in the cache.
682 external_data_manager_
->Fetch(k20BytePolicy
, ConstructFetchCallback(1));
683 base::RunLoop().RunUntilIdle();
684 EXPECT_EQ(1u, callback_data_
.size());
685 ASSERT_TRUE(callback_data_
[1]);
686 EXPECT_EQ(k20ByteData
, *callback_data_
[1]);
689 external_data_manager_
.reset();
690 base::RunLoop().RunUntilIdle();
691 cache
.reset(new CloudExternalDataStore(kCacheKey
, message_loop_
.task_runner(),
692 resource_cache_
.get()));
694 // Verify that the invalid external data for |k10BytePolicy| has been pruned
695 // from the cache. Load() will return |false| in two cases:
696 // 1) The cache entry for |k10BytePolicy| has been pruned.
697 // 2) The cache entry for |k10BytePolicy| still exists but the cached data
698 // does not match the expected hash or exceeds the maximum size allowed.
699 // To test for the former, Load() is called with a maximum data size and hash
700 // that would allow the data originally written to the cache to be loaded.
701 // When this fails, it is certain that the original data is no longer present
703 EXPECT_FALSE(cache
->Load(k10BytePolicy
,
704 crypto::SHA256HashString(k20ByteData
),
707 // Verify that the invalid external data for |k20BytePolicy| has been replaced
708 // with the downloaded valid data in the cache.
709 EXPECT_TRUE(cache
->Load(k20BytePolicy
,
710 crypto::SHA256HashString(k20ByteData
),
713 EXPECT_EQ(k20ByteData
, data
);
716 // Verifies that when the external data reference for a policy changes while a
717 // download of the external data for that policy is pending, the download is
718 // immediately retried using the new reference.
719 TEST_F(CloudExternalDataManagerBaseTest
, PolicyChangeWhileDownloadPending
) {
720 // Make attempts to download the external data for |k10BytePolicy| and
721 // |k20BytePolicy| fail with an error.
722 SetFakeResponse(k10BytePolicyURL
, std::string(),
723 net::HTTP_INTERNAL_SERVER_ERROR
,
724 net::URLRequestStatus::FAILED
);
725 SetFakeResponse(k20BytePolicyURL
, std::string(),
726 net::HTTP_INTERNAL_SERVER_ERROR
,
727 net::URLRequestStatus::FAILED
);
728 external_data_manager_
->Connect(request_content_getter_
);
730 // Attempt to retrieve external data for |k10BytePolicy| and |k20BytePolicy|.
731 // Verify that no callbacks are invoked as the download attempts fail and the
732 // requests remain pending.
733 external_data_manager_
->Fetch(k10BytePolicy
, ConstructFetchCallback(0));
734 external_data_manager_
->Fetch(k20BytePolicy
, ConstructFetchCallback(1));
735 base::RunLoop().RunUntilIdle();
736 EXPECT_TRUE(callback_data_
.empty());
739 // Modify the external data reference for |k10BytePolicy| to be invalid.
740 // Verify that the callback is invoked as the policy no longer has a valid
741 // external data reference.
742 cloud_policy_store_
.policy_map_
.Erase(k10BytePolicy
);
743 cloud_policy_store_
.NotifyStoreLoaded();
744 base::RunLoop().RunUntilIdle();
745 EXPECT_EQ(1u, callback_data_
.size());
746 EXPECT_TRUE(callback_data_
.find(0) != callback_data_
.end());
747 EXPECT_FALSE(callback_data_
[0]);
750 // Serve valid external data for |k20BytePolicy|.
751 fetcher_factory_
.ClearFakeResponses();
752 SetFakeResponse(k20BytePolicyURL
, k10ByteData
, net::HTTP_OK
,
753 net::URLRequestStatus::SUCCESS
);
755 // Modify the external data reference for |k20BytePolicy| to match the
756 // external data now being served. Verify that the callback is invoked with
757 // the downloaded data.
758 SetExternalDataReference(
760 ConstructMetadata(k20BytePolicyURL
,
761 crypto::SHA256HashString(k10ByteData
)));
762 cloud_policy_store_
.NotifyStoreLoaded();
763 base::RunLoop().RunUntilIdle();
764 EXPECT_EQ(1u, callback_data_
.size());
765 ASSERT_TRUE(callback_data_
[1]);
766 EXPECT_EQ(k10ByteData
, *callback_data_
[1]);
770 } // namespace policy