summaryrefslogtreecommitdiffstats
path: root/UnitTestFrameworkPkg/Library/UnitTestLib/Log.c
blob: ac4e229b40716afb28938882487666c8007ec44f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/**
  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", __FUNCTION__));
    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 ();

  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);
}