Skip to content

Commit

Permalink
[CHERRY-PICK] Unit Test Unexpected Exception (#756)
Browse files Browse the repository at this point in the history
## Description
Cherry pick from: tianocore/edk2#5345

- [ ] Impacts functionality?
- **Functionality** - Does the change ultimately impact how firmware
functions?
- Examples: Add a new library, publish a new PPI, update an algorithm,
...
- [ ] Impacts security?
- **Security** - Does the change have a direct security impact on an
application,
    flow, or firmware?
  - Examples: Crypto algorithm change, buffer overflow fix, parameter
    validation improvement, ...
- [ ] Breaking change?
- **Breaking change** - Will anyone consuming this change experience a
break
    in build or boot behavior?
- Examples: Add a new library class, move a module to a different repo,
call
    a function in a new library class in a pre-existing module, ...
- [ ] Includes tests?
  - **Tests** - Does the change include any explicit test code?
  - Examples: Unit tests, integration tests, robot tests, ...
- [ ] Includes documentation?
- **Documentation** - Does the change contain explicit documentation
additions
    outside direct code modifications (and comments)?
- Examples: Update readme file, add feature readme file, link to
documentation
    on an a separate Web page, ...

## How This Was Tested

Local builds and CI tests ran.

## Integration Instructions

N/A

---------

Signed-off-by: Michael D Kinney <[email protected]>
Co-authored-by: Michael D Kinney <[email protected]>
  • Loading branch information
VivianNK and mdkinney authored Mar 1, 2024
1 parent b778f1e commit 4907b58
Show file tree
Hide file tree
Showing 36 changed files with 2,224 additions and 22 deletions.
6 changes: 3 additions & 3 deletions MdePkg/Include/Library/DebugLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -379,9 +379,9 @@ UnitTestDebugAssert (
DebugPrint (PrintLevel, ##__VA_ARGS__); \
} \
} while (FALSE)
#define _DEBUG(Expression) _DEBUG_PRINT Expression
#define _DEBUGLIB_DEBUG(Expression) _DEBUG_PRINT Expression
#else
#define _DEBUG(Expression) DebugPrint Expression
#define _DEBUGLIB_DEBUG(Expression) DebugPrint Expression
#endif

/**
Expand Down Expand Up @@ -426,7 +426,7 @@ UnitTestDebugAssert (
#define DEBUG(Expression) \
do { \
if (DebugPrintEnabled ()) { \
_DEBUG (Expression); \
_DEBUGLIB_DEBUG (Expression); \
} \
} while (FALSE)
#else
Expand Down
20 changes: 20 additions & 0 deletions UnitTestFrameworkPkg/Include/Library/GoogleTestLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,26 @@
#include <gmock/gmock.h>
#include <cstring>

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.
//
#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)) \
)

extern "C" {
#include <Uefi.h>
}
Expand Down
6 changes: 3 additions & 3 deletions UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@
UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec

[BuildOptions]
MSFT:*_*_*_CC_FLAGS == /c /EHsc /Zi /Od
GCC:*_*_IA32_CC_FLAGS == -g -c -fshort-wchar -O0 -m32
GCC:*_*_X64_CC_FLAGS == -g -c -fshort-wchar -O0 -m64
MSFT:*_*_*_CC_FLAGS == /c /EHs /Zi /Od /MT
GCC:*_*_IA32_CC_FLAGS == -g -c -fshort-wchar -fexceptions -O0 -m32 -malign-double -fno-pie
GCC:*_*_X64_CC_FLAGS == -g -c -fshort-wchar -fexceptions -O0 -m64 -fno-pie "-DEFIAPI=__attribute__((ms_abi))"
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/** @file
Unit Test Debug Assert Library for host-based environments
Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/

#include <stdexcept>

#ifdef NULL
#undef NULL
#endif

extern "C" {
#include <Uefi.h>
#include <UnitTestFrameworkTypes.h>
#include <Library/BaseLib.h>
#include <Library/UnitTestLib.h>

///
/// Point to jump buffer used with SetJump()/LongJump() to test if a function
/// under test generates an expected ASSERT() condition.
///
BASE_LIBRARY_JUMP_BUFFER *gUnitTestExpectAssertFailureJumpBuffer = NULL;

/**
Unit test library replacement for DebugAssert() in DebugLib.
If FileName is NULL, then a <FileName> string of "(NULL) Filename" is printed.
If Description is NULL, then a <Description> string of "(NULL) Description" is printed.
@param FileName The pointer to the name of the source file that generated the assert condition.
@param LineNumber The line number in the source file that generated the assert condition
@param Description The pointer to the description of the assert condition.
**/
VOID
EFIAPI
UnitTestDebugAssert (
IN CONST CHAR8 *FileName,
IN UINTN LineNumber,
IN CONST CHAR8 *Description
)
{
CHAR8 Message[256];

if (gUnitTestExpectAssertFailureJumpBuffer != NULL) {
UT_LOG_INFO ("Detected expected ASSERT: %a(%d): %a\n", FileName, LineNumber, Description);
LongJump (gUnitTestExpectAssertFailureJumpBuffer, 1);
} else {
if (GetActiveFrameworkHandle () != NULL) {
AsciiStrCpyS (Message, sizeof (Message), "Detected unexpected ASSERT(");
AsciiStrCatS (Message, sizeof (Message), Description);
AsciiStrCatS (Message, sizeof (Message), ")");
UnitTestAssertTrue (FALSE, "", LineNumber, FileName, Message);
} else {
snprintf (Message, sizeof (Message), "Detected unexpected ASSERT: %s(%d): %s\n", FileName, (INT32)(UINT32)LineNumber, Description);
throw std::runtime_error (Message);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
## @file
# Unit Test Debug Assert Library for host-based environments
#
# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##

[Defines]
INF_VERSION = 0x00010005
BASE_NAME = UnitTestDebugAssertLibHost
MODULE_UNI_FILE = UnitTestDebugAssertLibHost.uni
FILE_GUID = F097D67C-0340-49C8-AB30-ABC1B7D1C8D2
MODULE_TYPE = HOST_APPLICATION
VERSION_STRING = 1.0
LIBRARY_CLASS = NULL

#
# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64
#

[Sources]
UnitTestDebugAssertLibHost.cpp

[Packages]
MdePkg/MdePkg.dec
UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec

[LibraryClasses]
BaseLib
UnitTestLib

[BuildOptions]
MSFT:*_*_*_CC_FLAGS == /c /EHs /Zi /Od /MT
GCC:*_*_IA32_CC_FLAGS == -g -c -fshort-wchar -fexceptions -O0 -m32 -malign-double -fno-pie
GCC:*_*_X64_CC_FLAGS == -g -c -fshort-wchar -fexceptions -O0 -m64 -fno-pie "-DEFIAPI=__attribute__((ms_abi))"
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// /** @file
// Unit Test Debug Assert Library for host-based environments
//
// Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
// SPDX-License-Identifier: BSD-2-Clause-Patent
//
// **/

#string STR_MODULE_ABSTRACT #language en-US "Unit Test Debug Assert Library for host-based environments"

#string STR_MODULE_DESCRIPTION #language en-US "Unit Test Debug Assert Library for host-based environments"
4 changes: 4 additions & 0 deletions UnitTestFrameworkPkg/Library/UnitTestLib/Assert.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ UnitTestLogFailure (
// Get active Framework handle
//
FrameworkHandle = GetActiveFrameworkHandle ();
if (FrameworkHandle == NULL) {
DEBUG ((DEBUG_ERROR, "%a - FrameworkHandle not initialized\n", __func__));
return;
}

//
// Convert the message to an ASCII String
Expand Down
4 changes: 4 additions & 0 deletions UnitTestFrameworkPkg/Library/UnitTestLib/Log.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@ UnitTestLog (
VA_LIST Marker;

FrameworkHandle = GetActiveFrameworkHandle ();
if (FrameworkHandle == NULL) {
DEBUG ((DEBUG_ERROR, "%a - FrameworkHandle not initialized\n", __func__));
return;
}

LogTypePrefix = NULL;

Expand Down
1 change: 0 additions & 1 deletion UnitTestFrameworkPkg/Library/UnitTestLib/RunTests.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ GetActiveFrameworkHandle (
VOID
)
{
ASSERT (mFrameworkHandle != NULL);
return mFrameworkHandle;
}

Expand Down
1 change: 0 additions & 1 deletion UnitTestFrameworkPkg/Library/UnitTestLib/RunTestsCmocka.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ GetActiveFrameworkHandle (
VOID
)
{
ASSERT (mFrameworkHandle != NULL);
return mFrameworkHandle;
}

Expand Down
4 changes: 4 additions & 0 deletions UnitTestFrameworkPkg/Library/UnitTestLib/UnitTestLib.c
Original file line number Diff line number Diff line change
Expand Up @@ -826,6 +826,10 @@ SaveFrameworkState (

Header = NULL;
FrameworkHandle = GetActiveFrameworkHandle ();
if (FrameworkHandle == NULL) {
DEBUG ((DEBUG_ERROR, "%a - Could not save state! FrameworkHandle not initialized\n", __func__));
return EFI_DEVICE_ERROR;
}

//
// Return a unique error code if the framework is not set.
Expand Down
2 changes: 1 addition & 1 deletion UnitTestFrameworkPkg/ReadMe.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ reviewed. The paths to the SecureBootVariableLib unit tests are:
| Unit Test Source Language | C | C++ |
| Register Test Suite | YES | Auto |
| Register Test Case | YES | Auto |
| Death/Expected Assert Tests | YES | YES |
| Expected Assert Tests | YES | YES |
| Setup/Teardown Hooks | YES | YES |
| Value-Parameterized Tests | NO | YES |
| Typed Tests | NO | YES |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
**/

#include <gtest/gtest.h>
#include <Library/GoogleTestLib.h>
extern "C" {
#include <Uefi.h>
#include <Library/BaseLib.h>
Expand Down Expand Up @@ -229,7 +229,7 @@ TEST_P (MacroTestsAssertsEnabledDisabled, MacroExpectNoAssertFailure) {
}

/**
Sample unit test using the ASSERT_DEATH() macro to test expected ASSERT()s.
Sample unit test using the EXPECT_ANY_THROW() macro to test expected ASSERT()s.
**/
TEST_P (MacroTestsAssertsEnabledDisabled, MacroExpectAssertFailure) {
//
Expand All @@ -242,14 +242,35 @@ TEST_P (MacroTestsAssertsEnabledDisabled, MacroExpectAssertFailure) {
//
// This test passes because it directly triggers an ASSERT().
//
ASSERT_DEATH (ASSERT (FALSE), "");
EXPECT_ANY_THROW (ASSERT (FALSE));

//
// This test passes because DecimalToBcd() generates an ASSERT() if the
// value passed in is >= 100. The expected ASSERT() is caught by the unit
// test framework and ASSERT_DEATH() returns without an error.
// test framework and EXPECT_ANY_THROW() returns without an error.
//
ASSERT_DEATH (DecimalToBcd8 (101), "");
EXPECT_ANY_THROW (DecimalToBcd8 (101));

//
// This test passes because DecimalToBcd() generates an ASSERT() if the
// value passed in is >= 100. The expected ASSERT() is caught by the unit
// test framework and throws the C++ exception of type std::runtime_error.
// EXPECT_THROW() returns without an error.
//
EXPECT_THROW (DecimalToBcd8 (101), std::runtime_error);

//
// This test passes because DecimalToBcd() generates an ASSERT() if the
// value passed in is >= 100. The expected ASSERT() is caught by the unit
// test framework and throws the C++ exception of type std::runtime_error with
// a message that includes the filename, linenumber, and the expression that
// triggered the ASSERT().
//
// EXPECT_THROW_MESSAGE() calls DecimalToBcd() expecting DecimalToBds() to
// throw a C++ exception of type std::runtime_error with a message that
// includes the expression of "Value < 100" that triggered the ASSERT().
//
EXPECT_THROW_MESSAGE (DecimalToBcd8 (101), "Value < 100");
}

INSTANTIATE_TEST_SUITE_P (
Expand All @@ -266,6 +287,11 @@ TEST (MacroTestsMessages, MacroTraceMessage) {
// Example of logging.
//
SCOPED_TRACE ("SCOPED_TRACE message\n");

//
// Always pass
//
ASSERT_TRUE (TRUE);
}

int
Expand Down
Loading

0 comments on commit 4907b58

Please sign in to comment.