Fork of daniellemaywood.uk/gleam — Wasm codegen work
15 kB
545 lines
1import {
2 BitString,
3 CustomType,
4 Empty,
5 Error,
6 List,
7 NonEmpty,
8 Ok,
9 UtfCodepoint,
10 codepointBits,
11 divideFloat,
12 divideInt,
13 inspect,
14 isEqual,
15 stringBits,
16 toBitString,
17 toList,
18} from "./prelude.mjs";
19
20let failures = 0;
21let passes = 0;
22
23function pass() {
24 process.stdout.write(`\u001b[${32}m.\u001b[${0}m`);
25 passes++;
26}
27
28function fail(message) {
29 console.log("");
30 console.assert(false, message);
31 failures++;
32}
33
34function assertEqual(a, b) {
35 if (isEqual(a, b)) {
36 pass();
37 } else {
38 fail(`\n\t${inspect(a)}\n\t!=\n\t${inspect(b)}`);
39 }
40}
41
42function assertNotEqual(a, b) {
43 if (isEqual(a, b)) {
44 fail(`\n\t${inspect(a)}\n\t==\n\t${inspect(b)}`);
45 } else {
46 pass();
47 }
48}
49
50class ExampleRecordImpl extends CustomType {
51 constructor(first, detail, boop) {
52 super();
53 this[0] = first;
54 this.detail = detail;
55 this.boop = boop;
56 }
57}
58
59let fmt = new Intl.DateTimeFormat("en-GB", { timeStyle: "medium" });
60console.log(`Running tests at ${fmt.format(new Date())}\n`);
61
62// Equality of Gleam values
63
64assertEqual(true, true);
65assertEqual(false, false);
66assertEqual(undefined, undefined);
67assertNotEqual(true, false);
68assertNotEqual(false, true);
69assertNotEqual(undefined, false);
70assertNotEqual(undefined, true);
71assertNotEqual(true, undefined);
72assertNotEqual(false, undefined);
73
74assertEqual(1, 1);
75assertNotEqual(1, 2);
76assertEqual(1.1, 1.1);
77assertNotEqual(2.1, 1.1);
78assertEqual(-1, -1);
79assertNotEqual(-1, 1);
80assertEqual(-1.1, -1.1);
81assertNotEqual(-1.1, 1.1);
82
83assertEqual("", "");
84assertEqual("123", "123");
85assertEqual("👽", "👽");
86assertNotEqual("👽", "👾");
87
88assertEqual(new Ok(1), new Ok(1));
89assertEqual(new Ok(2), new Ok(2));
90assertEqual(new Ok(new Ok(2)), new Ok(new Ok(2)));
91assertNotEqual(new Ok(1), new Ok(2));
92assertNotEqual(new Ok(new Ok(2)), new Ok(new Ok(3)));
93
94assertEqual(new Error(1), new Error(1));
95assertEqual(new Error(2), new Error(2));
96assertEqual(new Error(new Error(2)), new Error(new Error(2)));
97assertNotEqual(new Error(2), new Error(3));
98assertNotEqual(new Error(new Error(2)), new Error(new Error(3)));
99
100assertEqual(
101 new ExampleRecordImpl(undefined, 1, new Ok(2.1)),
102 new ExampleRecordImpl(undefined, 1, new Ok(2.1))
103);
104assertNotEqual(
105 new ExampleRecordImpl(undefined, 1, new Ok("2.1")),
106 new ExampleRecordImpl(undefined, 1, new Ok(2.1))
107);
108
109assertEqual(List.fromArray([]), List.fromArray([]));
110assertEqual(
111 List.fromArray([1, 2, new Ok(1)]),
112 List.fromArray([1, 2, new Ok(1)])
113);
114assertNotEqual(
115 List.fromArray([1, 2, new Ok(1)]),
116 List.fromArray([1, 2, new Ok(2)])
117);
118assertNotEqual(List.fromArray([1, 2]), List.fromArray([1, 2, new Ok(2)]));
119assertNotEqual(List.fromArray([1]), List.fromArray([]));
120assertNotEqual(List.fromArray([]), List.fromArray([1]));
121
122assertEqual(
123 new BitString(new Uint8Array([])),
124 new BitString(new Uint8Array([]))
125);
126assertEqual(
127 new BitString(new Uint8Array([1, 2, 3])),
128 new BitString(new Uint8Array([1, 2, 3]))
129);
130assertNotEqual(
131 new BitString(new Uint8Array([1, 2])),
132 new BitString(new Uint8Array([1, 2, 3]))
133);
134
135assertEqual(new UtfCodepoint(128013), new UtfCodepoint(128013));
136assertNotEqual(new UtfCodepoint(128013), new UtfCodepoint(128014));
137
138// toBitString
139
140assertEqual(new BitString(new Uint8Array([])), toBitString([]));
141
142assertEqual(
143 new BitString(new Uint8Array([97, 98, 99])),
144 toBitString([stringBits("abc")])
145);
146
147assertEqual(
148 new BitString(new Uint8Array([97])),
149 toBitString([codepointBits(new UtfCodepoint(97))])
150);
151
152assertEqual(
153 new BitString(new Uint8Array([240, 159, 144, 141])),
154 toBitString([codepointBits(new UtfCodepoint(128013))])
155);
156
157// toList
158
159assertEqual(toList([]), List.fromArray([]));
160assertEqual(toList([1, 2, 3]), List.fromArray([1, 2, 3]));
161assertEqual(toList([1, 2], toList([3, 4])), List.fromArray([1, 2, 3, 4]));
162assertEqual(toList([1, 2, 3], toList([4, 5])), List.fromArray([1, 2, 3, 4, 5]));
163
164// Equality of JavaScript values
165
166assertEqual([], []);
167assertEqual([1, 2], [1, 2]);
168assertEqual([new Ok([1, 2])], [new Ok([1, 2])]);
169assertNotEqual([], [[]]);
170assertNotEqual([], [1, []]);
171assertNotEqual([1, []], []);
172
173assertEqual({}, {});
174assertEqual({ a: 1 }, { a: 1 });
175assertEqual({ a: 1, b: 2 }, { b: 2, a: 1 });
176assertEqual({ a: new Ok(1) }, { a: new Ok(1) });
177assertNotEqual({ a: new Ok(2) }, { a: new Ok(1) });
178
179assertEqual(new Date(0), new Date(0));
180assertNotEqual(new Date(1), new Date(0));
181
182assertEqual(new Uint8Array([1, 2]), new Uint8Array([1, 2]));
183assertEqual(new Uint16Array([1, 2]), new Uint16Array([1, 2]));
184assertEqual(new Uint32Array([1, 2]), new Uint32Array([1, 2]));
185assertNotEqual(new Uint8Array([1, 3]), new Uint8Array([1, 2]));
186assertNotEqual(new Uint16Array([1, 3]), new Uint16Array([1, 2]));
187assertNotEqual(new Uint32Array([1, 3]), new Uint32Array([1, 2]));
188
189// Promises are not equal unless they have reference equality
190let promise = Promise.resolve(1);
191assertEqual(promise, promise);
192assertNotEqual(Promise.resolve(1), Promise.resolve(1));
193
194// Functions are not equal unless they have reference equality
195let fun = () => 1;
196assertEqual(fun, fun);
197assertNotEqual(
198 () => 1,
199 () => 1
200);
201
202// Maps are compared structurally
203let map = new Map([["a", 1]]);
204assertEqual(map, map);
205assertEqual(new Map([["a", 1]]), new Map([["a", 1]]));
206assertNotEqual(
207 new Map([
208 ["a", 1],
209 ["b", 2],
210 ]),
211 new Map([["a", 1]])
212);
213assertNotEqual(
214 new Map([["a", 1]]),
215 new Map([
216 ["a", 1],
217 ["b", 2],
218 ])
219);
220assertNotEqual(new Map([["a", 1]]), new Map([["b", 1]]));
221assertEqual(
222 new Map([["a", new Map([["a", []]])]]),
223 new Map([["a", new Map([["a", []]])]])
224);
225
226// Sets are compared structurally
227let set = new Set(["a", 1]);
228assertEqual(set, set);
229assertEqual(new Set(["a", 1]), new Set(["a", 1]));
230assertNotEqual(new Set(["a", 1]), new Set(["b", 1]));
231assertNotEqual(new Set(["a", 1, "b"]), new Set(["a", 1]));
232assertNotEqual(new Set(["a", 1]), new Set(["a", 1, "b"]));
233assertNotEqual(
234 new Set(["a", new Map([["a", []]])]),
235 new Set(["a", new Map([["a", []]])])
236);
237
238// WeakMaps are not equal unless they have reference equality
239let weak_map = new WeakMap([[map, 1]]);
240assertEqual(weak_map, weak_map);
241assertNotEqual(new WeakMap([[map, 1]]), new WeakMap([[map, 1]]));
242
243// WeakSets are not equal unless they have reference equality
244let weak_set = new WeakSet([map, set]);
245assertEqual(weak_set, weak_set);
246assertNotEqual(new WeakSet([map, set]), new WeakSet([map, set]));
247
248class ExampleA {
249 constructor(x) {
250 this.x = x;
251 }
252}
253
254class ExampleB {
255 constructor(x) {
256 this.x = x;
257 }
258}
259
260assertEqual(new ExampleA(1), new ExampleA(1));
261assertEqual(new ExampleB(1), new ExampleB(1));
262assertNotEqual(new ExampleA(1), new ExampleA(2));
263assertNotEqual(new ExampleA(1), new ExampleB(1));
264
265// Equality between Gleam prelude types from different packages
266//
267// The prelude is not global, each package gets one to fit into the JavaScript
268// module system. We work around this by having a single global
269// `globalThis.__gleam_prelude_variant` symbol and using this in place of the
270// constructor to check if Gleam values are of the same kind.
271//
272// In these tests we simulate a different prelude by creating new version of the
273// prelude types through inheritance.
274
275class AnotherEmpty extends Empty {}
276class AnotherNonEmpty extends NonEmpty {}
277class AnotherBitString extends BitString {}
278class AnotherOk extends Ok {}
279class AnotherError extends Error {}
280class AnotherUtfCodepoint extends UtfCodepoint {}
281
282assertEqual(List.fromArray([]), new AnotherEmpty());
283assertEqual(List.fromArray([1]), new AnotherNonEmpty(1, new AnotherEmpty()));
284assertNotEqual(List.fromArray([1]), new AnotherEmpty());
285assertEqual(new AnotherEmpty(), List.fromArray([]));
286assertEqual(new AnotherNonEmpty(1, new AnotherEmpty()), List.fromArray([1]));
287assertNotEqual(new AnotherEmpty(), List.fromArray([1]));
288
289assertEqual(new Ok(1), new AnotherOk(1));
290assertEqual(new AnotherOk(1), new Ok(1));
291assertNotEqual(new Ok(2), new AnotherOk(1));
292assertNotEqual(new AnotherOk(2), new Ok(1));
293
294assertEqual(new Error(1), new AnotherError(1));
295assertEqual(new AnotherError(1), new Error(1));
296assertNotEqual(new Error(2), new AnotherError(1));
297assertNotEqual(new AnotherError(2), new Error(1));
298
299assertEqual(
300 new BitString(new Uint8Array([1, 2])),
301 new AnotherBitString(new Uint8Array([1, 2]))
302);
303assertEqual(
304 new AnotherBitString(new Uint8Array([1, 2])),
305 new BitString(new Uint8Array([1, 2]))
306);
307assertNotEqual(
308 new BitString(new Uint8Array([2, 2])),
309 new AnotherBitString(new Uint8Array([1, 2]))
310);
311assertNotEqual(
312 new AnotherBitString(new Uint8Array([2, 2])),
313 new BitString(new Uint8Array([1, 2]))
314);
315
316assertEqual(new UtfCodepoint(128013), new AnotherUtfCodepoint(128013));
317assertEqual(new AnotherUtfCodepoint(128013), new UtfCodepoint(128013));
318assertNotEqual(new UtfCodepoint(128014), new AnotherUtfCodepoint(128013));
319assertNotEqual(new AnotherUtfCodepoint(128014), new UtfCodepoint(128013));
320
321// Inspecting Gleam values
322
323assertEqual(inspect(true), "True");
324assertEqual(inspect(false), "False");
325assertEqual(inspect(undefined), "Nil");
326
327assertEqual(inspect(0), "0");
328assertEqual(inspect(1), "1");
329assertEqual(inspect(2), "2");
330assertEqual(inspect(-1), "-1");
331assertEqual(inspect(-2), "-2");
332
333assertEqual(inspect(0.23), "0.23");
334assertEqual(inspect(1.23), "1.23");
335assertEqual(inspect(2.23), "2.23");
336assertEqual(inspect(-1.23), "-1.23");
337assertEqual(inspect(-2.23), "-2.23");
338
339assertEqual(inspect(new Ok(1)), "Ok(1)");
340assertEqual(inspect(new Ok(true)), "Ok(True)");
341assertEqual(inspect(new Ok(false)), "Ok(False)");
342assertEqual(inspect(new Ok(undefined)), "Ok(Nil)");
343
344assertEqual(inspect(new Error(2)), "Error(2)");
345assertEqual(inspect(new Error(true)), "Error(True)");
346assertEqual(inspect(new Error(false)), "Error(False)");
347assertEqual(inspect(new Error(undefined)), "Error(Nil)");
348
349assertEqual(
350 inspect(new ExampleRecordImpl(undefined, 1, 2.1)),
351 "ExampleRecordImpl(Nil, detail: 1, boop: 2.1)"
352);
353assertEqual(
354 inspect(new ExampleRecordImpl(new Ok(1), 1, 2.1)),
355 "ExampleRecordImpl(Ok(1), detail: 1, boop: 2.1)"
356);
357
358assertEqual(inspect([]), "#()");
359assertEqual(inspect([1, 2, 3]), "#(1, 2, 3)");
360assertEqual(inspect([new Ok(1), new Ok(2)]), "#(Ok(1), Ok(2))");
361
362assertEqual(inspect(List.fromArray([])), "[]");
363assertEqual(inspect(List.fromArray([1, 2, 3])), "[1, 2, 3]");
364assertEqual(inspect(List.fromArray([new Ok(1), new Ok(2)])), "[Ok(1), Ok(2)]");
365
366assertEqual(inspect(new BitString(new Uint8Array([]))), "<<>>");
367assertEqual(inspect(new BitString(new Uint8Array([1, 2, 3]))), "<<1, 2, 3>>");
368
369assertEqual(inspect(new UtfCodepoint(128013)), "//utfcodepoint(🐍)");
370
371assertEqual(
372 inspect(() => undefined),
373 "//fn() { ... }"
374);
375
376assertEqual(
377 inspect((a) => undefined),
378 "//fn(a) { ... }"
379);
380
381assertEqual(
382 inspect((x, y) => undefined),
383 "//fn(a, b) { ... }"
384);
385
386assertEqual(
387 inspect((x, y, z) => undefined),
388 "//fn(a, b, c) { ... }"
389);
390
391// Inspecting JavaScript values
392
393assertEqual(inspect(null), "//js(null)");
394assertEqual(inspect({}), "//js({})");
395assertEqual(inspect({ a: 1 }), '//js({ "a": 1 })');
396assertEqual(inspect({ a: 1, b: 2 }), '//js({ "a": 1, "b": 2 })');
397assertEqual(inspect({ a: 1, b: new Ok(1) }), '//js({ "a": 1, "b": Ok(1) })');
398assertEqual(
399 inspect(new globalThis.Error("Oh no")),
400 '//js(Error { "message": "Oh no" })'
401);
402assertEqual(
403 inspect(
404 (() => {
405 let error = new globalThis.Error("Oh no");
406 error.other = new Ok(1);
407 return error;
408 })()
409 ),
410 '//js(Error { "message": "Oh no", "other": Ok(1) })'
411);
412
413// Generic JS objects
414assertEqual(inspect(Promise.resolve(1)), "//js(Promise {})");
415
416// Inspecting Dates
417assertEqual(
418 inspect(new Date("1991-01-05")),
419 '//js(Date("1991-01-05T00:00:00.000Z"))'
420);
421
422// Inspecting RegExps
423assertEqual(inspect(/1[23]/g), "//js(/1[23]/g)");
424
425// Inspecting Maps
426assertEqual(
427 inspect(
428 new Map([
429 [1, 2],
430 [3, new Ok([1, 2])],
431 ])
432 ),
433 "//js(Map { 1: 2, 3: Ok(#(1, 2)) })"
434);
435
436// Inspecting Sets
437assertEqual(
438 inspect(new Set([1, 2, new Ok([1, 2])])),
439 "//js(Set(1, 2, Ok(#(1, 2))))"
440);
441
442// Result.isOk
443
444assertEqual(new Ok(1).isOk(), true);
445assertEqual(new Error(1).isOk(), false);
446
447// List.atLeastLength
448
449assertEqual(List.fromArray([]).atLeastLength(0), true);
450assertEqual(List.fromArray([]).atLeastLength(1), false);
451assertEqual(List.fromArray([]).atLeastLength(-1), true);
452assertEqual(List.fromArray([1]).atLeastLength(0), true);
453assertEqual(List.fromArray([1]).atLeastLength(1), true);
454assertEqual(List.fromArray([1]).atLeastLength(2), false);
455assertEqual(List.fromArray([1]).atLeastLength(-1), true);
456
457// List.hasLength
458
459assertEqual(toList([]).hasLength(0), true);
460assertEqual(toList([]).hasLength(1), false);
461assertEqual(toList([]).hasLength(-1), false);
462assertEqual(toList([1]).hasLength(0), false);
463assertEqual(toList([1]).hasLength(1), true);
464assertEqual(toList([1]).hasLength(2), false);
465assertEqual(toList([1, 1]).hasLength(1), false);
466assertEqual(toList([1, 1]).hasLength(2), true);
467assertEqual(toList([1, 1]).hasLength(3), false);
468
469// List iterable interface
470
471assertEqual([...toList([])], []);
472assertEqual([...toList([1, 2, 3])], [1, 2, 3]);
473
474// BitString.length
475
476assertEqual(new BitString(new Uint8Array([])).length, 0);
477assertEqual(new BitString(new Uint8Array([1, 2])).length, 2);
478assertEqual(new BitString(new Uint8Array([1, 2, 3, 4])).length, 4);
479
480//
481// Division
482//
483
484assertEqual(divideInt(1, 0), 0);
485assertEqual(divideInt(1, 1), 1);
486assertEqual(divideInt(1, 2), 0);
487assertEqual(divideInt(3, 2), 1);
488assertEqual(divideInt(11, 3), 3);
489assertEqual(divideInt(-1, 0), 0);
490assertEqual(divideInt(-1, 1), -1);
491assertEqual(divideInt(-1, 2), -0);
492assertEqual(divideInt(-3, 2), -1);
493assertEqual(divideInt(-11, 3), -3);
494assertEqual(divideInt(1, -1), -1);
495assertEqual(divideInt(1, -2), 0);
496assertEqual(divideInt(3, -2), -1);
497assertEqual(divideInt(11, -3), -3);
498assertEqual(divideInt(-1, -1), 1);
499assertEqual(divideInt(-1, -2), 0);
500assertEqual(divideInt(-3, -2), 1);
501assertEqual(divideInt(-11, -3), 3);
502
503assertEqual(divideFloat(1.5, 0.0), 0.0);
504assertEqual(divideFloat(1.5, 2.0), 0.75);
505assertEqual(divideFloat(1.5, 2.5), 0.6);
506assertEqual(divideFloat(-1.5, 0.0), -0.0);
507assertEqual(divideFloat(-1.5, 2.0), -0.75);
508assertEqual(divideFloat(-1.5, 2.5), -0.6);
509assertEqual(divideFloat(1.5, -0.0), -0.0);
510assertEqual(divideFloat(1.5, -2.0), -0.75);
511assertEqual(divideFloat(1.5, -2.5), -0.6);
512assertEqual(divideFloat(-1.5, -0.0), 0.0);
513assertEqual(divideFloat(-1.5, -2.0), 0.75);
514assertEqual(divideFloat(-1.5, -2.5), 0.6);
515
516// Record updates
517
518assertEqual(new Ok(1).withFields({ 0: 2 }), new Ok(2));
519assertEqual(new Error(1).withFields({ 0: 2 }), new Error(2));
520
521assertEqual(
522 new ExampleRecordImpl(1, 2, 3).withFields({}),
523 new ExampleRecordImpl(1, 2, 3)
524);
525assertEqual(
526 new ExampleRecordImpl(1, 2, 3).withFields({ boop: 6, 0: 40 }),
527 new ExampleRecordImpl(40, 2, 6)
528);
529assertEqual(
530 new ExampleRecordImpl(1, 2, 3).withFields({ boop: 4, detail: 5, 0: 6 }),
531 new ExampleRecordImpl(6, 5, 4)
532);
533
534//
535// Summary
536//
537
538console.log(`
539
540${passes + failures} tests
541${passes} passes
542${failures} failures
543`);
544
545if (failures) process.exit(1);