import { test } from 'node:test'; import assert from 'node:assert/strict'; import { mkdtempSync, mkdirSync, writeFileSync, existsSync, readFileSync, chmodSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { spawnSync } from 'node:child_process'; const SCRIPT = new URL('../scripts/geo-update.sh', import.meta.url).pathname; // Fremde Programme (curl, docker) sind Attrappen im PATH; docker schlaegt fehl, solange DOCKER_FAIL=1 gesetzt ist. function setup() { const root = mkdtempSync(join(tmpdir(), 'geoupd-')); const bin = join(root, 'bin'); const data = join(root, 'data'); mkdirSync(bin); mkdirSync(data); const csv = join(root, 'src.csv'); const rows = []; for (let i = 0; i < 100100; i++) rows.push(`1.${i % 250}.${Math.floor(i / 250) % 250}.0,1.${i % 250}.${Math.floor(i / 250) % 250}.255,AU`); rows.push('5.9.0.0,5.9.255.255,DE'); writeFileSync(csv, rows.join('\n') + '\n'); writeFileSync(join(bin, 'curl'), `#!/bin/sh\nwhile [ "$#" -gt 0 ]; do [ "$1" = "-o" ] && out="$2"; shift; done\ngzip -c "${csv}" > "$out"\n`); writeFileSync(join(bin, 'docker'), `#!/bin/sh\necho "$@" >> "${root}/docker.log"\n[ "\${DOCKER_FAIL:-0}" = "1" ] && exit 1\nexit 0\n`); chmodSync(join(bin, 'curl'), 0o755); chmodSync(join(bin, 'docker'), 0o755); const run = (fail) => spawnSync('sh', [SCRIPT], { env: { PATH: `${bin}:${process.env.PATH}`, ANALYTICS_DATA_DIR: data, DOCKER_FAIL: fail ? '1' : '0' }, encoding: 'utf8' }); const restarts = () => (existsSync(join(root, 'docker.log')) ? readFileSync(join(root, 'docker.log'), 'utf8').trim().split('\n').length : 0); return { data, run, restarts, marker: join(data, 'geo.restart-pending') }; } test('geo-update: Neustart schlägt fehl -> Marker; nächster Lauf startet trotz unveränderter Datei neu und entfernt ihn', () => { const s = setup(); const first = s.run(true); assert.notEqual(first.status, 0, first.stderr); assert.ok(existsSync(join(s.data, 'geo.csv')), 'neue Datei ist schon an Ort und Stelle'); assert.ok(existsSync(s.marker), 'Marker liegt'); assert.equal(s.restarts(), 1); const second = s.run(false); assert.equal(second.status, 0, second.stderr); assert.equal(s.restarts(), 2, 'Neustart nachgeholt'); assert.equal(existsSync(s.marker), false); const third = s.run(false); assert.equal(third.status, 0); assert.equal(s.restarts(), 2, 'unverändert und ohne Marker: kein Neustart'); }); test('geo-update: erfolgreicher Neustart hinterlässt keinen Marker', () => { const s = setup(); assert.equal(s.run(false).status, 0); assert.equal(s.restarts(), 1); assert.equal(existsSync(s.marker), false); });