'consumer', 'sourceId' => 'ips:8', 'sourceName' => ' Boiler ', 'code' => 'Temp.High', 'severity' => 'warning', 'message' => " Temperatur hoch ", ], [ 'sourceType' => 'manager', 'sourceId' => 'ips:42', 'sourceName' => 'Manager', 'code' => 'Grid.Missing', 'severity' => 'critical', 'message' => 'Netzmessung fehlt', ], [ 'sourceType' => 'consumer', 'sourceId' => 'ips:8', 'sourceName' => 'Boiler', 'code' => 'Temp.High', 'severity' => 'warning', 'message' => 'Temperatur sehr hoch', ], ], 1_700_000_000 ); self::assertSame('1.0', $snapshot['version']); self::assertSame('2023-11-14T22:13:20Z', $snapshot['capturedAt']); self::assertSame( ['Grid.Missing', 'Temp.High'], array_column($snapshot['faults'], 'code') ); self::assertSame('Temperatur sehr hoch', $snapshot['faults'][1]['message']); self::assertSame( ['instanceId' => 42, 'role' => 'main', 'active' => true], $snapshot['manager'] ); } public function testZustandHashIgnoriertDenErfassungszeitpunkt(): void { $a = StoerungsSnapshot::erstellen( self::INSTALLATION_ID, 42, 'standalone', false, [], 1_700_000_000 ); $b = StoerungsSnapshot::erstellen( self::INSTALLATION_ID, 42, 'standalone', false, [], 1_700_000_300 ); self::assertSame(StoerungsSnapshot::zustandHash($a), StoerungsSnapshot::zustandHash($b)); } public function testSnapshotBegrenztSichAufHundertPriorisierteMeldungen(): void { $meldungen = []; for ($index = 1; $index <= 101; ++$index) { $meldungen[] = [ 'sourceType' => 'consumer', 'sourceId' => 'ips:' . $index, 'sourceName' => sprintf('Quelle %03d', $index), 'code' => 'Fault.' . $index, 'severity' => $index === 101 ? 'critical' : 'warning', 'message' => 'Testmeldung ' . $index, ]; } $snapshot = StoerungsSnapshot::erstellen( self::INSTALLATION_ID, 42, 'standalone', true, $meldungen ); self::assertCount(100, $snapshot['faults']); self::assertSame('Fault.101', $snapshot['faults'][0]['code']); } public function testUngueltigerSchweregradWirdAbgelehnt(): void { $this->expectException(InvalidArgumentException::class); StoerungsSnapshot::erstellen( self::INSTALLATION_ID, 42, 'standalone', true, [[ 'sourceType' => 'consumer', 'sourceId' => 'ips:8', 'sourceName' => 'Boiler', 'code' => 'Temp.High', 'severity' => 'alarm', 'message' => 'Temperatur hoch', ]] ); } }