SessionTest.php 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Session
  17. * @subpackage UnitTests
  18. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id$
  21. */
  22. /**
  23. * PHPUnit test case
  24. */
  25. require_once 'PHPUnit/Framework/TestCase.php';
  26. /**
  27. * @see Zend_Session
  28. */
  29. require_once 'Zend/Session.php';
  30. /**
  31. * Black box testing for Zend_Session
  32. *
  33. * @category Zend
  34. * @package Zend_Session
  35. * @subpackage UnitTests
  36. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  37. * @license http://framework.zend.com/license/new-bsd New BSD License
  38. * @group Zend_Session
  39. */
  40. class Zend_SessionTest extends PHPUnit_Framework_TestCase
  41. {
  42. /**
  43. * Helper script invoked via exec()
  44. *
  45. * @var string
  46. */
  47. protected $_script = null;
  48. /**
  49. * Storage for session.save_path, so that unit tests may change the value without side effect
  50. *
  51. * @var string
  52. */
  53. protected $_savePath;
  54. /**
  55. * Initializes instance data
  56. *
  57. * @return void
  58. */
  59. public function __construct($name = NULL, array $data = array(), $dataName = '')
  60. {
  61. parent::__construct($name, $data, $dataName);
  62. $this->_script = 'php '
  63. . '-c ' . escapeshellarg(php_ini_loaded_file()) . ' '
  64. . escapeshellarg(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'SessionTestHelper.php');
  65. $this->_savePath = ini_get('session.save_path');
  66. }
  67. /**
  68. * Set up tests environment
  69. */
  70. function setUp()
  71. {
  72. // _unitTestEnabled is utilised by other tests to handle session data processing
  73. // Zend_Session tests should pass with _unitTestEnabled turned off
  74. Zend_Session::$_unitTestEnabled = false;
  75. }
  76. /**
  77. * Cleanup operations after each test method is run
  78. *
  79. * @return void
  80. */
  81. public function tearDown()
  82. {
  83. ini_set('session.save_path', $this->_savePath);
  84. $this->assertSame(
  85. E_ALL | E_STRICT,
  86. error_reporting( E_ALL | E_STRICT ),
  87. 'A test altered error_reporting to something other than E_ALL | E_STRICT'
  88. );
  89. Zend_Session_Namespace::unlockAll();
  90. // unset all namespaces
  91. foreach (Zend_Session::getIterator() as $space) {
  92. try {
  93. Zend_Session::namespaceUnset($space);
  94. } catch (Zend_Session_Exception $e) {
  95. $this->assertRegexp('/read.only/i', $e->getMessage());
  96. return;
  97. }
  98. }
  99. }
  100. /**
  101. * Sorts the compound result returned by SessionTestHelper, so that the
  102. * order of iteration over namespace items do not impact analysis of test results.
  103. *
  104. * @param array $result output of exec()'ing SessionTestHelper
  105. * @return string sorted alphabetically
  106. */
  107. public function sortResult(array $result)
  108. {
  109. $results = explode(';', array_pop($result));
  110. sort($results);
  111. return implode(';', $results);
  112. }
  113. /**
  114. * test session id manipulations; expect isRegenerated flag == true
  115. *
  116. * @return void
  117. */
  118. public function testRegenerateId()
  119. {
  120. // Check if session hasn't already been started by another test
  121. if (!Zend_Session::isStarted()) {
  122. Zend_Session::setId('myid123');
  123. Zend_Session::regenerateId();
  124. $this->assertFalse(Zend_Session::isRegenerated());
  125. $id = Zend_Session::getId();
  126. $this->assertTrue($id === 'myid123',
  127. 'getId() reported something different than set via setId("myid123")');
  128. Zend_Session::start();
  129. } else {
  130. // Start session if it's not actually started
  131. // That may happen if Zend_Session::$_unitTestEnabled is turned on while some other
  132. // Unit tests utilize Zend_Session functionality
  133. if (!defined('SID')) {
  134. session_start();
  135. }
  136. // only regenerate session id if session has already been started
  137. Zend_Session::regenerateId();
  138. }
  139. $this->assertTrue(Zend_Session::isRegenerated());
  140. try {
  141. Zend_Session::setId('someo-therid-123');
  142. $this->fail('No exception was returned when trying to set the session id, after session_start()');
  143. } catch (Zend_Session_Exception $e) {
  144. $this->assertRegexp('/already.*started/i', $e->getMessage());
  145. }
  146. }
  147. /**
  148. * Ensures that setOptions() behaves as expected
  149. *
  150. * @return void
  151. */
  152. public function testSetOptions()
  153. {
  154. try {
  155. Zend_Session::setOptions(array('foo' => 'break me'));
  156. $this->fail('Expected Zend_Session_Exception not thrown when trying to set an invalid option');
  157. } catch (Zend_Session_Exception $e) {
  158. $this->assertRegexp('/unknown.option/i', $e->getMessage());
  159. }
  160. Zend_Session::setOptions(array('save_path' => '1;777;/tmp'));
  161. Zend_Session::setOptions(array('save_path' => '2;/tmp'));
  162. Zend_Session::setOptions(array('save_path' => '/tmp'));
  163. }
  164. /**
  165. * test for initialisation without parameter; expect instance
  166. *
  167. * @return void
  168. */
  169. public function testInit()
  170. {
  171. $s = new Zend_Session_Namespace();
  172. $this->assertTrue($s instanceof Zend_Session_Namespace,'Zend_Session Object not returned');
  173. }
  174. /**
  175. * test for initialisation with empty string; expect failure
  176. *
  177. * @return void
  178. */
  179. public function testInitEmpty()
  180. {
  181. try {
  182. $s = new Zend_Session_Namespace('');
  183. } catch (Zend_Session_Exception $e) {
  184. $this->assertRegexp('/non.empty.string/i', $e->getMessage());
  185. return;
  186. }
  187. $this->fail('No exception was returned when trying to create a namespace having the empty string as '
  188. . 'its name; expected Zend_Session_Exception');
  189. }
  190. /**
  191. * test for initialisation with Session parameter; expect instance
  192. *
  193. * @return void
  194. */
  195. public function testInitSession()
  196. {
  197. $s = new Zend_Session_Namespace('namespace');
  198. $this->assertTrue($s instanceof Zend_Session_Namespace, 'Zend_Session_Namespace object not returned');
  199. }
  200. /**
  201. * test for initialisation with single instance; expected instance
  202. *
  203. * @return void
  204. */
  205. public function testInitSingleInstance()
  206. {
  207. $s = new Zend_Session_Namespace('single', true);
  208. try {
  209. $s = new Zend_Session_Namespace('single', true);
  210. } catch (Zend_Session_Exception $e) {
  211. // session namespace 'single' already exists and is set to be the only instance of this namespace
  212. $this->assertRegexp('/already.*exist/i', $e->getMessage());
  213. return;
  214. }
  215. $this->fail('No exception was returned when creating a duplicate session for the same namespace, '
  216. . 'even though "single instance" was specified; expected Zend_Session_Exception');
  217. }
  218. /**
  219. * test for retrieval of non-existent keys in a valid namespace; expected null value
  220. * returned by getter for an unset key
  221. *
  222. * @return void
  223. */
  224. public function testNamespaceGetNull()
  225. {
  226. try {
  227. $s = new Zend_Session_Namespace();
  228. $s->tree = 'fig';
  229. $dog = $s->dog;
  230. $this->assertTrue($dog === null, "getting value of non-existent key failed to return null ($dog)");
  231. } catch (Zend_Session_Exception $e) {
  232. $this->fail('Unexpected exception returned when attempting to fetch the value of non-existent key');
  233. }
  234. }
  235. /**
  236. * test for existence of namespace; expected true
  237. *
  238. * @return void
  239. */
  240. public function testNamespaceIsset()
  241. {
  242. try {
  243. $this->assertFalse(Zend_Session::namespaceIsset('trees'),
  244. 'namespaceIsset() should have returned false for a namespace with no keys set');
  245. $s = new Zend_Session_Namespace('trees');
  246. $this->assertFalse(Zend_Session::namespaceIsset('trees'),
  247. 'namespaceIsset() should have returned false for a namespace with no keys set');
  248. $s->cherry = 'bing';
  249. $this->assertTrue(Zend_Session::namespaceIsset('trees'),
  250. 'namespaceIsset() should have returned true for a namespace with keys set');
  251. } catch (Zend_Session_Exception $e) {
  252. $this->fail('Unexpected exception returned when attempting to fetch the value of non-existent key');
  253. }
  254. }
  255. /**
  256. * test magic methods with improper variable interpolation; expect no exceptions
  257. *
  258. * @return void
  259. */
  260. public function testMagicMethodsEmpty()
  261. {
  262. $s = new Zend_Session_Namespace();
  263. $name = 'fruit';
  264. $s->$name = 'apples';
  265. $this->assertTrue(isset($s->fruit), 'isset() failed - returned false, but should have been true');
  266. try {
  267. $name = ''; // simulate a common bug, where user refers to an unset/empty variable
  268. $s->$name = 'pear';
  269. $this->fail('No exception was returned when trying to __set() a key named ""; expected '
  270. . 'Zend_Session_Exception');
  271. } catch (Zend_Session_Exception $e) {
  272. $this->assertRegexp('/non.empty.string/i', $e->getMessage());
  273. }
  274. try {
  275. $name = ''; // simulate a common bug, where user refers to an unset/empty variable
  276. $nothing = $s->$name;
  277. $this->fail('No exception was returned when trying to __set() a key named ""; expected '
  278. . 'Zend_Session_Exception');
  279. } catch (Zend_Session_Exception $e) {
  280. $this->assertRegexp('/non.empty.string/i', $e->getMessage());
  281. }
  282. try {
  283. $name = ''; // simulate a common bug, where user refers to an unset/empty variable
  284. if (isset($s->$name)) { true; }
  285. $this->fail('No exception was returned when trying to __set() a key named ""; expected '
  286. . 'Zend_Session_Exception');
  287. } catch (Zend_Session_Exception $e) {
  288. $this->assertRegexp('/non.empty.string/i', $e->getMessage());
  289. }
  290. try {
  291. $name = ''; // simulate a common bug, where user refers to an unset/empty variable
  292. unset($s->$name);
  293. $this->fail('No exception was returned when trying to __set() a key named ""; expected '
  294. . 'Zend_Session_Exception');
  295. } catch (Zend_Session_Exception $e) {
  296. $this->assertRegexp('/non.empty.string/i', $e->getMessage());
  297. }
  298. }
  299. /**
  300. * test for proper separation of namespace "spaces"; expect variables in different namespaces are
  301. * different variables (i.e., not shared values)
  302. *
  303. * @return void
  304. */
  305. public function testInitNamespaces()
  306. {
  307. $s1 = new Zend_Session_Namespace('namespace1');
  308. $s1b = new Zend_Session_Namespace('namespace1');
  309. $s2 = new Zend_Session_Namespace('namespace2');
  310. $s2b = new Zend_Session_Namespace('namespace2');
  311. $s3 = new Zend_Session_Namespace();
  312. $s3b = new Zend_Session_Namespace();
  313. $s1->a = 'apple';
  314. $s2->a = 'pear';
  315. $s3->a = 'orange';
  316. $this->assertTrue(($s1->a != $s2->a && $s1->a != $s3->a && $s2->a != $s3->a),
  317. 'Zend_Session improperly shared namespaces');
  318. $this->assertTrue(($s1->a === $s1b->a),'Zend_Session namespace error');
  319. $this->assertTrue(($s2->a === $s2b->a),'Zend_Session namespace error');
  320. $this->assertTrue(($s3->a === $s3b->a),'Zend_Session namespace error');
  321. }
  322. /**
  323. * test for detection of illegal namespace names; expect exception complaining about name beginning
  324. * with an underscore
  325. *
  326. * @return void
  327. */
  328. public function testInitNamespaceUnderscore()
  329. {
  330. try {
  331. $s = new Zend_Session_Namespace('_namespace');
  332. $this->fail('No exception was returned when requesting a namespace having a name beginning with '
  333. . 'an underscore');
  334. } catch (Zend_Session_Exception $e) {
  335. $this->assertRegexp('/underscore/i', $e->getMessage());
  336. }
  337. }
  338. /**
  339. * test for detection of illegal namespace names; expect exception complaining about name beginning
  340. * with an underscore
  341. *
  342. * @return void
  343. */
  344. public function testInitNamespaceNumber()
  345. {
  346. try {
  347. $s = new Zend_Session_Namespace('0namespace');
  348. $this->fail('No exception was returned when requesting a namespace having a name beginning with '
  349. . 'a number');
  350. } catch (Zend_Session_Exception $e) {
  351. $this->assertRegexp('/number/i', $e->getMessage());
  352. }
  353. }
  354. /**
  355. * test iteration; expect native PHP foreach statement is able to properly iterate all items in a session namespace
  356. *
  357. * @return void
  358. */
  359. public function testGetIterator()
  360. {
  361. $s = new Zend_Session_Namespace();
  362. $s->a = 'apple';
  363. $s->p = 'pear';
  364. $s->o = 'orange';
  365. $result = '';
  366. foreach ($s->getIterator() as $key => $val) {
  367. $result .= "$key === $val;";
  368. }
  369. $this->assertTrue($result === 'a === apple;p === pear;o === orange;',
  370. 'iteration over default Zend_Session namespace failed: result="' . $result . '"');
  371. $s = new Zend_Session_Namespace('namespace');
  372. $s->g = 'guava';
  373. $s->p = 'peach';
  374. $s->p = 'plum';
  375. $result = '';
  376. foreach ($s->getIterator() as $key => $val) {
  377. $result .= "$key === $val;";
  378. }
  379. $this->assertTrue($result === 'g === guava;p === plum;',
  380. 'iteration over named Zend_Session namespace failed');
  381. }
  382. /**
  383. * test locking of the Default namespace (i.e. make namespace readonly); expect exceptions when trying to write to
  384. * locked namespace
  385. *
  386. * @return void
  387. */
  388. public function testLock()
  389. {
  390. $s = new Zend_Session_Namespace();
  391. $s->a = 'apple';
  392. $s->p = 'pear';
  393. $s->lock();
  394. try {
  395. $s->o = 'orange';
  396. $this->fail('No exception was returned when setting a variable in the "Default" namespace, '
  397. . 'after marking the namespace as read-only; expected Zend_Session_Exception');
  398. } catch (Zend_Session_Exception $e) {
  399. // session namespace 'single' already exists and is set to be the only instance of this namespace
  400. $this->assertRegexp('/read.only/i', $e->getMessage());
  401. }
  402. $s->unlock();
  403. $s->o = 'orange';
  404. $s->p = 'papaya';
  405. $s->c = 'cherry';
  406. $s->lock();
  407. try {
  408. $s->o = 'orange';
  409. $this->fail('No exception was returned when setting a variable in the "Default" namespace, '
  410. . 'after marking the namespace as read-only; expected Zend_Session_Exception');
  411. } catch (Zend_Session_Exception $e) {
  412. // session namespace 'single' already exists and is set to be the only instance of this namespace
  413. $this->assertRegexp('/read.only/i', $e->getMessage());
  414. }
  415. }
  416. /**
  417. * test locking of named namespaces (i.e. make namespace readonly); expect exceptions when trying to write
  418. * to locked namespace
  419. *
  420. * @return void
  421. */
  422. public function testLockNamespace()
  423. {
  424. $s = new Zend_Session_Namespace('somenamespace');
  425. $s->a = 'apple';
  426. $s->p = 'pear';
  427. $s->lock();
  428. try {
  429. $s->o = 'orange';
  430. $this->fail('No exception was returned when setting a variable in the "Default" namespace, '
  431. . 'after marking the namespace as read-only; expected Zend_Session_Exception');
  432. } catch (Zend_Session_Exception $e) {
  433. // session namespace 'single' already exists and is set to be the only instance of this namespace
  434. $this->assertRegexp('/read.only/i', $e->getMessage());
  435. }
  436. $s = new Zend_Session_Namespace('somenamespace');
  437. $s2 = new Zend_Session_Namespace('mayday');
  438. $s2->lock();
  439. $s->unlock();
  440. $s->o = 'orange';
  441. $s->p = 'papaya';
  442. $s->c = 'cherry';
  443. $s = new Zend_Session_Namespace('somenamespace');
  444. $s->lock();
  445. $s2->unlock();
  446. try {
  447. $s->o = 'orange';
  448. $this->fail('No exception was returned when setting a variable in the "Default" namespace, '
  449. . 'after marking the namespace as read-only; expected Zend_Session_Exception');
  450. } catch (Zend_Session_Exception $e) {
  451. $this->assertRegexp('/read.only/i', $e->getMessage());
  452. }
  453. }
  454. /**
  455. * test unlocking of the Default namespace (i.e. make namespace readonly); expected no exceptions
  456. *
  457. * @return void
  458. */
  459. public function testUnlock()
  460. {
  461. $s = new Zend_Session_Namespace();
  462. try {
  463. $s->a = 'apple';
  464. $s->p = 'pear';
  465. $s->lock();
  466. $s->unlock();
  467. $s->o = 'orange';
  468. $s->p = 'prune';
  469. $s->lock();
  470. $s->unlock();
  471. $s->o = 'orange';
  472. $s->p = 'papaya';
  473. $s->c = 'cherry';
  474. } catch (Zend_Session_Exception $e) {
  475. $this->fail('Unexpected exception when writing to namespaces after unlocking it.');
  476. }
  477. }
  478. /**
  479. * test combinations of locking and unlocking of the Default namespace (i.e. make namespace readonly)
  480. * expected no exceptions
  481. *
  482. * @return void
  483. */
  484. public function testUnLockAll()
  485. {
  486. $sessions = array('one', 'two', 'default', 'three');
  487. foreach ($sessions as $namespace) {
  488. $s = new Zend_Session_Namespace($namespace);
  489. $s->a = 'apple';
  490. $s->p = 'pear';
  491. $s->lock();
  492. $s->unlock();
  493. $s->o = 'orange';
  494. $s->p = 'prune';
  495. $s->lock();
  496. $s->unlock();
  497. $s->o = 'orange';
  498. $s->p = 'papaya';
  499. $s->c = 'cherry';
  500. $s->lock();
  501. $this->assertTrue($s->isLocked(), 'isLocked() returned incorrect status (not locked)');
  502. try {
  503. $s->p = 'prune';
  504. $s->f = 'fig';
  505. $this->fail('No exception was returned when setting a variable in the "Default" namespace, '
  506. . 'after marking the namespace as read-only; expected Zend_Session_Exception');
  507. } catch (Zend_Session_Exception $e) {
  508. $this->assertRegexp('/read.only/i', $e->getMessage());
  509. }
  510. }
  511. $s->unlockAll();
  512. foreach ($sessions as $namespace) {
  513. $this->assertFalse($s->isLocked(), 'isLocked() returned incorrect status (locked)');
  514. $s->p = 'pear';
  515. $s->f = 'fig';
  516. $s->l = 'lime';
  517. }
  518. }
  519. /**
  520. * test isLocked() unary comparison operator under various situations; expect lock status remains synchronized
  521. * with last call to unlock() or lock(); expect no exceptions
  522. *
  523. * @return void
  524. */
  525. public function testIsLocked()
  526. {
  527. try {
  528. $s = new Zend_Session_Namespace();
  529. $s->a = 'apple';
  530. $s->p = 'pear';
  531. $this->assertFalse($s->isLocked(), 'isLocked() returned incorrect status (locked)');
  532. $s->lock();
  533. $this->assertTrue($s->isLocked(), 'isLocked() returned incorrect status (unlocked)');
  534. $s->unlock();
  535. $s->o = 'orange';
  536. $s->p = 'prune';
  537. $this->assertFalse($s->isLocked(), 'isLocked() returned incorrect status (locked)');
  538. $s->lock();
  539. $this->assertTrue($s->isLocked(), 'isLocked() returned incorrect status (unlocked)');
  540. $s->unlock();
  541. $this->assertFalse($s->isLocked(), 'isLocked() returned incorrect status (locked)');
  542. $s->o = 'orange';
  543. $s->p = 'papaya';
  544. $s->c = 'cherry';
  545. $this->assertFalse($s->isLocked(), 'isLocked() returned incorrect status (locked)');
  546. } catch (Zend_Session_Exception $e) {
  547. $this->fail('Unexpected exception when writing to named namespaces after unlocking them.');
  548. }
  549. }
  550. /**
  551. * test unlocking of named namespaces (i.e., make namespace readonly); expect no exceptions
  552. *
  553. * @return void
  554. */
  555. public function testUnLockNamespace()
  556. {
  557. $s = new Zend_Session_Namespace('somenamespace');
  558. try {
  559. $s->a = 'apple';
  560. $s->p = 'pear';
  561. $s->lock();
  562. $s2 = new Zend_Session_Namespace('mayday');
  563. $s2->lock();
  564. $s->unlock();
  565. $s->o = 'orange';
  566. $s->p = 'prune';
  567. $s->lock();
  568. $s->unlock();
  569. $s->o = 'orange';
  570. $s->p = 'papaya';
  571. $s->c = 'cherry';
  572. } catch (Zend_Session_Exception $e) {
  573. $this->fail('Unexpected exception when writing to named namespaces after unlocking them.');
  574. }
  575. }
  576. /**
  577. * test isLocked() unary comparison operator under various situations; expect lock status remains synchronized with
  578. * last call to unlock() or lock(); expect no exceptions
  579. *
  580. * @return void
  581. */
  582. public function testIsLockedNamespace()
  583. {
  584. try {
  585. $s = new Zend_Session_Namespace('somenamespace');
  586. $s->a = 'apple';
  587. $s->p = 'pear';
  588. $this->assertFalse($s->isLocked(), 'isLocked() returned incorrect status (locked)');
  589. $s->lock();
  590. $s2 = new Zend_Session_Namespace('mayday');
  591. $s2->lock();
  592. $this->assertTrue($s->isLocked(), 'isLocked() returned incorrect status (unlocked)');
  593. $s->unlock();
  594. $s->o = 'orange';
  595. $s->p = 'prune';
  596. $this->assertFalse($s->isLocked(), 'isLocked() returned incorrect status (locked)');
  597. $s->lock();
  598. $s2->unlock();
  599. $this->assertTrue($s->isLocked(), 'isLocked() returned incorrect status (unlocked)');
  600. $s->unlock();
  601. $this->assertFalse($s->isLocked(), 'isLocked() returned incorrect status (locked)');
  602. $s->o = 'orange';
  603. $s->p = 'papaya';
  604. $s->c = 'cherry';
  605. $this->assertFalse($s->isLocked(), 'isLocked() returned incorrect status (locked)');
  606. } catch (Zend_Session_Exception $e) {
  607. $this->fail('Unexpected exception when writing to named namespaces after unlocking them.');
  608. }
  609. }
  610. /**
  611. * test unsetAll keys in default namespace; expect namespace contains only keys not unset()
  612. *
  613. * @return void
  614. */
  615. public function testUnsetAll()
  616. {
  617. $s = new Zend_Session_Namespace();
  618. $result = '';
  619. foreach ($s->getIterator() as $key => $val) {
  620. $result .= "$key === $val;";
  621. }
  622. $this->assertTrue(empty($result), "tearDown failure, found keys in default namespace: '$result'");
  623. $s->a = 'apple';
  624. $s->lock();
  625. $s->unlock();
  626. $s->p = 'papaya';
  627. $s->c = 'cherry';
  628. $s = new Zend_Session_Namespace();
  629. $result = '';
  630. foreach ($s->getIterator() as $key => $val) {
  631. $result .= "$key === $val;";
  632. }
  633. $this->assertTrue($result === 'a === apple;p === papaya;c === cherry;',
  634. "unsetAll() setup for test failed: '$result'");
  635. $s->unsetAll();
  636. $result = '';
  637. foreach ($s->getIterator() as $key => $val) {
  638. $result .= "$key === $val;";
  639. }
  640. $this->assertTrue(empty($result), "unsetAll() did not remove keys from namespace: '$result'");
  641. }
  642. /**
  643. * test unset() keys in default namespace; expect namespace contains only keys not unset()
  644. *
  645. * @return void
  646. */
  647. public function testUnset()
  648. {
  649. $s = new Zend_Session_Namespace();
  650. $result = '';
  651. foreach ($s->getIterator() as $key => $val) {
  652. $result .= "$key === $val;";
  653. }
  654. $this->assertTrue(empty($result), "tearDown failure, found keys in default namespace: '$result'");
  655. $s->a = 'apple';
  656. $s->lock();
  657. $s->unlock();
  658. $s->p = 'papaya';
  659. $s->c = 'cherry';
  660. $s = new Zend_Session_Namespace();
  661. foreach ($s->getIterator() as $key => $val) {
  662. unset($s->$key);
  663. }
  664. $result = '';
  665. foreach ($s->getIterator() as $key => $val) {
  666. $result .= "$key === $val;";
  667. }
  668. $this->assertTrue(empty($result), "unsetAll() did not remove keys from namespace: '$result'");
  669. }
  670. /**
  671. * test unset() keys in non-default namespace; expect namespace contains only keys not unset()
  672. *
  673. * @return void
  674. */
  675. public function testUnsetNamespace()
  676. {
  677. $s = new Zend_Session_Namespace('foobar');
  678. $result = '';
  679. foreach ($s->getIterator() as $key => $val) {
  680. $result .= "$key === $val;";
  681. }
  682. $this->assertTrue(empty($result), "tearDown failure, found keys in default namespace: '$result'");
  683. $s->a = 'apple';
  684. $s->lock();
  685. $s->unlock();
  686. $s->p = 'papaya';
  687. $s->c = 'cherry';
  688. $s = new Zend_Session_Namespace('foobar');
  689. foreach ($s->getIterator() as $key => $val) {
  690. unset($s->$key);
  691. }
  692. $result = '';
  693. foreach ($s->getIterator() as $key => $val) {
  694. $result .= "$key === $val;";
  695. }
  696. $this->assertTrue(empty($result), "unsetAll() did not remove keys from namespace: '$result'");
  697. }
  698. /**
  699. * test unsetAll keys in default namespace; expect namespace will contain no keys
  700. *
  701. * @return void
  702. */
  703. public function testUnsetAllNamespace()
  704. {
  705. $s = new Zend_Session_Namespace('somenamespace');
  706. $result = '';
  707. foreach ($s->getIterator() as $key => $val) {
  708. $result .= "$key === $val;";
  709. }
  710. $this->assertTrue(empty($result), "tearDown failure, found keys in 'somenamespace' namespace: '$result'");
  711. $s->a = 'apple';
  712. $s->lock();
  713. $s->unlock();
  714. $s->p = 'papaya';
  715. $s->c = 'cherry';
  716. $s = new Zend_Session_Namespace('somenamespace');
  717. $result = '';
  718. foreach ($s->getIterator() as $key => $val) {
  719. $result .= "$key === $val;";
  720. }
  721. $this->assertTrue($result === 'a === apple;p === papaya;c === cherry;',
  722. "unsetAll() setup for test failed: '$result'");
  723. $s->unsetAll();
  724. $result = '';
  725. foreach ($s->getIterator() as $key => $val) {
  726. $result .= "$key === $val;";
  727. }
  728. $this->assertTrue(empty($result), "unsetAll() did not remove keys from namespace: '$result'");
  729. }
  730. /**
  731. * test expiration of namespaces and namespace variables by seconds; expect expiration of specified keys/namespace
  732. *
  733. * @return void
  734. */
  735. public function testSetExpirationSeconds()
  736. {
  737. // Calculate common script execution time
  738. $startTime = time();
  739. exec($this->_script, $result, $returnValue);
  740. $execTime = time() - $startTime;
  741. $s = new Zend_Session_Namespace('expireAll');
  742. $s->a = 'apple';
  743. $s->p = 'pear';
  744. $s->o = 'orange';
  745. $s->setExpirationSeconds($execTime*2 + 5);
  746. Zend_Session::regenerateId();
  747. $id = Zend_Session::getId();
  748. sleep(4); // not long enough for things to expire
  749. session_write_close(); // release session so process below can use it
  750. exec("$this->_script expireAll $id expireAll", $result, $returnValue);
  751. session_start(); // resume artificially suspended session
  752. $result = $this->sortResult($result);
  753. $expect = ';a === apple;o === orange;p === pear';
  754. $this->assertTrue($result === $expect,
  755. "iteration over default Zend_Session namespace failed; expecting result === '$expect', but got '$result'");
  756. sleep($execTime*2 + 2); // long enough for things to expire (total of $execTime*2 + 6 seconds waiting, but expires in $execTime*2 + 5)
  757. session_write_close(); // release session so process below can use it
  758. exec("$this->_script expireAll $id expireAll", $result, $returnValue);
  759. session_start(); // resume artificially suspended session
  760. $this->assertNull(array_pop($result));
  761. // We could split this into a separate test, but actually, if anything leftover from above
  762. // contaminates the tests below, that is also a bug that we want to know about.
  763. $s = new Zend_Session_Namespace('expireGuava');
  764. $s->setExpirationSeconds(5, 'g'); // now try to expire only 1 of the keys in the namespace
  765. $s->g = 'guava';
  766. $s->p = 'peach';
  767. $s->p = 'plum';
  768. sleep(6); // not long enough for things to expire
  769. session_write_close(); // release session so process below can use it
  770. exec("$this->_script expireAll $id expireGuava", $result, $returnValue);
  771. session_start(); // resume artificially suspended session
  772. $result = $this->sortResult($result);
  773. $this->assertTrue($result === ';p === plum',
  774. "iteration over named Zend_Session namespace failed (result=$result)");
  775. }
  776. /**
  777. * test expiration of namespaces by hops; expect expiration of specified namespace in the proper number of hops
  778. *
  779. * @return void
  780. */
  781. public function testSetExpireSessionHops()
  782. {
  783. $s = new Zend_Session_Namespace('expireAll');
  784. $s->a = 'apple';
  785. $s->p = 'pear';
  786. $s->o = 'orange';
  787. $expireBeforeHop = 3;
  788. $s->setExpirationHops($expireBeforeHop);
  789. $id = session_id();
  790. for ($i = 1; $i <= ($expireBeforeHop + 2); $i++) {
  791. session_write_close(); // release session so process below can use it
  792. exec("$this->_script expireAll $id expireAll", $result, $returnValue);
  793. session_start(); // resume artificially suspended session
  794. $result = $this->sortResult($result);
  795. if ($i > $expireBeforeHop) {
  796. $this->assertTrue($result === '',
  797. "iteration over default Zend_Session namespace failed (result='$result'; hop #$i)");
  798. } else {
  799. $this->assertTrue($result === ';a === apple;o === orange;p === pear',
  800. "iteration over default Zend_Session namespace failed (result='$result'; hop #$i)");
  801. }
  802. }
  803. }
  804. /**
  805. * test expiration of namespace variables by hops; expect expiration of specified keys in the proper number of hops
  806. *
  807. * @return void
  808. */
  809. public function testSetExpireSessionVarsByHops1()
  810. {
  811. $this->setExpireSessionVarsByHops();
  812. }
  813. /**
  814. * sanity check .. we should be able to repeat this test without problems
  815. *
  816. * @return void
  817. */
  818. public function testSetExpireSessionVarsByHops2()
  819. {
  820. $this->setExpireSessionVarsByHops();
  821. }
  822. /**
  823. * test expiration of namespace variables by hops; expect expiration of specified keys in the proper number of hops
  824. *
  825. * @return void
  826. */
  827. public function setExpireSessionVarsByHops()
  828. {
  829. $s = new Zend_Session_Namespace('expireGuava');
  830. $expireBeforeHop = 4;
  831. $s->setExpirationHops($expireBeforeHop, 'g');
  832. $s->g = 'guava';
  833. $s->p = 'peach';
  834. $s->p = 'plum';
  835. $id = session_id();
  836. for ($i = 1; $i <= ($expireBeforeHop + 2); $i++) {
  837. session_write_close(); // release session so process below can use it
  838. exec("$this->_script expireAll $id expireGuava", $result);
  839. session_start(); // resume artificially suspended session
  840. $result = $this->sortResult($result);
  841. if ($i > $expireBeforeHop) {
  842. $this->assertTrue($result === ';p === plum',
  843. "iteration over named Zend_Session namespace failed (result='$result'; hop #$i)");
  844. } else {
  845. $this->assertTrue($result === ';g === guava;p === plum',
  846. "iteration over named Zend_Session namespace failed (result='$result'; hop #$i)");
  847. }
  848. }
  849. }
  850. /**
  851. * @todo PHP 5.2.1 is required (fixes a bug with magic __get() returning by reference)
  852. * @see http://framework.zend.com/issues/browse/ZF-800
  853. */
  854. public function testArrays()
  855. {
  856. $this->markTestIncomplete();
  857. $s = new Zend_Session_Namespace('aspace');
  858. $id = Zend_Session::getId();
  859. $this->assertSame($id, session_id());
  860. $s->top = 'begin';
  861. session_write_close(); // release session so process below can use it
  862. exec("$this->_script setArray $id aspace 1 2 3 4 5", $result);
  863. exec("$this->_script getArray $id aspace", $result);
  864. session_start(); // resume artificially suspended session
  865. $result = array_pop($result);
  866. $expect = 'top === begin;astring === happy;someArray === Array;(;[0]=>aspace;[1]=>1;[2]=>2;[3]=>3;[4]=>4;[5]=>5;[bee]=>honey;[ant]=>sugar;[dog]=>cat;);;serializedArray === a:8:{i:0;s:6:"aspace";i:1;s:1:"1";i:2;s:1:"2";i:3;s:1:"3";i:4;s:1:"4";i:5;s:1:"5";s:3:"ant";s:5:"sugar";s:3:"dog";s:3:"cat";};';
  867. $this->assertTrue($result === $expect,
  868. "iteration over default Zend_Session namespace failed; expecting result ===\n$expect\n, but got\n$result\n)");
  869. }
  870. /**
  871. * test expiration of namespace variables by hops; expect expiration of specified keys in the proper number of hops
  872. *
  873. * @return void
  874. */
  875. public function testSetExpireSessionVarsByHopsOnUse()
  876. {
  877. $s = new Zend_Session_Namespace('expireGuava');
  878. $expireBeforeHop = 2;
  879. $s->setExpirationHops($expireBeforeHop, 'g', true); // only count a hop, when namespace is used
  880. $s->g = 'guava';
  881. $s->p = 'peach';
  882. $s->p = 'plum';
  883. $id = session_id();
  884. // we are not accessing (using) the "expireGuava" namespace, so these hops should have no effect
  885. for ($i = 1; $i <= ($expireBeforeHop + 2); $i++) {
  886. session_write_close(); // release session so process below can use it
  887. exec("$this->_script expireAll $id notused", $result);
  888. session_start(); // resume artificially suspended session
  889. $result = $this->sortResult($result);
  890. $this->assertTrue($result === '',
  891. "iteration over named Zend_Session namespace failed (result='$result'; hop #$i)");
  892. }
  893. for ($i = 1; $i <= ($expireBeforeHop + 2); $i++) {
  894. session_write_close(); // release session so process below can use it
  895. exec("$this->_script expireAll $id expireGuava", $result);
  896. session_start(); // resume artificially suspended session
  897. $result = $this->sortResult($result);
  898. if ($i > $expireBeforeHop) {
  899. $expect = ';p === plum';
  900. $this->assertTrue($result === $expect,
  901. "unexpected results iterating over named Zend_Session namespace (result='$result'; expected '$expect'; hop #$i)");
  902. } else {
  903. $expect = ';g === guava;p === plum';
  904. $this->assertTrue($result === $expect,
  905. "unexpected results iterating over named Zend_Session namespace (result='$result'; expected '$expect'; hop #$i)");
  906. }
  907. }
  908. // Do not destroy session since it still may be used by other tests
  909. // Zend_Session::destroy();
  910. }
  911. /**
  912. * @group ZF-5003
  913. */
  914. public function testProcessSessionMetadataShouldNotThrowAnError()
  915. {
  916. Zend_Session::$_unitTestEnabled = true;
  917. if (isset($_SESSION) && isset($_SESSION['__ZF'])) {
  918. unset($_SESSION['__ZF']);
  919. }
  920. Zend_Session::start();
  921. }
  922. /**
  923. * test for method getNamespace()
  924. *
  925. * @group ZF-1982
  926. * @return void
  927. */
  928. public function testGetNameSpaceMethod()
  929. {
  930. Zend_Session::$_unitTestEnabled = true;
  931. $namespace = array(
  932. 'FooBar',
  933. 'Foo_Bar',
  934. 'Foo-Bar',
  935. 'Foo1000'
  936. );
  937. foreach ($namespace as $v) {
  938. $s = new Zend_Session_Namespace($v);
  939. $this->assertEquals($v, $s->getNamespace());
  940. }
  941. }
  942. }