| Index: services/resource_coordinator/coordination_unit/coordination_unit_graph_observer_unittest.cc
|
| diff --git a/services/resource_coordinator/coordination_unit/coordination_unit_graph_observer_unittest.cc b/services/resource_coordinator/coordination_unit/coordination_unit_graph_observer_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..5fbcb57447de9812b9a85cec04061f15bca637a6
|
| --- /dev/null
|
| +++ b/services/resource_coordinator/coordination_unit/coordination_unit_graph_observer_unittest.cc
|
| @@ -0,0 +1,337 @@
|
| +// Copyright 2017 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 <string>
|
| +#include <utility>
|
| +
|
| +#include "base/memory/ptr_util.h"
|
| +#include "base/process/process_handle.h"
|
| +#include "base/run_loop.h"
|
| +#include "services/resource_coordinator/coordination_unit/coordination_unit_factory.h"
|
| +#include "services/resource_coordinator/coordination_unit/coordination_unit_graph_observer.h"
|
| +#include "services/resource_coordinator/coordination_unit/coordination_unit_impl.h"
|
| +#include "services/resource_coordinator/coordination_unit/coordination_unit_impl_unittest_util.h"
|
| +#include "services/resource_coordinator/coordination_unit/coordination_unit_manager.h"
|
| +#include "services/resource_coordinator/public/cpp/coordination_unit_id.h"
|
| +#include "services/resource_coordinator/public/cpp/coordination_unit_types.h"
|
| +#include "services/resource_coordinator/public/interfaces/coordination_unit.mojom.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +namespace resource_coordinator {
|
| +
|
| +namespace {
|
| +
|
| +class CoordinationUnitGraphObserverTest : public CoordinationUnitImplTestBase {
|
| +};
|
| +
|
| +class TestBasicAPICoordinationUnitGraphObserver
|
| + : public CoordinationUnitGraphObserver {
|
| + public:
|
| + TestBasicAPICoordinationUnitGraphObserver()
|
| + : TestBasicAPICoordinationUnitGraphObserver(
|
| + CoordinationUnitType::kInvalidType) {}
|
| +
|
| + void OnCoordinationUnitCreated(
|
| + CoordinationUnitImpl* coordination_unit) override {
|
| + ++on_coordination_unit_created_invocations_;
|
| +
|
| + coordination_unit->on_add_child_event_listeners().AddListener(base::Bind(
|
| + &TestBasicAPICoordinationUnitGraphObserver::OnAddChildListenerInvoked,
|
| + base::Unretained(this)));
|
| + coordination_unit->on_add_parent_event_listeners().AddListener(base::Bind(
|
| + &TestBasicAPICoordinationUnitGraphObserver::OnAddParentListenerInvoked,
|
| + base::Unretained(this)));
|
| + coordination_unit->on_property_changed_event_listeners().AddListener(
|
| + base::Bind(&TestBasicAPICoordinationUnitGraphObserver::
|
| + OnPropertyChangedListenerInvoked,
|
| + base::Unretained(this)));
|
| + coordination_unit->on_remove_child_event_listeners().AddListener(
|
| + base::Bind(&TestBasicAPICoordinationUnitGraphObserver::
|
| + OnRemoveChildListenerInvoked,
|
| + base::Unretained(this)));
|
| + coordination_unit->on_remove_parent_event_listeners().AddListener(
|
| + base::Bind(&TestBasicAPICoordinationUnitGraphObserver::
|
| + OnRemoveParentListenerInvoked,
|
| + base::Unretained(this)));
|
| + coordination_unit->on_will_be_destroyed_event_listeners().AddListener(
|
| + base::Bind(&TestBasicAPICoordinationUnitGraphObserver::
|
| + OnWillBeDestroyedListenerInvoked,
|
| + base::Unretained(this)));
|
| + }
|
| +
|
| + size_t on_add_child_listener_invocations() {
|
| + return on_add_child_listener_invocations_;
|
| + }
|
| + size_t on_add_parent_listener_invocations() {
|
| + return on_add_parent_listener_invocations_;
|
| + }
|
| + size_t on_coordination_unit_created_invocations() {
|
| + return on_coordination_unit_created_invocations_;
|
| + }
|
| + size_t on_property_changed_listener_invocations() {
|
| + return on_property_changed_listener_invocations_;
|
| + }
|
| + size_t on_remove_child_listener_invocations() {
|
| + return on_remove_child_listener_invocations_;
|
| + }
|
| + size_t on_remove_parent_listener_invocations() {
|
| + return on_remove_parent_listener_invocations_;
|
| + }
|
| + size_t on_will_be_destroyed_listener_invocations() {
|
| + return on_will_be_destroyed_listener_invocations_;
|
| + }
|
| +
|
| + void OnAddChildListenerInvoked(
|
| + const CoordinationUnitImpl* coordination_unit,
|
| + const CoordinationUnitImpl* child_coordination_unit) {
|
| + ++on_add_child_listener_invocations_;
|
| + }
|
| + void OnAddParentListenerInvoked(
|
| + const CoordinationUnitImpl* coordination_unit,
|
| + const CoordinationUnitImpl* parent_coordination_unit) {
|
| + ++on_add_parent_listener_invocations_;
|
| + }
|
| + void OnPropertyChangedListenerInvoked(
|
| + const CoordinationUnitImpl* coordination_unit,
|
| + mojom::PropertyType property) {
|
| + ++on_property_changed_listener_invocations_;
|
| + }
|
| + void OnRemoveChildListenerInvoked(
|
| + const CoordinationUnitImpl* coordination_unit,
|
| + const CoordinationUnitImpl* former_child_coordination_unit) {
|
| + ++on_remove_child_listener_invocations_;
|
| + }
|
| + void OnRemoveParentListenerInvoked(
|
| + const CoordinationUnitImpl* coordination_unit,
|
| + const CoordinationUnitImpl* former_parent_coordination_unit) {
|
| + ++on_remove_parent_listener_invocations_;
|
| + }
|
| + void OnWillBeDestroyedListenerInvoked(
|
| + const CoordinationUnitImpl* coordination_unit) {
|
| + ++on_will_be_destroyed_listener_invocations_;
|
| + }
|
| +
|
| + protected:
|
| + explicit TestBasicAPICoordinationUnitGraphObserver(
|
| + CoordinationUnitType filter)
|
| + : CoordinationUnitGraphObserver(filter),
|
| + on_add_child_listener_invocations_(0u),
|
| + on_add_parent_listener_invocations_(0u),
|
| + on_coordination_unit_created_invocations_(0u),
|
| + on_property_changed_listener_invocations_(0u),
|
| + on_remove_child_listener_invocations_(0u),
|
| + on_remove_parent_listener_invocations_(0u),
|
| + on_will_be_destroyed_listener_invocations_(0u) {}
|
| +
|
| + size_t on_add_child_listener_invocations_;
|
| + size_t on_add_parent_listener_invocations_;
|
| + size_t on_coordination_unit_created_invocations_;
|
| + size_t on_property_changed_listener_invocations_;
|
| + size_t on_remove_child_listener_invocations_;
|
| + size_t on_remove_parent_listener_invocations_;
|
| + size_t on_will_be_destroyed_listener_invocations_;
|
| +};
|
| +
|
| +class TestFilterAPICoordinationUnitGraphObserver
|
| + : public TestBasicAPICoordinationUnitGraphObserver {
|
| + public:
|
| + explicit TestFilterAPICoordinationUnitGraphObserver(
|
| + CoordinationUnitType filter)
|
| + : TestBasicAPICoordinationUnitGraphObserver(filter) {}
|
| +
|
| + void OnCoordinationUnitCreated(
|
| + CoordinationUnitImpl* coordination_unit) override {
|
| + ++on_coordination_unit_created_invocations_;
|
| +
|
| + coordination_unit->on_add_child_event_listeners().AddListener(
|
| + base::Bind(&TestBasicAPICoordinationUnitGraphObserver::
|
| + OnAddChildListenerInvoked,
|
| + base::Unretained(this)),
|
| + CoordinationUnitType::kFrame);
|
| + coordination_unit->on_add_parent_event_listeners().AddListener(
|
| + base::Bind(&TestBasicAPICoordinationUnitGraphObserver::
|
| + OnAddParentListenerInvoked,
|
| + base::Unretained(this)),
|
| + CoordinationUnitType::kProcess);
|
| + // TODO(matthalp) Use property mojom::PropertyType enum once it is created.
|
| + // Currently the only enum is mojom::PropertyType::kTest which is mean to
|
| + // be filtered out in the test this observer class is used in.
|
| + coordination_unit->on_property_changed_event_listeners().AddListener(
|
| + base::Bind(&TestBasicAPICoordinationUnitGraphObserver::
|
| + OnPropertyChangedListenerInvoked,
|
| + base::Unretained(this)),
|
| + static_cast<mojom::PropertyType>(1));
|
| + coordination_unit->on_remove_child_event_listeners().AddListener(
|
| + base::Bind(&TestBasicAPICoordinationUnitGraphObserver::
|
| + OnRemoveChildListenerInvoked,
|
| + base::Unretained(this)),
|
| + CoordinationUnitType::kNavigation);
|
| + coordination_unit->on_remove_parent_event_listeners().AddListener(
|
| + base::Bind(&TestBasicAPICoordinationUnitGraphObserver::
|
| + OnRemoveParentListenerInvoked,
|
| + base::Unretained(this)),
|
| + CoordinationUnitType::kWebContents);
|
| + coordination_unit->on_will_be_destroyed_event_listeners().AddListener(
|
| + base::Bind(&TestBasicAPICoordinationUnitGraphObserver::
|
| + OnWillBeDestroyedListenerInvoked,
|
| + base::Unretained(this)));
|
| + }
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +TEST_F(CoordinationUnitGraphObserverTest, CallbacksInvokedNoFilters) {
|
| + TestBasicAPICoordinationUnitGraphObserver* observer =
|
| + new TestBasicAPICoordinationUnitGraphObserver();
|
| +
|
| + // The observer will be deleted after this test executes when the
|
| + // CoordinationUnitManager object goes out of scope and destructs.
|
| + coordination_unit_manager()->RegisterObserver(
|
| + std::unique_ptr<TestBasicAPICoordinationUnitGraphObserver>(observer));
|
| +
|
| + // The CoordinationUnit types are intentionally different to make
|
| + // sure filtering, which is not disabled, does not occur.
|
| + CoordinationUnitID parent_cu_id(CoordinationUnitType::kWebContents,
|
| + std::string());
|
| + CoordinationUnitID child_cu_id(CoordinationUnitType::kFrame, std::string());
|
| +
|
| + std::unique_ptr<CoordinationUnitImpl> parent_coordination_unit =
|
| + coordination_unit_factory::CreateCoordinationUnit(
|
| + parent_cu_id, service_context_ref_factory()->CreateRef());
|
| + std::unique_ptr<CoordinationUnitImpl> child_coordination_unit =
|
| + coordination_unit_factory::CreateCoordinationUnit(
|
| + child_cu_id, service_context_ref_factory()->CreateRef());
|
| +
|
| + coordination_unit_manager()->NotifyObserversCoordinationUnitCreated(
|
| + parent_coordination_unit.get());
|
| + coordination_unit_manager()->NotifyObserversCoordinationUnitCreated(
|
| + child_coordination_unit.get());
|
| +
|
| + parent_coordination_unit->AddChild(child_coordination_unit->id());
|
| + parent_coordination_unit->RemoveChild(child_coordination_unit->id());
|
| +
|
| + parent_coordination_unit->SetProperty(mojom::PropertyType::kTest,
|
| + base::Value(42));
|
| +
|
| + child_coordination_unit->WillBeDestroyed();
|
| + parent_coordination_unit->WillBeDestroyed();
|
| +
|
| + EXPECT_EQ(2u, observer->on_coordination_unit_created_invocations());
|
| + EXPECT_EQ(1u, observer->on_add_child_listener_invocations());
|
| + EXPECT_EQ(1u, observer->on_add_parent_listener_invocations());
|
| + EXPECT_EQ(1u, observer->on_property_changed_listener_invocations());
|
| + EXPECT_EQ(1u, observer->on_remove_child_listener_invocations());
|
| + EXPECT_EQ(1u, observer->on_remove_parent_listener_invocations());
|
| + EXPECT_EQ(2u, observer->on_will_be_destroyed_listener_invocations());
|
| +}
|
| +
|
| +TEST_F(CoordinationUnitGraphObserverTest, CallbacksInvokedWithoutFilters) {
|
| + TestFilterAPICoordinationUnitGraphObserver* observer =
|
| + new TestFilterAPICoordinationUnitGraphObserver(
|
| + CoordinationUnitType::kFrame);
|
| + coordination_unit_manager()->RegisterObserver(
|
| + std::unique_ptr<TestFilterAPICoordinationUnitGraphObserver>(observer));
|
| +
|
| + // The CoordinationUnit types are intentionally different to test
|
| + // that filtering is working correctly.
|
| + CoordinationUnitID process_cu_id(CoordinationUnitType::kProcess,
|
| + std::string());
|
| + CoordinationUnitID tab_cu_id(CoordinationUnitType::kWebContents,
|
| + std::string());
|
| + CoordinationUnitID root_frame_cu_id(CoordinationUnitType::kFrame,
|
| + std::string());
|
| + CoordinationUnitID frame_cu_id(CoordinationUnitType::kFrame, std::string());
|
| + CoordinationUnitID navigation_cu_id(CoordinationUnitType::kNavigation,
|
| + std::string());
|
| +
|
| + std::unique_ptr<CoordinationUnitImpl> process_coordination_unit =
|
| + coordination_unit_factory::CreateCoordinationUnit(
|
| + process_cu_id, service_context_ref_factory()->CreateRef());
|
| + std::unique_ptr<CoordinationUnitImpl> tab_coordination_unit =
|
| + coordination_unit_factory::CreateCoordinationUnit(
|
| + tab_cu_id, service_context_ref_factory()->CreateRef());
|
| + std::unique_ptr<CoordinationUnitImpl> root_frame_coordination_unit =
|
| + coordination_unit_factory::CreateCoordinationUnit(
|
| + root_frame_cu_id, service_context_ref_factory()->CreateRef());
|
| + std::unique_ptr<CoordinationUnitImpl> frame_coordination_unit =
|
| + coordination_unit_factory::CreateCoordinationUnit(
|
| + frame_cu_id, service_context_ref_factory()->CreateRef());
|
| + std::unique_ptr<CoordinationUnitImpl> navigation_coordination_unit =
|
| + coordination_unit_factory::CreateCoordinationUnit(
|
| + navigation_cu_id, service_context_ref_factory()->CreateRef());
|
| +
|
| + // Should only invoke the OnCoordinationUnitCreated listener for
|
| + // the root_frame and frame CoordinationUnits because the observer
|
| + // filter is set to CoordinationUnitType::kFrame.
|
| + coordination_unit_manager()->NotifyObserversCoordinationUnitCreated(
|
| + process_coordination_unit.get());
|
| + coordination_unit_manager()->NotifyObserversCoordinationUnitCreated(
|
| + tab_coordination_unit.get());
|
| + coordination_unit_manager()->NotifyObserversCoordinationUnitCreated(
|
| + root_frame_coordination_unit.get());
|
| + coordination_unit_manager()->NotifyObserversCoordinationUnitCreated(
|
| + frame_coordination_unit.get());
|
| + coordination_unit_manager()->NotifyObserversCoordinationUnitCreated(
|
| + navigation_coordination_unit.get());
|
| +
|
| + // Test AddChild filtering. The AddChild filter for the frame
|
| + // CoordinationUnit has been set to only execute when the child
|
| + // is a CoordinationUnitType::kFrame so the callback will execute.
|
| + root_frame_coordination_unit->AddChild(frame_coordination_unit->id());
|
| + // The child is CoordinationUnitType::kNavigation so the callback
|
| + // should not be executed. The navigation Coordination Unit is not
|
| + // actually a child of a frame in practice, but is being used here to
|
| + // check filtering on OnAddChild.
|
| + root_frame_coordination_unit->AddChild(navigation_coordination_unit->id());
|
| +
|
| + // Test AddParent filtering. The AddParent filter for the frame
|
| + // CoordinationUnit has been set to only execute when the parent
|
| + // is a CoordinationUnitType::kProcess so the callback will execute.
|
| + // Note that AddParent is called within Add child.
|
| + process_coordination_unit->AddChild(root_frame_coordination_unit->id());
|
| + // The parent is CoordinationUnitType::kFrame so the callback
|
| + // should not be executed.
|
| + tab_coordination_unit->AddChild(root_frame_coordination_unit->id());
|
| +
|
| + // Test RemoveChild filtering. The RemoveChild filter for the frame
|
| + // CoordinationUnit has been set to only execute when the child
|
| + // is a CoordinationUnitType::kFrame so the callback will execute.
|
| + root_frame_coordination_unit->RemoveChild(frame_coordination_unit->id());
|
| + // The child is CoordinationUnitType::kNavigation so the callback
|
| + // should not be executed. The navigation Coordination Unit is not
|
| + // actually a child of a frame in practice, but is being used here to
|
| + // check filtering on OnRemoveChild.
|
| + root_frame_coordination_unit->RemoveChild(navigation_coordination_unit->id());
|
| +
|
| + // Test RemoveParent filtering. The RemoveParent filter for the frame
|
| + // CoordinationUnit has been set to only execute when the parent
|
| + // is a CoordinationUnitType::kProcess so the callback will execute.
|
| + // Note that RemoveParent is called within Remove child.
|
| + process_coordination_unit->RemoveChild(root_frame_coordination_unit->id());
|
| + // The parent is CoordinationUnitType::kFrame so the callback
|
| + // should not be executed.
|
| + tab_coordination_unit->RemoveChild(root_frame_coordination_unit->id());
|
| +
|
| + // TODO(matthalp) Implement this another SetProperty once an additional
|
| + // mojom::PropertyType has been implemented so that the SetProperty
|
| + // filtering API can be tested.
|
| + root_frame_coordination_unit->SetProperty(mojom::PropertyType::kTest,
|
| + base::Value(42));
|
| +
|
| + process_coordination_unit->WillBeDestroyed();
|
| + tab_coordination_unit->WillBeDestroyed();
|
| + root_frame_coordination_unit->WillBeDestroyed();
|
| + frame_coordination_unit->WillBeDestroyed();
|
| + navigation_coordination_unit->WillBeDestroyed();
|
| +
|
| + EXPECT_EQ(1u, observer->on_add_child_listener_invocations());
|
| + EXPECT_EQ(1u, observer->on_add_parent_listener_invocations());
|
| + EXPECT_EQ(2u, observer->on_coordination_unit_created_invocations());
|
| + EXPECT_EQ(0u, observer->on_property_changed_listener_invocations());
|
| + EXPECT_EQ(1u, observer->on_remove_child_listener_invocations());
|
| + EXPECT_EQ(1u, observer->on_remove_parent_listener_invocations());
|
| + EXPECT_EQ(2u, observer->on_will_be_destroyed_listener_invocations());
|
| +}
|
| +
|
| +} // namespace resource_coordinator
|
|
|