NativeSessionStorageTest.php 9.8 KB

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