@calcit/ternary-tree 0.0.23 → 0.0.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -4
- package/TESTING.md +155 -0
- package/lib/benchmark.d.mts +1 -0
- package/lib/benchmark.mjs +67 -0
- package/lib/list.d.mts +2 -0
- package/lib/list.mjs +178 -124
- package/lib/map.mjs +124 -101
- package/lib/test-list-detailed-perf.d.mts +1 -0
- package/lib/test-list-detailed-perf.mjs +165 -0
- package/lib/test-list-perf.d.mts +1 -0
- package/lib/test-list-perf.mjs +153 -0
- package/lib/test-list.mjs +202 -203
- package/lib/test-map-perf.d.mts +1 -0
- package/lib/test-map-perf.mjs +70 -0
- package/lib/test-map.mjs +201 -208
- package/lib/test-utils.d.mts +9 -5
- package/lib/test-utils.mjs +131 -18
- package/lib/{main.mjs → test.mjs} +5 -0
- package/package.json +13 -5
- /package/lib/{main.d.mts → test.d.mts} +0 -0
package/lib/test-map.mjs
CHANGED
@@ -1,215 +1,208 @@
|
|
1
1
|
import { hashGenerator } from "./types.mjs";
|
2
2
|
import { cmp, deepEqual } from "./utils.mjs";
|
3
|
-
import { test, check, justDisplay } from "./test-utils.mjs";
|
3
|
+
import { describe, test, check, justDisplay } from "./test-utils.mjs";
|
4
4
|
import { initTernaryTreeMap, initTernaryTreeMapFromArray, toHashSortedPairs, merge, mergeSkip, formatMapInline, assocMap, dissocMap, contains, toPairs, initEmptyTernaryTreeMap, sameMapShape, checkMapStructure, mapLen, mapEqual, toKeys, toPairsArray, mapMapValues, mapGetDefault, } from "./map.mjs";
|
5
5
|
export let runMapTests = () => {
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
6
|
+
describe("TernaryTreeMap Tests", () => {
|
7
|
+
test("should initialize map correctly", () => {
|
8
|
+
var dict = new Map();
|
9
|
+
var inList = [];
|
10
|
+
for (let idx = 0; idx < 10; idx++) {
|
11
|
+
dict.set(`${idx}`, idx + 10);
|
12
|
+
inList.push([`${idx}`, idx + 10]);
|
13
|
+
}
|
14
|
+
inList.sort((x, y) => {
|
15
|
+
let hx = hashGenerator(x[0]);
|
16
|
+
let hy = hashGenerator(y[0]);
|
17
|
+
return cmp(hx, hy);
|
18
|
+
});
|
19
|
+
let data10 = initTernaryTreeMap(dict);
|
20
|
+
let data11 = initTernaryTreeMapFromArray(inList);
|
21
|
+
check(checkMapStructure(data10));
|
22
|
+
check(checkMapStructure(data11));
|
23
|
+
justDisplay(formatMapInline(data10, true), " ((0:10 1:11 2:12) (3:13 (4:14 5:15 _) 6:16) (7:17 8:18 9:19))");
|
24
|
+
check(deepEqual(toHashSortedPairs(data10), inList));
|
25
|
+
check(deepEqual(toHashSortedPairs(data11), inList));
|
26
|
+
check(contains(data10, "1") === true);
|
27
|
+
check(contains(data10, "11") === false);
|
28
|
+
check(deepEqual(mapGetDefault(data10, "1", null), 11));
|
29
|
+
check(deepEqual(mapGetDefault(data10, "111", 0), 0));
|
30
|
+
let emptyData = new Map();
|
31
|
+
check(mapEqual(initEmptyTernaryTreeMap(), initTernaryTreeMap(emptyData)));
|
32
|
+
});
|
33
|
+
test("should handle assoc and contains correctly", () => {
|
34
|
+
var dict = new Map();
|
35
|
+
for (let idx = 0; idx < 100; idx++) {
|
36
|
+
dict.set(`${idx * 2}`, idx);
|
37
|
+
}
|
38
|
+
let data = initTernaryTreeMap(dict);
|
39
|
+
for (let idx = 0; idx < 100; idx++) {
|
40
|
+
dict.set(`${idx * 2 + 1}`, idx);
|
41
|
+
let data2 = assocMap(data, `${idx * 2 + 1}`, idx);
|
42
|
+
check(contains(data2, `${idx * 2 + 1}`));
|
43
|
+
}
|
44
|
+
var dict2 = new Map();
|
45
|
+
data = initTernaryTreeMap(dict2);
|
46
|
+
for (let idx = 0; idx < 1000; idx++) {
|
47
|
+
let p = 100 - idx / 10;
|
48
|
+
data = assocMap(data, `${p}`, idx);
|
49
|
+
check(contains(data, `${p}`));
|
50
|
+
}
|
51
|
+
});
|
52
|
+
test("should maintain structure integrity", () => {
|
53
|
+
var dict = new Map();
|
54
|
+
for (let idx = 0; idx < 100; idx++) {
|
55
|
+
dict.set(`${idx}`, idx + 10);
|
56
|
+
}
|
57
|
+
let data = initTernaryTreeMap(dict);
|
58
|
+
check(checkMapStructure(data));
|
59
|
+
});
|
60
|
+
test("should handle map association correctly", () => {
|
61
|
+
var dict = new Map();
|
62
|
+
for (let idx = 0; idx < 10; idx++) {
|
63
|
+
dict.set(`${idx}`, idx + 10);
|
64
|
+
}
|
65
|
+
let data = initTernaryTreeMap(dict);
|
66
|
+
check(contains(data, "1") === true);
|
67
|
+
check(contains(data, "12") === false);
|
68
|
+
check(checkMapStructure(data));
|
69
|
+
justDisplay(formatMapInline(assocMap(data, "1", 2222), true), "((0:10 1:2222 2:12) (3:13 (4:14 5:15 _) 6:16) (7:17 8:18 9:19))");
|
70
|
+
justDisplay(formatMapInline(assocMap(data, "23", 2222), true), "(((0:10 1:11 2:12) (3:13 (4:14 5:15 _) 6:16) (7:17 8:18 9:19)) 23:2222 _)");
|
71
|
+
});
|
72
|
+
test("should handle dissociation correctly", () => {
|
73
|
+
var dict = new Map();
|
74
|
+
for (let idx = 0; idx < 10; idx++) {
|
75
|
+
dict.set(`${idx}`, idx + 10);
|
76
|
+
}
|
77
|
+
let data = initTernaryTreeMap(dict);
|
78
|
+
check(checkMapStructure(data));
|
79
|
+
for (let idx = 0; idx < 10; idx++) {
|
80
|
+
let v = dissocMap(data, `${idx}`);
|
81
|
+
check(contains(v, `${idx}`) === false);
|
82
|
+
check(contains(data, `${idx}`) === true);
|
83
|
+
check(mapLen(v) === mapLen(data) - 1);
|
84
|
+
}
|
85
|
+
for (let idx = 10; idx < 12; idx++) {
|
86
|
+
let v = dissocMap(data, `${idx}`);
|
87
|
+
check(contains(v, `${idx}`) === false);
|
88
|
+
check(mapLen(v) === mapLen(data));
|
89
|
+
}
|
90
|
+
});
|
91
|
+
test("should convert to array correctly", () => {
|
92
|
+
var dict = new Map();
|
93
|
+
for (let idx = 0; idx < 10; idx++) {
|
94
|
+
dict.set(`${idx}`, idx + 10);
|
95
|
+
}
|
96
|
+
let data = initTernaryTreeMap(dict);
|
97
|
+
check(checkMapStructure(data));
|
98
|
+
justDisplay([...toKeys(data)], ["2", "3", "7", "9", "6", "5", "1", "8", "0", "4"]);
|
99
|
+
check(deepEqual(toPairsArray(data), [...toPairs(data)]));
|
100
|
+
});
|
101
|
+
test("should check equality correctly", () => {
|
102
|
+
var dict = new Map();
|
103
|
+
for (let idx = 0; idx < 10; idx++) {
|
104
|
+
dict.set(`${idx}`, idx + 10);
|
105
|
+
}
|
106
|
+
let data = initTernaryTreeMap(dict);
|
107
|
+
let b = dissocMap(data, "3");
|
108
|
+
check(checkMapStructure(data));
|
109
|
+
check(checkMapStructure(b));
|
110
|
+
check(mapEqual(data, data));
|
111
|
+
check(!mapEqual(data, b));
|
112
|
+
let c = assocMap(data, "3", 15);
|
113
|
+
check(sameMapShape(data, data));
|
114
|
+
check(sameMapShape(data, b) === false);
|
115
|
+
check(sameMapShape(data, c) === false);
|
116
|
+
let d = assocMap(c, "3", 13);
|
117
|
+
check(mapEqual(data, d));
|
118
|
+
check(data !== d); // not identical
|
119
|
+
});
|
120
|
+
test("should merge maps correctly", () => {
|
121
|
+
var dict = new Map();
|
122
|
+
var dictBoth = new Map();
|
123
|
+
for (let idx = 0; idx < 4; idx++) {
|
124
|
+
dict.set(`${idx}`, idx + 10);
|
125
|
+
dictBoth.set(`${idx}`, idx + 10);
|
126
|
+
}
|
127
|
+
let data = initTernaryTreeMap(dict);
|
128
|
+
check(checkMapStructure(data));
|
129
|
+
var dictB = new Map();
|
130
|
+
for (let idx = 10; idx < 14; idx++) {
|
131
|
+
dictB.set(`${idx}`, idx + 23);
|
132
|
+
dictBoth.set(`${idx}`, idx + 23);
|
133
|
+
}
|
134
|
+
let b = initTernaryTreeMap(dictB);
|
135
|
+
let merged = merge(data, b);
|
136
|
+
let both = initTernaryTreeMap(dictBoth);
|
137
|
+
check(mapEqual(merged, both));
|
138
|
+
});
|
139
|
+
test("should merge with skip correctly", () => {
|
140
|
+
var dict = new Map();
|
141
|
+
for (let idx = 0; idx < 4; idx++) {
|
142
|
+
dict.set(`${idx}`, idx + 10);
|
143
|
+
}
|
144
|
+
let a = initTernaryTreeMap(dict);
|
145
|
+
check(checkMapStructure(a));
|
146
|
+
var dict2 = new Map();
|
147
|
+
for (let idx = 0; idx < 4; idx++) {
|
148
|
+
dict2.set(`${idx}`, idx + 11);
|
149
|
+
}
|
150
|
+
let b = initTernaryTreeMap(dict2);
|
151
|
+
check(checkMapStructure(b));
|
152
|
+
let c = mergeSkip(a, b, 11);
|
153
|
+
check(deepEqual(mapGetDefault(c, "0", null), 10));
|
154
|
+
check(deepEqual(mapGetDefault(c, "1", null), 12));
|
155
|
+
check(deepEqual(mapGetDefault(c, "2", null), 13));
|
156
|
+
check(deepEqual(mapGetDefault(c, "3", null), 14));
|
157
|
+
});
|
158
|
+
test("should handle iteration correctly", () => {
|
159
|
+
var dict = new Map();
|
160
|
+
var dictBoth = new Map();
|
161
|
+
for (let idx = 0; idx < 4; idx++) {
|
162
|
+
dict.set(`${idx}`, idx + 10);
|
163
|
+
dictBoth.set(`${idx}`, idx + 10);
|
164
|
+
}
|
165
|
+
let data = initTernaryTreeMap(dict);
|
166
|
+
check(checkMapStructure(data));
|
167
|
+
var count = 0;
|
168
|
+
for (let [k, v] of toPairs(data)) {
|
169
|
+
count = count + 1;
|
170
|
+
}
|
171
|
+
check(count === 4);
|
172
|
+
count = 0;
|
173
|
+
for (let key of toPairs(data)) {
|
174
|
+
count = count + 1;
|
175
|
+
}
|
176
|
+
check(count === 4);
|
177
|
+
});
|
178
|
+
test("should iterate through large maps", () => {
|
179
|
+
var dict = new Map();
|
180
|
+
for (let idx = 0; idx < 100; idx++) {
|
181
|
+
dict.set(`${idx}`, idx + 10);
|
182
|
+
}
|
183
|
+
let data = initTernaryTreeMap(dict);
|
184
|
+
check(checkMapStructure(data));
|
185
|
+
var count = 0;
|
186
|
+
for (let [k, v] of toPairs(data)) {
|
187
|
+
count = count + 1;
|
188
|
+
}
|
189
|
+
check(count === 100);
|
190
|
+
});
|
191
|
+
test("should map values correctly", () => {
|
192
|
+
var dict = new Map();
|
193
|
+
for (let idx = 0; idx < 4; idx++) {
|
194
|
+
dict.set(`${idx}`, idx + 10);
|
195
|
+
}
|
196
|
+
let data = initTernaryTreeMap(dict);
|
197
|
+
var dict2 = new Map();
|
198
|
+
for (let idx = 0; idx < 4; idx++) {
|
199
|
+
dict2.set(`${idx}`, idx + 20);
|
200
|
+
}
|
201
|
+
let data2 = initTernaryTreeMap(dict2);
|
202
|
+
let data3 = mapMapValues(data, (x) => x + 10);
|
203
|
+
check(checkMapStructure(data3));
|
204
|
+
check(mapEqual(data2, data3));
|
205
|
+
check(formatMapInline(data2) === formatMapInline(data3));
|
18
206
|
});
|
19
|
-
let data10 = initTernaryTreeMap(dict);
|
20
|
-
let data11 = initTernaryTreeMapFromArray(inList);
|
21
|
-
checkMapStructure(data10);
|
22
|
-
checkMapStructure(data11);
|
23
|
-
// echo data10
|
24
|
-
justDisplay(formatMapInline(data10, true), " ((0:10 1:11 2:12) (3:13 (4:14 5:15 _) 6:16) (7:17 8:18 9:19))");
|
25
|
-
check(deepEqual(toHashSortedPairs(data10), inList));
|
26
|
-
check(deepEqual(toHashSortedPairs(data11), inList));
|
27
|
-
check(contains(data10, "1") === true);
|
28
|
-
check(contains(data10, "11") === false);
|
29
|
-
check(deepEqual(mapGetDefault(data10, "1", null), 11));
|
30
|
-
check(deepEqual(mapGetDefault(data10, "111", 0), 0));
|
31
|
-
// check(deepEqual(mapGetDefault(data10, "11", {} as any), null)); // should throws error
|
32
|
-
let emptyData = new Map();
|
33
|
-
check(mapEqual(initEmptyTernaryTreeMap(), initTernaryTreeMap(emptyData)));
|
34
|
-
});
|
35
|
-
test("assoc and contains", () => {
|
36
|
-
var dict = new Map();
|
37
|
-
for (let idx = 0; idx < 100; idx++) {
|
38
|
-
dict.set(`${idx * 2}`, idx);
|
39
|
-
}
|
40
|
-
let data = initTernaryTreeMap(dict);
|
41
|
-
for (let idx = 0; idx < 100; idx++) {
|
42
|
-
dict.set(`${idx * 2 + 1}`, idx);
|
43
|
-
let data2 = assocMap(data, `${idx * 2 + 1}`, idx);
|
44
|
-
check(contains(data2, `${idx * 2 + 1}`));
|
45
|
-
}
|
46
|
-
var dict = new Map();
|
47
|
-
data = initTernaryTreeMap(dict);
|
48
|
-
for (let idx = 0; idx < 1000; idx++) {
|
49
|
-
let p = 100 - idx / 10;
|
50
|
-
data = assocMap(data, `${p}`, idx);
|
51
|
-
check(contains(data, `${p}`));
|
52
|
-
}
|
53
|
-
});
|
54
|
-
test("check structure", () => {
|
55
|
-
var dict = new Map();
|
56
|
-
for (let idx = 0; idx < 100; idx++) {
|
57
|
-
dict.set(`${idx}`, idx + 10);
|
58
|
-
}
|
59
|
-
let data = initTernaryTreeMap(dict);
|
60
|
-
check(checkMapStructure(data));
|
61
|
-
});
|
62
|
-
test("assoc map", () => {
|
63
|
-
var dict = new Map();
|
64
|
-
for (let idx = 0; idx < 10; idx++) {
|
65
|
-
dict.set(`${idx}`, idx + 10);
|
66
|
-
}
|
67
|
-
let data = initTernaryTreeMap(dict);
|
68
|
-
// echo data.formatInline
|
69
|
-
check(contains(data, "1") === true);
|
70
|
-
check(contains(data, "12") === false);
|
71
|
-
checkMapStructure(data);
|
72
|
-
justDisplay(formatMapInline(assocMap(data, "1", 2222), true), "((0:10 1:2222 2:12) (3:13 (4:14 5:15 _) 6:16) (7:17 8:18 9:19))");
|
73
|
-
justDisplay(formatMapInline(assocMap(data, "23", 2222), true), "(((0:10 1:11 2:12) (3:13 (4:14 5:15 _) 6:16) (7:17 8:18 9:19)) 23:2222 _)");
|
74
|
-
});
|
75
|
-
test("dissoc", () => {
|
76
|
-
var dict = new Map();
|
77
|
-
for (let idx = 0; idx < 10; idx++) {
|
78
|
-
dict.set(`${idx}`, idx + 10);
|
79
|
-
}
|
80
|
-
let data = initTernaryTreeMap(dict);
|
81
|
-
checkMapStructure(data);
|
82
|
-
// echo data.formatInline
|
83
|
-
for (let idx = 0; idx < 10; idx++) {
|
84
|
-
let v = dissocMap(data, `${idx}`);
|
85
|
-
check(contains(v, `${idx}`) === false);
|
86
|
-
check(contains(data, `${idx}`) === true);
|
87
|
-
check(mapLen(v) === mapLen(data) - 1);
|
88
|
-
}
|
89
|
-
for (let idx = 10; idx < 12; idx++) {
|
90
|
-
let v = dissocMap(data, `${idx}`);
|
91
|
-
check(contains(v, `${idx}`) === false);
|
92
|
-
check(mapLen(v) === mapLen(data));
|
93
|
-
}
|
94
|
-
});
|
95
|
-
test("to array", () => {
|
96
|
-
var dict = new Map();
|
97
|
-
for (let idx = 0; idx < 10; idx++) {
|
98
|
-
dict.set(`${idx}`, idx + 10);
|
99
|
-
}
|
100
|
-
let data = initTernaryTreeMap(dict);
|
101
|
-
checkMapStructure(data);
|
102
|
-
// TODO
|
103
|
-
// justDisplay((mapToString(toPairs(data))) , "@[2:12, 3:13, 7:17, 9:19, 6:16, 5:15, 1:11, 8:18, 0:10, 4:14]")
|
104
|
-
justDisplay([...toKeys(data)], ["2", "3", "7", "9", "6", "5", "1", "8", "0", "4"]);
|
105
|
-
check(deepEqual(toPairsArray(data), [...toPairs(data)]));
|
106
|
-
});
|
107
|
-
test("Equality", () => {
|
108
|
-
var dict = new Map();
|
109
|
-
for (let idx = 0; idx < 10; idx++) {
|
110
|
-
dict.set(`${idx}`, idx + 10);
|
111
|
-
}
|
112
|
-
let data = initTernaryTreeMap(dict);
|
113
|
-
let b = dissocMap(data, "3");
|
114
|
-
checkMapStructure(data);
|
115
|
-
checkMapStructure(b);
|
116
|
-
check(mapEqual(data, data));
|
117
|
-
check(!mapEqual(data, b));
|
118
|
-
let c = assocMap(data, "3", 15);
|
119
|
-
check(sameMapShape(data, data));
|
120
|
-
check(sameMapShape(data, b) === false);
|
121
|
-
check(sameMapShape(data, c) === false);
|
122
|
-
let d = assocMap(c, "3", 13);
|
123
|
-
check(mapEqual(data, d));
|
124
|
-
check(data !== d); // not identical
|
125
|
-
});
|
126
|
-
test("Merge", () => {
|
127
|
-
var dict = new Map();
|
128
|
-
var dictBoth = new Map();
|
129
|
-
for (let idx = 0; idx < 4; idx++) {
|
130
|
-
dict.set(`${idx}`, idx + 10);
|
131
|
-
dictBoth.set(`${idx}`, idx + 10);
|
132
|
-
}
|
133
|
-
let data = initTernaryTreeMap(dict);
|
134
|
-
checkMapStructure(data);
|
135
|
-
var dictB = new Map();
|
136
|
-
for (let idx = 10; idx < 14; idx++) {
|
137
|
-
dictB.set(`${idx}`, idx + 23);
|
138
|
-
dictBoth.set(`${idx}`, idx + 23);
|
139
|
-
}
|
140
|
-
let b = initTernaryTreeMap(dictB);
|
141
|
-
let merged = merge(data, b);
|
142
|
-
let both = initTernaryTreeMap(dictBoth);
|
143
|
-
check(mapEqual(merged, both));
|
144
|
-
});
|
145
|
-
test("Merge skip", () => {
|
146
|
-
var dict = new Map();
|
147
|
-
for (let idx = 0; idx < 4; idx++) {
|
148
|
-
dict.set(`${idx}`, idx + 10);
|
149
|
-
}
|
150
|
-
let a = initTernaryTreeMap(dict);
|
151
|
-
checkMapStructure(a);
|
152
|
-
var dict2 = new Map();
|
153
|
-
for (let idx = 0; idx < 4; idx++) {
|
154
|
-
dict2.set(`${idx}`, idx + 11);
|
155
|
-
}
|
156
|
-
let b = initTernaryTreeMap(dict2);
|
157
|
-
checkMapStructure(b);
|
158
|
-
let c = mergeSkip(a, b, 11);
|
159
|
-
check(deepEqual(mapGetDefault(c, "0", null), 10));
|
160
|
-
check(deepEqual(mapGetDefault(c, "1", null), 12));
|
161
|
-
check(deepEqual(mapGetDefault(c, "2", null), 13));
|
162
|
-
check(deepEqual(mapGetDefault(c, "3", null), 14));
|
163
|
-
});
|
164
|
-
test("iterator", () => {
|
165
|
-
var dict = new Map();
|
166
|
-
var dictBoth = new Map();
|
167
|
-
for (let idx = 0; idx < 4; idx++) {
|
168
|
-
dict.set(`${idx}`, idx + 10);
|
169
|
-
dictBoth.set(`${idx}`, idx + 10);
|
170
|
-
}
|
171
|
-
let data = initTernaryTreeMap(dict);
|
172
|
-
checkMapStructure(data);
|
173
|
-
var i = 0;
|
174
|
-
for (let [k, v] of toPairs(data)) {
|
175
|
-
i = i + 1;
|
176
|
-
}
|
177
|
-
check(i === 4);
|
178
|
-
i = 0;
|
179
|
-
for (let key of toPairs(data)) {
|
180
|
-
i = i + 1;
|
181
|
-
}
|
182
|
-
check(i === 4);
|
183
|
-
});
|
184
|
-
test("each map", () => {
|
185
|
-
var dict = new Map();
|
186
|
-
for (let idx = 0; idx < 100; idx++) {
|
187
|
-
dict.set(`${idx}`, idx + 10);
|
188
|
-
}
|
189
|
-
let data = initTernaryTreeMap(dict);
|
190
|
-
checkMapStructure(data);
|
191
|
-
var i = 0;
|
192
|
-
for (let [k, v] of toPairs(data)) {
|
193
|
-
// echo "..{k}-{v}.."
|
194
|
-
i = i + 1;
|
195
|
-
}
|
196
|
-
check(i === 100);
|
197
|
-
});
|
198
|
-
test("map values", () => {
|
199
|
-
var dict = new Map();
|
200
|
-
for (let idx = 0; idx < 4; idx++) {
|
201
|
-
dict.set(`${idx}`, idx + 10);
|
202
|
-
}
|
203
|
-
let data = initTernaryTreeMap(dict);
|
204
|
-
var dict2 = new Map();
|
205
|
-
for (let idx = 0; idx < 4; idx++) {
|
206
|
-
dict2.set(`${idx}`, idx + 20);
|
207
|
-
}
|
208
|
-
let data2 = initTernaryTreeMap(dict2);
|
209
|
-
let data3 = mapMapValues(data, (x) => x + 10);
|
210
|
-
checkMapStructure(data3);
|
211
|
-
checkMapStructure(data3);
|
212
|
-
check(mapEqual(data2, data3));
|
213
|
-
check(formatMapInline(data2) === formatMapInline(data3));
|
214
207
|
});
|
215
208
|
};
|
package/lib/test-utils.d.mts
CHANGED
@@ -1,6 +1,10 @@
|
|
1
|
-
export declare
|
2
|
-
export declare
|
3
|
-
|
4
|
-
export declare
|
1
|
+
export declare function describe(suiteName: string, cb: () => void): void;
|
2
|
+
export declare function test(testName: string, cb: () => void): void;
|
3
|
+
export declare function check(condition: boolean, message?: string): void;
|
4
|
+
export declare function checkEqual<T>(actual: T, expected: T, message?: string): void;
|
5
|
+
export declare function checkDeepEqual<T>(actual: T, expected: T, message?: string): void;
|
6
|
+
export declare function checkThrows(fn: () => void, message?: string): void;
|
5
7
|
export declare function arrayEqual<T>(xs: Array<T>, ys: Array<T>): boolean;
|
6
|
-
export declare
|
8
|
+
export declare function checkArrayEqual<T>(actual: Array<T>, expected: Array<T>, message?: string): void;
|
9
|
+
export declare function justDisplay(x: any, y: any): void;
|
10
|
+
export declare function printTestSummary(): void;
|
package/lib/test-utils.mjs
CHANGED
@@ -1,23 +1,87 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
const stats = { total: 0, passed: 0, failed: 0, suites: 0 };
|
2
|
+
const suites = [];
|
3
|
+
let currentSuite = null;
|
4
|
+
const colors = {
|
5
|
+
reset: "\x1b[0m",
|
6
|
+
bright: "\x1b[1m",
|
7
|
+
red: "\x1b[31m",
|
8
|
+
green: "\x1b[32m",
|
9
|
+
yellow: "\x1b[33m",
|
10
|
+
blue: "\x1b[34m",
|
11
|
+
magenta: "\x1b[35m",
|
12
|
+
cyan: "\x1b[36m",
|
13
|
+
};
|
14
|
+
export function describe(suiteName, cb) {
|
15
|
+
const target = process === null || process === void 0 ? void 0 : process.env["target"];
|
16
|
+
if (target != null && !suiteName.includes(target)) {
|
17
|
+
return;
|
18
|
+
}
|
19
|
+
console.log(`\n${colors.cyan}${colors.bright}○ ${suiteName}${colors.reset}`);
|
20
|
+
const suite = { name: suiteName, tests: [] };
|
21
|
+
suites.push(suite);
|
22
|
+
currentSuite = suite;
|
23
|
+
stats.suites++;
|
24
|
+
try {
|
5
25
|
cb();
|
6
26
|
}
|
7
|
-
|
8
|
-
|
9
|
-
if (!x) {
|
10
|
-
throw new Error("Test failed");
|
27
|
+
catch (error) {
|
28
|
+
console.log(`${colors.red}Suite "${suiteName}" failed to execute: ${error}${colors.reset}`);
|
11
29
|
}
|
12
|
-
|
13
|
-
|
14
|
-
export
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
throw new Error("Test failed");
|
30
|
+
currentSuite = null;
|
31
|
+
}
|
32
|
+
export function test(testName, cb) {
|
33
|
+
const target = process === null || process === void 0 ? void 0 : process.env["target"];
|
34
|
+
if (target != null && !testName.includes(target)) {
|
35
|
+
return;
|
19
36
|
}
|
20
|
-
};
|
37
|
+
const testCase = { name: testName, passed: false };
|
38
|
+
if (currentSuite) {
|
39
|
+
currentSuite.tests.push(testCase);
|
40
|
+
}
|
41
|
+
stats.total++;
|
42
|
+
const startTime = Date.now();
|
43
|
+
try {
|
44
|
+
cb();
|
45
|
+
testCase.passed = true;
|
46
|
+
testCase.duration = Date.now() - startTime;
|
47
|
+
stats.passed++;
|
48
|
+
console.log(` ${colors.green}✓${colors.reset} ${testName} ${colors.cyan}(${testCase.duration}ms)${colors.reset}`);
|
49
|
+
}
|
50
|
+
catch (error) {
|
51
|
+
testCase.passed = false;
|
52
|
+
testCase.error = error;
|
53
|
+
testCase.duration = Date.now() - startTime;
|
54
|
+
stats.failed++;
|
55
|
+
console.log(` ${colors.red}✗${colors.reset} ${testName} ${colors.cyan}(${testCase.duration}ms)${colors.reset}`);
|
56
|
+
console.log(` ${colors.red}${error.message}${colors.reset}`);
|
57
|
+
}
|
58
|
+
}
|
59
|
+
export function check(condition, message) {
|
60
|
+
if (!condition) {
|
61
|
+
throw new Error(message || "Assertion failed");
|
62
|
+
}
|
63
|
+
}
|
64
|
+
export function checkEqual(actual, expected, message) {
|
65
|
+
if (actual !== expected) {
|
66
|
+
const errorMessage = message || `Expected ${expected}, but got ${actual}`;
|
67
|
+
throw new Error(errorMessage);
|
68
|
+
}
|
69
|
+
}
|
70
|
+
export function checkDeepEqual(actual, expected, message) {
|
71
|
+
if (!deepEqual(actual, expected)) {
|
72
|
+
const errorMessage = message || `Deep equality check failed:\nActual: ${JSON.stringify(actual)}\nExpected: ${JSON.stringify(expected)}`;
|
73
|
+
throw new Error(errorMessage);
|
74
|
+
}
|
75
|
+
}
|
76
|
+
export function checkThrows(fn, message) {
|
77
|
+
try {
|
78
|
+
fn();
|
79
|
+
throw new Error(message || "Expected function to throw, but it didn't");
|
80
|
+
}
|
81
|
+
catch (error) {
|
82
|
+
// Success - function threw as expected
|
83
|
+
}
|
84
|
+
}
|
21
85
|
export function arrayEqual(xs, ys) {
|
22
86
|
if (xs.length != ys.length) {
|
23
87
|
return false;
|
@@ -29,9 +93,58 @@ export function arrayEqual(xs, ys) {
|
|
29
93
|
}
|
30
94
|
return true;
|
31
95
|
}
|
32
|
-
export
|
96
|
+
export function checkArrayEqual(actual, expected, message) {
|
97
|
+
if (!arrayEqual(actual, expected)) {
|
98
|
+
const errorMessage = message || `Arrays are not equal:\nActual: [${actual.join(", ")}]\nExpected: [${expected.join(", ")}]`;
|
99
|
+
throw new Error(errorMessage);
|
100
|
+
}
|
101
|
+
}
|
102
|
+
export function justDisplay(x, y) {
|
33
103
|
console.group("Compare:");
|
34
104
|
console.log(x);
|
35
105
|
console.log(y);
|
36
106
|
console.groupEnd();
|
37
|
-
}
|
107
|
+
}
|
108
|
+
function deepEqual(a, b) {
|
109
|
+
if (a === b)
|
110
|
+
return true;
|
111
|
+
if (a == null || b == null)
|
112
|
+
return false;
|
113
|
+
if (typeof a !== typeof b)
|
114
|
+
return false;
|
115
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
116
|
+
if (a.length !== b.length)
|
117
|
+
return false;
|
118
|
+
for (let i = 0; i < a.length; i++) {
|
119
|
+
if (!deepEqual(a[i], b[i]))
|
120
|
+
return false;
|
121
|
+
}
|
122
|
+
return true;
|
123
|
+
}
|
124
|
+
if (typeof a === "object" && typeof b === "object") {
|
125
|
+
const keysA = Object.keys(a);
|
126
|
+
const keysB = Object.keys(b);
|
127
|
+
if (keysA.length !== keysB.length)
|
128
|
+
return false;
|
129
|
+
for (const key of keysA) {
|
130
|
+
if (!keysB.includes(key) || !deepEqual(a[key], b[key]))
|
131
|
+
return false;
|
132
|
+
}
|
133
|
+
return true;
|
134
|
+
}
|
135
|
+
return false;
|
136
|
+
}
|
137
|
+
export function printTestSummary() {
|
138
|
+
console.log(`\n${colors.bright}Test Summary:${colors.reset}`);
|
139
|
+
console.log(`${colors.cyan}Suites: ${stats.suites}${colors.reset}`);
|
140
|
+
console.log(`${colors.cyan}Tests: ${stats.total}${colors.reset}`);
|
141
|
+
console.log(`${colors.green}Passed: ${stats.passed}${colors.reset}`);
|
142
|
+
if (stats.failed > 0) {
|
143
|
+
console.log(`${colors.red}Failed: ${stats.failed}${colors.reset}`);
|
144
|
+
console.log(`\n${colors.red}${colors.bright}❌ ${stats.failed} test(s) failed${colors.reset}`);
|
145
|
+
process.exit(1);
|
146
|
+
}
|
147
|
+
else {
|
148
|
+
console.log(`\n${colors.green}${colors.bright}✅ All tests passed!${colors.reset}`);
|
149
|
+
}
|
150
|
+
}
|
@@ -4,6 +4,9 @@ import "./test-map.mjs";
|
|
4
4
|
import { runListTests } from "./test-list.mjs";
|
5
5
|
import { runMapTests } from "./test-map.mjs";
|
6
6
|
import { mergeValueHash, overwriteHashGenerator, valueHash } from "./types.mjs";
|
7
|
+
import { printTestSummary } from "./test-utils.mjs";
|
8
|
+
// import { disableListStructureCheck } from "./list.mjs";
|
9
|
+
// disableListStructureCheck();
|
7
10
|
overwriteComparator((x, y) => {
|
8
11
|
// console.log("comparing", x, y);
|
9
12
|
return deepEqual(x, y);
|
@@ -13,5 +16,7 @@ overwriteHashGenerator((x) => {
|
|
13
16
|
// console.log("hashing", x, ret);
|
14
17
|
return ret;
|
15
18
|
});
|
19
|
+
console.log("🧪 Running TernaryTree Tests...\n");
|
16
20
|
runListTests();
|
17
21
|
runMapTests();
|
22
|
+
printTestSummary();
|
package/package.json
CHANGED
@@ -1,11 +1,19 @@
|
|
1
1
|
{
|
2
2
|
"name": "@calcit/ternary-tree",
|
3
|
-
"version": "0.0.
|
3
|
+
"version": "0.0.25",
|
4
4
|
"main": "./lib/index.mjs",
|
5
|
-
"scripts": {
|
5
|
+
"scripts": {
|
6
|
+
"build": "tsc",
|
7
|
+
"test": "yarn build && node lib/test.mjs",
|
8
|
+
"test:watch": "yarn build && node lib/test.mjs",
|
9
|
+
"test:list": "TARGET=list yarn test",
|
10
|
+
"test:map": "TARGET=map yarn test",
|
11
|
+
"test:list-perf": "yarn build && node lib/test-list-perf.mjs",
|
12
|
+
"test:list-detailed-perf": "yarn build && node lib/test-list-detailed-perf.mjs"
|
13
|
+
},
|
6
14
|
"devDependencies": {
|
7
|
-
"@types/node": "^20.
|
8
|
-
"prettier": "^3.
|
9
|
-
"typescript": "^5.
|
15
|
+
"@types/node": "^20.12.5",
|
16
|
+
"prettier": "^3.2.5",
|
17
|
+
"typescript": "^5.4.4"
|
10
18
|
}
|
11
19
|
}
|
File without changes
|