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