Files
op-packages/luci-app-homeproxy/tests/generator-golden/check_cases.js
T

119 lines
4.3 KiB
JavaScript
Executable File

#!/usr/bin/env node
'use strict';
const fs = require('fs');
const path = require('path');
const casesPath = path.join(__dirname, 'cases.json');
const cases = JSON.parse(fs.readFileSync(casesPath, 'utf8'));
const fixturesDir = path.join(__dirname, 'fixtures');
const requiredCases = [
'shadowsocks-basic',
'shadowsocks-shadowtls',
'selector-manual-nodes',
'selector-regex-nodes',
'selector-references-urltest',
'disabled-routing-node',
'routing-cycle',
'selector-cycle',
'routing-rule-direct-node',
'gfwlist-default-outbound-fallback',
'duplicate-label',
'reserved-tag-label',
'unsupported-certificate-pin',
'remove-subscription-node-references'
];
function assert(condition, message) {
if (!condition) {
console.error(message);
process.exitCode = 1;
}
}
function renameTagValue(value, rename) {
if (typeof value === 'string')
return Object.prototype.hasOwnProperty.call(rename, value) ? rename[value] : value;
if (Array.isArray(value))
return value.map((item) => (
item && typeof item === 'object' && !Array.isArray(item)
? renameTags(item, rename)
: renameTagValue(item, rename)
));
return value;
}
function renameTags(value, rename) {
if (Array.isArray(value))
return value.map((item) => renameTags(item, rename));
if (value && typeof value === 'object') {
for (const key of Object.keys(value)) {
if (['tag', 'outbound', 'outbounds', 'detour', 'default', 'final', 'download_detour'].includes(key))
value[key] = renameTagValue(value[key], rename);
else
value[key] = renameTags(value[key], rename);
}
}
return value;
}
assert(Array.isArray(cases), 'cases.json must contain an array');
const names = new Set();
for (const item of cases) {
assert(item && typeof item === 'object', 'each case must be an object');
assert(typeof item.name === 'string' && item.name.length > 0, 'case must have a name');
assert(!names.has(item.name), `duplicate case name: ${item.name}`);
names.add(item.name);
assert(typeof item.description === 'string' && item.description.length > 0, `${item.name}: missing description`);
assert(item.expects && typeof item.expects === 'object' && !Array.isArray(item.expects), `${item.name}: missing expects object`);
if (item.generator_fixture) {
const fixtureDir = path.join(fixturesDir, item.name);
const caseMetaPath = path.join(fixtureDir, 'case.json');
const configPath = path.join(fixtureDir, 'homeproxy');
const diagnosticsPath = path.join(fixtureDir, 'expected', 'config-diagnostics.json');
assert(fs.existsSync(configPath), `${item.name}: missing generator fixture homeproxy config`);
assert(fs.existsSync(caseMetaPath), `${item.name}: missing generator fixture case.json`);
assert(fs.existsSync(diagnosticsPath), `${item.name}: missing expected config diagnostics`);
if (fs.existsSync(caseMetaPath)) {
const meta = JSON.parse(fs.readFileSync(caseMetaPath, 'utf8'));
assert(typeof meta.success === 'boolean', `${item.name}: case.json must define boolean success`);
if (meta.success)
assert(fs.existsSync(path.join(fixtureDir, 'expected', 'sing-box-c.json')), `${item.name}: missing expected sing-box-c.json`);
}
}
}
for (const name of requiredCases)
assert(names.has(name), `missing required generator golden case: ${name}`);
const renameRegression = renameTags({
outbounds: [
{ type: 'selector', tag: 'Proxy_Selector', outbounds: ['Proxy_Auto', 'direct-out'] },
{ type: 'urltest', tag: 'Proxy_Auto', outbounds: ['node-a'] }
],
route: {
final: 'Proxy_Selector',
rules: [{ outbound: 'Proxy_Auto' }]
}
}, {
Proxy_Selector: '♻️ 节点选择',
Proxy_Auto: 'Proxy_Auto 标签',
'node-a': '节点 A'
});
assert(renameRegression.route.final === '♻️ 节点选择', 'rename_tags regression: route.final not renamed');
assert(renameRegression.outbounds[0].tag === '♻️ 节点选择', 'rename_tags regression: top-level outbound tag not renamed');
assert(renameRegression.outbounds[0].outbounds[0] === 'Proxy_Auto 标签', 'rename_tags regression: selector outbound list not renamed');
assert(renameRegression.outbounds[1].tag === 'Proxy_Auto 标签', 'rename_tags regression: nested outbound object not renamed');
if (!process.exitCode)
console.log(`generator golden cases: ${cases.length} ok`);