mirror of
https://github.com/PR0M3TH3AN/TORCH.git
synced 2026-10-27 07:51:52 +00:00
173 lines
6.9 KiB
JavaScript
173 lines
6.9 KiB
JavaScript
import { describe, it, after, beforeEach } from 'node:test';
|
|
import assert from 'node:assert';
|
|
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
import {
|
|
getTorchConfigPath,
|
|
parseTorchConfig,
|
|
loadTorchConfig,
|
|
_resetTorchConfigCache,
|
|
getRelays,
|
|
getQueryTimeoutMs,
|
|
getPublishTimeoutMs,
|
|
getMinSuccessfulRelayPublishes,
|
|
getRelayFallbacks,
|
|
getMinActiveRelayPool,
|
|
} from '../src/torch-config.mjs';
|
|
import { DEFAULT_RELAYS } from '../src/constants.mjs';
|
|
|
|
describe('torch-config', () => {
|
|
describe('getTorchConfigPath', () => {
|
|
const originalEnv = process.env.TORCH_CONFIG_PATH;
|
|
const originalCwd = process.cwd();
|
|
|
|
after(() => {
|
|
if (originalEnv === undefined) delete process.env.TORCH_CONFIG_PATH;
|
|
else process.env.TORCH_CONFIG_PATH = originalEnv;
|
|
process.chdir(originalCwd);
|
|
});
|
|
|
|
it('returns default path when env var is not set', () => {
|
|
delete process.env.TORCH_CONFIG_PATH;
|
|
assert.strictEqual(getTorchConfigPath(), path.resolve(process.cwd(), 'torch-config.json'));
|
|
});
|
|
|
|
it('returns custom path when env var is set', () => {
|
|
process.env.TORCH_CONFIG_PATH = 'custom-config.json';
|
|
assert.strictEqual(getTorchConfigPath(), path.resolve(process.cwd(), 'custom-config.json'));
|
|
});
|
|
|
|
it('prefers parent torch-config.json in host-repo mode when cwd is <repo>/torch', () => {
|
|
delete process.env.TORCH_CONFIG_PATH;
|
|
|
|
const fixtureRoot = fs.mkdtempSync(path.join(process.cwd(), 'test-torch-config-host-'));
|
|
const hostPkgPath = path.join(fixtureRoot, 'package.json');
|
|
const parentConfigPath = path.join(fixtureRoot, 'torch-config.json');
|
|
const torchDir = path.join(fixtureRoot, 'torch');
|
|
const localConfigPath = path.join(torchDir, 'torch-config.json');
|
|
|
|
fs.mkdirSync(torchDir, { recursive: true });
|
|
fs.writeFileSync(hostPkgPath, JSON.stringify({ name: 'seedpass', version: '1.0.0' }), 'utf8');
|
|
fs.writeFileSync(parentConfigPath, JSON.stringify({ nostrLock: { namespace: 'parent' } }), 'utf8');
|
|
fs.writeFileSync(localConfigPath, JSON.stringify({ nostrLock: { namespace: 'local' } }), 'utf8');
|
|
|
|
process.chdir(torchDir);
|
|
assert.strictEqual(getTorchConfigPath(), path.resolve(parentConfigPath));
|
|
});
|
|
});
|
|
|
|
describe('parseTorchConfig', () => {
|
|
it('parses new lock backend knobs', () => {
|
|
const config = parseTorchConfig({
|
|
nostrLock: {
|
|
namespace: ' test ',
|
|
relays: ['wss://relay1'],
|
|
relayFallbacks: [' wss://fallback-1 ', 'wss://fallback-2'],
|
|
queryTimeoutMs: 5000,
|
|
publishTimeoutMs: 8000,
|
|
minSuccessfulRelayPublishes: 2,
|
|
minActiveRelayPool: 2,
|
|
},
|
|
});
|
|
|
|
assert.strictEqual(config.nostrLock.namespace, 'test');
|
|
assert.deepStrictEqual(config.nostrLock.relays, ['wss://relay1']);
|
|
assert.deepStrictEqual(config.nostrLock.relayFallbacks, ['wss://fallback-1', 'wss://fallback-2']);
|
|
assert.strictEqual(config.nostrLock.queryTimeoutMs, 5000);
|
|
assert.strictEqual(config.nostrLock.publishTimeoutMs, 8000);
|
|
assert.strictEqual(config.nostrLock.minSuccessfulRelayPublishes, 2);
|
|
assert.strictEqual(config.nostrLock.minActiveRelayPool, 2);
|
|
});
|
|
});
|
|
|
|
describe('loadTorchConfig', () => {
|
|
const tempConfigPath = path.resolve(process.cwd(), 'temp-torch-config.json');
|
|
const badConfigPath = path.resolve(process.cwd(), 'bad-torch-config.json');
|
|
const originalEnv = process.env.TORCH_CONFIG_PATH;
|
|
|
|
beforeEach(() => {
|
|
_resetTorchConfigCache();
|
|
delete process.env.TORCH_CONFIG_PATH;
|
|
});
|
|
|
|
after(() => {
|
|
if (fs.existsSync(tempConfigPath)) fs.unlinkSync(tempConfigPath);
|
|
if (fs.existsSync(badConfigPath)) fs.unlinkSync(badConfigPath);
|
|
if (originalEnv === undefined) delete process.env.TORCH_CONFIG_PATH;
|
|
else process.env.TORCH_CONFIG_PATH = originalEnv;
|
|
_resetTorchConfigCache();
|
|
});
|
|
|
|
it('throws fatal error for invalid relay URL', async () => {
|
|
fs.writeFileSync(tempConfigPath, JSON.stringify({ nostrLock: { relays: ['https://bad'] } }));
|
|
process.env.TORCH_CONFIG_PATH = tempConfigPath;
|
|
await assert.rejects(() => loadTorchConfig(), /Invalid relay URL in nostrLock\.relays/);
|
|
});
|
|
|
|
it('throws fatal error for invalid timeout range', async () => {
|
|
fs.writeFileSync(tempConfigPath, JSON.stringify({ nostrLock: { queryTimeoutMs: 50 } }));
|
|
process.env.TORCH_CONFIG_PATH = tempConfigPath;
|
|
await assert.rejects(() => loadTorchConfig(), /Invalid nostrLock\.queryTimeoutMs/);
|
|
});
|
|
|
|
it('throws error for malformed JSON', async () => {
|
|
fs.writeFileSync(badConfigPath, '{ invalid json }');
|
|
process.env.TORCH_CONFIG_PATH = badConfigPath;
|
|
await assert.rejects(() => loadTorchConfig(), /Failed to parse/);
|
|
});
|
|
});
|
|
|
|
describe('backend getters', () => {
|
|
const originalEnv = {
|
|
NOSTR_LOCK_RELAYS: process.env.NOSTR_LOCK_RELAYS,
|
|
NOSTR_LOCK_QUERY_TIMEOUT_MS: process.env.NOSTR_LOCK_QUERY_TIMEOUT_MS,
|
|
NOSTR_LOCK_PUBLISH_TIMEOUT_MS: process.env.NOSTR_LOCK_PUBLISH_TIMEOUT_MS,
|
|
NOSTR_LOCK_MIN_SUCCESSFUL_PUBLISHES: process.env.NOSTR_LOCK_MIN_SUCCESSFUL_PUBLISHES,
|
|
NOSTR_LOCK_RELAY_FALLBACKS: process.env.NOSTR_LOCK_RELAY_FALLBACKS,
|
|
NOSTR_LOCK_MIN_ACTIVE_RELAY_POOL: process.env.NOSTR_LOCK_MIN_ACTIVE_RELAY_POOL,
|
|
};
|
|
|
|
beforeEach(() => {
|
|
_resetTorchConfigCache();
|
|
delete process.env.NOSTR_LOCK_RELAYS;
|
|
delete process.env.NOSTR_LOCK_QUERY_TIMEOUT_MS;
|
|
delete process.env.NOSTR_LOCK_PUBLISH_TIMEOUT_MS;
|
|
delete process.env.NOSTR_LOCK_MIN_SUCCESSFUL_PUBLISHES;
|
|
delete process.env.NOSTR_LOCK_RELAY_FALLBACKS;
|
|
delete process.env.NOSTR_LOCK_MIN_ACTIVE_RELAY_POOL;
|
|
});
|
|
|
|
after(() => {
|
|
for (const [k, v] of Object.entries(originalEnv)) {
|
|
if (v === undefined) delete process.env[k];
|
|
else process.env[k] = v;
|
|
}
|
|
_resetTorchConfigCache();
|
|
});
|
|
|
|
it('returns default relays', async () => {
|
|
assert.deepStrictEqual(await getRelays(), DEFAULT_RELAYS);
|
|
});
|
|
|
|
it('validates env knob values', async () => {
|
|
process.env.NOSTR_LOCK_QUERY_TIMEOUT_MS = '99';
|
|
await assert.rejects(() => getQueryTimeoutMs(), /NOSTR_LOCK_QUERY_TIMEOUT_MS/);
|
|
|
|
process.env.NOSTR_LOCK_QUERY_TIMEOUT_MS = '5000';
|
|
process.env.NOSTR_LOCK_PUBLISH_TIMEOUT_MS = 'abc';
|
|
await assert.rejects(() => getPublishTimeoutMs(), /NOSTR_LOCK_PUBLISH_TIMEOUT_MS/);
|
|
|
|
process.env.NOSTR_LOCK_PUBLISH_TIMEOUT_MS = '8000';
|
|
process.env.NOSTR_LOCK_MIN_SUCCESSFUL_PUBLISHES = '0';
|
|
await assert.rejects(() => getMinSuccessfulRelayPublishes(), /NOSTR_LOCK_MIN_SUCCESSFUL_PUBLISHES/);
|
|
|
|
process.env.NOSTR_LOCK_RELAY_FALLBACKS = 'https://bad';
|
|
await assert.rejects(() => getRelayFallbacks(), /NOSTR_LOCK_RELAY_FALLBACKS/);
|
|
|
|
process.env.NOSTR_LOCK_RELAY_FALLBACKS = '';
|
|
process.env.NOSTR_LOCK_MIN_ACTIVE_RELAY_POOL = '0';
|
|
await assert.rejects(() => getMinActiveRelayPool(), /NOSTR_LOCK_MIN_ACTIVE_RELAY_POOL/);
|
|
});
|
|
});
|
|
});
|