// 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