fix: DockerSecretsResolver - don't normalize absolute paths like /var/www/html/...
Some checks failed
Deploy Application / deploy (push) Has been cancelled
Some checks failed
Deploy Application / deploy (push) Has been cancelled
This commit is contained in:
153
tests/Unit/Framework/DI/InitializerDependencyGraphTest.php
Normal file
153
tests/Unit/Framework/DI/InitializerDependencyGraphTest.php
Normal file
@@ -0,0 +1,153 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Unit\Framework\DI;
|
||||
|
||||
use App\Framework\Core\ValueObjects\ClassName;
|
||||
use App\Framework\Core\ValueObjects\MethodName;
|
||||
use App\Framework\DI\Exceptions\InitializerCycleException;
|
||||
use App\Framework\DI\InitializerDependencyAnalyzer;
|
||||
use App\Framework\DI\InitializerDependencyGraph;
|
||||
use App\Framework\Reflection\ReflectionService;
|
||||
use App\Framework\Reflection\SimpleReflectionService;
|
||||
|
||||
describe('InitializerDependencyGraph', function () {
|
||||
it('can add initializers and build execution order', function () {
|
||||
$reflectionService = new SimpleReflectionService();
|
||||
$graph = new InitializerDependencyGraph($reflectionService);
|
||||
|
||||
$graph->addInitializer(
|
||||
'ServiceA',
|
||||
ClassName::create('App\Test\ServiceAInitializer'),
|
||||
MethodName::create('__invoke')
|
||||
);
|
||||
|
||||
$graph->addInitializer(
|
||||
'ServiceB',
|
||||
ClassName::create('App\Test\ServiceBInitializer'),
|
||||
MethodName::create('__invoke')
|
||||
);
|
||||
|
||||
expect($graph->hasNode('ServiceA'))->toBeTrue();
|
||||
expect($graph->hasNode('ServiceB'))->toBeTrue();
|
||||
expect($graph->hasNode('ServiceC'))->toBeFalse();
|
||||
});
|
||||
|
||||
it('uses explicit dependencies when provided', function () {
|
||||
$reflectionService = new SimpleReflectionService();
|
||||
$graph = new InitializerDependencyGraph($reflectionService);
|
||||
|
||||
$graph->addInitializer(
|
||||
'ServiceA',
|
||||
ClassName::create('App\Test\ServiceAInitializer'),
|
||||
MethodName::create('__invoke'),
|
||||
['ServiceB', 'ServiceC'], // Explicit dependencies
|
||||
100 // Priority
|
||||
);
|
||||
|
||||
$node = $graph->getNode('ServiceA');
|
||||
expect($node)->not->toBeNull();
|
||||
expect($node->dependencies)->toBe(['ServiceB', 'ServiceC']);
|
||||
});
|
||||
|
||||
it('detects circular dependencies', function () {
|
||||
$reflectionService = new SimpleReflectionService();
|
||||
$graph = new InitializerDependencyGraph($reflectionService);
|
||||
|
||||
// Create a cycle: A -> B -> A
|
||||
$graph->addInitializer(
|
||||
'ServiceA',
|
||||
ClassName::create('App\Test\ServiceAInitializer'),
|
||||
MethodName::create('__invoke'),
|
||||
['ServiceB'] // A depends on B
|
||||
);
|
||||
|
||||
$graph->addInitializer(
|
||||
'ServiceB',
|
||||
ClassName::create('App\Test\ServiceBInitializer'),
|
||||
MethodName::create('__invoke'),
|
||||
['ServiceA'] // B depends on A (cycle!)
|
||||
);
|
||||
|
||||
expect(fn() => $graph->getExecutionOrder())->toThrow(InitializerCycleException::class);
|
||||
});
|
||||
|
||||
it('provides cycle information with dependency paths', function () {
|
||||
$reflectionService = new SimpleReflectionService();
|
||||
$graph = new InitializerDependencyGraph($reflectionService);
|
||||
|
||||
// Create a cycle: A -> B -> A
|
||||
$graph->addInitializer(
|
||||
'ServiceA',
|
||||
ClassName::create('App\Test\ServiceAInitializer'),
|
||||
MethodName::create('__invoke'),
|
||||
['ServiceB']
|
||||
);
|
||||
|
||||
$graph->addInitializer(
|
||||
'ServiceB',
|
||||
ClassName::create('App\Test\ServiceBInitializer'),
|
||||
MethodName::create('__invoke'),
|
||||
['ServiceA']
|
||||
);
|
||||
|
||||
try {
|
||||
$graph->getExecutionOrder();
|
||||
expect(false)->toBeTrue(); // Should not reach here
|
||||
} catch (InitializerCycleException $e) {
|
||||
$cycles = $e->getCycles();
|
||||
expect($cycles)->not->toBeEmpty();
|
||||
|
||||
$paths = $e->getDependencyPaths();
|
||||
expect($paths)->not->toBeEmpty();
|
||||
}
|
||||
});
|
||||
|
||||
it('calculates correct execution order for linear dependencies', function () {
|
||||
$reflectionService = new SimpleReflectionService();
|
||||
$graph = new InitializerDependencyGraph($reflectionService);
|
||||
|
||||
// C depends on B, B depends on A
|
||||
$graph->addInitializer(
|
||||
'ServiceA',
|
||||
ClassName::create('App\Test\ServiceAInitializer'),
|
||||
MethodName::create('__invoke'),
|
||||
[] // No dependencies
|
||||
);
|
||||
|
||||
$graph->addInitializer(
|
||||
'ServiceB',
|
||||
ClassName::create('App\Test\ServiceBInitializer'),
|
||||
MethodName::create('__invoke'),
|
||||
['ServiceA'] // B depends on A
|
||||
);
|
||||
|
||||
$graph->addInitializer(
|
||||
'ServiceC',
|
||||
ClassName::create('App\Test\ServiceCInitializer'),
|
||||
MethodName::create('__invoke'),
|
||||
['ServiceB'] // C depends on B
|
||||
);
|
||||
|
||||
$order = $graph->getExecutionOrder();
|
||||
|
||||
// A should come before B, B should come before C
|
||||
$indexA = array_search('ServiceA', $order, true);
|
||||
$indexB = array_search('ServiceB', $order, true);
|
||||
$indexC = array_search('ServiceC', $order, true);
|
||||
|
||||
expect($indexA)->toBeLessThan($indexB);
|
||||
expect($indexB)->toBeLessThan($indexC);
|
||||
});
|
||||
|
||||
it('integrates with InitializerDependencyAnalyzer when provided', function () {
|
||||
$reflectionService = new SimpleReflectionService();
|
||||
$analyzer = new InitializerDependencyAnalyzer(null);
|
||||
$graph = new InitializerDependencyGraph($reflectionService, $analyzer);
|
||||
|
||||
// Graph should accept analyzer without errors
|
||||
expect($graph)->toBeInstanceOf(InitializerDependencyGraph::class);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user