4]; if ($rValue !== null) { $rHardware[OpensslExtra::HARDWARE_KEY] = OpensslExtra::fingerprint($rValue); } return array_merge(['id' => $rID, 'is_main' => (int) ($rID === 1), 'server_type' => 0, 'server_hardware' => json_encode($rHardware)], $rOverride); } /** @return array{0:string,1:string[]} [output, problems] */ private function check(array $rServer, ?array $rMain): array { $rMethod = new ReflectionMethod(ServerDiagnoseCommand::class, 'opensslExtraSection'); $rMethod->setAccessible(true); $rProblems = []; ob_start(); try { $rMethod->invokeArgs(new ServerDiagnoseCommand(), [$rServer, $rMain, &$rProblems]); } finally { $rOutput = (string) ob_get_clean(); } return [$rOutput, $rProblems]; } /** The source of one of the command's methods, as reflection locates it. */ private function body(string $rName): string { $rMethod = new ReflectionMethod(ServerDiagnoseCommand::class, $rName); $rLines = file((string) $rMethod->getFileName()); return implode('', array_slice($rLines, $rMethod->getStartLine() - 1, $rMethod->getEndLine() - $rMethod->getStartLine() + 1)); } public function testAMismatchIsReportedAsAProblem(): void { [$rOutput, $rProblems] = $this->check($this->row(2, 'fNiu3XD448xTDa27xoY4'), $this->row(1, 'random-main-extra')); $this->assertStringContainsString('[WARN]', $rOutput); $this->assertCount(1, $rProblems); $this->assertStringStartsWith('OPENSSL_EXTRA mismatch: tokens minted on MAIN are rejected by this node', $rProblems[0]); $this->assertStringContainsString('server:sync-openssl-extra 2', $rProblems[0]); } public function testMatchingValuesPass(): void { [$rOutput, $rProblems] = $this->check($this->row(2, 'same-extra'), $this->row(1, 'same-extra')); $this->assertStringContainsString('[OK]', $rOutput); $this->assertSame([], $rProblems); } public function testAMissingFingerprintReadsAsUnknown(): void { [$rOutput, $rProblems] = $this->check($this->row(2, null), $this->row(1, 'main-extra')); $this->assertStringContainsString('unknown (node not updated)', $rOutput); $this->assertSame([], $rProblems); [$rOutput, $rProblems] = $this->check($this->row(2, 'lb-extra'), $this->row(1, null)); $this->assertStringContainsString('unknown (main not updated)', $rOutput); $this->assertSame([], $rProblems); } /** Both modes still report the check (see the class comment). */ public function testBothModesRunTheCheck(): void { $this->assertStringContainsString('$this->opensslExtraSection($rServer, $rMain, $rProblems);', $this->body('diagnoseFromMain')); $this->assertStringContainsString('$this->opensslExtraSection($rMe, $rMain, $rProblems);', $this->body('diagnoseLocal')); } public function testProxiesAndAMissingMainAreSkipped(): void { $this->assertSame(['', []], $this->check($this->row(3, null, ['server_type' => 1]), $this->row(1, 'main-extra'))); $this->assertSame(['', []], $this->check($this->row(2, 'lb-extra'), null)); } }