/** Implemnet UnitTestLib log services Copyright (c) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #include #include #include #include #include #include #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); }