| /** | |
| Implement UnitTestLib assert services | |
| Copyright (c) Microsoft Corporation.<BR> | |
| SPDX-License-Identifier: BSD-2-Clause-Patent | |
| **/ | |
| #include <Uefi.h> | |
| #include <UnitTestFrameworkTypes.h> | |
| #include <Library/UnitTestLib.h> | |
| #include <Library/BaseLib.h> | |
| #include <Library/BaseMemoryLib.h> | |
| #include <Library/DebugLib.h> | |
| #include <Library/PrintLib.h> | |
| extern BASE_LIBRARY_JUMP_BUFFER gUnitTestJumpBuffer; | |
| STATIC | |
| EFI_STATUS | |
| AddUnitTestFailure ( | |
| IN OUT UNIT_TEST *UnitTest, | |
| IN CONST CHAR8 *FailureMessage, | |
| IN FAILURE_TYPE FailureType | |
| ) | |
| { | |
| // | |
| // Make sure that you're cooking with gas. | |
| // | |
| if ((UnitTest == NULL) || (FailureMessage == NULL)) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| UnitTest->FailureType = FailureType; | |
| AsciiStrCpyS ( | |
| &UnitTest->FailureMessage[0], | |
| UNIT_TEST_MAX_STRING_LENGTH, | |
| FailureMessage | |
| ); | |
| return EFI_SUCCESS; | |
| } | |
| STATIC | |
| VOID | |
| EFIAPI | |
| UnitTestLogFailure ( | |
| IN FAILURE_TYPE FailureType, | |
| IN CONST CHAR8 *Format, | |
| ... | |
| ) | |
| { | |
| UNIT_TEST_FRAMEWORK_HANDLE FrameworkHandle; | |
| CHAR8 LogString[UNIT_TEST_MAX_STRING_LENGTH]; | |
| VA_LIST Marker; | |
| // | |
| // 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 | |
| // | |
| VA_START (Marker, Format); | |
| AsciiVSPrint (LogString, sizeof (LogString), Format, Marker); | |
| VA_END (Marker); | |
| // | |
| // Finally, add the string to the log. | |
| // | |
| AddUnitTestFailure ( | |
| ((UNIT_TEST_FRAMEWORK *)FrameworkHandle)->CurrentTest, | |
| LogString, | |
| FailureType | |
| ); | |
| LongJump (&gUnitTestJumpBuffer, 1); | |
| } | |
| /** | |
| If Expression is TRUE, then TRUE is returned. | |
| If Expression is FALSE, then an assert is triggered and the location of the | |
| assert provided by FunctionName, LineNumber, FileName, and Description are | |
| recorded and FALSE is returned. | |
| @param[in] Expression The BOOLEAN result of the expression evaluation. | |
| @param[in] FunctionName Null-terminated ASCII string of the function | |
| executing the assert macro. | |
| @param[in] LineNumber The source file line number of the assert macro. | |
| @param[in] FileName Null-terminated ASCII string of the filename | |
| executing the assert macro. | |
| @param[in] Description Null-terminated ASCII string of the expression being | |
| evaluated. | |
| @retval TRUE Expression is TRUE. | |
| @retval FALSE Expression is FALSE. | |
| **/ | |
| BOOLEAN | |
| EFIAPI | |
| UnitTestAssertTrue ( | |
| IN BOOLEAN Expression, | |
| IN CONST CHAR8 *FunctionName, | |
| IN UINTN LineNumber, | |
| IN CONST CHAR8 *FileName, | |
| IN CONST CHAR8 *Description | |
| ) | |
| { | |
| if (!Expression) { | |
| UT_LOG_ERROR ( | |
| "[ASSERT FAIL] %a:%d: Expression (%a) is not TRUE!\n", | |
| FileName, | |
| LineNumber, | |
| Description | |
| ); | |
| UnitTestLogFailure ( | |
| FAILURETYPE_ASSERTTRUE, | |
| "%a:%d: Expression (%a) is not TRUE!\n", | |
| FileName, | |
| LineNumber, | |
| Description | |
| ); | |
| } | |
| return Expression; | |
| } | |
| /** | |
| If Expression is FALSE, then TRUE is returned. | |
| If Expression is TRUE, then an assert is triggered and the location of the | |
| assert provided by FunctionName, LineNumber, FileName, and Description are | |
| recorded and FALSE is returned. | |
| @param[in] Expression The BOOLEAN result of the expression evaluation. | |
| @param[in] FunctionName Null-terminated ASCII string of the function | |
| executing the assert macro. | |
| @param[in] LineNumber The source file line number of the assert macro. | |
| @param[in] FileName Null-terminated ASCII string of the filename | |
| executing the assert macro. | |
| @param[in] Description Null-terminated ASCII string of the expression being | |
| evaluated. | |
| @retval TRUE Expression is FALSE. | |
| @retval FALSE Expression is TRUE. | |
| **/ | |
| BOOLEAN | |
| EFIAPI | |
| UnitTestAssertFalse ( | |
| IN BOOLEAN Expression, | |
| IN CONST CHAR8 *FunctionName, | |
| IN UINTN LineNumber, | |
| IN CONST CHAR8 *FileName, | |
| IN CONST CHAR8 *Description | |
| ) | |
| { | |
| if (Expression) { | |
| UT_LOG_ERROR ( | |
| "[ASSERT FAIL] %a:%d: Expression (%a) is not FALSE!\n", | |
| FileName, | |
| LineNumber, | |
| Description | |
| ); | |
| UnitTestLogFailure ( | |
| FAILURETYPE_ASSERTFALSE, | |
| "%a:%d: Expression(%a) is not FALSE!\n", | |
| FileName, | |
| LineNumber, | |
| Description | |
| ); | |
| } | |
| return !Expression; | |
| } | |
| /** | |
| If Status is not an EFI_ERROR(), then TRUE is returned. | |
| If Status is an EFI_ERROR(), then an assert is triggered and the location of | |
| the assert provided by FunctionName, LineNumber, FileName, and Description are | |
| recorded and FALSE is returned. | |
| @param[in] Status The EFI_STATUS value to evaluate. | |
| @param[in] FunctionName Null-terminated ASCII string of the function | |
| executing the assert macro. | |
| @param[in] LineNumber The source file line number of the assert macro. | |
| @param[in] FileName Null-terminated ASCII string of the filename | |
| executing the assert macro. | |
| @param[in] Description Null-terminated ASCII string of the status | |
| expression being evaluated. | |
| @retval TRUE Status is not an EFI_ERROR(). | |
| @retval FALSE Status is an EFI_ERROR(). | |
| **/ | |
| BOOLEAN | |
| EFIAPI | |
| UnitTestAssertNotEfiError ( | |
| IN EFI_STATUS Status, | |
| IN CONST CHAR8 *FunctionName, | |
| IN UINTN LineNumber, | |
| IN CONST CHAR8 *FileName, | |
| IN CONST CHAR8 *Description | |
| ) | |
| { | |
| if (EFI_ERROR (Status)) { | |
| UT_LOG_ERROR ( | |
| "[ASSERT FAIL] %a:%d: Status '%a' is EFI_ERROR (%r)!\n", | |
| FileName, | |
| LineNumber, | |
| Description, | |
| Status | |
| ); | |
| UnitTestLogFailure ( | |
| FAILURETYPE_ASSERTNOTEFIERROR, | |
| "%a:%d: Status '%a' is EFI_ERROR (%r)!\n", | |
| FileName, | |
| LineNumber, | |
| Description, | |
| Status | |
| ); | |
| } | |
| return !EFI_ERROR (Status); | |
| } | |
| /** | |
| If ValueA is equal ValueB, then TRUE is returned. | |
| If ValueA is not equal to ValueB, then an assert is triggered and the location | |
| of the assert provided by FunctionName, LineNumber, FileName, DescriptionA, | |
| and DescriptionB are recorded and FALSE is returned. | |
| @param[in] ValueA 64-bit value. | |
| @param[in] ValueB 64-bit value. | |
| @param[in] FunctionName Null-terminated ASCII string of the function | |
| executing the assert macro. | |
| @param[in] LineNumber The source file line number of the assert macro. | |
| @param[in] FileName Null-terminated ASCII string of the filename | |
| executing the assert macro. | |
| @param[in] DescriptionA Null-terminated ASCII string that is a description | |
| of ValueA. | |
| @param[in] DescriptionB Null-terminated ASCII string that is a description | |
| of ValueB. | |
| @retval TRUE ValueA is equal to ValueB. | |
| @retval FALSE ValueA is not equal to ValueB. | |
| **/ | |
| BOOLEAN | |
| EFIAPI | |
| UnitTestAssertEqual ( | |
| IN UINT64 ValueA, | |
| IN UINT64 ValueB, | |
| IN CONST CHAR8 *FunctionName, | |
| IN UINTN LineNumber, | |
| IN CONST CHAR8 *FileName, | |
| IN CONST CHAR8 *DescriptionA, | |
| IN CONST CHAR8 *DescriptionB | |
| ) | |
| { | |
| if (ValueA != ValueB) { | |
| UT_LOG_ERROR ( | |
| "[ASSERT FAIL] %a:%d: Value %a != %a (%d != %d)!\n", | |
| FileName, | |
| LineNumber, | |
| DescriptionA, | |
| DescriptionB, | |
| ValueA, | |
| ValueB | |
| ); | |
| UnitTestLogFailure ( | |
| FAILURETYPE_ASSERTEQUAL, | |
| "%a:%d: Value %a != %a (%d != %d)!\n", | |
| FileName, | |
| LineNumber, | |
| DescriptionA, | |
| DescriptionB, | |
| ValueA, | |
| ValueB | |
| ); | |
| } | |
| return (ValueA == ValueB); | |
| } | |
| /** | |
| If the contents of BufferA are identical to the contents of BufferB, then TRUE | |
| is returned. If the contents of BufferA are not identical to the contents of | |
| BufferB, then an assert is triggered and the location of the assert provided | |
| by FunctionName, LineNumber, FileName, DescriptionA, and DescriptionB are | |
| recorded and FALSE is returned. | |
| @param[in] BufferA Pointer to a buffer for comparison. | |
| @param[in] BufferB Pointer to a buffer for comparison. | |
| @param[in] Length Number of bytes to compare in BufferA and BufferB. | |
| @param[in] FunctionName Null-terminated ASCII string of the function | |
| executing the assert macro. | |
| @param[in] LineNumber The source file line number of the assert macro. | |
| @param[in] FileName Null-terminated ASCII string of the filename | |
| executing the assert macro. | |
| @param[in] DescriptionA Null-terminated ASCII string that is a description | |
| of BufferA. | |
| @param[in] DescriptionB Null-terminated ASCII string that is a description | |
| of BufferB. | |
| @retval TRUE The contents of BufferA are identical to the contents of | |
| BufferB. | |
| @retval FALSE The contents of BufferA are not identical to the contents of | |
| BufferB. | |
| **/ | |
| BOOLEAN | |
| EFIAPI | |
| UnitTestAssertMemEqual ( | |
| IN VOID *BufferA, | |
| IN VOID *BufferB, | |
| IN UINTN Length, | |
| IN CONST CHAR8 *FunctionName, | |
| IN UINTN LineNumber, | |
| IN CONST CHAR8 *FileName, | |
| IN CONST CHAR8 *DescriptionA, | |
| IN CONST CHAR8 *DescriptionB | |
| ) | |
| { | |
| if (CompareMem (BufferA, BufferB, Length) != 0) { | |
| UT_LOG_ERROR ( | |
| "[ASSERT FAIL] %a:%d: Value %a != %a for length %d bytes!\n", | |
| FileName, | |
| LineNumber, | |
| DescriptionA, | |
| DescriptionB, | |
| Length | |
| ); | |
| UnitTestLogFailure ( | |
| FAILURETYPE_ASSERTEQUAL, | |
| "%a:%d: Memory at %a != %a for length %d bytes!\n", | |
| FileName, | |
| LineNumber, | |
| DescriptionA, | |
| DescriptionB, | |
| Length | |
| ); | |
| return FALSE; | |
| } | |
| return TRUE; | |
| } | |
| /** | |
| If ValueA is not equal ValueB, then TRUE is returned. | |
| If ValueA is equal to ValueB, then an assert is triggered and the location | |
| of the assert provided by FunctionName, LineNumber, FileName, DescriptionA | |
| and DescriptionB are recorded and FALSE is returned. | |
| @param[in] ValueA 64-bit value. | |
| @param[in] ValueB 64-bit value. | |
| @param[in] FunctionName Null-terminated ASCII string of the function | |
| executing the assert macro. | |
| @param[in] LineNumber The source file line number of the assert macro. | |
| @param[in] FileName Null-terminated ASCII string of the filename | |
| executing the assert macro. | |
| @param[in] DescriptionA Null-terminated ASCII string that is a description | |
| of ValueA. | |
| @param[in] DescriptionB Null-terminated ASCII string that is a description | |
| of ValueB. | |
| @retval TRUE ValueA is not equal to ValueB. | |
| @retval FALSE ValueA is equal to ValueB. | |
| **/ | |
| BOOLEAN | |
| EFIAPI | |
| UnitTestAssertNotEqual ( | |
| IN UINT64 ValueA, | |
| IN UINT64 ValueB, | |
| IN CONST CHAR8 *FunctionName, | |
| IN UINTN LineNumber, | |
| IN CONST CHAR8 *FileName, | |
| IN CONST CHAR8 *DescriptionA, | |
| IN CONST CHAR8 *DescriptionB | |
| ) | |
| { | |
| if (ValueA == ValueB) { | |
| UT_LOG_ERROR ( | |
| "[ASSERT FAIL] %a:%d: Value %a == %a (%d == %d)!\n", | |
| FileName, | |
| LineNumber, | |
| DescriptionA, | |
| DescriptionB, | |
| ValueA, | |
| ValueB | |
| ); | |
| UnitTestLogFailure ( | |
| FAILURETYPE_ASSERTNOTEQUAL, | |
| "%a:%d: Value %a == %a (%d == %d)!\n", | |
| FileName, | |
| LineNumber, | |
| DescriptionA, | |
| DescriptionB, | |
| ValueA, | |
| ValueB | |
| ); | |
| } | |
| return (ValueA != ValueB); | |
| } | |
| /** | |
| If Status is equal to Expected, then TRUE is returned. | |
| If Status is not equal to Expected, then an assert is triggered and the | |
| location of the assert provided by FunctionName, LineNumber, FileName, and | |
| Description are recorded and FALSE is returned. | |
| @param[in] Status EFI_STATUS value returned from an API under test. | |
| @param[in] Expected The expected EFI_STATUS return value from an API | |
| under test. | |
| @param[in] FunctionName Null-terminated ASCII string of the function | |
| executing the assert macro. | |
| @param[in] LineNumber The source file line number of the assert macro. | |
| @param[in] FileName Null-terminated ASCII string of the filename | |
| executing the assert macro. | |
| @param[in] Description Null-terminated ASCII string that is a description | |
| of Status. | |
| @retval TRUE Status is equal to Expected. | |
| @retval FALSE Status is not equal to Expected. | |
| **/ | |
| BOOLEAN | |
| EFIAPI | |
| UnitTestAssertStatusEqual ( | |
| IN EFI_STATUS Status, | |
| IN EFI_STATUS Expected, | |
| IN CONST CHAR8 *FunctionName, | |
| IN UINTN LineNumber, | |
| IN CONST CHAR8 *FileName, | |
| IN CONST CHAR8 *Description | |
| ) | |
| { | |
| if (Status != Expected) { | |
| UT_LOG_ERROR ( | |
| "[ASSERT FAIL] %a:%d: Status '%a' is %r, should be %r!\n", | |
| FileName, | |
| LineNumber, | |
| Description, | |
| Status, | |
| Expected | |
| ); | |
| UnitTestLogFailure ( | |
| FAILURETYPE_ASSERTSTATUSEQUAL, | |
| "%a:%d: Status '%a' is %r, should be %r!\n", | |
| FileName, | |
| LineNumber, | |
| Description, | |
| Status, | |
| Expected | |
| ); | |
| } | |
| return (Status == Expected); | |
| } | |
| /** | |
| If Pointer is not equal to NULL, then TRUE is returned. | |
| If Pointer is equal to NULL, then an assert is triggered and the location of | |
| the assert provided by FunctionName, LineNumber, FileName, and PointerName | |
| are recorded and FALSE is returned. | |
| @param[in] Pointer Pointer value to be checked against NULL. | |
| @param[in] Expected The expected EFI_STATUS return value from a function | |
| under test. | |
| @param[in] FunctionName Null-terminated ASCII string of the function | |
| executing the assert macro. | |
| @param[in] LineNumber The source file line number of the assert macro. | |
| @param[in] FileName Null-terminated ASCII string of the filename | |
| executing the assert macro. | |
| @param[in] PointerName Null-terminated ASCII string that is a description | |
| of Pointer. | |
| @retval TRUE Pointer is not equal to NULL. | |
| @retval FALSE Pointer is equal to NULL. | |
| **/ | |
| BOOLEAN | |
| EFIAPI | |
| UnitTestAssertNotNull ( | |
| IN VOID *Pointer, | |
| IN CONST CHAR8 *FunctionName, | |
| IN UINTN LineNumber, | |
| IN CONST CHAR8 *FileName, | |
| IN CONST CHAR8 *PointerName | |
| ) | |
| { | |
| if (Pointer == NULL) { | |
| UT_LOG_ERROR ( | |
| "[ASSERT FAIL] %a:%d: Pointer (%a) is NULL!\n", | |
| FileName, | |
| LineNumber, | |
| PointerName | |
| ); | |
| UnitTestLogFailure ( | |
| FAILURETYPE_ASSERTNOTNULL, | |
| "%a:%d: Pointer (%a) is NULL!\n", | |
| FileName, | |
| LineNumber, | |
| PointerName | |
| ); | |
| } | |
| return (Pointer != NULL); | |
| } | |
| /** | |
| If UnitTestStatus is UNIT_TEST_PASSED, then log an info message and return | |
| TRUE because an ASSERT() was expected when FunctionCall was executed and an | |
| ASSERT() was triggered. If UnitTestStatus is UNIT_TEST_SKIPPED, then log a | |
| warning message and return TRUE because ASSERT() macros are disabled. If | |
| UnitTestStatus is UNIT_TEST_ERROR_TEST_FAILED, then log an error message and | |
| return FALSE because an ASSERT() was expected when FunctionCall was executed, | |
| but no ASSERT() conditions were triggered. The log messages contain | |
| FunctionName, LineNumber, and FileName strings to provide the location of the | |
| UT_EXPECT_ASSERT_FAILURE() macro. | |
| @param[in] UnitTestStatus The status from UT_EXPECT_ASSERT_FAILURE() that | |
| is either pass, skipped, or failed. | |
| @param[in] FunctionName Null-terminated ASCII string of the function | |
| executing the UT_EXPECT_ASSERT_FAILURE() macro. | |
| @param[in] LineNumber The source file line number of the the function | |
| executing the UT_EXPECT_ASSERT_FAILURE() macro. | |
| @param[in] FileName Null-terminated ASCII string of the filename | |
| executing the UT_EXPECT_ASSERT_FAILURE() macro. | |
| @param[in] FunctionCall Null-terminated ASCII string of the function call | |
| executed by the UT_EXPECT_ASSERT_FAILURE() macro. | |
| @param[out] ResultStatus Used to return the UnitTestStatus value to the | |
| caller of UT_EXPECT_ASSERT_FAILURE(). This is | |
| optional parameter that may be NULL. | |
| @retval TRUE UnitTestStatus is UNIT_TEST_PASSED. | |
| @retval TRUE UnitTestStatus is UNIT_TEST_SKIPPED. | |
| @retval FALSE UnitTestStatus is UNIT_TEST_ERROR_TEST_FAILED. | |
| **/ | |
| BOOLEAN | |
| EFIAPI | |
| UnitTestExpectAssertFailure ( | |
| IN UNIT_TEST_STATUS UnitTestStatus, | |
| IN CONST CHAR8 *FunctionName, | |
| IN UINTN LineNumber, | |
| IN CONST CHAR8 *FileName, | |
| IN CONST CHAR8 *FunctionCall, | |
| OUT UNIT_TEST_STATUS *ResultStatus OPTIONAL | |
| ) | |
| { | |
| if (ResultStatus != NULL) { | |
| *ResultStatus = UnitTestStatus; | |
| } | |
| if (UnitTestStatus == UNIT_TEST_PASSED) { | |
| UT_LOG_INFO ( | |
| "[ASSERT PASS] %a:%d: UT_EXPECT_ASSERT_FAILURE(%a) detected expected assert\n", | |
| FileName, | |
| LineNumber, | |
| FunctionCall | |
| ); | |
| } | |
| if (UnitTestStatus == UNIT_TEST_SKIPPED) { | |
| UT_LOG_WARNING ( | |
| "[ASSERT WARN] %a:%d: UT_EXPECT_ASSERT_FAILURE(%a) disabled\n", | |
| FileName, | |
| LineNumber, | |
| FunctionCall | |
| ); | |
| } | |
| if (UnitTestStatus == UNIT_TEST_ERROR_TEST_FAILED) { | |
| UT_LOG_ERROR ( | |
| "[ASSERT FAIL] %a:%d: Function call (%a) did not ASSERT()!\n", | |
| FileName, | |
| LineNumber, | |
| FunctionCall | |
| ); | |
| UnitTestLogFailure ( | |
| FAILURETYPE_EXPECTASSERT, | |
| "%a:%d: Function call (%a) did not ASSERT()!\n", | |
| FileName, | |
| LineNumber, | |
| FunctionCall | |
| ); | |
| } | |
| return (UnitTestStatus != UNIT_TEST_ERROR_TEST_FAILED); | |
| } |