1 /**
2 Implement UnitTestLib assert services
3
4 Copyright (c) Microsoft Corporation.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6 **/
7
8 #include <Uefi.h>
9 #include <UnitTestFrameworkTypes.h>
10 #include <Library/UnitTestLib.h>
11 #include <Library/BaseLib.h>
12 #include <Library/BaseMemoryLib.h>
13 #include <Library/DebugLib.h>
14 #include <Library/PrintLib.h>
15
16 extern BASE_LIBRARY_JUMP_BUFFER gUnitTestJumpBuffer;
17
18 STATIC
19 EFI_STATUS
AddUnitTestFailure(IN OUT UNIT_TEST * UnitTest,IN CONST CHAR8 * FailureMessage,IN FAILURE_TYPE FailureType)20 AddUnitTestFailure (
21 IN OUT UNIT_TEST *UnitTest,
22 IN CONST CHAR8 *FailureMessage,
23 IN FAILURE_TYPE FailureType
24 )
25 {
26 //
27 // Make sure that you're cooking with gas.
28 //
29 if (UnitTest == NULL || FailureMessage == NULL) {
30 return EFI_INVALID_PARAMETER;
31 }
32
33 UnitTest->FailureType = FailureType;
34 AsciiStrCpyS (
35 &UnitTest->FailureMessage[0],
36 UNIT_TEST_TESTFAILUREMSG_LENGTH,
37 FailureMessage
38 );
39
40 return EFI_SUCCESS;
41 }
42
43 STATIC
44 VOID
UnitTestLogFailure(IN FAILURE_TYPE FailureType,IN CONST CHAR8 * Format,...)45 UnitTestLogFailure (
46 IN FAILURE_TYPE FailureType,
47 IN CONST CHAR8 *Format,
48 ...
49 )
50 {
51 UNIT_TEST_FRAMEWORK_HANDLE FrameworkHandle;
52 CHAR8 LogString[UNIT_TEST_TESTFAILUREMSG_LENGTH];
53 VA_LIST Marker;
54
55 //
56 // Get active Framework handle
57 //
58 FrameworkHandle = GetActiveFrameworkHandle ();
59
60 //
61 // Convert the message to an ASCII String
62 //
63 VA_START (Marker, Format);
64 AsciiVSPrint (LogString, sizeof (LogString), Format, Marker);
65 VA_END (Marker);
66
67 //
68 // Finally, add the string to the log.
69 //
70 AddUnitTestFailure (
71 ((UNIT_TEST_FRAMEWORK *)FrameworkHandle)->CurrentTest,
72 LogString,
73 FailureType
74 );
75
76 LongJump (&gUnitTestJumpBuffer, 1);
77 }
78
79 /**
80 If Expression is TRUE, then TRUE is returned.
81 If Expression is FALSE, then an assert is triggered and the location of the
82 assert provided by FunctionName, LineNumber, FileName, and Description are
83 recorded and FALSE is returned.
84
85 @param[in] Expression The BOOLEAN result of the expression evaluation.
86 @param[in] FunctionName Null-terminated ASCII string of the function
87 executing the assert macro.
88 @param[in] LineNumber The source file line number of the assert macro.
89 @param[in] FileName Null-terminated ASCII string of the filename
90 executing the assert macro.
91 @param[in] Description Null-terminated ASCII string of the expression being
92 evaluated.
93
94 @retval TRUE Expression is TRUE.
95 @retval FALSE Expression is FALSE.
96 **/
97 BOOLEAN
98 EFIAPI
UnitTestAssertTrue(IN BOOLEAN Expression,IN CONST CHAR8 * FunctionName,IN UINTN LineNumber,IN CONST CHAR8 * FileName,IN CONST CHAR8 * Description)99 UnitTestAssertTrue (
100 IN BOOLEAN Expression,
101 IN CONST CHAR8 *FunctionName,
102 IN UINTN LineNumber,
103 IN CONST CHAR8 *FileName,
104 IN CONST CHAR8 *Description
105 )
106 {
107 if (!Expression) {
108 UT_LOG_ERROR (
109 "[ASSERT FAIL] %a:%d: Expression (%a) is not TRUE!\n",
110 FileName,
111 LineNumber,
112 Description
113 );
114 UnitTestLogFailure (
115 FAILURETYPE_ASSERTTRUE,
116 "%a:%d: Expression (%a) is not TRUE!\n",
117 FileName,
118 LineNumber,
119 Description
120 );
121 }
122 return Expression;
123 }
124
125 /**
126 If Expression is FALSE, then TRUE is returned.
127 If Expression is TRUE, then an assert is triggered and the location of the
128 assert provided by FunctionName, LineNumber, FileName, and Description are
129 recorded and FALSE is returned.
130
131 @param[in] Expression The BOOLEAN result of the expression evaluation.
132 @param[in] FunctionName Null-terminated ASCII string of the function
133 executing the assert macro.
134 @param[in] LineNumber The source file line number of the assert macro.
135 @param[in] FileName Null-terminated ASCII string of the filename
136 executing the assert macro.
137 @param[in] Description Null-terminated ASCII string of the expression being
138 evaluated.
139
140 @retval TRUE Expression is FALSE.
141 @retval FALSE Expression is TRUE.
142 **/
143 BOOLEAN
144 EFIAPI
UnitTestAssertFalse(IN BOOLEAN Expression,IN CONST CHAR8 * FunctionName,IN UINTN LineNumber,IN CONST CHAR8 * FileName,IN CONST CHAR8 * Description)145 UnitTestAssertFalse (
146 IN BOOLEAN Expression,
147 IN CONST CHAR8 *FunctionName,
148 IN UINTN LineNumber,
149 IN CONST CHAR8 *FileName,
150 IN CONST CHAR8 *Description
151 )
152 {
153 if (Expression) {
154 UT_LOG_ERROR (
155 "[ASSERT FAIL] %a:%d: Expression (%a) is not FALSE!\n",
156 FileName,
157 LineNumber,
158 Description
159 );
160 UnitTestLogFailure (
161 FAILURETYPE_ASSERTFALSE,
162 "%a:%d: Expression(%a) is not FALSE!\n",
163 FileName,
164 LineNumber,
165 Description
166 );
167 }
168 return !Expression;
169 }
170
171 /**
172 If Status is not an EFI_ERROR(), then TRUE is returned.
173 If Status is an EFI_ERROR(), then an assert is triggered and the location of
174 the assert provided by FunctionName, LineNumber, FileName, and Description are
175 recorded and FALSE is returned.
176
177 @param[in] Status The EFI_STATUS value to evaluate.
178 @param[in] FunctionName Null-terminated ASCII string of the function
179 executing the assert macro.
180 @param[in] LineNumber The source file line number of the assert macro.
181 @param[in] FileName Null-terminated ASCII string of the filename
182 executing the assert macro.
183 @param[in] Description Null-terminated ASCII string of the status
184 expression being evaluated.
185
186 @retval TRUE Status is not an EFI_ERROR().
187 @retval FALSE Status is an EFI_ERROR().
188 **/
189 BOOLEAN
190 EFIAPI
UnitTestAssertNotEfiError(IN EFI_STATUS Status,IN CONST CHAR8 * FunctionName,IN UINTN LineNumber,IN CONST CHAR8 * FileName,IN CONST CHAR8 * Description)191 UnitTestAssertNotEfiError (
192 IN EFI_STATUS Status,
193 IN CONST CHAR8 *FunctionName,
194 IN UINTN LineNumber,
195 IN CONST CHAR8 *FileName,
196 IN CONST CHAR8 *Description
197 )
198 {
199 if (EFI_ERROR (Status)) {
200 UT_LOG_ERROR (
201 "[ASSERT FAIL] %a:%d: Status '%a' is EFI_ERROR (%r)!\n",
202 FileName,
203 LineNumber,
204 Description,
205 Status
206 );
207 UnitTestLogFailure (
208 FAILURETYPE_ASSERTNOTEFIERROR,
209 "%a:%d: Status '%a' is EFI_ERROR (%r)!\n",
210 FileName,
211 LineNumber,
212 Description,
213 Status
214 );
215 }
216 return !EFI_ERROR( Status );
217 }
218
219 /**
220 If ValueA is equal ValueB, then TRUE is returned.
221 If ValueA is not equal to ValueB, then an assert is triggered and the location
222 of the assert provided by FunctionName, LineNumber, FileName, DescriptionA,
223 and DescriptionB are recorded and FALSE is returned.
224
225 @param[in] ValueA 64-bit value.
226 @param[in] ValueB 64-bit value.
227 @param[in] FunctionName Null-terminated ASCII string of the function
228 executing the assert macro.
229 @param[in] LineNumber The source file line number of the assert macro.
230 @param[in] FileName Null-terminated ASCII string of the filename
231 executing the assert macro.
232 @param[in] DescriptionA Null-terminated ASCII string that is a description
233 of ValueA.
234 @param[in] DescriptionB Null-terminated ASCII string that is a description
235 of ValueB.
236
237 @retval TRUE ValueA is equal to ValueB.
238 @retval FALSE ValueA is not equal to ValueB.
239 **/
240 BOOLEAN
241 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)242 UnitTestAssertEqual (
243 IN UINT64 ValueA,
244 IN UINT64 ValueB,
245 IN CONST CHAR8 *FunctionName,
246 IN UINTN LineNumber,
247 IN CONST CHAR8 *FileName,
248 IN CONST CHAR8 *DescriptionA,
249 IN CONST CHAR8 *DescriptionB
250 )
251 {
252 if (ValueA != ValueB) {
253 UT_LOG_ERROR (
254 "[ASSERT FAIL] %a:%d: Value %a != %a (%d != %d)!\n",
255 FileName,
256 LineNumber,
257 DescriptionA,
258 DescriptionB,
259 ValueA,
260 ValueB
261 );
262 UnitTestLogFailure (
263 FAILURETYPE_ASSERTEQUAL,
264 "%a:%d: Value %a != %a (%d != %d)!\n",
265 FileName,
266 LineNumber,
267 DescriptionA,
268 DescriptionB,
269 ValueA,
270 ValueB
271 );
272 }
273 return (ValueA == ValueB);
274 }
275
276 /**
277 If the contents of BufferA are identical to the contents of BufferB, then TRUE
278 is returned. If the contents of BufferA are not identical to the contents of
279 BufferB, then an assert is triggered and the location of the assert provided
280 by FunctionName, LineNumber, FileName, DescriptionA, and DescriptionB are
281 recorded and FALSE is returned.
282
283 @param[in] BufferA Pointer to a buffer for comparison.
284 @param[in] BufferB Pointer to a buffer for comparison.
285 @param[in] Length Number of bytes to compare in BufferA and BufferB.
286 @param[in] FunctionName Null-terminated ASCII string of the function
287 executing the assert macro.
288 @param[in] LineNumber The source file line number of the assert macro.
289 @param[in] FileName Null-terminated ASCII string of the filename
290 executing the assert macro.
291 @param[in] DescriptionA Null-terminated ASCII string that is a description
292 of BufferA.
293 @param[in] DescriptionB Null-terminated ASCII string that is a description
294 of BufferB.
295
296 @retval TRUE The contents of BufferA are identical to the contents of
297 BufferB.
298 @retval FALSE The contents of BufferA are not identical to the contents of
299 BufferB.
300 **/
301 BOOLEAN
302 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)303 UnitTestAssertMemEqual (
304 IN VOID *BufferA,
305 IN VOID *BufferB,
306 IN UINTN Length,
307 IN CONST CHAR8 *FunctionName,
308 IN UINTN LineNumber,
309 IN CONST CHAR8 *FileName,
310 IN CONST CHAR8 *DescriptionA,
311 IN CONST CHAR8 *DescriptionB
312 )
313 {
314 if (CompareMem(BufferA, BufferB, Length) != 0) {
315 UT_LOG_ERROR (
316 "[ASSERT FAIL] %a:%d: Value %a != %a for length %d bytes!\n",
317 FileName,
318 LineNumber,
319 DescriptionA,
320 DescriptionB,
321 Length
322 );
323 UnitTestLogFailure (
324 FAILURETYPE_ASSERTEQUAL,
325 "%a:%d: Memory at %a != %a for length %d bytes!\n",
326 FileName,
327 LineNumber,
328 DescriptionA,
329 DescriptionB,
330 Length
331 );
332 return FALSE;
333 }
334 return TRUE;
335 }
336
337 /**
338 If ValueA is not equal ValueB, then TRUE is returned.
339 If ValueA is equal to ValueB, then an assert is triggered and the location
340 of the assert provided by FunctionName, LineNumber, FileName, DescriptionA
341 and DescriptionB are recorded and FALSE is returned.
342
343 @param[in] ValueA 64-bit value.
344 @param[in] ValueB 64-bit value.
345 @param[in] FunctionName Null-terminated ASCII string of the function
346 executing the assert macro.
347 @param[in] LineNumber The source file line number of the assert macro.
348 @param[in] FileName Null-terminated ASCII string of the filename
349 executing the assert macro.
350 @param[in] DescriptionA Null-terminated ASCII string that is a description
351 of ValueA.
352 @param[in] DescriptionB Null-terminated ASCII string that is a description
353 of ValueB.
354
355 @retval TRUE ValueA is not equal to ValueB.
356 @retval FALSE ValueA is equal to ValueB.
357 **/
358 BOOLEAN
359 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)360 UnitTestAssertNotEqual (
361 IN UINT64 ValueA,
362 IN UINT64 ValueB,
363 IN CONST CHAR8 *FunctionName,
364 IN UINTN LineNumber,
365 IN CONST CHAR8 *FileName,
366 IN CONST CHAR8 *DescriptionA,
367 IN CONST CHAR8 *DescriptionB
368 )
369 {
370 if (ValueA == ValueB) {
371 UT_LOG_ERROR (
372 "[ASSERT FAIL] %a:%d: Value %a == %a (%d == %d)!\n",
373 FileName,
374 LineNumber,
375 DescriptionA,
376 DescriptionB,
377 ValueA,
378 ValueB
379 );
380 UnitTestLogFailure (
381 FAILURETYPE_ASSERTNOTEQUAL,
382 "%a:%d: Value %a == %a (%d == %d)!\n",
383 FileName,
384 LineNumber,
385 DescriptionA,
386 DescriptionB,
387 ValueA,
388 ValueB
389 );
390 }
391 return (ValueA != ValueB);
392 }
393
394 /**
395 If Status is equal to Expected, then TRUE is returned.
396 If Status is not equal to Expected, then an assert is triggered and the
397 location of the assert provided by FunctionName, LineNumber, FileName, and
398 Description are recorded and FALSE is returned.
399
400 @param[in] Status EFI_STATUS value returned from an API under test.
401 @param[in] Expected The expected EFI_STATUS return value from an API
402 under test.
403 @param[in] FunctionName Null-terminated ASCII string of the function
404 executing the assert macro.
405 @param[in] LineNumber The source file line number of the assert macro.
406 @param[in] FileName Null-terminated ASCII string of the filename
407 executing the assert macro.
408 @param[in] Description Null-terminated ASCII string that is a description
409 of Status.
410
411 @retval TRUE Status is equal to Expected.
412 @retval FALSE Status is not equal to Expected.
413 **/
414 BOOLEAN
415 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)416 UnitTestAssertStatusEqual (
417 IN EFI_STATUS Status,
418 IN EFI_STATUS Expected,
419 IN CONST CHAR8 *FunctionName,
420 IN UINTN LineNumber,
421 IN CONST CHAR8 *FileName,
422 IN CONST CHAR8 *Description
423 )
424 {
425 if (Status != Expected) {
426 UT_LOG_ERROR (
427 "[ASSERT FAIL] %a:%d: Status '%a' is %r, should be %r!\n",
428 FileName,
429 LineNumber,
430 Description,
431 Status,
432 Expected
433 );
434 UnitTestLogFailure (
435 FAILURETYPE_ASSERTSTATUSEQUAL,
436 "%a:%d: Status '%a' is %r, should be %r!\n",
437 FileName,
438 LineNumber,
439 Description,
440 Status,
441 Expected
442 );
443 }
444 return (Status == Expected);
445 }
446
447 /**
448 If Pointer is not equal to NULL, then TRUE is returned.
449 If Pointer is equal to NULL, then an assert is triggered and the location of
450 the assert provided by FunctionName, LineNumber, FileName, and PointerName
451 are recorded and FALSE is returned.
452
453 @param[in] Pointer Pointer value to be checked against NULL.
454 @param[in] Expected The expected EFI_STATUS return value from a function
455 under test.
456 @param[in] FunctionName Null-terminated ASCII string of the function
457 executing the assert macro.
458 @param[in] LineNumber The source file line number of the assert macro.
459 @param[in] FileName Null-terminated ASCII string of the filename
460 executing the assert macro.
461 @param[in] PointerName Null-terminated ASCII string that is a description
462 of Pointer.
463
464 @retval TRUE Pointer is not equal to NULL.
465 @retval FALSE Pointer is equal to NULL.
466 **/
467 BOOLEAN
468 EFIAPI
UnitTestAssertNotNull(IN VOID * Pointer,IN CONST CHAR8 * FunctionName,IN UINTN LineNumber,IN CONST CHAR8 * FileName,IN CONST CHAR8 * PointerName)469 UnitTestAssertNotNull (
470 IN VOID *Pointer,
471 IN CONST CHAR8 *FunctionName,
472 IN UINTN LineNumber,
473 IN CONST CHAR8 *FileName,
474 IN CONST CHAR8 *PointerName
475 )
476 {
477 if (Pointer == NULL) {
478 UT_LOG_ERROR (
479 "[ASSERT FAIL] %a:%d: Pointer (%a) is NULL!\n",
480 FileName,
481 LineNumber,
482 PointerName
483 );
484 UnitTestLogFailure (
485 FAILURETYPE_ASSERTNOTNULL,
486 "%a:%d: Pointer (%a) is NULL!\n",
487 FileName,
488 LineNumber,
489 PointerName
490 );
491 }
492 return (Pointer != NULL);
493 }
494
495 /**
496 If UnitTestStatus is UNIT_TEST_PASSED, then log an info message and return
497 TRUE because an ASSERT() was expected when FunctionCall was executed and an
498 ASSERT() was triggered. If UnitTestStatus is UNIT_TEST_SKIPPED, then log a
499 warning message and return TRUE because ASSERT() macros are disabled. If
500 UnitTestStatus is UNIT_TEST_ERROR_TEST_FAILED, then log an error message and
501 return FALSE because an ASSERT() was expected when FunctionCall was executed,
502 but no ASSERT() conditions were triggered. The log messages contain
503 FunctionName, LineNumber, and FileName strings to provide the location of the
504 UT_EXPECT_ASSERT_FAILURE() macro.
505
506 @param[in] UnitTestStatus The status from UT_EXPECT_ASSERT_FAILURE() that
507 is either pass, skipped, or failed.
508 @param[in] FunctionName Null-terminated ASCII string of the function
509 executing the UT_EXPECT_ASSERT_FAILURE() macro.
510 @param[in] LineNumber The source file line number of the the function
511 executing the UT_EXPECT_ASSERT_FAILURE() macro.
512 @param[in] FileName Null-terminated ASCII string of the filename
513 executing the UT_EXPECT_ASSERT_FAILURE() macro.
514 @param[in] FunctionCall Null-terminated ASCII string of the function call
515 executed by the UT_EXPECT_ASSERT_FAILURE() macro.
516 @param[out] ResultStatus Used to return the UnitTestStatus value to the
517 caller of UT_EXPECT_ASSERT_FAILURE(). This is
518 optional parameter that may be NULL.
519
520 @retval TRUE UnitTestStatus is UNIT_TEST_PASSED.
521 @retval TRUE UnitTestStatus is UNIT_TEST_SKIPPED.
522 @retval FALSE UnitTestStatus is UNIT_TEST_ERROR_TEST_FAILED.
523 **/
524 BOOLEAN
525 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)526 UnitTestExpectAssertFailure (
527 IN UNIT_TEST_STATUS UnitTestStatus,
528 IN CONST CHAR8 *FunctionName,
529 IN UINTN LineNumber,
530 IN CONST CHAR8 *FileName,
531 IN CONST CHAR8 *FunctionCall,
532 OUT UNIT_TEST_STATUS *ResultStatus OPTIONAL
533 )
534 {
535 if (ResultStatus != NULL) {
536 *ResultStatus = UnitTestStatus;
537 }
538 if (UnitTestStatus == UNIT_TEST_PASSED) {
539 UT_LOG_INFO (
540 "[ASSERT PASS] %a:%d: UT_EXPECT_ASSERT_FAILURE(%a) detected expected assert\n",
541 FileName,
542 LineNumber,
543 FunctionCall
544 );
545 }
546 if (UnitTestStatus == UNIT_TEST_SKIPPED) {
547 UT_LOG_WARNING (
548 "[ASSERT WARN] %a:%d: UT_EXPECT_ASSERT_FAILURE(%a) disabled\n",
549 FileName,
550 LineNumber,
551 FunctionCall
552 );
553 }
554 if (UnitTestStatus == UNIT_TEST_ERROR_TEST_FAILED) {
555 UT_LOG_ERROR (
556 "[ASSERT FAIL] %a:%d: Function call (%a) did not ASSERT()!\n",
557 FileName,
558 LineNumber,
559 FunctionCall
560 );
561 UnitTestLogFailure (
562 FAILURETYPE_EXPECTASSERT,
563 "%a:%d: Function call (%a) did not ASSERT()!\n",
564 FileName,
565 LineNumber,
566 FunctionCall
567 );
568 }
569 return (UnitTestStatus != UNIT_TEST_ERROR_TEST_FAILED);
570 }
571