OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 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 <string> |
| 6 #include <utility> |
| 7 |
| 8 #include "base/memory/ptr_util.h" |
| 9 #include "base/process/process_handle.h" |
| 10 #include "base/run_loop.h" |
| 11 #include "services/resource_coordinator/coordination_unit/coordination_unit_fact
ory.h" |
| 12 #include "services/resource_coordinator/coordination_unit/coordination_unit_grap
h_observer.h" |
| 13 #include "services/resource_coordinator/coordination_unit/coordination_unit_impl
.h" |
| 14 #include "services/resource_coordinator/coordination_unit/coordination_unit_impl
_unittest_util.h" |
| 15 #include "services/resource_coordinator/coordination_unit/coordination_unit_mana
ger.h" |
| 16 #include "services/resource_coordinator/public/cpp/coordination_unit_id.h" |
| 17 #include "services/resource_coordinator/public/cpp/coordination_unit_types.h" |
| 18 #include "services/resource_coordinator/public/interfaces/coordination_unit.mojo
m.h" |
| 19 #include "testing/gtest/include/gtest/gtest.h" |
| 20 |
| 21 namespace resource_coordinator { |
| 22 |
| 23 namespace { |
| 24 |
| 25 class CoordinationUnitGraphObserverTest : public CoordinationUnitImplTestBase { |
| 26 }; |
| 27 |
| 28 class TestBasicAPICoordinationUnitGraphObserver |
| 29 : public CoordinationUnitGraphObserver { |
| 30 public: |
| 31 TestBasicAPICoordinationUnitGraphObserver() |
| 32 : TestBasicAPICoordinationUnitGraphObserver( |
| 33 CoordinationUnitType::kInvalidType) {} |
| 34 |
| 35 void OnCoordinationUnitCreated( |
| 36 CoordinationUnitImpl* coordination_unit) override { |
| 37 ++on_coordination_unit_created_invocations_; |
| 38 |
| 39 coordination_unit->on_add_child_event_listeners().AddListener(base::Bind( |
| 40 &TestBasicAPICoordinationUnitGraphObserver::OnAddChildListenerInvoked, |
| 41 base::Unretained(this))); |
| 42 coordination_unit->on_add_parent_event_listeners().AddListener(base::Bind( |
| 43 &TestBasicAPICoordinationUnitGraphObserver::OnAddParentListenerInvoked, |
| 44 base::Unretained(this))); |
| 45 coordination_unit->on_property_changed_event_listeners().AddListener( |
| 46 base::Bind(&TestBasicAPICoordinationUnitGraphObserver:: |
| 47 OnPropertyChangedListenerInvoked, |
| 48 base::Unretained(this))); |
| 49 coordination_unit->on_remove_child_event_listeners().AddListener( |
| 50 base::Bind(&TestBasicAPICoordinationUnitGraphObserver:: |
| 51 OnRemoveChildListenerInvoked, |
| 52 base::Unretained(this))); |
| 53 coordination_unit->on_remove_parent_event_listeners().AddListener( |
| 54 base::Bind(&TestBasicAPICoordinationUnitGraphObserver:: |
| 55 OnRemoveParentListenerInvoked, |
| 56 base::Unretained(this))); |
| 57 coordination_unit->on_will_be_destroyed_event_listeners().AddListener( |
| 58 base::Bind(&TestBasicAPICoordinationUnitGraphObserver:: |
| 59 OnWillBeDestroyedListenerInvoked, |
| 60 base::Unretained(this))); |
| 61 } |
| 62 |
| 63 size_t on_add_child_listener_invocations() { |
| 64 return on_add_child_listener_invocations_; |
| 65 } |
| 66 size_t on_add_parent_listener_invocations() { |
| 67 return on_add_parent_listener_invocations_; |
| 68 } |
| 69 size_t on_coordination_unit_created_invocations() { |
| 70 return on_coordination_unit_created_invocations_; |
| 71 } |
| 72 size_t on_property_changed_listener_invocations() { |
| 73 return on_property_changed_listener_invocations_; |
| 74 } |
| 75 size_t on_remove_child_listener_invocations() { |
| 76 return on_remove_child_listener_invocations_; |
| 77 } |
| 78 size_t on_remove_parent_listener_invocations() { |
| 79 return on_remove_parent_listener_invocations_; |
| 80 } |
| 81 size_t on_will_be_destroyed_listener_invocations() { |
| 82 return on_will_be_destroyed_listener_invocations_; |
| 83 } |
| 84 |
| 85 void OnAddChildListenerInvoked( |
| 86 const CoordinationUnitImpl* coordination_unit, |
| 87 const CoordinationUnitImpl* child_coordination_unit) { |
| 88 ++on_add_child_listener_invocations_; |
| 89 } |
| 90 void OnAddParentListenerInvoked( |
| 91 const CoordinationUnitImpl* coordination_unit, |
| 92 const CoordinationUnitImpl* parent_coordination_unit) { |
| 93 ++on_add_parent_listener_invocations_; |
| 94 } |
| 95 void OnPropertyChangedListenerInvoked( |
| 96 const CoordinationUnitImpl* coordination_unit, |
| 97 mojom::PropertyType property) { |
| 98 ++on_property_changed_listener_invocations_; |
| 99 } |
| 100 void OnRemoveChildListenerInvoked( |
| 101 const CoordinationUnitImpl* coordination_unit, |
| 102 const CoordinationUnitImpl* former_child_coordination_unit) { |
| 103 ++on_remove_child_listener_invocations_; |
| 104 } |
| 105 void OnRemoveParentListenerInvoked( |
| 106 const CoordinationUnitImpl* coordination_unit, |
| 107 const CoordinationUnitImpl* former_parent_coordination_unit) { |
| 108 ++on_remove_parent_listener_invocations_; |
| 109 } |
| 110 void OnWillBeDestroyedListenerInvoked( |
| 111 const CoordinationUnitImpl* coordination_unit) { |
| 112 ++on_will_be_destroyed_listener_invocations_; |
| 113 } |
| 114 |
| 115 protected: |
| 116 explicit TestBasicAPICoordinationUnitGraphObserver( |
| 117 CoordinationUnitType filter) |
| 118 : CoordinationUnitGraphObserver(filter), |
| 119 on_add_child_listener_invocations_(0u), |
| 120 on_add_parent_listener_invocations_(0u), |
| 121 on_coordination_unit_created_invocations_(0u), |
| 122 on_property_changed_listener_invocations_(0u), |
| 123 on_remove_child_listener_invocations_(0u), |
| 124 on_remove_parent_listener_invocations_(0u), |
| 125 on_will_be_destroyed_listener_invocations_(0u) {} |
| 126 |
| 127 size_t on_add_child_listener_invocations_; |
| 128 size_t on_add_parent_listener_invocations_; |
| 129 size_t on_coordination_unit_created_invocations_; |
| 130 size_t on_property_changed_listener_invocations_; |
| 131 size_t on_remove_child_listener_invocations_; |
| 132 size_t on_remove_parent_listener_invocations_; |
| 133 size_t on_will_be_destroyed_listener_invocations_; |
| 134 }; |
| 135 |
| 136 class TestFilterAPICoordinationUnitGraphObserver |
| 137 : public TestBasicAPICoordinationUnitGraphObserver { |
| 138 public: |
| 139 explicit TestFilterAPICoordinationUnitGraphObserver( |
| 140 CoordinationUnitType filter) |
| 141 : TestBasicAPICoordinationUnitGraphObserver(filter) {} |
| 142 |
| 143 void OnCoordinationUnitCreated( |
| 144 CoordinationUnitImpl* coordination_unit) override { |
| 145 ++on_coordination_unit_created_invocations_; |
| 146 |
| 147 coordination_unit->on_add_child_event_listeners().AddListener( |
| 148 base::Bind(&TestBasicAPICoordinationUnitGraphObserver:: |
| 149 OnAddChildListenerInvoked, |
| 150 base::Unretained(this)), |
| 151 CoordinationUnitType::kFrame); |
| 152 coordination_unit->on_add_parent_event_listeners().AddListener( |
| 153 base::Bind(&TestBasicAPICoordinationUnitGraphObserver:: |
| 154 OnAddParentListenerInvoked, |
| 155 base::Unretained(this)), |
| 156 CoordinationUnitType::kProcess); |
| 157 // TODO(matthalp) Use property mojom::PropertyType enum once it is created. |
| 158 // Currently the only enum is mojom::PropertyType::kTest which is mean to |
| 159 // be filtered out in the test this observer class is used in. |
| 160 coordination_unit->on_property_changed_event_listeners().AddListener( |
| 161 base::Bind(&TestBasicAPICoordinationUnitGraphObserver:: |
| 162 OnPropertyChangedListenerInvoked, |
| 163 base::Unretained(this)), |
| 164 static_cast<mojom::PropertyType>(1)); |
| 165 coordination_unit->on_remove_child_event_listeners().AddListener( |
| 166 base::Bind(&TestBasicAPICoordinationUnitGraphObserver:: |
| 167 OnRemoveChildListenerInvoked, |
| 168 base::Unretained(this)), |
| 169 CoordinationUnitType::kNavigation); |
| 170 coordination_unit->on_remove_parent_event_listeners().AddListener( |
| 171 base::Bind(&TestBasicAPICoordinationUnitGraphObserver:: |
| 172 OnRemoveParentListenerInvoked, |
| 173 base::Unretained(this)), |
| 174 CoordinationUnitType::kWebContents); |
| 175 coordination_unit->on_will_be_destroyed_event_listeners().AddListener( |
| 176 base::Bind(&TestBasicAPICoordinationUnitGraphObserver:: |
| 177 OnWillBeDestroyedListenerInvoked, |
| 178 base::Unretained(this))); |
| 179 } |
| 180 }; |
| 181 |
| 182 } // namespace |
| 183 |
| 184 TEST_F(CoordinationUnitGraphObserverTest, CallbacksInvokedNoFilters) { |
| 185 TestBasicAPICoordinationUnitGraphObserver* observer = |
| 186 new TestBasicAPICoordinationUnitGraphObserver(); |
| 187 |
| 188 // The observer will be deleted after this test executes when the |
| 189 // CoordinationUnitManager object goes out of scope and destructs. |
| 190 coordination_unit_manager()->RegisterObserver( |
| 191 std::unique_ptr<TestBasicAPICoordinationUnitGraphObserver>(observer)); |
| 192 |
| 193 // The CoordinationUnit types are intentionally different to make |
| 194 // sure filtering, which is not disabled, does not occur. |
| 195 CoordinationUnitID parent_cu_id(CoordinationUnitType::kWebContents, |
| 196 std::string()); |
| 197 CoordinationUnitID child_cu_id(CoordinationUnitType::kFrame, std::string()); |
| 198 |
| 199 std::unique_ptr<CoordinationUnitImpl> parent_coordination_unit = |
| 200 coordination_unit_factory::CreateCoordinationUnit( |
| 201 parent_cu_id, service_context_ref_factory()->CreateRef()); |
| 202 std::unique_ptr<CoordinationUnitImpl> child_coordination_unit = |
| 203 coordination_unit_factory::CreateCoordinationUnit( |
| 204 child_cu_id, service_context_ref_factory()->CreateRef()); |
| 205 |
| 206 coordination_unit_manager()->NotifyObserversCoordinationUnitCreated( |
| 207 parent_coordination_unit.get()); |
| 208 coordination_unit_manager()->NotifyObserversCoordinationUnitCreated( |
| 209 child_coordination_unit.get()); |
| 210 |
| 211 parent_coordination_unit->AddChild(child_coordination_unit->id()); |
| 212 parent_coordination_unit->RemoveChild(child_coordination_unit->id()); |
| 213 |
| 214 parent_coordination_unit->SetProperty(mojom::PropertyType::kTest, |
| 215 base::Value(42)); |
| 216 |
| 217 child_coordination_unit->WillBeDestroyed(); |
| 218 parent_coordination_unit->WillBeDestroyed(); |
| 219 |
| 220 EXPECT_EQ(2u, observer->on_coordination_unit_created_invocations()); |
| 221 EXPECT_EQ(1u, observer->on_add_child_listener_invocations()); |
| 222 EXPECT_EQ(1u, observer->on_add_parent_listener_invocations()); |
| 223 EXPECT_EQ(1u, observer->on_property_changed_listener_invocations()); |
| 224 EXPECT_EQ(1u, observer->on_remove_child_listener_invocations()); |
| 225 EXPECT_EQ(1u, observer->on_remove_parent_listener_invocations()); |
| 226 EXPECT_EQ(2u, observer->on_will_be_destroyed_listener_invocations()); |
| 227 } |
| 228 |
| 229 TEST_F(CoordinationUnitGraphObserverTest, CallbacksInvokedWithoutFilters) { |
| 230 TestFilterAPICoordinationUnitGraphObserver* observer = |
| 231 new TestFilterAPICoordinationUnitGraphObserver( |
| 232 CoordinationUnitType::kFrame); |
| 233 coordination_unit_manager()->RegisterObserver( |
| 234 std::unique_ptr<TestFilterAPICoordinationUnitGraphObserver>(observer)); |
| 235 |
| 236 // The CoordinationUnit types are intentionally different to test |
| 237 // that filtering is working correctly. |
| 238 CoordinationUnitID process_cu_id(CoordinationUnitType::kProcess, |
| 239 std::string()); |
| 240 CoordinationUnitID tab_cu_id(CoordinationUnitType::kWebContents, |
| 241 std::string()); |
| 242 CoordinationUnitID root_frame_cu_id(CoordinationUnitType::kFrame, |
| 243 std::string()); |
| 244 CoordinationUnitID frame_cu_id(CoordinationUnitType::kFrame, std::string()); |
| 245 CoordinationUnitID navigation_cu_id(CoordinationUnitType::kNavigation, |
| 246 std::string()); |
| 247 |
| 248 std::unique_ptr<CoordinationUnitImpl> process_coordination_unit = |
| 249 coordination_unit_factory::CreateCoordinationUnit( |
| 250 process_cu_id, service_context_ref_factory()->CreateRef()); |
| 251 std::unique_ptr<CoordinationUnitImpl> tab_coordination_unit = |
| 252 coordination_unit_factory::CreateCoordinationUnit( |
| 253 tab_cu_id, service_context_ref_factory()->CreateRef()); |
| 254 std::unique_ptr<CoordinationUnitImpl> root_frame_coordination_unit = |
| 255 coordination_unit_factory::CreateCoordinationUnit( |
| 256 root_frame_cu_id, service_context_ref_factory()->CreateRef()); |
| 257 std::unique_ptr<CoordinationUnitImpl> frame_coordination_unit = |
| 258 coordination_unit_factory::CreateCoordinationUnit( |
| 259 frame_cu_id, service_context_ref_factory()->CreateRef()); |
| 260 std::unique_ptr<CoordinationUnitImpl> navigation_coordination_unit = |
| 261 coordination_unit_factory::CreateCoordinationUnit( |
| 262 navigation_cu_id, service_context_ref_factory()->CreateRef()); |
| 263 |
| 264 // Should only invoke the OnCoordinationUnitCreated listener for |
| 265 // the root_frame and frame CoordinationUnits because the observer |
| 266 // filter is set to CoordinationUnitType::kFrame. |
| 267 coordination_unit_manager()->NotifyObserversCoordinationUnitCreated( |
| 268 process_coordination_unit.get()); |
| 269 coordination_unit_manager()->NotifyObserversCoordinationUnitCreated( |
| 270 tab_coordination_unit.get()); |
| 271 coordination_unit_manager()->NotifyObserversCoordinationUnitCreated( |
| 272 root_frame_coordination_unit.get()); |
| 273 coordination_unit_manager()->NotifyObserversCoordinationUnitCreated( |
| 274 frame_coordination_unit.get()); |
| 275 coordination_unit_manager()->NotifyObserversCoordinationUnitCreated( |
| 276 navigation_coordination_unit.get()); |
| 277 |
| 278 // Test AddChild filtering. The AddChild filter for the frame |
| 279 // CoordinationUnit has been set to only execute when the child |
| 280 // is a CoordinationUnitType::kFrame so the callback will execute. |
| 281 root_frame_coordination_unit->AddChild(frame_coordination_unit->id()); |
| 282 // The child is CoordinationUnitType::kNavigation so the callback |
| 283 // should not be executed. The navigation Coordination Unit is not |
| 284 // actually a child of a frame in practice, but is being used here to |
| 285 // check filtering on OnAddChild. |
| 286 root_frame_coordination_unit->AddChild(navigation_coordination_unit->id()); |
| 287 |
| 288 // Test AddParent filtering. The AddParent filter for the frame |
| 289 // CoordinationUnit has been set to only execute when the parent |
| 290 // is a CoordinationUnitType::kProcess so the callback will execute. |
| 291 // Note that AddParent is called within Add child. |
| 292 process_coordination_unit->AddChild(root_frame_coordination_unit->id()); |
| 293 // The parent is CoordinationUnitType::kFrame so the callback |
| 294 // should not be executed. |
| 295 tab_coordination_unit->AddChild(root_frame_coordination_unit->id()); |
| 296 |
| 297 // Test RemoveChild filtering. The RemoveChild filter for the frame |
| 298 // CoordinationUnit has been set to only execute when the child |
| 299 // is a CoordinationUnitType::kFrame so the callback will execute. |
| 300 root_frame_coordination_unit->RemoveChild(frame_coordination_unit->id()); |
| 301 // The child is CoordinationUnitType::kNavigation so the callback |
| 302 // should not be executed. The navigation Coordination Unit is not |
| 303 // actually a child of a frame in practice, but is being used here to |
| 304 // check filtering on OnRemoveChild. |
| 305 root_frame_coordination_unit->RemoveChild(navigation_coordination_unit->id()); |
| 306 |
| 307 // Test RemoveParent filtering. The RemoveParent filter for the frame |
| 308 // CoordinationUnit has been set to only execute when the parent |
| 309 // is a CoordinationUnitType::kProcess so the callback will execute. |
| 310 // Note that RemoveParent is called within Remove child. |
| 311 process_coordination_unit->RemoveChild(root_frame_coordination_unit->id()); |
| 312 // The parent is CoordinationUnitType::kFrame so the callback |
| 313 // should not be executed. |
| 314 tab_coordination_unit->RemoveChild(root_frame_coordination_unit->id()); |
| 315 |
| 316 // TODO(matthalp) Implement this another SetProperty once an additional |
| 317 // mojom::PropertyType has been implemented so that the SetProperty |
| 318 // filtering API can be tested. |
| 319 root_frame_coordination_unit->SetProperty(mojom::PropertyType::kTest, |
| 320 base::Value(42)); |
| 321 |
| 322 process_coordination_unit->WillBeDestroyed(); |
| 323 tab_coordination_unit->WillBeDestroyed(); |
| 324 root_frame_coordination_unit->WillBeDestroyed(); |
| 325 frame_coordination_unit->WillBeDestroyed(); |
| 326 navigation_coordination_unit->WillBeDestroyed(); |
| 327 |
| 328 EXPECT_EQ(1u, observer->on_add_child_listener_invocations()); |
| 329 EXPECT_EQ(1u, observer->on_add_parent_listener_invocations()); |
| 330 EXPECT_EQ(2u, observer->on_coordination_unit_created_invocations()); |
| 331 EXPECT_EQ(0u, observer->on_property_changed_listener_invocations()); |
| 332 EXPECT_EQ(1u, observer->on_remove_child_listener_invocations()); |
| 333 EXPECT_EQ(1u, observer->on_remove_parent_listener_invocations()); |
| 334 EXPECT_EQ(2u, observer->on_will_be_destroyed_listener_invocations()); |
| 335 } |
| 336 |
| 337 } // namespace resource_coordinator |
OLD | NEW |