chromium/chrome/common/win/delay_load_failure_hook_unittest.cc

// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <windows.h>

#include <delayimp.h>

#include "base/process/memory.h"
#include "base/strings/stringprintf.h"
#include "base/test/gtest_util.h"
#include "testing/gtest/include/gtest/gtest.h"

// Subtle: In tests, unit_tests.exe is linked with
// chrome/common/win/delay_load_failure_hook.cc not
// chrome/app/delay_load_failure_hook_win.cc. So, __pfnDliFailureHook2 will
// always call DelayLoadFailureHook and not DelayLoadFailureHookEXE despite
// existing in an exe file named unit_tests.exe.
//
// In production chrome.exe, __pfnDliFailureHook2 is instead backed by
// DelayLoadFailureHookEXE in chrome/app/delay_load_failure_hook_win.cc, while
// in chrome.dll, __pfnDliFailureHook2 is backed by DelayLoadFailureHook from
// chrome/common/win/delay_load_failure_hook.cc.

// This test verifies that delay load hooks are correctly in place for the
// current module, which is unit_tests.exe in the case of this test.
TEST(ChromeDelayLoadHookTest, HooksAreSetAtLinkTime) {
  ASSERT_NE(__pfnDliFailureHook2, nullptr);
}

// This test verifies DelayLoadFailureHook crashes for a failure.
TEST(ChromeDelayLoadHookTest, DllLoadFailureCrashes) {
  DelayLoadInfo dli = {.szDll = "test.dll"};
  EXPECT_CHECK_DEATH({ __pfnDliFailureHook2(dliFailLoadLib, &dli); });
}

// This test verifies that if a DLL is failing to load because of lack of
// memory, an OOM exception is generated rather than just a CHECK so as to
// distinguish them in crash reports.
TEST(ChromeDelayLoadHookDeathTest, OomIsHandled) {
  DelayLoadInfo dli = {.szDll = "test.dll",
                       .dwLastError = ERROR_COMMITMENT_LIMIT};
  const auto expected = base::StringPrintf("Received fatal exception 0x%08lx",
                                           base::win::kOomExceptionCode);
  EXPECT_DEATH_IF_SUPPORTED({ __pfnDliFailureHook2(dliFailLoadLib, &dli); },
                            expected);
}