https://bugzilla.tianocore.org/show_bug.cgi?id=2801

Add the UT_EXPECT_ASSERT_FAILURE(FunctionCall, Status) macro
to the UnitTestLib that can be used to check if a function
under test triggers an ASSERT() condition.  If an ASSERT()
condition is triggered, then the macro returns.  If the
ASSERT() condition is not triggered, then the current unit
test fails with a status of UNIT_TEST_ERROR_TEST_FAILED.

If ASSERT()s are disabled, then this check for ASSERT()
behavior is not possible, and the check is skipped.

Add the UnitTestDebugAssert() to the UnitTestLib class.  The
UnitTestDebugAssert() service is the same as the DebugLib
DebugAssert() service and is invoked from the DebugLib
_ASSERT() macro if unit testing is enabled.  This allows the
Unit Test Framework to know when code under test triggers an
ASSERT() condition.

The global variable gUnitTestExpectAssertFailureJumpBuffer
is added to the UnitTestLib to save/restore context when
the UT_EXPECT_ASSERT_FAILURE(FunctionCall, Status) macro
is used.  The UT_EXPECT_ASSERT_FAILURE() macro uses the
SetJump() service with this global variable.  The UnitTestLib
service UnitTestDebugAssert() uses the LongJump() service
with this global to restore context if an ASSERT() is
triggered by the code under test.

Cc: Liming Gao <liming....@intel.com>
Cc: Sean Brogan <sean.bro...@microsoft.com>
Cc: Bret Barkelew <bret.barke...@microsoft.com>
Cc: Jiewen Yao <jiewen....@intel.com>
Signed-off-by: Michael D Kinney <michael.d.kin...@intel.com>
---
 MdePkg/Include/Library/UnitTestLib.h | 70 ++++++++++++++++++++++++++++
 1 file changed, 70 insertions(+)

diff --git a/MdePkg/Include/Library/UnitTestLib.h 
b/MdePkg/Include/Library/UnitTestLib.h
index a4374580a8..1935a14ad1 100644
--- a/MdePkg/Include/Library/UnitTestLib.h
+++ b/MdePkg/Include/Library/UnitTestLib.h
@@ -10,6 +10,14 @@
 #ifndef __UNIT_TEST_LIB_H__
 #define __UNIT_TEST_LIB_H__
 
+#include <Library/BaseLib.h>
+
+///
+/// Pointer to jump buffer used with SetJump()/LongJump() to test if a function
+/// under test generates an expected ASSERT() condition.
+///
+extern BASE_LIBRARY_JUMP_BUFFER  *gUnitTestExpectAssertFailureJumpBuffer;
+
 ///
 /// Unit Test Status
 ///
@@ -441,6 +449,68 @@ SaveFrameworkState (
     return UNIT_TEST_ERROR_TEST_FAILED;                                        
      \
   }
 
+/**
+  This macro uses the framework assertion logic to check whether a function 
call
+  triggers an ASSERT() condition.  The BaseLib SetJump()/LongJump() services
+  are used to establish a safe return point when an ASSERT() is triggered.
+  If an ASSERT() is triggered, unit test execution continues and Status is set
+  to UNIT_TEST_PASSED.  Otherwise, a unit test case failure is raised and
+  Status is set to UNIT_TEST_ERROR_TEST_FAILED.
+
+  If ASSERT() macros are disabled, then the test case is skipped and a warning
+  message is added to the unit test log.  Status is set to UNIT_TEST_SKIPPED.
+
+  @param[in]  FunctionCall  Function call that is expected to trigger ASSERT().
+  @param[out] Status        Pointer to a UNIT_TEST_STATUS return value.  This
+                            is an optional parameter that may be NULL.
+**/
+#if defined (EDKII_UNIT_TEST_FRAMEWORK_ENABLED)
+  #define UT_EXPECT_ASSERT_FAILURE(FunctionCall, Status)                       
\
+    if (DebugAssertEnabled ()) {                                               
\
+      BASE_LIBRARY_JUMP_BUFFER  UnitTestJumpBuffer;                            
\
+      gUnitTestExpectAssertFailureJumpBuffer = &UnitTestJumpBuffer;            
\
+      if (SetJump (gUnitTestExpectAssertFailureJumpBuffer) == 0) {             
\
+        FunctionCall;                                                          
\
+        gUnitTestExpectAssertFailureJumpBuffer = NULL;                         
\
+        UT_LOG_ERROR ("UT_EXPECT_ASSERT_FAILURE("#FunctionCall") did not 
ASSERT()\n");  \
+        if (Status != NULL) {                                                  
\
+          *((UNIT_TEST_STATUS *)Status) = UNIT_TEST_ERROR_TEST_FAILED;         
\
+        }                                                                      
\
+        return UNIT_TEST_ERROR_TEST_FAILED;                                    
\
+      }                                                                        
\
+      gUnitTestExpectAssertFailureJumpBuffer = NULL;                           
\
+      if (Status != NULL) {                                                    
\
+        *((UNIT_TEST_STATUS *)Status) = UNIT_TEST_PASSED;                      
\
+      }                                                                        
\
+    } else {                                                                   
\
+      UT_LOG_WARNING ("UT_EXPECT_ASSERT_FAILURE("#FunctionCall") disabled\n"); 
\
+      if (Status != NULL) {                                                    
\
+        *((UNIT_TEST_STATUS *)Status) = UNIT_TEST_SKIPPED;                     
\
+      }                                                                        
\
+    }
+#else
+  #define UT_EXPECT_ASSERT_FAILURE(FunctionCall, Status)  FunctionCall;
+#endif
+
+/**
+  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
+  );
+
 /**
   If Expression is TRUE, then TRUE is returned.
   If Expression is FALSE, then an assert is triggered and the location of the
-- 
2.21.0.windows.1


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#61257): https://edk2.groups.io/g/devel/message/61257
Mute This Topic: https://groups.io/mt/74885927/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to