// 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 "base/threading/scoped_blocking_call.h" #include <memory> #include "base/macros.h" #include "base/test/gtest_util.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" namespace base { namespace { class MockBlockingObserver : public internal::BlockingObserver { public: MockBlockingObserver() = default; MOCK_METHOD1(BlockingStarted, void(BlockingType)); MOCK_METHOD0(BlockingTypeUpgraded, void()); MOCK_METHOD0(BlockingEnded, void()); private: DISALLOW_COPY_AND_ASSIGN(MockBlockingObserver); }; class ScopedBlockingCallTest : public testing::Test { protected: ScopedBlockingCallTest() { internal::SetBlockingObserverForCurrentThread(&observer_); } ~ScopedBlockingCallTest() override { internal::ClearBlockingObserverForTesting(); } testing::StrictMock<MockBlockingObserver> observer_; private: DISALLOW_COPY_AND_ASSIGN(ScopedBlockingCallTest); }; } // namespace TEST_F(ScopedBlockingCallTest, MayBlock) { EXPECT_CALL(observer_, BlockingStarted(BlockingType::MAY_BLOCK)); ScopedBlockingCall scoped_blocking_call(BlockingType::MAY_BLOCK); testing::Mock::VerifyAndClear(&observer_); EXPECT_CALL(observer_, BlockingEnded()); } TEST_F(ScopedBlockingCallTest, WillBlock) { EXPECT_CALL(observer_, BlockingStarted(BlockingType::WILL_BLOCK)); ScopedBlockingCall scoped_blocking_call(BlockingType::WILL_BLOCK); testing::Mock::VerifyAndClear(&observer_); EXPECT_CALL(observer_, BlockingEnded()); } TEST_F(ScopedBlockingCallTest, MayBlockWillBlock) { EXPECT_CALL(observer_, BlockingStarted(BlockingType::MAY_BLOCK)); ScopedBlockingCall scoped_blocking_call_a(BlockingType::MAY_BLOCK); testing::Mock::VerifyAndClear(&observer_); { EXPECT_CALL(observer_, BlockingTypeUpgraded()); ScopedBlockingCall scoped_blocking_call_b(BlockingType::WILL_BLOCK); testing::Mock::VerifyAndClear(&observer_); } EXPECT_CALL(observer_, BlockingEnded()); } TEST_F(ScopedBlockingCallTest, WillBlockMayBlock) { EXPECT_CALL(observer_, BlockingStarted(BlockingType::WILL_BLOCK)); ScopedBlockingCall scoped_blocking_call_a(BlockingType::WILL_BLOCK); testing::Mock::VerifyAndClear(&observer_); { ScopedBlockingCall scoped_blocking_call_b(BlockingType::MAY_BLOCK); } EXPECT_CALL(observer_, BlockingEnded()); } TEST_F(ScopedBlockingCallTest, MayBlockMayBlock) { EXPECT_CALL(observer_, BlockingStarted(BlockingType::MAY_BLOCK)); ScopedBlockingCall scoped_blocking_call_a(BlockingType::MAY_BLOCK); testing::Mock::VerifyAndClear(&observer_); { ScopedBlockingCall scoped_blocking_call_b(BlockingType::MAY_BLOCK); } EXPECT_CALL(observer_, BlockingEnded()); } TEST_F(ScopedBlockingCallTest, WillBlockWillBlock) { EXPECT_CALL(observer_, BlockingStarted(BlockingType::WILL_BLOCK)); ScopedBlockingCall scoped_blocking_call_a(BlockingType::WILL_BLOCK); testing::Mock::VerifyAndClear(&observer_); { ScopedBlockingCall scoped_blocking_call_b(BlockingType::WILL_BLOCK); } EXPECT_CALL(observer_, BlockingEnded()); } TEST_F(ScopedBlockingCallTest, MayBlockWillBlockTwice) { EXPECT_CALL(observer_, BlockingStarted(BlockingType::MAY_BLOCK)); ScopedBlockingCall scoped_blocking_call_a(BlockingType::MAY_BLOCK); testing::Mock::VerifyAndClear(&observer_); { EXPECT_CALL(observer_, BlockingTypeUpgraded()); ScopedBlockingCall scoped_blocking_call_b(BlockingType::WILL_BLOCK); testing::Mock::VerifyAndClear(&observer_); { ScopedBlockingCall scoped_blocking_call_c(BlockingType::MAY_BLOCK); ScopedBlockingCall scoped_blocking_call_d(BlockingType::WILL_BLOCK); } } EXPECT_CALL(observer_, BlockingEnded()); } TEST(ScopedBlockingCallDestructionOrderTest, InvalidDestructionOrder) { auto scoped_blocking_call_a = std::make_unique<ScopedBlockingCall>(BlockingType::WILL_BLOCK); auto scoped_blocking_call_b = std::make_unique<ScopedBlockingCall>(BlockingType::WILL_BLOCK); EXPECT_DCHECK_DEATH({ scoped_blocking_call_a.reset(); }); } } // namespace base