DbTableTest.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Framework\Session\SaveHandler;
  7. use Magento\Framework\App\ResourceConnection;
  8. class DbTableTest extends \PHPUnit\Framework\TestCase
  9. {
  10. /**
  11. * Test session ID
  12. */
  13. const SESSION_ID = 'session_id_value';
  14. /**#@+
  15. * Session keys
  16. */
  17. const SESSION_NEW = 'session_new';
  18. const SESSION_EXISTS = 'session_exists';
  19. /**#@-*/
  20. /**#@+
  21. * Table column names
  22. */
  23. const COLUMN_SESSION_ID = 'session_id';
  24. const COLUMN_SESSION_DATA = 'session_data';
  25. const COLUMN_SESSION_EXPIRES = 'session_expires';
  26. /**#@-*/
  27. /**
  28. * Test session data
  29. *
  30. * @var array
  31. */
  32. protected $_sourceData = [
  33. self::SESSION_NEW => ['new key' => 'new value'],
  34. self::SESSION_EXISTS => ['existing key' => 'existing value'],
  35. ];
  36. /**
  37. * Data as objects for serialization
  38. *
  39. * @var array
  40. */
  41. protected $_sessionData;
  42. /**
  43. * @var \Magento\TestFramework\ObjectManager
  44. */
  45. protected $_objectManager;
  46. /**
  47. * Model under test
  48. *
  49. * @var \Magento\Framework\Session\SaveHandler\DbTable
  50. */
  51. protected $_model;
  52. /**
  53. * Write connection adapter
  54. *
  55. * @var \Magento\Framework\DB\Adapter\AdapterInterface
  56. */
  57. protected $_connection;
  58. /**
  59. * Session table name
  60. *
  61. * @var string
  62. */
  63. protected $_sessionTable;
  64. /**
  65. * @return void
  66. */
  67. protected function setUp()
  68. {
  69. $this->_objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
  70. $this->_model = $this->_objectManager->get(\Magento\Framework\Session\SaveHandler\DbTable::class);
  71. /** @var $resource \Magento\Framework\App\ResourceConnection */
  72. $resource = $this->_objectManager->get(\Magento\Framework\App\ResourceConnection::class);
  73. $this->_connection = $resource->getConnection();
  74. $this->_sessionTable = $resource->getTableName('session');
  75. // session stores serialized objects with protected properties
  76. // we need to test this case to ensure that DB adapter successfully processes "\0" symbols in serialized data
  77. foreach ($this->_sourceData as $key => $data) {
  78. $this->_sessionData[$key] = new \Magento\Framework\DataObject($data);
  79. }
  80. }
  81. /**
  82. * @return void
  83. */
  84. public function testCheckConnection()
  85. {
  86. $method = new \ReflectionMethod(\Magento\Framework\Session\SaveHandler\DbTable::class, 'checkConnection');
  87. $method->setAccessible(true);
  88. $this->assertNull($method->invoke($this->_model));
  89. }
  90. /**
  91. * @return void
  92. */
  93. public function testOpenAndClose()
  94. {
  95. $this->assertTrue($this->_model->open('', 'test'));
  96. $this->assertTrue($this->_model->close());
  97. }
  98. /**
  99. * @return void
  100. */
  101. public function testWriteReadDestroy()
  102. {
  103. $data = serialize($this->_sessionData[self::SESSION_NEW]);
  104. $this->_model->write(self::SESSION_ID, $data);
  105. $this->assertEquals($data, $this->_model->read(self::SESSION_ID));
  106. $data = serialize($this->_sessionData[self::SESSION_EXISTS]);
  107. $this->_model->write(self::SESSION_ID, $data);
  108. $this->assertEquals($data, $this->_model->read(self::SESSION_ID));
  109. $this->_model->destroy(self::SESSION_ID);
  110. $this->assertEmpty($this->_model->read(self::SESSION_ID));
  111. }
  112. /**
  113. * @return void
  114. */
  115. public function testGc()
  116. {
  117. $this->_model->write('test', 'test');
  118. $this->assertEquals('test', $this->_model->read('test'));
  119. $this->_model->gc(-1);
  120. $this->assertEmpty($this->_model->read('test'));
  121. }
  122. /**
  123. * Assert that session data writes to DB in base64 encoding
  124. *
  125. * @return void
  126. */
  127. public function testWriteEncoded()
  128. {
  129. $data = serialize($this->_sessionData[self::SESSION_NEW]);
  130. $this->_model->write(self::SESSION_ID, $data);
  131. $select = $this->_connection->select()->from(
  132. $this->_sessionTable
  133. )->where(
  134. self::COLUMN_SESSION_ID . ' = :' . self::COLUMN_SESSION_ID
  135. );
  136. $bind = [self::COLUMN_SESSION_ID => self::SESSION_ID];
  137. $session = $this->_connection->fetchRow($select, $bind);
  138. $this->assertEquals(self::SESSION_ID, $session[self::COLUMN_SESSION_ID]);
  139. $this->assertTrue(
  140. ctype_digit((string)$session[self::COLUMN_SESSION_EXPIRES]),
  141. 'Value of session expire field must have integer type'
  142. );
  143. $this->assertEquals($data, base64_decode($session[self::COLUMN_SESSION_DATA]));
  144. }
  145. /**
  146. * Data provider for testReadEncoded
  147. *
  148. * @return array
  149. */
  150. public function readEncodedDataProvider()
  151. {
  152. // we can't use object data as a fixture because not encoded serialized object
  153. // might cause DB adapter fatal error, so we have to use array as a fixture
  154. $sessionData = serialize($this->_sourceData[self::SESSION_NEW]);
  155. return [
  156. 'session_encoded' => ['$sessionData' => base64_encode($sessionData)],
  157. 'session_not_encoded' => ['$sessionData' => $sessionData]
  158. ];
  159. }
  160. /**
  161. * Assert that session data reads from DB correctly regardless of encoding
  162. *
  163. * @param string $sessionData
  164. *
  165. * @dataProvider readEncodedDataProvider
  166. *
  167. * @return void
  168. */
  169. public function testReadEncoded($sessionData)
  170. {
  171. $sessionRecord = [self::COLUMN_SESSION_ID => self::SESSION_ID, self::COLUMN_SESSION_DATA => $sessionData];
  172. $this->_connection->insertOnDuplicate($this->_sessionTable, $sessionRecord, [self::COLUMN_SESSION_DATA]);
  173. $sessionData = $this->_model->read(self::SESSION_ID);
  174. $this->assertEquals($this->_sourceData[self::SESSION_NEW], unserialize($sessionData));
  175. }
  176. }