- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
160 lines
6.5 KiB
PHP
160 lines
6.5 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Framework\Core\ValueObjects\ClassName;
|
|
|
|
describe('ClassName Edge Cases and Security', function () {
|
|
|
|
it('handles potential security issues gracefully', function () {
|
|
// Test with potentially problematic class names that could cause issues
|
|
$dangerousCases = [
|
|
'../../etc/passwd', // Path traversal attempt
|
|
'<script>alert(1)</script>', // XSS attempt
|
|
'DROP TABLE users', // SQL injection style
|
|
"\0null\0byte", // Null byte injection
|
|
'very.long.dotted.name', // Invalid dots instead of backslashes
|
|
];
|
|
|
|
foreach ($dangerousCases as $dangerous) {
|
|
expect(function () use ($dangerous) {
|
|
ClassName::create($dangerous);
|
|
})->toThrow(InvalidArgumentException::class);
|
|
}
|
|
});
|
|
|
|
it('handles unicode and special characters', function () {
|
|
// Some unicode characters are valid in PHP class names (within \x80-\xff range)
|
|
$validUnicodeCase = 'Ñame'; // Accented characters in \x80-\xff range
|
|
$className = ClassName::create($validUnicodeCase);
|
|
expect($className->exists())->toBeFalse(); // Won't exist but should be valid name
|
|
|
|
// These should be definitely invalid
|
|
$definitivelyInvalidCases = [
|
|
'Name Space', // Space (definitely invalid)
|
|
'Name-Dash', // Dash (definitely invalid)
|
|
'Name.Dot', // Dot (definitely invalid)
|
|
];
|
|
|
|
foreach ($definitivelyInvalidCases as $invalid) {
|
|
expect(function () use ($invalid) {
|
|
ClassName::create($invalid);
|
|
})->toThrow(InvalidArgumentException::class);
|
|
}
|
|
|
|
// Test that we can create valid unicode names without errors
|
|
$potentiallyValidCases = ['Ñame', 'Tëst', 'Clâss'];
|
|
foreach ($potentiallyValidCases as $case) {
|
|
$className = ClassName::create($case);
|
|
expect($className->getFullyQualified())->toBe($case);
|
|
expect($className->exists())->toBeFalse(); // They won't exist but names should be valid
|
|
}
|
|
});
|
|
|
|
it('handles very long class names', function () {
|
|
// Test with extremely long but valid class name
|
|
$longNamespace = str_repeat('VeryLongNamespace\\', 50);
|
|
$longClassName = $longNamespace . 'VeryLongClassName';
|
|
|
|
$className = ClassName::create($longClassName);
|
|
expect($className->exists())->toBeFalse(); // Should not exist but should not error
|
|
expect($className->getFullyQualified())->toBe($longClassName);
|
|
});
|
|
|
|
it('handles constructor edge cases', function () {
|
|
// Test various whitespace and formatting issues
|
|
expect(function () {
|
|
ClassName::create('');
|
|
})->toThrow(InvalidArgumentException::class, 'Class name cannot be empty');
|
|
|
|
expect(function () {
|
|
ClassName::create(" \t\n ");
|
|
})->toThrow(InvalidArgumentException::class);
|
|
|
|
// Leading backslashes should be handled correctly (but trailing ones are preserved)
|
|
$className = ClassName::create('\\\\\\App\\Test');
|
|
expect($className->getFullyQualified())->toBe('App\\Test'); // Leading backslashes removed
|
|
});
|
|
|
|
it('stress test - handles many rapid exists() calls without issues', function () {
|
|
$startTime = microtime(true);
|
|
$startMemory = memory_get_usage();
|
|
|
|
// Rapid fire test
|
|
for ($i = 0; $i < 5000; $i++) {
|
|
$className = ClassName::create('TestClass' . ($i % 100));
|
|
$className->exists();
|
|
}
|
|
|
|
$endTime = microtime(true);
|
|
$endMemory = memory_get_usage();
|
|
|
|
$duration = $endTime - $startTime;
|
|
$memoryIncrease = $endMemory - $startMemory;
|
|
|
|
// Should complete within reasonable time (less than 1 second)
|
|
expect($duration)->toBeLessThan(1.0);
|
|
|
|
// Should not consume excessive memory (less than 5MB)
|
|
expect($memoryIncrease)->toBeLessThan(5 * 1024 * 1024);
|
|
});
|
|
|
|
it('validates that exists() is consistent across calls', function () {
|
|
// Test that multiple calls to exists() on the same instance return consistent results
|
|
$existingClass = ClassName::create('stdClass');
|
|
$nonExistingClass = ClassName::create('NonExistentClass123');
|
|
|
|
// Multiple calls should return the same result
|
|
for ($i = 0; $i < 10; $i++) {
|
|
expect($existingClass->exists())->toBeTrue();
|
|
expect($nonExistingClass->exists())->toBeFalse();
|
|
}
|
|
|
|
// Different instances of the same class name should also be consistent
|
|
for ($i = 0; $i < 5; $i++) {
|
|
$newInstance = ClassName::create('stdClass');
|
|
expect($newInstance->exists())->toBeTrue();
|
|
|
|
$newNonExisting = ClassName::create('NonExistentClass123');
|
|
expect($newNonExisting->exists())->toBeFalse();
|
|
}
|
|
});
|
|
|
|
it('handles the exact scenario from the bug report', function () {
|
|
// This test recreates the exact conditions that caused the original bug:
|
|
// 1. Container compilation process
|
|
// 2. Dependency resolution with potentially empty class names
|
|
// 3. Multiple rapid exists() checks
|
|
|
|
$problematicCases = [
|
|
'App\\Framework\\Filesystem\\AtomicStorage', // The interface that caused issues
|
|
'App\\Framework\\Filesystem\\Storage', // Parent interface
|
|
'App\\Framework\\Filesystem\\FileStorage', // Implementation
|
|
'App\\Framework\\DI\\Container', // Container interface
|
|
'App\\Framework\\DI\\DefaultContainer', // Container implementation
|
|
];
|
|
|
|
// Simulate rapid container compilation checks
|
|
foreach ($problematicCases as $case) {
|
|
$className = ClassName::create($case);
|
|
$exists = $className->exists();
|
|
|
|
// All these should exist and not cause warnings
|
|
expect($exists)->toBeTrue();
|
|
expect($className->getFullyQualified())->toBe($case);
|
|
}
|
|
|
|
// Also test with non-existent classes that might be checked during compilation
|
|
$nonExistentCases = [
|
|
'App\\NonExistent\\Interface',
|
|
'App\\Framework\\NonExistent\\Class',
|
|
'Some\\Random\\ClassName\\That\\DoesNot\\Exist',
|
|
];
|
|
|
|
foreach ($nonExistentCases as $case) {
|
|
$className = ClassName::create($case);
|
|
expect($className->exists())->toBeFalse();
|
|
}
|
|
});
|
|
});
|