Files
compras/tests/Concurrency/run-common-budget.php
T

51 lines
3.8 KiB
PHP

<?php
// Coordinator: provision disposable databases via maintenance DB, never migrate/read client data.
require __DIR__.'/../../vendor/autoload.php';
foreach (['APP_ENV'=>'budget-coordinator','DB_CONNECTION'=>'pgsql','CACHE_STORE'=>'array','SESSION_DRIVER'=>'array'] as $key=>$value) { putenv($key.'='.$value); $_ENV[$key]=$_SERVER[$key]=$value; }
$app=require __DIR__.'/../../bootstrap/app.php';
$app->make(\Illuminate\Contracts\Console\Kernel::class)->bootstrap();
use Illuminate\Support\Facades\DB;
use Symfony\Component\Process\Process;
$source=DB::connection('pgsql')->getConfig();
if(($source['driver']??'')!=='pgsql'||($source['host']??'')!=='127.0.0.1')throw new LogicException('Local PostgreSQL maintenance connection required.');
$maintenance=[...$source,'database'=>'postgres','url'=>null];
config(['database.connections.budget_admin'=>$maintenance]);
$admin=DB::connection('budget_admin')->getPdo();
$sgf=realpath(base_path('../sgf-tempo'));
$script=$sgf.'/packages/budget-control/tests/run-host.php';
$report=['version'=>'COMMON-BUDGET-SYNTHETIC-v1','checked_at'=>gmdate('c'),'client_databases_touched'=>false,'hosts'=>[]];
$artifact=sys_get_temp_dir().'/common-budget-artifact-'.bin2hex(random_bytes(6));
if(!mkdir($artifact.'/src',0700,true))throw new RuntimeException('Cannot prepare isolated package artifact.');
$artifactFiles=['bootstrap.php','src/BudgetContext.php','src/BudgetFailure.php','src/BudgetControl.php'];
foreach($artifactFiles as $file)if(!copy($sgf.'/packages/budget-control/'.$file,$artifact.'/'.$file))throw new RuntimeException('Cannot build package artifact.');
try {
foreach(['compras','sgf'] as $mode){
$db=($mode==='compras'?'compras_receipts_test_':'budget_core_sgf_').bin2hex(random_bytes(6));
$created=false;
try{
$admin->exec('CREATE DATABASE "'.$db.'"');$created=true;
$environment=['APP_ENV'=>$mode==='compras'?'testing':'budget-testing','DB_CONNECTION'=>'pgsql','DB_DATABASE'=>$db,'DB_URL'=>'','DB_HOST'=>'127.0.0.1','DB_PORT'=>(string)$source['port'],'DB_USERNAME'=>$source['username'],'DB_PASSWORD'=>$source['password'],'CACHE_STORE'=>'array','SESSION_DRIVER'=>'array','QUEUE_CONNECTION'=>'sync','MAIL_MAILER'=>'array','BCRYPT_ROUNDS'=>'4','COMMON_BUDGET_PATH'=>$mode==='compras'?$artifact:$sgf.'/packages/budget-control'];
$php=$mode==='compras'?PHP_BINARY:'C:/laragon/tools/sgf-tempo/php-8.4.27/php.exe';
$root=$mode==='compras'?base_path():$sgf;
$process=new Process([$php,$script,$root,$mode],$root,$environment);$process->setTimeout(120);$process->run();
if(!$process->isSuccessful())throw new RuntimeException('QA host failed: '.$process->getOutput().$process->getErrorOutput());
$report['hosts'][]=json_decode($process->getOutput(),true,64,JSON_THROW_ON_ERROR);
}finally{
if(isset($process)&&$process->isRunning())$process->stop();
if($created){
$stmt=$admin->prepare('SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname=? AND pid<>pg_backend_pid()');$stmt->execute([$db]);
$admin->exec('DROP DATABASE "'.$db.'"');
}
}
}
} finally {
// Delete only the exact files created above, never a recursive or computed project path.
foreach($artifactFiles as $file)if(is_file($artifact.'/'.$file))unlink($artifact.'/'.$file);
rmdir($artifact.'/src');rmdir($artifact);
}
if($report['hosts'][0]['core_sha256']!==$report['hosts'][1]['core_sha256']||$report['hosts'][0]['steps']!==$report['hosts'][1]['steps'])throw new RuntimeException('Host equivalence failed.');
$report['equivalent']=true;$report['disposable_databases_dropped']=true;
file_put_contents($sgf.'/docs/proofs/common-budget-hosts.json',json_encode($report,JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR).PHP_EOL);
echo "Two Laravel hosts passed the same core sequence and PostgreSQL concurrency checks. Disposable databases dropped.\n";