58 lines
2.6 KiB
PHP
58 lines
2.6 KiB
PHP
<?php
|
|
|
|
namespace Tests\Unit\Deployment;
|
|
|
|
use PHPUnit\Framework\TestCase;
|
|
use Symfony\Component\Process\Process;
|
|
|
|
class DeploymentSyncLockTest extends TestCase
|
|
{
|
|
public function test_container_replacement_waits_for_sync_and_fails_safely_on_lock_timeout(): void
|
|
{
|
|
foreach (['activate-release.sh', 'activate-incremental-release.sh'] as $script) {
|
|
$contents = file_get_contents(dirname(__DIR__, 3) . '/deploy/' . $script);
|
|
$start = strpos($contents, 'exec 8>/run/caiwu-upstream-sync.lock');
|
|
$end = strpos($contents, 'PREVIOUS_IMAGE=', $start ?: 0);
|
|
$this->assertNotFalse($start, $script);
|
|
$this->assertNotFalse($end, $script);
|
|
$this->assertLessThan(strpos($contents, 'docker compose -f compose.jiangling.yml up'), $end);
|
|
$guard = substr($contents, $start, $end - $start);
|
|
|
|
$directory = sys_get_temp_dir() . '/caiwu-deploy-lock-' . bin2hex(random_bytes(8));
|
|
mkdir($directory, 0700);
|
|
$holder = new Process(['sh', '-c', 'exec 8>"$1"; flock 8; touch "$2"; sleep 2', 'holder', $directory . '/sync.lock', $directory . '/held']);
|
|
try {
|
|
$holder->start();
|
|
$deadline = microtime(true) + 3;
|
|
while (! file_exists($directory . '/held') && microtime(true) < $deadline) {
|
|
usleep(10000);
|
|
}
|
|
$this->assertFileExists($directory . '/held');
|
|
$guard = str_replace('/run/caiwu-upstream-sync.lock', $directory . '/sync.lock', $guard);
|
|
$guard .= "touch '$directory/activated'\n";
|
|
|
|
$timeout = new Process(['sh', '-c', str_replace('-w 1800', '-w 0', $guard)]);
|
|
$timeout->run();
|
|
$this->assertSame(1, $timeout->getExitCode());
|
|
$this->assertStringContainsString('application container was not replaced', $timeout->getErrorOutput());
|
|
$this->assertFileDoesNotExist($directory . '/activated');
|
|
|
|
$release = new Process(['sh', '-c', $guard]);
|
|
$release->start();
|
|
usleep(100000);
|
|
$this->assertTrue($release->isRunning());
|
|
$this->assertFileDoesNotExist($directory . '/activated');
|
|
$release->wait();
|
|
$this->assertTrue($release->isSuccessful(), $release->getErrorOutput());
|
|
$this->assertFileExists($directory . '/activated');
|
|
} finally {
|
|
$holder->stop();
|
|
foreach (glob($directory . '/*') as $file) {
|
|
unlink($file);
|
|
}
|
|
rmdir($directory);
|
|
}
|
|
}
|
|
}
|
|
}
|