152 lines
5.1 KiB
C++
152 lines
5.1 KiB
C++
// Copyright 2020 The Chromium Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "base/win/com_init_balancer.h"
|
|
|
|
#include <shlobj.h>
|
|
#include <wrl/client.h>
|
|
|
|
#include "base/test/gtest_util.h"
|
|
#include "base/win/com_init_util.h"
|
|
#include "base/win/scoped_com_initializer.h"
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
|
|
namespace base {
|
|
namespace win {
|
|
|
|
using Microsoft::WRL::ComPtr;
|
|
|
|
TEST(TestComInitBalancer, BalancedPairsWithComBalancerEnabled) {
|
|
{
|
|
// Assert COM has initialized correctly.
|
|
ScopedCOMInitializer com_initializer(
|
|
ScopedCOMInitializer::Uninitialization::kBlockPremature);
|
|
ASSERT_TRUE(com_initializer.Succeeded());
|
|
|
|
// Create COM object successfully.
|
|
ComPtr<IUnknown> shell_link;
|
|
HRESULT hr = ::CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_ALL,
|
|
IID_PPV_ARGS(&shell_link));
|
|
EXPECT_TRUE(SUCCEEDED(hr));
|
|
}
|
|
|
|
// ScopedCOMInitializer has gone out of scope and COM has been uninitialized.
|
|
EXPECT_DCHECK_DEATH(AssertComInitialized());
|
|
}
|
|
|
|
TEST(TestComInitBalancer, UnbalancedPairsWithComBalancerEnabled) {
|
|
{
|
|
// Assert COM has initialized correctly.
|
|
ScopedCOMInitializer com_initializer(
|
|
ScopedCOMInitializer::Uninitialization::kBlockPremature);
|
|
ASSERT_TRUE(com_initializer.Succeeded());
|
|
|
|
// Attempt to prematurely uninitialize the COM library.
|
|
::CoUninitialize();
|
|
::CoUninitialize();
|
|
|
|
// Assert COM is still initialized.
|
|
AssertComInitialized();
|
|
|
|
// Create COM object successfully.
|
|
ComPtr<IUnknown> shell_link;
|
|
HRESULT hr = ::CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_ALL,
|
|
IID_PPV_ARGS(&shell_link));
|
|
EXPECT_TRUE(SUCCEEDED(hr));
|
|
}
|
|
|
|
// ScopedCOMInitializer has gone out of scope and COM has been uninitialized.
|
|
EXPECT_DCHECK_DEATH(AssertComInitialized());
|
|
}
|
|
|
|
TEST(TestComInitBalancer, BalancedPairsWithComBalancerDisabled) {
|
|
{
|
|
// Assert COM has initialized correctly.
|
|
ScopedCOMInitializer com_initializer(
|
|
ScopedCOMInitializer::Uninitialization::kAllow);
|
|
ASSERT_TRUE(com_initializer.Succeeded());
|
|
|
|
// Create COM object successfully.
|
|
ComPtr<IUnknown> shell_link;
|
|
HRESULT hr = ::CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_ALL,
|
|
IID_PPV_ARGS(&shell_link));
|
|
EXPECT_TRUE(SUCCEEDED(hr));
|
|
}
|
|
|
|
// ScopedCOMInitializer has gone out of scope and COM has been uninitialized.
|
|
EXPECT_DCHECK_DEATH(AssertComInitialized());
|
|
}
|
|
|
|
TEST(TestComInitBalancer, UnbalancedPairsWithComBalancerDisabled) {
|
|
// Assert COM has initialized correctly.
|
|
ScopedCOMInitializer com_initializer(
|
|
ScopedCOMInitializer::Uninitialization::kAllow);
|
|
ASSERT_TRUE(com_initializer.Succeeded());
|
|
|
|
// Attempt to prematurely uninitialize the COM library.
|
|
::CoUninitialize();
|
|
::CoUninitialize();
|
|
|
|
// Assert COM is not initialized.
|
|
EXPECT_DCHECK_DEATH(AssertComInitialized());
|
|
|
|
// Create COM object unsuccessfully.
|
|
ComPtr<IUnknown> shell_link;
|
|
HRESULT hr = ::CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_ALL,
|
|
IID_PPV_ARGS(&shell_link));
|
|
EXPECT_TRUE(FAILED(hr));
|
|
EXPECT_EQ(CO_E_NOTINITIALIZED, hr);
|
|
}
|
|
|
|
TEST(TestComInitBalancer, OneRegisteredSpyRefCount) {
|
|
ScopedCOMInitializer com_initializer(
|
|
ScopedCOMInitializer::Uninitialization::kBlockPremature);
|
|
ASSERT_TRUE(com_initializer.Succeeded());
|
|
|
|
// Reference count should be 1 after initialization.
|
|
EXPECT_EQ(DWORD(1), com_initializer.GetCOMBalancerReferenceCountForTesting());
|
|
|
|
// Attempt to prematurely uninitialize the COM library.
|
|
::CoUninitialize();
|
|
|
|
// Expect reference count to remain at 1.
|
|
EXPECT_EQ(DWORD(1), com_initializer.GetCOMBalancerReferenceCountForTesting());
|
|
}
|
|
|
|
TEST(TestComInitBalancer, ThreeRegisteredSpiesRefCount) {
|
|
ScopedCOMInitializer com_initializer_1(
|
|
ScopedCOMInitializer::Uninitialization::kBlockPremature);
|
|
ScopedCOMInitializer com_initializer_2(
|
|
ScopedCOMInitializer::Uninitialization::kBlockPremature);
|
|
ScopedCOMInitializer com_initializer_3(
|
|
ScopedCOMInitializer::Uninitialization::kBlockPremature);
|
|
ASSERT_TRUE(com_initializer_1.Succeeded());
|
|
ASSERT_TRUE(com_initializer_2.Succeeded());
|
|
ASSERT_TRUE(com_initializer_3.Succeeded());
|
|
|
|
// Reference count should be 3 after initialization.
|
|
EXPECT_EQ(DWORD(3),
|
|
com_initializer_1.GetCOMBalancerReferenceCountForTesting());
|
|
EXPECT_EQ(DWORD(3),
|
|
com_initializer_2.GetCOMBalancerReferenceCountForTesting());
|
|
EXPECT_EQ(DWORD(3),
|
|
com_initializer_3.GetCOMBalancerReferenceCountForTesting());
|
|
|
|
// Attempt to prematurely uninitialize the COM library.
|
|
::CoUninitialize(); // Reference count -> 2.
|
|
::CoUninitialize(); // Reference count -> 1.
|
|
::CoUninitialize();
|
|
|
|
// Expect reference count to remain at 1.
|
|
EXPECT_EQ(DWORD(1),
|
|
com_initializer_1.GetCOMBalancerReferenceCountForTesting());
|
|
EXPECT_EQ(DWORD(1),
|
|
com_initializer_2.GetCOMBalancerReferenceCountForTesting());
|
|
EXPECT_EQ(DWORD(1),
|
|
com_initializer_3.GetCOMBalancerReferenceCountForTesting());
|
|
}
|
|
|
|
} // namespace win
|
|
} // namespace base
|