///\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
/// 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
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
\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
\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
@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
@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
@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
\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
@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
\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
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