/** | |
Implemnet UnitTestLib log services | |
Copyright (c) Microsoft Corporation.<BR> | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#include <PiDxe.h> | |
#include <UnitTestFrameworkTypes.h> | |
#include <Library/UnitTestLib.h> | |
#include <Library/BaseLib.h> | |
#include <Library/BaseMemoryLib.h> | |
#include <Library/MemoryAllocationLib.h> | |
#include <Library/DebugLib.h> | |
#include <Library/PrintLib.h> | |
#include <Library/PcdLib.h> | |
#define UNIT_TEST_MAX_SINGLE_LOG_STRING_LENGTH (512) | |
#define UNIT_TEST_MAX_LOG_BUFFER SIZE_16KB | |
struct _UNIT_TEST_LOG_PREFIX_STRING { | |
UNIT_TEST_STATUS LogLevel; | |
CHAR8 *String; | |
}; | |
struct _UNIT_TEST_LOG_PREFIX_STRING mLogPrefixStrings[] = { | |
{ UNIT_TEST_LOG_LEVEL_ERROR, "[ERROR] " }, | |
{ UNIT_TEST_LOG_LEVEL_WARN, "[WARNING] " }, | |
{ UNIT_TEST_LOG_LEVEL_INFO, "[INFO] " }, | |
{ UNIT_TEST_LOG_LEVEL_VERBOSE, "[VERBOSE] " } | |
}; | |
// | |
// Unit-Test Log helper functions | |
// | |
STATIC | |
CONST CHAR8 * | |
GetStringForStatusLogPrefix ( | |
IN UINTN LogLevel | |
) | |
{ | |
UINTN Index; | |
CHAR8 *Result; | |
Result = NULL; | |
for (Index = 0; Index < ARRAY_SIZE (mLogPrefixStrings); Index++) { | |
if (mLogPrefixStrings[Index].LogLevel == LogLevel) { | |
Result = mLogPrefixStrings[Index].String; | |
break; | |
} | |
} | |
return Result; | |
} | |
STATIC | |
EFI_STATUS | |
AddStringToUnitTestLog ( | |
IN OUT UNIT_TEST *UnitTest, | |
IN CONST CHAR8 *String | |
) | |
{ | |
EFI_STATUS Status; | |
// | |
// Make sure that you're cooking with gas. | |
// | |
if ((UnitTest == NULL) || (String == NULL)) { | |
return EFI_INVALID_PARAMETER; | |
} | |
// If this is the first log for the test allocate log space | |
if (UnitTest->Log == NULL) { | |
UnitTestLogInit (UnitTest, NULL, 0); | |
} | |
if (UnitTest->Log == NULL) { | |
DEBUG ((DEBUG_ERROR, "Failed to allocate space for unit test log\n")); | |
ASSERT (UnitTest->Log != NULL); | |
return EFI_OUT_OF_RESOURCES; | |
} | |
Status = AsciiStrnCatS ( | |
UnitTest->Log, | |
UNIT_TEST_MAX_LOG_BUFFER / sizeof (CHAR8), | |
String, | |
UNIT_TEST_MAX_SINGLE_LOG_STRING_LENGTH | |
); | |
if (EFI_ERROR (Status)) { | |
DEBUG ((DEBUG_ERROR, "Failed to add unit test log string. Status = %r\n", Status)); | |
return Status; | |
} | |
return EFI_SUCCESS; | |
} | |
/** | |
This function is responsible for initializing the log buffer for a single test. It can | |
be used internally, but may also be consumed by the test framework to add pre-existing | |
data to a log before it's used. | |
@param[in,out] TestHandle A handle to the test being initialized. | |
@param[in] Buffer [Optional] A pointer to pre-existing log data that should | |
be used to initialize the log. Should include a NULL terminator. | |
@param[in] BufferSize [Optional] The size of the pre-existing log data. | |
**/ | |
VOID | |
EFIAPI | |
UnitTestLogInit ( | |
IN OUT UNIT_TEST *Test, | |
IN UINT8 *Buffer OPTIONAL, | |
IN UINTN BufferSize OPTIONAL | |
) | |
{ | |
// | |
// Make sure that you're cooking with gas. | |
// | |
if (Test == NULL) { | |
DEBUG ((DEBUG_ERROR, "%a called with invalid Test parameter\n", __func__)); | |
return; | |
} | |
// | |
// If this is the first log for the test allocate log space | |
// | |
if (Test->Log == NULL) { | |
Test->Log = AllocateZeroPool (UNIT_TEST_MAX_LOG_BUFFER); | |
} | |
// | |
// check again to make sure allocate worked | |
// | |
if (Test->Log == NULL) { | |
DEBUG ((DEBUG_ERROR, "Failed to allocate memory for the log\n")); | |
return; | |
} | |
if ((Buffer != NULL) && (BufferSize > 0) && (BufferSize <= UNIT_TEST_MAX_LOG_BUFFER)) { | |
CopyMem (Test->Log, Buffer, BufferSize); | |
} | |
} | |
/** | |
Test logging function that records a messages in the test framework log. | |
Record is associated with the currently executing test case. | |
@param[in] ErrorLevel The error level of the unit test log message. | |
@param[in] Format Formatting string following the format defined in the | |
MdePkg/Include/Library/PrintLib.h. | |
@param[in] ... Print args. | |
**/ | |
VOID | |
EFIAPI | |
UnitTestLog ( | |
IN UINTN ErrorLevel, | |
IN CONST CHAR8 *Format, | |
... | |
) | |
{ | |
UNIT_TEST_FRAMEWORK_HANDLE FrameworkHandle; | |
CHAR8 NewFormatString[UNIT_TEST_MAX_SINGLE_LOG_STRING_LENGTH]; | |
CHAR8 LogString[UNIT_TEST_MAX_SINGLE_LOG_STRING_LENGTH]; | |
CONST CHAR8 *LogTypePrefix; | |
VA_LIST Marker; | |
FrameworkHandle = GetActiveFrameworkHandle (); | |
if (FrameworkHandle == NULL) { | |
DEBUG ((DEBUG_ERROR, "%a - FrameworkHandle not initialized\n", __func__)); | |
return; | |
} | |
LogTypePrefix = NULL; | |
// | |
// Make sure that this unit test log level is enabled. | |
// | |
if ((ErrorLevel & (UINTN)PcdGet32 (PcdUnitTestLogLevel)) == 0) { | |
return; | |
} | |
// | |
// If we need to define a new format string... | |
// well... get to it. | |
// | |
LogTypePrefix = GetStringForStatusLogPrefix (ErrorLevel); | |
if (LogTypePrefix != NULL) { | |
AsciiSPrint (NewFormatString, sizeof (NewFormatString), "%a%a", LogTypePrefix, Format); | |
} else { | |
AsciiStrCpyS (NewFormatString, sizeof (NewFormatString), Format); | |
} | |
// | |
// Convert the message to an ASCII String | |
// | |
VA_START (Marker, Format); | |
AsciiVSPrint (LogString, sizeof (LogString), NewFormatString, Marker); | |
VA_END (Marker); | |
// | |
// Finally, add the string to the log. | |
// | |
AddStringToUnitTestLog (((UNIT_TEST_FRAMEWORK *)FrameworkHandle)->CurrentTest, LogString); | |
} |