]> git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Test/UnitTest/Library/BaseLib/Base64UnitTest.c
8952f9da6c3a0894c75ff21e541def1872e7afe4
[mirror_edk2.git] / MdePkg / Test / UnitTest / Library / BaseLib / Base64UnitTest.c
1 /** @file
2 Unit tests of Base64 conversion APIs in BaseLib.
3
4 Copyright (C) Microsoft Corporation.
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include <Uefi.h>
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>
15
16 #define UNIT_TEST_APP_NAME "BaseLib Unit Test Application"
17 #define UNIT_TEST_APP_VERSION "1.0"
18
19 /**
20 RFC 4648 https://tools.ietf.org/html/rfc4648 test vectors
21
22 BASE64("") = ""
23 BASE64("f") = "Zg=="
24 BASE64("fo") = "Zm8="
25 BASE64("foo") = "Zm9v"
26 BASE64("foob") = "Zm9vYg=="
27 BASE64("fooba") = "Zm9vYmE="
28 BASE64("foobar") = "Zm9vYmFy"
29
30 The test vectors are using ascii strings for the binary data
31 */
32
33 typedef struct {
34 CHAR8 *TestInput;
35 CHAR8 *TestOutput;
36 EFI_STATUS ExpectedStatus;
37 VOID *BufferToFree;
38 UINTN ExpectedSize;
39 } BASIC_TEST_CONTEXT;
40
41 #define B64_TEST_1 ""
42 #define BIN_TEST_1 ""
43
44 #define B64_TEST_2 "Zg=="
45 #define BIN_TEST_2 "f"
46
47 #define B64_TEST_3 "Zm8="
48 #define BIN_TEST_3 "fo"
49
50 #define B64_TEST_4 "Zm9v"
51 #define BIN_TEST_4 "foo"
52
53 #define B64_TEST_5 "Zm9vYg=="
54 #define BIN_TEST_5 "foob"
55
56 #define B64_TEST_6 "Zm9vYmE="
57 #define BIN_TEST_6 "fooba"
58
59 #define B64_TEST_7 "Zm9vYmFy"
60 #define BIN_TEST_7 "foobar"
61
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"
65
66 // Not a quantum multiple of 4
67 #define B64_ERROR_1 "Zm9vymFy="
68
69 // Invalid characters in the string
70 #define B64_ERROR_2 "Zm$vymFy"
71
72 // Too many '=' characters
73 #define B64_ERROR_3 "Z==="
74
75 // Poorly placed '='
76 #define B64_ERROR_4 "Zm=vYmFy"
77
78 #define MAX_TEST_STRING_SIZE (200)
79
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)};
89
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};
98
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};
104
105 /**
106 Simple clean up method to make sure tests clean up even if interrupted and fail
107 in the middle.
108 **/
109 STATIC
110 VOID
111 EFIAPI
112 CleanUpB64TestContext (
113 IN UNIT_TEST_CONTEXT Context
114 )
115 {
116 BASIC_TEST_CONTEXT *Btc;
117
118 Btc = (BASIC_TEST_CONTEXT *)Context;
119 if (Btc != NULL) {
120 //free string if set
121 if (Btc->BufferToFree != NULL) {
122 FreePool (Btc->BufferToFree);
123 Btc->BufferToFree = NULL;
124 }
125 }
126 }
127
128 /**
129 Unit test for Base64 encode APIs of BaseLib.
130
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
137 consume it.
138
139 @retval UNIT_TEST_PASSED The Unit test has completed and the test
140 case was successful.
141 @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
142 **/
143 STATIC
144 UNIT_TEST_STATUS
145 EFIAPI
146 RfcEncodeTest (
147 IN UNIT_TEST_CONTEXT Context
148 )
149 {
150 BASIC_TEST_CONTEXT *Btc;
151 CHAR8 *b64String;
152 CHAR8 *binString;
153 UINTN b64StringSize;
154 EFI_STATUS Status;
155 UINT8 *BinData;
156 UINTN BinSize;
157 CHAR8 *b64WorkString;
158 UINTN ReturnSize;
159 INTN CompareStatus;
160 UINTN indx;
161
162 Btc = (BASIC_TEST_CONTEXT *) Context;
163 binString = Btc->TestInput;
164 b64String = Btc->TestOutput;
165
166 //
167 // Only testing the the translate functionality, so preallocate the proper
168 // string buffer.
169 //
170
171 b64StringSize = AsciiStrnSizeS(b64String, MAX_TEST_STRING_SIZE);
172 BinSize = AsciiStrnLenS(binString, MAX_TEST_STRING_SIZE);
173 BinData = (UINT8 *) binString;
174
175 b64WorkString = (CHAR8 *) AllocatePool(b64StringSize);
176 UT_ASSERT_NOT_NULL(b64WorkString);
177
178 Btc->BufferToFree = b64WorkString;
179 ReturnSize = b64StringSize;
180
181 Status = Base64Encode(BinData, BinSize, b64WorkString, &ReturnSize);
182
183 UT_ASSERT_STATUS_EQUAL(Status, Btc->ExpectedStatus);
184
185 UT_ASSERT_EQUAL(ReturnSize, Btc->ExpectedSize);
186
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]);
194 }
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]);
198 }
199 UT_LOG_ERROR ("\n");
200 }
201 UT_ASSERT_EQUAL (CompareStatus, 0);
202 }
203 }
204
205 Btc->BufferToFree = NULL;
206 FreePool (b64WorkString);
207 return UNIT_TEST_PASSED;
208 }
209
210 /**
211 Unit test for Base64 decode APIs of BaseLib.
212
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
219 consume it.
220
221 @retval UNIT_TEST_PASSED The Unit test has completed and the test
222 case was successful.
223 @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
224 **/
225 STATIC
226 UNIT_TEST_STATUS
227 EFIAPI
228 RfcDecodeTest(
229 IN UNIT_TEST_CONTEXT Context
230 )
231 {
232 BASIC_TEST_CONTEXT *Btc;
233 CHAR8 *b64String;
234 CHAR8 *binString;
235 EFI_STATUS Status;
236 UINTN b64StringLen;
237 UINTN ReturnSize;
238 UINT8 *BinData;
239 UINTN BinSize;
240 INTN CompareStatus;
241 UINTN indx;
242
243 Btc = (BASIC_TEST_CONTEXT *)Context;
244 b64String = Btc->TestInput;
245 binString = Btc->TestOutput;
246
247 //
248 // Only testing the the translate functionality
249 //
250
251 b64StringLen = AsciiStrnLenS (b64String, MAX_TEST_STRING_SIZE);
252 BinSize = AsciiStrnLenS (binString, MAX_TEST_STRING_SIZE);
253
254 BinData = AllocatePool (BinSize);
255 UT_ASSERT_NOT_NULL(BinData);
256
257 Btc->BufferToFree = BinData;
258 ReturnSize = BinSize;
259
260 Status = Base64Decode (b64String, b64StringLen, BinData, &ReturnSize);
261
262 UT_ASSERT_STATUS_EQUAL (Status, Btc->ExpectedStatus);
263
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);
268 }
269 } else {
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]);
277 }
278 UT_LOG_ERROR ("\nBinData:\n");
279 for (indx = 0; indx < ReturnSize; indx++) {
280 UT_LOG_ERROR (" %2.2x", 0xff & BinData[indx]);
281 }
282 UT_LOG_ERROR ("\n");
283 }
284 UT_ASSERT_EQUAL (CompareStatus, 0);
285 }
286 }
287
288 Btc->BufferToFree = NULL;
289 FreePool (BinData);
290 return UNIT_TEST_PASSED;
291 }
292
293 /**
294 Initialze the unit test framework, suite, and unit tests for the
295 Base64 conversion APIs of BaseLib and run the unit tests.
296
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.
300 **/
301 STATIC
302 EFI_STATUS
303 EFIAPI
304 UnitTestingEntry (
305 VOID
306 )
307 {
308 EFI_STATUS Status;
309 UNIT_TEST_FRAMEWORK_HANDLE Fw;
310 UNIT_TEST_SUITE_HANDLE b64EncodeTests;
311 UNIT_TEST_SUITE_HANDLE b64DecodeTests;
312
313 Fw = NULL;
314
315 DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_APP_NAME, UNIT_TEST_APP_VERSION));
316
317 //
318 // Start setting up the test framework for running the tests.
319 //
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));
323 goto EXIT;
324 }
325
326 //
327 // Populate the B64 Encode Unit Test Suite.
328 //
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;
333 goto EXIT;
334 }
335
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);
345 //
346 // Populate the B64 Decode Unit Test Suite.
347 //
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;
352 goto EXIT;
353 }
354
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);
363
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);
369
370 //
371 // Execute the tests.
372 //
373 Status = RunAllTestSuites (Fw);
374
375 EXIT:
376 if (Fw) {
377 FreeUnitTestFramework (Fw);
378 }
379
380 return Status;
381 }
382
383 /**
384 Standard UEFI entry point for target based unit test execution from UEFI Shell.
385 **/
386 EFI_STATUS
387 EFIAPI
388 BaseLibUnitTestAppEntry (
389 IN EFI_HANDLE ImageHandle,
390 IN EFI_SYSTEM_TABLE *SystemTable
391 )
392 {
393 return UnitTestingEntry ();
394 }
395
396 /**
397 Standard POSIX C entry point for host based unit test execution.
398 **/
399 int
400 main (
401 int argc,
402 char *argv[]
403 )
404 {
405 return UnitTestingEntry ();
406 }