testLogDir = sys_get_temp_dir() . '/integration_logs_' . uniqid(); mkdir($this->testLogDir, 0755, true); // PathProvider Mock $pathProvider = $this->createMock(PathProvider::class); $pathProvider->method('resolvePath')->willReturnCallback(function (string $path) { return $this->testLogDir . '/' . $path; }); // LogConfig Mock $this->logConfig = $this->createMock(LogConfig::class); $this->logConfig->method('getLogPath')->willReturnCallback(function (string $type) { return match ($type) { 'security' => $this->testLogDir . '/security/security.log', 'cache' => $this->testLogDir . '/debug/cache.log', 'database' => $this->testLogDir . '/debug/database.log', 'framework' => $this->testLogDir . '/debug/framework.log', 'error' => $this->testLogDir . '/app/error.log', default => $this->testLogDir . '/app/app.log' }; }); // MultiFileHandler $multiFileHandler = new MultiFileHandler( $this->logConfig, $pathProvider, LogLevel::DEBUG, '[{timestamp}] [{level_name}] [{channel}] {message}' ); // DefaultLogger mit echtem MultiFileHandler $this->logger = new DefaultLogger( minLevel: LogLevel::DEBUG, handlers: [$multiFileHandler], processorManager: new ProcessorManager() ); } protected function tearDown(): void { // Cleanup: Test-Verzeichnis löschen if (is_dir($this->testLogDir)) { $this->deleteDirectory($this->testLogDir); } } private function deleteDirectory(string $dir): void { if (! is_dir($dir)) { return; } $files = array_diff(scandir($dir), ['.', '..']); foreach ($files as $file) { $path = $dir . '/' . $file; is_dir($path) ? $this->deleteDirectory($path) : unlink($path); } rmdir($dir); } public function test_complete_channel_system_integration(): void { // Verschiedene Channel-Logs erstellen $this->logger->security->warning('Failed login attempt', ['email' => 'test@example.com', 'ip' => '192.168.1.1']); $this->logger->cache->debug('Cache miss', ['key' => 'user_123']); $this->logger->database->error('Query timeout', ['query' => 'SELECT * FROM users', 'duration' => 30.5]); $this->logger->framework->info('Route registered', ['route' => '/api/users', 'method' => 'GET']); $this->logger->error->critical('System failure', ['component' => 'payment', 'error_code' => 'PAY_001']); // Alle Log-Dateien sollten erstellt worden sein expect(file_exists($this->testLogDir . '/security/security.log'))->toBeTrue(); expect(file_exists($this->testLogDir . '/debug/cache.log'))->toBeTrue(); expect(file_exists($this->testLogDir . '/debug/database.log'))->toBeTrue(); expect(file_exists($this->testLogDir . '/debug/framework.log'))->toBeTrue(); expect(file_exists($this->testLogDir . '/app/error.log'))->toBeTrue(); // Security Log Inhalt prüfen $securityContent = file_get_contents($this->testLogDir . '/security/security.log'); expect($securityContent)->toContain('[WARNING] [security] Failed login attempt'); expect($securityContent)->toContain('"email":"test@example.com"'); expect($securityContent)->toContain('"ip":"192.168.1.1"'); // Cache Log Inhalt prüfen $cacheContent = file_get_contents($this->testLogDir . '/debug/cache.log'); expect($cacheContent)->toContain('[DEBUG] [cache] Cache miss'); expect($cacheContent)->toContain('"key":"user_123"'); // Database Log Inhalt prüfen $databaseContent = file_get_contents($this->testLogDir . '/debug/database.log'); expect($databaseContent)->toContain('[ERROR] [database] Query timeout'); expect($databaseContent)->toContain('"query":"SELECT * FROM users"'); expect($databaseContent)->toContain('"duration":30.5'); // Framework Log Inhalt prüfen $frameworkContent = file_get_contents($this->testLogDir . '/debug/framework.log'); expect($frameworkContent)->toContain('[INFO] [framework] Route registered'); expect($frameworkContent)->toContain('"route":"\/api\/users"'); expect($frameworkContent)->toContain('"method":"GET"'); // Error Log Inhalt prüfen $errorContent = file_get_contents($this->testLogDir . '/app/error.log'); expect($errorContent)->toContain('[CRITICAL] [error] System failure'); expect($errorContent)->toContain('"component":"payment"'); expect($errorContent)->toContain('"error_code":"PAY_001"'); } public function test_mixed_standard_and_channel_logging(): void { // Mix aus Standard-Logging und Channel-Logging $this->logger->info('Standard application log'); $this->logger->security->error('Security incident'); $this->logger->warning('Another standard log'); $this->logger->cache->info('Cache operation'); // Standard-Logs sollten nicht in den spezifischen Channel-Dateien landen expect(file_exists($this->testLogDir . '/security/security.log'))->toBeTrue(); expect(file_exists($this->testLogDir . '/debug/cache.log'))->toBeTrue(); // Security Log sollte nur Security-spezifische Einträge haben $securityContent = file_get_contents($this->testLogDir . '/security/security.log'); expect($securityContent)->toContain('Security incident'); expect($securityContent)->not->toContain('Standard application log'); expect($securityContent)->not->toContain('Another standard log'); // Cache Log sollte nur Cache-spezifische Einträge haben $cacheContent = file_get_contents($this->testLogDir . '/debug/cache.log'); expect($cacheContent)->toContain('Cache operation'); expect($cacheContent)->not->toContain('Standard application log'); expect($cacheContent)->not->toContain('Security incident'); } public function test_multiple_entries_same_channel(): void { // Mehrere Einträge in den gleichen Channel $this->logger->security->info('User login', ['user_id' => 123]); $this->logger->security->warning('Suspicious activity', ['user_id' => 123, 'actions' => ['login', 'password_change']]); $this->logger->security->error('Account locked', ['user_id' => 123, 'reason' => 'too_many_attempts']); $securityFile = $this->testLogDir . '/security/security.log'; expect(file_exists($securityFile))->toBeTrue(); $content = file_get_contents($securityFile); $lines = explode("\n", trim($content)); // Drei Zeilen sollten vorhanden sein expect($lines)->toHaveCount(3); expect($content)->toContain('[INFO] [security] User login'); expect($content)->toContain('[WARNING] [security] Suspicious activity'); expect($content)->toContain('[ERROR] [security] Account locked'); // Alle Einträge sollten user_id 123 enthalten expect($content)->toContain('"user_id":123'); } public function test_channel_system_with_different_log_levels(): void { // Verschiedene Log-Level in verschiedenen Channels $this->logger->cache->debug('Debug cache operation'); $this->logger->security->info('Info security event'); $this->logger->database->warning('Warning database issue'); $this->logger->framework->error('Error in framework'); $this->logger->error->critical('Critical system error'); // Alle Dateien sollten existieren $files = [ 'cache' => $this->testLogDir . '/debug/cache.log', 'security' => $this->testLogDir . '/security/security.log', 'database' => $this->testLogDir . '/debug/database.log', 'framework' => $this->testLogDir . '/debug/framework.log', 'error' => $this->testLogDir . '/app/error.log', ]; foreach ($files as $channel => $file) { expect(file_exists($file))->toBeTrue("File for {$channel} channel should exist"); } // Level sollten korrekt sein expect(file_get_contents($files['cache']))->toContain('[DEBUG]'); expect(file_get_contents($files['security']))->toContain('[INFO]'); expect(file_get_contents($files['database']))->toContain('[WARNING]'); expect(file_get_contents($files['framework']))->toContain('[ERROR]'); expect(file_get_contents($files['error']))->toContain('[CRITICAL]'); } public function test_realistic_application_scenario(): void { // Simuliere eine realistische Anwendungsszenario // User Authentication Flow $this->logger->security->info('Authentication attempt started', ['email' => 'user@example.com']); $this->logger->cache->debug('Checking user cache', ['cache_key' => 'user_user@example.com']); $this->logger->cache->debug('Cache miss - loading from database'); $this->logger->database->debug('User query executed', ['query' => 'SELECT * FROM users WHERE email = ?']); $this->logger->security->info('User authenticated successfully', ['user_id' => 42]); $this->logger->cache->info('User cached', ['cache_key' => 'user_42', 'ttl' => 3600]); // API Request Processing $this->logger->framework->debug('Route matched', ['route' => '/api/orders', 'method' => 'GET']); $this->logger->database->debug('Orders query', ['user_id' => 42, 'limit' => 10]); $this->logger->cache->debug('Cache hit', ['cache_key' => 'orders_42_page_1']); // Error Scenario $this->logger->database->error('Database connection lost', ['host' => 'db.example.com', 'port' => 3306]); $this->logger->error->critical('Service degraded', ['affected_services' => ['orders', 'payments']]); $this->logger->security->warning('Potential attack detected', ['ip' => '1.2.3.4', 'pattern' => 'sql_injection']); // Überprüfe dass alle Logs korrekt in ihre Kanäle geschrieben wurden $securityLog = file_get_contents($this->testLogDir . '/security/security.log'); $cacheLog = file_get_contents($this->testLogDir . '/debug/cache.log'); $databaseLog = file_get_contents($this->testLogDir . '/debug/database.log'); $frameworkLog = file_get_contents($this->testLogDir . '/debug/framework.log'); $errorLog = file_get_contents($this->testLogDir . '/app/error.log'); // Security-Ereignisse expect($securityLog)->toContain('Authentication attempt started'); expect($securityLog)->toContain('User authenticated successfully'); expect($securityLog)->toContain('Potential attack detected'); // Cache-Operationen expect($cacheLog)->toContain('Checking user cache'); expect($cacheLog)->toContain('Cache miss'); expect($cacheLog)->toContain('User cached'); expect($cacheLog)->toContain('Cache hit'); // Database-Operationen expect($databaseLog)->toContain('User query executed'); expect($databaseLog)->toContain('Orders query'); expect($databaseLog)->toContain('Database connection lost'); // Framework-Ereignisse expect($frameworkLog)->toContain('Route matched'); // Error-Ereignisse expect($errorLog)->toContain('Service degraded'); // Cross-channel Isolation prüfen expect($securityLog)->not->toContain('Cache miss'); expect($cacheLog)->not->toContain('Authentication attempt'); expect($databaseLog)->not->toContain('Route matched'); } }