1<?php 2 3/* 4 * This file is part of the Symfony package. 5 * 6 * (c) Fabien Potencier <fabien@symfony.com> 7 * 8 * For the full copyright and license information, please view the LICENSE 9 * file that was distributed with this source code. 10 */ 11 12namespace Symfony\Component\HttpFoundation\Tests\Session\Storage; 13 14use PHPUnit\Framework\TestCase; 15use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; 16use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; 17use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeFileSessionHandler; 18use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler; 19use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; 20use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy; 21 22/** 23 * Test class for NativeSessionStorage. 24 * 25 * @author Drak <drak@zikula.org> 26 * 27 * These tests require separate processes. 28 * 29 * @runTestsInSeparateProcesses 30 * @preserveGlobalState disabled 31 */ 32class NativeSessionStorageTest extends TestCase 33{ 34 private $savePath; 35 36 protected function setUp() 37 { 38 $this->iniSet('session.save_handler', 'files'); 39 $this->iniSet('session.save_path', $this->savePath = sys_get_temp_dir().'/sf2test'); 40 if (!is_dir($this->savePath)) { 41 mkdir($this->savePath); 42 } 43 } 44 45 protected function tearDown() 46 { 47 session_write_close(); 48 array_map('unlink', glob($this->savePath.'/*')); 49 if (is_dir($this->savePath)) { 50 rmdir($this->savePath); 51 } 52 53 $this->savePath = null; 54 } 55 56 /** 57 * @return NativeSessionStorage 58 */ 59 protected function getStorage(array $options = array()) 60 { 61 $storage = new NativeSessionStorage($options); 62 $storage->registerBag(new AttributeBag()); 63 64 return $storage; 65 } 66 67 public function testBag() 68 { 69 $storage = $this->getStorage(); 70 $bag = new FlashBag(); 71 $storage->registerBag($bag); 72 $this->assertSame($bag, $storage->getBag($bag->getName())); 73 } 74 75 /** 76 * @expectedException \InvalidArgumentException 77 */ 78 public function testRegisterBagException() 79 { 80 $storage = $this->getStorage(); 81 $storage->getBag('non_existing'); 82 } 83 84 /** 85 * @expectedException \LogicException 86 */ 87 public function testRegisterBagForAStartedSessionThrowsException() 88 { 89 $storage = $this->getStorage(); 90 $storage->start(); 91 $storage->registerBag(new AttributeBag()); 92 } 93 94 public function testGetId() 95 { 96 $storage = $this->getStorage(); 97 $this->assertSame('', $storage->getId(), 'Empty ID before starting session'); 98 99 $storage->start(); 100 $id = $storage->getId(); 101 $this->assertInternalType('string', $id); 102 $this->assertNotSame('', $id); 103 104 $storage->save(); 105 $this->assertSame($id, $storage->getId(), 'ID stays after saving session'); 106 } 107 108 public function testRegenerate() 109 { 110 $storage = $this->getStorage(); 111 $storage->start(); 112 $id = $storage->getId(); 113 $storage->getBag('attributes')->set('lucky', 7); 114 $storage->regenerate(); 115 $this->assertNotEquals($id, $storage->getId()); 116 $this->assertEquals(7, $storage->getBag('attributes')->get('lucky')); 117 } 118 119 public function testRegenerateDestroy() 120 { 121 $storage = $this->getStorage(); 122 $storage->start(); 123 $id = $storage->getId(); 124 $storage->getBag('attributes')->set('legs', 11); 125 $storage->regenerate(true); 126 $this->assertNotEquals($id, $storage->getId()); 127 $this->assertEquals(11, $storage->getBag('attributes')->get('legs')); 128 } 129 130 public function testSessionGlobalIsUpToDateAfterIdRegeneration() 131 { 132 $storage = $this->getStorage(); 133 $storage->start(); 134 $storage->getBag('attributes')->set('lucky', 7); 135 $storage->regenerate(); 136 $storage->getBag('attributes')->set('lucky', 42); 137 138 $this->assertEquals(42, $_SESSION['_sf2_attributes']['lucky']); 139 } 140 141 public function testRegenerationFailureDoesNotFlagStorageAsStarted() 142 { 143 $storage = $this->getStorage(); 144 $this->assertFalse($storage->regenerate()); 145 $this->assertFalse($storage->isStarted()); 146 } 147 148 public function testDefaultSessionCacheLimiter() 149 { 150 $this->iniSet('session.cache_limiter', 'nocache'); 151 152 $storage = new NativeSessionStorage(); 153 $this->assertEquals('', ini_get('session.cache_limiter')); 154 } 155 156 public function testExplicitSessionCacheLimiter() 157 { 158 $this->iniSet('session.cache_limiter', 'nocache'); 159 160 $storage = new NativeSessionStorage(array('cache_limiter' => 'public')); 161 $this->assertEquals('public', ini_get('session.cache_limiter')); 162 } 163 164 public function testCookieOptions() 165 { 166 $options = array( 167 'cookie_lifetime' => 123456, 168 'cookie_path' => '/my/cookie/path', 169 'cookie_domain' => 'symfony.example.com', 170 'cookie_secure' => true, 171 'cookie_httponly' => false, 172 ); 173 174 $this->getStorage($options); 175 $temp = session_get_cookie_params(); 176 $gco = array(); 177 178 foreach ($temp as $key => $value) { 179 $gco['cookie_'.$key] = $value; 180 } 181 182 $this->assertEquals($options, $gco); 183 } 184 185 /** 186 * @expectedException \InvalidArgumentException 187 */ 188 public function testSetSaveHandlerException() 189 { 190 $storage = $this->getStorage(); 191 $storage->setSaveHandler(new \stdClass()); 192 } 193 194 public function testSetSaveHandler() 195 { 196 $this->iniSet('session.save_handler', 'files'); 197 $storage = $this->getStorage(); 198 $storage->setSaveHandler(); 199 $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler()); 200 $storage->setSaveHandler(null); 201 $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler()); 202 $storage->setSaveHandler(new SessionHandlerProxy(new NativeFileSessionHandler())); 203 $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler()); 204 $storage->setSaveHandler(new NativeFileSessionHandler()); 205 $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler()); 206 $storage->setSaveHandler(new SessionHandlerProxy(new NullSessionHandler())); 207 $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler()); 208 $storage->setSaveHandler(new NullSessionHandler()); 209 $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler()); 210 } 211 212 /** 213 * @expectedException \RuntimeException 214 */ 215 public function testStarted() 216 { 217 $storage = $this->getStorage(); 218 219 $this->assertFalse($storage->getSaveHandler()->isActive()); 220 $this->assertFalse($storage->isStarted()); 221 222 session_start(); 223 $this->assertTrue(isset($_SESSION)); 224 $this->assertTrue($storage->getSaveHandler()->isActive()); 225 226 // PHP session might have started, but the storage driver has not, so false is correct here 227 $this->assertFalse($storage->isStarted()); 228 229 $key = $storage->getMetadataBag()->getStorageKey(); 230 $this->assertArrayNotHasKey($key, $_SESSION); 231 $storage->start(); 232 } 233 234 public function testRestart() 235 { 236 $storage = $this->getStorage(); 237 $storage->start(); 238 $id = $storage->getId(); 239 $storage->getBag('attributes')->set('lucky', 7); 240 $storage->save(); 241 $storage->start(); 242 $this->assertSame($id, $storage->getId(), 'Same session ID after restarting'); 243 $this->assertSame(7, $storage->getBag('attributes')->get('lucky'), 'Data still available'); 244 } 245 246 public function testCanCreateNativeSessionStorageWhenSessionAlreadyStarted() 247 { 248 session_start(); 249 $this->getStorage(); 250 251 // Assert no exception has been thrown by `getStorage()` 252 $this->addToAssertionCount(1); 253 } 254 255 public function testSetSessionOptionsOnceSessionStartedIsIgnored() 256 { 257 session_start(); 258 $this->getStorage(array( 259 'name' => 'something-else', 260 )); 261 262 // Assert no exception has been thrown by `getStorage()` 263 $this->addToAssertionCount(1); 264 } 265 266 public function testGetBagsOnceSessionStartedIsIgnored() 267 { 268 session_start(); 269 $bag = new AttributeBag(); 270 $bag->setName('flashes'); 271 272 $storage = $this->getStorage(); 273 $storage->registerBag($bag); 274 275 $this->assertEquals($storage->getBag('flashes'), $bag); 276 } 277} 278