1 | (function() {
|
2 |
|
3 | var CND, CODEC, alert, badge, debug, echo, help, info, jr, log, rpr, test, urge, warn, whisper, ƒ;
|
4 |
|
5 | CND = require('cnd');
|
6 |
|
7 | rpr = CND.rpr;
|
8 |
|
9 | badge = 'HOLLERITH-CODEC/tests';
|
10 |
|
11 | log = CND.get_logger('plain', badge);
|
12 |
|
13 | info = CND.get_logger('info', badge);
|
14 |
|
15 | whisper = CND.get_logger('whisper', badge);
|
16 |
|
17 | alert = CND.get_logger('alert', badge);
|
18 |
|
19 | debug = CND.get_logger('debug', badge);
|
20 |
|
21 | warn = CND.get_logger('warn', badge);
|
22 |
|
23 | help = CND.get_logger('help', badge);
|
24 |
|
25 | urge = CND.get_logger('urge', badge);
|
26 |
|
27 | echo = CND.echo.bind(CND);
|
28 |
|
29 |
|
30 | test = require('guy-test');
|
31 |
|
32 | CODEC = require('./main');
|
33 |
|
34 | ƒ = CND.format_number;
|
35 |
|
36 | ({jr} = CND);
|
37 |
|
38 |
|
39 | this["codec encodes and decodes numbers"] = function(T) {
|
40 | var key, key_bfr;
|
41 | key = ['foo', 1234, 5678];
|
42 | key_bfr = CODEC.encode(key);
|
43 | T.eq(key, CODEC.decode(key_bfr));
|
44 | return whisper(`key length: ${key_bfr.length}`);
|
45 | };
|
46 |
|
47 |
|
48 | this["codec encodes and decodes dates"] = function(T) {
|
49 | var key, key_bfr;
|
50 | key = ['foo', new Date(), 5678];
|
51 | key_bfr = CODEC.encode(key);
|
52 | T.eq(key, CODEC.decode(key_bfr));
|
53 | return whisper(`key length: ${key_bfr.length}`);
|
54 | };
|
55 |
|
56 |
|
57 | this["codec accepts long numbers"] = function(T) {
|
58 | var i, key, key_bfr;
|
59 | key = [
|
60 | 'foo',
|
61 | (function() {
|
62 | var j,
|
63 | results1;
|
64 | results1 = [];
|
65 | for (i = j = 0; j <= 1000; i = ++j) {
|
66 | results1.push(i);
|
67 | }
|
68 | return results1;
|
69 | })(),
|
70 | 'bar'
|
71 | ];
|
72 | key_bfr = CODEC.encode(key);
|
73 | T.eq(key, CODEC.decode(key_bfr));
|
74 | return whisper(`key length: ${key_bfr.length}`);
|
75 | };
|
76 |
|
77 |
|
78 | this["codec accepts long texts"] = function(T) {
|
79 | var key, key_bfr, long_text;
|
80 | long_text = (new Array(1e4)).join('#');
|
81 | key = ['foo', [long_text, long_text, long_text, long_text], 42];
|
82 | key_bfr = CODEC.encode(key);
|
83 | T.eq(key, CODEC.decode(key_bfr));
|
84 | return whisper(`key length: ${key_bfr.length}`);
|
85 | };
|
86 |
|
87 |
|
88 | this["codec preserves critical escaped characters (roundtrip) (1)"] = function(T) {
|
89 | var key, key_bfr, text;
|
90 | text = 'abc\x00\x00\x00\x00def';
|
91 | key = ['xxx', [text], 0];
|
92 | key_bfr = CODEC.encode(key);
|
93 | return T.eq(key, CODEC.decode(key_bfr));
|
94 | };
|
95 |
|
96 |
|
97 | this["codec preserves critical escaped characters (roundtrip) (2)"] = function(T) {
|
98 | var key, key_bfr, text;
|
99 | text = 'abc\x01\x01\x01\x01def';
|
100 | key = ['xxx', [text], 0];
|
101 | key_bfr = CODEC.encode(key);
|
102 | return T.eq(key, CODEC.decode(key_bfr));
|
103 | };
|
104 |
|
105 |
|
106 | this["codec preserves critical escaped characters (roundtrip) (3)"] = function(T) {
|
107 | var key, key_bfr, text;
|
108 | text = 'abc\x00\x01\x00\x01def';
|
109 | key = ['xxx', [text], 0];
|
110 | key_bfr = CODEC.encode(key);
|
111 | return T.eq(key, CODEC.decode(key_bfr));
|
112 | };
|
113 |
|
114 |
|
115 | this["codec preserves critical escaped characters (roundtrip) (4)"] = function(T) {
|
116 | var key, key_bfr, text;
|
117 | text = 'abc\x01\x00\x01\x00def';
|
118 | key = ['xxx', [text], 0];
|
119 | key_bfr = CODEC.encode(key);
|
120 | return T.eq(key, CODEC.decode(key_bfr));
|
121 | };
|
122 |
|
123 |
|
124 | this["codec accepts private type (1)"] = function(T) {
|
125 | var key, key_bfr;
|
126 | key = [
|
127 | {
|
128 | type: 'price',
|
129 | value: 'abc'
|
130 | }
|
131 | ];
|
132 | key_bfr = CODEC.encode(key);
|
133 | return T.eq(key, CODEC.decode(key_bfr));
|
134 | };
|
135 |
|
136 |
|
137 | this["codec accepts private type (2)"] = function(T) {
|
138 | var key, key_bfr;
|
139 | key = [
|
140 | 123,
|
141 | 456,
|
142 | {
|
143 | type: 'price',
|
144 | value: 'abc'
|
145 | },
|
146 | 'xxx'
|
147 | ];
|
148 | key_bfr = CODEC.encode(key);
|
149 | return T.eq(key, CODEC.decode(key_bfr));
|
150 | };
|
151 |
|
152 |
|
153 | this["codec decodes private type with custom decoder (1)"] = function(T) {
|
154 | var decoded_key, encoded_value, key, key_bfr, matcher, value;
|
155 | value = '/etc/cron.d/anacron';
|
156 | matcher = [value];
|
157 | encoded_value = value.split('/');
|
158 | key = [
|
159 | {
|
160 | type: 'route',
|
161 | value: encoded_value
|
162 | }
|
163 | ];
|
164 | key_bfr = CODEC.encode(key);
|
165 |
|
166 | decoded_key = CODEC.decode(key_bfr, function(type, value) {
|
167 | if (type === 'route') {
|
168 | return value.join('/');
|
169 | }
|
170 | throw new Error(`unknown private type ${rpr(type)}`);
|
171 | });
|
172 |
|
173 |
|
174 |
|
175 |
|
176 | return T.eq(matcher, decoded_key);
|
177 | };
|
178 |
|
179 |
|
180 | this._sets_are_equal = function(a, b) {
|
181 | var a_done, a_keys, a_value, b_done, b_keys, b_value;
|
182 | if (!((CODEC.types.isa.set(a)) && (CODEC.types.isa.set(b)))) {
|
183 |
|
184 | return false;
|
185 | }
|
186 | if (a.size !== b.size) {
|
187 | return false;
|
188 | }
|
189 | a_keys = a.keys();
|
190 | b_keys = b.keys();
|
191 | while (true) {
|
192 | ({
|
193 | value: a_value,
|
194 | done: a_done
|
195 | } = a_keys.next());
|
196 | ({
|
197 | value: b_value,
|
198 | done: b_done
|
199 | } = b_keys.next());
|
200 | if (a_done || b_done) {
|
201 | break;
|
202 | }
|
203 | if (!CODEC.types.equals(a_value, b_value)) {
|
204 | return false;
|
205 | }
|
206 | }
|
207 | return true;
|
208 | };
|
209 |
|
210 |
|
211 | this["codec decodes private type with custom decoder (2)"] = function(T) {
|
212 | var decoded_key, encoded_value, key, key_bfr, matcher, value;
|
213 | value = new Set('qwert');
|
214 | matcher = [value];
|
215 | encoded_value = Array.from(value);
|
216 | key = [
|
217 | {
|
218 | type: 'set',
|
219 | value: encoded_value
|
220 | }
|
221 | ];
|
222 | key_bfr = CODEC.encode(key);
|
223 |
|
224 | decoded_key = CODEC.decode(key_bfr, function(type, value) {
|
225 | if (type === 'set') {
|
226 | return new Set(value);
|
227 | }
|
228 | throw new Error(`unknown private type ${rpr(type)}`);
|
229 | });
|
230 |
|
231 |
|
232 |
|
233 |
|
234 |
|
235 | return T.ok(this._sets_are_equal(matcher[0], decoded_key[0]));
|
236 | };
|
237 |
|
238 |
|
239 | this["Support for Sets"] = function(T) {
|
240 | var decoded_key, key, key_bfr, matcher;
|
241 | key = [new Set('qwert')];
|
242 | matcher = [new Set('qwert')];
|
243 | key_bfr = CODEC.encode(key);
|
244 | decoded_key = CODEC.decode(key_bfr);
|
245 |
|
246 |
|
247 |
|
248 |
|
249 | return T.ok(this._sets_are_equal(matcher[0], decoded_key[0]));
|
250 | };
|
251 |
|
252 |
|
253 | this["codec decodes private type with custom encoder and decoder (3)"] = function(T) {
|
254 | var decoded_key_1, decoded_key_2, decoder, encoder, key, key_bfr, matcher_1, matcher_2, parts, route;
|
255 | route = '/usr/local/lib/node_modules/coffee-script/README.md';
|
256 | parts = route.split('/');
|
257 | key = [
|
258 | {
|
259 | type: 'route',
|
260 | value: route
|
261 | }
|
262 | ];
|
263 | matcher_1 = [
|
264 | {
|
265 | type: 'route',
|
266 | value: parts
|
267 | }
|
268 | ];
|
269 | matcher_2 = [route];
|
270 |
|
271 | encoder = function(type, value) {
|
272 | if (type === 'route') {
|
273 | return value.split('/');
|
274 | }
|
275 | throw new Error(`unknown private type ${rpr(type)}`);
|
276 | };
|
277 |
|
278 | decoder = function(type, value) {
|
279 | if (type === 'route') {
|
280 | return value.join('/');
|
281 | }
|
282 | throw new Error(`unknown private type ${rpr(type)}`);
|
283 | };
|
284 |
|
285 | key_bfr = CODEC.encode(key, encoder);
|
286 |
|
287 | decoded_key_1 = CODEC.decode(key_bfr);
|
288 | T.eq(matcher_1, decoded_key_1);
|
289 | decoded_key_2 = CODEC.decode(key_bfr, decoder);
|
290 | return T.eq(matcher_2, decoded_key_2);
|
291 | };
|
292 |
|
293 |
|
294 | this["private type takes default shape when handler returns use_fallback"] = function(T) {
|
295 | var decoded_key, key, key_bfr, matcher;
|
296 | matcher = [
|
297 | 84,
|
298 | {
|
299 | type: 'bar',
|
300 | value: 108
|
301 | }
|
302 | ];
|
303 | key = [
|
304 | {
|
305 | type: 'foo',
|
306 | value: 42
|
307 | },
|
308 | {
|
309 | type: 'bar',
|
310 | value: 108
|
311 | }
|
312 | ];
|
313 | key_bfr = CODEC.encode(key);
|
314 |
|
315 | decoded_key = CODEC.decode(key_bfr, function(type, value, use_fallback) {
|
316 | if (type === 'foo') {
|
317 | return value * 2;
|
318 | }
|
319 | return use_fallback;
|
320 | });
|
321 |
|
322 | return T.eq(matcher, decoded_key);
|
323 | };
|
324 |
|
325 |
|
326 | this["test: flat file DB storage (1)"] = function(T) {
|
327 | var buffer_as_text, j, len, probe, probes;
|
328 | probes = [['foo', -2e308], ['foo', -1e12], ['foo', -3], ['foo', -2], ['foo', -1], ['foo', 1], ['foo', 2], ['foo', 3], ['foo', 1e12], ['foo', 2e308], ['bar', 'blah'], ['bar', 'gnu'], ['a'], ['b'], ['c'], ['A'], ['箲'], ['筅'], ['𥬗'], ['B'], ['C'], ['0'], ['1'], ['2'], ['Number', Number.EPSILON, 'EPSILON'], ['Number', Number.MAX_SAFE_INTEGER, 'MAX_SAFE_INTEGER'], ['Number', Number.MAX_VALUE, 'MAX_VALUE'], ['Number', 0, 'ZERO'], ['Number', Number.MIN_SAFE_INTEGER, 'MIN_SAFE_INTEGER'], ['Number', Number.MIN_VALUE, 'MIN_VALUE']];
|
329 | buffer_as_text = function(buffer) {
|
330 | var R, idx, j, ref;
|
331 | R = [];
|
332 | for (idx = j = 0, ref = buffer.length; (0 <= ref ? j < ref : j > ref); idx = 0 <= ref ? ++j : --j) {
|
333 | R.push(String.fromCodePoint(0x2800 + buffer[idx]));
|
334 | }
|
335 |
|
336 |
|
337 | return R.join('');
|
338 | };
|
339 | probes = (function() {
|
340 | var j, len, results1;
|
341 | results1 = [];
|
342 | for (j = 0, len = probes.length; j < len; j++) {
|
343 | probe = probes[j];
|
344 | results1.push([buffer_as_text(CODEC.encode(probe)), JSON.stringify(probe)]);
|
345 | }
|
346 | return results1;
|
347 | })();
|
348 | probes.sort(function(a, b) {
|
349 | if (a[0] < b[0]) {
|
350 | return -1;
|
351 | }
|
352 | if (a[0] > b[0]) {
|
353 | return +1;
|
354 | }
|
355 | return 0;
|
356 | });
|
357 | for (j = 0, len = probes.length; j < len; j++) {
|
358 | probe = probes[j];
|
359 | urge(probe.join(' - '));
|
360 | }
|
361 |
|
362 |
|
363 |
|
364 |
|
365 | urge("use `( export LC_ALL=C && sort hollerith-codec-flatfile-db.txt ) | less -SRN`");
|
366 | urge("to sort a file with these lines");
|
367 | return null;
|
368 | };
|
369 |
|
370 |
|
371 | this["test: flat file DB storage (2)"] = function(T) {
|
372 | var j, len, matcher, probe, probes_and_matchers, result, settings, stringify;
|
373 | probes_and_matchers = [[["foo", -1000000000000], "⡔⡦⡯⡯⠀⡋⢽⢒⣥⡫⡝⣿⣿⣿![\"foo\",-1000000000000]"], [["foo", -3], "⡔⡦⡯⡯⠀⡋⢿⣷⣿⣿⣿⣿⣿⣿![\"foo\",-3]"], [["foo", -2], "⡔⡦⡯⡯⠀⡋⢿⣿⣿⣿⣿⣿⣿⣿![\"foo\",-2]"], [["foo", -1], "⡔⡦⡯⡯⠀⡋⣀⠏⣿⣿⣿⣿⣿⣿![\"foo\",-1]"], [["foo", 1], "⡔⡦⡯⡯⠀⡍⠿⣰⠀⠀⠀⠀⠀⠀![\"foo\",1]"], [["foo", 2], "⡔⡦⡯⡯⠀⡍⡀⠀⠀⠀⠀⠀⠀⠀![\"foo\",2]"], [["foo", 3], "⡔⡦⡯⡯⠀⡍⡀⠈⠀⠀⠀⠀⠀⠀![\"foo\",3]"], [["foo", 1000000000000], "⡔⡦⡯⡯⠀⡍⡂⡭⠚⢔⢢⠀⠀⠀![\"foo\",1000000000000]"], [["bar", "blah"], "⡔⡢⡡⡲⠀⡔⡢⡬⡡⡨⠀![\"bar\",\"blah\"]"], [["bar", "gnu"], "⡔⡢⡡⡲⠀⡔⡧⡮⡵⠀![\"bar\",\"gnu\"]"], [["a"], "⡔⡡⠀![\"a\"]"], [["b"], "⡔⡢⠀![\"b\"]"], [["c"], "⡔⡣⠀![\"c\"]"], [["A"], "⡔⡁⠀![\"A\"]"], [["箲"], "⡔⣧⢮⢲⠀![\"箲\"]"], [["筅"], "⡔⣧⢭⢅⠀![\"筅\"]"], [["𥬗"], "⡔⣰⢥⢬⢗⠀![\"𥬗\"]"], [["B"], "⡔⡂⠀![\"B\"]"], [["C"], "⡔⡃⠀![\"C\"]"], [["0"], "⡔⠰⠀![\"0\"]"], [["1"], "⡔⠱⠀![\"1\"]"], [["2"], "⡔⠲⠀![\"2\"]"], [["Number", 2.220446049250313e-16, "EPSILON"], "⡔⡎⡵⡭⡢⡥⡲⠀⡍⠼⢰⠀⠀⠀⠀⠀⠀⡔⡅⡐⡓⡉⡌⡏⡎⠀![\"Number\",2.220446049250313e-16,\"EPSILON\"]"], [["Number", 9007199254740991, "MAX_SAFE_INTEGER"], "⡔⡎⡵⡭⡢⡥⡲⠀⡍⡃⠿⣿⣿⣿⣿⣿⣿⡔⡍⡁⡘⡟⡓⡁⡆⡅⡟⡉⡎⡔⡅⡇⡅⡒⠀![\"Number\",9007199254740991,\"MAX_SAFE_INTEGER\"]"], [["Number", 1.7976931348623157e+308, "MAX_VALUE"], "⡔⡎⡵⡭⡢⡥⡲⠀⡍⡿⣯⣿⣿⣿⣿⣿⣿⡔⡍⡁⡘⡟⡖⡁⡌⡕⡅⠀![\"Number\",1.7976931348623157e+308,\"MAX_VALUE\"]"], [["Number", 0, "ZERO"], "⡔⡎⡵⡭⡢⡥⡲⠀⡍⠀⠀⠀⠀⠀⠀⠀⠀⡔⡚⡅⡒⡏⠀![\"Number\",0,\"ZERO\"]"], [["Number", -9007199254740991, "MIN_SAFE_INTEGER"], "⡔⡎⡵⡭⡢⡥⡲⠀⡋⢼⣀⠀⠀⠀⠀⠀⠀⡔⡍⡉⡎⡟⡓⡁⡆⡅⡟⡉⡎⡔⡅⡇⡅⡒⠀![\"Number\",-9007199254740991,\"MIN_SAFE_INTEGER\"]"], [["Number", 5e-324, "MIN_VALUE"], "⡔⡎⡵⡭⡢⡥⡲⠀⡍⠀⠀⠀⠀⠀⠀⠀⠁⡔⡍⡉⡎⡟⡖⡁⡌⡕⡅⠀![\"Number\",5e-324,\"MIN_VALUE\"]"]];
|
374 |
|
375 | stringify = jr;
|
376 |
|
377 |
|
378 |
|
379 |
|
380 |
|
381 |
|
382 | settings = {
|
383 | stringify,
|
384 | joiner: '!'
|
385 | };
|
386 | for (j = 0, len = probes_and_matchers.length; j < len; j++) {
|
387 | [probe, matcher] = probes_and_matchers[j];
|
388 | result = CODEC.as_sortline(probe, settings);
|
389 | debug('33392', stringify([probe, result]));
|
390 | T.eq(result, matcher);
|
391 | }
|
392 | return null;
|
393 | };
|
394 |
|
395 |
|
396 | this["test: flat file DB storage (3)"] = function(T) {
|
397 | var j, len, matcher, probe, probes_and_matchers, result, settings, stringify;
|
398 | stringify = function(x) {
|
399 | return (require('util')).inspect(x, {
|
400 | maxArrayLength: null,
|
401 | breakLength: 2e308
|
402 | });
|
403 | };
|
404 | probes_and_matchers = [
|
405 | [
|
406 | ['foo',
|
407 | 1234],
|
408 | {
|
409 | bare: false,
|
410 | joiner: ',',
|
411 | base: 19968
|
412 | },
|
413 | '乔书乯乯一乍乀亓么一一一一一,["foo",1234]'
|
414 | ],
|
415 | [
|
416 | ['foo',
|
417 | 1234],
|
418 | {
|
419 | bare: true,
|
420 | joiner: ',',
|
421 | base: null
|
422 | },
|
423 | '⡔⡦⡯⡯⠀⡍⡀⢓⡈⠀⠀⠀⠀⠀'
|
424 | ]
|
425 | ];
|
426 | for (j = 0, len = probes_and_matchers.length; j < len; j++) {
|
427 | [probe, settings, matcher] = probes_and_matchers[j];
|
428 | result = CODEC.as_sortline(probe, settings);
|
429 | debug('33392', stringify([probe, settings, result]));
|
430 | T.eq(result, matcher);
|
431 | }
|
432 |
|
433 | return null;
|
434 | };
|
435 |
|
436 |
|
437 |
|
438 |
|
439 |
|
440 |
|
441 |
|
442 |
|
443 |
|
444 |
|
445 |
|
446 |
|
447 |
|
448 | this["test: ordering where negatives precede void"] = function(T) {
|
449 | var buffer_as_text, encode, j, jrx, len, probe, probes, result, results;
|
450 | probes = [[-10], [10], [10, 0], [10, -1], [10, -2], [10, 1], [10, 2], [10, 4], [10, 4, 0], [10, 4, -1], [10, 4, -2], [10, 4, 1], [10, 4, 2], [10, 0, 3], [10, -1, 3], [10, -2, 3], [10, 1, 3], [10, 2, 3], [], [0], [-1], [1], [1, 0], [1, -1], [1, 1]];
|
451 | buffer_as_text = function(buffer) {
|
452 | return buffer.toString('hex');
|
453 | };
|
454 | jrx = function(x) {
|
455 | return (JSON.stringify(x)).padEnd(15);
|
456 | };
|
457 | encode = function(x) {
|
458 | return buffer_as_text(CODEC.encode(x));
|
459 | };
|
460 | results = (function() {
|
461 | var j, len, results1;
|
462 | results1 = [];
|
463 | for (j = 0, len = probes.length; j < len; j++) {
|
464 | probe = probes[j];
|
465 | results1.push([jrx(probe), probe, encode(probe)]);
|
466 | }
|
467 | return results1;
|
468 | })();
|
469 | results.sort(function(a, b) {
|
470 | if (a[2] < b[2]) {
|
471 | return -1;
|
472 | }
|
473 | if (a[2] > b[2]) {
|
474 | return +1;
|
475 | }
|
476 | return 0;
|
477 | });
|
478 | for (j = 0, len = results.length; j < len; j++) {
|
479 | result = results[j];
|
480 | urge(result[0] + ' ... ' + result[2]);
|
481 | }
|
482 | results = (function() {
|
483 | var k, len1, results1;
|
484 | results1 = [];
|
485 | for (k = 0, len1 = results.length; k < len1; k++) {
|
486 | result = results[k];
|
487 | results1.push(result[1]);
|
488 | }
|
489 | return results1;
|
490 | })();
|
491 | T.eq(results, [[-10], [-1], [], [0], [1, -1], [1], [1, 0], [1, 1], [10, -2], [10, -2, 3], [10, -1], [10, -1, 3], [10], [10, 0], [10, 0, 3], [10, 1], [10, 1, 3], [10, 2], [10, 2, 3], [10, 4, -2], [10, 4, -1], [10, 4], [10, 4, 0], [10, 4, 1], [10, 4, 2]]);
|
492 | return null;
|
493 | };
|
494 |
|
495 |
|
496 | if (module.parent == null) {
|
497 | test(this);
|
498 | }
|
499 |
|
500 |
|
501 |
|
502 |
|
503 |
|
504 |
|
505 |
|
506 |
|
507 |
|
508 |
|
509 |
|
510 |
|
511 |
|
512 |
|
513 | }).call(this);
|
514 |
|
515 |
|
\ | No newline at end of file |