Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(385)

Unified Diff: components/password_manager/core/browser/affiliation_backend_unittest.cc

Issue 947563002: Add prefetch support to AffiliationBackend. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Comment phrasing. Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 009cd9a3f1599b083b57a402e022d7669bbc2285..1227174dea6472b4d4bc2b42e8985acda24a4fe7 100644
--- a/components/password_manager/core/browser/affiliation_backend_unittest.cc
+++ b/components/password_manager/core/browser/affiliation_backend_unittest.cc
@@ -9,8 +9,10 @@
#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/fake_affiliation_api.h"
#include "components/password_manager/core/browser/mock_affiliation_consumer.h"
#include "net/url_request/url_request_context_getter.h"
@@ -55,7 +57,11 @@ 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 +73,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 +116,40 @@ 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) {
+ backend_->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 AdvanceTime(base::TimeDelta delta) { clock_->Advance(delta); }
+ void DestroyBackend() { backend_.reset(); }
+
+ void AdvanceTime(base::TimeDelta delta) {
+ backend_task_runner_->FastForwardBy(delta);
+ }
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 +163,6 @@ class AffiliationBackendTest : public testing::Test {
private:
// testing::Test:
void SetUp() override {
- clock_->Advance(base::TimeDelta::FromMicroseconds(1));
- backend_.reset(new AffiliationBackend(NULL, make_scoped_ptr(clock_)));
-
base::FilePath database_path;
ASSERT_TRUE(CreateTemporaryFile(&database_path));
backend_->Initialize(database_path);
@@ -142,7 +179,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 +191,53 @@ 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());
+ GetAffiliationsAndExpectFailureWithoutFetch(
+ FacetURI::FromCanonicalSpec(kTestFacetURIAlpha2));
+ EXPECT_EQ(0u, backend()->facet_manager_count());
+}
+
+TEST_F(AffiliationBackendTest, IndefinitePrefetchTriggersInitialFetch) {
+ ASSERT_NO_FATAL_FAILURE(PrefetchAndExpectFetch(
+ FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1), base::Time::Max()));
}
-// 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.
+TEST_F(AffiliationBackendTest, FinitePrefetchTriggersInitialFetch) {
+ ASSERT_NO_FATAL_FAILURE(PrefetchAndExpectFetch(
+ FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
+ backend_task_runner()->Now() + base::TimeDelta::FromHours(1)));
+}
+
+TEST_F(AffiliationBackendTest, ExpiredPrefetchTriggersNoInitialFetch) {
+ Prefetch(FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
+ backend_task_runner()->Now());
+ EXPECT_EQ(0u, backend()->facet_manager_count());
+ EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
+ // backend_task_runner()->RunUntilIdle();
+ EXPECT_FALSE(backend_task_runner()->HasPendingTask());
+}
+
+// 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 +247,10 @@ 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());
+
+ EXPECT_GE(1u, backend()->facet_manager_count());
}
TEST_F(AffiliationBackendTest, CacheServesSubsequentRequestForSameFacet) {
@@ -208,6 +265,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 +274,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()));
-
- AdvanceTime(base::TimeDelta::FromHours(24) -
- base::TimeDelta::FromMicroseconds(1));
+TEST_F(AffiliationBackendTest, CacheServesRequestsForPrefetchedFacets) {
+ ASSERT_NO_FATAL_FAILURE(PrefetchAndExpectFetch(
+ FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1), base::Time::Max()));
- // 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()));
}
@@ -289,6 +327,588 @@ 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_uri2, 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(base::TimeDelta::FromHours(24) -
+ base::TimeDelta::FromMicroseconds(1));
+
+ ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
+ 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.
+ 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());
+}
+
+TEST_F(AffiliationBackendTest, PrefetchTriggersInitialFetchWhenDataIsStale) {
+ ASSERT_NO_FATAL_FAILURE(GetAffiliationsAndExpectFetchAndThenResult(
+ FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
+ GetTestEquivalenceClassAlpha()));
+
+ AdvanceTime(base::TimeDelta::FromHours(24));
+
+ ASSERT_NO_FATAL_FAILURE(PrefetchAndExpectFetch(
+ FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1), base::Time::Max()));
+
+ AdvanceTime(base::TimeDelta::FromHours(21) -
+ base::TimeDelta::FromMicroseconds(1));
+
+ ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
+ GetTestEquivalenceClassAlpha()));
+}
+
+TEST_F(AffiliationBackendTest,
+ PrefetchTriggersInitialFetchWhenDataIsNearStale) {
+ ASSERT_NO_FATAL_FAILURE(GetAffiliationsAndExpectFetchAndThenResult(
+ FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
+ GetTestEquivalenceClassAlpha()));
+
+ AdvanceTime(base::TimeDelta::FromHours(21));
+
+ ASSERT_NO_FATAL_FAILURE(PrefetchAndExpectFetch(
+ FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1), base::Time::Max()));
+
+ AdvanceTime(base::TimeDelta::FromHours(21) -
+ base::TimeDelta::FromMicroseconds(1));
+
+ ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
+ GetTestEquivalenceClassAlpha()));
+}
+
+TEST_F(AffiliationBackendTest, PrefetchTriggersNoInitialFetchWhenDataIsFresh) {
+ ASSERT_NO_FATAL_FAILURE(GetAffiliationsAndExpectFetchAndThenResult(
+ FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
+ GetTestEquivalenceClassAlpha()));
+
+ AdvanceTime(base::TimeDelta::FromHours(21) -
+ base::TimeDelta::FromMicroseconds(1));
+
+ Prefetch(FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1), base::Time::Max());
+ EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
+
+ ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
+ GetTestEquivalenceClassAlpha()));
+
+ AdvanceTime(base::TimeDelta::FromMicroseconds(1));
+
+ // The first fetch should be the refetch once the data gets near-stale.
+ ASSERT_NO_FATAL_FAILURE(
+ ExpectAndCompleteFetch(FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1)));
+
+ AdvanceTime(base::TimeDelta::FromHours(21) -
+ base::TimeDelta::FromMicroseconds(1));
+
+ ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
+ GetTestEquivalenceClassAlpha()));
+}
+
+// Same as above, but with a prefetch for a finite duration.
+TEST_F(AffiliationBackendTest, PrefetchTriggersNoInitialFetchWhenDataIsFresh2) {
+ ASSERT_NO_FATAL_FAILURE(GetAffiliationsAndExpectFetchAndThenResult(
+ FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
+ GetTestEquivalenceClassAlpha()));
+
+ AdvanceTime(base::TimeDelta::FromHours(20));
+
+ Prefetch(FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
+ backend_task_runner()->Now() + base::TimeDelta::FromHours(5));
+ EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
+
+ AdvanceTime(base::TimeDelta::FromHours(1));
+
+ // The first fetch should be the refetch once the data gets near-stale.
+ ASSERT_NO_FATAL_FAILURE(
+ ExpectAndCompleteFetch(FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1)));
+
+ AdvanceTime(base::TimeDelta::FromHours(4) -
+ base::TimeDelta::FromMicroseconds(1));
+
+ ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
+ GetTestEquivalenceClassAlpha()));
+
+ AdvanceTime(base::TimeDelta::FromMicroseconds(1));
+
+ EXPECT_EQ(0u, backend()->facet_manager_count());
+ EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
+ EXPECT_FALSE(backend_task_runner()->HasPendingTask());
+}
+
+TEST_F(AffiliationBackendTest, NoRefetchIfPrefetchIsShortLived) {
+ ASSERT_NO_FATAL_FAILURE(PrefetchAndExpectFetch(
+ FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
+ backend_task_runner()->Now() + base::TimeDelta::FromHours(1)));
+
+ AdvanceTime(base::TimeDelta::FromHours(1) -
+ base::TimeDelta::FromMicroseconds(1));
+
+ EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
+ ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
+ GetTestEquivalenceClassAlpha()));
+
+ AdvanceTime(base::TimeDelta::FromMicroseconds(1));
+
+ EXPECT_EQ(0u, backend()->facet_manager_count());
+ EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
+ EXPECT_FALSE(backend_task_runner()->HasPendingTask());
+}
+
+TEST_F(AffiliationBackendTest, NoRefetchIfPrefetchExpiresWhenDataSoftExpires) {
+ ASSERT_NO_FATAL_FAILURE(PrefetchAndExpectFetch(
+ FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
+ backend_task_runner()->Now() + base::TimeDelta::FromHours(21)));
+
+ AdvanceTime(base::TimeDelta::FromHours(21) -
+ base::TimeDelta::FromMicroseconds(1));
+
+ EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
+ ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
+ GetTestEquivalenceClassAlpha()));
+
+ AdvanceTime(base::TimeDelta::FromMicroseconds(1));
+
+ EXPECT_EQ(0u, backend()->facet_manager_count());
+ EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
+ EXPECT_FALSE(backend_task_runner()->HasPendingTask());
+}
+
+TEST_F(AffiliationBackendTest,
+ NoFetchIfDataWasInitiallyFetchAndPrefetchExpiresWhenDataSoftExpires) {
+ ASSERT_NO_FATAL_FAILURE(GetAffiliationsAndExpectFetchAndThenResult(
+ FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
+ GetTestEquivalenceClassAlpha()));
+
+ AdvanceTime(base::TimeDelta::FromHours(20));
+
+ Prefetch(FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
+ backend_task_runner()->Now() + base::TimeDelta::FromHours(1));
+
+ AdvanceTime(base::TimeDelta::FromHours(1) -
+ base::TimeDelta::FromMicroseconds(1));
+
+ EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
+ ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
+ GetTestEquivalenceClassAlpha()));
+
+ AdvanceTime(base::TimeDelta::FromMicroseconds(1));
+
+ EXPECT_EQ(0u, backend()->facet_manager_count());
+ EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
+ EXPECT_FALSE(backend_task_runner()->HasPendingTask());
+}
+
+TEST_F(AffiliationBackendTest, NoRefetchIfPrefetchExpiresWhenDataHardExpires) {
+ ASSERT_NO_FATAL_FAILURE(PrefetchAndExpectFetch(
+ FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
+ backend_task_runner()->Now() + base::TimeDelta::FromHours(24)));
+
+ AdvanceTime(base::TimeDelta::FromHours(24) -
+ base::TimeDelta::FromMicroseconds(1));
+
+ EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
+ ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
+ GetTestEquivalenceClassAlpha()));
+
+ AdvanceTime(base::TimeDelta::FromMicroseconds(1));
+
+ 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)));
+}
+
+TEST_F(AffiliationBackendTest,
+ NoFetchIfDataWasInitiallyFreshAndPrefetchExpiresWhenDataHardExpires) {
+ ASSERT_NO_FATAL_FAILURE(GetAffiliationsAndExpectFetchAndThenResult(
+ FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
+ GetTestEquivalenceClassAlpha()));
+
+ AdvanceTime(base::TimeDelta::FromHours(20));
+
+ Prefetch(FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
+ backend_task_runner()->Now() + base::TimeDelta::FromHours(4));
+
+ AdvanceTime(base::TimeDelta::FromHours(4) -
+ base::TimeDelta::FromMicroseconds(1));
+
+ EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
+ ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
+ GetTestEquivalenceClassAlpha()));
+
+ AdvanceTime(base::TimeDelta::FromMicroseconds(1));
+
+ EXPECT_EQ(0u, backend()->facet_manager_count());
+ EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
+ EXPECT_FALSE(backend_task_runner()->HasPendingTask());
+}
+
+// A prefetch for a finite period of 21 + 24 hours should trigger exactly one
+// initial fetch and one refetch, as the cached data obtained with the refetch
+// expires exactly when the prefetch request.
+TEST_F(AffiliationBackendTest,
+ OneRefetchIfPrefetchExpiresWhenDataHardExpiresTheSecondTime) {
+ ASSERT_NO_FATAL_FAILURE(PrefetchAndExpectFetch(
+ FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
+ backend_task_runner()->Now() + base::TimeDelta::FromHours(21 + 24)));
+
+ AdvanceTime(base::TimeDelta::FromHours(21) -
+ base::TimeDelta::FromMicroseconds(1));
+
+ EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
+
+ AdvanceTime(base::TimeDelta::FromMicroseconds(1));
+
+ ASSERT_NO_FATAL_FAILURE(
+ ExpectAndCompleteFetch(FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1)));
+
+ AdvanceTime(base::TimeDelta::FromHours(24) -
+ base::TimeDelta::FromMicroseconds(1));
+
+ ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
+ GetTestEquivalenceClassAlpha()));
+
+ AdvanceTime(base::TimeDelta::FromMicroseconds(1));
+
+ EXPECT_EQ(0u, backend()->facet_manager_count());
+ EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
+ EXPECT_FALSE(backend_task_runner()->HasPendingTask());
+
+ // The data should be allowed to expire.
+ 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()));
+}
+
+// Same as above, but the prefetch period being 21 + 21 hours.
+TEST_F(AffiliationBackendTest,
+ OneRefetchIfPrefetchExpiresWhenDataSoftExpiresTheSecondTime) {
+ ASSERT_NO_FATAL_FAILURE(PrefetchAndExpectFetch(
+ FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
+ backend_task_runner()->Now() + base::TimeDelta::FromHours(21 + 21)));
+
+ AdvanceTime(base::TimeDelta::FromHours(21) -
+ base::TimeDelta::FromMicroseconds(1));
+
+ EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
+
+ AdvanceTime(base::TimeDelta::FromMicroseconds(1));
+
+ ASSERT_NO_FATAL_FAILURE(
+ ExpectAndCompleteFetch(FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1)));
+
+ AdvanceTime(base::TimeDelta::FromHours(21) -
+ base::TimeDelta::FromMicroseconds(1));
+
+ ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
+ GetTestEquivalenceClassAlpha()));
+
+ AdvanceTime(base::TimeDelta::FromMicroseconds(1));
+
+ EXPECT_EQ(0u, backend()->facet_manager_count());
+ EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
+ EXPECT_FALSE(backend_task_runner()->HasPendingTask());
+}
+
+TEST_F(AffiliationBackendTest, OneRefetchIfPrefetchExpiresShortlyAfterRefetch) {
+ ASSERT_NO_FATAL_FAILURE(PrefetchAndExpectFetch(
+ FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
+ backend_task_runner()->Now() + base::TimeDelta::FromHours(21 + 4)));
+
+ AdvanceTime(base::TimeDelta::FromHours(21) -
+ base::TimeDelta::FromMicroseconds(1));
+
+ EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
+
+ AdvanceTime(base::TimeDelta::FromMicroseconds(1));
+
+ ASSERT_NO_FATAL_FAILURE(
+ ExpectAndCompleteFetch(FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1)));
+
+ AdvanceTime(base::TimeDelta::FromHours(4) -
+ base::TimeDelta::FromMicroseconds(1));
+
+ ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
+ GetTestEquivalenceClassAlpha()));
+
+ AdvanceTime(base::TimeDelta::FromMicroseconds(1));
+
+ EXPECT_EQ(0u, backend()->facet_manager_count());
+ EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
+ EXPECT_FALSE(backend_task_runner()->HasPendingTask());
+}
+
+// Affiliation data for prefetches facets should be automatically refetched once
+// every 23 hours. GetAffiliations() requests regarding affiliated facets should
+// be continuously served from cache.
+TEST_F(AffiliationBackendTest, PeriodicRefetchAfterSoftCacheExpiry) {
+ ASSERT_NO_FATAL_FAILURE(PrefetchAndExpectFetch(
+ FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1), base::Time::Max()));
+
+ for (int cycle = 0; cycle < 3; ++cycle) {
+ SCOPED_TRACE(cycle);
+
+ AdvanceTime(base::TimeDelta::FromHours(21) -
+ base::TimeDelta::FromMicroseconds(1));
+
+ EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
+ ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
+ GetTestEquivalenceClassAlpha()));
+
+ AdvanceTime(base::TimeDelta::FromMicroseconds(1));
+
+ ASSERT_NO_FATAL_FAILURE(ExpectAndCompleteFetch(
+ FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1)));
+ ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
+ GetTestEquivalenceClassAlpha()));
+ }
+}
+
+TEST_F(AffiliationBackendTest, CancelPrefetch) {
+ ASSERT_NO_FATAL_FAILURE(PrefetchAndExpectFetch(
+ FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1), base::Time::Max()));
+
+ AdvanceTime(base::TimeDelta::FromHours(21) -
+ base::TimeDelta::FromMicroseconds(1));
+
+ // Cancel the prefetch the last microsecond before a refetch would take place.
+ backend()->CancelPrefetch(FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
+ base::Time::Max());
+
+ AdvanceTime(base::TimeDelta::FromHours(3) +
+ base::TimeDelta::FromMicroseconds(1));
+
+ 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)));
+}
+
+// Should multiple Prefetch() requests come in for the same facet with the same
+// |keep_fresh_until| thresholds, the prefetch should be considered active until
+// a matching number of CancelPrefetch() are called.
+TEST_F(AffiliationBackendTest, DuplicatePrefetches) {
+ FacetURI facet_uri(FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1));
+
+ ASSERT_NO_FATAL_FAILURE(PrefetchAndExpectFetch(facet_uri, base::Time::Max()));
+
+ Prefetch(facet_uri, base::Time::Max());
+ CancelPrefetch(facet_uri, base::Time::Max());
+ EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
+
+ AdvanceTime(base::TimeDelta::FromHours(21) -
+ base::TimeDelta::FromMicroseconds(1));
+
+ EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
+ ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
+ GetTestEquivalenceClassAlpha()));
+
+ AdvanceTime(base::TimeDelta::FromMicroseconds(1));
+
+ ASSERT_NO_FATAL_FAILURE(
+ ExpectAndCompleteFetch(FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1)));
+ ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
+ GetTestEquivalenceClassAlpha()));
+
+ CancelPrefetch(facet_uri, base::Time::Max());
+
+ EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
+ EXPECT_EQ(0u, backend()->facet_manager_count());
+
+ AdvanceTime(base::TimeDelta::FromHours(24));
+
+ EXPECT_FALSE(backend_task_runner()->HasPendingTask());
+ ASSERT_NO_FATAL_FAILURE(GetAffiliationsAndExpectFailureWithoutFetch(
+ FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1)));
+ ASSERT_NO_FATAL_FAILURE(GetAffiliationsAndExpectFailureWithoutFetch(
+ FacetURI::FromCanonicalSpec(kTestFacetURIAlpha2)));
+}
+
+TEST_F(AffiliationBackendTest, NestedPrefetches) {
+ ASSERT_NO_FATAL_FAILURE(PrefetchAndExpectFetch(
+ FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
+ backend_task_runner()->Now() + base::TimeDelta::FromHours(21 + 21)));
+
+ AdvanceTime(base::TimeDelta::FromHours(12));
+ Prefetch(FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
+ backend_task_runner()->Now() + base::TimeDelta::FromHours(6));
+ EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
+
+ AdvanceTime(base::TimeDelta::FromHours(9));
+
+ ASSERT_NO_FATAL_FAILURE(
+ ExpectAndCompleteFetch(FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1)));
+ ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
+ GetTestEquivalenceClassAlpha()));
+
+ AdvanceTime(base::TimeDelta::FromHours(21) -
+ base::TimeDelta::FromMicroseconds(1));
+
+ ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
+ GetTestEquivalenceClassAlpha()));
+
+ AdvanceTime(base::TimeDelta::FromMicroseconds(1));
+
+ EXPECT_EQ(0u, backend()->facet_manager_count());
+ EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
+ EXPECT_FALSE(backend_task_runner()->HasPendingTask());
+}
+
+TEST_F(AffiliationBackendTest, OverlappingPrefetches) {
+ ASSERT_NO_FATAL_FAILURE(PrefetchAndExpectFetch(
+ FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
+ backend_task_runner()->Now() + base::TimeDelta::FromHours(17)));
+
+ AdvanceTime(base::TimeDelta::FromHours(15));
+
+ Prefetch(FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
+ backend_task_runner()->Now() + base::TimeDelta::FromHours(24));
+ EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
+ ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
+ GetTestEquivalenceClassAlpha()));
+
+ AdvanceTime(base::TimeDelta::FromHours(3));
+
+ ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
+ GetTestEquivalenceClassAlpha()));
+
+ AdvanceTime(base::TimeDelta::FromHours(3));
+
+ ASSERT_NO_FATAL_FAILURE(
+ ExpectAndCompleteFetch(FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1)));
+ ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
+ GetTestEquivalenceClassAlpha()));
+
+ AdvanceTime(base::TimeDelta::FromHours(18) -
+ base::TimeDelta::FromMicroseconds(1));
+
+ ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
+ GetTestEquivalenceClassAlpha()));
+
+ AdvanceTime(base::TimeDelta::FromMicroseconds(1));
+
+ EXPECT_EQ(0u, backend()->facet_manager_count());
+ EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
+ EXPECT_FALSE(backend_task_runner()->HasPendingTask());
+}
+
+TEST_F(AffiliationBackendTest, OverlappingPrefetches2) {
+ FacetURI facet_uri(FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1));
+
+ ASSERT_NO_FATAL_FAILURE(PrefetchAndExpectFetch(facet_uri, base::Time::Max()));
+
+ AdvanceTime(base::TimeDelta::FromHours(12));
+
+ Prefetch(facet_uri,
+ backend_task_runner()->Now() + base::TimeDelta::FromHours(24));
+ CancelPrefetch(facet_uri, base::Time::Max());
+ EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
+ ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
+ GetTestEquivalenceClassAlpha()));
+
+ AdvanceTime(base::TimeDelta::FromHours(9));
+
+ ASSERT_NO_FATAL_FAILURE(
+ ExpectAndCompleteFetch(FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1)));
+ ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
+ GetTestEquivalenceClassAlpha()));
+
+ AdvanceTime(base::TimeDelta::FromHours(15) -
+ base::TimeDelta::FromMicroseconds(1));
+
+ ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
+ GetTestEquivalenceClassAlpha()));
+
+ AdvanceTime(base::TimeDelta::FromMicroseconds(1));
Mike West 2015/02/25 10:33:06 See the magic number discussion below, but there's
engedy 2015/03/10 11:01:00 I have completely reworked the unittests. I am no
+
+ EXPECT_EQ(0u, backend()->facet_manager_count());
+ EXPECT_FALSE(fake_affiliation_api()->HasPendingRequest());
+ EXPECT_FALSE(backend_task_runner()->HasPendingTask());
+}
+
+// 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));
+}
+
+// Canceling a non-existing prefetch request for an otherwise prefetched facet.
+TEST_F(AffiliationBackendTest, CancelingNonExistingPrefetchIsSilentlyIgnored2) {
+ ASSERT_NO_FATAL_FAILURE(PrefetchAndExpectFetch(
+ FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
+ backend_task_runner()->Now() + base::TimeDelta::FromHours(21 + 21)));
+
+ AdvanceTime(base::TimeDelta::FromHours(15));
+
+ // Non-existing prefetch for a prefetched facet.
+ CancelPrefetch(FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1),
+ backend_task_runner()->Now() + base::TimeDelta::FromHours(24));
+
+ AdvanceTime(base::TimeDelta::FromHours(9));
+
+ ASSERT_NO_FATAL_FAILURE(
+ ExpectAndCompleteFetch(FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1)));
+ ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
+ GetTestEquivalenceClassAlpha()));
+
+ AdvanceTime(base::TimeDelta::FromHours(21) -
Mike West 2015/02/25 10:33:06 Throughout: I don't like magic numbers. Why is 1 m
engedy 2015/03/10 11:01:00 Done.
+ base::TimeDelta::FromMicroseconds(1));
+
+ ASSERT_NO_FATAL_FAILURE(ExpectThatEquivalenceClassIsServedFromCache(
+ GetTestEquivalenceClassAlpha()));
}
TEST_F(AffiliationBackendTest, NothingExplodesWhenShutDownDuringFetch) {

Powered by Google App Engine
This is Rietveld 408576698