commit13
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Contracts\Console\Kernel;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
use Symfony\Component\Process\Process;
|
||||
|
||||
require dirname(__DIR__).'/vendor/autoload.php';
|
||||
$app = require dirname(__DIR__).'/bootstrap/app.php';
|
||||
$app->make(Kernel::class)->bootstrap();
|
||||
$config = DB::connection('pgsql')->getConfig();
|
||||
unset($config['name']);
|
||||
if ($config['host'] !== '127.0.0.1') {
|
||||
throw new LogicException('Prova de contexto apenas em servidor local.');
|
||||
}
|
||||
$database = 'compras_receipts_test_'.bin2hex(random_bytes(6));
|
||||
config(['database.connections.context_proof_admin' => [...$config, 'database' => 'postgres', 'url' => null]]);
|
||||
$admin = DB::connection('context_proof_admin');
|
||||
$admin->statement('CREATE DATABASE "'.$database.'"');
|
||||
$workflow = in_array('--workflow', $argv ?? [], true);
|
||||
$warehouse = in_array('--warehouse', $argv ?? [], true);
|
||||
try {
|
||||
$environment = ['APP_ENV' => 'testing', 'DB_CONNECTION' => 'pgsql', 'DB_URL' => '', 'DB_HOST' => $config['host'], 'DB_PORT' => (string) $config['port'],
|
||||
'DB_DATABASE' => $database, 'DB_USERNAME' => $config['username'], 'DB_PASSWORD' => $config['password']];
|
||||
$tests = $workflow ? ['tests/Feature/InternalRequisitionCandidateTest.php', 'tests/Feature/WorkContextTest.php'] : ['tests/Feature/WorkContextTest.php'];
|
||||
if ($warehouse) {
|
||||
$tests = ['tests/Feature/WarehouseRequestsTest.php', 'tests/Feature/WarehouseAvailabilityTest.php', 'tests/Feature/WarehouseFulfilmentTest.php'];
|
||||
}
|
||||
$process = new Process([PHP_BINARY, 'vendor/bin/pest', '--compact', ...$tests], dirname(__DIR__), $environment, timeout: 120);
|
||||
$process->run();
|
||||
echo $process->getOutput();
|
||||
if (! $process->isSuccessful()) {
|
||||
throw new RuntimeException('Prova PostgreSQL de contexto não aprovada.');
|
||||
}
|
||||
$races = [];
|
||||
if ($warehouse) {
|
||||
config(['database.connections.warehouse_proof_read' => [...$config, 'database' => $database, 'url' => null]]);
|
||||
$reader = DB::connection('warehouse_proof_read');
|
||||
foreach (['same_operation', 'different_operations'] as $scenario) {
|
||||
$fixture = new Process([PHP_BINARY, 'tests/Concurrency/warehouse-worker.php', 'prepare'], dirname(__DIR__), $environment, timeout: 20);
|
||||
$fixture->mustRun();
|
||||
$data = json_decode($fixture->getOutput(), true, 32, JSON_THROW_ON_ERROR);
|
||||
$first = new Process([PHP_BINARY, 'tests/Concurrency/warehouse-worker.php', 'hold', json_encode($data, JSON_THROW_ON_ERROR)], dirname(__DIR__), $environment, timeout: 20);
|
||||
$first->start();
|
||||
$deadline = microtime(true) + 5;
|
||||
while ($first->isRunning() && ! str_contains($first->getOutput(), 'locked') && microtime(true) < $deadline) {
|
||||
usleep(20000);
|
||||
}
|
||||
if (! str_contains($first->getOutput(), 'locked')) {
|
||||
throw new RuntimeException('Primeiro executor sem bloqueio demonstrado.');
|
||||
}
|
||||
if ($scenario === 'different_operations') {
|
||||
$data['input']['operation_key'] = (string) Str::uuid();
|
||||
}
|
||||
$second = new Process([PHP_BINARY, 'tests/Concurrency/warehouse-worker.php', 'run', json_encode($data, JSON_THROW_ON_ERROR)], dirname(__DIR__), $environment, timeout: 20);
|
||||
$second->start();
|
||||
$blocked = false;
|
||||
$deadline = microtime(true) + 5;
|
||||
while ($first->isRunning() && microtime(true) < $deadline) {
|
||||
$blocked = (bool) $reader->selectOne("select exists(select 1 from pg_stat_activity where datname=? and wait_event_type='Lock') as blocked", [$database])->blocked;
|
||||
if ($blocked) {
|
||||
break;
|
||||
} usleep(20000);
|
||||
}
|
||||
$first->wait();
|
||||
$second->wait();
|
||||
$a = json_decode(trim(str_replace('locked', '', $first->getOutput())), true, 16, JSON_THROW_ON_ERROR);
|
||||
$b = json_decode(trim($second->getOutput()), true, 16, JSON_THROW_ON_ERROR);
|
||||
if (! $blocked || $a['result'] !== 'saved' || ($scenario === 'same_operation' ? ($b['result'] !== 'saved' || $a['event'] !== $b['event']) : $b['result'] !== 'rejected')) {
|
||||
throw new RuntimeException('Disputa não preservou entrega única.');
|
||||
}
|
||||
if ((int) $reader->table('warehouse_request_events')->where('warehouse_request_id', $data['request'])->where('action', 'deliver')->count() !== 1
|
||||
|| (int) $reader->table('stock_movements')->where('tenant_id', $data['tenant'])->where('stock_item_id', $data['stock'])->where('warehouse_id', $data['warehouse'])->sum('quantity_milli') !== 6000) {
|
||||
throw new RuntimeException('Movimento ou entrega duplicados.');
|
||||
}
|
||||
$races[] = ['scenario' => $scenario, 'real_lock_contention' => true, 'result' => 'passed'];
|
||||
}
|
||||
DB::purge('warehouse_proof_read');
|
||||
}
|
||||
file_put_contents(dirname(__DIR__).'/docs/proofs/'.($warehouse ? 'warehouse-drafts-pg' : ($workflow ? 'workflow-notices-pg' : 'work-context-pg')).'.json', json_encode(['checked_at' => gmdate('c'), 'database' => 'disposable PostgreSQL', 'result' => trim($process->getOutput()), 'races' => $races, 'persistent_data_changed' => false, 'database_removed_in_finally' => true], JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
|
||||
} finally {
|
||||
$admin->select('select pg_terminate_backend(pid) from pg_stat_activity where datname = ? and pid <> pg_backend_pid()', [$database]);
|
||||
$admin->statement('DROP DATABASE "'.$database.'"');
|
||||
}
|
||||
Reference in New Issue
Block a user