1 | //===- llvm/unittest/Support/Base64Test.cpp - Base64 tests |
2 | //--------------------===// |
3 | // |
4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
5 | // See https://llvm.org/LICENSE.txt for license information. |
6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | // |
10 | // This file implements unit tests for the Base64 functions. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "llvm/Support/Base64.h" |
15 | #include "llvm/ADT/StringRef.h" |
16 | #include "llvm/Testing/Support/Error.h" |
17 | #include "gtest/gtest.h" |
18 | |
19 | using namespace llvm; |
20 | |
21 | namespace { |
22 | /// Tests an arbitrary set of bytes passed as \p Input. |
23 | void TestBase64(StringRef Input, StringRef Final) { |
24 | auto Res = encodeBase64(Bytes: Input); |
25 | EXPECT_EQ(Res, Final); |
26 | } |
27 | |
28 | void TestBase64Decode(StringRef Input, StringRef Expected, |
29 | StringRef ExpectedErrorMessage = {}) { |
30 | std::vector<char> DecodedBytes; |
31 | if (ExpectedErrorMessage.empty()) { |
32 | ASSERT_THAT_ERROR(decodeBase64(Input, DecodedBytes), Succeeded()); |
33 | EXPECT_EQ(llvm::ArrayRef<char>(DecodedBytes), |
34 | llvm::ArrayRef<char>(Expected.data(), Expected.size())); |
35 | } else { |
36 | ASSERT_THAT_ERROR(decodeBase64(Input, DecodedBytes), |
37 | FailedWithMessage(ExpectedErrorMessage)); |
38 | } |
39 | } |
40 | |
41 | char NonPrintableVector[] = {0x00, 0x00, 0x00, 0x46, |
42 | 0x00, 0x08, (char)0xff, (char)0xee}; |
43 | |
44 | char LargeVector[] = {0x54, 0x68, 0x65, 0x20, 0x71, 0x75, 0x69, 0x63, 0x6b, |
45 | 0x20, 0x62, 0x72, 0x6f, 0x77, 0x6e, 0x20, 0x66, 0x6f, |
46 | 0x78, 0x20, 0x6a, 0x75, 0x6d, 0x70, 0x73, 0x20, 0x6f, |
47 | 0x76, 0x65, 0x72, 0x20, 0x31, 0x33, 0x20, 0x6c, 0x61, |
48 | 0x7a, 0x79, 0x20, 0x64, 0x6f, 0x67, 0x73, 0x2e}; |
49 | |
50 | } // namespace |
51 | |
52 | TEST(Base64Test, Base64) { |
53 | // from: https://tools.ietf.org/html/rfc4648#section-10 |
54 | TestBase64(Input: "" , Final: "" ); |
55 | TestBase64(Input: "f" , Final: "Zg==" ); |
56 | TestBase64(Input: "fo" , Final: "Zm8=" ); |
57 | TestBase64(Input: "foo" , Final: "Zm9v" ); |
58 | TestBase64(Input: "foob" , Final: "Zm9vYg==" ); |
59 | TestBase64(Input: "fooba" , Final: "Zm9vYmE=" ); |
60 | TestBase64(Input: "foobar" , Final: "Zm9vYmFy" ); |
61 | |
62 | // With non-printable values. |
63 | TestBase64(Input: {NonPrintableVector, sizeof(NonPrintableVector)}, Final: "AAAARgAI/+4=" ); |
64 | |
65 | // Large test case |
66 | TestBase64(Input: {LargeVector, sizeof(LargeVector)}, |
67 | Final: "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIDEzIGxhenkgZG9ncy4=" ); |
68 | } |
69 | |
70 | TEST(Base64Test, DecodeBase64) { |
71 | std::vector<llvm::StringRef> Outputs = {"" , "f" , "fo" , "foo" , |
72 | "foob" , "fooba" , "foobar" }; |
73 | Outputs.push_back( |
74 | x: llvm::StringRef(NonPrintableVector, sizeof(NonPrintableVector))); |
75 | |
76 | Outputs.push_back(x: llvm::StringRef(LargeVector, sizeof(LargeVector))); |
77 | // Make sure we can encode and decode any byte. |
78 | std::vector<char> AllChars; |
79 | for (int Ch = INT8_MIN; Ch <= INT8_MAX; ++Ch) |
80 | AllChars.push_back(x: Ch); |
81 | Outputs.push_back(x: llvm::StringRef(AllChars.data(), AllChars.size())); |
82 | |
83 | for (const auto &Output : Outputs) { |
84 | // We trust that encoding is working after running the Base64Test::Base64() |
85 | // test function above, so we can use it to encode the string and verify we |
86 | // can decode it correctly. |
87 | auto Input = encodeBase64(Bytes: Output); |
88 | TestBase64Decode(Input, Expected: Output); |
89 | } |
90 | struct ErrorInfo { |
91 | llvm::StringRef Input; |
92 | llvm::StringRef ErrorMessage; |
93 | }; |
94 | std::vector<ErrorInfo> ErrorInfos = { |
95 | {.Input: "f" , .ErrorMessage: "Base64 encoded strings must be a multiple of 4 bytes in length" }, |
96 | {.Input: "=abc" , .ErrorMessage: "Invalid Base64 character 0x3d at index 0" }, |
97 | {.Input: "a=bc" , .ErrorMessage: "Invalid Base64 character 0x3d at index 1" }, |
98 | {.Input: "ab=c" , .ErrorMessage: "Invalid Base64 character 0x3d at index 2" }, |
99 | {.Input: "fun!" , .ErrorMessage: "Invalid Base64 character 0x21 at index 3" }, |
100 | }; |
101 | |
102 | for (const auto &EI : ErrorInfos) |
103 | TestBase64Decode(Input: EI.Input, Expected: "" , ExpectedErrorMessage: EI.ErrorMessage); |
104 | } |
105 | |