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

Side by Side Diff: sync/notifier/chrome_invalidation_client_unittest.cc

Issue 10827133: [Sync] Rework unit tests for ChromeInvalidationClient (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Sync to head Created 8 years, 4 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <cstddef>
6 #include <set>
5 #include <string> 7 #include <string>
6 8
9 #include "base/compiler_specific.h"
7 #include "base/message_loop.h" 10 #include "base/message_loop.h"
8 #include "google/cacheinvalidation/include/invalidation-client.h" 11 #include "google/cacheinvalidation/include/invalidation-client.h"
9 #include "google/cacheinvalidation/include/types.h" 12 #include "google/cacheinvalidation/include/types.h"
10 #include "google/cacheinvalidation/types.pb.h"
11 #include "jingle/notifier/listener/fake_push_client.h" 13 #include "jingle/notifier/listener/fake_push_client.h"
12 #include "sync/internal_api/public/util/weak_handle.h" 14 #include "sync/internal_api/public/util/weak_handle.h"
13 #include "sync/notifier/chrome_invalidation_client.h" 15 #include "sync/notifier/chrome_invalidation_client.h"
14 #include "sync/notifier/mock_invalidation_state_tracker.h" 16 #include "sync/notifier/fake_invalidation_state_tracker.h"
15 #include "testing/gmock/include/gmock/gmock.h" 17 #include "sync/notifier/invalidation_util.h"
16 #include "testing/gtest/include/gtest/gtest.h" 18 #include "testing/gtest/include/gtest/gtest.h"
17 19
18 namespace syncer { 20 namespace syncer {
19 21
20 using ::testing::_;
21 using ::testing::InSequence;
22 using ::testing::Return;
23 using ::testing::StrictMock;
24
25 namespace { 22 namespace {
26 23
24 using invalidation::AckHandle;
25 using invalidation::ObjectId;
26
27 const char kClientId[] = "client_id"; 27 const char kClientId[] = "client_id";
28 const char kClientInfo[] = "client_info"; 28 const char kClientInfo[] = "client_info";
29
29 const char kState[] = "state"; 30 const char kState[] = "state";
30 const char kNewState[] = "new_state"; 31 const char kNewState[] = "new_state";
31 32
33 const char kPayload1[] = "payload1";
34 const char kPayload2[] = "payload2";
35
36 const int64 kMinVersion = FakeInvalidationStateTracker::kMinVersion;
37 const int64 kVersion1 = 1LL;
38 const int64 kVersion2 = 2LL;
39
32 const int kChromeSyncSourceId = 1004; 40 const int kChromeSyncSourceId = 1004;
33 41
34 class MockInvalidationClient : public invalidation::InvalidationClient { 42 struct AckHandleLessThan {
43 bool operator()(const AckHandle& lhs, const AckHandle& rhs) const {
44 return lhs.handle_data() < rhs.handle_data();
45 }
46 };
47
48 typedef std::set<AckHandle, AckHandleLessThan> AckHandleSet;
49
50 // Fake invalidation::InvalidationClient implementation that keeps
51 // track of registered IDs and acked handles.
52 class FakeInvalidationClient : public invalidation::InvalidationClient {
35 public: 53 public:
36 MOCK_METHOD0(Start, void()); 54 FakeInvalidationClient() : started_(false) {}
37 MOCK_METHOD0(Stop, void()); 55 virtual ~FakeInvalidationClient() {}
38 MOCK_METHOD1(Register, void(const invalidation::ObjectId&)); 56
39 MOCK_METHOD1(Register, void(const std::vector<invalidation::ObjectId>&)); 57 const ObjectIdSet& GetRegisteredIds() const {
40 MOCK_METHOD1(Unregister, void(const invalidation::ObjectId&)); 58 return registered_ids_;
41 MOCK_METHOD1(Unregister, void(const std::vector<invalidation::ObjectId>&)); 59 }
42 MOCK_METHOD1(Acknowledge, void(const invalidation::AckHandle&)); 60
61 void ClearAckedHandles() {
62 acked_handles_.clear();
63 }
64
65 bool IsAckedHandle(const AckHandle& ack_handle) const {
66 return (acked_handles_.find(ack_handle) != acked_handles_.end());
67 }
68
69 // invalidation::InvalidationClient implementation.
70
71 virtual void Start() OVERRIDE {
72 started_ = true;
73 }
74
75 virtual void Stop() OVERRIDE {
76 started_ = false;
77 }
78
79 virtual void Register(const ObjectId& object_id) OVERRIDE {
80 if (!started_) {
81 ADD_FAILURE();
82 return;
83 }
84 registered_ids_.insert(object_id);
85 }
86
87 virtual void Register(
88 const invalidation::vector<ObjectId>& object_ids) OVERRIDE {
89 if (!started_) {
90 ADD_FAILURE();
91 return;
92 }
93 registered_ids_.insert(object_ids.begin(), object_ids.end());
94 }
95
96 virtual void Unregister(const ObjectId& object_id) OVERRIDE {
97 if (!started_) {
98 ADD_FAILURE();
99 return;
100 }
101 registered_ids_.erase(object_id);
102 }
103
104 virtual void Unregister(
105 const invalidation::vector<ObjectId>& object_ids) OVERRIDE {
106 if (!started_) {
107 ADD_FAILURE();
108 return;
109 }
110 for (invalidation::vector<ObjectId>::const_iterator
111 it = object_ids.begin(); it != object_ids.end(); ++it) {
112 registered_ids_.erase(*it);
113 }
114 }
115
116 virtual void Acknowledge(const AckHandle& ack_handle) OVERRIDE {
117 if (!started_) {
118 ADD_FAILURE();
119 return;
120 }
121 acked_handles_.insert(ack_handle);
122 }
123
124 private:
125 bool started_;
126 ObjectIdSet registered_ids_;
127 AckHandleSet acked_handles_;
43 }; 128 };
44 129
45 class MockListener : public ChromeInvalidationClient::Listener { 130 // Fake listener tkat keeps track of invalidation counts, payloads,
131 // and state.
132 class FakeListener : public ChromeInvalidationClient::Listener {
46 public: 133 public:
47 MOCK_METHOD1(OnInvalidate, void(const ObjectIdPayloadMap&)); 134 FakeListener() : reason_(TRANSIENT_NOTIFICATION_ERROR) {}
48 MOCK_METHOD0(OnNotificationsEnabled, void()); 135 virtual ~FakeListener() {}
49 MOCK_METHOD1(OnNotificationsDisabled, void(NotificationsDisabledReason)); 136
137 int GetInvalidationCount(const ObjectId& id) const {
138 ObjectIdCountMap::const_iterator it = invalidation_counts_.find(id);
139 return (it == invalidation_counts_.end()) ? 0 : it->second;
140 }
141
142 std::string GetPayload(const ObjectId& id) const {
143 ObjectIdPayloadMap::const_iterator it = payloads_.find(id);
144 return (it == payloads_.end()) ? "" : it->second;
145 }
146
147 // NO_NOTIFICATION_ERROR is the enabled state.
148 NotificationsDisabledReason GetNotificationsDisabledReason() const {
149 return reason_;
150 }
151
152 // ChromeInvalidationClient::Listener implementation.
153
154 virtual void OnInvalidate(const ObjectIdPayloadMap& id_payloads) OVERRIDE {
155 for (ObjectIdPayloadMap::const_iterator it = id_payloads.begin();
156 it != id_payloads.end(); ++it) {
157 ++invalidation_counts_[it->first];
158 payloads_[it->first] = it->second;
159 }
160 }
161
162 virtual void OnNotificationsEnabled() {
163 reason_ = NO_NOTIFICATION_ERROR;
164 }
165
166 virtual void OnNotificationsDisabled(NotificationsDisabledReason reason) {
167 reason_ = reason;
168 }
169
170 private:
171 typedef std::map<ObjectId, int, ObjectIdLessThan> ObjectIdCountMap;
172 ObjectIdCountMap invalidation_counts_;
173 ObjectIdPayloadMap payloads_;
174 NotificationsDisabledReason reason_;
50 }; 175 };
51 176
52 ObjectIdSet MakeSetFromId(const invalidation::ObjectId& id) { 177 invalidation::InvalidationClient* CreateFakeInvalidationClient(
53 ObjectIdSet ids; 178 FakeInvalidationClient** fake_invalidation_client,
54 ids.insert(id); 179 invalidation::SystemResources* resources,
55 return ids; 180 int client_type,
56 } 181 const invalidation::string& client_name,
57 182 const invalidation::string& application_name,
58 ObjectIdPayloadMap ObjectIdsAndPayloadToMap(const ObjectIdSet& ids, 183 invalidation::InvalidationListener* listener) {
59 const std::string& payload) { 184 *fake_invalidation_client = new FakeInvalidationClient();
60 ObjectIdPayloadMap id_payloads; 185 return *fake_invalidation_client;
61 for (ObjectIdSet::const_iterator it = ids.begin(); it != ids.end(); ++it) { 186 }
62 id_payloads[*it] = payload;
63 }
64 return id_payloads;
65 }
66
67 } // namespace
68 187
69 class ChromeInvalidationClientTest : public testing::Test { 188 class ChromeInvalidationClientTest : public testing::Test {
70 protected: 189 protected:
71 ChromeInvalidationClientTest() 190 ChromeInvalidationClientTest()
72 : fake_push_client_(new notifier::FakePushClient()), 191 : kBookmarksId_(kChromeSyncSourceId, "BOOKMARK"),
73 client_(scoped_ptr<notifier::PushClient>(fake_push_client_)),
74 kBookmarksId_(kChromeSyncSourceId, "BOOKMARK"),
75 kPreferencesId_(kChromeSyncSourceId, "PREFERENCE"), 192 kPreferencesId_(kChromeSyncSourceId, "PREFERENCE"),
76 kExtensionsId_(kChromeSyncSourceId, "EXTENSION"), 193 kExtensionsId_(kChromeSyncSourceId, "EXTENSION"),
77 kAppsId_(kChromeSyncSourceId, "APP") {} 194 kAppsId_(kChromeSyncSourceId, "APP"),
195 fake_push_client_(new notifier::FakePushClient()),
196 fake_invalidation_client_(NULL),
197 client_(scoped_ptr<notifier::PushClient>(fake_push_client_)) {}
78 198
79 virtual void SetUp() { 199 virtual void SetUp() {
80 client_.Start(kClientId, kClientInfo, kState, 200 StartClient();
81 InvalidationVersionMap(), 201
82 MakeWeakHandle(mock_invalidation_state_tracker_.AsWeakPtr()), 202 registered_ids_.insert(kBookmarksId_);
83 &mock_listener_); 203 registered_ids_.insert(kPreferencesId_);
204 client_.UpdateRegisteredIds(registered_ids_);
84 } 205 }
85 206
86 virtual void TearDown() { 207 virtual void TearDown() {
87 // client_.Stop() stops the invalidation scheduler, which deletes any 208 StopClient();
88 // pending tasks without running them. Some tasks "run and delete" another 209 }
89 // task, so they must be run in order to avoid leaking the inner task. 210
90 // client_.Stop() does not schedule any tasks, so it's both necessary and 211 // Restart client without re-registering IDs.
91 // sufficient to drain the task queue before calling it. 212 void RestartClient() {
92 message_loop_.RunAllPending(); 213 StopClient();
93 client_.Stop(); 214 StartClient();
94 } 215 }
95 216
96 // |payload| can be NULL, but not |type_name|. 217 int GetInvalidationCount(const ObjectId& id) const {
97 void FireInvalidate(const char* type_name, 218 return fake_listener_.GetInvalidationCount(id);
219 }
220
221 std::string GetPayload(const ObjectId& id) const {
222 return fake_listener_.GetPayload(id);
223 }
224
225 NotificationsDisabledReason GetNotificationsDisabledReason() const {
226 return fake_listener_.GetNotificationsDisabledReason();
227 }
228
229 int64 GetMaxVersion(const ObjectId& id) const {
230 return fake_tracker_.GetMaxVersion(id);
231 }
232
233 std::string GetInvalidationState() const {
234 return fake_tracker_.GetInvalidationState();
235 }
236
237 ObjectIdSet GetRegisteredIds() const {
238 return fake_invalidation_client_->GetRegisteredIds();
239 }
240
241 // |payload| can be NULL.
242 void FireInvalidate(const ObjectId& object_id,
98 int64 version, const char* payload) { 243 int64 version, const char* payload) {
99 const invalidation::ObjectId object_id(
100 ipc::invalidation::ObjectSource::CHROME_SYNC, type_name);
101 std::string payload_tmp = payload ? payload : "";
102 invalidation::Invalidation inv; 244 invalidation::Invalidation inv;
103 if (payload) { 245 if (payload) {
104 inv = invalidation::Invalidation(object_id, version, payload); 246 inv = invalidation::Invalidation(object_id, version, payload);
105 } else { 247 } else {
106 inv = invalidation::Invalidation(object_id, version); 248 inv = invalidation::Invalidation(object_id, version);
107 } 249 }
108 invalidation::AckHandle ack_handle("fakedata"); 250 const AckHandle ack_handle("fakedata");
109 EXPECT_CALL(mock_invalidation_client_, Acknowledge(ack_handle)); 251 fake_invalidation_client_->ClearAckedHandles();
110 client_.Invalidate(&mock_invalidation_client_, inv, ack_handle); 252 client_.Invalidate(fake_invalidation_client_, inv, ack_handle);
253 EXPECT_TRUE(fake_invalidation_client_->IsAckedHandle(ack_handle));
111 // Pump message loop to trigger 254 // Pump message loop to trigger
112 // InvalidationStateTracker::SetMaxVersion(). 255 // InvalidationStateTracker::SetMaxVersion().
113 message_loop_.RunAllPending(); 256 message_loop_.RunAllPending();
114 } 257 }
115 258
116 // |payload| can be NULL, but not |type_name|. 259 // |payload| can be NULL, but not |type_name|.
117 void FireInvalidateUnknownVersion(const char* type_name) { 260 void FireInvalidateUnknownVersion(const ObjectId& object_id) {
118 const invalidation::ObjectId object_id( 261 const AckHandle ack_handle("fakedata_unknown");
119 ipc::invalidation::ObjectSource::CHROME_SYNC, type_name); 262 fake_invalidation_client_->ClearAckedHandles();
120 263 client_.InvalidateUnknownVersion(fake_invalidation_client_, object_id,
121 invalidation::AckHandle ack_handle("fakedata");
122 EXPECT_CALL(mock_invalidation_client_, Acknowledge(ack_handle));
123 client_.InvalidateUnknownVersion(&mock_invalidation_client_, object_id,
124 ack_handle); 264 ack_handle);
265 EXPECT_TRUE(fake_invalidation_client_->IsAckedHandle(ack_handle));
125 } 266 }
126 267
127 void FireInvalidateAll() { 268 void FireInvalidateAll() {
128 invalidation::AckHandle ack_handle("fakedata"); 269 const AckHandle ack_handle("fakedata_all");
129 EXPECT_CALL(mock_invalidation_client_, Acknowledge(ack_handle)); 270 fake_invalidation_client_->ClearAckedHandles();
130 client_.InvalidateAll(&mock_invalidation_client_, ack_handle); 271 client_.InvalidateAll(fake_invalidation_client_, ack_handle);
272 EXPECT_TRUE(fake_invalidation_client_->IsAckedHandle(ack_handle));
273 }
274
275 void WriteState(const std::string& new_state) {
276 client_.WriteState(new_state);
277 // Pump message loop to trigger
278 // InvalidationStateTracker::WriteState().
279 message_loop_.RunAllPending();
280 }
281
282 void EnableNotifications() {
283 fake_push_client_->EnableNotifications();
284 }
285
286 void DisableNotifications(notifier::NotificationsDisabledReason reason) {
287 fake_push_client_->DisableNotifications(reason);
288 }
289
290 const ObjectId kBookmarksId_;
291 const ObjectId kPreferencesId_;
292 const ObjectId kExtensionsId_;
293 const ObjectId kAppsId_;
294
295 ObjectIdSet registered_ids_;
296
297 private:
298 void StartClient() {
299 fake_invalidation_client_ = NULL;
300 client_.Start(base::Bind(&CreateFakeInvalidationClient,
301 &fake_invalidation_client_),
302 kClientId, kClientInfo, kState,
303 InvalidationVersionMap(),
304 MakeWeakHandle(fake_tracker_.AsWeakPtr()),
305 &fake_listener_);
306 DCHECK(fake_invalidation_client_);
307 }
308
309 void StopClient() {
310 // client_.StopForTest() stops the invalidation scheduler, which
311 // deletes any pending tasks without running them. Some tasks
312 // "run and delete" another task, so they must be run in order to
313 // avoid leaking the inner task. client_.StopForTest() does not
314 // schedule any tasks, so it's both necessary and sufficient to
315 // drain the task queue before calling it.
316 message_loop_.RunAllPending();
317 fake_invalidation_client_ = NULL;
318 client_.StopForTest();
131 } 319 }
132 320
133 MessageLoop message_loop_; 321 MessageLoop message_loop_;
134 StrictMock<MockListener> mock_listener_; 322
135 StrictMock<MockInvalidationStateTracker> 323 FakeListener fake_listener_;
136 mock_invalidation_state_tracker_; 324 FakeInvalidationStateTracker fake_tracker_;
137 StrictMock<MockInvalidationClient> mock_invalidation_client_;
138 notifier::FakePushClient* const fake_push_client_; 325 notifier::FakePushClient* const fake_push_client_;
326
327 protected:
328 // Tests need to access these directly.
329 FakeInvalidationClient* fake_invalidation_client_;
139 ChromeInvalidationClient client_; 330 ChromeInvalidationClient client_;
140
141 const invalidation::ObjectId kBookmarksId_;
142 const invalidation::ObjectId kPreferencesId_;
143 const invalidation::ObjectId kExtensionsId_;
144 const invalidation::ObjectId kAppsId_;
145 }; 331 };
146 332
147 // Checks that we still dispatch an invalidation for something that's not 333 // Write a new state to the client. It should propagate to the
148 // currently registered (perhaps it was unregistered while it was still in 334 // tracker.
149 // flight). 335 TEST_F(ChromeInvalidationClientTest, WriteState) {
150 TEST_F(ChromeInvalidationClientTest, InvalidateBadObjectId) { 336 WriteState(kNewState);
151 ObjectIdSet ids; 337
152 ids.insert(kBookmarksId_); 338 EXPECT_EQ(kNewState, GetInvalidationState());
153 ids.insert(kAppsId_); 339 }
154 client_.RegisterIds(ids); 340
155 EXPECT_CALL(mock_listener_, OnInvalidate( 341 // Invalidation tests.
156 ObjectIdsAndPayloadToMap( 342
157 MakeSetFromId(invalidation::ObjectId(kChromeSyncSourceId, "bad")), 343 // Fire an invalidation without a payload. It should be processed,
158 std::string()))); 344 // the payload should remain empty, and the version should be updated.
159 EXPECT_CALL(mock_invalidation_state_tracker_,
160 SetMaxVersion(invalidation::ObjectId(kChromeSyncSourceId, "bad"),
161 1));
162 FireInvalidate("bad", 1, NULL);
163 }
164
165 TEST_F(ChromeInvalidationClientTest, InvalidateNoPayload) { 345 TEST_F(ChromeInvalidationClientTest, InvalidateNoPayload) {
166 EXPECT_CALL(mock_listener_, OnInvalidate( 346 const ObjectId& id = kBookmarksId_;
167 ObjectIdsAndPayloadToMap(MakeSetFromId(kBookmarksId_), std::string()))); 347
168 EXPECT_CALL(mock_invalidation_state_tracker_, 348 FireInvalidate(id, kVersion1, NULL);
169 SetMaxVersion(kBookmarksId_, 1)); 349
170 FireInvalidate("BOOKMARK", 1, NULL); 350 EXPECT_EQ(1, GetInvalidationCount(id));
171 } 351 EXPECT_EQ("", GetPayload(id));
172 352 EXPECT_EQ(kVersion1, GetMaxVersion(id));
353 }
354
355 // Fire an invalidation with an empty payload. It should be
356 // processed, the payload should remain empty, and the version should
357 // be updated.
358 TEST_F(ChromeInvalidationClientTest, InvalidateEmptyPayload) {
359 const ObjectId& id = kBookmarksId_;
360
361 FireInvalidate(id, kVersion1, "");
362
363 EXPECT_EQ(1, GetInvalidationCount(id));
364 EXPECT_EQ("", GetPayload(id));
365 EXPECT_EQ(kVersion1, GetMaxVersion(id));
366 }
367
368 // Fire an invalidation with a payload. It should be processed, and
369 // both the payload and the version should be updated.
173 TEST_F(ChromeInvalidationClientTest, InvalidateWithPayload) { 370 TEST_F(ChromeInvalidationClientTest, InvalidateWithPayload) {
174 EXPECT_CALL(mock_listener_, OnInvalidate( 371 const ObjectId& id = kPreferencesId_;
175 ObjectIdsAndPayloadToMap(MakeSetFromId(kPreferencesId_), "payload"))); 372
176 EXPECT_CALL(mock_invalidation_state_tracker_, 373 FireInvalidate(id, kVersion1, kPayload1);
177 SetMaxVersion(kPreferencesId_, 1)); 374
178 FireInvalidate("PREFERENCE", 1, "payload"); 375 EXPECT_EQ(1, GetInvalidationCount(id));
179 } 376 EXPECT_EQ(kPayload1, GetPayload(id));
180 377 EXPECT_EQ(kVersion1, GetMaxVersion(id));
378 }
379
380 // Fire an invalidation with a payload. It should still be processed,
381 // and both the payload and the version should be updated.
382 TEST_F(ChromeInvalidationClientTest, InvalidateUnregistered) {
383 const ObjectId kUnregisteredId(
384 kChromeSyncSourceId, "unregistered");
385 const ObjectId& id = kUnregisteredId;
386
387 EXPECT_EQ(0, GetInvalidationCount(id));
388 EXPECT_EQ("", GetPayload(id));
389 EXPECT_EQ(kMinVersion, GetMaxVersion(id));
390
391 FireInvalidate(id, kVersion1, NULL);
392
393 EXPECT_EQ(1, GetInvalidationCount(id));
394 EXPECT_EQ("", GetPayload(id));
395 EXPECT_EQ(kVersion1, GetMaxVersion(id));
396 }
397
398 // Fire an invalidation, then fire another one with a lower version.
399 // The first one should be processed and should update the payload and
400 // version, but the second one shouldn't.
181 TEST_F(ChromeInvalidationClientTest, InvalidateVersion) { 401 TEST_F(ChromeInvalidationClientTest, InvalidateVersion) {
182 using ::testing::Mock; 402 const ObjectId& id = kPreferencesId_;
183 403
184 EXPECT_CALL(mock_listener_, OnInvalidate( 404 FireInvalidate(id, kVersion2, kPayload2);
185 ObjectIdsAndPayloadToMap(MakeSetFromId(kAppsId_), std::string()))); 405
186 EXPECT_CALL(mock_invalidation_state_tracker_, 406 EXPECT_EQ(1, GetInvalidationCount(id));
187 SetMaxVersion(kAppsId_, 1)); 407 EXPECT_EQ(kPayload2, GetPayload(id));
188 408 EXPECT_EQ(kVersion2, GetMaxVersion(id));
189 // Should trigger. 409
190 FireInvalidate("APP", 1, NULL); 410 FireInvalidate(id, kVersion1, kPayload1);
191 411
192 Mock::VerifyAndClearExpectations(&mock_listener_); 412 EXPECT_EQ(1, GetInvalidationCount(id));
193 413 EXPECT_EQ(kPayload2, GetPayload(id));
194 // Should be dropped. 414 EXPECT_EQ(kVersion2, GetMaxVersion(id));
195 FireInvalidate("APP", 1, NULL); 415 }
196 } 416
197 417 // Fire an invalidation with an unknown version twice. It shouldn't
418 // update the payload or version either time, but it should still be
419 // processed.
198 TEST_F(ChromeInvalidationClientTest, InvalidateUnknownVersion) { 420 TEST_F(ChromeInvalidationClientTest, InvalidateUnknownVersion) {
199 EXPECT_CALL(mock_listener_, OnInvalidate( 421 const ObjectId& id = kBookmarksId_;
200 ObjectIdsAndPayloadToMap(MakeSetFromId(kExtensionsId_), 422
201 std::string()))).Times(2); 423 FireInvalidateUnknownVersion(id);
202 424
203 // Should trigger twice. 425 EXPECT_EQ(1, GetInvalidationCount(id));
204 FireInvalidateUnknownVersion("EXTENSION"); 426 EXPECT_EQ("", GetPayload(id));
205 FireInvalidateUnknownVersion("EXTENSION"); 427 EXPECT_EQ(kMinVersion, GetMaxVersion(id));
206 } 428
207 429 FireInvalidateUnknownVersion(id);
208 // Comprehensive test of various invalidations that we might receive from Tango 430
209 // and how they interact. 431 EXPECT_EQ(2, GetInvalidationCount(id));
210 TEST_F(ChromeInvalidationClientTest, InvalidateVersionMultipleTypes) { 432 EXPECT_EQ("", GetPayload(id));
211 using ::testing::Mock; 433 EXPECT_EQ(kMinVersion, GetMaxVersion(id));
212 434 }
213 ObjectIdSet ids; 435
214 ids.insert(kBookmarksId_); 436 // Fire an invalidation for all enabled IDs. It shouldn't update the
215 ids.insert(kAppsId_); 437 // payload or version, but it should still invalidate the IDs.
216 client_.RegisterIds(ids); 438 TEST_F(ChromeInvalidationClientTest, InvalidateAll) {
217 439 FireInvalidateAll();
218 // Initial invalidations to the client should be recorded and dispatched to 440
219 // the listener. 441 for (ObjectIdSet::const_iterator it = registered_ids_.begin();
220 EXPECT_CALL(mock_listener_, OnInvalidate( 442 it != registered_ids_.end(); ++it) {
221 ObjectIdsAndPayloadToMap(MakeSetFromId(kAppsId_), std::string()))); 443 EXPECT_EQ(1, GetInvalidationCount(*it));
222 EXPECT_CALL(mock_listener_, OnInvalidate( 444 EXPECT_EQ("", GetPayload(*it));
223 ObjectIdsAndPayloadToMap(MakeSetFromId(kExtensionsId_), std::string()))); 445 EXPECT_EQ(kMinVersion, GetMaxVersion(*it));
224 446 }
225 EXPECT_CALL(mock_invalidation_state_tracker_, 447 }
226 SetMaxVersion(kAppsId_, 3)); 448
227 EXPECT_CALL(mock_invalidation_state_tracker_, 449 // Comprehensive test of various scenarios for multiple IDs.
228 SetMaxVersion(kExtensionsId_, 2)); 450 TEST_F(ChromeInvalidationClientTest, InvalidateMultipleIds) {
229 451 FireInvalidate(kBookmarksId_, 3, NULL);
230 FireInvalidate("APP", 3, NULL); 452
231 FireInvalidate("EXTENSION", 2, NULL); 453 EXPECT_EQ(1, GetInvalidationCount(kBookmarksId_));
232 454 EXPECT_EQ("", GetPayload(kBookmarksId_));
233 Mock::VerifyAndClearExpectations(&mock_listener_); 455 EXPECT_EQ(3, GetMaxVersion(kBookmarksId_));
234 Mock::VerifyAndClearExpectations(&mock_invalidation_state_tracker_); 456
235 457 FireInvalidate(kExtensionsId_, 2, NULL);
236 // Out-of-order invalidations with lower version numbers should be ignored. 458
237 FireInvalidate("APP", 1, NULL); 459 EXPECT_EQ(1, GetInvalidationCount(kExtensionsId_));
238 FireInvalidate("EXTENSION", 1, NULL); 460 EXPECT_EQ("", GetPayload(kExtensionsId_));
239 461 EXPECT_EQ(2, GetMaxVersion(kExtensionsId_));
240 Mock::VerifyAndClearExpectations(&mock_listener_); 462
241 Mock::VerifyAndClearExpectations(&mock_invalidation_state_tracker_); 463 // Invalidations with lower version numbers should be ignored.
464
465 FireInvalidate(kBookmarksId_, 1, NULL);
466
467 EXPECT_EQ(1, GetInvalidationCount(kBookmarksId_));
468 EXPECT_EQ("", GetPayload(kBookmarksId_));
469 EXPECT_EQ(3, GetMaxVersion(kBookmarksId_));
470
471 FireInvalidate(kExtensionsId_, 1, NULL);
472
473 EXPECT_EQ(1, GetInvalidationCount(kExtensionsId_));
474 EXPECT_EQ("", GetPayload(kExtensionsId_));
475 EXPECT_EQ(2, GetMaxVersion(kExtensionsId_));
242 476
243 // InvalidateAll shouldn't change any version state. 477 // InvalidateAll shouldn't change any version state.
244 EXPECT_CALL(mock_listener_, 478
245 OnInvalidate(ObjectIdsAndPayloadToMap(ids, std::string())));
246 FireInvalidateAll(); 479 FireInvalidateAll();
247 480
248 Mock::VerifyAndClearExpectations(&mock_listener_); 481 EXPECT_EQ(2, GetInvalidationCount(kBookmarksId_));
249 Mock::VerifyAndClearExpectations(&mock_invalidation_state_tracker_); 482 EXPECT_EQ("", GetPayload(kBookmarksId_));
250 483 EXPECT_EQ(3, GetMaxVersion(kBookmarksId_));
251 EXPECT_CALL(mock_listener_, OnInvalidate( 484
252 ObjectIdsAndPayloadToMap(MakeSetFromId(kPreferencesId_), std::string()))); 485 EXPECT_EQ(1, GetInvalidationCount(kPreferencesId_));
253 EXPECT_CALL(mock_listener_, OnInvalidate( 486 EXPECT_EQ("", GetPayload(kPreferencesId_));
254 ObjectIdsAndPayloadToMap(MakeSetFromId(kExtensionsId_), std::string()))); 487 EXPECT_EQ(kMinVersion, GetMaxVersion(kPreferencesId_));
255 EXPECT_CALL(mock_listener_, OnInvalidate( 488
256 ObjectIdsAndPayloadToMap(MakeSetFromId(kAppsId_), std::string()))); 489 EXPECT_EQ(1, GetInvalidationCount(kExtensionsId_));
257 490 EXPECT_EQ("", GetPayload(kExtensionsId_));
258 // Normal invalidations with monotonically increasing version numbers. 491 EXPECT_EQ(2, GetMaxVersion(kExtensionsId_));
259 EXPECT_CALL(mock_invalidation_state_tracker_, 492
260 SetMaxVersion(kPreferencesId_, 5)); 493 // Invalidations with higher version numbers should be processed.
261 EXPECT_CALL(mock_invalidation_state_tracker_, 494
262 SetMaxVersion(kExtensionsId_, 3)); 495 FireInvalidate(kPreferencesId_, 5, NULL);
263 EXPECT_CALL(mock_invalidation_state_tracker_, 496 EXPECT_EQ(2, GetInvalidationCount(kPreferencesId_));
264 SetMaxVersion(kAppsId_, 4)); 497 EXPECT_EQ("", GetPayload(kPreferencesId_));
265 498 EXPECT_EQ(5, GetMaxVersion(kPreferencesId_));
266 // All three should be triggered. 499
267 FireInvalidate("PREFERENCE", 5, NULL); 500 FireInvalidate(kExtensionsId_, 3, NULL);
268 FireInvalidate("EXTENSION", 3, NULL); 501 EXPECT_EQ(2, GetInvalidationCount(kExtensionsId_));
269 FireInvalidate("APP", 4, NULL); 502 EXPECT_EQ("", GetPayload(kExtensionsId_));
270 } 503 EXPECT_EQ(3, GetMaxVersion(kExtensionsId_));
271 504
272 TEST_F(ChromeInvalidationClientTest, InvalidateAll) { 505 FireInvalidate(kBookmarksId_, 4, NULL);
273 ObjectIdSet ids; 506 EXPECT_EQ(3, GetInvalidationCount(kBookmarksId_));
274 ids.insert(kPreferencesId_); 507 EXPECT_EQ("", GetPayload(kBookmarksId_));
275 ids.insert(kExtensionsId_); 508 EXPECT_EQ(4, GetMaxVersion(kBookmarksId_));
276 client_.RegisterIds(ids); 509 }
277 EXPECT_CALL(mock_listener_, OnInvalidate( 510
278 ObjectIdsAndPayloadToMap(ids, std::string()))); 511 // Registration tests.
279 FireInvalidateAll(); 512
280 } 513 // With IDs already registered, enable notifications then ready the
281 514 // client. The IDs should be registered only after the client is
282 TEST_F(ChromeInvalidationClientTest, RegisterTypes) { 515 // readied.
283 ObjectIdSet ids; 516 TEST_F(ChromeInvalidationClientTest, RegisterEnableReady) {
284 ids.insert(kPreferencesId_); 517 EXPECT_TRUE(GetRegisteredIds().empty());
285 ids.insert(kExtensionsId_); 518
286 client_.RegisterIds(ids); 519 EnableNotifications();
287 // Registered types should be preserved across Stop/Start. 520
288 TearDown(); 521 EXPECT_TRUE(GetRegisteredIds().empty());
289 SetUp(); 522
290 EXPECT_CALL(mock_listener_,OnInvalidate( 523 client_.Ready(fake_invalidation_client_);
291 ObjectIdsAndPayloadToMap(ids, std::string()))); 524
292 FireInvalidateAll(); 525 EXPECT_EQ(registered_ids_, GetRegisteredIds());
rlarocque 2012/08/07 18:21:48 How sure are we that !GetRegisteredIds().Has(TYPE
akalin 2012/08/08 22:46:35 Note that in this case, GetRegisteredIds() returns
rlarocque 2012/08/08 23:22:56 Never mind, I got confused because I didn't bother
293 } 526 }
294 527
295 TEST_F(ChromeInvalidationClientTest, WriteState) { 528 // With IDs already registered, ready the client then enable
296 EXPECT_CALL(mock_invalidation_state_tracker_, 529 // notifications. The IDs should be registered after the client is
297 SetInvalidationState(kNewState)); 530 // readied.
298 client_.WriteState(kNewState); 531 TEST_F(ChromeInvalidationClientTest, RegisterReadyEnable) {
299 } 532 EXPECT_TRUE(GetRegisteredIds().empty());
300 533
301 TEST_F(ChromeInvalidationClientTest, StateChangesNotReady) { 534 client_.Ready(fake_invalidation_client_);
302 InSequence dummy; 535
303 EXPECT_CALL(mock_listener_, 536 EXPECT_EQ(registered_ids_, GetRegisteredIds());
304 OnNotificationsDisabled(TRANSIENT_NOTIFICATION_ERROR)); 537
305 EXPECT_CALL(mock_listener_, 538 EnableNotifications();
306 OnNotificationsDisabled(NOTIFICATION_CREDENTIALS_REJECTED)); 539
307 EXPECT_CALL(mock_listener_, 540 EXPECT_EQ(registered_ids_, GetRegisteredIds());
308 OnNotificationsDisabled(TRANSIENT_NOTIFICATION_ERROR)); 541 }
309 542
310 fake_push_client_->DisableNotifications( 543 // Unregister the IDs, enable notifications, re-register the IDs, then
544 // ready the client. The IDs should be registered only after the
545 // client is readied.
546 TEST_F(ChromeInvalidationClientTest, EnableRegisterReady) {
547 client_.UpdateRegisteredIds(ObjectIdSet());
548
549 EXPECT_TRUE(GetRegisteredIds().empty());
550
551 EnableNotifications();
552
553 EXPECT_TRUE(GetRegisteredIds().empty());
554
555 client_.UpdateRegisteredIds(registered_ids_);
556
557 EXPECT_TRUE(GetRegisteredIds().empty());
558
559 client_.Ready(fake_invalidation_client_);
560
561 EXPECT_EQ(registered_ids_, GetRegisteredIds());
562 }
563
564 // Unregister the IDs, enable notifications, ready the client, then
565 // re-register the IDs. The IDs should be registered only after the
566 // client is readied.
567 TEST_F(ChromeInvalidationClientTest, EnableReadyRegister) {
568 client_.UpdateRegisteredIds(ObjectIdSet());
569
570 EXPECT_TRUE(GetRegisteredIds().empty());
571
572 EnableNotifications();
573
574 EXPECT_TRUE(GetRegisteredIds().empty());
575
576 client_.Ready(fake_invalidation_client_);
577
578 EXPECT_TRUE(GetRegisteredIds().empty());
579
580 client_.UpdateRegisteredIds(registered_ids_);
581
582 EXPECT_EQ(registered_ids_, GetRegisteredIds());
583 }
584
585 // Unregister the IDs, ready the client, enable notifications, then
586 // re-register the IDs. The IDs should be registered only after the
587 // client is readied.
588 TEST_F(ChromeInvalidationClientTest, ReadyEnableRegister) {
589 client_.UpdateRegisteredIds(ObjectIdSet());
590
591 EXPECT_TRUE(GetRegisteredIds().empty());
592
593 EnableNotifications();
594
595 EXPECT_TRUE(GetRegisteredIds().empty());
596
597 client_.Ready(fake_invalidation_client_);
598
599 EXPECT_TRUE(GetRegisteredIds().empty());
600
601 client_.UpdateRegisteredIds(registered_ids_);
602
603 EXPECT_EQ(registered_ids_, GetRegisteredIds());
604 }
605
606 // Unregister the IDs, ready the client, re-register the IDs, then
607 // enable notifications. The IDs should be registered only after the
608 // client is readied.
609 //
610 // This test is important: see http://crbug.com/139424.
611 TEST_F(ChromeInvalidationClientTest, ReadyRegisterEnable) {
612 client_.UpdateRegisteredIds(ObjectIdSet());
613
614 EXPECT_TRUE(GetRegisteredIds().empty());
615
616 client_.Ready(fake_invalidation_client_);
617
618 EXPECT_TRUE(GetRegisteredIds().empty());
619
620 client_.UpdateRegisteredIds(registered_ids_);
621
622 EXPECT_EQ(registered_ids_, GetRegisteredIds());
623
624 EnableNotifications();
625
626 EXPECT_EQ(registered_ids_, GetRegisteredIds());
627 }
628
629 // With IDs already registered, ready the client, restart the client,
630 // then re-ready it. The IDs should still be registered.
631 TEST_F(ChromeInvalidationClientTest, RegisterTypesPreserved) {
632 EXPECT_TRUE(GetRegisteredIds().empty());
633
634 client_.Ready(fake_invalidation_client_);
635
636 EXPECT_EQ(registered_ids_, GetRegisteredIds());
637
638 RestartClient();
639
640 EXPECT_TRUE(GetRegisteredIds().empty());
641
642 client_.Ready(fake_invalidation_client_);
643
644 EXPECT_EQ(registered_ids_, GetRegisteredIds());
645 }
646
647 // Without readying the client, disable notifications, then enable
648 // them. The listener should still think notifications are disabled.
649 TEST_F(ChromeInvalidationClientTest, EnableNotificationsNotReady) {
650 EXPECT_EQ(TRANSIENT_NOTIFICATION_ERROR,
651 GetNotificationsDisabledReason());
652
653 DisableNotifications(
311 notifier::TRANSIENT_NOTIFICATION_ERROR); 654 notifier::TRANSIENT_NOTIFICATION_ERROR);
312 fake_push_client_->DisableNotifications( 655
656 EXPECT_EQ(TRANSIENT_NOTIFICATION_ERROR,
657 GetNotificationsDisabledReason());
658
659 DisableNotifications(
313 notifier::NOTIFICATION_CREDENTIALS_REJECTED); 660 notifier::NOTIFICATION_CREDENTIALS_REJECTED);
314 fake_push_client_->EnableNotifications(); 661
315 } 662 EXPECT_EQ(NOTIFICATION_CREDENTIALS_REJECTED,
316 663 GetNotificationsDisabledReason());
317 TEST_F(ChromeInvalidationClientTest, StateChangesReady) { 664
318 InSequence dummy; 665 EnableNotifications();
319 EXPECT_CALL(mock_listener_, 666
320 OnNotificationsDisabled(TRANSIENT_NOTIFICATION_ERROR)); 667 EXPECT_EQ(TRANSIENT_NOTIFICATION_ERROR,
321 EXPECT_CALL(mock_listener_, OnNotificationsEnabled()); 668 GetNotificationsDisabledReason());
rlarocque 2012/08/07 18:21:48 Same concern here as with GetRegisteredIds(). Do
akalin 2012/08/08 22:46:35 Not specifically. But I think there's nothing tha
rlarocque 2012/08/08 23:22:56 Never mind, I misread this. I thought that GetNot
322 EXPECT_CALL(mock_listener_, 669 }
323 OnNotificationsDisabled(TRANSIENT_NOTIFICATION_ERROR)); 670
324 EXPECT_CALL(mock_listener_, 671 // Enable notifications then Ready the invalidation client. The
325 OnNotificationsDisabled(NOTIFICATION_CREDENTIALS_REJECTED)); 672 // listener should then be ready.
326 EXPECT_CALL(mock_listener_, OnNotificationsEnabled()); 673 TEST_F(ChromeInvalidationClientTest, EnableNotificationsThenReady) {
327 674 EXPECT_EQ(TRANSIENT_NOTIFICATION_ERROR, GetNotificationsDisabledReason());
328 fake_push_client_->EnableNotifications(); 675
329 client_.Ready(NULL); 676 EnableNotifications();
330 fake_push_client_->DisableNotifications( 677
331 notifier::TRANSIENT_NOTIFICATION_ERROR); 678 EXPECT_EQ(TRANSIENT_NOTIFICATION_ERROR, GetNotificationsDisabledReason());
332 fake_push_client_->DisableNotifications( 679
680 client_.Ready(fake_invalidation_client_);
681
682 EXPECT_EQ(NO_NOTIFICATION_ERROR, GetNotificationsDisabledReason());
683 }
684
685 // Ready the invalidation client then enable notifications. The
686 // listener should then be ready.
687 TEST_F(ChromeInvalidationClientTest, ReadyThenEnableNotifications) {
688 EXPECT_EQ(TRANSIENT_NOTIFICATION_ERROR, GetNotificationsDisabledReason());
689
690 client_.Ready(fake_invalidation_client_);
691
692 EXPECT_EQ(TRANSIENT_NOTIFICATION_ERROR, GetNotificationsDisabledReason());
693
694 EnableNotifications();
695
696 EXPECT_EQ(NO_NOTIFICATION_ERROR, GetNotificationsDisabledReason());
697 }
698
699 // Enable notifications and ready the client. Then disable
700 // notifications with an auth error and re-enable notifications. The
701 // listener should go into an auth error mode and then back out.
702 TEST_F(ChromeInvalidationClientTest, PushClientAuthError) {
703 EnableNotifications();
704 client_.Ready(fake_invalidation_client_);
705
706 EXPECT_EQ(NO_NOTIFICATION_ERROR, GetNotificationsDisabledReason());
707
708 DisableNotifications(
333 notifier::NOTIFICATION_CREDENTIALS_REJECTED); 709 notifier::NOTIFICATION_CREDENTIALS_REJECTED);
334 fake_push_client_->EnableNotifications(); 710
335 } 711 EXPECT_EQ(NOTIFICATION_CREDENTIALS_REJECTED,
336 712 GetNotificationsDisabledReason());
337 TEST_F(ChromeInvalidationClientTest, StateChangesAuthError) { 713
338 InSequence dummy; 714 EnableNotifications();
339 EXPECT_CALL(mock_listener_, 715
340 OnNotificationsDisabled(TRANSIENT_NOTIFICATION_ERROR)); 716 EXPECT_EQ(NO_NOTIFICATION_ERROR, GetNotificationsDisabledReason());
341 EXPECT_CALL(mock_listener_, OnNotificationsEnabled()); 717 }
342 EXPECT_CALL(mock_listener_, 718
343 OnNotificationsDisabled(NOTIFICATION_CREDENTIALS_REJECTED)) 719 // Enable notifications and ready the client. Then simulate an auth
344 .Times(4); 720 // error from the invalidation client. Simulate some notification
345 EXPECT_CALL(mock_listener_, OnNotificationsEnabled()); 721 // events, then re-ready the client. The listener should go into an
346 722 // auth error mode and come out of it only after the client is ready.
347 fake_push_client_->EnableNotifications(); 723 TEST_F(ChromeInvalidationClientTest, InvalidationClientAuthError) {
348 client_.Ready(NULL); 724 EnableNotifications();
725 client_.Ready(fake_invalidation_client_);
726
727 EXPECT_EQ(NO_NOTIFICATION_ERROR, GetNotificationsDisabledReason());
349 728
350 client_.InformError( 729 client_.InformError(
351 NULL, 730 fake_invalidation_client_,
352 invalidation::ErrorInfo( 731 invalidation::ErrorInfo(
353 invalidation::ErrorReason::AUTH_FAILURE, 732 invalidation::ErrorReason::AUTH_FAILURE,
354 false /* is_transient */, 733 false /* is_transient */,
355 "auth error", 734 "auth error",
356 invalidation::ErrorContext())); 735 invalidation::ErrorContext()));
357 fake_push_client_->DisableNotifications( 736
737 EXPECT_EQ(NOTIFICATION_CREDENTIALS_REJECTED,
738 GetNotificationsDisabledReason());
739
740 DisableNotifications(
358 notifier::TRANSIENT_NOTIFICATION_ERROR); 741 notifier::TRANSIENT_NOTIFICATION_ERROR);
359 fake_push_client_->DisableNotifications( 742
360 notifier::NOTIFICATION_CREDENTIALS_REJECTED); 743 EXPECT_EQ(NOTIFICATION_CREDENTIALS_REJECTED,
361 fake_push_client_->EnableNotifications(); 744 GetNotificationsDisabledReason());
362 client_.Ready(NULL); 745
363 } 746 DisableNotifications(
747 notifier::TRANSIENT_NOTIFICATION_ERROR);
748
749 EXPECT_EQ(NOTIFICATION_CREDENTIALS_REJECTED,
750 GetNotificationsDisabledReason());
751
752 EnableNotifications();
753
754 EXPECT_EQ(NOTIFICATION_CREDENTIALS_REJECTED,
755 GetNotificationsDisabledReason());
756
757 client_.Ready(fake_invalidation_client_);
758
759 EXPECT_EQ(NO_NOTIFICATION_ERROR, GetNotificationsDisabledReason());
760 }
761
762 } // namespace
364 763
365 } // namespace syncer 764 } // namespace syncer
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698