diff options
author | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2016-05-09 14:22:11 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2016-05-09 15:11:45 +0000 |
commit | 2ddb2d3e14eef3de7dbd0cef553d669b9ac2361c (patch) | |
tree | e75f511546c5fd1a173e87c1f9fb11d7ac8d1af3 /chromium/components/bubble/bubble_manager_unittest.cc | |
parent | a4f3d46271c57e8155ba912df46a05559d14726e (diff) | |
download | qtwebengine-chromium-2ddb2d3e14eef3de7dbd0cef553d669b9ac2361c.tar.gz |
BASELINE: Update Chromium to 51.0.2704.41
Also adds in all smaller components by reversing logic for exclusion.
Change-Id: Ibf90b506e7da088ea2f65dcf23f2b0992c504422
Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com>
Diffstat (limited to 'chromium/components/bubble/bubble_manager_unittest.cc')
-rw-r--r-- | chromium/components/bubble/bubble_manager_unittest.cc | 446 |
1 files changed, 446 insertions, 0 deletions
diff --git a/chromium/components/bubble/bubble_manager_unittest.cc b/chromium/components/bubble/bubble_manager_unittest.cc new file mode 100644 index 00000000000..625fe94ffe3 --- /dev/null +++ b/chromium/components/bubble/bubble_manager_unittest.cc @@ -0,0 +1,446 @@ +// 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/bubble/bubble_manager.h" + +#include <utility> + +#include "base/macros.h" +#include "components/bubble/bubble_controller.h" +#include "components/bubble/bubble_manager_mocks.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +// A "show chain" happens when a bubble decides to show another bubble on close. +// All bubbles must be iterated to handle a close event. If a bubble shows +// another bubble while it's being closed, the iterator can get messed up. +class ChainShowBubbleDelegate : public MockBubbleDelegate { + public: + // |chained_bubble| can be nullptr if not interested in getting a reference to + // the chained bubble. + ChainShowBubbleDelegate(BubbleManager* manager, + scoped_ptr<BubbleDelegate> delegate, + BubbleReference* chained_bubble) + : manager_(manager), + delegate_(std::move(delegate)), + chained_bubble_(chained_bubble), + closed_(false) { + EXPECT_CALL(*this, ShouldClose(testing::_)).WillOnce(testing::Return(true)); + } + + ~ChainShowBubbleDelegate() override { EXPECT_TRUE(closed_); } + + void DidClose(BubbleCloseReason reason) override { + MockBubbleDelegate::DidClose(reason); + BubbleReference ref = manager_->ShowBubble(std::move(delegate_)); + if (chained_bubble_) + *chained_bubble_ = ref; + closed_ = true; + } + + private: + BubbleManager* manager_; + scoped_ptr<BubbleDelegate> delegate_; + BubbleReference* chained_bubble_; + bool closed_; + + DISALLOW_COPY_AND_ASSIGN(ChainShowBubbleDelegate); +}; + +// A "close chain" happens when a close event is received while another close +// event is in progress. Ex: Closing the BubbleUi will hide the bubble, causing +// it to lose focus, which causes another close event. This test simulates this +// by sending a close event during the |DidClose| method of a BubbleDelegate. +// Similarly to the show chain, a close chain can mess up the iterator. +class ChainCloseBubbleDelegate : public MockBubbleDelegate { + public: + ChainCloseBubbleDelegate(BubbleManager* manager) : manager_(manager) {} + + ~ChainCloseBubbleDelegate() override {} + + void DidClose(BubbleCloseReason reason) override { + manager_->CloseAllBubbles(BUBBLE_CLOSE_FOCUS_LOST); + } + + private: + BubbleManager* manager_; + + DISALLOW_COPY_AND_ASSIGN(ChainCloseBubbleDelegate); +}; + +class MockBubbleManagerObserver : public BubbleManager::BubbleManagerObserver { + public: + MockBubbleManagerObserver() {} + ~MockBubbleManagerObserver() override {} + + MOCK_METHOD1(OnBubbleNeverShown, void(BubbleReference)); + MOCK_METHOD2(OnBubbleClosed, void(BubbleReference, BubbleCloseReason)); + + private: + DISALLOW_COPY_AND_ASSIGN(MockBubbleManagerObserver); +}; + +class BubbleManagerSubclass : public BubbleManager { + public: + using BubbleManager::CloseBubblesOwnedBy; +}; + +class BubbleManagerTest : public testing::Test { + public: + BubbleManagerTest(); + ~BubbleManagerTest() override {} + + void SetUp() override; + void TearDown() override; + + protected: + scoped_ptr<BubbleManagerSubclass> manager_; + + private: + DISALLOW_COPY_AND_ASSIGN(BubbleManagerTest); +}; + +BubbleManagerTest::BubbleManagerTest() {} + +void BubbleManagerTest::SetUp() { + testing::Test::SetUp(); + manager_.reset(new BubbleManagerSubclass); +} + +void BubbleManagerTest::TearDown() { + manager_.reset(); + testing::Test::TearDown(); +} + +TEST_F(BubbleManagerTest, ManagerShowsBubbleUi) { + scoped_ptr<MockBubbleDelegate> delegate = MockBubbleDelegate::Default(); + + MockBubbleUi* bubble_ui = delegate->bubble_ui(); + EXPECT_CALL(*bubble_ui, Destroyed()); + EXPECT_CALL(*bubble_ui, Show(testing::_)); + EXPECT_CALL(*bubble_ui, Close()); + EXPECT_CALL(*bubble_ui, UpdateAnchorPosition()).Times(0); + + manager_->ShowBubble(std::move(delegate)); +} + +TEST_F(BubbleManagerTest, ManagerUpdatesBubbleUiAnchor) { + scoped_ptr<MockBubbleDelegate> delegate = MockBubbleDelegate::Default(); + + MockBubbleUi* bubble_ui = delegate->bubble_ui(); + EXPECT_CALL(*bubble_ui, Destroyed()); + EXPECT_CALL(*bubble_ui, Show(testing::_)); + EXPECT_CALL(*bubble_ui, Close()); + EXPECT_CALL(*bubble_ui, UpdateAnchorPosition()); + + manager_->ShowBubble(std::move(delegate)); + manager_->UpdateAllBubbleAnchors(); +} + +TEST_F(BubbleManagerTest, CloseOnReferenceInvalidatesReference) { + BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Default()); + + ASSERT_TRUE(ref->CloseBubble(BUBBLE_CLOSE_FOCUS_LOST)); + + ASSERT_FALSE(ref); +} + +TEST_F(BubbleManagerTest, CloseOnStubbornReferenceDoesNotInvalidate) { + BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Stubborn()); + + ASSERT_FALSE(ref->CloseBubble(BUBBLE_CLOSE_FOCUS_LOST)); + + ASSERT_TRUE(ref); +} + +TEST_F(BubbleManagerTest, CloseInvalidatesReference) { + BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Default()); + + ASSERT_TRUE(manager_->CloseBubble(ref, BUBBLE_CLOSE_FOCUS_LOST)); + + ASSERT_FALSE(ref); +} + +TEST_F(BubbleManagerTest, CloseAllInvalidatesReference) { + BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Default()); + + manager_->CloseAllBubbles(BUBBLE_CLOSE_FOCUS_LOST); + + ASSERT_FALSE(ref); +} + +TEST_F(BubbleManagerTest, DestroyInvalidatesReference) { + BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Default()); + + manager_.reset(); + + ASSERT_FALSE(ref); +} + +TEST_F(BubbleManagerTest, CloseInvalidatesStubbornReference) { + BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Stubborn()); + + ASSERT_TRUE(manager_->CloseBubble(ref, BUBBLE_CLOSE_FORCED)); + + ASSERT_FALSE(ref); +} + +TEST_F(BubbleManagerTest, CloseAllInvalidatesStubbornReference) { + BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Stubborn()); + + manager_->CloseAllBubbles(BUBBLE_CLOSE_FORCED); + + ASSERT_FALSE(ref); +} + +TEST_F(BubbleManagerTest, DestroyInvalidatesStubbornReference) { + BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Stubborn()); + + manager_.reset(); + + ASSERT_FALSE(ref); +} + +TEST_F(BubbleManagerTest, CloseDoesNotInvalidateStubbornReference) { + BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Stubborn()); + + ASSERT_FALSE(manager_->CloseBubble(ref, BUBBLE_CLOSE_FOCUS_LOST)); + + ASSERT_TRUE(ref); +} + +TEST_F(BubbleManagerTest, CloseAllDoesNotInvalidateStubbornReference) { + BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Stubborn()); + + manager_->CloseAllBubbles(BUBBLE_CLOSE_FOCUS_LOST); + + ASSERT_TRUE(ref); +} + +TEST_F(BubbleManagerTest, CloseAllInvalidatesMixAppropriately) { + BubbleReference stubborn_ref1 = + manager_->ShowBubble(MockBubbleDelegate::Stubborn()); + BubbleReference normal_ref1 = + manager_->ShowBubble(MockBubbleDelegate::Default()); + BubbleReference stubborn_ref2 = + manager_->ShowBubble(MockBubbleDelegate::Stubborn()); + BubbleReference normal_ref2 = + manager_->ShowBubble(MockBubbleDelegate::Default()); + BubbleReference stubborn_ref3 = + manager_->ShowBubble(MockBubbleDelegate::Stubborn()); + BubbleReference normal_ref3 = + manager_->ShowBubble(MockBubbleDelegate::Default()); + + manager_->CloseAllBubbles(BUBBLE_CLOSE_FOCUS_LOST); + + ASSERT_TRUE(stubborn_ref1); + ASSERT_TRUE(stubborn_ref2); + ASSERT_TRUE(stubborn_ref3); + ASSERT_FALSE(normal_ref1); + ASSERT_FALSE(normal_ref2); + ASSERT_FALSE(normal_ref3); +} + +TEST_F(BubbleManagerTest, CloseBubbleShouldOnlylCloseSelf) { + BubbleReference ref1 = manager_->ShowBubble(MockBubbleDelegate::Default()); + BubbleReference ref2 = manager_->ShowBubble(MockBubbleDelegate::Default()); + BubbleReference ref3 = manager_->ShowBubble(MockBubbleDelegate::Default()); + + EXPECT_TRUE(ref1); + EXPECT_TRUE(ref2); + EXPECT_TRUE(ref3); + + ref2->CloseBubble(BUBBLE_CLOSE_FOCUS_LOST); + + EXPECT_TRUE(ref1); + EXPECT_FALSE(ref2); + EXPECT_TRUE(ref3); +} + +TEST_F(BubbleManagerTest, CloseOwnedByShouldLeaveUnowned) { + scoped_ptr<MockBubbleDelegate> delegate1 = MockBubbleDelegate::Default(); + scoped_ptr<MockBubbleDelegate> delegate2 = MockBubbleDelegate::Default(); + scoped_ptr<MockBubbleDelegate> delegate3 = MockBubbleDelegate::Default(); + MockBubbleDelegate& delegate1_ref = *delegate1; + MockBubbleDelegate& delegate2_ref = *delegate2; + MockBubbleDelegate& delegate3_ref = *delegate3; + BubbleReference ref1 = manager_->ShowBubble(std::move(delegate1)); + BubbleReference ref2 = manager_->ShowBubble(std::move(delegate2)); + BubbleReference ref3 = manager_->ShowBubble(std::move(delegate3)); + + // These pointers are only compared for equality, not dereferenced. + const content::RenderFrameHost* const frame1 = + reinterpret_cast<const content::RenderFrameHost*>(&ref1); + const content::RenderFrameHost* const frame2 = + reinterpret_cast<const content::RenderFrameHost*>(&ref2); + + EXPECT_CALL(delegate1_ref, OwningFrame()) + .WillRepeatedly(testing::Return(frame1)); + EXPECT_CALL(delegate2_ref, OwningFrame()) + .WillRepeatedly(testing::Return(frame2)); + EXPECT_CALL(delegate3_ref, OwningFrame()) + .WillRepeatedly(testing::Return(nullptr)); + EXPECT_CALL(delegate1_ref, ShouldClose(BUBBLE_CLOSE_FRAME_DESTROYED)) + .WillOnce(testing::Return(true)); + + manager_->CloseBubblesOwnedBy(frame1); + EXPECT_FALSE(ref1); + EXPECT_TRUE(ref2); + EXPECT_TRUE(ref3); +} + +TEST_F(BubbleManagerTest, UpdateAllShouldWorkWithoutBubbles) { + // Manager shouldn't crash if bubbles have never been added. + manager_->UpdateAllBubbleAnchors(); + + // Add a bubble and close it. + BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Default()); + ASSERT_TRUE(manager_->CloseBubble(ref, BUBBLE_CLOSE_FORCED)); + + // Bubble should NOT get an update event because it's already closed. + manager_->UpdateAllBubbleAnchors(); +} + +TEST_F(BubbleManagerTest, CloseAllShouldWorkWithoutBubbles) { + // Manager shouldn't crash if bubbles have never been added. + manager_->CloseAllBubbles(BUBBLE_CLOSE_FOCUS_LOST); + + // Add a bubble and close it. + BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Default()); + ASSERT_TRUE(manager_->CloseBubble(ref, BUBBLE_CLOSE_FORCED)); + + // Bubble should NOT get a close event because it's already closed. + manager_->CloseAllBubbles(BUBBLE_CLOSE_FOCUS_LOST); +} + +// This test validates that it's possible to show another bubble when +// |CloseBubble| is called. +TEST_F(BubbleManagerTest, AllowBubbleChainingOnClose) { + BubbleReference chained_bubble; + BubbleReference ref = + manager_->ShowBubble(make_scoped_ptr(new ChainShowBubbleDelegate( + manager_.get(), MockBubbleDelegate::Default(), &chained_bubble))); + ASSERT_FALSE(chained_bubble); // Bubble not yet visible. + ASSERT_TRUE(manager_->CloseBubble(ref, BUBBLE_CLOSE_FORCED)); + ASSERT_TRUE(chained_bubble); // Bubble is now visible. +} + +// This test validates that it's possible to show another bubble when +// |CloseAllBubbles| is called. +TEST_F(BubbleManagerTest, AllowBubbleChainingOnCloseAll) { + BubbleReference chained_bubble; + BubbleReference ref = + manager_->ShowBubble(make_scoped_ptr(new ChainShowBubbleDelegate( + manager_.get(), MockBubbleDelegate::Default(), &chained_bubble))); + ASSERT_FALSE(chained_bubble); // Bubble not yet visible. + manager_->CloseAllBubbles(BUBBLE_CLOSE_FORCED); + ASSERT_TRUE(chained_bubble); // Bubble is now visible. +} + +// This test validates that a show chain will not happen in the destructor. +// While chaining is during the normal life span of the manager, it should NOT +// happen when the manager is being destroyed. +TEST_F(BubbleManagerTest, BubblesDoNotChainOnDestroy) { + MockBubbleManagerObserver metrics; + // |chained_delegate| should never be shown. + EXPECT_CALL(metrics, OnBubbleNeverShown(testing::_)); + // The ChainShowBubbleDelegate should be closed when the manager is destroyed. + EXPECT_CALL(metrics, OnBubbleClosed(testing::_, BUBBLE_CLOSE_FORCED)); + manager_->AddBubbleManagerObserver(&metrics); + + scoped_ptr<MockBubbleDelegate> chained_delegate(new MockBubbleDelegate); + EXPECT_CALL(*chained_delegate->bubble_ui(), Show(testing::_)).Times(0); + EXPECT_CALL(*chained_delegate, ShouldClose(testing::_)).Times(0); + EXPECT_CALL(*chained_delegate, DidClose(testing::_)).Times(0); + + manager_->ShowBubble(make_scoped_ptr(new ChainShowBubbleDelegate( + manager_.get(), std::move(chained_delegate), nullptr))); + manager_.reset(); +} + +TEST_F(BubbleManagerTest, BubbleCloseReasonIsCalled) { + MockBubbleManagerObserver metrics; + EXPECT_CALL(metrics, OnBubbleNeverShown(testing::_)).Times(0); + EXPECT_CALL(metrics, OnBubbleClosed(testing::_, BUBBLE_CLOSE_ACCEPTED)); + manager_->AddBubbleManagerObserver(&metrics); + + BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Default()); + ref->CloseBubble(BUBBLE_CLOSE_ACCEPTED); + + // Destroy to verify no events are sent to |metrics| in destructor. + manager_.reset(); +} + +// In a close chain, it should be possible for the bubble in the second close +// event to close. +TEST_F(BubbleManagerTest, BubbleCloseChainCloseClose) { + scoped_ptr<ChainCloseBubbleDelegate> closing_bubble( + new ChainCloseBubbleDelegate(manager_.get())); + EXPECT_CALL(*closing_bubble, ShouldClose(testing::_)) + .WillOnce(testing::Return(true)); + + BubbleReference other_bubble_ref = + manager_->ShowBubble(MockBubbleDelegate::Default()); + + BubbleReference closing_bubble_ref = + manager_->ShowBubble(std::move(closing_bubble)); + + EXPECT_TRUE(other_bubble_ref); + EXPECT_TRUE(closing_bubble_ref); + + closing_bubble_ref->CloseBubble(BUBBLE_CLOSE_ACCEPTED); + + EXPECT_FALSE(other_bubble_ref); + EXPECT_FALSE(closing_bubble_ref); +} + +// In a close chain, it should be possible for the bubble in the second close +// event to remain open because close is a request. +TEST_F(BubbleManagerTest, BubbleCloseChainCloseNoClose) { + scoped_ptr<ChainCloseBubbleDelegate> closing_bubble( + new ChainCloseBubbleDelegate(manager_.get())); + EXPECT_CALL(*closing_bubble, ShouldClose(testing::_)) + .WillOnce(testing::Return(true)); + + BubbleReference other_bubble_ref = + manager_->ShowBubble(MockBubbleDelegate::Stubborn()); + + BubbleReference closing_bubble_ref = + manager_->ShowBubble(std::move(closing_bubble)); + + EXPECT_TRUE(other_bubble_ref); + EXPECT_TRUE(closing_bubble_ref); + + closing_bubble_ref->CloseBubble(BUBBLE_CLOSE_ACCEPTED); + + EXPECT_TRUE(other_bubble_ref); + EXPECT_FALSE(closing_bubble_ref); +} + +// This test is a sanity check. |closing_bubble| will attempt to close all other +// bubbles if it's closed, but it doesn't want to close. Sending a close request +// should keep it open without starting a close chain. +TEST_F(BubbleManagerTest, BubbleCloseChainNoCloseNoClose) { + scoped_ptr<ChainCloseBubbleDelegate> closing_bubble( + new ChainCloseBubbleDelegate(manager_.get())); + EXPECT_CALL(*closing_bubble, ShouldClose(testing::_)) + .WillRepeatedly(testing::Return(false)); + + BubbleReference other_bubble_ref = + manager_->ShowBubble(MockBubbleDelegate::Default()); + + BubbleReference closing_bubble_ref = + manager_->ShowBubble(std::move(closing_bubble)); + + EXPECT_TRUE(other_bubble_ref); + EXPECT_TRUE(closing_bubble_ref); + + closing_bubble_ref->CloseBubble(BUBBLE_CLOSE_ACCEPTED); + + EXPECT_TRUE(other_bubble_ref); + EXPECT_TRUE(closing_bubble_ref); +} + +} // namespace |