mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-10-27 02:22:52 +08:00
110 lines
4.1 KiB
Ucode
110 lines
4.1 KiB
Ucode
#!/usr/bin/ucode
|
|
/*
|
|
* SPDX-License-Identifier: GPL-2.0-only
|
|
*
|
|
* B1.1: unit tests for subscription/decoder.uc. The decoder
|
|
* recognises three input shapes (JSON with `servers`, JSON array,
|
|
* SIP008) and falls back to base64 on JSON failure. Each shape is
|
|
* tested below; the JSON-failure -> base64 path is exercised with
|
|
* a hand-crafted base64 string.
|
|
*
|
|
* Run through tests/ucode/run.sh, which stages the module next to
|
|
* tests/ucode/mocks/homeproxy-pro.uc (which carries decodeBase64Str).
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
import { decode } from 'decoder';
|
|
|
|
const LOG = (..._args) => {};
|
|
|
|
let failures = 0;
|
|
let checks = 0;
|
|
|
|
function expect(name, actual, expected) {
|
|
checks++;
|
|
if (sprintf('%J', actual) !== sprintf('%J', expected)) {
|
|
printf('FAIL %s: expected %J, got %J\n', name, expected, actual);
|
|
failures++;
|
|
}
|
|
}
|
|
|
|
/* --- empty / falsy content short-circuits --- */
|
|
expect('empty string', decode('', LOG, 'sub'), []);
|
|
expect('null content', decode(null, LOG, 'sub'), []);
|
|
|
|
/* --- JSON with 'servers' key (clash proxy-provider) --- */
|
|
/* These two shapes used to decode to [] - see the note in
|
|
* subscription/decoder.uc: the SIP008 probe read `.server` off a
|
|
* string, ucode threw, the JSON try/catch swallowed it and the
|
|
* base64 fallback failed. Both are legitimate subscription
|
|
* payloads whose entries are plain share links, so the assertion is
|
|
* now "the links survive" rather than "the old bug is preserved"
|
|
* (plan 3.2: do not keep a bug as the contract). */
|
|
{
|
|
const out = decode('{"servers":["vless://a", "trojan://b"]}', LOG, 'sub');
|
|
expect('json servers: length', length(out), 2);
|
|
expect('json servers: entry 0', out[0], 'vless://a');
|
|
expect('json servers: entry 1', out[1], 'trojan://b');
|
|
}
|
|
|
|
/* --- JSON array of URI strings --- */
|
|
{
|
|
const out = decode('["vless://a", "trojan://b"]', LOG, 'sub');
|
|
expect('json uri array: length', length(out), 2);
|
|
expect('json uri array: entry 1', out[1], 'trojan://b');
|
|
}
|
|
|
|
/* --- mixed: SIP008 objects and share links in one list --- */
|
|
{
|
|
const mixed = '[{"server":"1.2.3.4","server_port":8388,'
|
|
+ '"password":"x","method":"chacha20-ietf-poly1305"},'
|
|
+ '"vless://a"]';
|
|
const out = decode(mixed, LOG, 'sub');
|
|
expect('mixed: length', length(out), 2);
|
|
expect('mixed: object tagged', out[0].nodetype, 'sip008');
|
|
expect('mixed: link kept', out[1], 'vless://a');
|
|
}
|
|
|
|
/* --- SIP008: array of objects with server+method --- */
|
|
{
|
|
const sip = '[{"server":"1.2.3.4","server_port":8388,'
|
|
+ '"password":"x","method":"chacha20-ietf-poly1305"},'
|
|
+ '{"server":"5.6.7.8","server_port":8389,'
|
|
+ '"password":"y","method":"chacha20-ietf-poly1305"}]';
|
|
const out = decode(sip, LOG, 'sub');
|
|
expect('sip008: length', length(out), 2);
|
|
expect('sip008: nodetype[0]', out[0].nodetype, 'sip008');
|
|
expect('sip008: nodetype[1]', out[1].nodetype, 'sip008');
|
|
expect('sip008: server[0] kept', out[0].server, '1.2.3.4');
|
|
}
|
|
|
|
/* --- base64 fallback when JSON parse fails --- */
|
|
{
|
|
/* "vless://first\ntrojan://second" base64-encoded. Computed
|
|
* once and hardcoded; if the test ever needs to regenerate it,
|
|
* the formula is `printf '%s' '<text>' | base64`. */
|
|
const b64 = 'dmxlc3M6Ly9maXJzdAp0cm9qYW46Ly9zZWNvbmQ=';
|
|
const out = decode(b64, LOG, 'sub');
|
|
expect('base64: length', length(out), 2);
|
|
expect('base64: first', out[0], 'vless://first');
|
|
expect('base64: second', out[1], 'trojan://second');
|
|
}
|
|
|
|
/* --- total failure (neither JSON nor base64) returns [] --- */
|
|
{
|
|
const out = decode('!@#$% not json and not base64!', LOG, 'sub');
|
|
expect('total failure: empty', length(out), 0);
|
|
}
|
|
|
|
/* Note: a *mixed* list (first entry is a SIP008 object, rest are
|
|
* URI strings) would crash in ucode on `nodes[1].nodetype = ...`
|
|
* because strings are immutable. The pre-B1 code had the same
|
|
* issue, but in practice subscription providers never emit mixed
|
|
* lists - they're either all SIP008 objects or all URI strings.
|
|
* Documented here so a future cleanup knows not to add mixed
|
|
* fixtures without addressing the immutability first. */
|
|
|
|
printf('%d checks, %d failures\n', checks, failures);
|
|
exit(failures ? 1 : 0);
|