<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:DengXian;
panose-1:2 1 6 0 3 1 1 1 1 1;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
{font-family:"\@DengXian";
panose-1:2 1 6 0 3 1 1 1 1 1;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0in;
margin-bottom:.0001pt;
font-size:11.0pt;
font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:blue;
text-decoration:underline;}
.MsoChpDefault
{mso-style-type:export-only;}
@page WordSection1
{size:8.5in 11.0in;
margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
{page:WordSection1;}
--></style>
</head>
<body lang="EN-US" link="blue" vlink="#954F72">
<div class="WordSection1">
<p class="MsoNormal">Reviewed-by: Bret Barkelew <bret.barkelew@microsoft.com><o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">- Bret</p>
<p class="MsoNormal"><o:p> </o:p></p>
<div style="mso-element:para-border-div;border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal" style="border:none;padding:0in"><b>From: </b><a href="mailto:michael.d.kinney@intel.com">Michael D Kinney</a><br>
<b>Sent: </b>Friday, July 10, 2020 7:09 PM<br>
<b>To: </b><a href="mailto:devel@edk2.groups.io">devel@edk2.groups.io</a><br>
<b>Cc: </b><a href="mailto:sean.brogan@microsoft.com">Sean Brogan</a>; <a href="mailto:Bret.Barkelew@microsoft.com">
Bret Barkelew</a>; <a href="mailto:jiewen.yao@intel.com">Yao, Jiewen</a><br>
<b>Subject: </b>[EXTERNAL] [Patch v3 12/16] UnitTestFrameworkPkg/UnitTestLib: Add checks for ASSERT()</p>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal" style="margin-bottom:12.0pt">REF: REF: <a href="https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D2801&data=02%7C01%7CBret.Barkelew%40microsoft.com%7C5764407d5dc9445fec9808d8253f699c%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637300301574194018&sdata=4UQXMIDPbI9xRP%2BKcPorH1PpbFb1%2BjZR%2BlpsnCP5lAM%3D&reserved=0">
https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D2801&data=02%7C01%7CBret.Barkelew%40microsoft.com%7C5764407d5dc9445fec9808d8253f699c%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637300301574194018&sdata=4UQXMIDPbI9xRP%2BKcPorH1PpbFb1%2BjZR%2BlpsnCP5lAM%3D&reserved=0</a><br>
<br>
Add UnitTestDebugAssertLib that provides the UnitTestDebugAssert()<br>
service and the gUnitTestExpectAssertFailureJumpBuffer global<br>
variable. This NULL library is linked against all host and target<br>
unit test builds. This guarantees that the UnitTestDebugAssert()<br>
service is available to link against all libraries and modules that<br>
use the DebugLib class.<br>
<br>
EDKII_UNIT_TEST_FRAMEWORK_ENABLED must always be defined when<br>
building unit tests so the behavior of the DebugLib ASSERT()<br>
macros can be adjusted to allow the unit test framework to<br>
catch an ASSERT() if it is triggered by a function under test.<br>
<br>
Cc: Sean Brogan <sean.brogan@microsoft.com><br>
Cc: Bret Barkelew <Bret.Barkelew@microsoft.com><br>
Cc: Jiewen Yao <jiewen.yao@intel.com><br>
Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com><br>
---<br>
.../UnitTestDebugAssertLib.c | 49 +++++<br>
.../UnitTestDebugAssertLib.inf | 31 +++<br>
.../UnitTestDebugAssertLib.uni | 11 +<br>
.../Library/UnitTestLib/Assert.c | 203 ++++++++++++------<br>
.../Library/UnitTestLib/AssertCmocka.c | 68 ++++++<br>
.../Library/UnitTestLib/RunTests.c | 23 +-<br>
.../UnitTestResultReportLib.c | 3 +-<br>
.../PrivateInclude/UnitTestFrameworkTypes.h | 1 +<br>
.../Test/UnitTestFrameworkPkgHostTest.dsc | 2 +-<br>
UnitTestFrameworkPkg/UnitTestFrameworkPkg.dsc | 1 +<br>
.../UnitTestFrameworkPkgTarget.dsc.inc | 6 +-<br>
11 files changed, 328 insertions(+), 70 deletions(-)<br>
create mode 100644 UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLib.c<br>
create mode 100644 UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLib.inf<br>
create mode 100644 UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLib.uni<br>
<br>
diff --git a/UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLib.c b/UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLib.c<br>
new file mode 100644<br>
index 0000000000..0a4001e182<br>
--- /dev/null<br>
+++ b/UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLib.c<br>
@@ -0,0 +1,49 @@<br>
+/** @file<br>
+ Unit Test Debug Assert Library<br>
+<br>
+ Copyright (c) 2020, Intel Corporation. All rights reserved.<BR><br>
+ SPDX-License-Identifier: BSD-2-Clause-Patent<br>
+<br>
+**/<br>
+<br>
+#include <Uefi.h><br>
+#include <Library/BaseLib.h><br>
+#include <Library/UnitTestLib.h><br>
+<br>
+///<br>
+/// Point to jump buffer used with SetJump()/LongJump() to test if a function<br>
+/// under test generates an expected ASSERT() condition.<br>
+///<br>
+BASE_LIBRARY_JUMP_BUFFER *gUnitTestExpectAssertFailureJumpBuffer = NULL;<br>
+<br>
+/**<br>
+ Unit test library replacement for DebugAssert() in DebugLib.<br>
+<br>
+ If FileName is NULL, then a <FileName> string of "(NULL) Filename" is printed.<br>
+ If Description is NULL, then a <Description> string of "(NULL) Description" is printed.<br>
+<br>
+ @param FileName The pointer to the name of the source file that generated the assert condition.<br>
+ @param LineNumber The line number in the source file that generated the assert condition<br>
+ @param Description The pointer to the description of the assert condition.<br>
+<br>
+**/<br>
+VOID<br>
+EFIAPI<br>
+UnitTestDebugAssert (<br>
+ IN CONST CHAR8 *FileName,<br>
+ IN UINTN LineNumber,<br>
+ IN CONST CHAR8 *Description<br>
+ )<br>
+{<br>
+ CHAR8 Message[256];<br>
+<br>
+ if (gUnitTestExpectAssertFailureJumpBuffer != NULL) {<br>
+ UT_LOG_INFO ("Detected expected ASSERT: %a(%d): %a\n", FileName, LineNumber, Description);<br>
+ LongJump (gUnitTestExpectAssertFailureJumpBuffer, 1);<br>
+ } else {<br>
+ AsciiStrCpyS (Message, sizeof(Message), "Detected unexpected ASSERT(");<br>
+ AsciiStrCatS (Message, sizeof(Message), Description);<br>
+ AsciiStrCatS (Message, sizeof(Message), ")");<br>
+ UnitTestAssertTrue (FALSE, "", LineNumber, FileName, Message);<br>
+ }<br>
+}<br>
diff --git a/UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLib.inf b/UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLib.inf<br>
new file mode 100644<br>
index 0000000000..e6ccab0dd9<br>
--- /dev/null<br>
+++ b/UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLib.inf<br>
@@ -0,0 +1,31 @@<br>
+## @file<br>
+# Unit Test Debug Assert Library<br>
+#<br>
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR><br>
+# SPDX-License-Identifier: BSD-2-Clause-Patent<br>
+#<br>
+##<br>
+<br>
+[Defines]<br>
+ INF_VERSION = 0x00010005<br>
+ BASE_NAME = UnitTestDebugAssertLib<br>
+ MODULE_UNI_FILE = UnitTestDebugAssertLib.uni<br>
+ FILE_GUID = 9D53AD0D-5416-451F-A5BF-E5420051A99B<br>
+ MODULE_TYPE = BASE<br>
+ VERSION_STRING = 1.0<br>
+ LIBRARY_CLASS = NULL<br>
+<br>
+#<br>
+# VALID_ARCHITECTURES = ARM AARCH64<br>
+#<br>
+<br>
+[Sources]<br>
+ UnitTestDebugAssertLib.c<br>
+<br>
+[Packages]<br>
+ MdePkg/MdePkg.dec<br>
+ UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec<br>
+<br>
+[LibraryClasses]<br>
+ BaseLib<br>
+ UnitTestLib<br>
diff --git a/UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLib.uni b/UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLib.uni<br>
new file mode 100644<br>
index 0000000000..9b794aa205<br>
--- /dev/null<br>
+++ b/UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLib.uni<br>
@@ -0,0 +1,11 @@<br>
+// /** @file<br>
+// Unit Test Debug Assert Library<br>
+//<br>
+// Copyright (c) 2020, Intel Corporation. All rights reserved.<BR><br>
+// SPDX-License-Identifier: BSD-2-Clause-Patent<br>
+//<br>
+// **/<br>
+<br>
+#string STR_MODULE_ABSTRACT #language en-US "Unit Test Debug Assert Library"<br>
+<br>
+#string STR_MODULE_DESCRIPTION #language en-US "Unit Test Debug Assert Library"<br>
diff --git a/UnitTestFrameworkPkg/Library/UnitTestLib/Assert.c b/UnitTestFrameworkPkg/Library/UnitTestLib/Assert.c<br>
index 8a131fab2b..3669d63701 100644<br>
--- a/UnitTestFrameworkPkg/Library/UnitTestLib/Assert.c<br>
+++ b/UnitTestFrameworkPkg/Library/UnitTestLib/Assert.c<br>
@@ -13,6 +13,8 @@<br>
#include <Library/DebugLib.h><br>
#include <Library/PrintLib.h><br>
<br>
+extern BASE_LIBRARY_JUMP_BUFFER gUnitTestJumpBuffer;<br>
+<br>
STATIC<br>
EFI_STATUS<br>
AddUnitTestFailure (<br>
@@ -71,7 +73,7 @@ UnitTestLogFailure (<br>
FailureType<br>
);<br>
<br>
- return;<br>
+ LongJump (&gUnitTestJumpBuffer, 1);<br>
}<br>
<br>
/**<br>
@@ -103,6 +105,12 @@ UnitTestAssertTrue (<br>
)<br>
{<br>
if (!Expression) {<br>
+ UT_LOG_ERROR (<br>
+ "[ASSERT FAIL] %a:%d: Expression (%a) is not TRUE!\n",<br>
+ FileName,<br>
+ LineNumber,<br>
+ Description<br>
+ );<br>
UnitTestLogFailure (<br>
FAILURETYPE_ASSERTTRUE,<br>
"%a:%d: Expression (%a) is not TRUE!\n",<br>
@@ -110,12 +118,6 @@ UnitTestAssertTrue (<br>
LineNumber,<br>
Description<br>
);<br>
- UT_LOG_ERROR (<br>
- "[ASSERT FAIL] %a:%d: Expression (%a) is not TRUE!\n",<br>
- FileName,<br>
- LineNumber,<br>
- Description<br>
- );<br>
}<br>
return Expression;<br>
}<br>
@@ -149,6 +151,12 @@ UnitTestAssertFalse (<br>
)<br>
{<br>
if (Expression) {<br>
+ UT_LOG_ERROR (<br>
+ "[ASSERT FAIL] %a:%d: Expression (%a) is not FALSE!\n",<br>
+ FileName,<br>
+ LineNumber,<br>
+ Description<br>
+ );<br>
UnitTestLogFailure (<br>
FAILURETYPE_ASSERTFALSE,<br>
"%a:%d: Expression(%a) is not FALSE!\n",<br>
@@ -156,12 +164,6 @@ UnitTestAssertFalse (<br>
LineNumber,<br>
Description<br>
);<br>
- UT_LOG_ERROR (<br>
- "[ASSERT FAIL] %a:%d: Expression (%a) is not FALSE!\n",<br>
- FileName,<br>
- LineNumber,<br>
- Description<br>
- );<br>
}<br>
return !Expression;<br>
}<br>
@@ -195,6 +197,13 @@ UnitTestAssertNotEfiError (<br>
)<br>
{<br>
if (EFI_ERROR (Status)) {<br>
+ UT_LOG_ERROR (<br>
+ "[ASSERT FAIL] %a:%d: Status '%a' is EFI_ERROR (%r)!\n",<br>
+ FileName,<br>
+ LineNumber,<br>
+ Description,<br>
+ Status<br>
+ );<br>
UnitTestLogFailure (<br>
FAILURETYPE_ASSERTNOTEFIERROR,<br>
"%a:%d: Status '%a' is EFI_ERROR (%r)!\n",<br>
@@ -203,13 +212,6 @@ UnitTestAssertNotEfiError (<br>
Description,<br>
Status<br>
);<br>
- UT_LOG_ERROR (<br>
- "[ASSERT FAIL] %a:%d: Status '%a' is EFI_ERROR (%r)!\n",<br>
- FileName,<br>
- LineNumber,<br>
- Description,<br>
- Status<br>
- );<br>
}<br>
return !EFI_ERROR( Status );<br>
}<br>
@@ -248,16 +250,6 @@ UnitTestAssertEqual (<br>
)<br>
{<br>
if (ValueA != ValueB) {<br>
- UnitTestLogFailure (<br>
- FAILURETYPE_ASSERTEQUAL,<br>
- "%a:%d: Value %a != %a (%d != %d)!\n",<br>
- FileName,<br>
- LineNumber,<br>
- DescriptionA,<br>
- DescriptionB,<br>
- ValueA,<br>
- ValueB<br>
- );<br>
UT_LOG_ERROR (<br>
"[ASSERT FAIL] %a:%d: Value %a != %a (%d != %d)!\n",<br>
FileName,<br>
@@ -267,6 +259,16 @@ UnitTestAssertEqual (<br>
ValueA,<br>
ValueB<br>
);<br>
+ UnitTestLogFailure (<br>
+ FAILURETYPE_ASSERTEQUAL,<br>
+ "%a:%d: Value %a != %a (%d != %d)!\n",<br>
+ FileName,<br>
+ LineNumber,<br>
+ DescriptionA,<br>
+ DescriptionB,<br>
+ ValueA,<br>
+ ValueB<br>
+ );<br>
}<br>
return (ValueA == ValueB);<br>
}<br>
@@ -310,15 +312,6 @@ UnitTestAssertMemEqual (<br>
)<br>
{<br>
if (CompareMem(BufferA, BufferB, Length) != 0) {<br>
- UnitTestLogFailure (<br>
- FAILURETYPE_ASSERTEQUAL,<br>
- "%a:%d: Memory at %a != %a for length %d bytes!\n",<br>
- FileName,<br>
- LineNumber,<br>
- DescriptionA,<br>
- DescriptionB,<br>
- Length<br>
- );<br>
UT_LOG_ERROR (<br>
"[ASSERT FAIL] %a:%d: Value %a != %a for length %d bytes!\n",<br>
FileName,<br>
@@ -327,6 +320,15 @@ UnitTestAssertMemEqual (<br>
DescriptionB,<br>
Length<br>
);<br>
+ UnitTestLogFailure (<br>
+ FAILURETYPE_ASSERTEQUAL,<br>
+ "%a:%d: Memory at %a != %a for length %d bytes!\n",<br>
+ FileName,<br>
+ LineNumber,<br>
+ DescriptionA,<br>
+ DescriptionB,<br>
+ Length<br>
+ );<br>
return FALSE;<br>
}<br>
return TRUE;<br>
@@ -366,6 +368,15 @@ UnitTestAssertNotEqual (<br>
)<br>
{<br>
if (ValueA == ValueB) {<br>
+ UT_LOG_ERROR (<br>
+ "[ASSERT FAIL] %a:%d: Value %a == %a (%d == %d)!\n",<br>
+ FileName,<br>
+ LineNumber,<br>
+ DescriptionA,<br>
+ DescriptionB,<br>
+ ValueA,<br>
+ ValueB<br>
+ );<br>
UnitTestLogFailure (<br>
FAILURETYPE_ASSERTNOTEQUAL,<br>
"%a:%d: Value %a == %a (%d == %d)!\n",<br>
@@ -376,15 +387,6 @@ UnitTestAssertNotEqual (<br>
ValueA,<br>
ValueB<br>
);<br>
- UT_LOG_ERROR (<br>
- "[ASSERT FAIL] %a:%d: Value %a == %a (%d == %d)!\n",<br>
- FileName,<br>
- LineNumber,<br>
- DescriptionA,<br>
- DescriptionB,<br>
- ValueA,<br>
- ValueB<br>
- );<br>
}<br>
return (ValueA != ValueB);<br>
}<br>
@@ -421,6 +423,14 @@ UnitTestAssertStatusEqual (<br>
)<br>
{<br>
if (Status != Expected) {<br>
+ UT_LOG_ERROR (<br>
+ "[ASSERT FAIL] %a:%d: Status '%a' is %r, should be %r!\n",<br>
+ FileName,<br>
+ LineNumber,<br>
+ Description,<br>
+ Status,<br>
+ Expected<br>
+ );<br>
UnitTestLogFailure (<br>
FAILURETYPE_ASSERTSTATUSEQUAL,<br>
"%a:%d: Status '%a' is %r, should be %r!\n",<br>
@@ -430,14 +440,6 @@ UnitTestAssertStatusEqual (<br>
Status,<br>
Expected<br>
);<br>
- UT_LOG_ERROR (<br>
- "[ASSERT FAIL] %a:%d: Status '%a' is %r, should be %r!\n",<br>
- FileName,<br>
- LineNumber,<br>
- Description,<br>
- Status,<br>
- Expected<br>
- );<br>
}<br>
return (Status == Expected);<br>
}<br>
@@ -473,6 +475,12 @@ UnitTestAssertNotNull (<br>
)<br>
{<br>
if (Pointer == NULL) {<br>
+ UT_LOG_ERROR (<br>
+ "[ASSERT FAIL] %a:%d: Pointer (%a) is NULL!\n",<br>
+ FileName,<br>
+ LineNumber,<br>
+ PointerName<br>
+ );<br>
UnitTestLogFailure (<br>
FAILURETYPE_ASSERTNOTNULL,<br>
"%a:%d: Pointer (%a) is NULL!\n",<br>
@@ -480,12 +488,83 @@ UnitTestAssertNotNull (<br>
LineNumber,<br>
PointerName<br>
);<br>
- UT_LOG_ERROR (<br>
- "[ASSERT FAIL] %a:%d: Pointer (%a) is NULL!\n",<br>
- FileName,<br>
- LineNumber,<br>
- PointerName<br>
- );<br>
}<br>
return (Pointer != NULL);<br>
}<br>
+<br>
+/**<br>
+ If UnitTestStatus is UNIT_TEST_PASSED, then log an info message and return<br>
+ TRUE because an ASSERT() was expected when FunctionCall was executed and an<br>
+ ASSERT() was triggered. If UnitTestStatus is UNIT_TEST_SKIPPED, then log a<br>
+ warning message and return TRUE because ASSERT() macros are disabled. If<br>
+ UnitTestStatus is UNIT_TEST_ERROR_TEST_FAILED, then log an error message and<br>
+ return FALSE because an ASSERT() was expected when FunctionCall was executed,<br>
+ but no ASSERT() conditions were triggered. The log messages contain<br>
+ FunctionName, LineNumber, and FileName strings to provide the location of the<br>
+ UT_EXPECT_ASSERT_FAILURE() macro.<br>
+<br>
+ @param[in] UnitTestStatus The status from UT_EXPECT_ASSERT_FAILURE() that<br>
+ is either pass, skipped, or failed.<br>
+ @param[in] FunctionName Null-terminated ASCII string of the function<br>
+ executing the UT_EXPECT_ASSERT_FAILURE() macro.<br>
+ @param[in] LineNumber The source file line number of the the function<br>
+ executing the UT_EXPECT_ASSERT_FAILURE() macro.<br>
+ @param[in] FileName Null-terminated ASCII string of the filename<br>
+ executing the UT_EXPECT_ASSERT_FAILURE() macro.<br>
+ @param[in] FunctionCall Null-terminated ASCII string of the function call<br>
+ executed by the UT_EXPECT_ASSERT_FAILURE() macro.<br>
+ @param[out] ResultStatus Used to return the UnitTestStatus value to the<br>
+ caller of UT_EXPECT_ASSERT_FAILURE(). This is<br>
+ optional parameter that may be NULL.<br>
+<br>
+ @retval TRUE UnitTestStatus is UNIT_TEST_PASSED.<br>
+ @retval TRUE UnitTestStatus is UNIT_TEST_SKIPPED.<br>
+ @retval FALSE UnitTestStatus is UNIT_TEST_ERROR_TEST_FAILED.<br>
+**/<br>
+BOOLEAN<br>
+EFIAPI<br>
+UnitTestExpectAssertFailure (<br>
+ IN UNIT_TEST_STATUS UnitTestStatus,<br>
+ IN CONST CHAR8 *FunctionName,<br>
+ IN UINTN LineNumber,<br>
+ IN CONST CHAR8 *FileName,<br>
+ IN CONST CHAR8 *FunctionCall,<br>
+ OUT UNIT_TEST_STATUS *ResultStatus OPTIONAL<br>
+ )<br>
+{<br>
+ if (ResultStatus != NULL) {<br>
+ *ResultStatus = UnitTestStatus;<br>
+ }<br>
+ if (UnitTestStatus == UNIT_TEST_PASSED) {<br>
+ UT_LOG_INFO (<br>
+ "[ASSERT PASS] %a:%d: UT_EXPECT_ASSERT_FAILURE(%a) detected expected assert\n",<br>
+ FileName,<br>
+ LineNumber,<br>
+ FunctionCall<br>
+ );<br>
+ }<br>
+ if (UnitTestStatus == UNIT_TEST_SKIPPED) {<br>
+ UT_LOG_WARNING (<br>
+ "[ASSERT WARN] %a:%d: UT_EXPECT_ASSERT_FAILURE(%a) disabled\n",<br>
+ FileName,<br>
+ LineNumber,<br>
+ FunctionCall<br>
+ );<br>
+ }<br>
+ if (UnitTestStatus == UNIT_TEST_ERROR_TEST_FAILED) {<br>
+ UT_LOG_ERROR (<br>
+ "[ASSERT FAIL] %a:%d: Function call (%a) did not ASSERT()!\n",<br>
+ FileName,<br>
+ LineNumber,<br>
+ FunctionCall<br>
+ );<br>
+ UnitTestLogFailure (<br>
+ FAILURETYPE_EXPECTASSERT,<br>
+ "%a:%d: Function call (%a) did not ASSERT()!\n",<br>
+ FileName,<br>
+ LineNumber,<br>
+ FunctionCall<br>
+ );<br>
+ }<br>
+ return (UnitTestStatus != UNIT_TEST_ERROR_TEST_FAILED);<br>
+}<br>
diff --git a/UnitTestFrameworkPkg/Library/UnitTestLib/AssertCmocka.c b/UnitTestFrameworkPkg/Library/UnitTestLib/AssertCmocka.c<br>
index e48d614976..687c6243ab 100644<br>
--- a/UnitTestFrameworkPkg/Library/UnitTestLib/AssertCmocka.c<br>
+++ b/UnitTestFrameworkPkg/Library/UnitTestLib/AssertCmocka.c<br>
@@ -333,3 +333,71 @@ UnitTestAssertNotNull (<br>
<br>
return (Pointer != NULL);<br>
}<br>
+<br>
+/**<br>
+ If UnitTestStatus is UNIT_TEST_PASSED, then log an info message and return<br>
+ TRUE because an ASSERT() was expected when FunctionCall was executed and an<br>
+ ASSERT() was triggered. If UnitTestStatus is UNIT_TEST_SKIPPED, then log a<br>
+ warning message and return TRUE because ASSERT() macros are disabled. If<br>
+ UnitTestStatus is UNIT_TEST_ERROR_TEST_FAILED, then log an error message and<br>
+ return FALSE because an ASSERT() was expected when FunctionCall was executed,<br>
+ but no ASSERT() conditions were triggered. The log messages contain<br>
+ FunctionName, LineNumber, and FileName strings to provide the location of the<br>
+ UT_EXPECT_ASSERT_FAILURE() macro.<br>
+<br>
+ @param[in] UnitTestStatus The status from UT_EXPECT_ASSERT_FAILURE() that<br>
+ is either pass, skipped, or failed.<br>
+ @param[in] FunctionName Null-terminated ASCII string of the function<br>
+ executing the UT_EXPECT_ASSERT_FAILURE() macro.<br>
+ @param[in] LineNumber The source file line number of the the function<br>
+ executing the UT_EXPECT_ASSERT_FAILURE() macro.<br>
+ @param[in] FileName Null-terminated ASCII string of the filename<br>
+ executing the UT_EXPECT_ASSERT_FAILURE() macro.<br>
+ @param[in] FunctionCall Null-terminated ASCII string of the function call<br>
+ executed by the UT_EXPECT_ASSERT_FAILURE() macro.<br>
+ @param[out] ResultStatus Used to return the UnitTestStatus value to the<br>
+ caller of UT_EXPECT_ASSERT_FAILURE(). This is<br>
+ optional parameter that may be NULL.<br>
+<br>
+ @retval TRUE UnitTestStatus is UNIT_TEST_PASSED.<br>
+ @retval TRUE UnitTestStatus is UNIT_TEST_SKIPPED.<br>
+ @retval FALSE UnitTestStatus is UNIT_TEST_ERROR_TEST_FAILED.<br>
+**/<br>
+BOOLEAN<br>
+EFIAPI<br>
+UnitTestExpectAssertFailure (<br>
+ IN UNIT_TEST_STATUS UnitTestStatus,<br>
+ IN CONST CHAR8 *FunctionName,<br>
+ IN UINTN LineNumber,<br>
+ IN CONST CHAR8 *FileName,<br>
+ IN CONST CHAR8 *FunctionCall,<br>
+ OUT UNIT_TEST_STATUS *ResultStatus OPTIONAL<br>
+ )<br>
+{<br>
+ CHAR8 TempStr[MAX_STRING_SIZE];<br>
+<br>
+ if (ResultStatus != NULL) {<br>
+ *ResultStatus = UnitTestStatus;<br>
+ }<br>
+ if (UnitTestStatus == UNIT_TEST_PASSED) {<br>
+ UT_LOG_INFO (<br>
+ "[ASSERT PASS] %a:%d: UT_EXPECT_ASSERT_FAILURE(%a) detected expected assert\n",<br>
+ FileName,<br>
+ LineNumber,<br>
+ FunctionCall<br>
+ );<br>
+ }<br>
+ if (UnitTestStatus == UNIT_TEST_SKIPPED) {<br>
+ UT_LOG_WARNING (<br>
+ "[ASSERT WARN] %a:%d: UT_EXPECT_ASSERT_FAILURE(%a) disabled\n",<br>
+ FileName,<br>
+ LineNumber,<br>
+ FunctionCall<br>
+ );<br>
+ }<br>
+ if (UnitTestStatus == UNIT_TEST_ERROR_TEST_FAILED) {<br>
+ snprintf (TempStr, sizeof(TempStr), "UT_EXPECT_ASSERT_FAILURE(%s) did not trigger ASSERT()", FunctionCall);<br>
+ _assert_true (FALSE, TempStr, FileName, (INT32)LineNumber);<br>
+ }<br>
+ return (UnitTestStatus != UNIT_TEST_ERROR_TEST_FAILED);<br>
+}<br>
diff --git a/UnitTestFrameworkPkg/Library/UnitTestLib/RunTests.c b/UnitTestFrameworkPkg/Library/UnitTestLib/RunTests.c<br>
index 793335fd0f..2dc1d159d5 100644<br>
--- a/UnitTestFrameworkPkg/Library/UnitTestLib/RunTests.c<br>
+++ b/UnitTestFrameworkPkg/Library/UnitTestLib/RunTests.c<br>
@@ -14,6 +14,8 @@<br>
<br>
STATIC UNIT_TEST_FRAMEWORK_HANDLE mFrameworkHandle = NULL;<br>
<br>
+BASE_LIBRARY_JUMP_BUFFER gUnitTestJumpBuffer;<br>
+<br>
UNIT_TEST_FRAMEWORK_HANDLE<br>
GetActiveFrameworkHandle (<br>
VOID<br>
@@ -75,7 +77,14 @@ RunTestSuite (<br>
// Next, if we're still running, make sure that our test prerequisites are in place.<br>
if (Test->Result == UNIT_TEST_PENDING && Test->Prerequisite != NULL) {<br>
DEBUG ((DEBUG_VERBOSE, "PREREQ\n"));<br>
- if (Test->Prerequisite (Test->Context) != UNIT_TEST_PASSED) {<br>
+ if (SetJump (&gUnitTestJumpBuffer) == 0) {<br>
+ if (Test->Prerequisite (Test->Context) != UNIT_TEST_PASSED) {<br>
+ DEBUG ((DEBUG_ERROR, "Prerequisite Not Met\n"));<br>
+ Test->Result = UNIT_TEST_ERROR_PREREQUISITE_NOT_MET;<br>
+ ParentFramework->CurrentTest = NULL;<br>
+ continue;<br>
+ }<br>
+ } else {<br>
DEBUG ((DEBUG_ERROR, "Prerequisite Not Met\n"));<br>
Test->Result = UNIT_TEST_ERROR_PREREQUISITE_NOT_MET;<br>
ParentFramework->CurrentTest = NULL;<br>
@@ -88,14 +97,20 @@ RunTestSuite (<br>
// We set the status to UNIT_TEST_RUNNING in case the test needs to reboot<br>
// or quit. The UNIT_TEST_RUNNING state will allow the test to resume<br>
// but will prevent the Prerequisite from being dispatched a second time.<br>
- Test->Result = UNIT_TEST_RUNNING;<br>
- Test->Result = Test->RunTest (Test->Context);<br>
+ if (SetJump (&gUnitTestJumpBuffer) == 0) {<br>
+ Test->Result = UNIT_TEST_RUNNING;<br>
+ Test->Result = Test->RunTest (Test->Context);<br>
+ } else {<br>
+ Test->Result = UNIT_TEST_ERROR_TEST_FAILED;<br>
+ }<br>
<br>
//<br>
// Finally, clean everything up, if need be.<br>
if (Test->CleanUp != NULL) {<br>
DEBUG ((DEBUG_VERBOSE, "CLEANUP\n"));<br>
- Test->CleanUp (Test->Context);<br>
+ if (SetJump (&gUnitTestJumpBuffer) == 0) {<br>
+ Test->CleanUp (Test->Context);<br>
+ }<br>
}<br>
<br>
//<br>
diff --git a/UnitTestFrameworkPkg/Library/UnitTestResultReportLib/UnitTestResultReportLib.c b/UnitTestFrameworkPkg/Library/UnitTestResultReportLib/UnitTestResultReportLib.c<br>
index eba68e330c..66c9db457d 100644<br>
--- a/UnitTestFrameworkPkg/Library/UnitTestResultReportLib/UnitTestResultReportLib.c<br>
+++ b/UnitTestFrameworkPkg/Library/UnitTestResultReportLib/UnitTestResultReportLib.c<br>
@@ -49,7 +49,8 @@ struct _UNIT_TEST_FAILURE_TYPE_STRING mFailureTypeStrings[] = {<br>
{ FAILURETYPE_ASSERTNOTEQUAL, "ASSERT_NOTEQUAL FAILURE"},<br>
{ FAILURETYPE_ASSERTNOTEFIERROR, "ASSERT_NOTEFIERROR FAILURE"},<br>
{ FAILURETYPE_ASSERTSTATUSEQUAL, "ASSERT_STATUSEQUAL FAILURE"},<br>
- { FAILURETYPE_ASSERTNOTNULL , "ASSERT_NOTNULL FAILURE"},<br>
+ { FAILURETYPE_ASSERTNOTNULL, "ASSERT_NOTNULL FAILURE"},<br>
+ { FAILURETYPE_EXPECTASSERT, "EXPECT_ASSERT FAILURE"},<br>
{ 0, "*UNKNOWN* Failure"}<br>
};<br>
<br>
diff --git a/UnitTestFrameworkPkg/PrivateInclude/UnitTestFrameworkTypes.h b/UnitTestFrameworkPkg/PrivateInclude/UnitTestFrameworkTypes.h<br>
index e58b30093e..b0e2f61bbf 100644<br>
--- a/UnitTestFrameworkPkg/PrivateInclude/UnitTestFrameworkTypes.h<br>
+++ b/UnitTestFrameworkPkg/PrivateInclude/UnitTestFrameworkTypes.h<br>
@@ -44,6 +44,7 @@ typedef UINT32 FAILURE_TYPE;<br>
#define FAILURETYPE_ASSERTNOTEFIERROR (6)<br>
#define FAILURETYPE_ASSERTSTATUSEQUAL (7)<br>
#define FAILURETYPE_ASSERTNOTNULL (8)<br>
+#define FAILURETYPE_EXPECTASSERT (9)<br>
<br>
///<br>
/// Unit Test context structure tracked by the unit test framework.<br>
diff --git a/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTest.dsc b/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTest.dsc<br>
index 701e7299d7..70affddead 100644<br>
--- a/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTest.dsc<br>
+++ b/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTest.dsc<br>
@@ -25,7 +25,7 @@ [Components]<br>
UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestHost.inf<br>
<br>
#<br>
- # Build Libraries<br>
+ # Build HOST_APPLICATION Libraries<br>
#<br>
UnitTestFrameworkPkg/Library/CmockaLib/CmockaLib.inf<br>
UnitTestFrameworkPkg/Library/Posix/DebugLibPosix/DebugLibPosix.inf<br>
diff --git a/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dsc b/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dsc<br>
index 2d84691bf1..0dfd98f2a8 100644<br>
--- a/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dsc<br>
+++ b/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dsc<br>
@@ -28,6 +28,7 @@ [Components]<br>
UnitTestFrameworkPkg/Library/UnitTestResultReportLib/UnitTestResultReportLibConOut.inf<br>
UnitTestFrameworkPkg/Library/UnitTestBootLibUsbClass/UnitTestBootLibUsbClass.inf<br>
UnitTestFrameworkPkg/Library/UnitTestPersistenceLibSimpleFileSystem/UnitTestPersistenceLibSimpleFileSystem.inf<br>
+ UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLib.inf<br>
<br>
UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestDxe.inf<br>
UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestPei.inf<br>
diff --git a/UnitTestFrameworkPkg/UnitTestFrameworkPkgTarget.dsc.inc b/UnitTestFrameworkPkg/UnitTestFrameworkPkgTarget.dsc.inc<br>
index 0881278ab0..8adf690098 100644<br>
--- a/UnitTestFrameworkPkg/UnitTestFrameworkPkgTarget.dsc.inc<br>
+++ b/UnitTestFrameworkPkg/UnitTestFrameworkPkgTarget.dsc.inc<br>
@@ -29,6 +29,7 @@ [LibraryClasses]<br>
UnitTestLib|UnitTestFrameworkPkg/Library/UnitTestLib/UnitTestLib.inf<br>
UnitTestPersistenceLib|UnitTestFrameworkPkg/Library/UnitTestPersistenceLibNull/UnitTestPersistenceLibNull.inf<br>
UnitTestResultReportLib|UnitTestFrameworkPkg/Library/UnitTestResultReportLib/UnitTestResultReportLibDebugLib.inf<br>
+ NULL|UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLib.inf<br>
<br>
[LibraryClasses.ARM, LibraryClasses.AARCH64]<br>
#<br>
@@ -56,5 +57,6 @@ [PcdsFixedAtBuild]<br>
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17<br>
<br>
[BuildOptions]<br>
- MSFT:*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES<br>
- GCC:*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES<br>
+ MSFT:*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES -D EDKII_UNIT_TEST_FRAMEWORK_ENABLED<br>
+ GCC:*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES -D EDKII_UNIT_TEST_FRAMEWORK_ENABLED<br>
+ XCODE:*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES -D EDKII_UNIT_TEST_FRAMEWORK_ENABLED<br>
-- <br>
2.21.0.windows.1<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
</body>
</html>
<div width="1" style="color:white;clear:both">_._,_._,_</div>
<hr>
Groups.io Links:<p>
You receive all messages sent to this group.
<p>
<a target="_blank" href="https://edk2.groups.io/g/devel/message/62580">View/Reply Online (#62580)</a> |
|
<a target="_blank" href="https://groups.io/mt/75514381/1813853">Mute This Topic</a>
| <a href="https://edk2.groups.io/g/devel/post">New Topic</a><br>
<br>
<a href="https://edk2.groups.io/g/devel/editsub/1813853">Your Subscription</a> |
<a href="mailto:devel+owner@edk2.groups.io">Contact Group Owner</a> |
<a href="https://edk2.groups.io/g/devel/unsub">Unsubscribe</a>
[edk2-devel-archive@redhat.com]<br>
<div width="1" style="color:white;clear:both">_._,_._,_</div>