| Index: components/password_manager/core/browser/affiliation_backend_unittest.cc
|
| diff --git a/components/password_manager/core/browser/affiliation_backend_unittest.cc b/components/password_manager/core/browser/affiliation_backend_unittest.cc
|
| index a291da5cb8ba774787a5248abd72295579d35a35..5c45f35602f7a2a897063522800ed455f9612fa6 100644
|
| --- a/components/password_manager/core/browser/affiliation_backend_unittest.cc
|
| +++ b/components/password_manager/core/browser/affiliation_backend_unittest.cc
|
| @@ -9,8 +9,11 @@
|
| #include "base/macros.h"
|
| #include "base/memory/ref_counted.h"
|
| #include "base/memory/scoped_ptr.h"
|
| -#include "base/test/simple_test_clock.h"
|
| +#include "base/test/test_mock_time_task_runner.h"
|
| #include "base/test/test_simple_task_runner.h"
|
| +#include "base/thread_task_runner_handle.h"
|
| +#include "base/time/clock.h"
|
| +#include "components/password_manager/core/browser/facet_manager.h"
|
| #include "components/password_manager/core/browser/fake_affiliation_api.h"
|
| #include "components/password_manager/core/browser/mock_affiliation_consumer.h"
|
| #include "net/url_request/url_request_context_getter.h"
|
| @@ -49,13 +52,30 @@ AffiliatedFacets GetTestEquivalenceClassGamma() {
|
| return affiliated_facets;
|
| }
|
|
|
| +base::TimeDelta GetCacheHardExpiryPeriod() {
|
| + return base::TimeDelta::FromHours(FacetManager::kCacheHardExpiryInHours);
|
| +}
|
| +
|
| +base::TimeDelta GetCacheSoftExpiryPeriod() {
|
| + return base::TimeDelta::FromHours(FacetManager::kCacheSoftExpiryInHours);
|
| +}
|
| +
|
| +// Returns a smallest time difference that this test cares about.
|
| +base::TimeDelta Epsilon() {
|
| + return base::TimeDelta::FromMicroseconds(1);
|
| +}
|
| +
|
| } // namespace
|
|
|
| class AffiliationBackendTest : public testing::Test {
|
| public:
|
| AffiliationBackendTest()
|
| : consumer_task_runner_(new base::TestSimpleTaskRunner),
|
| - clock_(new base::SimpleTestClock) {}
|
| + backend_task_runner_(new base::TestMockTimeTaskRunner),
|
| + backend_task_runner_handle_(backend_task_runner_),
|
| + backend_(new AffiliationBackend(NULL,
|
| + backend_task_runner_->GetMockClock())) {
|
| + }
|
| ~AffiliationBackendTest() override {}
|
|
|
| protected:
|
| @@ -67,6 +87,14 @@ class AffiliationBackendTest : public testing::Test {
|
| consumer_task_runner());
|
| }
|
|
|
| + void Prefetch(const FacetURI& facet_uri, base::Time keep_fresh_until) {
|
| + backend_->Prefetch(facet_uri, keep_fresh_until);
|
| + }
|
| +
|
| + void CancelPrefetch(const FacetURI& facet_uri, base::Time keep_fresh_until) {
|
| + backend_->CancelPrefetch(facet_uri, keep_fresh_until);
|
| + }
|
| +
|
| void ExpectAndCompleteFetch(const FacetURI& expected_requested_facet_uri) {
|
| ASSERT_TRUE(fake_affiliation_api()->HasPendingRequest());
|
| EXPECT_THAT(fake_affiliation_api()->GetNextRequestedFacets(),
|
| @@ -102,14 +130,57 @@ class AffiliationBackendTest : public testing::Test {
|
| testing::Mock::VerifyAndClearExpectations(mock_consumer());
|
| }
|
|
|
| - void DestroyBackend() {
|
| - clock_ = nullptr;
|
| - backend_.reset();
|
| + void GetAffiliationsAndExpectFailureWithoutFetch(const FacetURI& facet_uri) {
|
| + GetAffiliations(mock_consumer(), facet_uri, true /* cached_only */);
|
| + ASSERT_NO_FATAL_FAILURE(ExpectFailureWithoutFetch(mock_consumer()));
|
| + }
|
| +
|
| + void PrefetchAndExpectFetch(const FacetURI& facet_uri,
|
| + base::Time keep_fresh_until) {
|
| + Prefetch(facet_uri, keep_fresh_until);
|
| + ASSERT_NO_FATAL_FAILURE(ExpectAndCompleteFetch(facet_uri));
|
| + }
|
| +
|
| + // Verifies that both on-demand and cached-only GetAffiliations() requests for
|
| + // each facet in |affiliated_facets| are served from cache with no fetches.
|
| + void ExpectThatEquivalenceClassIsServedFromCache(
|
| + const AffiliatedFacets& affiliated_facets) {
|
| + for (const FacetURI& facet_uri : affiliated_facets) {
|
| + SCOPED_TRACE(facet_uri);
|
| + ASSERT_NO_FATAL_FAILURE(GetAffiliationsAndExpectResultWithoutFetch(
|
| + facet_uri, false /* cached_only */, affiliated_facets));
|
| + ASSERT_NO_FATAL_FAILURE(GetAffiliationsAndExpectResultWithoutFetch(
|
| + facet_uri, true /* cached_only */, affiliated_facets));
|
| + }
|
| + }
|
| +
|
| + void DestroyBackend() { backend_.reset(); }
|
| +
|
| + void AdvanceTime(base::TimeDelta delta) {
|
| + backend_task_runner_->FastForwardBy(delta);
|
| }
|
|
|
| - void AdvanceTime(base::TimeDelta delta) { clock_->Advance(delta); }
|
| + size_t backend_facet_manager_count() {
|
| + return backend()->facet_manager_count_for_testing();
|
| + }
|
| +
|
| + bool IsCachedDataFreshForFacet(const FacetURI& facet_uri) {
|
| + scoped_ptr<base::Clock> clock(backend_task_runner_->GetMockClock());
|
| + return FacetManager(facet_uri, backend(), clock.get()).IsCachedDataFresh();
|
| + }
|
| +
|
| + bool IsCachedDataNearStaleForFacet(const FacetURI& facet_uri) {
|
| + scoped_ptr<base::Clock> clock(backend_task_runner_->GetMockClock());
|
| + return FacetManager(facet_uri, backend(), clock.get())
|
| + .IsCachedDataNearStale();
|
| + }
|
|
|
| AffiliationBackend* backend() { return backend_.get(); }
|
| +
|
| + base::TestMockTimeTaskRunner* backend_task_runner() {
|
| + return backend_task_runner_.get();
|
| + }
|
| +
|
| MockAffiliationConsumer* mock_consumer() { return &mock_consumer_; }
|
|
|
| base::TestSimpleTaskRunner* consumer_task_runner() {
|
| @@ -123,9 +194,6 @@ class AffiliationBackendTest : public testing::Test {
|
| private:
|
| // testing::Test:
|
| void SetUp() override {
|
| - clock_->Advance(base::TimeDelta::FromMicroseconds(1));
|
| - backend_.reset(new AffiliationBackend(nullptr, make_scoped_ptr(clock_)));
|
| -
|
| base::FilePath database_path;
|
| ASSERT_TRUE(CreateTemporaryFile(&database_path));
|
| backend_->Initialize(database_path);
|
| @@ -142,7 +210,9 @@ class AffiliationBackendTest : public testing::Test {
|
| MockAffiliationConsumer mock_consumer_;
|
| scoped_refptr<base::TestSimpleTaskRunner> consumer_task_runner_;
|
|
|
| - base::SimpleTestClock* clock_; // Owned by |backend_|.
|
| + scoped_refptr<base::TestMockTimeTaskRunner> backend_task_runner_;
|
| + base::ThreadTaskRunnerHandle backend_task_runner_handle_;
|
| +
|
| scoped_ptr<AffiliationBackend> backend_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(AffiliationBackendTest);
|
| @@ -152,36 +222,50 @@ TEST_F(AffiliationBackendTest, OnDemandRequestSucceedsWithFetch) {
|
| ASSERT_NO_FATAL_FAILURE(GetAffiliationsAndExpectFetchAndThenResult(
|
| FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
|
| GetTestEquivalenceClassAlpha()));
|
| + EXPECT_EQ(0u, backend_facet_manager_count());
|
|
|
| ASSERT_NO_FATAL_FAILURE(GetAffiliationsAndExpectFetchAndThenResult(
|
| FacetURI::FromCanonicalSpec(kTestFacetURIBeta1),
|
| GetTestEquivalenceClassBeta()));
|
| + EXPECT_EQ(0u, backend_facet_manager_count());
|
| }
|
|
|
| -TEST_F(AffiliationBackendTest, CachedOnlyRequestFailsOnCacheMiss) {
|
| - GetAffiliations(mock_consumer(),
|
| - FacetURI::FromCanonicalSpec(kTestFacetURIAlpha2),
|
| - true /* cached_only */);
|
| - ASSERT_FALSE(fake_affiliation_api()->HasPendingRequest());
|
| - mock_consumer()->ExpectFailure();
|
| - consumer_task_runner()->RunUntilIdle();
|
| - testing::Mock::VerifyAndClearExpectations(mock_consumer());
|
| +// This test also verifies that the FacetManager is immediately discarded.
|
| +TEST_F(AffiliationBackendTest, CachedOnlyRequestFailsDueToCacheMiss) {
|
| + GetAffiliationsAndExpectFailureWithoutFetch(
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha2));
|
| + EXPECT_EQ(0u, backend_facet_manager_count());
|
| +}
|
| +
|
| +TEST_F(AffiliationBackendTest, PrefetchTriggersInitialFetch) {
|
| + ASSERT_NO_FATAL_FAILURE(PrefetchAndExpectFetch(
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1), base::Time::Max()));
|
| +}
|
| +
|
| +// This test also verifies that the FacetManager is immediately discarded.
|
| +TEST_F(AffiliationBackendTest, ExpiredPrefetchTriggersNoInitialFetch) {
|
| + // Prefetch intervals are open from the right, thus intervals ending Now() are
|
| + // already expired.
|
| + Prefetch(FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
|
| + backend_task_runner()->Now());
|
| + EXPECT_EQ(0u, backend_facet_manager_count());
|
| + EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
|
| + EXPECT_FALSE(backend_task_runner()->HasPendingTask());
|
| }
|
|
|
| -// Two additional requests for unrelated facets come in while the network fetch
|
| -// triggered by the first request is in flight. There should be no simultaneous
|
| -// requests, and the additional facets should be queried together in a second
|
| -// fetch after the first fetch completes.
|
| +// One additional GetAffiliations() and one Prefetch() request for unrelated
|
| +// facets come in while the network fetch triggered by the first request is in
|
| +// flight. There should be no simultaneous requests, and the additional facets
|
| +// should be queried together in a second fetch after the first fetch completes.
|
| TEST_F(AffiliationBackendTest, ConcurrentUnrelatedRequests) {
|
| FacetURI facet_alpha(FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1));
|
| FacetURI facet_beta(FacetURI::FromCanonicalSpec(kTestFacetURIBeta1));
|
| FacetURI facet_gamma(FacetURI::FromCanonicalSpec(kTestFacetURIGamma1));
|
|
|
| MockAffiliationConsumer second_consumer;
|
| - MockAffiliationConsumer third_consumer;
|
| GetAffiliations(mock_consumer(), facet_alpha, false);
|
| GetAffiliations(&second_consumer, facet_beta, false);
|
| - GetAffiliations(&third_consumer, facet_gamma, false);
|
| + Prefetch(facet_gamma, base::Time::Max());
|
|
|
| ASSERT_NO_FATAL_FAILURE(ExpectAndCompleteFetch(facet_alpha));
|
| ASSERT_TRUE(fake_affiliation_api()->HasPendingRequest());
|
| @@ -191,9 +275,13 @@ TEST_F(AffiliationBackendTest, ConcurrentUnrelatedRequests) {
|
|
|
| mock_consumer()->ExpectSuccessWithResult(GetTestEquivalenceClassAlpha());
|
| second_consumer.ExpectSuccessWithResult(GetTestEquivalenceClassBeta());
|
| - third_consumer.ExpectSuccessWithResult(GetTestEquivalenceClassGamma());
|
| consumer_task_runner()->RunUntilIdle();
|
| testing::Mock::VerifyAndClearExpectations(mock_consumer());
|
| +
|
| + // Now that the two GetAffiliation() requests have been completed, the first
|
| + // two FacetManagers should be discarded. The third FacetManager corresponding
|
| + // to the prefetched facet should be kept.
|
| + EXPECT_GE(1u, backend_facet_manager_count());
|
| }
|
|
|
| TEST_F(AffiliationBackendTest, CacheServesSubsequentRequestForSameFacet) {
|
| @@ -208,6 +296,8 @@ TEST_F(AffiliationBackendTest, CacheServesSubsequentRequestForSameFacet) {
|
| ASSERT_NO_FATAL_FAILURE(GetAffiliationsAndExpectResultWithoutFetch(
|
| FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1), true /* cached_only */,
|
| GetTestEquivalenceClassAlpha()));
|
| +
|
| + EXPECT_EQ(0u, backend_facet_manager_count());
|
| }
|
|
|
| TEST_F(AffiliationBackendTest, CacheServesSubsequentRequestForAffiliatedFacet) {
|
| @@ -215,52 +305,31 @@ TEST_F(AffiliationBackendTest, CacheServesSubsequentRequestForAffiliatedFacet) {
|
| FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
|
| GetTestEquivalenceClassAlpha()));
|
|
|
| - ASSERT_NO_FATAL_FAILURE(GetAffiliationsAndExpectResultWithoutFetch(
|
| - FacetURI::FromCanonicalSpec(kTestFacetURIAlpha2), false /* cached_only */,
|
| + ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
|
| GetTestEquivalenceClassAlpha()));
|
|
|
| - ASSERT_NO_FATAL_FAILURE(GetAffiliationsAndExpectResultWithoutFetch(
|
| - FacetURI::FromCanonicalSpec(kTestFacetURIAlpha2), true /* cached_only */,
|
| - GetTestEquivalenceClassAlpha()));
|
| + EXPECT_EQ(0u, backend_facet_manager_count());
|
| }
|
|
|
| -TEST_F(AffiliationBackendTest, CacheExpiry) {
|
| - ASSERT_NO_FATAL_FAILURE(GetAffiliationsAndExpectFetchAndThenResult(
|
| - FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
|
| - GetTestEquivalenceClassAlpha()));
|
| +TEST_F(AffiliationBackendTest, CacheServesRequestsForPrefetchedFacets) {
|
| + ASSERT_NO_FATAL_FAILURE(PrefetchAndExpectFetch(
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1), base::Time::Max()));
|
|
|
| - AdvanceTime(base::TimeDelta::FromHours(24) -
|
| - base::TimeDelta::FromMicroseconds(1));
|
| -
|
| - // Before the data becomes stale, both on-demand and cached-only requests are
|
| - // expected to be served from the cache.
|
| ASSERT_NO_FATAL_FAILURE(GetAffiliationsAndExpectResultWithoutFetch(
|
| - FacetURI::FromCanonicalSpec(kTestFacetURIAlpha2), false /* cached_only */,
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1), false /* cached_only */,
|
| GetTestEquivalenceClassAlpha()));
|
|
|
| ASSERT_NO_FATAL_FAILURE(GetAffiliationsAndExpectResultWithoutFetch(
|
| - FacetURI::FromCanonicalSpec(kTestFacetURIAlpha2), true /* cached_only */,
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1), true /* cached_only */,
|
| GetTestEquivalenceClassAlpha()));
|
| +}
|
|
|
| - AdvanceTime(base::TimeDelta::FromMicroseconds(1));
|
| -
|
| - // After the data becomes stale, the cached-only request should fail, but the
|
| - // subsequent on-demand request should fetch the data again and succeed.
|
| - GetAffiliations(mock_consumer(),
|
| - FacetURI::FromCanonicalSpec(kTestFacetURIAlpha2),
|
| - true /* cached_only */);
|
| - ASSERT_FALSE(fake_affiliation_api()->HasPendingRequest());
|
| -
|
| - mock_consumer()->ExpectFailure();
|
| - consumer_task_runner()->RunUntilIdle();
|
| - testing::Mock::VerifyAndClearExpectations(mock_consumer());
|
| -
|
| - ASSERT_NO_FATAL_FAILURE(GetAffiliationsAndExpectFetchAndThenResult(
|
| - FacetURI::FromCanonicalSpec(kTestFacetURIAlpha2),
|
| - GetTestEquivalenceClassAlpha()));
|
| +TEST_F(AffiliationBackendTest,
|
| + CacheServesRequestsForFacetsAffiliatedWithPrefetchedFacets) {
|
| + ASSERT_NO_FATAL_FAILURE(PrefetchAndExpectFetch(
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1), base::Time::Max()));
|
|
|
| - ASSERT_NO_FATAL_FAILURE(GetAffiliationsAndExpectResultWithoutFetch(
|
| - FacetURI::FromCanonicalSpec(kTestFacetURIAlpha2), true /* cached_only */,
|
| + ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
|
| GetTestEquivalenceClassAlpha()));
|
| }
|
|
|
| @@ -268,7 +337,7 @@ TEST_F(AffiliationBackendTest, CacheExpiry) {
|
| // for an affiliated facet comes in while the network fetch triggered by the
|
| // first request is in flight.
|
| //
|
| -// There should be no simultaneous requests, so once the fetch completes, all
|
| +// There should be no simultaneous requests, and once the fetch completes, all
|
| // three requests should be served without further fetches (they have the data).
|
| TEST_F(AffiliationBackendTest,
|
| CacheServesConcurrentRequestsForAffiliatedFacets) {
|
| @@ -289,6 +358,223 @@ TEST_F(AffiliationBackendTest,
|
| third_consumer.ExpectSuccessWithResult(GetTestEquivalenceClassAlpha());
|
| consumer_task_runner()->RunUntilIdle();
|
| testing::Mock::VerifyAndClearExpectations(mock_consumer());
|
| +
|
| + EXPECT_EQ(0u, backend_facet_manager_count());
|
| +}
|
| +
|
| +// A second Prefetch() request for the same facet and a third request for an
|
| +// affiliated facet comes in while the initial fetch triggered by the first
|
| +// request is in flight.
|
| +//
|
| +// There should be no simultaneous requests, and once the fetch completes, there
|
| +// should be no further initial fetches as the data needed is already there.
|
| +TEST_F(AffiliationBackendTest,
|
| + CacheServesConcurrentPrefetchesForAffiliatedFacets) {
|
| + FacetURI facet_uri1(FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1));
|
| + FacetURI facet_uri2(FacetURI::FromCanonicalSpec(kTestFacetURIAlpha2));
|
| +
|
| + Prefetch(facet_uri1, base::Time::Max());
|
| + Prefetch(facet_uri1, base::Time::Max());
|
| + Prefetch(facet_uri2, base::Time::Max());
|
| +
|
| + ASSERT_NO_FATAL_FAILURE(ExpectAndCompleteFetch(facet_uri1));
|
| + ASSERT_FALSE(fake_affiliation_api()->HasPendingRequest());
|
| +
|
| + ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
|
| + GetTestEquivalenceClassAlpha()));
|
| +}
|
| +
|
| +TEST_F(AffiliationBackendTest, SimpleCacheExpiryWithoutPrefetches) {
|
| + ASSERT_NO_FATAL_FAILURE(GetAffiliationsAndExpectFetchAndThenResult(
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
|
| + GetTestEquivalenceClassAlpha()));
|
| +
|
| + AdvanceTime(GetCacheHardExpiryPeriod() - Epsilon());
|
| +
|
| + EXPECT_TRUE(IsCachedDataFreshForFacet(
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1)));
|
| + ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
|
| + GetTestEquivalenceClassAlpha()));
|
| +
|
| + AdvanceTime(Epsilon());
|
| +
|
| + // After the data becomes stale, the cached-only request should fail, but the
|
| + // subsequent on-demand request should fetch the data again and succeed.
|
| + EXPECT_FALSE(IsCachedDataFreshForFacet(
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1)));
|
| + GetAffiliationsAndExpectFailureWithoutFetch(
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1));
|
| +
|
| + ASSERT_NO_FATAL_FAILURE(GetAffiliationsAndExpectFetchAndThenResult(
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha2),
|
| + GetTestEquivalenceClassAlpha()));
|
| +
|
| + ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
|
| + GetTestEquivalenceClassAlpha()));
|
| +
|
| + EXPECT_EQ(0u, backend_facet_manager_count());
|
| +}
|
| +
|
| +// A Prefetch() request for a finite period. It should trigger an initial fetch
|
| +// and exactly one refetch, as the Prefetch() request expires exactly when the
|
| +// cached data obtained with the refetch expires.
|
| +TEST_F(AffiliationBackendTest,
|
| + PrefetchTriggersOneInitialFetchAndOneRefetchBeforeExpiring) {
|
| + ASSERT_NO_FATAL_FAILURE(PrefetchAndExpectFetch(
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
|
| + backend_task_runner()->Now() + GetCacheHardExpiryPeriod() +
|
| + GetCacheSoftExpiryPeriod()));
|
| +
|
| + AdvanceTime(GetCacheSoftExpiryPeriod() - Epsilon());
|
| +
|
| + EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
|
| + EXPECT_FALSE(IsCachedDataNearStaleForFacet(
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1)));
|
| +
|
| + AdvanceTime(Epsilon());
|
| +
|
| + EXPECT_TRUE(IsCachedDataNearStaleForFacet(
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1)));
|
| + ASSERT_NO_FATAL_FAILURE(
|
| + ExpectAndCompleteFetch(FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1)));
|
| +
|
| + AdvanceTime(GetCacheHardExpiryPeriod() - Epsilon());
|
| +
|
| + EXPECT_TRUE(IsCachedDataFreshForFacet(
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1)));
|
| + EXPECT_TRUE(IsCachedDataNearStaleForFacet(
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1)));
|
| + ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
|
| + GetTestEquivalenceClassAlpha()));
|
| +
|
| + AdvanceTime(Epsilon());
|
| +
|
| + // The data should be allowed to expire and the FacetManager discarded.
|
| + EXPECT_FALSE(IsCachedDataFreshForFacet(
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1)));
|
| + EXPECT_EQ(0u, backend_facet_manager_count());
|
| + EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
|
| + EXPECT_FALSE(backend_task_runner()->HasPendingTask());
|
| +
|
| + ASSERT_NO_FATAL_FAILURE(GetAffiliationsAndExpectFailureWithoutFetch(
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1)));
|
| + ASSERT_NO_FATAL_FAILURE(GetAffiliationsAndExpectFailureWithoutFetch(
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha2)));
|
| +
|
| + // However, a subsequent on-demand request should be able to trigger a fetch.
|
| + ASSERT_NO_FATAL_FAILURE(GetAffiliationsAndExpectFetchAndThenResult(
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
|
| + GetTestEquivalenceClassAlpha()));
|
| +}
|
| +
|
| +// Affiliation data for prefetched facets should be automatically refetched once
|
| +// every 23 hours, and GetAffiliations() requests regarding affiliated facets
|
| +// should be continuously served from cache.
|
| +TEST_F(AffiliationBackendTest, PrefetchTriggersPeriodicRefetch) {
|
| + ASSERT_NO_FATAL_FAILURE(PrefetchAndExpectFetch(
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1), base::Time::Max()));
|
| +
|
| + for (int cycle = 0; cycle < 3; ++cycle) {
|
| + SCOPED_TRACE(cycle);
|
| +
|
| + AdvanceTime(GetCacheSoftExpiryPeriod() - Epsilon());
|
| +
|
| + EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
|
| + EXPECT_TRUE(IsCachedDataFreshForFacet(
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1)));
|
| + EXPECT_FALSE(IsCachedDataNearStaleForFacet(
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1)));
|
| + ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
|
| + GetTestEquivalenceClassAlpha()));
|
| +
|
| + AdvanceTime(Epsilon());
|
| +
|
| + EXPECT_TRUE(IsCachedDataNearStaleForFacet(
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1)));
|
| + ASSERT_NO_FATAL_FAILURE(ExpectAndCompleteFetch(
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1)));
|
| + ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
|
| + GetTestEquivalenceClassAlpha()));
|
| + }
|
| +}
|
| +
|
| +TEST_F(AffiliationBackendTest,
|
| + PrefetchTriggersNoInitialFetchIfDataIsAlreadyFresh) {
|
| + ASSERT_NO_FATAL_FAILURE(GetAffiliationsAndExpectFetchAndThenResult(
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
|
| + GetTestEquivalenceClassAlpha()));
|
| +
|
| + EXPECT_FALSE(IsCachedDataNearStaleForFacet(
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1)));
|
| +
|
| + Prefetch(FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1), base::Time::Max());
|
| + EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
|
| + ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
|
| + GetTestEquivalenceClassAlpha()));
|
| +}
|
| +
|
| +TEST_F(AffiliationBackendTest, CancelPrefetch) {
|
| + ASSERT_NO_FATAL_FAILURE(PrefetchAndExpectFetch(
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1), base::Time::Max()));
|
| +
|
| + AdvanceTime(GetCacheSoftExpiryPeriod() - Epsilon());
|
| +
|
| + // Cancel the prefetch the last microsecond before a refetch would take place.
|
| + backend()->CancelPrefetch(FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
|
| + base::Time::Max());
|
| + EXPECT_EQ(0u, backend_facet_manager_count());
|
| + EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
|
| + EXPECT_TRUE(backend_task_runner()->HasPendingTask());
|
| +
|
| + AdvanceTime(GetCacheHardExpiryPeriod() - GetCacheSoftExpiryPeriod() +
|
| + Epsilon());
|
| +
|
| + // The data should be allowed to expire.
|
| + EXPECT_FALSE(backend_task_runner()->HasPendingTask());
|
| + EXPECT_TRUE(IsCachedDataNearStaleForFacet(
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1)));
|
| + ASSERT_NO_FATAL_FAILURE(GetAffiliationsAndExpectFailureWithoutFetch(
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1)));
|
| + ASSERT_NO_FATAL_FAILURE(GetAffiliationsAndExpectFailureWithoutFetch(
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha2)));
|
| +}
|
| +
|
| +TEST_F(AffiliationBackendTest, CancelDuplicatePrefetch) {
|
| + ASSERT_NO_FATAL_FAILURE(PrefetchAndExpectFetch(
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1), base::Time::Max()));
|
| + Prefetch(FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1), base::Time::Max());
|
| +
|
| + AdvanceTime(GetCacheSoftExpiryPeriod() - Epsilon());
|
| +
|
| + // Cancel the prefetch the last microsecond before a refetch would take place.
|
| + backend()->CancelPrefetch(FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
|
| + base::Time::Max());
|
| +
|
| + AdvanceTime(Epsilon());
|
| +
|
| + // However, there is a second Prefetch() request which should keep the data
|
| + // fresh.
|
| + EXPECT_EQ(1u, backend_facet_manager_count());
|
| + EXPECT_TRUE(IsCachedDataNearStaleForFacet(
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1)));
|
| + ASSERT_NO_FATAL_FAILURE(
|
| + ExpectAndCompleteFetch(FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1)));
|
| +
|
| + AdvanceTime(GetCacheHardExpiryPeriod() - GetCacheSoftExpiryPeriod());
|
| +
|
| + EXPECT_TRUE(IsCachedDataFreshForFacet(
|
| + FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1)));
|
| + ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
|
| + GetTestEquivalenceClassAlpha()));
|
| +}
|
| +
|
| +// Canceling a non-existing prefetch request for a non-prefetched facet.
|
| +TEST_F(AffiliationBackendTest, CancelingNonExistingPrefetchIsSilentlyIgnored) {
|
| + CancelPrefetch(FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
|
| + backend_task_runner()->Now() + base::TimeDelta::FromHours(24));
|
| + EXPECT_EQ(0u, backend_facet_manager_count());
|
| + EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
|
| + EXPECT_FALSE(backend_task_runner()->HasPendingTask());
|
| }
|
|
|
| TEST_F(AffiliationBackendTest, NothingExplodesWhenShutDownDuringFetch) {
|
|
|