xref: /aosp_15_r20/external/perfetto/src/base/base64_unittest.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "perfetto/ext/base/base64.h"
18 
19 #include "perfetto/ext/base/string_view.h"
20 #include "perfetto/ext/base/utils.h"
21 #include "test/gtest_and_gmock.h"
22 
23 namespace perfetto {
24 namespace base {
25 namespace {
26 
27 struct TestPattern {
28   size_t decoded_len;
29   const char* decoded;
30   const char* encoded;
31 };
32 
33 TestPattern kPatterns[] = {
34 
35     // Basic bit patterns;
36     // values obtained with "echo -n '...' | uuencode -m test"
37 
38     {1, "\000", "AA=="},
39     {1, "\001", "AQ=="},
40     {1, "\002", "Ag=="},
41     {1, "\004", "BA=="},
42     {1, "\010", "CA=="},
43     {1, "\020", "EA=="},
44     {1, "\040", "IA=="},
45     {1, "\100", "QA=="},
46     {1, "\200", "gA=="},
47 
48     {1, "\377", "/w=="},
49     {1, "\376", "/g=="},
50     {1, "\375", "/Q=="},
51     {1, "\373", "+w=="},
52     {1, "\367", "9w=="},
53     {1, "\357", "7w=="},
54     {1, "\337", "3w=="},
55     {1, "\277", "vw=="},
56     {1, "\177", "fw=="},
57     {2, "\000\000", "AAA="},
58     {2, "\000\001", "AAE="},
59     {2, "\000\002", "AAI="},
60     {2, "\000\004", "AAQ="},
61     {2, "\000\010", "AAg="},
62     {2, "\000\020", "ABA="},
63     {2, "\000\040", "ACA="},
64     {2, "\000\100", "AEA="},
65     {2, "\000\200", "AIA="},
66     {2, "\001\000", "AQA="},
67     {2, "\002\000", "AgA="},
68     {2, "\004\000", "BAA="},
69     {2, "\010\000", "CAA="},
70     {2, "\020\000", "EAA="},
71     {2, "\040\000", "IAA="},
72     {2, "\100\000", "QAA="},
73     {2, "\200\000", "gAA="},
74 
75     {2, "\377\377", "//8="},
76     {2, "\377\376", "//4="},
77     {2, "\377\375", "//0="},
78     {2, "\377\373", "//s="},
79     {2, "\377\367", "//c="},
80     {2, "\377\357", "/+8="},
81     {2, "\377\337", "/98="},
82     {2, "\377\277", "/78="},
83     {2, "\377\177", "/38="},
84     {2, "\376\377", "/v8="},
85     {2, "\375\377", "/f8="},
86     {2, "\373\377", "+/8="},
87     {2, "\367\377", "9/8="},
88     {2, "\357\377", "7/8="},
89     {2, "\337\377", "3/8="},
90     {2, "\277\377", "v/8="},
91     {2, "\177\377", "f/8="},
92 
93     {3, "\000\000\000", "AAAA"},
94     {3, "\000\000\001", "AAAB"},
95     {3, "\000\000\002", "AAAC"},
96     {3, "\000\000\004", "AAAE"},
97     {3, "\000\000\010", "AAAI"},
98     {3, "\000\000\020", "AAAQ"},
99     {3, "\000\000\040", "AAAg"},
100     {3, "\000\000\100", "AABA"},
101     {3, "\000\000\200", "AACA"},
102     {3, "\000\001\000", "AAEA"},
103     {3, "\000\002\000", "AAIA"},
104     {3, "\000\004\000", "AAQA"},
105     {3, "\000\010\000", "AAgA"},
106     {3, "\000\020\000", "ABAA"},
107     {3, "\000\040\000", "ACAA"},
108     {3, "\000\100\000", "AEAA"},
109     {3, "\000\200\000", "AIAA"},
110     {3, "\001\000\000", "AQAA"},
111     {3, "\002\000\000", "AgAA"},
112     {3, "\004\000\000", "BAAA"},
113     {3, "\010\000\000", "CAAA"},
114     {3, "\020\000\000", "EAAA"},
115     {3, "\040\000\000", "IAAA"},
116     {3, "\100\000\000", "QAAA"},
117     {3, "\200\000\000", "gAAA"},
118 
119     {3, "\377\377\377", "////"},
120     {3, "\377\377\376", "///+"},
121     {3, "\377\377\375", "///9"},
122     {3, "\377\377\373", "///7"},
123     {3, "\377\377\367", "///3"},
124     {3, "\377\377\357", "///v"},
125     {3, "\377\377\337", "///f"},
126     {3, "\377\377\277", "//+/"},
127     {3, "\377\377\177", "//9/"},
128     {3, "\377\376\377", "//7/"},
129     {3, "\377\375\377", "//3/"},
130     {3, "\377\373\377", "//v/"},
131     {3, "\377\367\377", "//f/"},
132     {3, "\377\357\377", "/+//"},
133     {3, "\377\337\377", "/9//"},
134     {3, "\377\277\377", "/7//"},
135     {3, "\377\177\377", "/3//"},
136     {3, "\376\377\377", "/v//"},
137     {3, "\375\377\377", "/f//"},
138     {3, "\373\377\377", "+///"},
139     {3, "\367\377\377", "9///"},
140     {3, "\357\377\377", "7///"},
141     {3, "\337\377\377", "3///"},
142     {3, "\277\377\377", "v///"},
143     {3, "\177\377\377", "f///"},
144 
145     // Random numbers: values obtained with
146     //
147     //  #! /bin/bash
148     //  dd bs=$1 count=1 if=/dev/random of=/tmp/bar.random
149     //  od -N $1 -t o1 /tmp/bar.random
150     //  uuencode -m test < /tmp/bar.random
151     //
152     // where $1 is the number of bytes (2, 3)
153 
154     {2, "\243\361", "o/E="},
155     {2, "\024\167", "FHc="},
156     {2, "\313\252", "y6o="},
157     {2, "\046\041", "JiE="},
158     {2, "\145\236", "ZZ4="},
159     {2, "\254\325", "rNU="},
160     {2, "\061\330", "Mdg="},
161     {2, "\245\032", "pRo="},
162     {2, "\006\000", "BgA="},
163     {2, "\375\131", "/Vk="},
164     {2, "\303\210", "w4g="},
165     {2, "\040\037", "IB8="},
166     {2, "\261\372", "sfo="},
167     {2, "\335\014", "3Qw="},
168     {2, "\233\217", "m48="},
169     {2, "\373\056", "+y4="},
170     {2, "\247\232", "p5o="},
171     {2, "\107\053", "Rys="},
172     {2, "\204\077", "hD8="},
173     {2, "\276\211", "vok="},
174     {2, "\313\110", "y0g="},
175     {2, "\363\376", "8/4="},
176     {2, "\251\234", "qZw="},
177     {2, "\103\262", "Q7I="},
178     {2, "\142\312", "Yso="},
179     {2, "\067\211", "N4k="},
180     {2, "\220\001", "kAE="},
181     {2, "\152\240", "aqA="},
182     {2, "\367\061", "9zE="},
183     {2, "\133\255", "W60="},
184     {2, "\176\035", "fh0="},
185     {2, "\032\231", "Gpk="},
186 
187     {3, "\013\007\144", "Cwdk"},
188     {3, "\030\112\106", "GEpG"},
189     {3, "\047\325\046", "J9Um"},
190     {3, "\310\160\022", "yHAS"},
191     {3, "\131\100\237", "WUCf"},
192     {3, "\064\342\134", "NOJc"},
193     {3, "\010\177\004", "CH8E"},
194     {3, "\345\147\205", "5WeF"},
195     {3, "\300\343\360", "wOPw"},
196     {3, "\061\240\201", "MaCB"},
197     {3, "\225\333\044", "ldsk"},
198     {3, "\215\137\352", "jV/q"},
199     {3, "\371\147\160", "+Wdw"},
200     {3, "\030\320\051", "GNAp"},
201     {3, "\044\174\241", "JHyh"},
202     {3, "\260\127\037", "sFcf"},
203     {3, "\111\045\033", "SSUb"},
204     {3, "\202\114\107", "gkxH"},
205     {3, "\057\371\042", "L/ki"},
206     {3, "\223\247\244", "k6ek"},
207     {3, "\047\216\144", "J45k"},
208     {3, "\203\070\327", "gzjX"},
209     {3, "\247\140\072", "p2A6"},
210     {3, "\124\115\116", "VE1O"},
211     {3, "\157\162\050", "b3Io"},
212     {3, "\357\223\004", "75ME"},
213     {3, "\052\117\156", "Kk9u"},
214     {3, "\347\154\000", "52wA"},
215     {3, "\303\012\142", "wwpi"},
216     {3, "\060\035\362", "MB3y"},
217     {3, "\130\226\361", "WJbx"},
218     {3, "\173\013\071", "ews5"},
219     {3, "\336\004\027", "3gQX"},
220     {3, "\357\366\234", "7/ac"},
221     {3, "\353\304\111", "68RJ"},
222     {3, "\024\264\131", "FLRZ"},
223     {3, "\075\114\251", "PUyp"},
224     {3, "\315\031\225", "zRmV"},
225     {3, "\154\201\276", "bIG+"},
226     {3, "\200\066\072", "gDY6"},
227     {3, "\142\350\267", "Yui3"},
228     {3, "\033\000\166", "GwB2"},
229     {3, "\210\055\077", "iC0/"},
230     {3, "\341\037\124", "4R9U"},
231     {3, "\161\103\152", "cUNq"},
232     {3, "\270\142\131", "uGJZ"},
233     {3, "\337\076\074", "3z48"},
234     {3, "\375\106\362", "/Uby"},
235     {3, "\227\301\127", "l8FX"},
236     {3, "\340\002\234", "4AKc"},
237     {3, "\121\064\033", "UTQb"},
238     {3, "\157\134\143", "b1xj"},
239     {3, "\247\055\327", "py3X"},
240     {3, "\340\142\005", "4GIF"},
241     {3, "\060\260\143", "MLBj"},
242     {3, "\075\203\170", "PYN4"},
243     {3, "\143\160\016", "Y3AO"},
244     {3, "\313\013\063", "ywsz"},
245     {3, "\174\236\135", "fJ5d"},
246     {3, "\103\047\026", "QycW"},
247     {3, "\365\005\343", "9QXj"},
248     {3, "\271\160\223", "uXCT"},
249     {3, "\362\255\172", "8q16"},
250     {3, "\113\012\015", "SwoN"},
251 
252     // various lengths, generated by this python script:
253     //
254     // from string import lowercase as lc
255     // for i in range(27):
256     //   print '{ %2d, "%s",%s "%s" },' % (i, lc[:i], ' ' * (26-i),
257     //                                     lc[:i].encode('base64').strip())
258 
259     {0, "abcdefghijklmnopqrstuvwxyz", ""},
260     {1, "abcdefghijklmnopqrstuvwxyz", "YQ=="},
261     {2, "abcdefghijklmnopqrstuvwxyz", "YWI="},
262     {3, "abcdefghijklmnopqrstuvwxyz", "YWJj"},
263     {4, "abcdefghijklmnopqrstuvwxyz", "YWJjZA=="},
264     {5, "abcdefghijklmnopqrstuvwxyz", "YWJjZGU="},
265     {6, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVm"},
266     {7, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZw=="},
267     {8, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2g="},
268     {9, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hp"},
269     {10, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpag=="},
270     {11, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpams="},
271     {12, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamts"},
272     {13, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbQ=="},
273     {14, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW4="},
274     {15, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW5v"},
275     {16, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW5vcA=="},
276     {17, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW5vcHE="},
277     {18, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW5vcHFy"},
278     {19, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW5vcHFycw=="},
279     {20, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW5vcHFyc3Q="},
280     {21, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1"},
281     {22, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dg=="},
282     {23, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnc="},
283     {24, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4"},
284     {25, "abcdefghijklmnopqrstuvwxy", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eQ=="},
285     {26, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo="},
286 };
287 
TEST(Base64Test,Encode)288 TEST(Base64Test, Encode) {
289   EXPECT_EQ(Base64Encode(""), "");
290   EXPECT_EQ(Base64Encode("f"), "Zg==");
291   EXPECT_EQ(Base64Encode("fo"), "Zm8=");
292   EXPECT_EQ(Base64Encode("foo"), "Zm9v");
293   EXPECT_EQ(Base64Encode("foob"), "Zm9vYg==");
294   EXPECT_EQ(Base64Encode("fooba"), "Zm9vYmE=");
295   EXPECT_EQ(Base64Encode("foobar"), "Zm9vYmFy");
296   EXPECT_EQ(Base64Encode("\xff"), "/w==");
297   EXPECT_EQ(Base64Encode("\xff\xfe"), "//4=");
298   EXPECT_EQ(Base64Encode("\xff\xfe\xfd"), "//79");
299   EXPECT_EQ(Base64Encode("\xff\xfe\xfd\xfc"), "//79/A==");
300 
301   for (size_t i = 0; i < ArraySize(kPatterns); ++i) {
302     const auto& p = kPatterns[i];
303     std::string res = Base64Encode(StringView(p.decoded, p.decoded_len));
304     EXPECT_EQ(p.encoded, res);
305   }
306 
307   // Error cases
308   char buf[4];
309   EXPECT_EQ(0, Base64Encode("", 0, buf, 0));
310   EXPECT_EQ(0, Base64Encode("", 0, buf, 1));
311   EXPECT_EQ(-1, Base64Encode("a", 1, buf, 0));
312   EXPECT_EQ(-1, Base64Encode("abc", 3, buf, 0));
313   EXPECT_EQ(-1, Base64Encode("abc", 3, buf, 1));
314   EXPECT_EQ(-1, Base64Encode("abc", 3, buf, 3));
315   EXPECT_EQ(4, Base64Encode("abc", 3, buf, 4));
316 }
317 
TEST(Base64Test,Decode)318 TEST(Base64Test, Decode) {
319   EXPECT_EQ(Base64Decode(""), "");
320   EXPECT_EQ(Base64Decode("Zg=="), "f");
321   EXPECT_EQ(Base64Decode("Zg="), "f");
322   EXPECT_EQ(Base64Decode("Zg"), "f");
323   EXPECT_EQ(Base64Decode("Zm8="), "fo");
324   EXPECT_EQ(Base64Decode("Zm8"), "fo");
325   EXPECT_EQ(Base64Decode("Zm9v"), "foo");
326   EXPECT_EQ(Base64Decode("Zm9vYg=="), "foob");
327   EXPECT_EQ(Base64Decode("Zm9vYg="), "foob");
328   EXPECT_EQ(Base64Decode("Zm9vYg"), "foob");
329   EXPECT_EQ(Base64Decode("Zm9vYmE="), "fooba");
330   EXPECT_EQ(Base64Decode("Zm9vYmE"), "fooba");
331   EXPECT_EQ(Base64Decode("Zm9vYmFy"), "foobar");
332   EXPECT_EQ(Base64Decode("/w=="), "\xff");
333   EXPECT_EQ(Base64Decode("/w="), "\xff");
334   EXPECT_EQ(Base64Decode("/w"), "\xff");
335   EXPECT_EQ(Base64Decode("//4="), "\xff\xfe");
336   EXPECT_EQ(Base64Decode("//4"), "\xff\xfe");
337   EXPECT_EQ(Base64Decode("//79"), "\xff\xfe\xfd");
338   EXPECT_EQ(Base64Decode("//79/A=="), "\xff\xfe\xfd\xfc");
339   EXPECT_EQ(Base64Decode("//79/A="), "\xff\xfe\xfd\xfc");
340   EXPECT_EQ(Base64Decode("//79/A"), "\xff\xfe\xfd\xfc");
341 
342   for (size_t i = 0; i < ArraySize(kPatterns); ++i) {
343     const auto& p = kPatterns[i];
344     std::optional<std::string> dec = Base64Decode(StringView(p.encoded));
345     EXPECT_TRUE(dec.has_value());
346     EXPECT_EQ(dec.value(), StringView(p.decoded, p.decoded_len).ToStdString());
347   }
348 
349   // Error cases:
350   EXPECT_EQ(Base64Decode("Z"), std::nullopt);
351   EXPECT_EQ(Base64Decode("Zm9vY"), std::nullopt);
352 
353   uint8_t buf[4];
354   EXPECT_EQ(Base64Decode("", 0, buf, 2), 0);       // Valid, 0 len.
355   EXPECT_EQ(Base64Decode("Z", 1, buf, 1), -1);     // Invalid input.
356   EXPECT_EQ(Base64Decode("Zg==", 4, buf, 1), -1);  // Not enough dst space.
357 }
358 
359 }  // namespace
360 }  // namespace base
361 }  // namespace perfetto
362