1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "components/invalidation/impl/invalidation_logger.h"
6 
7 #include "components/invalidation/impl/invalidation_logger_observer.h"
8 #include "components/invalidation/public/invalidation.h"
9 #include "components/invalidation/public/topic_invalidation_map.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11 
12 namespace invalidation {
13 
14 class InvalidationLoggerObserverTest : public InvalidationLoggerObserver {
15  public:
InvalidationLoggerObserverTest()16   InvalidationLoggerObserverTest() { ResetStates(); }
17 
ResetStates()18   void ResetStates() {
19     registration_change_received = false;
20     state_received = false;
21     update_id_received = false;
22     debug_message_received = false;
23     invalidation_received = false;
24     detailed_status_received = false;
25     updated_topics_replicated = std::map<std::string, syncer::TopicCountMap>();
26     registered_handlers = std::multiset<std::string>();
27   }
28 
OnRegistrationChange(const std::multiset<std::string> & handlers)29   void OnRegistrationChange(
30       const std::multiset<std::string>& handlers) override {
31     registered_handlers = handlers;
32     registration_change_received = true;
33   }
34 
OnStateChange(const syncer::InvalidatorState & new_state,const base::Time & last_change_timestamp)35   void OnStateChange(const syncer::InvalidatorState& new_state,
36                      const base::Time& last_change_timestamp) override {
37     state_received = true;
38   }
39 
OnUpdatedTopics(const std::string & handler,const syncer::TopicCountMap & topics_counts)40   void OnUpdatedTopics(const std::string& handler,
41                        const syncer::TopicCountMap& topics_counts) override {
42     update_id_received = true;
43     updated_topics_replicated[handler] = topics_counts;
44   }
45 
OnDebugMessage(const base::DictionaryValue & details)46   void OnDebugMessage(const base::DictionaryValue& details) override {
47     debug_message_received = true;
48   }
49 
OnInvalidation(const syncer::TopicInvalidationMap & new_invalidations)50   void OnInvalidation(
51       const syncer::TopicInvalidationMap& new_invalidations) override {
52     invalidation_received = true;
53   }
54 
OnDetailedStatus(const base::DictionaryValue & details)55   void OnDetailedStatus(const base::DictionaryValue& details) override {
56     detailed_status_received = true;
57   }
58 
59   bool registration_change_received;
60   bool state_received;
61   bool update_id_received;
62   bool debug_message_received;
63   bool invalidation_received;
64   bool detailed_status_received;
65   std::map<std::string, syncer::TopicCountMap> updated_topics_replicated;
66   std::multiset<std::string> registered_handlers;
67 };
68 
69 // Test that the callbacks are actually being called when observers are
70 // registered and don't produce any other callback in the meantime.
TEST(InvalidationLoggerTest,TestCallbacks)71 TEST(InvalidationLoggerTest, TestCallbacks) {
72   InvalidationLogger log;
73   InvalidationLoggerObserverTest observer_test;
74 
75   log.RegisterObserver(&observer_test);
76   log.OnStateChange(syncer::INVALIDATIONS_ENABLED);
77   EXPECT_TRUE(observer_test.state_received);
78   EXPECT_FALSE(observer_test.update_id_received);
79   EXPECT_FALSE(observer_test.registration_change_received);
80   EXPECT_FALSE(observer_test.invalidation_received);
81   EXPECT_FALSE(observer_test.debug_message_received);
82   EXPECT_FALSE(observer_test.detailed_status_received);
83 
84   observer_test.ResetStates();
85 
86   log.OnInvalidation(syncer::TopicInvalidationMap());
87   EXPECT_TRUE(observer_test.invalidation_received);
88   EXPECT_FALSE(observer_test.state_received);
89   EXPECT_FALSE(observer_test.update_id_received);
90   EXPECT_FALSE(observer_test.registration_change_received);
91   EXPECT_FALSE(observer_test.debug_message_received);
92   EXPECT_FALSE(observer_test.detailed_status_received);
93 
94   log.UnregisterObserver(&observer_test);
95 }
96 
97 // Test that after registering an observer and then unregistering it
98 // no callbacks regarding that observer are called.
99 // (i.e. the observer is cleanly removed)
TEST(InvalidationLoggerTest,TestReleaseOfObserver)100 TEST(InvalidationLoggerTest, TestReleaseOfObserver) {
101   InvalidationLogger log;
102   InvalidationLoggerObserverTest observer_test;
103 
104   log.RegisterObserver(&observer_test);
105   log.UnregisterObserver(&observer_test);
106 
107   log.OnInvalidation(syncer::TopicInvalidationMap());
108   log.OnStateChange(syncer::INVALIDATIONS_ENABLED);
109   log.OnRegistration(std::string());
110   log.OnUnregistration(std::string());
111   log.OnDebugMessage(base::DictionaryValue());
112   log.OnUpdatedTopics(std::map<std::string, syncer::Topics>());
113   EXPECT_FALSE(observer_test.registration_change_received);
114   EXPECT_FALSE(observer_test.update_id_received);
115   EXPECT_FALSE(observer_test.invalidation_received);
116   EXPECT_FALSE(observer_test.state_received);
117   EXPECT_FALSE(observer_test.debug_message_received);
118   EXPECT_FALSE(observer_test.detailed_status_received);
119 }
120 
121 // Test the EmitContet in InvalidationLogger is actually
122 // sending state and updateIds notifications.
TEST(InvalidationLoggerTest,TestEmitContent)123 TEST(InvalidationLoggerTest, TestEmitContent) {
124   InvalidationLogger log;
125   InvalidationLoggerObserverTest observer_test;
126 
127   log.RegisterObserver(&observer_test);
128   EXPECT_FALSE(observer_test.state_received);
129   EXPECT_FALSE(observer_test.update_id_received);
130   log.EmitContent();
131   // Expect state and registered handlers only because no Ids were registered.
132   EXPECT_TRUE(observer_test.state_received);
133   EXPECT_TRUE(observer_test.registration_change_received);
134   EXPECT_FALSE(observer_test.update_id_received);
135   EXPECT_FALSE(observer_test.invalidation_received);
136   EXPECT_FALSE(observer_test.debug_message_received);
137   EXPECT_FALSE(observer_test.detailed_status_received);
138 
139   observer_test.ResetStates();
140   std::map<std::string, syncer::Topics> test_map;
141   test_map["Test"] = syncer::Topics();
142   log.OnUpdatedTopics(test_map);
143   EXPECT_TRUE(observer_test.update_id_received);
144   observer_test.ResetStates();
145 
146   log.EmitContent();
147   // Expect now state, ids and registered handlers change.
148   EXPECT_TRUE(observer_test.state_received);
149   EXPECT_TRUE(observer_test.update_id_received);
150   EXPECT_TRUE(observer_test.registration_change_received);
151   EXPECT_FALSE(observer_test.invalidation_received);
152   EXPECT_FALSE(observer_test.debug_message_received);
153   EXPECT_FALSE(observer_test.detailed_status_received);
154   log.UnregisterObserver(&observer_test);
155 }
156 
157 // Test that the OnUpdatedTopics() notification actually sends the same Topic
158 // that was sent to the Observer.
159 // The ObserverTest rebuilds the map that was sent in pieces by the logger.
TEST(InvalidationLoggerTest,TestUpdatedTopicsMap)160 TEST(InvalidationLoggerTest, TestUpdatedTopicsMap) {
161   InvalidationLogger log;
162   InvalidationLoggerObserverTest observer_test;
163   std::map<std::string, syncer::Topics> send_test_map;
164   std::map<std::string, syncer::TopicCountMap> expected_received_map;
165   log.RegisterObserver(&observer_test);
166 
167   syncer::Topics topics_a;
168   syncer::TopicCountMap topics_counts_a;
169 
170   syncer::Topic t1 = "Topic1";
171   topics_a.emplace(t1, syncer::TopicMetadata{/*is_public=*/false});
172   topics_counts_a[t1] = 0;
173 
174   syncer::Topic t2 = "Topic2";
175   topics_a.emplace(t2, syncer::TopicMetadata{/*is_public=*/false});
176   topics_counts_a[t2] = 0;
177 
178   syncer::Topics topics_b;
179   syncer::TopicCountMap topics_counts_b;
180 
181   syncer::Topic t3 = "Topic3";
182   topics_b.emplace(t3, syncer::TopicMetadata{/*is_public=*/false});
183   topics_counts_b[t3] = 0;
184 
185   send_test_map["TestA"] = topics_a;
186   send_test_map["TestB"] = topics_b;
187   expected_received_map["TestA"] = topics_counts_a;
188   expected_received_map["TestB"] = topics_counts_b;
189 
190   // Send the topics registered for the two different handler name.
191   log.OnUpdatedTopics(send_test_map);
192   EXPECT_EQ(expected_received_map, observer_test.updated_topics_replicated);
193 
194   syncer::Topics topics_b2;
195   syncer::TopicCountMap topics_counts_b2;
196 
197   syncer::Topic t4 = "Topic4";
198   topics_b2.emplace(t4, syncer::TopicMetadata{/*is_public=*/false});
199   topics_counts_b2[t4] = 0;
200 
201   syncer::Topic t5 = "Topic5";
202   topics_b2.emplace(t5, syncer::TopicMetadata{/*is_public=*/false});
203   topics_counts_b2[t5] = 0;
204 
205   send_test_map["TestB"] = topics_b2;
206   expected_received_map["TestB"] = topics_counts_b2;
207 
208   // Test now that if we replace the registered topics for TestB, the
209   // original don't show up again.
210   log.OnUpdatedTopics(send_test_map);
211   EXPECT_EQ(expected_received_map, observer_test.updated_topics_replicated);
212 
213   // The emit content should return the same map too.
214   observer_test.ResetStates();
215   log.EmitContent();
216   EXPECT_EQ(expected_received_map, observer_test.updated_topics_replicated);
217   log.UnregisterObserver(&observer_test);
218 }
219 
220 // Test that the invalidation notification changes the total count
221 // of invalidations received for that datatype.
TEST(InvalidationLoggerTest,TestInvalidtionsTotalCount)222 TEST(InvalidationLoggerTest, TestInvalidtionsTotalCount) {
223   InvalidationLogger log;
224   InvalidationLoggerObserverTest observer_test;
225   log.RegisterObserver(&observer_test);
226 
227   std::map<std::string, syncer::Topics> send_test_map;
228   std::map<std::string, syncer::TopicCountMap> expected_received_map;
229   syncer::Topics topics;
230   syncer::TopicCountMap topics_counts;
231 
232   syncer::Topic t1 = "Topic1";
233   topics.emplace(t1, syncer::TopicMetadata{/*is_public=*/false});
234   topics_counts[t1] = 1;
235 
236   // Generate invalidation for |t1| only.
237   syncer::TopicInvalidationMap fake_invalidations;
238   fake_invalidations.Insert(syncer::Invalidation::InitUnknownVersion(t1));
239 
240   syncer::Topic t2 = "Topic2";
241   topics.emplace(t2, syncer::TopicMetadata{/*is_public=*/false});
242   topics_counts[t2] = 0;
243 
244   // Register the two Topics and send an invalidation only for |t1|.
245   send_test_map["Test"] = topics;
246   log.OnUpdatedTopics(send_test_map);
247   log.OnInvalidation(fake_invalidations);
248 
249   expected_received_map["Test"] = topics_counts;
250 
251   // Reset the state of the observer to receive the Topics with the count of
252   // invalidations received (1 and 0).
253   observer_test.ResetStates();
254   log.EmitContent();
255   EXPECT_EQ(expected_received_map, observer_test.updated_topics_replicated);
256 
257   log.UnregisterObserver(&observer_test);
258 }
259 
260 // Test that registered handlers are being sent to the observers.
TEST(InvalidationLoggerTest,TestRegisteredHandlers)261 TEST(InvalidationLoggerTest, TestRegisteredHandlers) {
262   InvalidationLogger log;
263   InvalidationLoggerObserverTest observer_test;
264   log.RegisterObserver(&observer_test);
265 
266   log.OnRegistration(std::string("FakeHandler1"));
267   std::multiset<std::string> test_multiset;
268   test_multiset.insert("FakeHandler1");
269   EXPECT_TRUE(observer_test.registration_change_received);
270   EXPECT_EQ(observer_test.registered_handlers, test_multiset);
271 
272   observer_test.ResetStates();
273   log.OnRegistration(std::string("FakeHandler2"));
274   test_multiset.insert("FakeHandler2");
275   EXPECT_TRUE(observer_test.registration_change_received);
276   EXPECT_EQ(observer_test.registered_handlers, test_multiset);
277 
278   observer_test.ResetStates();
279   log.OnUnregistration(std::string("FakeHandler2"));
280   test_multiset.erase("FakeHandler2");
281   EXPECT_TRUE(observer_test.registration_change_received);
282   EXPECT_EQ(observer_test.registered_handlers, test_multiset);
283 
284   log.UnregisterObserver(&observer_test);
285 }
286 }  // namespace invalidation
287