rDir = CRONS_TMP_PATH; @mkdir($this->rDir, 0775, true); } protected function tearDown(): void { foreach (glob($this->rDir . '*') ?: [] as $rFile) { @unlink($rFile); } } public function testLockPathIsStablePerClassAndIgnoresTheSecret(): void { $rA = ProcessManager::cronLockPath('XcVm\\Cli\\CronJobs\\ServersCronJob'); $this->assertSame($rA, ProcessManager::cronLockPath('XcVm\\Cli\\CronJobs\\ServersCronJob')); $this->assertNotSame($rA, ProcessManager::cronLockPath('XcVm\\Cli\\CronJobs\\CacheCronJob')); $this->assertStringStartsWith(CRONS_TMP_PATH, $rA); $this->assertNotSame( ProcessManager::legacyCronLockPath('X', 'secret-one'), ProcessManager::legacyCronLockPath('X', 'secret-two'), 'the legacy name is exactly what a rotation used to break' ); } public function testNoCronLockIsDerivedFromTheStreamingSecret(): void { $rRoot = dirname(__DIR__, 2) . '/src/'; foreach (['Cli/CronTrait.php', 'Cli/CronJobs/RootSignalsCronJob.php', 'Cli/Commands/ServerDiagnoseCommand.php'] as $rFile) { $rSource = (string) file_get_contents($rRoot . $rFile); $this->assertStringContainsString('ProcessManager::cronLockPath(', $rSource, $rFile); $this->assertStringNotContainsString("md5(Encryption::generateUniqueCode(SettingsManager::get('live_streaming_pass')", $rSource, $rFile); } } public function testAStaleOrMissingLegacyLockDoesNotBlock(): void { $rLegacy = ProcessManager::legacyCronLockPath('X', 'pass'); ProcessManager::exitIfCronLockHeld($rLegacy); // absent: returns file_put_contents($rLegacy, '999999999'); // pid that cannot exist ProcessManager::exitIfCronLockHeld($rLegacy); $this->addToAssertionCount(1); } }