auth = VAuth::getInstance(); $this->rbac = VRBAC::getInstance(); // Clear session data if (isset($_SESSION)) { $_SESSION = []; } // Mock server variables $_SERVER = [ 'REQUEST_URI' => '/test', 'REQUEST_METHOD' => 'POST', 'HTTP_USER_AGENT' => 'PHPUnit Performance Test', 'REMOTE_ADDR' => '127.0.0.1', 'HTTPS' => '1' ]; // Clean up any existing test data $this->cleanupTestData(); // Create test users for performance testing $this->createTestUsers(); } protected function tearDown(): void { // Clean up test data $this->cleanupTestData(); // Clear session if (isset($_SESSION)) { $_SESSION = []; } } private function cleanupTestData() { global $class_database; $db = $class_database->dbConnection(); // Clean up test users for ($i = 1; $i <= 10; $i++) { $email = "perftest{$i}@example.com"; $userId = $db->GetOne("SELECT user_id FROM db_users WHERE email = ?", [$email]); if ($userId) { $db->Execute("DELETE FROM db_user_permissions WHERE user_id = ?", [$userId]); $db->Execute("DELETE FROM db_sessions WHERE user_id = ?", [$userId]); $db->Execute("DELETE FROM db_login_history WHERE user_id = ?", [$userId]); $db->Execute("DELETE FROM db_users WHERE user_id = ?", [$userId]); } } } private function createTestUsers() { for ($i = 1; $i <= 10; $i++) { $userData = [ 'username' => "perftest{$i}", 'email' => "perftest{$i}@example.com", 'password' => 'TestPassword123!' ]; $result = $this->auth->register($userData); if ($result['success']) { $this->testUsers[] = [ 'user_id' => $result['user_id'], 'username' => $userData['username'], 'email' => $userData['email'] ]; // Verify email global $class_database; $db = $class_database->dbConnection(); $token = $db->GetOne("SELECT verification_token FROM db_users WHERE user_id = ?", [$result['user_id']]); if ($token) { $this->auth->verifyEmail($token); } } } } /** * Test login performance */ public function testLoginPerformance() { $iterations = 50; $maxTimePerLogin = 0.1; // 100ms max per login $startTime = microtime(true); for ($i = 0; $i < $iterations; $i++) { $userIndex = $i % count($this->testUsers); $user = $this->testUsers[$userIndex]; $loginStart = microtime(true); $result = $this->auth->login($user['username'], 'TestPassword123!'); $loginTime = microtime(true) - $loginStart; $this->assertTrue($result['success'], "Login should succeed for user {$user['username']}"); $this->assertLessThan($maxTimePerLogin, $loginTime, "Login should complete within {$maxTimePerLogin}s"); $this->auth->logout(); } $totalTime = microtime(true) - $startTime; $averageTime = $totalTime / $iterations; $this->assertLessThan($maxTimePerLogin, $averageTime, "Average login time should be under {$maxTimePerLogin}s"); echo "\nLogin Performance: {$iterations} logins in " . number_format($totalTime, 3) . "s"; echo " (avg: " . number_format($averageTime * 1000, 2) . "ms per login)\n"; } /** * Test permission checking performance */ public function testPermissionCheckingPerformance() { // Login a user $user = $this->testUsers[0]; $this->auth->login($user['username'], 'TestPassword123!'); $permissions = [ 'content.view', 'content.create', 'content.edit', 'content.delete', 'comment.view', 'comment.create', 'upload.video', 'upload.image', 'admin.dashboard', 'user.ban', 'api.access', 'feature.beta' ]; $iterations = 1000; $maxTimePerCheck = 0.001; // 1ms max per permission check $startTime = microtime(true); for ($i = 0; $i < $iterations; $i++) { $permission = $permissions[$i % count($permissions)]; $checkStart = microtime(true); $hasPermission = $this->rbac->hasPermission($permission); $checkTime = microtime(true) - $checkStart; $this->assertIsBool($hasPermission); $this->assertLessThan($maxTimePerCheck, $checkTime, "Permission check should complete within {$maxTimePerCheck}s"); } $totalTime = microtime(true) - $startTime; $averageTime = $totalTime / $iterations; $this->assertLessThan($maxTimePerCheck, $averageTime, "Average permission check time should be under {$maxTimePerCheck}s"); echo "\nPermission Check Performance: {$iterations} checks in " . number_format($totalTime, 3) . "s"; echo " (avg: " . number_format($averageTime * 1000, 3) . "ms per check)\n"; $this->auth->logout(); } /** * Test session validation performance */ public function testSessionValidationPerformance() { // Login a user $user = $this->testUsers[0]; $this->auth->login($user['username'], 'TestPassword123!'); $iterations = 500; $maxTimePerValidation = 0.005; // 5ms max per validation $startTime = microtime(true); for ($i = 0; $i < $iterations; $i++) { $validationStart = microtime(true); $isAuthenticated = $this->auth->isAuthenticated(); $validationTime = microtime(true) - $validationStart; $this->assertTrue($isAuthenticated); $this->assertLessThan($maxTimePerValidation, $validationTime, "Session validation should complete within {$maxTimePerValidation}s"); } $totalTime = microtime(true) - $startTime; $averageTime = $totalTime / $iterations; $this->assertLessThan($maxTimePerValidation, $averageTime, "Average session validation time should be under {$maxTimePerValidation}s"); echo "\nSession Validation Performance: {$iterations} validations in " . number_format($totalTime, 3) . "s"; echo " (avg: " . number_format($averageTime * 1000, 3) . "ms per validation)\n"; $this->auth->logout(); } /** * Test concurrent login performance */ public function testConcurrentLoginPerformance() { $concurrentLogins = 10; $maxTotalTime = 2.0; // 2 seconds max for all concurrent logins $startTime = microtime(true); // Simulate concurrent logins by rapidly switching sessions for ($i = 0; $i < $concurrentLogins; $i++) { $user = $this->testUsers[$i]; // Create new session for each "concurrent" user session_write_close(); session_id('perf_test_session_' . $i); session_start(); $result = $this->auth->login($user['username'], 'TestPassword123!'); $this->assertTrue($result['success'], "Concurrent login should succeed for user {$user['username']}"); } $totalTime = microtime(true) - $startTime; $this->assertLessThan($maxTotalTime, $totalTime, "Concurrent logins should complete within {$maxTotalTime}s"); echo "\nConcurrent Login Performance: {$concurrentLogins} concurrent logins in " . number_format($totalTime, 3) . "s\n"; // Cleanup sessions for ($i = 0; $i < $concurrentLogins; $i++) { session_write_close(); session_id('perf_test_session_' . $i); session_start(); $this->auth->logout(); } } /** * Test password hashing performance */ public function testPasswordHashingPerformance() { $iterations = 10; $maxTimePerHash = 0.5; // 500ms max per hash (password hashing should be slow) $minTimePerHash = 0.01; // 10ms min per hash (ensure it's not too fast) $passwords = [ 'TestPassword123!', 'AnotherPassword456@', 'ComplexPassword789#', 'SecurePassword012$' ]; $startTime = microtime(true); for ($i = 0; $i < $iterations; $i++) { $password = $passwords[$i % count($passwords)]; $hashStart = microtime(true); $hash = password_hash($password, PASSWORD_DEFAULT); $hashTime = microtime(true) - $hashStart; $this->assertNotEmpty($hash); $this->assertLessThan($maxTimePerHash, $hashTime, "Password hashing should complete within {$maxTimePerHash}s"); $this->assertGreaterThan($minTimePerHash, $hashTime, "Password hashing should take at least {$minTimePerHash}s for security"); // Verify the hash works $this->assertTrue(password_verify($password, $hash)); } $totalTime = microtime(true) - $startTime; $averageTime = $totalTime / $iterations; echo "\nPassword Hashing Performance: {$iterations} hashes in " . number_format($totalTime, 3) . "s"; echo " (avg: " . number_format($averageTime * 1000, 2) . "ms per hash)\n"; } /** * Test CSRF token generation performance */ public function testCSRFTokenPerformance() { $iterations = 1000; $maxTimePerToken = 0.001; // 1ms max per token generation $startTime = microtime(true); for ($i = 0; $i < $iterations; $i++) { $tokenStart = microtime(true); $token = VSecurity::generateCSRFToken('test_action_' . $i); $tokenTime = microtime(true) - $tokenStart; $this->assertNotEmpty($token); $this->assertEquals(64, strlen($token)); $this->assertLessThan($maxTimePerToken, $tokenTime, "CSRF token generation should complete within {$maxTimePerToken}s"); } $totalTime = microtime(true) - $startTime; $averageTime = $totalTime / $iterations; $this->assertLessThan($maxTimePerToken, $averageTime, "Average CSRF token generation time should be under {$maxTimePerToken}s"); echo "\nCSRF Token Performance: {$iterations} tokens in " . number_format($totalTime, 3) . "s"; echo " (avg: " . number_format($averageTime * 1000, 3) . "ms per token)\n"; } /** * Test database query performance for authentication */ public function testDatabaseQueryPerformance() { $iterations = 100; $maxTimePerQuery = 0.01; // 10ms max per query global $class_database; $db = $class_database->dbConnection(); // Test user lookup queries $startTime = microtime(true); for ($i = 0; $i < $iterations; $i++) { $user = $this->testUsers[$i % count($this->testUsers)]; $queryStart = microtime(true); $result = $db->Execute("SELECT * FROM db_users WHERE username = ? OR email = ?", [$user['username'], $user['email']]); $queryTime = microtime(true) - $queryStart; $this->assertNotFalse($result); $this->assertFalse($result->EOF); $this->assertLessThan($maxTimePerQuery, $queryTime, "User lookup query should complete within {$maxTimePerQuery}s"); } $totalTime = microtime(true) - $startTime; $averageTime = $totalTime / $iterations; $this->assertLessThan($maxTimePerQuery, $averageTime, "Average query time should be under {$maxTimePerQuery}s"); echo "\nDatabase Query Performance: {$iterations} user lookups in " . number_format($totalTime, 3) . "s"; echo " (avg: " . number_format($averageTime * 1000, 3) . "ms per query)\n"; } /** * Test memory usage during authentication operations */ public function testMemoryUsage() { $initialMemory = memory_get_usage(); $maxMemoryIncrease = 5 * 1024 * 1024; // 5MB max increase // Perform various authentication operations $user = $this->testUsers[0]; // Login/logout cycle for ($i = 0; $i < 10; $i++) { $this->auth->login($user['username'], 'TestPassword123!'); $this->auth->logout(); } // Permission checks $this->auth->login($user['username'], 'TestPassword123!'); for ($i = 0; $i < 100; $i++) { $this->rbac->hasPermission('content.view'); $this->rbac->hasPermission('admin.dashboard'); } $this->auth->logout(); // CSRF token generation for ($i = 0; $i < 100; $i++) { VSecurity::generateCSRFToken('test_' . $i); } $finalMemory = memory_get_usage(); $memoryIncrease = $finalMemory - $initialMemory; $this->assertLessThan($maxMemoryIncrease, $memoryIncrease, "Memory usage should not increase by more than " . ($maxMemoryIncrease / 1024 / 1024) . "MB"); echo "\nMemory Usage: " . number_format($memoryIncrease / 1024, 2) . "KB increase"; echo " (Peak: " . number_format(memory_get_peak_usage() / 1024 / 1024, 2) . "MB)\n"; } /** * Test rate limiting performance impact */ public function testRateLimitingPerformance() { $iterations = 100; $maxTimePerCheck = 0.002; // 2ms max per rate limit check $startTime = microtime(true); for ($i = 0; $i < $iterations; $i++) { $key = 'perf_test_' . ($i % 10); // Use 10 different keys $checkStart = microtime(true); $allowed = VSecurity::checkRateLimit($key, 100, 3600, 'test_action'); $checkTime = microtime(true) - $checkStart; $this->assertIsBool($allowed); $this->assertLessThan($maxTimePerCheck, $checkTime, "Rate limit check should complete within {$maxTimePerCheck}s"); } $totalTime = microtime(true) - $startTime; $averageTime = $totalTime / $iterations; $this->assertLessThan($maxTimePerCheck, $averageTime, "Average rate limit check time should be under {$maxTimePerCheck}s"); echo "\nRate Limiting Performance: {$iterations} checks in " . number_format($totalTime, 3) . "s"; echo " (avg: " . number_format($averageTime * 1000, 3) . "ms per check)\n"; } /** * Test overall authentication system performance under load */ public function testOverallSystemPerformance() { $operations = 200; $maxTotalTime = 5.0; // 5 seconds max for all operations $startTime = microtime(true); for ($i = 0; $i < $operations; $i++) { $user = $this->testUsers[$i % count($this->testUsers)]; // Mix of operations switch ($i % 4) { case 0: // Login/logout $this->auth->login($user['username'], 'TestPassword123!'); $this->auth->logout(); break; case 1: // Permission check $this->auth->login($user['username'], 'TestPassword123!'); $this->rbac->hasPermission('content.create'); $this->auth->logout(); break; case 2: // CSRF token generation VSecurity::generateCSRFToken('mixed_test_' . $i); break; case 3: // Rate limit check VSecurity::checkRateLimit('mixed_' . ($i % 5), 50, 3600, 'mixed_test'); break; } } $totalTime = microtime(true) - $startTime; $averageTime = $totalTime / $operations; $this->assertLessThan($maxTotalTime, $totalTime, "Overall system should handle {$operations} operations within {$maxTotalTime}s"); echo "\nOverall System Performance: {$operations} mixed operations in " . number_format($totalTime, 3) . "s"; echo " (avg: " . number_format($averageTime * 1000, 3) . "ms per operation)\n"; } }