capturedRecords = []; // Test-Handler der alle Records captured $testHandler = new class ($this->capturedRecords) implements LogHandler { public function __construct(private array &$records) { } public function isHandling(LogRecord $record): bool { return true; } public function handle(LogRecord $record): void { $this->records[] = $record; } }; $this->logger = new DefaultLogger( minLevel: LogLevel::DEBUG, handlers: [$testHandler], processorManager: new ProcessorManager() ); } public function test_channel_system_basic_functionality(): void { // Teste alle Channel-Logger $this->logger->channel(LogChannel::SECURITY)->warning('Security alert', LogContext::withData(['ip' => '192.168.1.1'])); $this->logger->channel(LogChannel::CACHE)->debug('Cache miss', LogContext::withData(['key' => 'user_123'])); $this->logger->channel(LogChannel::DATABASE)->error('Query failed', LogContext::withData(['table' => 'users'])); $this->logger->channel(LogChannel::FRAMEWORK)->info('Route registered', LogContext::withData(['path' => '/api/test'])); $this->logger->channel(LogChannel::ERROR)->critical('System failure', LogContext::withData(['component' => 'auth'])); expect($this->capturedRecords)->toHaveCount(5); // Prüfe Channels expect($this->capturedRecords[0]->getChannel())->toBe('security'); expect($this->capturedRecords[1]->getChannel())->toBe('cache'); expect($this->capturedRecords[2]->getChannel())->toBe('database'); expect($this->capturedRecords[3]->getChannel())->toBe('framework'); expect($this->capturedRecords[4]->getChannel())->toBe('error'); // Prüfe Messages expect($this->capturedRecords[0]->getMessage())->toBe('Security alert'); expect($this->capturedRecords[1]->getMessage())->toBe('Cache miss'); expect($this->capturedRecords[2]->getMessage())->toBe('Query failed'); expect($this->capturedRecords[3]->getMessage())->toBe('Route registered'); expect($this->capturedRecords[4]->getMessage())->toBe('System failure'); // Prüfe Levels expect($this->capturedRecords[0]->getLevel())->toBe(LogLevel::WARNING); expect($this->capturedRecords[1]->getLevel())->toBe(LogLevel::DEBUG); expect($this->capturedRecords[2]->getLevel())->toBe(LogLevel::ERROR); expect($this->capturedRecords[3]->getLevel())->toBe(LogLevel::INFO); expect($this->capturedRecords[4]->getLevel())->toBe(LogLevel::CRITICAL); } public function test_standard_logging_vs_channel_logging(): void { // Standard-Logging $this->logger->info('Standard log'); // Channel-Logging $this->logger->channel(LogChannel::SECURITY)->info('Channel log'); expect($this->capturedRecords)->toHaveCount(2); // Standard-Log hat keinen Channel expect($this->capturedRecords[0]->getChannel())->toBeNull(); expect($this->capturedRecords[0]->getMessage())->toBe('Standard log'); // Channel-Log hat Channel expect($this->capturedRecords[1]->getChannel())->toBe('security'); expect($this->capturedRecords[1]->getMessage())->toBe('Channel log'); } public function test_all_log_levels_work_with_channels(): void { $this->logger->channel(LogChannel::SECURITY)->debug('Debug message'); $this->logger->channel(LogChannel::SECURITY)->info('Info message'); $this->logger->channel(LogChannel::SECURITY)->notice('Notice message'); $this->logger->channel(LogChannel::SECURITY)->warning('Warning message'); $this->logger->channel(LogChannel::SECURITY)->error('Error message'); $this->logger->channel(LogChannel::SECURITY)->critical('Critical message'); $this->logger->channel(LogChannel::SECURITY)->alert('Alert message'); $this->logger->channel(LogChannel::SECURITY)->emergency('Emergency message'); expect($this->capturedRecords)->toHaveCount(8); $expectedLevels = [ LogLevel::DEBUG, LogLevel::INFO, LogLevel::NOTICE, LogLevel::WARNING, LogLevel::ERROR, LogLevel::CRITICAL, LogLevel::ALERT, LogLevel::EMERGENCY, ]; foreach ($this->capturedRecords as $index => $record) { expect($record->getChannel())->toBe('security'); expect($record->getLevel())->toBe($expectedLevels[$index]); } } public function test_context_data_passed_correctly(): void { $context = LogContext::withData([ 'user_id' => 123, 'action' => 'login', 'metadata' => ['ip' => '127.0.0.1', 'browser' => 'Chrome'], ]); $this->logger->channel(LogChannel::SECURITY)->warning('Authentication event', $context); expect($this->capturedRecords)->toHaveCount(1); expect($this->capturedRecords[0]->getContext())->toMatchArray([ 'user_id' => 123, 'action' => 'login', 'metadata' => ['ip' => '127.0.0.1', 'browser' => 'Chrome'], ]); expect($this->capturedRecords[0]->getChannel())->toBe('security'); } public function test_channel_isolation(): void { // Jeder Channel sollte unabhängig funktionieren $this->logger->channel(LogChannel::SECURITY)->error('Security error'); $this->logger->channel(LogChannel::CACHE)->error('Cache error'); $this->logger->channel(LogChannel::DATABASE)->error('Database error'); expect($this->capturedRecords)->toHaveCount(3); // Alle sollten ERROR level haben, aber verschiedene Channels foreach ($this->capturedRecords as $record) { expect($record->getLevel())->toBe(LogLevel::ERROR); } expect($this->capturedRecords[0]->getChannel())->toBe('security'); expect($this->capturedRecords[1]->getChannel())->toBe('cache'); expect($this->capturedRecords[2]->getChannel())->toBe('database'); expect($this->capturedRecords[0]->getMessage())->toBe('Security error'); expect($this->capturedRecords[1]->getMessage())->toBe('Cache error'); expect($this->capturedRecords[2]->getMessage())->toBe('Database error'); } public function test_channel_enum_integration(): void { // Teste dass die Channels den Enum-Werten entsprechen expect($this->logger->channel(LogChannel::SECURITY)->channel)->toBe(LogChannel::SECURITY); expect($this->logger->channel(LogChannel::CACHE)->channel)->toBe(LogChannel::CACHE); expect($this->logger->channel(LogChannel::DATABASE)->channel)->toBe(LogChannel::DATABASE); expect($this->logger->channel(LogChannel::FRAMEWORK)->channel)->toBe(LogChannel::FRAMEWORK); expect($this->logger->channel(LogChannel::ERROR)->channel)->toBe(LogChannel::ERROR); // Teste dass die Channel-Namen korrekt sind expect(LogChannel::SECURITY->value)->toBe('security'); expect(LogChannel::CACHE->value)->toBe('cache'); expect(LogChannel::DATABASE->value)->toBe('database'); expect(LogChannel::FRAMEWORK->value)->toBe('framework'); expect(LogChannel::ERROR->value)->toBe('error'); } public function test_realistic_usage_scenario(): void { // Simuliere eine realistische Anwendungssequenz // 1. Framework startet $this->logger->channel(LogChannel::FRAMEWORK)->info('Application starting'); // 2. User versucht Login $this->logger->channel(LogChannel::SECURITY)->info('Login attempt', LogContext::withData(['email' => 'user@test.com'])); // 3. Cache Miss $this->logger->channel(LogChannel::CACHE)->debug('User cache miss', LogContext::withData(['email' => 'user@test.com'])); // 4. Database Query $this->logger->channel(LogChannel::DATABASE)->debug('User lookup query', LogContext::withData(['table' => 'users'])); // 5. Successful authentication $this->logger->channel(LogChannel::SECURITY)->info('Login successful', LogContext::withData(['user_id' => 42])); // 6. Cache Store $this->logger->channel(LogChannel::CACHE)->info('User cached', LogContext::withData(['user_id' => 42, 'ttl' => 3600])); // 7. Später: Ein Fehler $this->logger->channel(LogChannel::DATABASE)->error('Connection timeout', LogContext::withData(['host' => 'db.example.com'])); $this->logger->channel(LogChannel::ERROR)->critical('Service degraded', LogContext::withData(['affected' => ['users', 'orders']])); expect($this->capturedRecords)->toHaveCount(8); // Prüfe die Sequenz $channels = array_map(fn ($record) => $record->getChannel(), $this->capturedRecords); $expected = ['framework', 'security', 'cache', 'database', 'security', 'cache', 'database', 'error']; expect($channels)->toBe($expected); // Prüfe dass jeder Record den richtigen Channel hat foreach ($this->capturedRecords as $index => $record) { expect($record->getChannel())->toBe($expected[$index]); } } }