]> Lady’s Gitweb - Pisces/blob - binary.test.js
Fix base64 implementation
[Pisces] / binary.test.js
1 // ♓🌟 Piscēs ∷ binary.test.js
2 // ====================================================================
3 //
4 // Copyright © 2020–2023 Lady [@ Lady’s Computer].
5 //
6 // This Source Code Form is subject to the terms of the Mozilla Public
7 // License, v. 2.0. If a copy of the MPL was not distributed with this
8 // file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
9
10 import {
11 assert,
12 assertEquals,
13 assertStrictEquals,
14 assertThrows,
15 describe,
16 it,
17 } from "./dev-deps.js";
18 import {
19 base64Binary,
20 base64String,
21 filenameSafeBase64Binary,
22 filenameSafeBase64String,
23 isBase64,
24 isFilenameSafeBase64,
25 } from "./binary.js";
26
27 // These tests assume a LITTLE‐ENDIAN environment.
28 const data = new Map([
29 ["", {
30 base64: "",
31 }],
32 ["base64", {
33 base64: "AGIAYQBzAGUANgA0",
34 }],
35 [new Uint16Array([62535]), {
36 base64: "R/Q=",
37 }],
38 [new Uint8ClampedArray([75, 73, 66, 73]).buffer, {
39 base64: "S0lCSQ==",
40 }],
41 [new DataView(new Uint8Array([98, 97, 115, 101, 54, 52]).buffer), {
42 base64: "YmFzZTY0",
43 }],
44
45 // The following three examples are from RFC 3548.
46 [new Uint8Array([0x14, 0xFB, 0x9C, 0x03, 0xD9, 0x7E]), {
47 base64: "FPucA9l+",
48 }],
49 [new Uint8Array([0x14, 0xFB, 0x9C, 0x03, 0xD9]), {
50 base64: "FPucA9k=",
51 }],
52 [new Uint8Array([0x14, 0xFB, 0x9C, 0x03]), {
53 base64: "FPucAw==",
54 }],
55
56 // The following examples are from the Ruby base32 gem.
57 [new Uint8Array([0x28]), {
58 base64: "KA==",
59 }],
60 [new Uint8Array([0xD6]), {
61 base64: "1g==",
62 }],
63 [new Uint16Array([0xF8D6]), {
64 base64: "1vg=",
65 }],
66 [new Uint8Array([0xD6, 0xF8, 0x00]), {
67 base64: "1vgA",
68 }],
69 [new Uint8Array([0xD6, 0xF8, 0x10]), {
70 base64: "1vgQ",
71 }],
72 [new Uint32Array([0x0C11F8D6]), {
73 base64: "1vgRDA==",
74 }],
75 [new Uint8Array([0xD6, 0xF8, 0x11, 0x0C, 0x80]), {
76 base64: "1vgRDIA=",
77 }],
78 [new Uint16Array([0xF8D6, 0x0C11, 0x3085]), {
79 base64: "1vgRDIUw",
80 }],
81 ]);
82
83 describe("base64Binary", () => {
84 it("[[Call]] returns the correct data", () => {
85 assertEquals(
86 new Uint8Array(base64Binary("")),
87 new Uint8Array([]),
88 "<empty>",
89 );
90 assertEquals(
91 new Uint8Array(base64Binary("AGIAYQBzAGUANgA0")),
92 Uint8Array.from(
93 "\u{0}b\u{0}a\u{0}s\u{0}e\u{0}6\u{0}4",
94 ($) => $.charCodeAt(0),
95 ),
96 "AGIAYQBzAGUANgA0",
97 );
98 assertEquals(
99 new Uint16Array(base64Binary("R/Q=")),
100 new Uint16Array([62535]),
101 "R/Q=",
102 );
103 assertEquals(
104 new Uint8ClampedArray(base64Binary("S0lCSQ==")),
105 new Uint8ClampedArray([75, 73, 66, 73]),
106 "S0lCSQ==",
107 );
108 assertEquals(
109 new Uint8Array(base64Binary("YmFzZTY0")),
110 new Uint8Array([98, 97, 115, 101, 54, 52]),
111 "YmFzZTY0",
112 );
113 assertEquals(
114 new Uint8Array(base64Binary("FPucA9l+")),
115 new Uint8Array([0x14, 0xFB, 0x9C, 0x03, 0xD9, 0x7E]),
116 "FPucA9l+",
117 );
118 assertEquals(
119 new Uint8Array(base64Binary("FPucA9k=")),
120 new Uint8Array([0x14, 0xFB, 0x9C, 0x03, 0xD9]),
121 "FPucA9k=",
122 );
123 assertEquals(
124 new Uint8Array(base64Binary("FPucAw==")),
125 new Uint8Array([0x14, 0xFB, 0x9C, 0x03]),
126 "FPucAw==",
127 );
128 assertEquals(
129 new Uint8Array(base64Binary("KA==")),
130 new Uint8Array([0x28]),
131 "KA==",
132 );
133 assertEquals(
134 new Uint8Array(base64Binary("1g==")),
135 new Uint8Array([0xD6]),
136 "1g==",
137 );
138 assertEquals(
139 new Uint16Array(base64Binary("1vg")),
140 new Uint16Array([0xF8D6]),
141 "1vg",
142 );
143 assertEquals(
144 new Uint8Array(base64Binary("1vgA")),
145 new Uint8Array([0xD6, 0xF8, 0x00]),
146 "1vgA",
147 );
148 assertEquals(
149 new Uint8Array(base64Binary("1vgQ")),
150 new Uint8Array([0xD6, 0xF8, 0x10]),
151 "1vgQ",
152 );
153 assertEquals(
154 new Uint32Array(base64Binary("1vgRDA==")),
155 new Uint32Array([0x0C11F8D6]),
156 "1vgRDA==",
157 );
158 assertEquals(
159 new Uint8Array(base64Binary("1vgRDIA=")),
160 new Uint8Array([0xD6, 0xF8, 0x11, 0x0C, 0x80]),
161 "1vgRDIA=",
162 );
163 assertEquals(
164 new Uint16Array(base64Binary("1vgRDIUw")),
165 new Uint16Array([0xF8D6, 0x0C11, 0x3085]),
166 "1vgRDIUw",
167 );
168 });
169
170 it("[[Call]] throws when provided with an invalid character", () => {
171 assertThrows(() => base64Binary("abc_"));
172 });
173
174 it("[[Call]] throws when provided with an invalid equals", () => {
175 assertThrows(() => base64Binary("abc=="));
176 });
177
178 it("[[Call]] throws when provided with a length with a remainder of 1 when divided by 4", () => {
179 assertThrows(() => base64Binary("abcde"));
180 assertThrows(() => base64Binary("abcde==="));
181 });
182 });
183
184 describe("base64String", () => {
185 it("[[Call]] returns the correct string", () => {
186 for (const [source, { base64 }] of data) {
187 assertStrictEquals(base64String(source), base64);
188 }
189 });
190 });
191
192 describe("filenameSafeBase64Binary", () => {
193 it("[[Call]] returns the correct data", () => {
194 assertEquals(
195 new Uint8Array(filenameSafeBase64Binary("")),
196 new Uint8Array([]),
197 "<empty>",
198 );
199 assertEquals(
200 new Uint8Array(filenameSafeBase64Binary("AGIAYQBzAGUANgA0")),
201 Uint8Array.from(
202 "\u{0}b\u{0}a\u{0}s\u{0}e\u{0}6\u{0}4",
203 ($) => $.charCodeAt(0),
204 ),
205 "AGIAYQBzAGUANgA0",
206 );
207 assertEquals(
208 new Uint16Array(filenameSafeBase64Binary("R_Q=")),
209 new Uint16Array([62535]),
210 "R/Q=",
211 );
212 assertEquals(
213 new Uint8ClampedArray(filenameSafeBase64Binary("S0lCSQ==")),
214 new Uint8ClampedArray([75, 73, 66, 73]),
215 "S0lCSQ==",
216 );
217 assertEquals(
218 new Uint8Array(filenameSafeBase64Binary("YmFzZTY0")),
219 new Uint8Array([98, 97, 115, 101, 54, 52]),
220 "YmFzZTY0",
221 );
222 assertEquals(
223 new Uint8Array(filenameSafeBase64Binary("KA==")),
224 new Uint8Array([0x28]),
225 "KA==",
226 );
227 assertEquals(
228 new Uint8Array(filenameSafeBase64Binary("1g==")),
229 new Uint8Array([0xD6]),
230 "1g==",
231 );
232 assertEquals(
233 new Uint16Array(filenameSafeBase64Binary("1vg")),
234 new Uint16Array([0xF8D6]),
235 "1vg",
236 );
237 assertEquals(
238 new Uint8Array(filenameSafeBase64Binary("1vgA")),
239 new Uint8Array([0xD6, 0xF8, 0x00]),
240 "1vgA",
241 );
242 assertEquals(
243 new Uint8Array(filenameSafeBase64Binary("1vgQ")),
244 new Uint8Array([0xD6, 0xF8, 0x10]),
245 "1vgQ",
246 );
247 assertEquals(
248 new Uint32Array(filenameSafeBase64Binary("1vgQDA==")),
249 new Uint32Array([0x0C10F8D6]),
250 "1vgQDA==",
251 );
252 assertEquals(
253 new Uint8Array(filenameSafeBase64Binary("1vgQDIA=")),
254 new Uint8Array([0xD6, 0xF8, 0x10, 0x0C, 0x80]),
255 "1vgQDIA=",
256 );
257 assertEquals(
258 new Uint16Array(filenameSafeBase64Binary("1vgQDIUw")),
259 new Uint16Array([0xF8D6, 0x0C10, 0x3085]),
260 "1vgQDIUw",
261 );
262 });
263
264 it("[[Call]] throws when provided with an invalid character", () => {
265 assertThrows(() => filenameSafeBase64Binary("abc/"));
266 });
267
268 it("[[Call]] throws when provided with an invalid equals", () => {
269 assertThrows(() => filenameSafeBase64Binary("abc=="));
270 });
271
272 it("[[Call]] throws when provided with a length with a remainder of 1 when divided by 4", () => {
273 assertThrows(() => filenameSafeBase64Binary("abcde"));
274 assertThrows(() => filenameSafeBase64Binary("abcde==="));
275 });
276 });
277
278 describe("filenameSafeBase64String", () => {
279 it("[[Call]] returns the correct string", () => {
280 for (const [source, { base64 }] of data) {
281 assertStrictEquals(
282 filenameSafeBase64String(source),
283 base64.replace("+", "-").replace("/", "_"),
284 );
285 }
286 });
287 });
288
289 describe("isBase64", () => {
290 it("[[Call]] returns true for base64 strings", () => {
291 for (const { base64 } of data.values()) {
292 assert(isBase64(base64));
293 }
294 });
295
296 it("[[Call]] returns false for others", () => {
297 [
298 undefined,
299 null,
300 true,
301 Symbol(),
302 27,
303 98n,
304 {},
305 [],
306 () => {},
307 new Proxy({}, {}),
308 "abc_",
309 "a",
310 "abc==",
311 ].forEach((value) => assert(!isBase64(value)));
312 });
313 });
314
315 describe("isFilenameSafeBase64", () => {
316 it("[[Call]] returns true for filename‐safe base64 strings", () => {
317 for (const { base64 } of data.values()) {
318 assert(
319 isFilenameSafeBase64(
320 base64.replace("+", "-").replace("/", "_"),
321 ),
322 );
323 }
324 });
325
326 it("[[Call]] returns false for others", () => {
327 [
328 undefined,
329 null,
330 true,
331 Symbol(),
332 27,
333 98n,
334 {},
335 [],
336 () => {},
337 new Proxy({}, {}),
338 "abc/",
339 "a",
340 "abc==",
341 ].forEach((value) => assert(!isFilenameSafeBase64(value)));
342 });
343 });
This page took 0.077253 seconds and 5 git commands to generate.