- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
321 lines
12 KiB
PHP
321 lines
12 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Framework\Http\Session\FileSessionStorage;
|
|
use App\Framework\Http\Session\InMemorySessionStorage;
|
|
use App\Framework\Http\Session\SessionId;
|
|
use App\Framework\Http\Session\SessionStorage;
|
|
|
|
describe('InMemorySessionStorage', function () {
|
|
beforeEach(function () {
|
|
$this->storage = new InMemorySessionStorage();
|
|
$this->sessionId = SessionId::fromString('testsessionid1234567890abcdefgh12');
|
|
});
|
|
|
|
test('reads empty array for non-existent session', function () {
|
|
$data = $this->storage->read($this->sessionId);
|
|
expect($data)->toBe([]);
|
|
});
|
|
|
|
test('writes and reads session data correctly', function () {
|
|
$testData = [
|
|
'user_id' => 123,
|
|
'username' => 'testuser',
|
|
'preferences' => ['theme' => 'dark', 'language' => 'en'],
|
|
];
|
|
|
|
$this->storage->write($this->sessionId, $testData);
|
|
$retrievedData = $this->storage->read($this->sessionId);
|
|
|
|
expect($retrievedData)->toBe($testData);
|
|
});
|
|
|
|
test('removes session data correctly', function () {
|
|
$testData = ['key' => 'value'];
|
|
|
|
$this->storage->write($this->sessionId, $testData);
|
|
expect($this->storage->read($this->sessionId))->toBe($testData);
|
|
|
|
$this->storage->remove($this->sessionId);
|
|
expect($this->storage->read($this->sessionId))->toBe([]);
|
|
});
|
|
|
|
test('migrates session data correctly', function () {
|
|
$oldId = SessionId::fromString('oldsessionid1234567890abcdefghij1');
|
|
$newId = SessionId::fromString('newsessionid1234567890abcdefghij1');
|
|
$testData = ['migration_test' => 'data'];
|
|
|
|
$this->storage->write($oldId, $testData);
|
|
$this->storage->migrate($oldId, $newId);
|
|
|
|
expect($this->storage->read($oldId))->toBe([]);
|
|
expect($this->storage->read($newId))->toBe($testData);
|
|
});
|
|
|
|
test('handles complex data structures', function () {
|
|
$complexData = [
|
|
'nested' => [
|
|
'deep' => [
|
|
'array' => [1, 2, 3],
|
|
'object' => (object)['property' => 'value'],
|
|
],
|
|
],
|
|
'null_value' => null,
|
|
'boolean_true' => true,
|
|
'boolean_false' => false,
|
|
'empty_string' => '',
|
|
'zero' => 0,
|
|
];
|
|
|
|
$this->storage->write($this->sessionId, $complexData);
|
|
$retrieved = $this->storage->read($this->sessionId);
|
|
|
|
expect($retrieved)->toBe($complexData);
|
|
});
|
|
|
|
test('multiple sessions work independently', function () {
|
|
$session1Id = SessionId::fromString('session1id1234567890abcdefghijk1');
|
|
$session2Id = SessionId::fromString('session2id1234567890abcdefghijk2');
|
|
|
|
$data1 = ['session' => '1', 'data' => 'first'];
|
|
$data2 = ['session' => '2', 'data' => 'second'];
|
|
|
|
$this->storage->write($session1Id, $data1);
|
|
$this->storage->write($session2Id, $data2);
|
|
|
|
expect($this->storage->read($session1Id))->toBe($data1);
|
|
expect($this->storage->read($session2Id))->toBe($data2);
|
|
|
|
$this->storage->remove($session1Id);
|
|
expect($this->storage->read($session1Id))->toBe([]);
|
|
expect($this->storage->read($session2Id))->toBe($data2);
|
|
});
|
|
});
|
|
|
|
describe('FileSessionStorage', function () {
|
|
beforeEach(function () {
|
|
$this->tempDir = sys_get_temp_dir() . '/session_test_' . uniqid();
|
|
$this->storage = new FileSessionStorage($this->tempDir);
|
|
$this->sessionId = SessionId::fromString('testfilesessionid1234567890abcde');
|
|
});
|
|
|
|
afterEach(function () {
|
|
// Cleanup: Remove test directory and files
|
|
if (is_dir($this->tempDir)) {
|
|
$files = glob($this->tempDir . '/*');
|
|
foreach ($files as $file) {
|
|
if (is_file($file)) {
|
|
unlink($file);
|
|
}
|
|
}
|
|
rmdir($this->tempDir);
|
|
}
|
|
});
|
|
|
|
test('creates storage directory if it does not exist', function () {
|
|
expect(is_dir($this->tempDir))->toBeTrue();
|
|
});
|
|
|
|
test('reads empty array for non-existent session file', function () {
|
|
$data = $this->storage->read($this->sessionId);
|
|
expect($data)->toBe([]);
|
|
});
|
|
|
|
test('writes and reads session data to/from file correctly', function () {
|
|
$testData = [
|
|
'user_id' => 456,
|
|
'username' => 'fileuser',
|
|
'complex' => [
|
|
'nested' => ['deep' => 'value'],
|
|
'array' => [1, 2, 3, 4],
|
|
],
|
|
];
|
|
|
|
$this->storage->write($this->sessionId, $testData);
|
|
$retrievedData = $this->storage->read($this->sessionId);
|
|
|
|
expect($retrievedData)->toBe($testData);
|
|
});
|
|
|
|
test('file exists after writing', function () {
|
|
$testData = ['file_test' => 'exists'];
|
|
$this->storage->write($this->sessionId, $testData);
|
|
|
|
$expectedFile = $this->tempDir . '/sess_' . $this->sessionId->toString();
|
|
expect(file_exists($expectedFile))->toBeTrue();
|
|
});
|
|
|
|
test('removes session file correctly', function () {
|
|
$testData = ['to_be_removed' => 'data'];
|
|
|
|
$this->storage->write($this->sessionId, $testData);
|
|
$expectedFile = $this->tempDir . '/sess_' . $this->sessionId->toString();
|
|
expect(file_exists($expectedFile))->toBeTrue();
|
|
|
|
$this->storage->remove($this->sessionId);
|
|
expect(file_exists($expectedFile))->toBeFalse();
|
|
expect($this->storage->read($this->sessionId))->toBe([]);
|
|
});
|
|
|
|
test('migrates session file correctly', function () {
|
|
$oldId = SessionId::fromString('oldfilesessionid1234567890abcdef');
|
|
$newId = SessionId::fromString('newfilesessionid1234567890abcdef');
|
|
$testData = ['migration_file_test' => 'data'];
|
|
|
|
$this->storage->write($oldId, $testData);
|
|
|
|
$oldFile = $this->tempDir . '/sess_' . $oldId->toString();
|
|
$newFile = $this->tempDir . '/sess_' . $newId->toString();
|
|
|
|
expect(file_exists($oldFile))->toBeTrue();
|
|
expect(file_exists($newFile))->toBeFalse();
|
|
|
|
$this->storage->migrate($oldId, $newId);
|
|
|
|
expect(file_exists($oldFile))->toBeFalse();
|
|
expect(file_exists($newFile))->toBeTrue();
|
|
expect($this->storage->read($newId))->toBe($testData);
|
|
});
|
|
|
|
test('handles JSON encoding/decoding correctly', function () {
|
|
$testData = [
|
|
'string' => 'test string with üñíçødé',
|
|
'integer' => 42,
|
|
'float' => 3.14159,
|
|
'boolean_true' => true,
|
|
'boolean_false' => false,
|
|
'null' => null,
|
|
'array' => ['a', 'b', 'c'],
|
|
'object' => ['key' => 'value'],
|
|
];
|
|
|
|
$this->storage->write($this->sessionId, $testData);
|
|
$retrieved = $this->storage->read($this->sessionId);
|
|
|
|
expect($retrieved)->toBe($testData);
|
|
});
|
|
|
|
test('handles corrupted JSON file gracefully', function () {
|
|
// Schreibe invalides JSON in die Session-Datei
|
|
$sessionFile = $this->tempDir . '/sess_' . $this->sessionId->toString();
|
|
file_put_contents($sessionFile, 'invalid json content {');
|
|
|
|
$data = $this->storage->read($this->sessionId);
|
|
expect($data)->toBe([]); // Sollte leeres Array zurückgeben
|
|
});
|
|
|
|
test('handles file system errors gracefully', function () {
|
|
// Versuche in nicht-existierendes Verzeichnis zu schreiben (das Framework sollte das abfangen)
|
|
expect(fn () => new FileSessionStorage('/root/nonexistent/directory/path'))
|
|
->toThrow(RuntimeException::class);
|
|
});
|
|
|
|
test('garbage collection removes old files', function () {
|
|
// Erstelle mehrere Session-Dateien mit verschiedenen Timestamps
|
|
$oldSessionId = SessionId::fromString('oldsessionid1234567890abcdefghij1');
|
|
$newSessionId = SessionId::fromString('newsessionid1234567890abcdefghij2');
|
|
|
|
$this->storage->write($oldSessionId, ['old' => 'data']);
|
|
$this->storage->write($newSessionId, ['new' => 'data']);
|
|
|
|
// Da wir die neue FileSessionStorage verwenden, können wir nicht direkt touch() verwenden
|
|
// Stattdessen testen wir nur dass GC nicht crashed und beide Files noch existieren
|
|
// (da sie frisch erstellt wurden)
|
|
$this->storage->gc(3600);
|
|
|
|
// Beide Sessions sollten noch existieren da sie gerade erstellt wurden
|
|
expect($this->storage->read($oldSessionId))->toBe(['old' => 'data']);
|
|
expect($this->storage->read($newSessionId))->toBe(['new' => 'data']);
|
|
});
|
|
});
|
|
|
|
describe('SessionStorage Interface Compliance', function () {
|
|
/**
|
|
* Teste dass alle Storage-Implementierungen das gleiche Interface-Verhalten haben
|
|
*/
|
|
$storageProviders = [
|
|
'InMemorySessionStorage' => fn () => new InMemorySessionStorage(),
|
|
'FileSessionStorage' => fn () => new FileSessionStorage(sys_get_temp_dir() . '/pest_session_test_' . uniqid()),
|
|
];
|
|
|
|
foreach ($storageProviders as $storageName => $storageFactory) {
|
|
describe($storageName . ' Interface Compliance', function () use ($storageName, $storageFactory) {
|
|
beforeEach(function () use ($storageFactory) {
|
|
$this->storage = $storageFactory();
|
|
$this->sessionId = SessionId::fromString('interfacetestsessionid1234567890');
|
|
});
|
|
|
|
afterEach(function () use ($storageName) {
|
|
// Cleanup für FileStorage
|
|
if ($storageName === 'FileSessionStorage' && $this->storage instanceof FileSessionStorage) {
|
|
$basePath = $this->storage->getBasePath();
|
|
$pathString = $basePath->toString();
|
|
|
|
if (is_dir($pathString)) {
|
|
$files = glob($pathString . '/*');
|
|
foreach ($files as $file) {
|
|
if (is_file($file)) {
|
|
unlink($file);
|
|
}
|
|
}
|
|
rmdir($pathString);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('implements SessionStorage interface', function () {
|
|
expect($this->storage)->toBeInstanceOf(SessionStorage::class);
|
|
});
|
|
|
|
test('read() returns array', function () {
|
|
$result = $this->storage->read($this->sessionId);
|
|
expect($result)->toBeArray();
|
|
});
|
|
|
|
test('write() and read() cycle works', function () {
|
|
$testData = ['interface_test' => 'value', 'number' => 42];
|
|
|
|
$this->storage->write($this->sessionId, $testData);
|
|
$result = $this->storage->read($this->sessionId);
|
|
|
|
expect($result)->toBe($testData);
|
|
});
|
|
|
|
test('remove() clears session data', function () {
|
|
$this->storage->write($this->sessionId, ['to_remove' => 'data']);
|
|
$this->storage->remove($this->sessionId);
|
|
|
|
expect($this->storage->read($this->sessionId))->toBe([]);
|
|
});
|
|
|
|
test('migrate() transfers data correctly', function () {
|
|
$oldId = SessionId::fromString('oldinterfacetest1234567890abcdefg');
|
|
$newId = SessionId::fromString('newinterfacetest1234567890abcdefg');
|
|
$testData = ['migrate_interface_test' => 'data'];
|
|
|
|
$this->storage->write($oldId, $testData);
|
|
$this->storage->migrate($oldId, $newId);
|
|
|
|
expect($this->storage->read($oldId))->toBe([]);
|
|
expect($this->storage->read($newId))->toBe($testData);
|
|
});
|
|
|
|
test('handles empty data correctly', function () {
|
|
$this->storage->write($this->sessionId, []);
|
|
expect($this->storage->read($this->sessionId))->toBe([]);
|
|
});
|
|
|
|
test('handles null values in data', function () {
|
|
$testData = ['null_value' => null, 'string' => 'value'];
|
|
|
|
$this->storage->write($this->sessionId, $testData);
|
|
$result = $this->storage->read($this->sessionId);
|
|
|
|
expect($result)->toBe($testData);
|
|
expect($result['null_value'])->toBeNull();
|
|
});
|
|
});
|
|
}
|
|
});
|