Files
michaelschiemer/tests/Unit/Framework/Async/AsyncPoolTest.php
Michael Schiemer fc3d7e6357 feat(Production): Complete production deployment infrastructure
- Add comprehensive health check system with multiple endpoints
- Add Prometheus metrics endpoint
- Add production logging configurations (5 strategies)
- Add complete deployment documentation suite:
  * QUICKSTART.md - 30-minute deployment guide
  * DEPLOYMENT_CHECKLIST.md - Printable verification checklist
  * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle
  * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference
  * production-logging.md - Logging configuration guide
  * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation
  * README.md - Navigation hub
  * DEPLOYMENT_SUMMARY.md - Executive summary
- Add deployment scripts and automation
- Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment
- Update README with production-ready features

All production infrastructure is now complete and ready for deployment.
2025-10-25 19:18:37 +02:00

131 lines
4.0 KiB
PHP

<?php
declare(strict_types=1);
namespace Tests\Unit\Framework\Async;
use App\Framework\Async\AsyncPool;
use App\Framework\Async\FiberManager;
use App\Framework\DateTime\SystemClock;
use App\Framework\DateTime\SystemTimer;
describe('AsyncPool', function () {
beforeEach(function () {
$clock = new SystemClock();
$timer = new SystemTimer();
$fiberManager = new FiberManager($clock, $timer);
$this->pool = new AsyncPool($fiberManager, maxConcurrency: 3);
});
it('executes operations with limited concurrency', function () {
$executedOperations = [];
for ($i = 1; $i <= 10; $i++) {
$this->pool->add(function () use ($i, &$executedOperations) {
$executedOperations[] = $i;
return "result-{$i}";
}, "op{$i}");
}
$results = $this->pool->execute();
expect(count($results))->toBe(10);
expect($results['op1'])->toBe('result-1');
expect($results['op10'])->toBe('result-10');
});
it('respects max concurrency limit', function () {
$stats = $this->pool->getStats();
expect($stats['max_concurrency'])->toBe(3);
expect($stats['pending'])->toBe(0);
expect($stats['active'])->toBe(0);
expect($stats['completed'])->toBe(0);
});
it('tracks operation statistics', function () {
$this->pool->add(fn() => 'test1', 'op1');
$this->pool->add(fn() => 'test2', 'op2');
$statsBefore = $this->pool->getStats();
expect($statsBefore['pending'])->toBe(2);
$this->pool->execute();
$statsAfter = $this->pool->getStats();
expect($statsAfter['completed'])->toBe(2);
expect($statsAfter['pending'])->toBe(0);
});
it('awaits specific operation result', function () {
$this->pool->add(fn() => 'result-1', 'op1');
$this->pool->add(fn() => 'result-2', 'op2');
// Start execution in background
$this->pool->execute();
$result = $this->pool->await('op1');
expect($result)->toBe('result-1');
});
it('handles exceptions in operations', function () {
// Test that exceptions during execution are caught and stored as results
$this->pool->add(fn() => 'success', 'op1');
$this->pool->add(function () {
throw new \RuntimeException('error');
}, 'op2');
// Execute all operations - exceptions are caught and stored as results
$results = $this->pool->execute();
expect($results['op1'])->toBe('success');
expect($results['op2'])->toBeInstanceOf(\RuntimeException::class);
expect($results['op2']->getMessage())->toBe('error');
});
it('generates unique IDs when not provided', function () {
$id1 = $this->pool->add(fn() => 'test1');
$id2 = $this->pool->add(fn() => 'test2');
expect($id1)->not->toBe($id2);
expect(str_starts_with($id1, 'pool_'))->toBeTrue();
expect(str_starts_with($id2, 'pool_'))->toBeTrue();
});
it('executes all operations eventually', function () {
$completed = [];
for ($i = 1; $i <= 50; $i++) {
$this->pool->add(function () use ($i, &$completed) {
usleep(1000); // 1ms delay
$completed[] = $i;
return $i;
});
}
$results = $this->pool->execute();
expect(count($results))->toBe(50);
expect(count($completed))->toBe(50);
});
it('maintains operation order in results', function () {
$operations = [
'first' => fn() => 'first-result',
'second' => fn() => 'second-result',
'third' => fn() => 'third-result',
];
foreach ($operations as $id => $operation) {
$this->pool->add($operation, $id);
}
$results = $this->pool->execute();
expect($results['first'])->toBe('first-result');
expect($results['second'])->toBe('second-result');
expect($results['third'])->toBe('third-result');
});
});