public function autoExpireTriggersGarbageCollectionForExpiredSessions()
{
$settings = $this->settings;
$settings['session']['inactivityTimeout'] = 5000;
$settings['session']['garbageCollection']['probability'] = 100;
$metaDataCache = $this->createCache('Meta');
$storageCache = $this->createCache('Storage');
// Create a session which first runs fine and then expires by later modifying
// the inactivity timeout:
$session = new Session();
$this->inject($session, 'bootstrap', $this->mockBootstrap);
$this->inject($session, 'objectManager', $this->mockObjectManager);
$this->inject($session, 'metaDataCache', $this->createCache('Meta'));
$this->inject($session, 'storageCache', $this->createCache('Storage'));
$session->injectSettings($settings);
$session->initializeObject();
$session->start();
$sessionIdentifier1 = $session->getId();
$session->putData('session 1 key 1', 'session 1 value 1');
$session->putData('session 1 key 2', 'session 1 value 2');
$session->close();
$session->resume();
$this->assertTrue($session->isStarted());
$this->assertTrue($metaDataCache->has($sessionIdentifier1), 'session 1 meta entry doesnt exist');
$session->close();
$sessionInfo1 = $metaDataCache->get($sessionIdentifier1);
$sessionInfo1['lastActivityTimestamp'] = time() - 4000;
$metaDataCache->set($sessionIdentifier1, $sessionInfo1, ['session'], 0);
// Because we change the timeout post factum, the previously valid session
// now expires:
$settings['session']['inactivityTimeout'] = 3000;
// Create a second session which should remove the first expired session
// implicitly by calling autoExpire()
/** @var Session $session */
$session = $this->getAccessibleMock(Session::class, ['dummy']);
$this->inject($session, 'bootstrap', $this->mockBootstrap);
$this->inject($session, 'objectManager', $this->mockObjectManager);
$this->inject($session, 'metaDataCache', $this->createCache('Meta'));
$this->inject($session, 'storageCache', $this->createCache('Storage'));
$session->injectSettings($settings);
$session->initializeObject();
$session->start();
$sessionIdentifier2 = $session->getId();
$session->putData('session 2 key 1', 'session 1 value 1');
$session->putData('session 2 key 2', 'session 1 value 2');
$session->close();
// Calls autoExpire() internally:
$session->resume();
$sessionInfo2 = $metaDataCache->get($sessionIdentifier2);
// Check how the cache looks like - data of session 1 should be gone:
$this->assertFalse($metaDataCache->has($sessionIdentifier1), 'session 1 meta entry still there');
$this->assertFalse($storageCache->has($sessionInfo1['storageIdentifier'] . md5('session 1 key 1')), 'session 1 key 1 still there');
$this->assertFalse($storageCache->has($sessionInfo1['storageIdentifier'] . md5('session 1 key 2')), 'session 1 key 2 still there');
$this->assertTrue($storageCache->has($sessionInfo2['storageIdentifier'] . md5('session 2 key 1')), 'session 2 key 1 not there');
$this->assertTrue($storageCache->has($sessionInfo2['storageIdentifier'] . md5('session 2 key 2')), 'session 2 key 2 not there');
}