PageRenderTime 42ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/core/modules/system/lib/Drupal/system/Tests/Database/ConnectionUnitTest.php

https://bitbucket.org/aswinvk28/smartpan-stock-drupal
PHP | 296 lines | 161 code | 47 blank | 88 comment | 9 complexity | 55211e1320ede4fb7953ff61816db67d MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php
  2. /**
  3. * @file
  4. * Contains Drupal\system\Tests\Database\ConnectionUnitTest.
  5. */
  6. namespace Drupal\system\Tests\Database;
  7. use Drupal\Core\Database\Database;
  8. use Drupal\simpletest\UnitTestBase;
  9. /**
  10. * Tests management of database connections.
  11. */
  12. class ConnectionUnitTest extends UnitTestBase {
  13. protected $key;
  14. protected $target;
  15. protected $monitor;
  16. protected $originalCount;
  17. public static function getInfo() {
  18. return array(
  19. 'name' => 'Connection unit tests',
  20. 'description' => 'Tests management of database connections.',
  21. 'group' => 'Database',
  22. );
  23. }
  24. function setUp() {
  25. parent::setUp();
  26. $this->key = 'default';
  27. $this->originalTarget = 'default';
  28. $this->target = 'DatabaseConnectionUnitTest';
  29. // Determine whether the database driver is MySQL. If it is not, the test
  30. // methods will not be executed.
  31. // @todo Make this test driver-agnostic, or find a proper way to skip it.
  32. // @see http://drupal.org/node/1273478
  33. $connection_info = Database::getConnectionInfo('default');
  34. $this->skipTest = (bool) ($connection_info['default']['driver'] != 'mysql');
  35. if ($this->skipTest) {
  36. // Insert an assertion to prevent Simpletest from interpreting the test
  37. // as failure.
  38. $this->pass('This test is only compatible with MySQL.');
  39. }
  40. // Create an additional connection to monitor the connections being opened
  41. // and closed in this test.
  42. // @see TestBase::changeDatabasePrefix()
  43. Database::addConnectionInfo('default', 'monitor', $connection_info['default']);
  44. global $databases;
  45. $databases['default']['monitor'] = $connection_info['default'];
  46. $this->monitor = Database::getConnection('monitor');
  47. }
  48. /**
  49. * Adds a new database connection info to Database.
  50. */
  51. protected function addConnection() {
  52. // Add a new target to the connection, by cloning the current connection.
  53. $connection_info = Database::getConnectionInfo($this->key);
  54. Database::addConnectionInfo($this->key, $this->target, $connection_info[$this->originalTarget]);
  55. // Verify that the new target exists.
  56. $info = Database::getConnectionInfo($this->key);
  57. // Note: Custom assertion message to not expose database credentials.
  58. $this->assertIdentical($info[$this->target], $connection_info[$this->key], 'New connection info found.');
  59. }
  60. /**
  61. * Returns the connection ID of the current test connection.
  62. *
  63. * @return integer
  64. */
  65. protected function getConnectionID() {
  66. return (int) Database::getConnection($this->target, $this->key)->query('SELECT CONNECTION_ID()')->fetchField();
  67. }
  68. /**
  69. * Asserts that a connection ID exists.
  70. *
  71. * @param integer $id
  72. * The connection ID to verify.
  73. */
  74. protected function assertConnection($id) {
  75. $list = $this->monitor->query('SHOW PROCESSLIST')->fetchAllKeyed(0, 0);
  76. return $this->assertTrue(isset($list[$id]), format_string('Connection ID @id found.', array('@id' => $id)));
  77. }
  78. /**
  79. * Asserts that a connection ID does not exist.
  80. *
  81. * @param integer $id
  82. * The connection ID to verify.
  83. */
  84. protected function assertNoConnection($id) {
  85. $list = $this->monitor->query('SHOW PROCESSLIST')->fetchAllKeyed(0, 0);
  86. return $this->assertFalse(isset($list[$id]), format_string('Connection ID @id not found.', array('@id' => $id)));
  87. }
  88. /**
  89. * Tests Database::closeConnection() without query.
  90. *
  91. * @todo getConnectionID() executes a query.
  92. */
  93. function testOpenClose() {
  94. if ($this->skipTest) {
  95. return;
  96. }
  97. // Add and open a new connection.
  98. $this->addConnection();
  99. $id = $this->getConnectionID();
  100. Database::getConnection($this->target, $this->key);
  101. // Verify that there is a new connection.
  102. $this->assertConnection($id);
  103. // Close the connection.
  104. Database::closeConnection($this->target, $this->key);
  105. // Wait 20ms to give the database engine sufficient time to react.
  106. usleep(20000);
  107. // Verify that we are back to the original connection count.
  108. $this->assertNoConnection($id);
  109. }
  110. /**
  111. * Tests Database::closeConnection() with a query.
  112. */
  113. function testOpenQueryClose() {
  114. if ($this->skipTest) {
  115. return;
  116. }
  117. // Add and open a new connection.
  118. $this->addConnection();
  119. $id = $this->getConnectionID();
  120. Database::getConnection($this->target, $this->key);
  121. // Verify that there is a new connection.
  122. $this->assertConnection($id);
  123. // Execute a query.
  124. Database::getConnection($this->target, $this->key)->query('SHOW TABLES');
  125. // Close the connection.
  126. Database::closeConnection($this->target, $this->key);
  127. // Wait 20ms to give the database engine sufficient time to react.
  128. usleep(20000);
  129. // Verify that we are back to the original connection count.
  130. $this->assertNoConnection($id);
  131. }
  132. /**
  133. * Tests Database::closeConnection() with a query and custom prefetch method.
  134. */
  135. function testOpenQueryPrefetchClose() {
  136. if ($this->skipTest) {
  137. return;
  138. }
  139. // Add and open a new connection.
  140. $this->addConnection();
  141. $id = $this->getConnectionID();
  142. Database::getConnection($this->target, $this->key);
  143. // Verify that there is a new connection.
  144. $this->assertConnection($id);
  145. // Execute a query.
  146. Database::getConnection($this->target, $this->key)->query('SHOW TABLES')->fetchCol();
  147. // Close the connection.
  148. Database::closeConnection($this->target, $this->key);
  149. // Wait 20ms to give the database engine sufficient time to react.
  150. usleep(20000);
  151. // Verify that we are back to the original connection count.
  152. $this->assertNoConnection($id);
  153. }
  154. /**
  155. * Tests Database::closeConnection() with a select query.
  156. */
  157. function testOpenSelectQueryClose() {
  158. if ($this->skipTest) {
  159. return;
  160. }
  161. // Add and open a new connection.
  162. $this->addConnection();
  163. $id = $this->getConnectionID();
  164. Database::getConnection($this->target, $this->key);
  165. // Verify that there is a new connection.
  166. $this->assertConnection($id);
  167. // Create a table.
  168. $name = 'foo';
  169. Database::getConnection($this->target, $this->key)->schema()->createTable($name, array(
  170. 'fields' => array(
  171. 'name' => array(
  172. 'type' => 'varchar',
  173. 'length' => 255,
  174. ),
  175. ),
  176. ));
  177. // Execute a query.
  178. Database::getConnection($this->target, $this->key)->select('foo', 'f')
  179. ->fields('f', array('name'))
  180. ->execute()
  181. ->fetchAll();
  182. // Drop the table.
  183. Database::getConnection($this->target, $this->key)->schema()->dropTable($name);
  184. // Close the connection.
  185. Database::closeConnection($this->target, $this->key);
  186. // Wait 20ms to give the database engine sufficient time to react.
  187. usleep(20000);
  188. // Verify that we are back to the original connection count.
  189. $this->assertNoConnection($id);
  190. }
  191. /**
  192. * Tests the serialization and unserialization of a database connection.
  193. */
  194. public function testConnectionSerialization() {
  195. $db = Database::getConnection('default', 'default');
  196. try {
  197. $serialized = serialize($db);
  198. $this->pass('The database connection can be serialized.');
  199. $unserialized = unserialize($serialized);
  200. $this->assertTrue(get_class($unserialized) === get_class($db));
  201. }
  202. catch (\Exception $e) {
  203. $this->fail('The database connection cannot be serialized.');
  204. }
  205. // Ensure that all properties on the unserialized object are the same.
  206. $db_reflection = new \ReflectionObject($db);
  207. $unserialized_reflection = new \ReflectionObject($unserialized);
  208. foreach ($db_reflection->getProperties() as $value) {
  209. $value->setAccessible(TRUE);
  210. $unserialized_property = $unserialized_reflection->getProperty($value->getName());
  211. $unserialized_property->setAccessible(TRUE);
  212. // For the PDO object, just check the statement class attribute.
  213. if ($value->getName() == 'connection') {
  214. $db_statement_class = $unserialized_property->getValue($db)->getAttribute(\PDO::ATTR_STATEMENT_CLASS);
  215. $unserialized_statement_class = $unserialized_property->getValue($unserialized)->getAttribute(\PDO::ATTR_STATEMENT_CLASS);
  216. // Assert the statement class.
  217. $this->assertEqual($unserialized_statement_class[0], $db_statement_class[0]);
  218. // Assert the connection argument that is passed into the statement.
  219. $this->assertEqual(get_class($unserialized_statement_class[1][0]), get_class($db_statement_class[1][0]));
  220. }
  221. else {
  222. $this->assertEqual($unserialized_property->getValue($unserialized), $value->getValue($db));
  223. }
  224. }
  225. }
  226. /**
  227. * Tests pdo options override.
  228. */
  229. public function testConnectionOpen() {
  230. $connection = Database::getConnection('default');
  231. $reflection = new \ReflectionObject($connection);
  232. $connection_property = $reflection->getProperty('connection');
  233. $connection_property->setAccessible(TRUE);
  234. $error_mode = $connection_property->getValue($connection)
  235. ->getAttribute(\PDO::ATTR_ERRMODE);
  236. $this->assertEqual($error_mode, \PDO::ERRMODE_EXCEPTION, 'Ensure the default error mode is set to exception.');
  237. $connection = Database::getConnectionInfo('default');
  238. $connection['default']['pdo'][\PDO::ATTR_ERRMODE] = \PDO::ERRMODE_SILENT;
  239. Database::addConnectionInfo('test', 'default', $connection['default']);
  240. $connection = Database::getConnection('default', 'test');
  241. $reflection = new \ReflectionObject($connection);
  242. $connection_property = $reflection->getProperty('connection');
  243. $connection_property->setAccessible(TRUE);
  244. $error_mode = $connection_property->getValue($connection)
  245. ->getAttribute(\PDO::ATTR_ERRMODE);
  246. $this->assertEqual($error_mode, \PDO::ERRMODE_SILENT, 'Ensure PDO connection options can be overridden.');
  247. Database::removeConnection('test');
  248. }
  249. }