// Copyright 2014 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.
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "components/invalidation/fake_invalidation_handler.h"
#include "components/invalidation/invalidator_registrar.h"
#include "components/invalidation/invalidator_test_template.h"
#include "google/cacheinvalidation/types.pb.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace syncer {
namespace {
// We test InvalidatorRegistrar by wrapping it in an Invalidator and
// running the usual Invalidator tests.
// Thin Invalidator wrapper around InvalidatorRegistrar.
class RegistrarInvalidator : public Invalidator {
public:
RegistrarInvalidator() {}
virtual ~RegistrarInvalidator() {}
InvalidatorRegistrar* GetRegistrar() {
return ®istrar_;
}
// Invalidator implementation.
virtual void RegisterHandler(InvalidationHandler* handler) OVERRIDE {
registrar_.RegisterHandler(handler);
}
virtual void UpdateRegisteredIds(InvalidationHandler* handler,
const ObjectIdSet& ids) OVERRIDE {
registrar_.UpdateRegisteredIds(handler, ids);
}
virtual void UnregisterHandler(InvalidationHandler* handler) OVERRIDE {
registrar_.UnregisterHandler(handler);
}
virtual InvalidatorState GetInvalidatorState() const OVERRIDE {
return registrar_.GetInvalidatorState();
}
virtual void UpdateCredentials(
const std::string& email, const std::string& token) OVERRIDE {
// Do nothing.
}
virtual void RequestDetailedStatus(
base::Callback<void(const base::DictionaryValue&)> call) const OVERRIDE {
// Do nothing.
}
private:
InvalidatorRegistrar registrar_;
DISALLOW_COPY_AND_ASSIGN(RegistrarInvalidator);
};
class RegistrarInvalidatorTestDelegate {
public:
RegistrarInvalidatorTestDelegate() {}
~RegistrarInvalidatorTestDelegate() {
DestroyInvalidator();
}
void CreateInvalidator(
const std::string& invalidator_client_id,
const std::string& initial_state,
const base::WeakPtr<InvalidationStateTracker>&
invalidation_state_tracker) {
DCHECK(!invalidator_.get());
invalidator_.reset(new RegistrarInvalidator());
}
RegistrarInvalidator* GetInvalidator() {
return invalidator_.get();
}
void DestroyInvalidator() {
invalidator_.reset();
}
void WaitForInvalidator() {
// Do nothing.
}
void TriggerOnInvalidatorStateChange(InvalidatorState state) {
invalidator_->GetRegistrar()->UpdateInvalidatorState(state);
}
void TriggerOnIncomingInvalidation(
const ObjectIdInvalidationMap& invalidation_map) {
invalidator_->GetRegistrar()->DispatchInvalidationsToHandlers(
invalidation_map);
}
private:
scoped_ptr<RegistrarInvalidator> invalidator_;
};
INSTANTIATE_TYPED_TEST_CASE_P(
RegistrarInvalidatorTest, InvalidatorTest,
RegistrarInvalidatorTestDelegate);
class InvalidatorRegistrarTest : public testing::Test {};
// Technically the tests below can be part of InvalidatorTest, but we
// want to keep the number of death tests down.
// When we expect a death via CHECK(), we can't match against the
// CHECK() message since they are removed in official builds.
#if GTEST_HAS_DEATH_TEST
// Having registered handlers on destruction should cause a CHECK.
TEST_F(InvalidatorRegistrarTest, RegisteredHandlerOnDestruction) {
scoped_ptr<InvalidatorRegistrar> registrar(new InvalidatorRegistrar());
FakeInvalidationHandler handler;
registrar->RegisterHandler(&handler);
EXPECT_DEATH({ registrar.reset(); }, "");
ASSERT_TRUE(registrar.get());
registrar->UnregisterHandler(&handler);
}
// Multiple registrations by different handlers on the same object ID should
// cause a CHECK.
TEST_F(InvalidatorRegistrarTest, MultipleRegistration) {
const invalidation::ObjectId id1(ipc::invalidation::ObjectSource::TEST, "a");
const invalidation::ObjectId id2(ipc::invalidation::ObjectSource::TEST, "a");
InvalidatorRegistrar registrar;
FakeInvalidationHandler handler1;
registrar.RegisterHandler(&handler1);
FakeInvalidationHandler handler2;
registrar.RegisterHandler(&handler2);
ObjectIdSet ids;
ids.insert(id1);
ids.insert(id2);
registrar.UpdateRegisteredIds(&handler1, ids);
registrar.DetachFromThreadForTest();
EXPECT_DEATH({ registrar.UpdateRegisteredIds(&handler2, ids); }, "");
registrar.UnregisterHandler(&handler2);
registrar.UnregisterHandler(&handler1);
}
#endif // GTEST_HAS_DEATH_TEST
} // namespace
} // namespace syncer