2 Unit tests of Base64 conversion APIs in BaseLib.
4 Copyright (C) Microsoft Corporation.
5 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include <Library/BaseLib.h>
11 #include <Library/BaseMemoryLib.h>
12 #include <Library/DebugLib.h>
13 #include <Library/MemoryAllocationLib.h>
14 #include <Library/UnitTestLib.h>
16 #define UNIT_TEST_APP_NAME "BaseLib Unit Test Application"
17 #define UNIT_TEST_APP_VERSION "1.0"
20 RFC 4648 https://tools.ietf.org/html/rfc4648 test vectors
25 BASE64("foo") = "Zm9v"
26 BASE64("foob") = "Zm9vYg=="
27 BASE64("fooba") = "Zm9vYmE="
28 BASE64("foobar") = "Zm9vYmFy"
30 The test vectors are using ascii strings for the binary data
36 EFI_STATUS ExpectedStatus
;
44 #define B64_TEST_2 "Zg=="
45 #define BIN_TEST_2 "f"
47 #define B64_TEST_3 "Zm8="
48 #define BIN_TEST_3 "fo"
50 #define B64_TEST_4 "Zm9v"
51 #define BIN_TEST_4 "foo"
53 #define B64_TEST_5 "Zm9vYg=="
54 #define BIN_TEST_5 "foob"
56 #define B64_TEST_6 "Zm9vYmE="
57 #define BIN_TEST_6 "fooba"
59 #define B64_TEST_7 "Zm9vYmFy"
60 #define BIN_TEST_7 "foobar"
62 // Adds all white space - also ends the last quantum with only spaces afterwards
63 #define B64_TEST_8_IN " \t\v Zm9\r\nvYmFy \f "
64 #define BIN_TEST_8 "foobar"
66 // Not a quantum multiple of 4
67 #define B64_ERROR_1 "Zm9vymFy="
69 // Invalid characters in the string
70 #define B64_ERROR_2 "Zm$vymFy"
72 // Too many '=' characters
73 #define B64_ERROR_3 "Z==="
76 #define B64_ERROR_4 "Zm=vYmFy"
78 #define MAX_TEST_STRING_SIZE (200)
80 // ------------------------------------------------ Input----------Output-----------Result-------Free--Expected Output Size
81 static BASIC_TEST_CONTEXT mBasicEncodeTest1
= {BIN_TEST_1
, B64_TEST_1
, EFI_SUCCESS
, NULL
, sizeof(B64_TEST_1
)};
82 static BASIC_TEST_CONTEXT mBasicEncodeTest2
= {BIN_TEST_2
, B64_TEST_2
, EFI_SUCCESS
, NULL
, sizeof(B64_TEST_2
)};
83 static BASIC_TEST_CONTEXT mBasicEncodeTest3
= {BIN_TEST_3
, B64_TEST_3
, EFI_SUCCESS
, NULL
, sizeof(B64_TEST_3
)};
84 static BASIC_TEST_CONTEXT mBasicEncodeTest4
= {BIN_TEST_4
, B64_TEST_4
, EFI_SUCCESS
, NULL
, sizeof(B64_TEST_4
)};
85 static BASIC_TEST_CONTEXT mBasicEncodeTest5
= {BIN_TEST_5
, B64_TEST_5
, EFI_SUCCESS
, NULL
, sizeof(B64_TEST_5
)};
86 static BASIC_TEST_CONTEXT mBasicEncodeTest6
= {BIN_TEST_6
, B64_TEST_6
, EFI_SUCCESS
, NULL
, sizeof(B64_TEST_6
)};
87 static BASIC_TEST_CONTEXT mBasicEncodeTest7
= {BIN_TEST_7
, B64_TEST_7
, EFI_SUCCESS
, NULL
, sizeof(B64_TEST_7
)};
88 static BASIC_TEST_CONTEXT mBasicEncodeError1
= {BIN_TEST_7
, B64_TEST_1
, EFI_BUFFER_TOO_SMALL
, NULL
, sizeof(B64_TEST_7
)};
90 static BASIC_TEST_CONTEXT mBasicDecodeTest1
= {B64_TEST_1
, BIN_TEST_1
, EFI_SUCCESS
, NULL
, sizeof(BIN_TEST_1
)-1};
91 static BASIC_TEST_CONTEXT mBasicDecodeTest2
= {B64_TEST_2
, BIN_TEST_2
, EFI_SUCCESS
, NULL
, sizeof(BIN_TEST_2
)-1};
92 static BASIC_TEST_CONTEXT mBasicDecodeTest3
= {B64_TEST_3
, BIN_TEST_3
, EFI_SUCCESS
, NULL
, sizeof(BIN_TEST_3
)-1};
93 static BASIC_TEST_CONTEXT mBasicDecodeTest4
= {B64_TEST_4
, BIN_TEST_4
, EFI_SUCCESS
, NULL
, sizeof(BIN_TEST_4
)-1};
94 static BASIC_TEST_CONTEXT mBasicDecodeTest5
= {B64_TEST_5
, BIN_TEST_5
, EFI_SUCCESS
, NULL
, sizeof(BIN_TEST_5
)-1};
95 static BASIC_TEST_CONTEXT mBasicDecodeTest6
= {B64_TEST_6
, BIN_TEST_6
, EFI_SUCCESS
, NULL
, sizeof(BIN_TEST_6
)-1};
96 static BASIC_TEST_CONTEXT mBasicDecodeTest7
= {B64_TEST_7
, BIN_TEST_7
, EFI_SUCCESS
, NULL
, sizeof(BIN_TEST_7
)-1};
97 static BASIC_TEST_CONTEXT mBasicDecodeTest8
= {B64_TEST_8_IN
, BIN_TEST_8
, EFI_SUCCESS
, NULL
, sizeof(BIN_TEST_8
)-1};
99 static BASIC_TEST_CONTEXT mBasicDecodeError1
= {B64_ERROR_1
, B64_ERROR_1
, EFI_INVALID_PARAMETER
, NULL
, 0};
100 static BASIC_TEST_CONTEXT mBasicDecodeError2
= {B64_ERROR_2
, B64_ERROR_2
, EFI_INVALID_PARAMETER
, NULL
, 0};
101 static BASIC_TEST_CONTEXT mBasicDecodeError3
= {B64_ERROR_3
, B64_ERROR_3
, EFI_INVALID_PARAMETER
, NULL
, 0};
102 static BASIC_TEST_CONTEXT mBasicDecodeError4
= {B64_ERROR_4
, B64_ERROR_4
, EFI_INVALID_PARAMETER
, NULL
, 0};
103 static BASIC_TEST_CONTEXT mBasicDecodeError5
= {B64_TEST_7
, BIN_TEST_1
, EFI_BUFFER_TOO_SMALL
, NULL
, sizeof(BIN_TEST_7
)-1};
106 Simple clean up method to make sure tests clean up even if interrupted and fail
112 CleanUpB64TestContext (
113 IN UNIT_TEST_CONTEXT Context
116 BASIC_TEST_CONTEXT
*Btc
;
118 Btc
= (BASIC_TEST_CONTEXT
*)Context
;
121 if (Btc
->BufferToFree
!= NULL
) {
122 FreePool (Btc
->BufferToFree
);
123 Btc
->BufferToFree
= NULL
;
129 Unit test for Base64 encode APIs of BaseLib.
131 @param[in] Context [Optional] An optional parameter that enables:
132 1) test-case reuse with varied parameters and
133 2) test-case re-entry for Target tests that need a
134 reboot. This parameter is a VOID* and it is the
135 responsibility of the test author to ensure that the
136 contents are well understood by all test cases that may
139 @retval UNIT_TEST_PASSED The Unit test has completed and the test
141 @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
147 IN UNIT_TEST_CONTEXT Context
150 BASIC_TEST_CONTEXT
*Btc
;
157 CHAR8
*b64WorkString
;
162 Btc
= (BASIC_TEST_CONTEXT
*) Context
;
163 binString
= Btc
->TestInput
;
164 b64String
= Btc
->TestOutput
;
167 // Only testing the the translate functionality, so preallocate the proper
171 b64StringSize
= AsciiStrnSizeS(b64String
, MAX_TEST_STRING_SIZE
);
172 BinSize
= AsciiStrnLenS(binString
, MAX_TEST_STRING_SIZE
);
173 BinData
= (UINT8
*) binString
;
175 b64WorkString
= (CHAR8
*) AllocatePool(b64StringSize
);
176 UT_ASSERT_NOT_NULL(b64WorkString
);
178 Btc
->BufferToFree
= b64WorkString
;
179 ReturnSize
= b64StringSize
;
181 Status
= Base64Encode(BinData
, BinSize
, b64WorkString
, &ReturnSize
);
183 UT_ASSERT_STATUS_EQUAL(Status
, Btc
->ExpectedStatus
);
185 UT_ASSERT_EQUAL(ReturnSize
, Btc
->ExpectedSize
);
187 if (!EFI_ERROR (Btc
->ExpectedStatus
)) {
188 if (ReturnSize
!= 0) {
189 CompareStatus
= AsciiStrnCmp (b64String
, b64WorkString
, ReturnSize
);
190 if (CompareStatus
!= 0) {
191 UT_LOG_ERROR ("b64 string compare error - size=%d\n", ReturnSize
);
192 for (indx
= 0; indx
< ReturnSize
; indx
++) {
193 UT_LOG_ERROR (" %2.2x", 0xff & b64String
[indx
]);
195 UT_LOG_ERROR ("\n b64 work string:\n");
196 for (indx
= 0; indx
< ReturnSize
; indx
++) {
197 UT_LOG_ERROR (" %2.2x", 0xff & b64WorkString
[indx
]);
201 UT_ASSERT_EQUAL (CompareStatus
, 0);
205 Btc
->BufferToFree
= NULL
;
206 FreePool (b64WorkString
);
207 return UNIT_TEST_PASSED
;
211 Unit test for Base64 decode APIs of BaseLib.
213 @param[in] Context [Optional] An optional parameter that enables:
214 1) test-case reuse with varied parameters and
215 2) test-case re-entry for Target tests that need a
216 reboot. This parameter is a VOID* and it is the
217 responsibility of the test author to ensure that the
218 contents are well understood by all test cases that may
221 @retval UNIT_TEST_PASSED The Unit test has completed and the test
223 @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
229 IN UNIT_TEST_CONTEXT Context
232 BASIC_TEST_CONTEXT
*Btc
;
243 Btc
= (BASIC_TEST_CONTEXT
*)Context
;
244 b64String
= Btc
->TestInput
;
245 binString
= Btc
->TestOutput
;
248 // Only testing the the translate functionality
251 b64StringLen
= AsciiStrnLenS (b64String
, MAX_TEST_STRING_SIZE
);
252 BinSize
= AsciiStrnLenS (binString
, MAX_TEST_STRING_SIZE
);
254 BinData
= AllocatePool (BinSize
);
255 UT_ASSERT_NOT_NULL(BinData
);
257 Btc
->BufferToFree
= BinData
;
258 ReturnSize
= BinSize
;
260 Status
= Base64Decode (b64String
, b64StringLen
, BinData
, &ReturnSize
);
262 UT_ASSERT_STATUS_EQUAL (Status
, Btc
->ExpectedStatus
);
264 // If an error is not expected, check the results
265 if (EFI_ERROR (Btc
->ExpectedStatus
)) {
266 if (Btc
->ExpectedStatus
== EFI_BUFFER_TOO_SMALL
) {
267 UT_ASSERT_EQUAL (ReturnSize
, Btc
->ExpectedSize
);
270 UT_ASSERT_EQUAL (ReturnSize
, Btc
->ExpectedSize
);
271 if (ReturnSize
!= 0) {
272 CompareStatus
= CompareMem (binString
, BinData
, ReturnSize
);
273 if (CompareStatus
!= 0) {
274 UT_LOG_ERROR ("bin string compare error - size=%d\n", ReturnSize
);
275 for (indx
= 0; indx
< ReturnSize
; indx
++) {
276 UT_LOG_ERROR (" %2.2x", 0xff & binString
[indx
]);
278 UT_LOG_ERROR ("\nBinData:\n");
279 for (indx
= 0; indx
< ReturnSize
; indx
++) {
280 UT_LOG_ERROR (" %2.2x", 0xff & BinData
[indx
]);
284 UT_ASSERT_EQUAL (CompareStatus
, 0);
288 Btc
->BufferToFree
= NULL
;
290 return UNIT_TEST_PASSED
;
293 #define SOURCE_STRING L"Hello"
298 SafeStringContraintCheckTest (
299 IN UNIT_TEST_CONTEXT Context
302 RETURN_STATUS Status
;
303 CHAR16 Destination
[20];
307 // Zero buffer used to verify Destination is not modified
309 ZeroMem (AllZero
, sizeof (AllZero
));
312 // Positive test case copy source unicode string to destination
314 ZeroMem (Destination
, sizeof (Destination
));
315 Status
= StrCpyS (Destination
, sizeof (Destination
) / sizeof (CHAR16
), SOURCE_STRING
);
316 UT_ASSERT_NOT_EFI_ERROR (Status
);
317 UT_ASSERT_MEM_EQUAL (Destination
, SOURCE_STRING
, sizeof (SOURCE_STRING
));
320 // Positive test case with DestMax the same as Source size
322 ZeroMem (Destination
, sizeof (Destination
));
323 Status
= StrCpyS (Destination
, sizeof (SOURCE_STRING
) / sizeof (CHAR16
), SOURCE_STRING
);
324 UT_ASSERT_NOT_EFI_ERROR (Status
);
325 UT_ASSERT_MEM_EQUAL (Destination
, SOURCE_STRING
, sizeof (SOURCE_STRING
));
328 // Negative test case with Destination NULL
330 ZeroMem (Destination
, sizeof (Destination
));
331 Status
= StrCpyS (NULL
, sizeof (Destination
) / sizeof (CHAR16
), SOURCE_STRING
);
332 UT_ASSERT_STATUS_EQUAL (Status
, RETURN_INVALID_PARAMETER
);
333 UT_ASSERT_MEM_EQUAL (Destination
, AllZero
, sizeof (AllZero
));
336 // Negative test case with Source NULL
338 ZeroMem (Destination
, sizeof (Destination
));
339 Status
= StrCpyS (Destination
, sizeof (Destination
) / sizeof (CHAR16
), NULL
);
340 UT_ASSERT_STATUS_EQUAL (Status
, RETURN_INVALID_PARAMETER
);
341 UT_ASSERT_MEM_EQUAL (Destination
, AllZero
, sizeof (AllZero
));
344 // Negative test case with DestMax too big
346 ZeroMem (Destination
, sizeof (Destination
));
347 Status
= StrCpyS (Destination
, MAX_UINTN
, SOURCE_STRING
);
348 UT_ASSERT_STATUS_EQUAL (Status
, RETURN_INVALID_PARAMETER
);
349 UT_ASSERT_MEM_EQUAL (Destination
, AllZero
, sizeof (AllZero
));
352 // Negative test case with DestMax 0
354 ZeroMem (Destination
, sizeof (Destination
));
355 Status
= StrCpyS (Destination
, 0, SOURCE_STRING
);
356 UT_ASSERT_STATUS_EQUAL (Status
, RETURN_INVALID_PARAMETER
);
357 UT_ASSERT_MEM_EQUAL (Destination
, AllZero
, sizeof (AllZero
));
360 // Negative test case with DestMax smaller than Source size
362 ZeroMem (Destination
, sizeof (Destination
));
363 Status
= StrCpyS (Destination
, 1, SOURCE_STRING
);
364 UT_ASSERT_STATUS_EQUAL (Status
, RETURN_BUFFER_TOO_SMALL
);
365 UT_ASSERT_MEM_EQUAL (Destination
, AllZero
, sizeof (AllZero
));
368 // Negative test case with DestMax smaller than Source size by one character
370 ZeroMem (Destination
, sizeof (Destination
));
371 Status
= StrCpyS (Destination
, sizeof (SOURCE_STRING
) / sizeof (CHAR16
) - 1, SOURCE_STRING
);
372 UT_ASSERT_STATUS_EQUAL (Status
, RETURN_BUFFER_TOO_SMALL
);
373 UT_ASSERT_MEM_EQUAL (Destination
, AllZero
, sizeof (AllZero
));
376 // Negative test case with overlapping Destination and Source
378 ZeroMem (Destination
, sizeof (Destination
));
379 Status
= StrCpyS (Destination
, sizeof (Destination
) / sizeof (CHAR16
), Destination
);
380 UT_ASSERT_STATUS_EQUAL (Status
, RETURN_ACCESS_DENIED
);
381 UT_ASSERT_MEM_EQUAL (Destination
, AllZero
, sizeof (AllZero
));
383 return UNIT_TEST_PASSED
;
387 Initialze the unit test framework, suite, and unit tests for the
388 Base64 conversion APIs of BaseLib and run the unit tests.
390 @retval EFI_SUCCESS All test cases were dispatched.
391 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to
392 initialize the unit tests.
402 UNIT_TEST_FRAMEWORK_HANDLE Fw
;
403 UNIT_TEST_SUITE_HANDLE b64EncodeTests
;
404 UNIT_TEST_SUITE_HANDLE b64DecodeTests
;
405 UNIT_TEST_SUITE_HANDLE SafeStringTests
;
409 DEBUG ((DEBUG_INFO
, "%a v%a\n", UNIT_TEST_APP_NAME
, UNIT_TEST_APP_VERSION
));
412 // Start setting up the test framework for running the tests.
414 Status
= InitUnitTestFramework (&Fw
, UNIT_TEST_APP_NAME
, gEfiCallerBaseName
, UNIT_TEST_APP_VERSION
);
415 if (EFI_ERROR (Status
)) {
416 DEBUG ((DEBUG_ERROR
, "Failed in InitUnitTestFramework. Status = %r\n", Status
));
421 // Populate the B64 Encode Unit Test Suite.
423 Status
= CreateUnitTestSuite (&b64EncodeTests
, Fw
, "b64 Encode binary to Ascii string", "BaseLib.b64Encode", NULL
, NULL
);
424 if (EFI_ERROR (Status
)) {
425 DEBUG ((DEBUG_ERROR
, "Failed in CreateUnitTestSuite for b64EncodeTests\n"));
426 Status
= EFI_OUT_OF_RESOURCES
;
430 // --------------Suite-----------Description--------------Class Name----------Function--------Pre---Post-------------------Context-----------
431 AddTestCase (b64EncodeTests
, "RFC 4686 Test Vector - Empty", "Test1", RfcEncodeTest
, NULL
, CleanUpB64TestContext
, &mBasicEncodeTest1
);
432 AddTestCase (b64EncodeTests
, "RFC 4686 Test Vector - f", "Test2", RfcEncodeTest
, NULL
, CleanUpB64TestContext
, &mBasicEncodeTest2
);
433 AddTestCase (b64EncodeTests
, "RFC 4686 Test Vector - fo", "Test3", RfcEncodeTest
, NULL
, CleanUpB64TestContext
, &mBasicEncodeTest3
);
434 AddTestCase (b64EncodeTests
, "RFC 4686 Test Vector - foo", "Test4", RfcEncodeTest
, NULL
, CleanUpB64TestContext
, &mBasicEncodeTest4
);
435 AddTestCase (b64EncodeTests
, "RFC 4686 Test Vector - foob", "Test5", RfcEncodeTest
, NULL
, CleanUpB64TestContext
, &mBasicEncodeTest5
);
436 AddTestCase (b64EncodeTests
, "RFC 4686 Test Vector - fooba", "Test6", RfcEncodeTest
, NULL
, CleanUpB64TestContext
, &mBasicEncodeTest6
);
437 AddTestCase (b64EncodeTests
, "RFC 4686 Test Vector - foobar", "Test7", RfcEncodeTest
, NULL
, CleanUpB64TestContext
, &mBasicEncodeTest7
);
438 AddTestCase (b64EncodeTests
, "Too small of output buffer", "Error1", RfcEncodeTest
, NULL
, CleanUpB64TestContext
, &mBasicEncodeError1
);
440 // Populate the B64 Decode Unit Test Suite.
442 Status
= CreateUnitTestSuite (&b64DecodeTests
, Fw
, "b64 Decode Ascii string to binary", "BaseLib.b64Decode", NULL
, NULL
);
443 if (EFI_ERROR (Status
)) {
444 DEBUG ((DEBUG_ERROR
, "Failed in CreateUnitTestSuite for b64Decode Tests\n"));
445 Status
= EFI_OUT_OF_RESOURCES
;
449 AddTestCase (b64DecodeTests
, "RFC 4686 Test Vector - Empty", "Test1", RfcDecodeTest
, NULL
, CleanUpB64TestContext
, &mBasicDecodeTest1
);
450 AddTestCase (b64DecodeTests
, "RFC 4686 Test Vector - f", "Test2", RfcDecodeTest
, NULL
, CleanUpB64TestContext
, &mBasicDecodeTest2
);
451 AddTestCase (b64DecodeTests
, "RFC 4686 Test Vector - fo", "Test3", RfcDecodeTest
, NULL
, CleanUpB64TestContext
, &mBasicDecodeTest3
);
452 AddTestCase (b64DecodeTests
, "RFC 4686 Test Vector - foo", "Test4", RfcDecodeTest
, NULL
, CleanUpB64TestContext
, &mBasicDecodeTest4
);
453 AddTestCase (b64DecodeTests
, "RFC 4686 Test Vector - foob", "Test5", RfcDecodeTest
, NULL
, CleanUpB64TestContext
, &mBasicDecodeTest5
);
454 AddTestCase (b64DecodeTests
, "RFC 4686 Test Vector - fooba", "Test6", RfcDecodeTest
, NULL
, CleanUpB64TestContext
, &mBasicDecodeTest6
);
455 AddTestCase (b64DecodeTests
, "RFC 4686 Test Vector - foobar", "Test7", RfcDecodeTest
, NULL
, CleanUpB64TestContext
, &mBasicDecodeTest7
);
456 AddTestCase (b64DecodeTests
, "Ignore Whitespace test", "Test8", RfcDecodeTest
, NULL
, CleanUpB64TestContext
, &mBasicDecodeTest8
);
458 AddTestCase (b64DecodeTests
, "Not a quantum multiple of 4", "Error1", RfcDecodeTest
, NULL
, CleanUpB64TestContext
, &mBasicDecodeError1
);
459 AddTestCase (b64DecodeTests
, "Invalid characters in the string", "Error2", RfcDecodeTest
, NULL
, CleanUpB64TestContext
, &mBasicDecodeError2
);
460 AddTestCase (b64DecodeTests
, "Too many padding characters", "Error3", RfcDecodeTest
, NULL
, CleanUpB64TestContext
, &mBasicDecodeError3
);
461 AddTestCase (b64DecodeTests
, "Incorrectly placed padding character", "Error4", RfcDecodeTest
, NULL
, CleanUpB64TestContext
, &mBasicDecodeError4
);
462 AddTestCase (b64DecodeTests
, "Too small of output buffer", "Error5", RfcDecodeTest
, NULL
, CleanUpB64TestContext
, &mBasicDecodeError5
);
465 // Populate the safe string Unit Test Suite.
467 Status
= CreateUnitTestSuite (&SafeStringTests
, Fw
, "Safe String", "BaseLib.SafeString", NULL
, NULL
);
468 if (EFI_ERROR (Status
)) {
469 DEBUG ((DEBUG_ERROR
, "Failed in CreateUnitTestSuite for SafeStringTests\n"));
470 Status
= EFI_OUT_OF_RESOURCES
;
474 // --------------Suite-----------Description--------------Class Name----------Function--------Pre---Post-------------------Context-----------
475 AddTestCase (SafeStringTests
, "SAFE_STRING_CONSTRAINT_CHECK", "SafeStringContraintCheckTest", SafeStringContraintCheckTest
, NULL
, NULL
, NULL
);
478 // Execute the tests.
480 Status
= RunAllTestSuites (Fw
);
484 FreeUnitTestFramework (Fw
);
491 Standard UEFI entry point for target based unit test execution from UEFI Shell.
495 BaseLibUnitTestAppEntry (
496 IN EFI_HANDLE ImageHandle
,
497 IN EFI_SYSTEM_TABLE
*SystemTable
500 return UnitTestingEntry ();
504 Standard POSIX C entry point for host based unit test execution.
512 return UnitTestingEntry ();