- Implemented SecurityTest to validate token generation, CSRF protection, input sanitization, and rate limiting. - Created UserModelTest to ensure correct database operations for user management, including creation, updating, banning, and fetching active users. - Developed ValidationTest to verify input validation and sanitization for user IDs, nicknames, messages, and API requests. - Introduced Security and Validation utility classes with methods for secure token generation, input sanitization, and comprehensive validation rules.
222 lines
8.2 KiB
PHP
222 lines
8.2 KiB
PHP
<?php
|
|
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
/**
|
|
* Test Validation utility functions
|
|
*/
|
|
class ValidationTest extends TestCase
|
|
{
|
|
protected function setUp(): void
|
|
{
|
|
// Clear any previous test data
|
|
$_POST = [];
|
|
$_GET = [];
|
|
}
|
|
|
|
public function testValidateUserId()
|
|
{
|
|
// Valid user IDs
|
|
$result = Validation::validateUserId('a1b2c3d4e5f67890123456789012abcd');
|
|
$this->assertTrue($result['valid']);
|
|
$this->assertEquals('a1b2c3d4e5f67890123456789012abcd', $result['user_id']);
|
|
|
|
// Invalid user IDs
|
|
$result = Validation::validateUserId('invalid_user_id');
|
|
$this->assertFalse($result['valid']);
|
|
|
|
$result = Validation::validateUserId('a1b2c3d4'); // Too short
|
|
$this->assertFalse($result['valid']);
|
|
|
|
$result = Validation::validateUserId('a1b2c3d4e5f67890123456789012abcdextra'); // Too long
|
|
$this->assertFalse($result['valid']);
|
|
|
|
$result = Validation::validateUserId('gggggggggggggggggggggggggggggggg'); // Invalid chars
|
|
$this->assertFalse($result['valid']);
|
|
}
|
|
|
|
public function testValidateNickname()
|
|
{
|
|
// Valid nicknames
|
|
$result = Validation::validateNickname('JohnDoe');
|
|
$this->assertTrue($result['valid']);
|
|
|
|
$result = Validation::validateNickname('Test User');
|
|
$this->assertTrue($result['valid']);
|
|
|
|
$result = Validation::validateNickname("O'Connor-Smith");
|
|
$this->assertTrue($result['valid']);
|
|
|
|
// Invalid nicknames
|
|
$result = Validation::validateNickname(''); // Empty
|
|
$this->assertFalse($result['valid']);
|
|
|
|
$result = Validation::validateNickname('A'); // Too short
|
|
$this->assertFalse($result['valid']);
|
|
|
|
$result = Validation::validateNickname(str_repeat('A', 21)); // Too long
|
|
$this->assertFalse($result['valid']);
|
|
|
|
$result = Validation::validateNickname('Invalid@Name'); // Invalid chars
|
|
$this->assertFalse($result['valid']);
|
|
|
|
$result = Validation::validateNickname('<script>evil</script>'); // XSS attempt
|
|
$this->assertFalse($result['valid']);
|
|
}
|
|
|
|
public function testValidateMessage()
|
|
{
|
|
// Valid messages
|
|
$result = Validation::validateMessage('Hello World!');
|
|
$this->assertTrue($result['valid']);
|
|
|
|
$result = Validation::validateMessage('This is a longer message with punctuation, numbers 123, and symbols @#$%!');
|
|
$this->assertTrue($result['valid']);
|
|
|
|
// Invalid messages
|
|
$result = Validation::validateMessage(''); // Empty
|
|
$this->assertFalse($result['valid']);
|
|
|
|
$result = Validation::validateMessage(str_repeat('A', 1001)); // Too long
|
|
$this->assertFalse($result['valid']);
|
|
|
|
$result = Validation::validateMessage('<script>alert("xss")</script>'); // XSS
|
|
$this->assertFalse($result['valid']);
|
|
}
|
|
|
|
public function testValidateMessageSend()
|
|
{
|
|
// Valid message send data
|
|
$data = [
|
|
'nickname' => 'TestUser',
|
|
'message' => 'Hello World!',
|
|
'user_agent' => 'Mozilla/5.0 (Test Browser)',
|
|
'ip_address' => '192.168.1.1'
|
|
];
|
|
|
|
$result = Validation::validateMessageSend($data);
|
|
$this->assertTrue($result['valid']);
|
|
$this->assertEquals($data['nickname'], $result['validated']['nickname']);
|
|
$this->assertEquals($data['message'], $result['validated']['message']);
|
|
|
|
// Invalid message send data
|
|
$invalidData = [
|
|
'nickname' => 'Invalid@Name',
|
|
'message' => '<script>evil</script>',
|
|
];
|
|
|
|
$result = Validation::validateMessageSend($invalidData);
|
|
$this->assertFalse($result['valid']);
|
|
$this->assertArrayHasKey('errors', $result);
|
|
}
|
|
|
|
public function testValidateHeartbeat()
|
|
{
|
|
// Valid heartbeat data
|
|
$data = [
|
|
'nickname' => 'TestUser',
|
|
'user_id' => 'a1b2c3d4e5f67890123456789012abcd',
|
|
'session_id' => 'session_123456'
|
|
];
|
|
|
|
$result = Validation::validateHeartbeat($data);
|
|
$this->assertTrue($result['valid']);
|
|
$this->assertEquals($data['nickname'], $result['validated']['nickname']);
|
|
|
|
// Invalid heartbeat data
|
|
$invalidData = [
|
|
'nickname' => str_repeat('A', 21), // Too long
|
|
'user_id' => 'invalid_id',
|
|
];
|
|
|
|
$result = Validation::validateHeartbeat($invalidData);
|
|
$this->assertFalse($result['valid']);
|
|
$this->assertArrayHasKey('errors', $result);
|
|
}
|
|
|
|
public function testValidateAdminLogin()
|
|
{
|
|
// Valid login data
|
|
$result = Validation::validateAdminLogin('admin_user', 'valid_password');
|
|
$this->assertTrue($result['valid']);
|
|
$this->assertEquals('admin_user', $result['data']['username']);
|
|
|
|
// Invalid login data
|
|
$result = Validation::validateAdminLogin('', 'password'); // Empty username
|
|
$this->assertFalse($result['valid']);
|
|
|
|
$result = Validation::validateAdminLogin('admin', ''); // Empty password
|
|
$this->assertFalse($result['valid']);
|
|
|
|
$result = Validation::validateAdminLogin('us', 'password'); // Username too short
|
|
$this->assertFalse($result['valid']);
|
|
|
|
$result = Validation::validateAdminLogin('user@domain.com', 'password'); // Invalid username format
|
|
$this->assertFalse($result['valid']);
|
|
}
|
|
|
|
public function testIsValidEmail()
|
|
{
|
|
// Valid emails
|
|
$this->assertTrue(Validation::isValidEmail('user@example.com'));
|
|
$this->assertTrue(Validation::isValidEmail('test.user+tag@example.co.uk'));
|
|
$this->assertTrue(Validation::isValidEmail('user@localhost'));
|
|
|
|
// Invalid emails
|
|
$this->assertFalse(Validation::isValidEmail('invalid-email'));
|
|
$this->assertFalse(Validation::isValidEmail('user@'));
|
|
$this->assertFalse(Validation::isValidEmail('@example.com'));
|
|
$this->assertFalse(Validation::isValidEmail('user@.com'));
|
|
}
|
|
|
|
public function testIsValidURL()
|
|
{
|
|
// Valid URLs
|
|
$this->assertTrue(Validation::isValidURL('http://example.com'));
|
|
$this->assertTrue(Validation::isValidURL('https://example.com/path?query=1'));
|
|
$this->assertTrue(Validation::isValidURL('ftp://example.com/file.txt'));
|
|
|
|
// Invalid URLs
|
|
$this->assertFalse(Validation::isValidURL('not-a-url'));
|
|
$this->assertFalse(Validation::isValidURL('javascript:alert(1)'));
|
|
$this->assertFalse(Validation::isValidURL(''));
|
|
}
|
|
|
|
public function testCleanString()
|
|
{
|
|
// Test normal cleaning
|
|
$result = Validation::cleanString(' Hello World ');
|
|
$this->assertEquals('Hello World', $result);
|
|
|
|
// Test with HTML entities
|
|
$result = Validation::cleanString('Hello & World <tag>');
|
|
$this->assertEquals('Hello & World <tag>', $result);
|
|
|
|
// Test with script tags (should be encoded)
|
|
$result = Validation::cleanString('<script>alert(1)</script>Hello');
|
|
$this->assertEquals('<script>alert(1)</script>Hello', $result);
|
|
}
|
|
|
|
public function testLengthBetween()
|
|
{
|
|
// Test valid lengths
|
|
$this->assertTrue(Validation::lengthBetween('test', 2, 10));
|
|
$this->assertTrue(Validation::lengthBetween('test', 4, 4));
|
|
|
|
// Test invalid lengths
|
|
$this->assertFalse(Validation::lengthBetween('t', 2, 10)); // Too short
|
|
$this->assertFalse(Validation::lengthBetween('this_is_a_very_long_string', 2, 10)); // Too long
|
|
}
|
|
|
|
public function testMatchesPattern()
|
|
{
|
|
// Test valid patterns
|
|
$this->assertTrue(Validation::matchesPattern('123', '/^\d+$/'));
|
|
$this->assertTrue(Validation::matchesPattern('abc123', '/^[a-zA-Z0-9]+$/'));
|
|
$this->assertTrue(Validation::matchesPattern('test@example.com', '/^[^\s@]+@[^\s@]+\.[^\s@]+$/')); // Simple email regex
|
|
|
|
// Test invalid patterns
|
|
$this->assertFalse(Validation::matchesPattern('abc', '/^\d+$/')); // Not numeric
|
|
$this->assertFalse(Validation::matchesPattern('invalid-email', '/^[^\s@]+@[^\s@]+\.[^\s@]+$/')); // Not email
|
|
}
|
|
}
|