// Copyright 2015 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 "components/scheduler/renderer/render_widget_signals.h" #include "base/macros.h" #include "components/scheduler/renderer/render_widget_scheduling_state.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" using testing::AnyNumber; using testing::Mock; using testing::_; namespace scheduler { namespace { class MockObserver : public RenderWidgetSignals::Observer { public: MockObserver() {} virtual ~MockObserver() {} MOCK_METHOD1(SetAllRenderWidgetsHidden, void(bool hidden)); MOCK_METHOD1(SetHasVisibleRenderWidgetWithTouchHandler, void(bool has_visible_render_widget_with_touch_handler)); private: DISALLOW_COPY_AND_ASSIGN(MockObserver); }; } class RenderWidgetSignalsTest : public testing::Test { public: RenderWidgetSignalsTest() {} ~RenderWidgetSignalsTest() override {} void SetUp() override { mock_observer_.reset(new MockObserver()); render_widget_signals_.reset(new RenderWidgetSignals(mock_observer_.get())); } void IgnoreWidgetCreationCallbacks() { EXPECT_CALL(*mock_observer_, SetAllRenderWidgetsHidden(false)) .Times(AnyNumber()); } void IgnoreWidgetDestructionCallbacks() { EXPECT_CALL(*mock_observer_, SetAllRenderWidgetsHidden(true)) .Times(AnyNumber()); } scoped_ptr mock_observer_; scoped_ptr render_widget_signals_; }; TEST_F(RenderWidgetSignalsTest, RenderWidgetSchedulingStateLifeCycle) { EXPECT_CALL(*mock_observer_, SetAllRenderWidgetsHidden(false)).Times(1); scoped_ptr widget1_state = render_widget_signals_->NewRenderWidgetSchedulingState(); Mock::VerifyAndClearExpectations(mock_observer_.get()); EXPECT_CALL(*mock_observer_, SetAllRenderWidgetsHidden(true)).Times(1); } TEST_F(RenderWidgetSignalsTest, RenderWidget_Hidden) { IgnoreWidgetCreationCallbacks(); scoped_ptr widget1_state = render_widget_signals_->NewRenderWidgetSchedulingState(); Mock::VerifyAndClearExpectations(mock_observer_.get()); EXPECT_CALL(*mock_observer_, SetAllRenderWidgetsHidden(true)).Times(1); widget1_state->SetHidden(true); Mock::VerifyAndClearExpectations(mock_observer_.get()); IgnoreWidgetDestructionCallbacks(); } TEST_F(RenderWidgetSignalsTest, RenderWidget_HiddenThreeTimesShownOnce) { IgnoreWidgetCreationCallbacks(); scoped_ptr widget1_state = render_widget_signals_->NewRenderWidgetSchedulingState(); Mock::VerifyAndClearExpectations(mock_observer_.get()); EXPECT_CALL(*mock_observer_, SetAllRenderWidgetsHidden(true)).Times(1); widget1_state->SetHidden(true); widget1_state->SetHidden(true); widget1_state->SetHidden(true); Mock::VerifyAndClearExpectations(mock_observer_.get()); EXPECT_CALL(*mock_observer_, SetAllRenderWidgetsHidden(false)).Times(1); widget1_state->SetHidden(false); Mock::VerifyAndClearExpectations(mock_observer_.get()); IgnoreWidgetDestructionCallbacks(); } TEST_F(RenderWidgetSignalsTest, MultipleRenderWidgetsBecomeHiddenThenVisible) { IgnoreWidgetCreationCallbacks(); scoped_ptr widget1_state = render_widget_signals_->NewRenderWidgetSchedulingState(); scoped_ptr widget2_state = render_widget_signals_->NewRenderWidgetSchedulingState(); scoped_ptr widget3_state = render_widget_signals_->NewRenderWidgetSchedulingState(); Mock::VerifyAndClearExpectations(mock_observer_.get()); // Widgets are initially assumed to be visible so start hiding them, we should // not get any calls to SetAllRenderWidgetsHidden till the last one is hidden. EXPECT_CALL(*mock_observer_, SetAllRenderWidgetsHidden(_)).Times(0); widget1_state->SetHidden(true); widget2_state->SetHidden(true); Mock::VerifyAndClearExpectations(mock_observer_.get()); EXPECT_CALL(*mock_observer_, SetAllRenderWidgetsHidden(true)).Times(1); widget3_state->SetHidden(true); Mock::VerifyAndClearExpectations(mock_observer_.get()); // We should get a call back once the first widget is unhidden and no more // after that. EXPECT_CALL(*mock_observer_, SetAllRenderWidgetsHidden(false)).Times(1); widget1_state->SetHidden(false); Mock::VerifyAndClearExpectations(mock_observer_.get()); EXPECT_CALL(*mock_observer_, SetAllRenderWidgetsHidden(_)).Times(0); widget2_state->SetHidden(false); widget3_state->SetHidden(false); Mock::VerifyAndClearExpectations(mock_observer_.get()); IgnoreWidgetDestructionCallbacks(); } TEST_F(RenderWidgetSignalsTest, TouchHandlerAddedAndRemoved_VisibleWidget) { IgnoreWidgetCreationCallbacks(); scoped_ptr widget_state = render_widget_signals_->NewRenderWidgetSchedulingState(); Mock::VerifyAndClearExpectations(mock_observer_.get()); EXPECT_CALL(*mock_observer_, SetHasVisibleRenderWidgetWithTouchHandler(true)) .Times(1); widget_state->SetHasTouchHandler(true); Mock::VerifyAndClearExpectations(mock_observer_.get()); EXPECT_CALL(*mock_observer_, SetHasVisibleRenderWidgetWithTouchHandler(false)) .Times(1); widget_state->SetHasTouchHandler(false); Mock::VerifyAndClearExpectations(mock_observer_.get()); IgnoreWidgetDestructionCallbacks(); } TEST_F(RenderWidgetSignalsTest, TouchHandlerAddedThriceAndRemovedOnce_VisibleWidget) { IgnoreWidgetCreationCallbacks(); scoped_ptr widget_state = render_widget_signals_->NewRenderWidgetSchedulingState(); Mock::VerifyAndClearExpectations(mock_observer_.get()); EXPECT_CALL(*mock_observer_, SetHasVisibleRenderWidgetWithTouchHandler(true)) .Times(1); widget_state->SetHasTouchHandler(true); widget_state->SetHasTouchHandler(true); widget_state->SetHasTouchHandler(true); Mock::VerifyAndClearExpectations(mock_observer_.get()); EXPECT_CALL(*mock_observer_, SetHasVisibleRenderWidgetWithTouchHandler(false)) .Times(1); widget_state->SetHasTouchHandler(false); Mock::VerifyAndClearExpectations(mock_observer_.get()); IgnoreWidgetDestructionCallbacks(); } TEST_F(RenderWidgetSignalsTest, TouchHandlerAddedAndRemoved_HiddenWidget) { IgnoreWidgetCreationCallbacks(); scoped_ptr widget_state = render_widget_signals_->NewRenderWidgetSchedulingState(); EXPECT_CALL(*mock_observer_, SetAllRenderWidgetsHidden(true)).Times(1); widget_state->SetHidden(true); Mock::VerifyAndClearExpectations(mock_observer_.get()); EXPECT_CALL(*mock_observer_, SetHasVisibleRenderWidgetWithTouchHandler(_)) .Times(0); widget_state->SetHasTouchHandler(true); widget_state->SetHasTouchHandler(false); Mock::VerifyAndClearExpectations(mock_observer_.get()); IgnoreWidgetDestructionCallbacks(); } TEST_F(RenderWidgetSignalsTest, MultipleTouchHandlerAddedAndRemoved_VisibleWidgets) { IgnoreWidgetCreationCallbacks(); scoped_ptr widget1_state = render_widget_signals_->NewRenderWidgetSchedulingState(); scoped_ptr widget2_state = render_widget_signals_->NewRenderWidgetSchedulingState(); scoped_ptr widget3_state = render_widget_signals_->NewRenderWidgetSchedulingState(); Mock::VerifyAndClearExpectations(mock_observer_.get()); // We should only get a callback for the first widget with a touch handler. EXPECT_CALL(*mock_observer_, SetHasVisibleRenderWidgetWithTouchHandler(true)) .Times(1); widget1_state->SetHasTouchHandler(true); Mock::VerifyAndClearExpectations(mock_observer_.get()); EXPECT_CALL(*mock_observer_, SetHasVisibleRenderWidgetWithTouchHandler(_)) .Times(0); widget2_state->SetHasTouchHandler(true); widget3_state->SetHasTouchHandler(true); Mock::VerifyAndClearExpectations(mock_observer_.get()); // We should only get a callback when the last touch handler is removed. EXPECT_CALL(*mock_observer_, SetHasVisibleRenderWidgetWithTouchHandler(_)) .Times(0); widget1_state->SetHasTouchHandler(false); widget2_state->SetHasTouchHandler(false); Mock::VerifyAndClearExpectations(mock_observer_.get()); EXPECT_CALL(*mock_observer_, SetHasVisibleRenderWidgetWithTouchHandler(false)) .Times(1); widget3_state->SetHasTouchHandler(false); Mock::VerifyAndClearExpectations(mock_observer_.get()); IgnoreWidgetDestructionCallbacks(); } TEST_F(RenderWidgetSignalsTest, TouchHandlerAddedThenWigetDeleted_VisibleWidget) { IgnoreWidgetCreationCallbacks(); scoped_ptr widget_state = render_widget_signals_->NewRenderWidgetSchedulingState(); Mock::VerifyAndClearExpectations(mock_observer_.get()); EXPECT_CALL(*mock_observer_, SetHasVisibleRenderWidgetWithTouchHandler(true)) .Times(1); widget_state->SetHasTouchHandler(true); Mock::VerifyAndClearExpectations(mock_observer_.get()); EXPECT_CALL(*mock_observer_, SetHasVisibleRenderWidgetWithTouchHandler(false)) .Times(1); IgnoreWidgetDestructionCallbacks(); } TEST_F(RenderWidgetSignalsTest, TouchHandlerAddedThenWigetDeleted_HiddenWidget) { IgnoreWidgetCreationCallbacks(); scoped_ptr widget_state = render_widget_signals_->NewRenderWidgetSchedulingState(); EXPECT_CALL(*mock_observer_, SetAllRenderWidgetsHidden(true)).Times(1); widget_state->SetHidden(true); Mock::VerifyAndClearExpectations(mock_observer_.get()); EXPECT_CALL(*mock_observer_, SetHasVisibleRenderWidgetWithTouchHandler(_)) .Times(0); IgnoreWidgetDestructionCallbacks(); } } // namespace scheduler