blob: 951a5aa89aee2e4960a37ded58caf1712c41b528 [file] [log] [blame]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/performance_manager/public/graph/graph_registered.h"
#include <memory>
#include <utility>
#include "base/test/gtest_util.h"
#include "components/performance_manager/performance_manager_registry_impl.h"
#include "components/performance_manager/public/graph/graph.h"
#include "components/performance_manager/public/performance_manager.h"
#include "components/performance_manager/test_support/graph_test_harness.h"
#include "components/performance_manager/test_support/performance_manager_test_harness.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace performance_manager {
using GraphRegisteredTest = GraphTestHarness;
class Foo : public GraphRegisteredImpl<Foo> {
public:
Foo() = default;
~Foo() override = default;
};
class Bar : public GraphRegisteredImpl<Bar> {
public:
Bar() = default;
~Bar() override = default;
};
// A GraphOwnedAndRegistered that doesn't override OnPassedToGraph and
// OnTakenFromGraph.
class OwnedFoo final : public GraphOwnedAndRegistered<OwnedFoo> {
public:
OwnedFoo() = default;
~OwnedFoo() final = default;
};
// A GraphOwnedAndRegistered that overrides OnPassedToGraph and
// OnTakenFromGraph.
class OwnedBar final : public GraphOwnedAndRegistered<OwnedBar> {
public:
OwnedBar() = default;
~OwnedBar() final = default;
void OnPassedToGraph(Graph* graph) final { on_passed_called_ = true; }
void OnTakenFromGraph(Graph* graph) final { on_taken_called_ = true; }
bool on_passed_called() const { return on_passed_called_; }
bool on_taken_called() const { return on_taken_called_; }
private:
bool on_passed_called_ = false;
bool on_taken_called_ = false;
};
TEST_F(GraphRegisteredTest, GraphRegistrationWorks) {
// This ensures that the templated distinct TypeId generation works.
ASSERT_NE(Foo::TypeId(), Bar::TypeId());
EXPECT_FALSE(graph()->GetRegisteredObject(Foo::TypeId()));
EXPECT_FALSE(graph()->GetRegisteredObjectAs<Foo>());
EXPECT_FALSE(graph()->GetRegisteredObject(Bar::TypeId()));
EXPECT_FALSE(graph()->GetRegisteredObjectAs<Bar>());
// Insertion works.
Foo foo;
graph()->RegisterObject(&foo);
EXPECT_EQ(&foo, graph()->GetRegisteredObject(Foo::TypeId()));
EXPECT_EQ(&foo, graph()->GetRegisteredObjectAs<Foo>());
EXPECT_FALSE(graph()->GetRegisteredObject(Bar::TypeId()));
EXPECT_FALSE(graph()->GetRegisteredObjectAs<Bar>());
// Inserting again fails.
EXPECT_CHECK_DEATH(graph()->RegisterObject(&foo));
// Unregistered the wrong object fails.
Foo foo2;
EXPECT_CHECK_DEATH(graph()->UnregisterObject(&foo2));
// Unregistering works.
graph()->UnregisterObject(&foo);
EXPECT_FALSE(graph()->GetRegisteredObject(Foo::TypeId()));
EXPECT_FALSE(graph()->GetRegisteredObjectAs<Foo>());
EXPECT_FALSE(graph()->GetRegisteredObject(Bar::TypeId()));
EXPECT_FALSE(graph()->GetRegisteredObjectAs<Bar>());
// Unregistering again fails.
EXPECT_CHECK_DEATH(graph()->UnregisterObject(&foo));
EXPECT_CHECK_DEATH(graph()->UnregisterObject(&foo2));
// Registering multiple objects works.
Bar bar;
graph()->RegisterObject(&foo);
graph()->RegisterObject(&bar);
EXPECT_EQ(&foo, graph()->GetRegisteredObject(Foo::TypeId()));
EXPECT_EQ(&foo, graph()->GetRegisteredObjectAs<Foo>());
EXPECT_EQ(&bar, graph()->GetRegisteredObject(Bar::TypeId()));
EXPECT_EQ(&bar, graph()->GetRegisteredObjectAs<Bar>());
// Check the various helper functions.
EXPECT_EQ(&foo, Foo::GetFromGraph(graph()));
EXPECT_EQ(&bar, Bar::GetFromGraph(graph()));
EXPECT_TRUE(foo.IsRegistered(graph()));
EXPECT_TRUE(bar.IsRegistered(graph()));
EXPECT_FALSE(Foo::NothingRegistered(graph()));
EXPECT_FALSE(Bar::NothingRegistered(graph()));
graph()->UnregisterObject(&bar);
EXPECT_EQ(&foo, Foo::GetFromGraph(graph()));
EXPECT_FALSE(Bar::GetFromGraph(graph()));
EXPECT_TRUE(foo.IsRegistered(graph()));
EXPECT_FALSE(bar.IsRegistered(graph()));
EXPECT_FALSE(Foo::NothingRegistered(graph()));
EXPECT_TRUE(Bar::NothingRegistered(graph()));
// At this point if the graph is torn down it should explode because foo
// hasn't been unregistered.
EXPECT_CHECK_DEATH(TearDownAndDestroyGraph());
graph()->UnregisterObject(&foo);
}
TEST_F(GraphRegisteredTest, GraphOwnedAndRegistered) {
// Insertion works.
EXPECT_FALSE(graph()->GetRegisteredObjectAs<OwnedFoo>());
auto unique_foo = std::make_unique<OwnedFoo>();
EXPECT_EQ(unique_foo->GetOwningGraph(), nullptr);
OwnedFoo* foo = graph()->PassToGraph(std::move(unique_foo));
EXPECT_EQ(foo, graph()->GetRegisteredObjectAs<OwnedFoo>());
EXPECT_EQ(foo->GetOwningGraph(), graph());
EXPECT_FALSE(graph()->GetRegisteredObjectAs<OwnedBar>());
auto unique_bar = std::make_unique<OwnedBar>();
EXPECT_EQ(unique_bar->GetOwningGraph(), nullptr);
OwnedBar* bar = graph()->PassToGraph(std::move(unique_bar));
EXPECT_EQ(bar, graph()->GetRegisteredObjectAs<OwnedBar>());
EXPECT_TRUE(bar->on_passed_called());
EXPECT_EQ(bar->GetOwningGraph(), graph());
// Inserting again fails.
EXPECT_CHECK_DEATH(graph()->RegisterObject(foo));
EXPECT_CHECK_DEATH(graph()->PassToGraph(std::make_unique<OwnedFoo>()));
// Unregistering works.
std::unique_ptr<OwnedFoo> unique_foo2 =
graph()->TakeFromGraphAs<OwnedFoo>(foo);
EXPECT_EQ(foo, unique_foo2.get());
EXPECT_EQ(nullptr, graph()->GetRegisteredObjectAs<OwnedFoo>());
EXPECT_EQ(foo->GetOwningGraph(), nullptr);
std::unique_ptr<OwnedBar> unique_bar2 =
graph()->TakeFromGraphAs<OwnedBar>(bar);
EXPECT_EQ(bar, unique_bar2.get());
EXPECT_EQ(nullptr, graph()->GetRegisteredObjectAs<OwnedBar>());
EXPECT_TRUE(bar->on_taken_called());
EXPECT_EQ(bar->GetOwningGraph(), nullptr);
// Unregistering again fails.
EXPECT_CHECK_DEATH(graph()->UnregisterObject(foo));
// Passing back an object that was taken should re-register it.
graph()->PassToGraph(std::move(unique_foo2));
EXPECT_EQ(foo, graph()->GetRegisteredObjectAs<OwnedFoo>());
EXPECT_EQ(foo->GetOwningGraph(), graph());
// At this point the graph can be safely torn down because
// GraphOwnedAndRegistered objects will be deleted and unregistered.
TearDownAndDestroyGraph();
}
} // namespace performance_manager