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

Unified Diff: chrome/browser/invalidation/invalidation_frontend_test_template.h

Issue 13991017: Commit InvalidationService implementations (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Another attempt to fix Android Created 7 years, 7 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: chrome/browser/invalidation/invalidation_frontend_test_template.h
diff --git a/chrome/browser/invalidation/invalidation_frontend_test_template.h b/chrome/browser/invalidation/invalidation_frontend_test_template.h
new file mode 100644
index 0000000000000000000000000000000000000000..9643504d4000438ac19d5e5489517e28a8129453
--- /dev/null
+++ b/chrome/browser/invalidation/invalidation_frontend_test_template.h
@@ -0,0 +1,384 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This class defines tests that implementations of InvalidationFrontend should
+// pass in order to be conformant. Here's how you use it to test your
+// implementation.
+//
+// Say your class is called MyInvalidationFrontend. Then you need to define a
+// class called MyInvalidationFrontendTestDelegate in
+// my_invalidation_frontend_unittest.cc like this:
+//
+// class MyInvalidationFrontendTestDelegate {
+// public:
+// MyInvalidationFrontendTestDelegate() ...
+//
+// ~MyInvalidationFrontendTestDelegate() {
+// // DestroyInvalidator() may not be explicitly called by tests.
+// DestroyInvalidator();
+// }
+//
+// // Create the InvalidationFrontend implementation with the given params.
+// void CreateInvalidationFrontend() {
+// ...
+// }
+//
+// // Should return the InvalidationFrontend implementation. Only called
+// // after CreateInvalidator and before DestroyInvalidator.
+// MyInvalidationFrontend* GetInvalidationFrontend() {
+// ...
+// }
+//
+// // Destroy the InvalidationFrontend implementation.
+// void DestroyInvalidationFrontend() {
+// ...
+// }
+//
+// // The Trigger* functions below should block until the effects of
+// // the call are visible on the current thread.
+//
+// // Should cause OnInvalidatorStateChange() to be called on all
+// // observers of the InvalidationFrontend implementation with the given
+// // parameters.
+// void TriggerOnInvalidatorStateChange(InvalidatorState state) {
+// ...
+// }
+//
+// // Should cause OnIncomingInvalidation() to be called on all
+// // observers of the InvalidationFrontend implementation with the given
+// // parameters.
+// void TriggerOnIncomingInvalidation(
+// const ObjectIdInvalidationMap& invalidation_map) {
+// ...
+// }
+// };
+//
+// The InvalidationFrontendTest test harness will have a member variable of
+// this delegate type and will call its functions in the various
+// tests.
+//
+// Then you simply #include this file as well as gtest.h and add the
+// following statement to my_sync_notifier_unittest.cc:
+//
+// INSTANTIATE_TYPED_TEST_CASE_P(
+// MyInvalidationFrontend,
+// InvalidationFrontendTest,
+// MyInvalidatorTestDelegate);
+//
+// Easy!
+
+#ifndef CHROME_BROWSER_INVALIDATION_INVALIDATION_FRONTEND_TEST_TEMPLATE_H_
+#define CHROME_BROWSER_INVALIDATION_INVALIDATION_FRONTEND_TEST_TEMPLATE_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "chrome/browser/invalidation/invalidation_frontend.h"
+#include "google/cacheinvalidation/include/types.h"
+#include "google/cacheinvalidation/types.pb.h"
+#include "sync/notifier/fake_invalidation_handler.h"
+#include "sync/notifier/object_id_invalidation_map.h"
+#include "sync/notifier/object_id_invalidation_map_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+template <typename InvalidatorTestDelegate>
+class InvalidationFrontendTest : public testing::Test {
+ protected:
+ // Note: The IDs defined below must be valid. Otherwise they won't make it
+ // through the round-trip to ModelTypeInvalidationMap and back that the
+ // AndroidInvalidation test requires.
+ InvalidationFrontendTest()
+ : id1(ipc::invalidation::ObjectSource::CHROME_SYNC, "BOOKMARK"),
+ id2(ipc::invalidation::ObjectSource::CHROME_SYNC, "PREFERENCE"),
+ id3(ipc::invalidation::ObjectSource::CHROME_SYNC, "AUTOFILL"),
+ id4(ipc::invalidation::ObjectSource::CHROME_SYNC, "EXPERIMENTS") {
+ }
+
+ invalidation::InvalidationFrontend*
+ CreateAndInitializeInvalidationFrontend() {
+ this->delegate_.CreateInvalidationFrontend();
+ return this->delegate_.GetInvalidationFrontend();
+ }
+
+ InvalidatorTestDelegate delegate_;
+
+ const invalidation::ObjectId id1;
+ const invalidation::ObjectId id2;
+ const invalidation::ObjectId id3;
+ const invalidation::ObjectId id4;
+};
+
+TYPED_TEST_CASE_P(InvalidationFrontendTest);
+
+// Initialize the invalidator, register a handler, register some IDs for that
+// handler, and then unregister the handler, dispatching invalidations in
+// between. The handler should only see invalidations when its registered and
+// its IDs are registered.
+TYPED_TEST_P(InvalidationFrontendTest, Basic) {
+ invalidation::InvalidationFrontend* const invalidator =
+ this->CreateAndInitializeInvalidationFrontend();
+
+ syncer::FakeInvalidationHandler handler;
+
+ invalidator->RegisterInvalidationHandler(&handler);
+
+ syncer::ObjectIdInvalidationMap states;
+ states[this->id1].payload = "1";
+ states[this->id2].payload = "2";
+ states[this->id3].payload = "3";
+
+ // Should be ignored since no IDs are registered to |handler|.
+ this->delegate_.TriggerOnIncomingInvalidation(states);
+ EXPECT_EQ(0, handler.GetInvalidationCount());
+
+ syncer::ObjectIdSet ids;
+ ids.insert(this->id1);
+ ids.insert(this->id2);
+ invalidator->UpdateRegisteredInvalidationIds(&handler, ids);
+
+ this->delegate_.TriggerOnInvalidatorStateChange(
+ syncer::INVALIDATIONS_ENABLED);
+ EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler.GetInvalidatorState());
+
+ syncer::ObjectIdInvalidationMap expected_states;
+ expected_states[this->id1].payload = "1";
+ expected_states[this->id2].payload = "2";
+
+ this->delegate_.TriggerOnIncomingInvalidation(states);
+ EXPECT_EQ(1, handler.GetInvalidationCount());
+ EXPECT_THAT(expected_states, Eq(handler.GetLastInvalidationMap()));
+
+ ids.erase(this->id1);
+ ids.insert(this->id3);
+ invalidator->UpdateRegisteredInvalidationIds(&handler, ids);
+
+ expected_states.erase(this->id1);
+ expected_states[this->id3].payload = "3";
+
+ // Removed object IDs should not be notified, newly-added ones should.
+ this->delegate_.TriggerOnIncomingInvalidation(states);
+ EXPECT_EQ(2, handler.GetInvalidationCount());
+ EXPECT_THAT(expected_states, Eq(handler.GetLastInvalidationMap()));
+
+ this->delegate_.TriggerOnInvalidatorStateChange(
+ syncer::TRANSIENT_INVALIDATION_ERROR);
+ EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
+ handler.GetInvalidatorState());
+
+ this->delegate_.TriggerOnInvalidatorStateChange(
+ syncer::INVALIDATION_CREDENTIALS_REJECTED);
+ EXPECT_EQ(syncer::INVALIDATION_CREDENTIALS_REJECTED,
+ handler.GetInvalidatorState());
+
+ invalidator->UnregisterInvalidationHandler(&handler);
+
+ // Should be ignored since |handler| isn't registered anymore.
+ this->delegate_.TriggerOnIncomingInvalidation(states);
+ EXPECT_EQ(2, handler.GetInvalidationCount());
+}
+
+// Register handlers and some IDs for those handlers, register a handler with
+// no IDs, and register a handler with some IDs but unregister it. Then,
+// dispatch some invalidations and invalidations. Handlers that are registered
+// should get invalidations, and the ones that have registered IDs should
+// receive invalidations for those IDs.
+TYPED_TEST_P(InvalidationFrontendTest, MultipleHandlers) {
+ invalidation::InvalidationFrontend* const invalidator =
+ this->CreateAndInitializeInvalidationFrontend();
+
+ syncer::FakeInvalidationHandler handler1;
+ syncer::FakeInvalidationHandler handler2;
+ syncer::FakeInvalidationHandler handler3;
+ syncer::FakeInvalidationHandler handler4;
+
+ invalidator->RegisterInvalidationHandler(&handler1);
+ invalidator->RegisterInvalidationHandler(&handler2);
+ invalidator->RegisterInvalidationHandler(&handler3);
+ invalidator->RegisterInvalidationHandler(&handler4);
+
+ {
+ syncer::ObjectIdSet ids;
+ ids.insert(this->id1);
+ ids.insert(this->id2);
+ invalidator->UpdateRegisteredInvalidationIds(&handler1, ids);
+ }
+
+ {
+ syncer::ObjectIdSet ids;
+ ids.insert(this->id3);
+ invalidator->UpdateRegisteredInvalidationIds(&handler2, ids);
+ }
+
+ // Don't register any IDs for handler3.
+
+ {
+ syncer::ObjectIdSet ids;
+ ids.insert(this->id4);
+ invalidator->UpdateRegisteredInvalidationIds(&handler4, ids);
+ }
+
+ invalidator->UnregisterInvalidationHandler(&handler4);
+
+ this->delegate_.TriggerOnInvalidatorStateChange(
+ syncer::INVALIDATIONS_ENABLED);
+ EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler1.GetInvalidatorState());
+ EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler2.GetInvalidatorState());
+ EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler3.GetInvalidatorState());
+ EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
+ handler4.GetInvalidatorState());
+
+ {
+ syncer::ObjectIdInvalidationMap states;
+ states[this->id1].payload = "1";
+ states[this->id2].payload = "2";
+ states[this->id3].payload = "3";
+ states[this->id4].payload = "4";
+ this->delegate_.TriggerOnIncomingInvalidation(states);
+
+ syncer::ObjectIdInvalidationMap expected_states;
+ expected_states[this->id1].payload = "1";
+ expected_states[this->id2].payload = "2";
+
+ EXPECT_EQ(1, handler1.GetInvalidationCount());
+ EXPECT_THAT(expected_states, Eq(handler1.GetLastInvalidationMap()));
+
+ expected_states.clear();
+ expected_states[this->id3].payload = "3";
+
+ EXPECT_EQ(1, handler2.GetInvalidationCount());
+ EXPECT_THAT(expected_states, Eq(handler2.GetLastInvalidationMap()));
+
+ EXPECT_EQ(0, handler3.GetInvalidationCount());
+ EXPECT_EQ(0, handler4.GetInvalidationCount());
+ }
+
+ this->delegate_.TriggerOnInvalidatorStateChange(
+ syncer::TRANSIENT_INVALIDATION_ERROR);
+ EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
+ handler1.GetInvalidatorState());
+ EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
+ handler2.GetInvalidatorState());
+ EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
+ handler3.GetInvalidatorState());
+ EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
+ handler4.GetInvalidatorState());
+
+ invalidator->UnregisterInvalidationHandler(&handler3);
+ invalidator->UnregisterInvalidationHandler(&handler2);
+ invalidator->UnregisterInvalidationHandler(&handler1);
+}
+
+// Make sure that passing an empty set to UpdateRegisteredInvalidationIds clears
+// the corresponding entries for the handler.
+TYPED_TEST_P(InvalidationFrontendTest, EmptySetUnregisters) {
+ invalidation::InvalidationFrontend* const invalidator =
+ this->CreateAndInitializeInvalidationFrontend();
+
+ syncer::FakeInvalidationHandler handler1;
+
+ // Control observer.
+ syncer::FakeInvalidationHandler handler2;
+
+ invalidator->RegisterInvalidationHandler(&handler1);
+ invalidator->RegisterInvalidationHandler(&handler2);
+
+ {
+ syncer::ObjectIdSet ids;
+ ids.insert(this->id1);
+ ids.insert(this->id2);
+ invalidator->UpdateRegisteredInvalidationIds(&handler1, ids);
+ }
+
+ {
+ syncer::ObjectIdSet ids;
+ ids.insert(this->id3);
+ invalidator->UpdateRegisteredInvalidationIds(&handler2, ids);
+ }
+
+ // Unregister the IDs for the first observer. It should not receive any
+ // further invalidations.
+ invalidator->UpdateRegisteredInvalidationIds(&handler1,
+ syncer::ObjectIdSet());
+
+ this->delegate_.TriggerOnInvalidatorStateChange(
+ syncer::INVALIDATIONS_ENABLED);
+ EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler1.GetInvalidatorState());
+ EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler2.GetInvalidatorState());
+
+ {
+ syncer::ObjectIdInvalidationMap states;
+ states[this->id1].payload = "1";
+ states[this->id2].payload = "2";
+ states[this->id3].payload = "3";
+ this->delegate_.TriggerOnIncomingInvalidation(states);
+ EXPECT_EQ(0, handler1.GetInvalidationCount());
+ EXPECT_EQ(1, handler2.GetInvalidationCount());
+ }
+
+ this->delegate_.TriggerOnInvalidatorStateChange(
+ syncer::TRANSIENT_INVALIDATION_ERROR);
+ EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
+ handler1.GetInvalidatorState());
+ EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
+ handler2.GetInvalidatorState());
+
+ invalidator->UnregisterInvalidationHandler(&handler2);
+ invalidator->UnregisterInvalidationHandler(&handler1);
+}
+
+namespace internal {
+
+// A FakeInvalidationHandler that is "bound" to a specific
+// InvalidationFrontend. This is for cross-referencing state information with
+// the bound InvalidationFrontend.
+class BoundFakeInvalidationHandler : public syncer::FakeInvalidationHandler {
+ public:
+ explicit BoundFakeInvalidationHandler(
+ const invalidation::InvalidationFrontend& invalidator);
+ virtual ~BoundFakeInvalidationHandler();
+
+ // Returns the last return value of GetInvalidatorState() on the
+ // bound invalidator from the last time the invalidator state
+ // changed.
+ syncer::InvalidatorState GetLastRetrievedState() const;
+
+ // InvalidationHandler implementation.
+ virtual void OnInvalidatorStateChange(
+ syncer::InvalidatorState state) OVERRIDE;
+
+ private:
+ const invalidation::InvalidationFrontend& invalidator_;
+ syncer::InvalidatorState last_retrieved_state_;
+
+ DISALLOW_COPY_AND_ASSIGN(BoundFakeInvalidationHandler);
+};
+
+} // namespace internal
+
+TYPED_TEST_P(InvalidationFrontendTest, GetInvalidatorStateAlwaysCurrent) {
+ invalidation::InvalidationFrontend* const invalidator =
+ this->CreateAndInitializeInvalidationFrontend();
+
+ internal::BoundFakeInvalidationHandler handler(*invalidator);
+ invalidator->RegisterInvalidationHandler(&handler);
+
+ this->delegate_.TriggerOnInvalidatorStateChange(
+ syncer::INVALIDATIONS_ENABLED);
+ EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler.GetInvalidatorState());
+ EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler.GetLastRetrievedState());
+
+ this->delegate_.TriggerOnInvalidatorStateChange(
+ syncer::TRANSIENT_INVALIDATION_ERROR);
+ EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
+ handler.GetInvalidatorState());
+ EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
+ handler.GetLastRetrievedState());
+
+ invalidator->UnregisterInvalidationHandler(&handler);
+}
+
+REGISTER_TYPED_TEST_CASE_P(InvalidationFrontendTest,
+ Basic, MultipleHandlers, EmptySetUnregisters,
+ GetInvalidatorStateAlwaysCurrent);
+
+#endif // CHROME_BROWSER_INVALIDATION_INVALIDATION_FRONTEND_TEST_TEMPLATE_H_

Powered by Google App Engine
This is Rietveld 408576698