mirror of
https://github.com/tianocore/edk2
synced 2026-08-27 00:23:19 -04:00
Update GoogleTestLib.h to support Windows/CLANGPDB build. When using Windows/CLANGPDB, _MSC_VER is not defined. If it is not defined, then set to 1900 for Visual Studio 2015 or newer compatibility when using windows include files for host based unit test application builds. If _MSC_VER is not set, then those application fail to build. Also address a Windows/CLANG issue when ASAN is enabled by providing an alternate implementation of the EXPECT_THROW_MESSAGE() and ASSERT_THROW_MESSAGE() macros. Without this alternate implementation, an exception is generated due to the description of the ASSERT() condition being NULL. Update all implementations of EXPECT_THROW_MESSAGE() and ASSERT_THROW_MESSAGE() to support parameters to the statement executed to return values. Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
187 lines
6.6 KiB
C++
187 lines
6.6 KiB
C++
/** @file
|
|
GoogleTestLib class with APIs from the googletest project
|
|
|
|
Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
|
|
#ifndef GOOGLE_TEST_LIB_H_
|
|
#define GOOGLE_TEST_LIB_H_
|
|
|
|
//
|
|
// For Windows/clang builds if _MSC_VER is not defined, then set to
|
|
// Visual Studio 2015 value of 1900
|
|
//
|
|
#if defined (__clang__) && defined (_WIN32)
|
|
#ifndef _MSC_VER
|
|
#define _MSC_VER 1900
|
|
#endif
|
|
#endif
|
|
|
|
#include <gtest/gtest.h>
|
|
#include <gmock/gmock.h>
|
|
#include <cstring>
|
|
#include <iomanip>
|
|
|
|
//
|
|
// For all use of GoogleTestLib, make sure NULL is defined to nullptr to
|
|
// support matching any unit test pointer value to NULL.
|
|
//
|
|
#ifdef NULL
|
|
#undef NULL
|
|
#define NULL nullptr
|
|
#endif
|
|
|
|
using ::testing::Throws;
|
|
using ::testing::ThrowsMessage;
|
|
using ::testing::HasSubstr;
|
|
|
|
//
|
|
// Extended macros for testing exceptions with a specific description string
|
|
// in the exception message. Typically used to check that the expression
|
|
// that generates an ASSERT() matches the expected expression.
|
|
//
|
|
// NOTE: Windows/CLANG builds with ASAN enabled generate an exception
|
|
// due to the generated exception string being NULL. An alternate implementation
|
|
// of these macros is provided for Windows/CLANG builds that disables ASAN
|
|
// checks in a function that uses try/catch for the expected exception type
|
|
// and provides the correct exception string for comparison.
|
|
//
|
|
#if defined (__clang__) && defined (_WIN32)
|
|
#define EXPECT_THROW_MESSAGE(statement, description) \
|
|
[&]() __attribute__((no_sanitize_address)){ \
|
|
try { \
|
|
(statement); \
|
|
FAIL() << "Exception not thrown"; \
|
|
} catch (const std::runtime_error& ex) { \
|
|
EXPECT_THAT ( \
|
|
std::string(ex.what()), \
|
|
HasSubstr(description) \
|
|
); \
|
|
} catch(...) { \
|
|
FAIL() << "Unexpected exception"; \
|
|
} \
|
|
}()
|
|
#define ASSERT_THROW_MESSAGE(statement, description) \
|
|
[&]() __attribute__((no_sanitize_address)){ \
|
|
try { \
|
|
(statement); \
|
|
FAIL() << "Exception not thrown"; \
|
|
} catch (const std::runtime_error& ex) { \
|
|
ASSERT_THAT ( \
|
|
std::string(ex.what()), \
|
|
HasSubstr(description) \
|
|
); \
|
|
} catch(...) { \
|
|
FAIL() << "Unexpected exception"; \
|
|
} \
|
|
}()
|
|
#else
|
|
#define EXPECT_THROW_MESSAGE(statement, description) \
|
|
EXPECT_THAT ( \
|
|
[&]() { statement; }, \
|
|
ThrowsMessage<std::runtime_error>(HasSubstr (description)) \
|
|
)
|
|
#define ASSERT_THROW_MESSAGE(statement, description) \
|
|
ASSERT_THAT ( \
|
|
[&]() { statement; }, \
|
|
ThrowsMessage<std::runtime_error>(HasSubstr (description)) \
|
|
)
|
|
#endif
|
|
|
|
extern "C" {
|
|
#include <Uefi.h>
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Below are the action extensions to GoogleTest and gmock for EDK2 types.
|
|
// These actions are intended to be used in EXPECT_CALL (and related gmock
|
|
// macros) to support assignments to output arguments in the expected call.
|
|
//
|
|
|
|
// Action to support pointer types to a buffer (such as UINT8* or VOID*)
|
|
ACTION_TEMPLATE (
|
|
SetArgBuffer,
|
|
HAS_1_TEMPLATE_PARAMS (size_t, ArgNum),
|
|
AND_2_VALUE_PARAMS (Buffer, ByteSize)
|
|
) {
|
|
auto ArgBuffer = std::get<ArgNum>(args);
|
|
|
|
std::memcpy (ArgBuffer, Buffer, ByteSize);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Below are the matcher extensions to GoogleTest and gmock for EDK2 types.
|
|
// These matchers are intended to be used in EXPECT_CALL (and related gmock
|
|
// macros) to support comparisons to input arguments in the expected call.
|
|
//
|
|
// Note that these matchers can also be used in the EXPECT_THAT or ASSERT_THAT
|
|
// macros to compare whether two values are equal.
|
|
//
|
|
|
|
// Matcher to support pointer types to a buffer (such as UINT8* or VOID* or
|
|
// any structure pointer)
|
|
MATCHER_P2 (
|
|
BufferEq,
|
|
Buffer,
|
|
ByteSize,
|
|
std::string ("buffer data to ") + (negation ? "not " : "") + "be the same"
|
|
) {
|
|
UINT8 *Actual = (UINT8 *)arg;
|
|
UINT8 *Expected = (UINT8 *)Buffer;
|
|
|
|
for (size_t i = 0; i < ByteSize; i++) {
|
|
if (Actual[i] != Expected[i]) {
|
|
*result_listener << "byte at offset " << i
|
|
<< " does not match expected. [" << std::hex
|
|
<< "Actual: 0x" << std::setw (2) << std::setfill ('0')
|
|
<< (unsigned int)Actual[i] << ", "
|
|
<< "Expected: 0x" << std::setw (2) << std::setfill ('0')
|
|
<< (unsigned int)Expected[i] << "]";
|
|
return false;
|
|
}
|
|
}
|
|
|
|
*result_listener << "all bytes match";
|
|
return true;
|
|
}
|
|
|
|
// Matcher to support CHAR16* type
|
|
MATCHER_P (
|
|
Char16StrEq,
|
|
String,
|
|
std::string ("strings to ") + (negation ? "not " : "") + "be the same"
|
|
) {
|
|
CHAR16 *Actual = (CHAR16 *)arg;
|
|
CHAR16 *Expected = (CHAR16 *)String;
|
|
|
|
for (size_t i = 0; Actual[i] != 0; i++) {
|
|
if (Actual[i] != Expected[i]) {
|
|
*result_listener << "character at offset " << i
|
|
<< " does not match expected. [" << std::hex
|
|
<< "Actual: 0x" << std::setw (4) << std::setfill ('0')
|
|
<< Actual[i];
|
|
|
|
if (std::isprint (Actual[i])) {
|
|
*result_listener << " ('" << (char)Actual[i] << "')";
|
|
}
|
|
|
|
*result_listener << ", Expected: 0x" << std::setw (4) << std::setfill ('0')
|
|
<< Expected[i];
|
|
|
|
if (std::isprint (Expected[i])) {
|
|
*result_listener << " ('" << (char)Expected[i] << "')";
|
|
}
|
|
|
|
*result_listener << "]";
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
*result_listener << "strings match";
|
|
return true;
|
|
}
|
|
|
|
#endif
|