]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdePkg/Include/Library/UnitTestLib.h
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdePkg / Include / Library / UnitTestLib.h
index a4374580a8d58fceac737132d8ea5efe5d73d943..71c205b1b14352b6590745997756322a3665d39f 100644 (file)
@@ -13,7 +13,7 @@
 ///\r
 /// Unit Test Status\r
 ///\r
-typedef UINT32  UNIT_TEST_STATUS;\r
+typedef UINT32 UNIT_TEST_STATUS;\r
 #define UNIT_TEST_PASSED                      (0)\r
 #define UNIT_TEST_ERROR_PREREQUISITE_NOT_MET  (1)\r
 #define UNIT_TEST_ERROR_TEST_FAILED           (2)\r
@@ -34,24 +34,24 @@ typedef UINT32  UNIT_TEST_STATUS;
 /// Unit Test Framework Handle\r
 ///\r
 struct UNIT_TEST_FRAMEWORK_OBJECT;\r
-typedef struct UNIT_TEST_FRAMEWORK_OBJECT  *UNIT_TEST_FRAMEWORK_HANDLE;\r
+typedef struct UNIT_TEST_FRAMEWORK_OBJECT *UNIT_TEST_FRAMEWORK_HANDLE;\r
 \r
 ///\r
 /// Unit Test Suite Handle\r
 ///\r
 struct UNIT_TEST_SUITE_OBJECT;\r
-typedef struct UNIT_TEST_SUITE_OBJECT  *UNIT_TEST_SUITE_HANDLE;\r
+typedef struct UNIT_TEST_SUITE_OBJECT *UNIT_TEST_SUITE_HANDLE;\r
 \r
 ///\r
 /// Unit Test Handle\r
 ///\r
 struct UNIT_TEST_OBJECT;\r
-typedef struct UNIT_TEST_OBJECT  *UNIT_TEST_HANDLE;\r
+typedef struct UNIT_TEST_OBJECT *UNIT_TEST_HANDLE;\r
 \r
 ///\r
 /// Unit Test Context\r
 ///\r
-typedef VOID*  UNIT_TEST_CONTEXT;\r
+typedef VOID *UNIT_TEST_CONTEXT;\r
 \r
 /**\r
   The prototype for a single UnitTest case function.\r
@@ -336,8 +336,8 @@ FreeUnitTestFramework (
 EFI_STATUS\r
 EFIAPI\r
 SaveFrameworkState (\r
-  IN UNIT_TEST_CONTEXT           ContextToSave     OPTIONAL,\r
-  IN UINTN                       ContextToSaveSize\r
+  IN UNIT_TEST_CONTEXT  ContextToSave     OPTIONAL,\r
+  IN UINTN              ContextToSaveSize\r
   );\r
 \r
 /**\r
@@ -347,9 +347,9 @@ SaveFrameworkState (
 \r
   @param[in]  Expression  Expression to be evaluated for TRUE.\r
 **/\r
-#define UT_ASSERT_TRUE(Expression)                                                        \\r
-  if(!UnitTestAssertTrue ((Expression), __FUNCTION__, __LINE__, __FILE__, #Expression)) { \\r
-    return UNIT_TEST_ERROR_TEST_FAILED;                                                   \\r
+#define UT_ASSERT_TRUE(Expression)                                                                 \\r
+  if(!UnitTestAssertTrue ((Expression), __FUNCTION__, DEBUG_LINE_NUMBER, __FILE__, #Expression)) { \\r
+    return UNIT_TEST_ERROR_TEST_FAILED;                                                            \\r
   }\r
 \r
 /**\r
@@ -359,9 +359,9 @@ SaveFrameworkState (
 \r
   @param[in]  Expression  Expression to be evaluated for FALSE.\r
 **/\r
-#define UT_ASSERT_FALSE(Expression)                                                        \\r
-  if(!UnitTestAssertFalse ((Expression), __FUNCTION__, __LINE__, __FILE__, #Expression)) { \\r
-    return UNIT_TEST_ERROR_TEST_FAILED;                                                    \\r
+#define UT_ASSERT_FALSE(Expression)                                                                 \\r
+  if(!UnitTestAssertFalse ((Expression), __FUNCTION__, DEBUG_LINE_NUMBER, __FILE__, #Expression)) { \\r
+    return UNIT_TEST_ERROR_TEST_FAILED;                                                             \\r
   }\r
 \r
 /**\r
@@ -373,7 +373,7 @@ SaveFrameworkState (
   @param[in]  ValueB  Value to be compared for equality (64-bit comparison).\r
 **/\r
 #define UT_ASSERT_EQUAL(ValueA, ValueB)                                                                           \\r
-  if(!UnitTestAssertEqual ((UINT64)(ValueA), (UINT64)(ValueB), __FUNCTION__, __LINE__, __FILE__, #ValueA, #ValueB)) { \\r
+  if(!UnitTestAssertEqual ((UINT64)(ValueA), (UINT64)(ValueB), __FUNCTION__, DEBUG_LINE_NUMBER, __FILE__, #ValueA, #ValueB)) { \\r
     return UNIT_TEST_ERROR_TEST_FAILED;                                                                           \\r
   }\r
 \r
@@ -386,9 +386,9 @@ SaveFrameworkState (
   @param[in]  BufferB  Pointer to a buffer for comparison.\r
   @param[in]  Length   Number of bytes to compare in BufferA and BufferB.\r
 **/\r
-#define UT_ASSERT_MEM_EQUAL(BufferA, BufferB, Length)                                                                               \\r
-  if(!UnitTestAssertMemEqual ((VOID *)(UINTN)(BufferA), (VOID *)(UINTN)(BufferB), (UINTN)Length, __FUNCTION__, __LINE__, __FILE__, #BufferA, #BufferB)) { \\r
-    return UNIT_TEST_ERROR_TEST_FAILED;                                                                                           \\r
+#define UT_ASSERT_MEM_EQUAL(BufferA, BufferB, Length)                                                                                                              \\r
+  if(!UnitTestAssertMemEqual ((VOID *)(UINTN)(BufferA), (VOID *)(UINTN)(BufferB), (UINTN)Length, __FUNCTION__, DEBUG_LINE_NUMBER, __FILE__, #BufferA, #BufferB)) { \\r
+    return UNIT_TEST_ERROR_TEST_FAILED;                                                                                                                            \\r
   }\r
 \r
 /**\r
@@ -399,9 +399,9 @@ SaveFrameworkState (
   @param[in]  ValueA  Value to be compared for inequality (64-bit comparison).\r
   @param[in]  ValueB  Value to be compared for inequality (64-bit comparison).\r
 **/\r
-#define UT_ASSERT_NOT_EQUAL(ValueA, ValueB)                                                                          \\r
-  if(!UnitTestAssertNotEqual ((UINT64)(ValueA), (UINT64)(ValueB), __FUNCTION__, __LINE__, __FILE__, #ValueA, #ValueB)) { \\r
-    return UNIT_TEST_ERROR_TEST_FAILED;                                                                              \\r
+#define UT_ASSERT_NOT_EQUAL(ValueA, ValueB)                                                                                       \\r
+  if(!UnitTestAssertNotEqual ((UINT64)(ValueA), (UINT64)(ValueB), __FUNCTION__, DEBUG_LINE_NUMBER, __FILE__, #ValueA, #ValueB)) { \\r
+    return UNIT_TEST_ERROR_TEST_FAILED;                                                                                           \\r
   }\r
 \r
 /**\r
@@ -411,9 +411,9 @@ SaveFrameworkState (
 \r
   @param[in]  Status  EFI_STATUS value to check.\r
 **/\r
-#define UT_ASSERT_NOT_EFI_ERROR(Status)                                                \\r
-  if(!UnitTestAssertNotEfiError ((Status), __FUNCTION__, __LINE__, __FILE__, #Status)) { \\r
-    return UNIT_TEST_ERROR_TEST_FAILED;                                                \\r
+#define UT_ASSERT_NOT_EFI_ERROR(Status)                                                           \\r
+  if(!UnitTestAssertNotEfiError ((Status), __FUNCTION__, DEBUG_LINE_NUMBER, __FILE__, #Status)) { \\r
+    return UNIT_TEST_ERROR_TEST_FAILED;                                                           \\r
   }\r
 \r
 /**\r
@@ -424,9 +424,9 @@ SaveFrameworkState (
   @param[in]  Status    EFI_STATUS values to compare for equality.\r
   @param[in]  Expected  EFI_STATUS values to compare for equality.\r
 **/\r
-#define UT_ASSERT_STATUS_EQUAL(Status, Expected)                                                 \\r
-  if(!UnitTestAssertStatusEqual ((Status), (Expected), __FUNCTION__, __LINE__, __FILE__, #Status)) { \\r
-    return UNIT_TEST_ERROR_TEST_FAILED;                                                          \\r
+#define UT_ASSERT_STATUS_EQUAL(Status, Expected)                                                              \\r
+  if(!UnitTestAssertStatusEqual ((Status), (Expected), __FUNCTION__, DEBUG_LINE_NUMBER, __FILE__, #Status)) { \\r
+    return UNIT_TEST_ERROR_TEST_FAILED;                                                                       \\r
   }\r
 \r
 /**\r
@@ -436,11 +436,61 @@ SaveFrameworkState (
 \r
   @param[in]  Pointer  Pointer to be checked against NULL.\r
 **/\r
-#define UT_ASSERT_NOT_NULL(Pointer)                                                  \\r
-  if(!UnitTestAssertNotNull ((Pointer), __FUNCTION__, __LINE__, __FILE__, #Pointer)) { \\r
-    return UNIT_TEST_ERROR_TEST_FAILED;                                              \\r
+#define UT_ASSERT_NOT_NULL(Pointer)                                                             \\r
+  if(!UnitTestAssertNotNull ((Pointer), __FUNCTION__, DEBUG_LINE_NUMBER, __FILE__, #Pointer)) { \\r
+    return UNIT_TEST_ERROR_TEST_FAILED;                                                         \\r
   }\r
 \r
+/**\r
+  This macro uses the framework assertion logic to check whether a function call\r
+  triggers an ASSERT() condition.  The BaseLib SetJump()/LongJump() services\r
+  are used to establish a safe return point when an ASSERT() is triggered.\r
+  If an ASSERT() is triggered, unit test execution continues and Status is set\r
+  to UNIT_TEST_PASSED.  Otherwise, a unit test case failure is raised and\r
+  Status is set to UNIT_TEST_ERROR_TEST_FAILED.\r
+\r
+  If ASSERT() macros are disabled, then the test case is skipped and a warning\r
+  message is added to the unit test log.  Status is set to UNIT_TEST_SKIPPED.\r
+\r
+  @param[in]  FunctionCall  Function call that is expected to trigger ASSERT().\r
+  @param[out] Status        Pointer to a UNIT_TEST_STATUS return value.  This\r
+                            is an optional parameter that may be NULL.\r
+**/\r
+#if defined (EDKII_UNIT_TEST_FRAMEWORK_ENABLED)\r
+  #include <Library/BaseLib.h>\r
+\r
+///\r
+/// Pointer to jump buffer used with SetJump()/LongJump() to test if a\r
+/// function under test generates an expected ASSERT() condition.\r
+///\r
+extern BASE_LIBRARY_JUMP_BUFFER  *gUnitTestExpectAssertFailureJumpBuffer;\r
+\r
+#define UT_EXPECT_ASSERT_FAILURE(FunctionCall, Status)               \\r
+    do {                                                               \\r
+      UNIT_TEST_STATUS          UnitTestJumpStatus;                    \\r
+      BASE_LIBRARY_JUMP_BUFFER  UnitTestJumpBuffer;                    \\r
+      UnitTestJumpStatus = UNIT_TEST_SKIPPED;                          \\r
+      if (DebugAssertEnabled ()) {                                     \\r
+        gUnitTestExpectAssertFailureJumpBuffer = &UnitTestJumpBuffer;  \\r
+        if (SetJump (gUnitTestExpectAssertFailureJumpBuffer) == 0) {   \\r
+          FunctionCall;                                                \\r
+          UnitTestJumpStatus = UNIT_TEST_ERROR_TEST_FAILED;            \\r
+        } else {                                                       \\r
+          UnitTestJumpStatus = UNIT_TEST_PASSED;                       \\r
+        }                                                              \\r
+        gUnitTestExpectAssertFailureJumpBuffer = NULL;                 \\r
+      }                                                                \\r
+      if (!UnitTestExpectAssertFailure (                               \\r
+             UnitTestJumpStatus,                                       \\r
+             __FUNCTION__, DEBUG_LINE_NUMBER, __FILE__,                \\r
+             #FunctionCall, Status)) {                                 \\r
+        return UNIT_TEST_ERROR_TEST_FAILED;                            \\r
+      }                                                                \\r
+    } while (FALSE)\r
+#else\r
+#define UT_EXPECT_ASSERT_FAILURE(FunctionCall, Status)  FunctionCall;\r
+#endif\r
+\r
 /**\r
   If Expression is TRUE, then TRUE is returned.\r
   If Expression is FALSE, then an assert is triggered and the location of the\r
@@ -690,6 +740,46 @@ UnitTestAssertNotNull (
   IN CONST CHAR8  *PointerName\r
   );\r
 \r
+/**\r
+  If UnitTestStatus is UNIT_TEST_PASSED, then log an info message and return\r
+  TRUE because an ASSERT() was expected when FunctionCall was executed and an\r
+  ASSERT() was triggered. If UnitTestStatus is UNIT_TEST_SKIPPED, then log a\r
+  warning message and return TRUE because ASSERT() macros are disabled.  If\r
+  UnitTestStatus is UNIT_TEST_ERROR_TEST_FAILED, then log an error message and\r
+  return FALSE because an ASSERT() was expected when FunctionCall was executed,\r
+  but no ASSERT() conditions were triggered.  The log messages contain\r
+  FunctionName, LineNumber, and FileName strings to provide the location of the\r
+  UT_EXPECT_ASSERT_FAILURE() macro.\r
+\r
+  @param[in]  UnitTestStatus  The status from UT_EXPECT_ASSERT_FAILURE() that\r
+                              is either pass, skipped, or failed.\r
+  @param[in]  FunctionName    Null-terminated ASCII string of the function\r
+                              executing the UT_EXPECT_ASSERT_FAILURE() macro.\r
+  @param[in]  LineNumber      The source file line number of the the function\r
+                              executing the UT_EXPECT_ASSERT_FAILURE() macro.\r
+  @param[in]  FileName        Null-terminated ASCII string of the filename\r
+                              executing the UT_EXPECT_ASSERT_FAILURE() macro.\r
+  @param[in]  FunctionCall    Null-terminated ASCII string of the function call\r
+                              executed by the UT_EXPECT_ASSERT_FAILURE() macro.\r
+  @param[out] ResultStatus    Used to return the UnitTestStatus value to the\r
+                              caller of UT_EXPECT_ASSERT_FAILURE().  This is\r
+                              optional parameter that may be NULL.\r
+\r
+  @retval  TRUE   UnitTestStatus is UNIT_TEST_PASSED.\r
+  @retval  TRUE   UnitTestStatus is UNIT_TEST_SKIPPED.\r
+  @retval  FALSE  UnitTestStatus is UNIT_TEST_ERROR_TEST_FAILED.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+UnitTestExpectAssertFailure (\r
+  IN  UNIT_TEST_STATUS  UnitTestStatus,\r
+  IN  CONST CHAR8       *FunctionName,\r
+  IN  UINTN             LineNumber,\r
+  IN  CONST CHAR8       *FileName,\r
+  IN  CONST CHAR8       *FunctionCall,\r
+  OUT UNIT_TEST_STATUS  *ResultStatus  OPTIONAL\r
+  );\r
+\r
 /**\r
   Test logging macro that records an ERROR message in the test framework log.\r
   Record is associated with the currently executing test case.\r