import os from pathlib import Path import subprocess import tempfile import time import unittest SCRIPT=Path(__file__).resolve().parents[1]/'scripts/collect.sh' class CollectorTests(unittest.TestCase): def collect(self,response,code=0): with tempfile.TemporaryDirectory() as tmp: root=Path(tmp) fake=root/'rcon' fake.write_text('#!/bin/sh\n[ "$*" = "/players online" ] || exit 88\nprintf "%s\\n" "$RESPONSE"\nexit "$CODE"\n') fake.chmod(0o755) proc=subprocess.Popen(['sh',str(SCRIPT)],env={**os.environ,'PATH':tmp+':'+os.environ['PATH'],'METRICS_DIR':tmp,'RESPONSE':response,'CODE':str(code)},start_new_session=True,stderr=subprocess.DEVNULL) try: output=root/'factorio.prom' for _ in range(100): if output.exists():return output.read_text() time.sleep(.01) self.fail('Collector did not atomically publish metrics') finally: import signal os.killpg(proc.pid,signal.SIGTERM);proc.wait() def test_empty_world_reports_zero(self): metrics=self.collect('Online players (0):') self.assertIn('factorio_server_up 1',metrics);self.assertIn('factorio_players_online 0',metrics) def test_players_reported_without_lua(self): self.assertIn('factorio_players_online 12',self.collect('Online players (12):\n Alice (online)')) def test_failed_rcon_is_not_zero_players(self): metrics=self.collect('',1) self.assertIn('factorio_server_up 0',metrics);self.assertNotIn('\nfactorio_players_online ',metrics) def test_unexpected_response_does_not_report_healthy(self): self.assertIn('factorio_server_up 0',self.collect('Authentication failed'))