mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-09-14 20:34:19 +08:00
183 lines
5.0 KiB
Ucode
183 lines
5.0 KiB
Ucode
#!/usr/bin/ucode
|
|
'use strict';
|
|
|
|
import { readfile, writefile, stat } from 'fs';
|
|
|
|
const base_dir = ARGV?.[0] || 'tests/generator-golden';
|
|
const generator = ARGV?.[1] || '/etc/homeproxy/scripts/generate_client.uc';
|
|
const module_dir = ARGV?.[2];
|
|
|
|
function hasFlag(flag) {
|
|
const argv = (type(ARGV) === 'array') ? ARGV : [];
|
|
|
|
for (let item in argv)
|
|
if (item === flag)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
const update_expected = hasFlag('--update');
|
|
|
|
function shellquote(s) {
|
|
return `'${replace(s, "'", "'\\''")}'`;
|
|
}
|
|
|
|
function fail(message) {
|
|
warn(message + '\n');
|
|
exit(1);
|
|
}
|
|
|
|
function path(...parts) {
|
|
return join('/', parts);
|
|
}
|
|
|
|
function exists(file) {
|
|
return stat(file)?.type === 'file';
|
|
}
|
|
|
|
function readJson(file, fallback) {
|
|
if (!exists(file))
|
|
return fallback;
|
|
|
|
return json(readfile(file));
|
|
}
|
|
|
|
function normalize(value, test_root) {
|
|
let value_type = type(value);
|
|
|
|
if (value_type === 'string')
|
|
return replace(value, test_root, '__TEST_ROOT__');
|
|
|
|
if (value_type === 'array') {
|
|
let result = [];
|
|
for (let item in value)
|
|
push(result, normalize(item, test_root));
|
|
return result;
|
|
}
|
|
|
|
if (value_type === 'object') {
|
|
let result = {};
|
|
for (let key in value) {
|
|
if (key === 'time')
|
|
continue;
|
|
result[key] = normalize(value[key], test_root);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
function canonical(value) {
|
|
return sprintf('%.J', value);
|
|
}
|
|
|
|
function compareJson(case_name, label, actual, expected) {
|
|
if (canonical(actual) === canonical(expected))
|
|
return;
|
|
|
|
warn(sprintf('%s: %s golden mismatch\n', case_name, label));
|
|
warn('expected:\n' + sprintf('%.J\n', expected));
|
|
warn('actual:\n' + sprintf('%.J\n', actual));
|
|
exit(1);
|
|
}
|
|
|
|
function generatorCommand() {
|
|
if (module_dir && module_dir !== '--update')
|
|
return sprintf('ucode -S -L %s %s', shellquote(module_dir), shellquote(generator));
|
|
|
|
return shellquote(generator);
|
|
}
|
|
|
|
function prepareRoot(case_name, fixture_dir) {
|
|
const test_root = '/tmp/homeproxy-golden-' + replace(case_name, /[^A-Za-z0-9_-]/g, '_');
|
|
|
|
system('rm -rf ' + shellquote(test_root));
|
|
system('mkdir -p ' +
|
|
shellquote(path(test_root, 'etc/config')) + ' ' +
|
|
shellquote(path(test_root, 'etc/homeproxy/resources')) + ' ' +
|
|
shellquote(path(test_root, 'var/run/homeproxy')));
|
|
|
|
writefile(path(test_root, 'etc/config/homeproxy'), readfile(path(fixture_dir, 'homeproxy')));
|
|
|
|
const direct_list = path(fixture_dir, 'resources/direct_list.txt'),
|
|
proxy_list = path(fixture_dir, 'resources/proxy_list.txt');
|
|
writefile(path(test_root, 'etc/homeproxy/resources/direct_list.txt'), exists(direct_list) ? readfile(direct_list) : '');
|
|
writefile(path(test_root, 'etc/homeproxy/resources/proxy_list.txt'), exists(proxy_list) ? readfile(proxy_list) : '');
|
|
|
|
return test_root;
|
|
}
|
|
|
|
function runCase(item) {
|
|
const case_name = item.name,
|
|
fixture_dir = path(base_dir, 'fixtures', case_name),
|
|
meta = readJson(path(fixture_dir, 'case.json'), null);
|
|
|
|
if (!meta)
|
|
fail(sprintf('%s: missing fixture case.json', case_name));
|
|
|
|
const test_root = prepareRoot(case_name, fixture_dir),
|
|
stdout_path = path(test_root, 'var/run/homeproxy/stdout.log'),
|
|
stderr_path = path(test_root, 'var/run/homeproxy/stderr.log'),
|
|
command = sprintf('%s --test-root %s >%s 2>%s',
|
|
generatorCommand(),
|
|
shellquote(test_root),
|
|
shellquote(stdout_path),
|
|
shellquote(stderr_path)),
|
|
status = system(command),
|
|
success = (status === 0);
|
|
|
|
if (!!meta.success !== success) {
|
|
warn(sprintf('%s: expected success=%J, got status=%d\n', case_name, meta.success, status));
|
|
warn(readfile(stderr_path) || '');
|
|
system('rm -rf ' + shellquote(test_root));
|
|
exit(1);
|
|
}
|
|
|
|
const actual_config_path = path(test_root, 'var/run/homeproxy/sing-box-c.json'),
|
|
expected_config_path = path(fixture_dir, 'expected/sing-box-c.json');
|
|
|
|
if (meta.success) {
|
|
if (!exists(actual_config_path))
|
|
fail(sprintf('%s: generator succeeded but sing-box-c.json is missing', case_name));
|
|
const actual_config = normalize(json(readfile(actual_config_path)), test_root);
|
|
|
|
if (update_expected)
|
|
writefile(expected_config_path, sprintf('%.J\n', actual_config));
|
|
else
|
|
compareJson(case_name, 'sing-box-c.json',
|
|
actual_config,
|
|
readJson(expected_config_path, null));
|
|
}
|
|
|
|
const actual_diagnostics = exists(path(test_root, 'var/run/homeproxy/config-diagnostics.json'))
|
|
? json(readfile(path(test_root, 'var/run/homeproxy/config-diagnostics.json')))
|
|
: { items: [] };
|
|
const normalized_diagnostics = normalize(actual_diagnostics, test_root),
|
|
expected_diagnostics_path = path(fixture_dir, 'expected/config-diagnostics.json');
|
|
|
|
if (update_expected)
|
|
writefile(expected_diagnostics_path, sprintf('%.J\n', normalized_diagnostics));
|
|
else
|
|
compareJson(case_name, 'config-diagnostics.json',
|
|
normalized_diagnostics,
|
|
readJson(expected_diagnostics_path, { items: [] }));
|
|
|
|
system('rm -rf ' + shellquote(test_root));
|
|
printf('%s ok\n', case_name);
|
|
}
|
|
|
|
const cases = readJson(path(base_dir, 'cases.json'), []);
|
|
let count = 0;
|
|
|
|
for (let item in cases) {
|
|
if (!item.generator_fixture)
|
|
continue;
|
|
|
|
runCase(item);
|
|
count++;
|
|
}
|
|
|
|
printf('generator golden fixtures: %d ok\n', count);
|