Files
michaelschiemer/tests/debug/test-default-implementation.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

257 lines
8.6 KiB
PHP

<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use App\Framework\Core\ValueObjects\ClassName;
use App\Framework\DI\Attributes\DefaultImplementation;
use App\Framework\DI\DefaultContainer;
use App\Framework\DI\DefaultImplementationProcessor;
use App\Framework\DI\Exceptions\DefaultImplementationException;
use App\Framework\Discovery\Results\AttributeRegistry;
use App\Framework\Discovery\Results\DiscoveryRegistry;
use App\Framework\Discovery\ValueObjects\AttributeTarget;
use App\Framework\Discovery\ValueObjects\DiscoveredAttribute;
// Test Interfaces
interface UserRepository
{
public function findById(string $id): ?object;
}
interface LoggerInterface
{
public function log(string $message): void;
}
interface FormattableInterface
{
public function format(): string;
}
// Test Classes
// Scenario 1: Explicit interface specification
#[DefaultImplementation(UserRepository::class)]
final readonly class DatabaseUserRepository implements UserRepository
{
public function findById(string $id): ?object
{
return (object) ['id' => $id, 'name' => 'Test User'];
}
}
// Scenario 2: Auto-detect single interface
#[DefaultImplementation]
final readonly class FileUserRepository implements UserRepository
{
public function findById(string $id): ?object
{
return (object) ['id' => $id, 'name' => 'File User'];
}
}
// Scenario 3: Auto-detect with multiple interfaces (should use first)
#[DefaultImplementation]
final readonly class AppLogger implements LoggerInterface, FormattableInterface
{
public function log(string $message): void
{
echo "[LOG] $message\n";
}
public function format(): string
{
return 'AppLogger';
}
}
// Scenario 4: Invalid - explicit interface not implemented (for error testing)
#[DefaultImplementation(LoggerInterface::class)]
final readonly class BadRepository implements UserRepository
{
public function findById(string $id): ?object
{
return null;
}
}
// Scenario 5: Invalid - no interfaces implemented (for error testing)
#[DefaultImplementation]
final readonly class NoInterfaceClass
{
public function doSomething(): void {}
}
// Helper function to create DiscoveredAttribute
function createDiscoveredAttribute(string $className, array $attributeArgs = []): DiscoveredAttribute
{
return new DiscoveredAttribute(
className: ClassName::create($className),
attributeClass: DefaultImplementation::class,
target: AttributeTarget::TARGET_CLASS,
arguments: $attributeArgs
);
}
// Helper function to create DiscoveryRegistry with specific attributes
function createRegistryWithAttributes(array $discoveredAttributes): DiscoveryRegistry
{
$attributeRegistry = new AttributeRegistry();
foreach ($discoveredAttributes as $attr) {
$attributeRegistry->add(DefaultImplementation::class, $attr);
}
return new DiscoveryRegistry(
attributes: $attributeRegistry,
interfaces: new \App\Framework\Discovery\Results\InterfaceRegistry(),
templates: new \App\Framework\Discovery\Results\TemplateRegistry()
);
}
// Test Runner
echo "=== DefaultImplementation Attribute Tests ===\n\n";
// Test 1: Explicit Interface Specification
echo "Test 1: Explicit interface specification\n";
try {
$container = new DefaultContainer();
$processor = new DefaultImplementationProcessor($container);
$discovered = createDiscoveredAttribute(DatabaseUserRepository::class, ['interface' => UserRepository::class]);
$registry = createRegistryWithAttributes([$discovered]);
$registered = $processor->process($registry);
echo "✓ Registered $registered binding(s)\n";
echo "✓ Container has binding: " . ($container->has(UserRepository::class) ? 'YES' : 'NO') . "\n";
$instance = $container->get(UserRepository::class);
echo "✓ Instance type: " . get_class($instance) . "\n";
echo "✓ Find user: " . json_encode($instance->findById('123')) . "\n";
echo "PASSED\n\n";
} catch (\Exception $e) {
echo "✗ FAILED: " . $e->getMessage() . "\n\n";
}
// Test 2: Auto-detect Single Interface
echo "Test 2: Auto-detect single interface\n";
try {
$container = new DefaultContainer();
$processor = new DefaultImplementationProcessor($container);
$discovered = createDiscoveredAttribute(FileUserRepository::class, []); // No explicit interface
$registry = createRegistryWithAttributes([$discovered]);
$registered = $processor->process($registry);
echo "✓ Registered $registered binding(s)\n";
echo "✓ Container has binding: " . ($container->has(UserRepository::class) ? 'YES' : 'NO') . "\n";
$instance = $container->get(UserRepository::class);
echo "✓ Instance type: " . get_class($instance) . "\n";
echo "PASSED\n\n";
} catch (\Exception $e) {
echo "✗ FAILED: " . $e->getMessage() . "\n\n";
}
// Test 3: Auto-detect Multiple Interfaces (uses first)
echo "Test 3: Auto-detect with multiple interfaces\n";
try {
$container = new DefaultContainer();
$processor = new DefaultImplementationProcessor($container);
$discovered = createDiscoveredAttribute(AppLogger::class, []);
$registry = createRegistryWithAttributes([$discovered]);
$registered = $processor->process($registry);
echo "✓ Registered $registered binding(s)\n";
echo "✓ Container has LoggerInterface: " . ($container->has(LoggerInterface::class) ? 'YES' : 'NO') . "\n";
$instance = $container->get(LoggerInterface::class);
echo "✓ Instance type: " . get_class($instance) . "\n";
$instance->log("Test message");
echo "PASSED\n\n";
} catch (\Exception $e) {
echo "✗ FAILED: " . $e->getMessage() . "\n\n";
}
// Test 4: Error - Explicit Interface Not Implemented
echo "Test 4: Error - explicit interface not implemented\n";
try {
$container = new DefaultContainer();
$processor = new DefaultImplementationProcessor($container);
$discovered = createDiscoveredAttribute(BadRepository::class, ['interface' => LoggerInterface::class]);
$registry = createRegistryWithAttributes([$discovered]);
$processor->process($registry);
echo "✗ FAILED: Should have thrown exception\n\n";
} catch (DefaultImplementationException $e) {
echo "✓ Caught expected exception: " . $e->getMessage() . "\n";
echo "PASSED\n\n";
}
// Test 5: Error - No Interfaces Implemented
echo "Test 5: Error - no interfaces implemented\n";
try {
$container = new DefaultContainer();
$processor = new DefaultImplementationProcessor($container);
$discovered = createDiscoveredAttribute(NoInterfaceClass::class, []);
$registry = createRegistryWithAttributes([$discovered]);
$processor->process($registry);
echo "✗ FAILED: Should have thrown exception\n\n";
} catch (DefaultImplementationException $e) {
echo "✓ Caught expected exception: " . $e->getMessage() . "\n";
echo "PASSED\n\n";
}
// Test 6: Multiple Bindings
echo "Test 6: Multiple bindings in one registry\n";
try {
$container = new DefaultContainer();
$processor = new DefaultImplementationProcessor($container);
$discovered1 = createDiscoveredAttribute(DatabaseUserRepository::class, ['interface' => UserRepository::class]);
$discovered2 = createDiscoveredAttribute(AppLogger::class, []);
$registry = createRegistryWithAttributes([$discovered1, $discovered2]);
$registered = $processor->process($registry);
echo "✓ Registered $registered binding(s)\n";
echo "✓ Has UserRepository: " . ($container->has(UserRepository::class) ? 'YES' : 'NO') . "\n";
echo "✓ Has LoggerInterface: " . ($container->has(LoggerInterface::class) ? 'YES' : 'NO') . "\n";
echo "PASSED\n\n";
} catch (\Exception $e) {
echo "✗ FAILED: " . $e->getMessage() . "\n\n";
}
// Test 7: Singleton Registration (verify it's actually singleton)
echo "Test 7: Singleton registration verification\n";
try {
$container = new DefaultContainer();
$processor = new DefaultImplementationProcessor($container);
$discovered = createDiscoveredAttribute(DatabaseUserRepository::class, ['interface' => UserRepository::class]);
$registry = createRegistryWithAttributes([$discovered]);
$processor->process($registry);
$instance1 = $container->get(UserRepository::class);
$instance2 = $container->get(UserRepository::class);
echo "✓ Instance 1 ID: " . spl_object_id($instance1) . "\n";
echo "✓ Instance 2 ID: " . spl_object_id($instance2) . "\n";
echo "✓ Same instance: " . ($instance1 === $instance2 ? 'YES' : 'NO') . "\n";
echo "PASSED\n\n";
} catch (\Exception $e) {
echo "✗ FAILED: " . $e->getMessage() . "\n\n";
}
echo "=== All Tests Complete ===\n";