SessionTest.php 36 KB

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