Files
easystream-main/tests/Performance/AuthPerformanceTest.php
SamiAhmed7777 0b7e2d0a5b feat: Add comprehensive documentation suite and reorganize project structure
- Created complete documentation in docs/ directory
- Added PROJECT_OVERVIEW.md with feature highlights and getting started guide
- Added ARCHITECTURE.md with system design and technical details
- Added SECURITY.md with comprehensive security implementation guide
- Added DEVELOPMENT.md with development workflows and best practices
- Added DEPLOYMENT.md with production deployment instructions
- Added API.md with complete REST API documentation
- Added CONTRIBUTING.md with contribution guidelines
- Added CHANGELOG.md with version history and migration notes
- Reorganized all documentation files into docs/ directory for better organization
- Updated README.md with proper documentation links and quick navigation
- Enhanced project structure with professional documentation standards
2025-10-21 00:39:45 -07:00

469 lines
17 KiB
PHP

<?php
namespace EasyStream\Tests\Performance;
use PHPUnit\Framework\TestCase;
use VAuth;
use VRBAC;
use VSecurity;
class AuthPerformanceTest extends TestCase
{
private $auth;
private $rbac;
private $testUsers = [];
protected function setUp(): void
{
$this->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";
}
}