originalEnvVersion = $_ENV['APP_VERSION'] ?? null; $this->setMemoryVersion(null); } protected function tearDown(): void { foreach ($this->stubStepFiles as $file) { if (File::exists($file)) { File::delete($file); } } $this->setMemoryVersion($this->originalEnvVersion); parent::tearDown(); } /** * 가드가 읽는 "메모리 버전" 을 env 와 config 양쪽에 세운다 (null 이면 env 만 비운다). * * @param string|null $version 세울 버전 */ private function setMemoryVersion(?string $version): void { if ($version === null) { unset($_ENV['APP_VERSION'], $_SERVER['APP_VERSION']); putenv('APP_VERSION'); return; } $_ENV['APP_VERSION'] = $version; $_SERVER['APP_VERSION'] = $version; putenv('APP_VERSION='.$version); config(['app.version' => $version]); } public function test_throws_when_beta5_step_does_not_extend_abstract(): void { // stale 메모리 가드 우회를 위해 메모리 버전을 target 이상으로 $this->setMemoryVersion('7.9.9'); // 7.9.9-test.guard.a 는 7.0.0-beta.5 보다 명확히 큼 (version_compare 의 pre-release // 해석에 영향 받지 않음). stub 은 AbstractUpgradeStep 미상속 → fatal 가드 발동. $version = '7_9_9_test_guard_a'; $className = 'Upgrade_'.$version; $path = base_path('upgrades/'.$className.'.php'); $this->stubStepFiles[] = $path; File::put($path, <<expectException(CoreUpdateOperationException::class); $this->expectExceptionMessageMatches('/must extend App\\\\Extension\\\\AbstractUpgradeStep/'); $service = app(CoreUpdateService::class); $service->runUpgradeSteps('7.0.0-beta.4', '7.9.9-test.guard.a'); } public function test_passes_when_beta5_step_extends_abstract(): void { $this->setMemoryVersion('7.9.9'); $version = '7_9_9_test_guard_b'; $className = 'Upgrade_'.$version; $path = base_path('upgrades/'.$className.'.php'); $this->stubStepFiles[] = $path; File::put($path, <<runUpgradeSteps( '7.0.0-beta.4', '7.9.9-test.guard.b', function (string $v) use (&$executed): void { $executed[] = $v; }, ); $this->assertContains('7.9.9-test.guard.b', $executed); } public function test_legacy_pre_beta5_step_bypasses_guard(): void { // legacy beta.4 이하 step 은 AbstractUpgradeStep 미상속이어도 통과 (호환) $this->setMemoryVersion('7.0.0-beta.5'); $version = '7_0_0_beta_4_test_guard_legacy'; $className = 'Upgrade_'.$version; $path = base_path('upgrades/'.$className.'.php'); $this->stubStepFiles[] = $path; File::put($path, <<runUpgradeSteps( '7.0.0-beta.3', '7.0.0-beta.4.test.guard.legacy', function (string $v) use (&$executed): void { $executed[] = $v; }, ); $this->assertContains('7.0.0-beta.4.test.guard.legacy', $executed); } }