import { test } from 'node:test'; import assert from 'node:assert/strict'; import { loadConfig } from '../src/config.js'; import { openDatabase } from '../src/db.js'; import { ServerSettings } from '../src/serverSettings.js'; import { DockerHostPool } from '../src/servers/dockerAdapter.js'; function setup() { const config = loadConfig({ match: { maxRoundsCompetitive: 24, extraCommands: [] }, vetoStepSeconds: 30 }); const db = openDatabase(':memory:'); return { config, db, settings: new ServerSettings({ db, config }) }; } test('Geänderte Einstellungen landen in der Konfiguration und überstehen einen Neustart', () => { const { config, db, settings } = setup(); const changed = settings.update({ maxRoundsCompetitive: 30, extraCommands: 'mp_freezetime 15; sv_cheats 0', vetoStepSeconds: 30 }); assert.deepEqual(changed, ['maxRoundsCompetitive', 'extraCommands']); assert.equal(config.match.maxRoundsCompetitive, 30); assert.deepEqual(config.match.extraCommands, ['mp_freezetime 15', 'sv_cheats 0']); // Neustart: neue Konfiguration aus der .env, gespeicherte Werte werden wieder darübergelegt const fresh = loadConfig({ match: { maxRoundsCompetitive: 24, extraCommands: [] } }); new ServerSettings({ db, config: fresh }).load(); assert.equal(fresh.match.maxRoundsCompetitive, 30); assert.deepEqual(fresh.match.extraCommands, ['mp_freezetime 15', 'sv_cheats 0']); }); test('Ungültige Werte und gesperrte Befehle werden abgelehnt', () => { const { config, settings } = setup(); assert.throws(() => settings.update({ maxRoundsCompetitive: 500 }), /ganze Zahl von 2 bis 60/); assert.throws(() => settings.update({ overtime: 'ja' }), /an oder aus/); assert.throws(() => settings.update({ extraCommands: 'rcon_password neu' }), /nicht erlaubt/); assert.throws(() => settings.update({ unbekannt: 1 }), /Unbekannte Einstellung/); // Nichts davon wurde übernommen assert.equal(config.match.maxRoundsCompetitive, 24); }); test('Zurück auf die Vorgabe entfernt die gespeicherte Abweichung', () => { const { settings } = setup(); settings.update({ maxRoundsCompetitive: 30 }); assert.equal(settings.view().find((f) => f.key === 'maxRoundsCompetitive').overridden, true); settings.update({ maxRoundsCompetitive: 24 }); assert.equal(settings.view().find((f) => f.key === 'maxRoundsCompetitive').overridden, false); }); test('Docker-Hosts: Prüfung der Liste und Übernahme in den Pool, Startzeit wirkt sofort', () => { const { config, settings } = setup(); assert.throws(() => settings.parseHosts([{ name: 'a', publicHost: '1.2.3.4', dockerHost: 'ssh://x; rm -rf /' }]), /Ungültiges Docker-Ziel/); assert.throws(() => settings.parseHosts([{ name: 'a', publicHost: '1.2.3.4', portStart: 80, portEnd: 90 }]), /Portbereich/); const hosts = settings.parseHosts([ { name: 'a', publicHost: '10.0.0.1', dockerHost: 'ssh://server@10.0.0.1', portStart: 27100, portEnd: 27139 }, { name: 'b', publicHost: '10.0.0.2', dockerHost: 'ssh://b', portStart: 27100, portEnd: 27119 }, ]); const pool = new DockerHostPool({ ...config.docker, startTimeoutMinutes: 20, hosts: null }); pool.setHosts(hosts); assert.deepEqual(pool.hostStats().map((h) => [h.name, h.total]), [['a', 20], ['b', 10]]); pool.options.startTimeoutMinutes = 45; assert.equal(pool.adapters.get('b').options.startTimeoutMinutes, 45); });