Files
Cs2-Mapveto/server/test/dockerAdapter.test.js
T
mregosar e8e070dfe6 CSTV: Verzögerung wirkt wieder, Server läuft am Serienende bis zum Ende der Übertragung
- Das Image schrieb TV_DELAY (Standard 0) bei jedem Containerstart in alle gamemode_*.cfg, die bei
  jedem Laden einer Map laufen: tv_delay stand danach immer auf 0. Die App gibt TV_DELAY jetzt mit
  und setzt tv_delay zusätzlich nach dem Laden der Map per RCON.
- Am Serienende (automatisch oder von Hand abgeschlossen) bleibt der Server die CSTV-Verzögerung
  plus 15 s an, damit der Stream das Ende zeigt. Abgebrochene Matches stoppen sofort.
- Ingame-Chat: Hinweis, dass der Server für CSTV noch online bleibt und sich dann abschaltet;
  beim Mapwechsel die echte Wartezeit nach der CSTV-Übertragung (tv_delaymapchange).
2026-11-01 22:07:39 +01:00

110 lines
5.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { DockerServerAdapter } from '../src/servers/dockerAdapter.js';
const options = {
bin: 'docker', image: 'joedwards32/cs2:latest', host: '192.168.178.111', rconHost: '192.168.178.111',
portRangeStart: 27100, portRangeEnd: 27139, gslt: '', volume: 'cs2-mapveto-gamefiles', extraArgs: '', startTimeoutMinutes: 1,
};
const secrets = { rconPassword: 'Rcon123', serverPassword: 'Pw123', tvPassword: 'Tv123' };
/** Simuliertes Docker: merkt sich Aufrufe; Container gelten als "Update fertig", sobald freigegeben. */
function fakeDocker() {
const calls = [];
const updated = new Set();
const run = async (args) => {
calls.push(args);
const [cmd] = args;
const name = args.at(-1);
if (cmd === 'inspect') return 'running';
if (cmd === 'logs') return updated.has(name) ? 'Success! App \'730\' already up to date.\nStarting CS2 Dedicated Server' : 'Checking for available updates...';
return '';
};
return { run, calls, finishUpdate: (name) => updated.add(name) };
}
const envOf = (args) => Object.fromEntries(args.flatMap((a, i) => (args[i - 1] === '-e' ? [a.split(/=(.*)/s).slice(0, 2)] : [])));
test('Ohne GSLT startet der Container im LAN-Modus, mit GSLT mit Token', async () => {
const lan = fakeDocker();
const a = new DockerServerAdapter(options, { getUsedPorts: () => new Set(), runDocker: lan.run });
a.isReachable = async () => false;
const r = await a.start({ matchId: 'abc_DEF-1', mode: 'wingman', secrets });
lan.finishUpdate(r.handle.container);
const runArgs = lan.calls.find((c) => c[0] === 'run');
const env = envOf(runArgs);
assert.equal(env.CS2_LAN, '1');
assert.equal(env.SRCDS_TOKEN, undefined);
assert.equal(env.CS2_GAMEMODE, '2');
assert.equal(env.CS2_MAXPLAYERS, '6', '4 Spieler + CSTV + Reserve');
assert.equal(env.CS2_ADDITIONAL_ARGS, '-allow_round_backup_files +sv_deltaticks_enforce 0', 'Rundensicherung für Rollback, keine Trennung wegen Delta-Ticks');
assert.equal(env.CS2_PORT, '27100');
assert.equal(env.TV_PORT, '27200');
assert.ok(runArgs.includes('cs2-mapveto-gamefiles:/home/steam/cs2-dedicated'));
assert.equal(r.host, '192.168.178.111');
const tok = fakeDocker();
const b = new DockerServerAdapter({ ...options, gslt: 'TOKEN1' }, { getUsedPorts: () => new Set(), runDocker: tok.run });
b.isReachable = async () => false;
const r2 = await b.start({ matchId: 'x', mode: 'competitive', secrets });
tok.finishUpdate(r2.handle.container);
const env2 = envOf(tok.calls.find((c) => c[0] === 'run'));
assert.equal(env2.SRCDS_TOKEN, 'TOKEN1');
assert.equal(env2.CS2_LAN, '0');
});
test('Zweiter Container startet erst, wenn der erste seinen Update-Check abgeschlossen hat', async () => {
const d = fakeDocker();
const used = new Set();
const a = new DockerServerAdapter(options, { getUsedPorts: () => used, runDocker: d.run });
// Wartezeit zwischen Prüfungen für den Test verkürzen
const original = a.waitForUpdateCheck.bind(a);
a.waitForUpdateCheck = (handle) => original(handle, { pollMs: 10 });
a.isReachable = async () => false;
const first = await a.start({ matchId: 'm1', mode: 'competitive', secrets });
used.add(first.port).add(first.tvPort);
let secondDone = false;
const second = a.start({ matchId: 'm2', mode: 'competitive', secrets }).then((r) => { secondDone = true; return r; });
await new Promise((r) => setTimeout(r, 60));
assert.equal(secondDone, false, 'zweiter Start wartet noch');
assert.equal(d.calls.filter((c) => c[0] === 'run').length, 1);
d.finishUpdate(first.handle.container);
const r2 = await second;
assert.equal(d.calls.filter((c) => c[0] === 'run').length, 2);
assert.equal(r2.port, 27101, 'zweiter Container bekommt den nächsten Port');
d.finishUpdate(r2.handle.container);
});
test('Warteschlange gibt frei, sobald der Server per RCON antwortet – auch ohne Startzeile im Log', async () => {
const d = fakeDocker();
const used = new Set();
const a = new DockerServerAdapter(options, { getUsedPorts: () => used, runDocker: d.run });
const original = a.waitForUpdateCheck.bind(a);
a.waitForUpdateCheck = (handle) => original(handle, { pollMs: 10 });
const reachable = new Set();
a.isReachable = async (handle) => reachable.has(handle.container);
const first = await a.start({ matchId: 'r1', mode: 'wingman', secrets });
used.add(first.port).add(first.tvPort);
const second = a.start({ matchId: 'r2', mode: 'wingman', secrets });
await new Promise((r) => setTimeout(r, 50));
assert.equal(d.calls.filter((c) => c[0] === 'run').length, 1, 'wartet noch');
reachable.add(first.handle.container); // Log ohne Startzeile, aber RCON antwortet
const r2 = await second;
assert.equal(d.calls.filter((c) => c[0] === 'run').length, 2);
reachable.add(r2.handle.container);
});
test('TV_DELAY geht an das Image, sonst setzt es CSTV nach jedem Mapwechsel auf 0 Sekunden', async () => {
const d = fakeDocker();
const a = new DockerServerAdapter(options, { getUsedPorts: () => new Set(), runDocker: d.run });
a.isReachable = async () => false;
await a.launch({ matchId: 'tv1', mode: 'competitive', secrets, tvDelaySeconds: 90 });
const run = d.calls.find((c) => c.args?.[0] === 'run' || c[0] === 'run');
const env = envOf(run.args ?? run);
assert.equal(env.TV_DELAY, '90');
});