Index: sync/notifier/sync_invalidation_listener_unittest.cc |
diff --git a/sync/notifier/sync_invalidation_listener_unittest.cc b/sync/notifier/sync_invalidation_listener_unittest.cc |
index a335060cbfed4e27bde760a14e0fcb55095634ea..39d7e24e07b8fe66b4ab1b5c1c4ee8a78f27b773 100644 |
--- a/sync/notifier/sync_invalidation_listener_unittest.cc |
+++ b/sync/notifier/sync_invalidation_listener_unittest.cc |
@@ -8,9 +8,11 @@ |
#include "base/compiler_specific.h" |
#include "base/message_loop.h" |
+#include "base/time.h" |
#include "google/cacheinvalidation/include/invalidation-client.h" |
#include "google/cacheinvalidation/include/types.h" |
#include "jingle/notifier/listener/fake_push_client.h" |
+#include "sync/internal_api/public/base/invalidation_test_util.h" |
#include "sync/internal_api/public/util/weak_handle.h" |
#include "sync/notifier/fake_invalidation_state_tracker.h" |
#include "sync/notifier/invalidation_util.h" |
@@ -19,6 +21,13 @@ |
namespace syncer { |
+// TODO(dcheng): Duplicated from invalidator_storage_unittest.cc. |
+bool operator==(const LocalState& lhs, const LocalState& rhs) { |
+ return lhs.version == rhs.version && |
+ lhs.expected.Equals(rhs.expected) && |
+ rhs.current.Equals(rhs.current); |
+} |
+ |
namespace { |
using invalidation::AckHandle; |
@@ -131,7 +140,9 @@ class FakeInvalidationClient : public invalidation::InvalidationClient { |
// and state. |
class FakeDelegate : public SyncInvalidationListener::Delegate { |
public: |
- FakeDelegate() : state_(TRANSIENT_INVALIDATION_ERROR) {} |
+ explicit FakeDelegate(SyncInvalidationListener* listener) |
+ : listener_(listener), |
+ state_(TRANSIENT_INVALIDATION_ERROR) {} |
virtual ~FakeDelegate() {} |
int GetInvalidationCount(const ObjectId& id) const { |
@@ -148,6 +159,10 @@ class FakeDelegate : public SyncInvalidationListener::Delegate { |
return state_; |
} |
+ void Acknowledge(const ObjectId& id) { |
+ listener_->Acknowledge(id, invalidations_[id].ack_handle); |
+ } |
+ |
// SyncInvalidationListener::Delegate implementation. |
virtual void OnInvalidate( |
@@ -167,6 +182,7 @@ class FakeDelegate : public SyncInvalidationListener::Delegate { |
typedef std::map<ObjectId, int, ObjectIdLessThan> ObjectIdCountMap; |
ObjectIdCountMap invalidation_counts_; |
ObjectIdInvalidationMap invalidations_; |
+ SyncInvalidationListener* listener_; |
InvalidatorState state_; |
}; |
@@ -190,14 +206,15 @@ class SyncInvalidationListenerTest : public testing::Test { |
kAppsId_(kChromeSyncSourceId, "APP"), |
fake_push_client_(new notifier::FakePushClient()), |
fake_invalidation_client_(NULL), |
- client_(scoped_ptr<notifier::PushClient>(fake_push_client_)) {} |
+ listener_(scoped_ptr<notifier::PushClient>(fake_push_client_)), |
+ fake_delegate_(&listener_) {} |
virtual void SetUp() { |
StartClient(); |
registered_ids_.insert(kBookmarksId_); |
registered_ids_.insert(kPreferencesId_); |
- client_.UpdateRegisteredIds(registered_ids_); |
+ listener_.UpdateRegisteredIds(registered_ids_); |
} |
virtual void TearDown() { |
@@ -245,31 +262,37 @@ class SyncInvalidationListenerTest : public testing::Test { |
} |
const AckHandle ack_handle("fakedata"); |
fake_invalidation_client_->ClearAckedHandles(); |
- client_.Invalidate(fake_invalidation_client_, inv, ack_handle); |
- EXPECT_TRUE(fake_invalidation_client_->IsAckedHandle(ack_handle)); |
- // Pump message loop to trigger |
- // InvalidationStateTracker::SetMaxVersion(). |
+ listener_.Invalidate(fake_invalidation_client_, inv, ack_handle); |
+ // Pump message loop to trigger InvalidationStateTracker::SetMaxVersion() |
+ // and callback from InvalidationStateTracker::GenerateAckHandles(). |
message_loop_.RunAllPending(); |
+ EXPECT_TRUE(fake_invalidation_client_->IsAckedHandle(ack_handle)); |
} |
// |payload| can be NULL, but not |type_name|. |
void FireInvalidateUnknownVersion(const ObjectId& object_id) { |
const AckHandle ack_handle("fakedata_unknown"); |
fake_invalidation_client_->ClearAckedHandles(); |
- client_.InvalidateUnknownVersion(fake_invalidation_client_, object_id, |
+ listener_.InvalidateUnknownVersion(fake_invalidation_client_, object_id, |
ack_handle); |
+ // Pump message loop to trigger callback from |
+ // InvalidationStateTracker::GenerateAckHandles(). |
+ message_loop_.RunAllPending(); |
EXPECT_TRUE(fake_invalidation_client_->IsAckedHandle(ack_handle)); |
} |
void FireInvalidateAll() { |
const AckHandle ack_handle("fakedata_all"); |
fake_invalidation_client_->ClearAckedHandles(); |
- client_.InvalidateAll(fake_invalidation_client_, ack_handle); |
+ listener_.InvalidateAll(fake_invalidation_client_, ack_handle); |
+ // Pump message loop to trigger callback from |
+ // InvalidationStateTracker::GenerateAckHandles(). |
+ message_loop_.RunAllPending(); |
EXPECT_TRUE(fake_invalidation_client_->IsAckedHandle(ack_handle)); |
} |
void WriteState(const std::string& new_state) { |
- client_.WriteState(new_state); |
+ listener_.WriteState(new_state); |
// Pump message loop to trigger |
// InvalidationStateTracker::WriteState(). |
message_loop_.RunAllPending(); |
@@ -283,6 +306,29 @@ class SyncInvalidationListenerTest : public testing::Test { |
fake_push_client_->DisableNotifications(reason); |
} |
+ void VerifyUnacknowledged(const ObjectId& object_id) { |
+ InvalidationStateMap state_map = fake_tracker_.GetStateMap(); |
+ EXPECT_THAT(state_map[object_id].current, |
+ Not(Eq(state_map[object_id].expected))); |
+ EXPECT_EQ(listener_.GetStateMapForTest(), state_map); |
+ } |
+ |
+ void VerifyAcknowledged(const ObjectId& object_id) { |
+ InvalidationStateMap state_map = fake_tracker_.GetStateMap(); |
+ EXPECT_THAT(state_map[object_id].current, |
+ Eq(state_map[object_id].expected)); |
+ EXPECT_EQ(listener_.GetStateMapForTest(), state_map); |
+ } |
+ |
+ void AcknowledgeAndVerify(const ObjectId& object_id) { |
+ VerifyUnacknowledged(object_id); |
+ fake_delegate_.Acknowledge(object_id); |
+ // Pump message loop to trigger |
+ // InvalidationStateTracker::Acknowledge(). |
+ message_loop_.RunAllPending(); |
+ VerifyAcknowledged(object_id); |
+ } |
+ |
const ObjectId kBookmarksId_; |
const ObjectId kPreferencesId_; |
const ObjectId kExtensionsId_; |
@@ -293,37 +339,40 @@ class SyncInvalidationListenerTest : public testing::Test { |
private: |
void StartClient() { |
fake_invalidation_client_ = NULL; |
- client_.Start(base::Bind(&CreateFakeInvalidationClient, |
- &fake_invalidation_client_), |
- kClientId, kClientInfo, kState, |
- InvalidationVersionMap(), |
- MakeWeakHandle(fake_tracker_.AsWeakPtr()), |
- &fake_delegate_); |
+ listener_.Start(base::Bind(&CreateFakeInvalidationClient, |
+ &fake_invalidation_client_), |
+ kClientId, kClientInfo, kState, |
+ fake_tracker_.GetStateMap(), |
+ MakeWeakHandle(fake_tracker_.AsWeakPtr()), |
+ &fake_delegate_); |
DCHECK(fake_invalidation_client_); |
} |
void StopClient() { |
- // client_.StopForTest() stops the invalidation scheduler, which |
+ // listener_.StopForTest() stops the invalidation scheduler, which |
// deletes any pending tasks without running them. Some tasks |
// "run and delete" another task, so they must be run in order to |
- // avoid leaking the inner task. client_.StopForTest() does not |
+ // avoid leaking the inner task. listener_.StopForTest() does not |
// schedule any tasks, so it's both necessary and sufficient to |
// drain the task queue before calling it. |
message_loop_.RunAllPending(); |
fake_invalidation_client_ = NULL; |
- client_.StopForTest(); |
+ listener_.StopForTest(); |
} |
MessageLoop message_loop_; |
- FakeDelegate fake_delegate_; |
+ private: |
FakeInvalidationStateTracker fake_tracker_; |
notifier::FakePushClient* const fake_push_client_; |
protected: |
// Tests need to access these directly. |
FakeInvalidationClient* fake_invalidation_client_; |
- SyncInvalidationListener client_; |
+ SyncInvalidationListener listener_; |
+ |
+ private: |
+ FakeDelegate fake_delegate_; |
}; |
// Write a new state to the client. It should propagate to the |
@@ -346,6 +395,7 @@ TEST_F(SyncInvalidationListenerTest, InvalidateNoPayload) { |
EXPECT_EQ(1, GetInvalidationCount(id)); |
EXPECT_EQ("", GetPayload(id)); |
EXPECT_EQ(kVersion1, GetMaxVersion(id)); |
+ AcknowledgeAndVerify(id); |
} |
// Fire an invalidation with an empty payload. It should be |
@@ -359,6 +409,7 @@ TEST_F(SyncInvalidationListenerTest, InvalidateEmptyPayload) { |
EXPECT_EQ(1, GetInvalidationCount(id)); |
EXPECT_EQ("", GetPayload(id)); |
EXPECT_EQ(kVersion1, GetMaxVersion(id)); |
+ AcknowledgeAndVerify(id); |
} |
// Fire an invalidation with a payload. It should be processed, and |
@@ -371,11 +422,12 @@ TEST_F(SyncInvalidationListenerTest, InvalidateWithPayload) { |
EXPECT_EQ(1, GetInvalidationCount(id)); |
EXPECT_EQ(kPayload1, GetPayload(id)); |
EXPECT_EQ(kVersion1, GetMaxVersion(id)); |
+ AcknowledgeAndVerify(id); |
} |
-// Fire an invalidation with a payload. It should still be processed, |
-// and both the payload and the version should be updated. |
-TEST_F(SyncInvalidationListenerTest, InvalidateUnregistered) { |
+// Fire an invalidation for an unregistered object ID with a payload. It should |
+// still be processed, and both the payload and the version should be updated. |
+TEST_F(SyncInvalidationListenerTest, InvalidateUnregisteredWithPayload) { |
const ObjectId kUnregisteredId( |
kChromeSyncSourceId, "unregistered"); |
const ObjectId& id = kUnregisteredId; |
@@ -384,11 +436,12 @@ TEST_F(SyncInvalidationListenerTest, InvalidateUnregistered) { |
EXPECT_EQ("", GetPayload(id)); |
EXPECT_EQ(kMinVersion, GetMaxVersion(id)); |
- FireInvalidate(id, kVersion1, NULL); |
+ FireInvalidate(id, kVersion1, "unregistered payload"); |
EXPECT_EQ(1, GetInvalidationCount(id)); |
- EXPECT_EQ("", GetPayload(id)); |
+ EXPECT_EQ("unregistered payload", GetPayload(id)); |
EXPECT_EQ(kVersion1, GetMaxVersion(id)); |
+ AcknowledgeAndVerify(id); |
} |
// Fire an invalidation, then fire another one with a lower version. |
@@ -402,12 +455,14 @@ TEST_F(SyncInvalidationListenerTest, InvalidateVersion) { |
EXPECT_EQ(1, GetInvalidationCount(id)); |
EXPECT_EQ(kPayload2, GetPayload(id)); |
EXPECT_EQ(kVersion2, GetMaxVersion(id)); |
+ AcknowledgeAndVerify(id); |
FireInvalidate(id, kVersion1, kPayload1); |
EXPECT_EQ(1, GetInvalidationCount(id)); |
EXPECT_EQ(kPayload2, GetPayload(id)); |
EXPECT_EQ(kVersion2, GetMaxVersion(id)); |
+ VerifyAcknowledged(id); |
} |
// Fire an invalidation with an unknown version twice. It shouldn't |
@@ -421,12 +476,14 @@ TEST_F(SyncInvalidationListenerTest, InvalidateUnknownVersion) { |
EXPECT_EQ(1, GetInvalidationCount(id)); |
EXPECT_EQ("", GetPayload(id)); |
EXPECT_EQ(kMinVersion, GetMaxVersion(id)); |
+ AcknowledgeAndVerify(id); |
FireInvalidateUnknownVersion(id); |
EXPECT_EQ(2, GetInvalidationCount(id)); |
EXPECT_EQ("", GetPayload(id)); |
EXPECT_EQ(kMinVersion, GetMaxVersion(id)); |
+ AcknowledgeAndVerify(id); |
} |
// Fire an invalidation for all enabled IDs. It shouldn't update the |
@@ -439,6 +496,7 @@ TEST_F(SyncInvalidationListenerTest, InvalidateAll) { |
EXPECT_EQ(1, GetInvalidationCount(*it)); |
EXPECT_EQ("", GetPayload(*it)); |
EXPECT_EQ(kMinVersion, GetMaxVersion(*it)); |
+ AcknowledgeAndVerify(*it); |
} |
} |
@@ -449,12 +507,14 @@ TEST_F(SyncInvalidationListenerTest, InvalidateMultipleIds) { |
EXPECT_EQ(1, GetInvalidationCount(kBookmarksId_)); |
EXPECT_EQ("", GetPayload(kBookmarksId_)); |
EXPECT_EQ(3, GetMaxVersion(kBookmarksId_)); |
+ AcknowledgeAndVerify(kBookmarksId_); |
FireInvalidate(kExtensionsId_, 2, NULL); |
EXPECT_EQ(1, GetInvalidationCount(kExtensionsId_)); |
EXPECT_EQ("", GetPayload(kExtensionsId_)); |
EXPECT_EQ(2, GetMaxVersion(kExtensionsId_)); |
+ AcknowledgeAndVerify(kExtensionsId_); |
// Invalidations with lower version numbers should be ignored. |
@@ -477,14 +537,19 @@ TEST_F(SyncInvalidationListenerTest, InvalidateMultipleIds) { |
EXPECT_EQ(2, GetInvalidationCount(kBookmarksId_)); |
EXPECT_EQ("", GetPayload(kBookmarksId_)); |
EXPECT_EQ(3, GetMaxVersion(kBookmarksId_)); |
+ AcknowledgeAndVerify(kBookmarksId_); |
EXPECT_EQ(1, GetInvalidationCount(kPreferencesId_)); |
EXPECT_EQ("", GetPayload(kPreferencesId_)); |
EXPECT_EQ(kMinVersion, GetMaxVersion(kPreferencesId_)); |
+ AcknowledgeAndVerify(kPreferencesId_); |
+ // Note that kExtensionsId_ is not registered, so InvalidateAll() shouldn't |
+ // affect it. |
EXPECT_EQ(1, GetInvalidationCount(kExtensionsId_)); |
EXPECT_EQ("", GetPayload(kExtensionsId_)); |
EXPECT_EQ(2, GetMaxVersion(kExtensionsId_)); |
+ VerifyAcknowledged(kExtensionsId_); |
// Invalidations with higher version numbers should be processed. |
@@ -492,16 +557,252 @@ TEST_F(SyncInvalidationListenerTest, InvalidateMultipleIds) { |
EXPECT_EQ(2, GetInvalidationCount(kPreferencesId_)); |
EXPECT_EQ("", GetPayload(kPreferencesId_)); |
EXPECT_EQ(5, GetMaxVersion(kPreferencesId_)); |
+ AcknowledgeAndVerify(kPreferencesId_); |
FireInvalidate(kExtensionsId_, 3, NULL); |
EXPECT_EQ(2, GetInvalidationCount(kExtensionsId_)); |
EXPECT_EQ("", GetPayload(kExtensionsId_)); |
EXPECT_EQ(3, GetMaxVersion(kExtensionsId_)); |
+ AcknowledgeAndVerify(kExtensionsId_); |
FireInvalidate(kBookmarksId_, 4, NULL); |
EXPECT_EQ(3, GetInvalidationCount(kBookmarksId_)); |
EXPECT_EQ("", GetPayload(kBookmarksId_)); |
EXPECT_EQ(4, GetMaxVersion(kBookmarksId_)); |
+ AcknowledgeAndVerify(kBookmarksId_); |
+} |
+ |
+// Various tests for the local invalidation feature. |
+// Test that timeout behavior for one object ID. The timeout should increase |
+// exponentially until it hits the cap. If a new invalidation with a higher |
+// version is received, it should reset the timeout period as well. |
+TEST_F(SyncInvalidationListenerTest, InvalidateOneTimeout) { |
+ // The timeout should increase exponentially while unacknowledged. |
+ base::TimeTicks next_invalidation_time; |
+ base::TimeTicks start = base::TimeTicks::Now(); |
+ FireInvalidate(kBookmarksId_, 3, NULL); |
+ EXPECT_EQ(1, GetInvalidationCount(kBookmarksId_)); |
+ EXPECT_EQ("", GetPayload(kBookmarksId_)); |
+ EXPECT_EQ(3, GetMaxVersion(kBookmarksId_)); |
+ |
+ // First timeout. |
+ VerifyUnacknowledged(kBookmarksId_); |
+ EXPECT_EQ(base::TimeDelta::FromSeconds(60), |
+ listener_.GetCurrentDelayForTest()); |
+ EXPECT_TRUE(listener_.TriggerNextTimeoutForTest(&next_invalidation_time)); |
+ EXPECT_EQ(2, GetInvalidationCount(kBookmarksId_)); |
+ EXPECT_NEAR(60, (next_invalidation_time - start).InSecondsF(), 0.5); |
+ |
+ // Second timeout. |
+ start = base::TimeTicks::Now(); |
+ VerifyUnacknowledged(kBookmarksId_); |
+ EXPECT_EQ(base::TimeDelta::FromSeconds(120), |
+ listener_.GetCurrentDelayForTest()); |
+ EXPECT_TRUE(listener_.TriggerNextTimeoutForTest(&next_invalidation_time)); |
+ EXPECT_EQ(3, GetInvalidationCount(kBookmarksId_)); |
+ EXPECT_NEAR(120, (next_invalidation_time - start).InSecondsF(), 0.5); |
+ |
+ // Third timeout. |
+ start = base::TimeTicks::Now(); |
+ VerifyUnacknowledged(kBookmarksId_); |
+ EXPECT_EQ(base::TimeDelta::FromSeconds(240), |
+ listener_.GetCurrentDelayForTest()); |
+ EXPECT_TRUE(listener_.TriggerNextTimeoutForTest(&next_invalidation_time)); |
+ EXPECT_EQ(4, GetInvalidationCount(kBookmarksId_)); |
+ EXPECT_NEAR(240, (next_invalidation_time - start).InSecondsF(), 0.5); |
+ start = next_invalidation_time; |
+ |
+ // Fourth timeout. |
+ start = base::TimeTicks::Now(); |
+ VerifyUnacknowledged(kBookmarksId_); |
+ EXPECT_EQ(base::TimeDelta::FromSeconds(480), |
+ listener_.GetCurrentDelayForTest()); |
+ EXPECT_TRUE(listener_.TriggerNextTimeoutForTest(&next_invalidation_time)); |
+ EXPECT_EQ(5, GetInvalidationCount(kBookmarksId_)); |
+ EXPECT_NEAR(480, (next_invalidation_time - start).InSecondsF(), 0.5); |
+ |
+ // Until it is capped at 600 seconds. |
+ start = base::TimeTicks::Now(); |
+ VerifyUnacknowledged(kBookmarksId_); |
+ EXPECT_EQ(base::TimeDelta::FromSeconds(600), |
+ listener_.GetCurrentDelayForTest()); |
+ EXPECT_TRUE(listener_.TriggerNextTimeoutForTest(&next_invalidation_time)); |
+ EXPECT_EQ(6, GetInvalidationCount(kBookmarksId_)); |
+ EXPECT_NEAR(600, (next_invalidation_time - start).InSecondsF(), 0.5); |
+ |
+ // A new incoming invalidation with the same version should not reset the |
+ // timer. |
+ start = base::TimeTicks::Now(); |
+ FireInvalidate(kBookmarksId_, 3, NULL); |
+ EXPECT_EQ(6, GetInvalidationCount(kBookmarksId_)); |
+ EXPECT_EQ("", GetPayload(kBookmarksId_)); |
+ EXPECT_EQ(3, GetMaxVersion(kBookmarksId_)); |
+ |
+ VerifyUnacknowledged(kBookmarksId_); |
+ EXPECT_EQ(base::TimeDelta::FromSeconds(600), |
+ listener_.GetCurrentDelayForTest()); |
+ EXPECT_TRUE(listener_.TriggerNextTimeoutForTest(&next_invalidation_time)); |
+ EXPECT_EQ(7, GetInvalidationCount(kBookmarksId_)); |
+ EXPECT_NEAR(600, (next_invalidation_time - start).InSecondsF(), 0.5); |
+ |
+ // But one with a higher version should. |
+ start = base::TimeTicks::Now(); |
+ FireInvalidate(kBookmarksId_, 4, NULL); |
+ EXPECT_EQ(8, GetInvalidationCount(kBookmarksId_)); |
+ EXPECT_EQ("", GetPayload(kBookmarksId_)); |
+ EXPECT_EQ(4, GetMaxVersion(kBookmarksId_)); |
+ |
+ VerifyUnacknowledged(kBookmarksId_); |
+ EXPECT_EQ(base::TimeDelta::FromSeconds(60), |
+ listener_.GetCurrentDelayForTest()); |
+ EXPECT_TRUE(listener_.TriggerNextTimeoutForTest(&next_invalidation_time)); |
+ EXPECT_NEAR(60, (next_invalidation_time - start).InSecondsF(), 0.5); |
+ AcknowledgeAndVerify(kBookmarksId_); |
+ |
+ // The timer queue should be empty at this point. |
+ EXPECT_FALSE(listener_.TriggerNextTimeoutForTest(&next_invalidation_time)); |
+} |
+ |
+// Test that the timer runs until all pending invalidations are acknowledged. |
+TEST_F(SyncInvalidationListenerTest, InvalidateAllTimeout) { |
+ base::TimeTicks next_invalidation_time; |
+ base::TimeTicks start = base::TimeTicks::Now(); |
+ FireInvalidateAll(); |
+ |
+ EXPECT_EQ(1, GetInvalidationCount(kBookmarksId_)); |
+ EXPECT_EQ("", GetPayload(kBookmarksId_)); |
+ EXPECT_EQ(kMinVersion, GetMaxVersion(kBookmarksId_)); |
+ |
+ EXPECT_EQ(1, GetInvalidationCount(kPreferencesId_)); |
+ EXPECT_EQ("", GetPayload(kPreferencesId_)); |
+ EXPECT_EQ(kMinVersion, GetMaxVersion(kPreferencesId_)); |
+ |
+ // Trigger one timeout where neither is acknowledged. |
+ VerifyUnacknowledged(kBookmarksId_); |
+ VerifyUnacknowledged(kPreferencesId_); |
+ EXPECT_EQ(base::TimeDelta::FromSeconds(60), |
+ listener_.GetCurrentDelayForTest()); |
+ EXPECT_TRUE(listener_.TriggerNextTimeoutForTest(&next_invalidation_time)); |
+ EXPECT_EQ(2, GetInvalidationCount(kBookmarksId_)); |
+ EXPECT_EQ(2, GetInvalidationCount(kPreferencesId_)); |
+ EXPECT_NEAR(60, (next_invalidation_time - start).InSecondsF(), 0.5); |
+ |
+ AcknowledgeAndVerify(kBookmarksId_); |
+ |
+ // Trigger another timeout. Now we should only receive one invalidation. |
+ start = base::TimeTicks::Now(); |
+ VerifyAcknowledged(kBookmarksId_); |
+ VerifyUnacknowledged(kPreferencesId_); |
+ EXPECT_EQ(base::TimeDelta::FromSeconds(120), |
+ listener_.GetCurrentDelayForTest()); |
+ EXPECT_TRUE(listener_.TriggerNextTimeoutForTest(&next_invalidation_time)); |
+ EXPECT_EQ(2, GetInvalidationCount(kBookmarksId_)); |
+ EXPECT_EQ(3, GetInvalidationCount(kPreferencesId_)); |
+ EXPECT_NEAR(120, (next_invalidation_time - start).InSecondsF(), 0.5); |
+ |
+ AcknowledgeAndVerify(kPreferencesId_); |
+ // The timer queue should be empty at this point. |
+ EXPECT_FALSE(listener_.TriggerNextTimeoutForTest(&next_invalidation_time)); |
+} |
+ |
+// Test that the timer is appropriately updated if we schedule a timeout |
+// that occurs before the currently queued timeouts. |
+TEST_F(SyncInvalidationListenerTest, InvalidateShortenTimeout) { |
+ // The timeout should increase exponentially while unacknowledged. |
+ base::TimeTicks next_invalidation_time; |
+ base::TimeTicks start = base::TimeTicks::Now(); |
+ FireInvalidate(kBookmarksId_, 3, NULL); |
+ EXPECT_EQ(1, GetInvalidationCount(kBookmarksId_)); |
+ EXPECT_EQ("", GetPayload(kBookmarksId_)); |
+ EXPECT_EQ(3, GetMaxVersion(kBookmarksId_)); |
+ |
+ VerifyUnacknowledged(kBookmarksId_); |
+ EXPECT_EQ(base::TimeDelta::FromSeconds(60), |
+ listener_.GetCurrentDelayForTest()); |
+ EXPECT_TRUE(listener_.TriggerNextTimeoutForTest(&next_invalidation_time)); |
+ EXPECT_EQ(2, GetInvalidationCount(kBookmarksId_)); |
+ EXPECT_NEAR(60, (next_invalidation_time - start).InSecondsF(), 0.5); |
+ |
+ // The timeout should now be 120 seconds... |
+ EXPECT_EQ(base::TimeDelta::FromSeconds(120), |
+ listener_.GetCurrentDelayForTest()); |
+ // But a new invalidation should reset the timeout to 60 seconds. |
+ start = base::TimeTicks::Now(); |
+ FireInvalidate(kExtensionsId_, 2, NULL); |
+ EXPECT_EQ(1, GetInvalidationCount(kExtensionsId_)); |
+ EXPECT_EQ("", GetPayload(kExtensionsId_)); |
+ EXPECT_EQ(2, GetMaxVersion(kExtensionsId_)); |
+ |
+ EXPECT_EQ(base::TimeDelta::FromSeconds(60), |
+ listener_.GetCurrentDelayForTest()); |
+ EXPECT_TRUE(listener_.TriggerNextTimeoutForTest(&next_invalidation_time)); |
+ EXPECT_EQ(2, GetInvalidationCount(kExtensionsId_)); |
+ EXPECT_NEAR(60, (next_invalidation_time - start).InSecondsF(), 0.5); |
+ |
+ // The next timeout should trigger another invalidation for |kBookmarksId_|. |
+ // Note that we don't check the exact times here, as they will be incorrect in |
+ // tests, due to the fact that we pretend that the next timeout has elapsed, |
+ // but then we update the timers based on base::TimeTicks::Now(). |
+ EXPECT_TRUE(listener_.TriggerNextTimeoutForTest(&next_invalidation_time)); |
+ EXPECT_EQ(3, GetInvalidationCount(kBookmarksId_)); |
+ EXPECT_EQ(2, GetInvalidationCount(kExtensionsId_)); |
+ |
+ // Foollowed by |kExtensionsId_| again. |
+ EXPECT_TRUE(listener_.TriggerNextTimeoutForTest(&next_invalidation_time)); |
+ EXPECT_EQ(3, GetInvalidationCount(kBookmarksId_)); |
+ EXPECT_EQ(3, GetInvalidationCount(kExtensionsId_)); |
+ |
+ AcknowledgeAndVerify(kBookmarksId_); |
+ AcknowledgeAndVerify(kExtensionsId_); |
+ |
+ // The timer queue should be empty at this point. |
+ EXPECT_FALSE(listener_.TriggerNextTimeoutForTest(&next_invalidation_time)); |
+} |
+ |
+// Test that an unacknowledged invalidation triggers reminders if the listener |
+// is restarted. |
+TEST_F(SyncInvalidationListenerTest, InvalidationTimeoutRestart) { |
+ base::TimeTicks next_invalidation_time; |
+ base::TimeTicks start = base::TimeTicks::Now(); |
+ FireInvalidate(kBookmarksId_, 3, NULL); |
+ EXPECT_EQ(1, GetInvalidationCount(kBookmarksId_)); |
+ EXPECT_EQ("", GetPayload(kBookmarksId_)); |
+ EXPECT_EQ(3, GetMaxVersion(kBookmarksId_)); |
+ |
+ VerifyUnacknowledged(kBookmarksId_); |
+ EXPECT_EQ(base::TimeDelta::FromSeconds(60), |
+ listener_.GetCurrentDelayForTest()); |
+ EXPECT_TRUE(listener_.TriggerNextTimeoutForTest(&next_invalidation_time)); |
+ EXPECT_EQ(2, GetInvalidationCount(kBookmarksId_)); |
+ EXPECT_NEAR(60, (next_invalidation_time - start).InSecondsF(), 0.5); |
+ |
+ EXPECT_EQ(base::TimeDelta::FromSeconds(120), |
+ listener_.GetCurrentDelayForTest()); |
+ |
+ // Restarting the client should reset the retry count and the timeout period. |
+ RestartClient(); |
+ // The bookmark invalidation state should not have changed. |
+ EXPECT_EQ(2, GetInvalidationCount(kBookmarksId_)); |
+ EXPECT_EQ("", GetPayload(kBookmarksId_)); |
+ EXPECT_EQ(3, GetMaxVersion(kBookmarksId_)); |
+ |
+ // Now trigger a reminder. |
+ VerifyUnacknowledged(kBookmarksId_); |
+ EXPECT_EQ(base::TimeDelta::FromSeconds(60), |
+ listener_.GetCurrentDelayForTest()); |
+ EXPECT_TRUE(listener_.TriggerNextTimeoutForTest(&next_invalidation_time)); |
+ EXPECT_EQ(3, GetInvalidationCount(kBookmarksId_)); |
+ EXPECT_NEAR(60, (next_invalidation_time - start).InSecondsF(), 0.5); |
+ |
+ AcknowledgeAndVerify(kBookmarksId_); |
+ |
+ // The timer queue should be empty at this point. |
+ EXPECT_FALSE(listener_.TriggerNextTimeoutForTest(&next_invalidation_time)); |
+ |
+ // A restart with no unacknowledged invalidations should not have any running |
+ // timers. |
+ RestartClient(); |
+ EXPECT_FALSE(listener_.TriggerNextTimeoutForTest(&next_invalidation_time)); |
} |
// Registration tests. |
@@ -516,7 +817,7 @@ TEST_F(SyncInvalidationListenerTest, RegisterEnableReady) { |
EXPECT_TRUE(GetRegisteredIds().empty()); |
- client_.Ready(fake_invalidation_client_); |
+ listener_.Ready(fake_invalidation_client_); |
EXPECT_EQ(registered_ids_, GetRegisteredIds()); |
} |
@@ -527,7 +828,7 @@ TEST_F(SyncInvalidationListenerTest, RegisterEnableReady) { |
TEST_F(SyncInvalidationListenerTest, RegisterReadyEnable) { |
EXPECT_TRUE(GetRegisteredIds().empty()); |
- client_.Ready(fake_invalidation_client_); |
+ listener_.Ready(fake_invalidation_client_); |
EXPECT_EQ(registered_ids_, GetRegisteredIds()); |
@@ -540,7 +841,7 @@ TEST_F(SyncInvalidationListenerTest, RegisterReadyEnable) { |
// ready the client. The IDs should be registered only after the |
// client is readied. |
TEST_F(SyncInvalidationListenerTest, EnableRegisterReady) { |
- client_.UpdateRegisteredIds(ObjectIdSet()); |
+ listener_.UpdateRegisteredIds(ObjectIdSet()); |
EXPECT_TRUE(GetRegisteredIds().empty()); |
@@ -548,11 +849,11 @@ TEST_F(SyncInvalidationListenerTest, EnableRegisterReady) { |
EXPECT_TRUE(GetRegisteredIds().empty()); |
- client_.UpdateRegisteredIds(registered_ids_); |
+ listener_.UpdateRegisteredIds(registered_ids_); |
EXPECT_TRUE(GetRegisteredIds().empty()); |
- client_.Ready(fake_invalidation_client_); |
+ listener_.Ready(fake_invalidation_client_); |
EXPECT_EQ(registered_ids_, GetRegisteredIds()); |
} |
@@ -561,7 +862,7 @@ TEST_F(SyncInvalidationListenerTest, EnableRegisterReady) { |
// re-register the IDs. The IDs should be registered only after the |
// client is readied. |
TEST_F(SyncInvalidationListenerTest, EnableReadyRegister) { |
- client_.UpdateRegisteredIds(ObjectIdSet()); |
+ listener_.UpdateRegisteredIds(ObjectIdSet()); |
EXPECT_TRUE(GetRegisteredIds().empty()); |
@@ -569,11 +870,11 @@ TEST_F(SyncInvalidationListenerTest, EnableReadyRegister) { |
EXPECT_TRUE(GetRegisteredIds().empty()); |
- client_.Ready(fake_invalidation_client_); |
+ listener_.Ready(fake_invalidation_client_); |
EXPECT_TRUE(GetRegisteredIds().empty()); |
- client_.UpdateRegisteredIds(registered_ids_); |
+ listener_.UpdateRegisteredIds(registered_ids_); |
EXPECT_EQ(registered_ids_, GetRegisteredIds()); |
} |
@@ -582,7 +883,7 @@ TEST_F(SyncInvalidationListenerTest, EnableReadyRegister) { |
// re-register the IDs. The IDs should be registered only after the |
// client is readied. |
TEST_F(SyncInvalidationListenerTest, ReadyEnableRegister) { |
- client_.UpdateRegisteredIds(ObjectIdSet()); |
+ listener_.UpdateRegisteredIds(ObjectIdSet()); |
EXPECT_TRUE(GetRegisteredIds().empty()); |
@@ -590,11 +891,11 @@ TEST_F(SyncInvalidationListenerTest, ReadyEnableRegister) { |
EXPECT_TRUE(GetRegisteredIds().empty()); |
- client_.Ready(fake_invalidation_client_); |
+ listener_.Ready(fake_invalidation_client_); |
EXPECT_TRUE(GetRegisteredIds().empty()); |
- client_.UpdateRegisteredIds(registered_ids_); |
+ listener_.UpdateRegisteredIds(registered_ids_); |
EXPECT_EQ(registered_ids_, GetRegisteredIds()); |
} |
@@ -605,15 +906,15 @@ TEST_F(SyncInvalidationListenerTest, ReadyEnableRegister) { |
// |
// This test is important: see http://crbug.com/139424. |
TEST_F(SyncInvalidationListenerTest, ReadyRegisterEnable) { |
- client_.UpdateRegisteredIds(ObjectIdSet()); |
+ listener_.UpdateRegisteredIds(ObjectIdSet()); |
EXPECT_TRUE(GetRegisteredIds().empty()); |
- client_.Ready(fake_invalidation_client_); |
+ listener_.Ready(fake_invalidation_client_); |
EXPECT_TRUE(GetRegisteredIds().empty()); |
- client_.UpdateRegisteredIds(registered_ids_); |
+ listener_.UpdateRegisteredIds(registered_ids_); |
EXPECT_EQ(registered_ids_, GetRegisteredIds()); |
@@ -627,7 +928,7 @@ TEST_F(SyncInvalidationListenerTest, ReadyRegisterEnable) { |
TEST_F(SyncInvalidationListenerTest, RegisterTypesPreserved) { |
EXPECT_TRUE(GetRegisteredIds().empty()); |
- client_.Ready(fake_invalidation_client_); |
+ listener_.Ready(fake_invalidation_client_); |
EXPECT_EQ(registered_ids_, GetRegisteredIds()); |
@@ -635,7 +936,7 @@ TEST_F(SyncInvalidationListenerTest, RegisterTypesPreserved) { |
EXPECT_TRUE(GetRegisteredIds().empty()); |
- client_.Ready(fake_invalidation_client_); |
+ listener_.Ready(fake_invalidation_client_); |
EXPECT_EQ(registered_ids_, GetRegisteredIds()); |
} |
@@ -669,7 +970,7 @@ TEST_F(SyncInvalidationListenerTest, EnableNotificationsThenReady) { |
EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, GetInvalidatorState()); |
- client_.Ready(fake_invalidation_client_); |
+ listener_.Ready(fake_invalidation_client_); |
EXPECT_EQ(INVALIDATIONS_ENABLED, GetInvalidatorState()); |
} |
@@ -679,7 +980,7 @@ TEST_F(SyncInvalidationListenerTest, EnableNotificationsThenReady) { |
TEST_F(SyncInvalidationListenerTest, ReadyThenEnableNotifications) { |
EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, GetInvalidatorState()); |
- client_.Ready(fake_invalidation_client_); |
+ listener_.Ready(fake_invalidation_client_); |
EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, GetInvalidatorState()); |
@@ -693,7 +994,7 @@ TEST_F(SyncInvalidationListenerTest, ReadyThenEnableNotifications) { |
// delegate should go into an auth error mode and then back out. |
TEST_F(SyncInvalidationListenerTest, PushClientAuthError) { |
EnableNotifications(); |
- client_.Ready(fake_invalidation_client_); |
+ listener_.Ready(fake_invalidation_client_); |
EXPECT_EQ(INVALIDATIONS_ENABLED, GetInvalidatorState()); |
@@ -713,11 +1014,11 @@ TEST_F(SyncInvalidationListenerTest, PushClientAuthError) { |
// auth error mode and come out of it only after the client is ready. |
TEST_F(SyncInvalidationListenerTest, InvalidationClientAuthError) { |
EnableNotifications(); |
- client_.Ready(fake_invalidation_client_); |
+ listener_.Ready(fake_invalidation_client_); |
EXPECT_EQ(INVALIDATIONS_ENABLED, GetInvalidatorState()); |
- client_.InformError( |
+ listener_.InformError( |
fake_invalidation_client_, |
invalidation::ErrorInfo( |
invalidation::ErrorReason::AUTH_FAILURE, |
@@ -739,7 +1040,7 @@ TEST_F(SyncInvalidationListenerTest, InvalidationClientAuthError) { |
EXPECT_EQ(INVALIDATION_CREDENTIALS_REJECTED, GetInvalidatorState()); |
- client_.Ready(fake_invalidation_client_); |
+ listener_.Ready(fake_invalidation_client_); |
EXPECT_EQ(INVALIDATIONS_ENABLED, GetInvalidatorState()); |
} |