BUGFIX] Wrong renaming of DBAL dbPostgresqlTest
[Packages/TYPO3.CMS.git] / tests / Unit / t3lib / db / class.t3lib_db_preparedstatementTest.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2010-2011 Helmut Hummel <helmut@typo3.org>
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 *
17 * This script is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * This copyright notice MUST APPEAR in all copies of the script!
23 ***************************************************************/
24 /**
25 * Testcase for the prepared statement database class
26 *
27 * @author Helmut Hummel <helmut@typo3.org>
28 * @package TYPO3
29 * @subpackage tests
30 */
31 class t3lib_db_PreparedStatementTest extends tx_phpunit_testcase {
32
33 /**
34 * Backup and restore of the $GLOBALS array.
35 *
36 * @var boolean
37 */
38 protected $backupGlobalsArray = array();
39
40 /**
41 * Mock object of t3lib_db
42 *
43 * @var PHPUnit_Framework_MockObject_MockObject
44 */
45 private $databaseStub;
46
47 /**
48 * Create a new database mock object for every test
49 * and backup the original global database object.
50 *
51 * @return void
52 */
53 protected function setUp() {
54 $this->backupGlobalsArray['TYPO3_DB'] = $GLOBALS['TYPO3_DB'];
55 $this->databaseStub = $this->setUpAndReturnDatabaseStub();
56 }
57
58 /**
59 * Restore global database object.
60 *
61 * @return void
62 */
63 protected function tearDown() {
64 $GLOBALS['TYPO3_DB'] = $this->backupGlobalsArray['TYPO3_DB'];
65 }
66
67 //////////////////////
68 // Utility functions
69 //////////////////////
70 /**
71 * Set up the stub to be able to get the result of the prepared statement.
72 *
73 * @return PHPUnit_Framework_MockObject_MockObject
74 */
75 private function setUpAndReturnDatabaseStub() {
76 $databaseLink = $GLOBALS['TYPO3_DB']->link;
77 $GLOBALS['TYPO3_DB'] = $this->getMock('TYPO3\\CMS\\Core\\Database\\DatabaseConnection', array('exec_PREPAREDquery'), array(), '', FALSE, FALSE);
78 $GLOBALS['TYPO3_DB']->link = $databaseLink;
79 return $GLOBALS['TYPO3_DB'];
80 }
81
82 /**
83 * Create a object fo the subject to be tested.
84 *
85 * @param string $query
86 * @return \TYPO3\CMS\Core\Database\PreparedStatement
87 */
88 private function createPreparedStatement($query) {
89 return new \TYPO3\CMS\Core\Database\PreparedStatement($query, 'pages');
90 }
91
92 ////////////////////////////////////
93 // Tests for the utility functions
94 ////////////////////////////////////
95 /**
96 * Checks if setUpAndReturnDatabaseStub() really returns
97 * a mock of t3lib_DB.
98 *
99 * @test
100 * @return void
101 */
102 public function setUpAndReturnDatabaseStubReturnsMockObjectOf_t3lib_DB() {
103 $this->assertTrue($this->setUpAndReturnDatabaseStub() instanceof \TYPO3\CMS\Core\Database\DatabaseConnection);
104 }
105
106 /**
107 * Checks if createPreparedStatement() really returns an instance of t3lib_db_PreparedStatement.
108 *
109 * @test
110 * @return void
111 */
112 public function createPreparedStatementReturnsInstanceOfPreparedStatementClass() {
113 $this->assertTrue($this->createPreparedStatement('dummy') instanceof \TYPO3\CMS\Core\Database\PreparedStatement);
114 }
115
116 ///////////////////////////////////////
117 // Tests for t3lib_db_PreparedStatement
118 ///////////////////////////////////////
119 /**
120 * Data Provider for two tests, providing sample queries, parameters and expected result queries.
121 *
122 * @see parametersAreReplacedInQueryByCallingExecute
123 * @see parametersAreReplacedInQueryWhenBoundWithBindValues
124 * @return array
125 */
126 public function parametersAndQueriesDataProvider() {
127 return array(
128 'one named integer parameter' => array('SELECT * FROM pages WHERE pid=:pid', array(':pid' => 1), 'SELECT * FROM pages WHERE pid=1'),
129 'one unnamed integer parameter' => array('SELECT * FROM pages WHERE pid=?', array(1), 'SELECT * FROM pages WHERE pid=1'),
130 'one named integer parameter is replaced multiple times' => array('SELECT * FROM pages WHERE pid=:pid OR uid=:pid', array(':pid' => 1), 'SELECT * FROM pages WHERE pid=1 OR uid=1'),
131 'two named integer parameters are replaced' => array('SELECT * FROM pages WHERE pid=:pid OR uid=:uid', array(':pid' => 1, ':uid' => 10), 'SELECT * FROM pages WHERE pid=1 OR uid=10'),
132 'two unnamed integer parameters are replaced' => array('SELECT * FROM pages WHERE pid=? OR uid=?', array(1, 1), 'SELECT * FROM pages WHERE pid=1 OR uid=1'),
133 'php bool TRUE parameter is replaced with 1' => array('SELECT * FROM pages WHERE deleted=?', array(TRUE), 'SELECT * FROM pages WHERE deleted=1'),
134 'php bool FALSE parameter is replaced with 0' => array('SELECT * FROM pages WHERE deleted=?', array(FALSE), 'SELECT * FROM pages WHERE deleted=0'),
135 'php null parameter is replaced with NULL' => array('SELECT * FROM pages WHERE deleted=?', array(NULL), 'SELECT * FROM pages WHERE deleted=NULL'),
136 'string parameter is wrapped in quotes' => array('SELECT * FROM pages WHERE title=?', array('Foo bar'), 'SELECT * FROM pages WHERE title=\'Foo bar\''),
137 'number as string parameter is wrapped in quotes' => array('SELECT * FROM pages WHERE title=?', array('12'), 'SELECT * FROM pages WHERE title=\'12\''),
138 'string single quotes in parameter are properly escaped' => array('SELECT * FROM pages WHERE title=?', array('\'Foo\''), 'SELECT * FROM pages WHERE title=\'\\\'Foo\\\'\''),
139 'question mark as values with unnamed parameters are properly escaped' => array('SELECT * FROM foo WHERE title=? AND name=?', array('?', 'fancy title'), 'SELECT * FROM foo WHERE title=\'?\' AND name=\'fancy title\''),
140 'parameter name as value is properly escaped' => array('SELECT * FROM foo WHERE title=:name AND name=:title', array(':name' => ':title', ':title' => 'fancy title'), 'SELECT * FROM foo WHERE title=\':title\' AND name=\'fancy title\''),
141 'question mark as value of a parameter with a name is properly escaped' => array('SELECT * FROM foo WHERE title=:name AND name=?', array(':name' => '?', 'cool name'), 'SELECT * FROM foo WHERE title=\'?\' AND name=\'cool name\''),
142 'regular expression back references as values are left untouched' => array('SELECT * FROM foo WHERE title=:name AND name=?', array(':name' => '\\1', '${1}'), 'SELECT * FROM foo WHERE title=\'\\\\1\' AND name=\'${1}\''),
143 'unsubstituted question marks do not contain the token wrap' => array('SELECT * FROM foo WHERE title=:name AND question LIKE "%what?" AND name=:title', array(':name' => 'Title', ':title' => 'Name'), 'SELECT * FROM foo WHERE title=\'Title\' AND question LIKE "%what?" AND name=\'Name\'')
144 );
145 }
146
147 /**
148 * Checking if calling execute() with parameters, they are
149 * properly relpaced in the query.
150 *
151 * @test
152 * @dataProvider parametersAndQueriesDataProvider
153 * @param string $query Query with unreplaced markers
154 * @param array $parameters Array of parameters to be replaced in the query
155 * @param string $expectedResult Query with all markers replaced
156 * @return void
157 */
158 public function parametersAreReplacedInQueryByCallingExecute($query, $parameters, $expectedResult) {
159 $statement = $this->createPreparedStatement($query);
160 $this->databaseStub->expects($this->any())->method('exec_PREPAREDquery')->with($this->equalTo($expectedResult));
161 $statement->execute($parameters);
162 }
163
164 /**
165 * Checking if parameters bound to the statement by bindValues()
166 * are properly replaced in the query.
167 *
168 * @test
169 * @dataProvider parametersAndQueriesDataProvider
170 * @param string $query Query with unreplaced markers
171 * @param array $parameters Array of parameters to be replaced in the query
172 * @param string $expectedResult Query with all markers replaced
173 * @return void
174 */
175 public function parametersAreReplacedInQueryWhenBoundWithBindValues($query, $parameters, $expectedResult) {
176 $statement = $this->createPreparedStatement($query);
177 $this->databaseStub->expects($this->any())->method('exec_PREPAREDquery')->with($this->equalTo($expectedResult));
178 $statement->bindValues($parameters);
179 $statement->execute();
180 }
181
182 /**
183 * Data Provider with invalid parameters.
184 *
185 * @see invalidParameterTypesPassedToBindValueThrowsException
186 * @return array
187 */
188 public function invalidParameterTypesPassedToBindValueThrowsExceptionDataProvider() {
189 return array(
190 'integer passed with param type NULL' => array(1, \TYPO3\CMS\Core\Database\PreparedStatement::PARAM_NULL),
191 'string passed with param type NULL' => array('1', \TYPO3\CMS\Core\Database\PreparedStatement::PARAM_NULL),
192 'bool passed with param type NULL' => array(TRUE, \TYPO3\CMS\Core\Database\PreparedStatement::PARAM_NULL),
193 'NULL passed with param type INT' => array(NULL, \TYPO3\CMS\Core\Database\PreparedStatement::PARAM_INT),
194 'string passed with param type INT' => array('1', \TYPO3\CMS\Core\Database\PreparedStatement::PARAM_INT),
195 'bool passed with param type INT' => array(TRUE, \TYPO3\CMS\Core\Database\PreparedStatement::PARAM_INT),
196 'NULL passed with param type BOOL' => array(NULL, \TYPO3\CMS\Core\Database\PreparedStatement::PARAM_BOOL),
197 'string passed with param type BOOL' => array('1', \TYPO3\CMS\Core\Database\PreparedStatement::PARAM_BOOL),
198 'integer passed with param type BOOL' => array(1, \TYPO3\CMS\Core\Database\PreparedStatement::PARAM_BOOL)
199 );
200 }
201
202 /**
203 * Checking if an exception is thrown if invalid parameters are
204 * provided vor bindValue().
205 *
206 * @test
207 * @expectedException InvalidArgumentException
208 * @dataProvider invalidParameterTypesPassedToBindValueThrowsExceptionDataProvider
209 * @param mixed $parameter Parameter to be replaced in the query
210 * @param integer $type Type of the parameter value
211 * @return void
212 */
213 public function invalidParameterTypesPassedToBindValueThrowsException($parameter, $type) {
214 $statement = $this->createPreparedStatement('');
215 $statement->bindValue(1, $parameter, $type);
216 }
217
218 /**
219 * Checking if formerly bound values are replaced by the values passed to execute().
220 *
221 * @test
222 * @return void
223 */
224 public function parametersPassedToExecuteOverrulesFormerlyBoundValues() {
225 $query = 'SELECT * FROM pages WHERE pid=? OR uid=?';
226 $expectedResult = 'SELECT * FROM pages WHERE pid=30 OR uid=40';
227 $this->databaseStub->expects($this->any())->method('exec_PREPAREDquery')->with($this->equalTo($expectedResult));
228 $statement = $this->createPreparedStatement($query);
229 $statement->bindValues(array(10, 20));
230 $statement->execute(array(30, 40));
231 }
232
233 /**
234 * Data Provieder for invalid marker names.
235 *
236 * @see passingInvalidMarkersThrowsExeption
237 * @return array
238 */
239 public function passingInvalidMarkersThrowsExeptionDataProvider() {
240 return array(
241 'using other prefix than colon' => array('SELECT * FROM pages WHERE pid=#pid', array('#pid' => 1)),
242 'using non alphanumerical character' => array('SELECT * FROM pages WHERE title=:stra≠e', array(':stra≠e' => 1)),
243 'no colon used' => array('SELECT * FROM pages WHERE pid=pid', array('pid' => 1)),
244 'colon at the end' => array('SELECT * FROM pages WHERE pid=pid:', array('pid:' => 1)),
245 'colon without alphanumerical character' => array('SELECT * FROM pages WHERE pid=:', array(':' => 1))
246 );
247 }
248
249 /**
250 * Checks if an exception is thrown, if parameter have invalid marker named.
251 *
252 * @test
253 * @expectedException InvalidArgumentException
254 * @dataProvider passingInvalidMarkersThrowsExeptionDataProvider
255 * @param string $query Query with unreplaced markers
256 * @param array $parameters Array of parameters to be replaced in the query
257 * @return void
258 */
259 public function passingInvalidMarkersThrowsExeption($query, $parameters) {
260 $statement = $this->createPreparedStatement($query);
261 $statement->execute($parameters);
262 }
263
264 }
265
266 ?>