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
;
294 Initialze the unit test framework, suite, and unit tests for the
295 Base64 conversion APIs of BaseLib and run the unit tests.
297 @retval EFI_SUCCESS All test cases were dispatched.
298 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to
299 initialize the unit tests.
309 UNIT_TEST_FRAMEWORK_HANDLE Fw
;
310 UNIT_TEST_SUITE_HANDLE b64EncodeTests
;
311 UNIT_TEST_SUITE_HANDLE b64DecodeTests
;
315 DEBUG ((DEBUG_INFO
, "%a v%a\n", UNIT_TEST_APP_NAME
, UNIT_TEST_APP_VERSION
));
318 // Start setting up the test framework for running the tests.
320 Status
= InitUnitTestFramework (&Fw
, UNIT_TEST_APP_NAME
, gEfiCallerBaseName
, UNIT_TEST_APP_VERSION
);
321 if (EFI_ERROR (Status
)) {
322 DEBUG ((DEBUG_ERROR
, "Failed in InitUnitTestFramework. Status = %r\n", Status
));
327 // Populate the B64 Encode Unit Test Suite.
329 Status
= CreateUnitTestSuite (&b64EncodeTests
, Fw
, "b64 Encode binary to Ascii string", "BaseLib.b64Encode", NULL
, NULL
);
330 if (EFI_ERROR (Status
)) {
331 DEBUG ((DEBUG_ERROR
, "Failed in CreateUnitTestSuite for b64EncodeTests\n"));
332 Status
= EFI_OUT_OF_RESOURCES
;
336 // --------------Suite-----------Description--------------Class Name----------Function--------Pre---Post-------------------Context-----------
337 AddTestCase (b64EncodeTests
, "RFC 4686 Test Vector - Empty", "Test1", RfcEncodeTest
, NULL
, CleanUpB64TestContext
, &mBasicEncodeTest1
);
338 AddTestCase (b64EncodeTests
, "RFC 4686 Test Vector - f", "Test2", RfcEncodeTest
, NULL
, CleanUpB64TestContext
, &mBasicEncodeTest2
);
339 AddTestCase (b64EncodeTests
, "RFC 4686 Test Vector - fo", "Test3", RfcEncodeTest
, NULL
, CleanUpB64TestContext
, &mBasicEncodeTest3
);
340 AddTestCase (b64EncodeTests
, "RFC 4686 Test Vector - foo", "Test4", RfcEncodeTest
, NULL
, CleanUpB64TestContext
, &mBasicEncodeTest4
);
341 AddTestCase (b64EncodeTests
, "RFC 4686 Test Vector - foob", "Test5", RfcEncodeTest
, NULL
, CleanUpB64TestContext
, &mBasicEncodeTest5
);
342 AddTestCase (b64EncodeTests
, "RFC 4686 Test Vector - fooba", "Test6", RfcEncodeTest
, NULL
, CleanUpB64TestContext
, &mBasicEncodeTest6
);
343 AddTestCase (b64EncodeTests
, "RFC 4686 Test Vector - foobar", "Test7", RfcEncodeTest
, NULL
, CleanUpB64TestContext
, &mBasicEncodeTest7
);
344 AddTestCase (b64EncodeTests
, "Too small of output buffer", "Error1", RfcEncodeTest
, NULL
, CleanUpB64TestContext
, &mBasicEncodeError1
);
346 // Populate the B64 Decode Unit Test Suite.
348 Status
= CreateUnitTestSuite (&b64DecodeTests
, Fw
, "b64 Decode Ascii string to binary", "BaseLib.b64Decode", NULL
, NULL
);
349 if (EFI_ERROR (Status
)) {
350 DEBUG ((DEBUG_ERROR
, "Failed in CreateUnitTestSuite for b64Decode Tests\n"));
351 Status
= EFI_OUT_OF_RESOURCES
;
355 AddTestCase (b64DecodeTests
, "RFC 4686 Test Vector - Empty", "Test1", RfcDecodeTest
, NULL
, CleanUpB64TestContext
, &mBasicDecodeTest1
);
356 AddTestCase (b64DecodeTests
, "RFC 4686 Test Vector - f", "Test2", RfcDecodeTest
, NULL
, CleanUpB64TestContext
, &mBasicDecodeTest2
);
357 AddTestCase (b64DecodeTests
, "RFC 4686 Test Vector - fo", "Test3", RfcDecodeTest
, NULL
, CleanUpB64TestContext
, &mBasicDecodeTest3
);
358 AddTestCase (b64DecodeTests
, "RFC 4686 Test Vector - foo", "Test4", RfcDecodeTest
, NULL
, CleanUpB64TestContext
, &mBasicDecodeTest4
);
359 AddTestCase (b64DecodeTests
, "RFC 4686 Test Vector - foob", "Test5", RfcDecodeTest
, NULL
, CleanUpB64TestContext
, &mBasicDecodeTest5
);
360 AddTestCase (b64DecodeTests
, "RFC 4686 Test Vector - fooba", "Test6", RfcDecodeTest
, NULL
, CleanUpB64TestContext
, &mBasicDecodeTest6
);
361 AddTestCase (b64DecodeTests
, "RFC 4686 Test Vector - foobar", "Test7", RfcDecodeTest
, NULL
, CleanUpB64TestContext
, &mBasicDecodeTest7
);
362 AddTestCase (b64DecodeTests
, "Ignore Whitespace test", "Test8", RfcDecodeTest
, NULL
, CleanUpB64TestContext
, &mBasicDecodeTest8
);
364 AddTestCase (b64DecodeTests
, "Not a quantum multiple of 4", "Error1", RfcDecodeTest
, NULL
, CleanUpB64TestContext
, &mBasicDecodeError1
);
365 AddTestCase (b64DecodeTests
, "Invalid characters in the string", "Error2", RfcDecodeTest
, NULL
, CleanUpB64TestContext
, &mBasicDecodeError2
);
366 AddTestCase (b64DecodeTests
, "Too many padding characters", "Error3", RfcDecodeTest
, NULL
, CleanUpB64TestContext
, &mBasicDecodeError3
);
367 AddTestCase (b64DecodeTests
, "Incorrectly placed padding character", "Error4", RfcDecodeTest
, NULL
, CleanUpB64TestContext
, &mBasicDecodeError4
);
368 AddTestCase (b64DecodeTests
, "Too small of output buffer", "Error5", RfcDecodeTest
, NULL
, CleanUpB64TestContext
, &mBasicDecodeError5
);
371 // Execute the tests.
373 Status
= RunAllTestSuites (Fw
);
377 FreeUnitTestFramework (Fw
);
384 Standard UEFI entry point for target based unit test execution from UEFI Shell.
388 BaseLibUnitTestAppEntry (
389 IN EFI_HANDLE ImageHandle
,
390 IN EFI_SYSTEM_TABLE
*SystemTable
393 return UnitTestingEntry ();
397 Standard POSIX C entry point for host based unit test execution.
405 return UnitTestingEntry ();