]> Lady’s Gitweb - Pisces/blob - binary.test.js
9dbce5753e7ee3970093973517a82fc6e595d6d1
[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 base16Binary,
20 base16String,
21 base64Binary,
22 base64String,
23 filenameSafeBase64Binary,
24 filenameSafeBase64String,
25 isBase16,
26 isBase64,
27 isFilenameSafeBase64,
28 } from "./binary.js";
29
30 // These tests assume a LITTLE‐ENDIAN environment.
31 const data = new Map([
32 ["", {
33 base16: "",
34 base64: "",
35 }],
36 ["base64", {
37 base16: "006200610073006500360034",
38 base64: "AGIAYQBzAGUANgA0",
39 }],
40 [new Uint16Array([62535]), {
41 base16: "47F4",
42 base64: "R/Q=",
43 }],
44 [new Uint8ClampedArray([75, 73, 66, 73]).buffer, {
45 base16: "4B494249",
46 base64: "S0lCSQ==",
47 }],
48 [new DataView(new Uint8Array([98, 97, 115, 101, 54, 52]).buffer), {
49 base16: "626173653634",
50 base64: "YmFzZTY0",
51 }],
52
53 // The following three examples are from RFC 3548.
54 [new Uint8Array([0x14, 0xFB, 0x9C, 0x03, 0xD9, 0x7E]), {
55 base16: "14FB9C03D97E",
56 base64: "FPucA9l+",
57 }],
58 [new Uint8Array([0x14, 0xFB, 0x9C, 0x03, 0xD9]), {
59 base16: "14FB9C03D9",
60 base64: "FPucA9k=",
61 }],
62 [new Uint8Array([0x14, 0xFB, 0x9C, 0x03]), {
63 base16: "14FB9C03",
64 base64: "FPucAw==",
65 }],
66
67 // The following examples are from the Ruby base32 gem.
68 [new Uint8Array([0x28]), {
69 base16: "28",
70 base64: "KA==",
71 }],
72 [new Uint8Array([0xD6]), {
73 base16: "D6",
74 base64: "1g==",
75 }],
76 [new Uint16Array([0xF8D6]), {
77 base16: "D6F8",
78 base64: "1vg=",
79 }],
80 [new Uint8Array([0xD6, 0xF8, 0x00]), {
81 base16: "D6F800",
82 base64: "1vgA",
83 }],
84 [new Uint8Array([0xD6, 0xF8, 0x10]), {
85 base16: "D6F810",
86 base64: "1vgQ",
87 }],
88 [new Uint32Array([0x0C11F8D6]), {
89 base16: "D6F8110C",
90 base64: "1vgRDA==",
91 }],
92 [new Uint8Array([0xD6, 0xF8, 0x11, 0x0C, 0x80]), {
93 base16: "D6F8110C80",
94 base64: "1vgRDIA=",
95 }],
96 [new Uint16Array([0xF8D6, 0x0C11, 0x3085]), {
97 base16: "D6F8110C8530",
98 base64: "1vgRDIUw",
99 }],
100 ]);
101
102 describe("base16Binary", () => {
103 it("[[Call]] returns the correct data", () => {
104 assertEquals(
105 new Uint8Array(base16Binary("")),
106 new Uint8Array([]),
107 "<empty>",
108 );
109 assertEquals(
110 new Uint8Array(base16Binary("006200610073006500360034")),
111 Uint8Array.from(
112 "\u{0}b\u{0}a\u{0}s\u{0}e\u{0}6\u{0}4",
113 ($) => $.charCodeAt(0),
114 ),
115 "006200610073006500360034",
116 );
117 assertEquals(
118 new Uint16Array(base16Binary("47F4")),
119 new Uint16Array([62535]),
120 "47F4",
121 );
122 assertEquals(
123 new Uint8ClampedArray(base16Binary("4B494249")),
124 new Uint8ClampedArray([75, 73, 66, 73]),
125 "4B494249",
126 );
127 assertEquals(
128 new Uint8Array(base16Binary("626173653634")),
129 new Uint8Array([98, 97, 115, 101, 54, 52]),
130 "626173653634",
131 );
132 assertEquals(
133 new Uint8Array(base16Binary("14FB9C03D97E")),
134 new Uint8Array([0x14, 0xFB, 0x9C, 0x03, 0xD9, 0x7E]),
135 "14FB9C03D97E",
136 );
137 assertEquals(
138 new Uint8Array(base16Binary("14FB9C03D9")),
139 new Uint8Array([0x14, 0xFB, 0x9C, 0x03, 0xD9]),
140 "14FB9C03D9",
141 );
142 assertEquals(
143 new Uint8Array(base16Binary("14FB9C03")),
144 new Uint8Array([0x14, 0xFB, 0x9C, 0x03]),
145 "14FB9C03",
146 );
147 assertEquals(
148 new Uint8Array(base16Binary("28")),
149 new Uint8Array([0x28]),
150 "28",
151 );
152 assertEquals(
153 new Uint8Array(base16Binary("D6")),
154 new Uint8Array([0xD6]),
155 "D6",
156 );
157 assertEquals(
158 new Uint16Array(base16Binary("D6F8")),
159 new Uint16Array([0xF8D6]),
160 "D6F8",
161 );
162 assertEquals(
163 new Uint8Array(base16Binary("D6F800")),
164 new Uint8Array([0xD6, 0xF8, 0x00]),
165 "D6F800",
166 );
167 assertEquals(
168 new Uint8Array(base16Binary("D6F810")),
169 new Uint8Array([0xD6, 0xF8, 0x10]),
170 "D6F810",
171 );
172 assertEquals(
173 new Uint32Array(base16Binary("D6F8110C")),
174 new Uint32Array([0x0C11F8D6]),
175 "D6F8110C",
176 );
177 assertEquals(
178 new Uint8Array(base16Binary("D6F8110C80")),
179 new Uint8Array([0xD6, 0xF8, 0x11, 0x0C, 0x80]),
180 "D6F8110C80",
181 );
182 assertEquals(
183 new Uint16Array(base16Binary("D6F8110C8530")),
184 new Uint16Array([0xF8D6, 0x0C11, 0x3085]),
185 "D6F8110C8530",
186 );
187 });
188
189 it("[[Call]] is case‐insensitive", () => {
190 assertEquals(
191 new Uint8Array(base16Binary("d6f8110C80")),
192 new Uint8Array([0xD6, 0xF8, 0x11, 0x0C, 0x80]),
193 "d6f8110C80",
194 );
195 });
196
197 it("[[Call]] throws when provided with an invalid character", () => {
198 assertThrows(() => base16Binary("ABCG"));
199 });
200
201 it("[[Call]] throws when provided with a length with a remainder of 1 when divided by 2", () => {
202 assertThrows(() => base16Binary("A"));
203 assertThrows(() => base16Binary("ABC"));
204 });
205 });
206
207 describe("base16String", () => {
208 it("[[Call]] returns the correct string", () => {
209 for (const [source, { base16 }] of data) {
210 assertStrictEquals(base16String(source), base16);
211 }
212 });
213 });
214
215 describe("base64Binary", () => {
216 it("[[Call]] returns the correct data", () => {
217 assertEquals(
218 new Uint8Array(base64Binary("")),
219 new Uint8Array([]),
220 "<empty>",
221 );
222 assertEquals(
223 new Uint8Array(base64Binary("AGIAYQBzAGUANgA0")),
224 Uint8Array.from(
225 "\u{0}b\u{0}a\u{0}s\u{0}e\u{0}6\u{0}4",
226 ($) => $.charCodeAt(0),
227 ),
228 "AGIAYQBzAGUANgA0",
229 );
230 assertEquals(
231 new Uint16Array(base64Binary("R/Q=")),
232 new Uint16Array([62535]),
233 "R/Q=",
234 );
235 assertEquals(
236 new Uint8ClampedArray(base64Binary("S0lCSQ==")),
237 new Uint8ClampedArray([75, 73, 66, 73]),
238 "S0lCSQ==",
239 );
240 assertEquals(
241 new Uint8Array(base64Binary("YmFzZTY0")),
242 new Uint8Array([98, 97, 115, 101, 54, 52]),
243 "YmFzZTY0",
244 );
245 assertEquals(
246 new Uint8Array(base64Binary("FPucA9l+")),
247 new Uint8Array([0x14, 0xFB, 0x9C, 0x03, 0xD9, 0x7E]),
248 "FPucA9l+",
249 );
250 assertEquals(
251 new Uint8Array(base64Binary("FPucA9k=")),
252 new Uint8Array([0x14, 0xFB, 0x9C, 0x03, 0xD9]),
253 "FPucA9k=",
254 );
255 assertEquals(
256 new Uint8Array(base64Binary("FPucAw==")),
257 new Uint8Array([0x14, 0xFB, 0x9C, 0x03]),
258 "FPucAw==",
259 );
260 assertEquals(
261 new Uint8Array(base64Binary("KA==")),
262 new Uint8Array([0x28]),
263 "KA==",
264 );
265 assertEquals(
266 new Uint8Array(base64Binary("1g==")),
267 new Uint8Array([0xD6]),
268 "1g==",
269 );
270 assertEquals(
271 new Uint16Array(base64Binary("1vg")),
272 new Uint16Array([0xF8D6]),
273 "1vg",
274 );
275 assertEquals(
276 new Uint8Array(base64Binary("1vgA")),
277 new Uint8Array([0xD6, 0xF8, 0x00]),
278 "1vgA",
279 );
280 assertEquals(
281 new Uint8Array(base64Binary("1vgQ")),
282 new Uint8Array([0xD6, 0xF8, 0x10]),
283 "1vgQ",
284 );
285 assertEquals(
286 new Uint32Array(base64Binary("1vgRDA==")),
287 new Uint32Array([0x0C11F8D6]),
288 "1vgRDA==",
289 );
290 assertEquals(
291 new Uint8Array(base64Binary("1vgRDIA=")),
292 new Uint8Array([0xD6, 0xF8, 0x11, 0x0C, 0x80]),
293 "1vgRDIA=",
294 );
295 assertEquals(
296 new Uint16Array(base64Binary("1vgRDIUw")),
297 new Uint16Array([0xF8D6, 0x0C11, 0x3085]),
298 "1vgRDIUw",
299 );
300 });
301
302 it("[[Call]] throws when provided with an invalid character", () => {
303 assertThrows(() => base64Binary("abc_"));
304 });
305
306 it("[[Call]] throws when provided with an invalid equals", () => {
307 assertThrows(() => base64Binary("abc=="));
308 });
309
310 it("[[Call]] throws when provided with a length with a remainder of 1 when divided by 4", () => {
311 assertThrows(() => base64Binary("abcde"));
312 assertThrows(() => base64Binary("abcde==="));
313 });
314 });
315
316 describe("base64String", () => {
317 it("[[Call]] returns the correct string", () => {
318 for (const [source, { base64 }] of data) {
319 assertStrictEquals(base64String(source), base64);
320 }
321 });
322 });
323
324 describe("filenameSafeBase64Binary", () => {
325 it("[[Call]] returns the correct data", () => {
326 assertEquals(
327 new Uint8Array(filenameSafeBase64Binary("")),
328 new Uint8Array([]),
329 "<empty>",
330 );
331 assertEquals(
332 new Uint8Array(filenameSafeBase64Binary("AGIAYQBzAGUANgA0")),
333 Uint8Array.from(
334 "\u{0}b\u{0}a\u{0}s\u{0}e\u{0}6\u{0}4",
335 ($) => $.charCodeAt(0),
336 ),
337 "AGIAYQBzAGUANgA0",
338 );
339 assertEquals(
340 new Uint16Array(filenameSafeBase64Binary("R_Q=")),
341 new Uint16Array([62535]),
342 "R/Q=",
343 );
344 assertEquals(
345 new Uint8ClampedArray(filenameSafeBase64Binary("S0lCSQ==")),
346 new Uint8ClampedArray([75, 73, 66, 73]),
347 "S0lCSQ==",
348 );
349 assertEquals(
350 new Uint8Array(filenameSafeBase64Binary("YmFzZTY0")),
351 new Uint8Array([98, 97, 115, 101, 54, 52]),
352 "YmFzZTY0",
353 );
354 assertEquals(
355 new Uint8Array(filenameSafeBase64Binary("KA==")),
356 new Uint8Array([0x28]),
357 "KA==",
358 );
359 assertEquals(
360 new Uint8Array(filenameSafeBase64Binary("1g==")),
361 new Uint8Array([0xD6]),
362 "1g==",
363 );
364 assertEquals(
365 new Uint16Array(filenameSafeBase64Binary("1vg")),
366 new Uint16Array([0xF8D6]),
367 "1vg",
368 );
369 assertEquals(
370 new Uint8Array(filenameSafeBase64Binary("1vgA")),
371 new Uint8Array([0xD6, 0xF8, 0x00]),
372 "1vgA",
373 );
374 assertEquals(
375 new Uint8Array(filenameSafeBase64Binary("1vgQ")),
376 new Uint8Array([0xD6, 0xF8, 0x10]),
377 "1vgQ",
378 );
379 assertEquals(
380 new Uint32Array(filenameSafeBase64Binary("1vgQDA==")),
381 new Uint32Array([0x0C10F8D6]),
382 "1vgQDA==",
383 );
384 assertEquals(
385 new Uint8Array(filenameSafeBase64Binary("1vgQDIA=")),
386 new Uint8Array([0xD6, 0xF8, 0x10, 0x0C, 0x80]),
387 "1vgQDIA=",
388 );
389 assertEquals(
390 new Uint16Array(filenameSafeBase64Binary("1vgQDIUw")),
391 new Uint16Array([0xF8D6, 0x0C10, 0x3085]),
392 "1vgQDIUw",
393 );
394 });
395
396 it("[[Call]] throws when provided with an invalid character", () => {
397 assertThrows(() => filenameSafeBase64Binary("abc/"));
398 });
399
400 it("[[Call]] throws when provided with an invalid equals", () => {
401 assertThrows(() => filenameSafeBase64Binary("abc=="));
402 });
403
404 it("[[Call]] throws when provided with a length with a remainder of 1 when divided by 4", () => {
405 assertThrows(() => filenameSafeBase64Binary("abcde"));
406 assertThrows(() => filenameSafeBase64Binary("abcde==="));
407 });
408 });
409
410 describe("filenameSafeBase64String", () => {
411 it("[[Call]] returns the correct string", () => {
412 for (const [source, { base64 }] of data) {
413 assertStrictEquals(
414 filenameSafeBase64String(source),
415 base64.replace("+", "-").replace("/", "_"),
416 );
417 }
418 });
419 });
420
421 describe("isBase16", () => {
422 it("[[Call]] returns true for base64 strings", () => {
423 for (const { base16 } of data.values()) {
424 assert(isBase16(base16));
425 assert(isBase16(base16.toLowerCase()));
426 }
427 });
428
429 it("[[Call]] returns false for others", () => {
430 [
431 undefined,
432 null,
433 true,
434 Symbol(),
435 27,
436 98n,
437 {},
438 [],
439 () => {},
440 new Proxy({}, {}),
441 "abc_",
442 "a",
443 "abc",
444 "abcg",
445 ].forEach((value) => assert(!isBase16(value)));
446 });
447 });
448
449 describe("isBase64", () => {
450 it("[[Call]] returns true for base64 strings", () => {
451 for (const { base64 } of data.values()) {
452 assert(isBase64(base64));
453 }
454 });
455
456 it("[[Call]] returns false for others", () => {
457 [
458 undefined,
459 null,
460 true,
461 Symbol(),
462 27,
463 98n,
464 {},
465 [],
466 () => {},
467 new Proxy({}, {}),
468 "abc_",
469 "a",
470 "abc==",
471 ].forEach((value) => assert(!isBase64(value)));
472 });
473 });
474
475 describe("isFilenameSafeBase64", () => {
476 it("[[Call]] returns true for filename‐safe base64 strings", () => {
477 for (const { base64 } of data.values()) {
478 assert(
479 isFilenameSafeBase64(
480 base64.replace("+", "-").replace("/", "_"),
481 ),
482 );
483 }
484 });
485
486 it("[[Call]] returns false for others", () => {
487 [
488 undefined,
489 null,
490 true,
491 Symbol(),
492 27,
493 98n,
494 {},
495 [],
496 () => {},
497 new Proxy({}, {}),
498 "abc/",
499 "a",
500 "abc==",
501 ].forEach((value) => assert(!isFilenameSafeBase64(value)));
502 });
503 });
This page took 0.140167 seconds and 3 git commands to generate.