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) { |