[TASK] Increase test coverage of DatabaseConnection classes
[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 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Core\Database\DatabaseConnection;
18 use TYPO3\CMS\Core\Database\PreparedStatement;
19
20 /**
21 * Test case
22 */
23 class PreparedStatementTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
24 {
25 /**
26 * @var \PHPUnit_Framework_MockObject_MockObject|DatabaseConnection
27 */
28 protected $databaseStub;
29
30 /**
31 * Create a new database mock object for every test
32 * and backup the original global database object.
33 *
34 * @return void
35 */
36 protected function setUp()
37 {
38 $this->databaseStub = $this->setUpAndReturnDatabaseStub();
39 }
40
41 //////////////////////
42 // Utility functions
43 //////////////////////
44 /**
45 * Set up the stub to be able to get the result of the prepared statement.
46 *
47 * @return \PHPUnit_Framework_MockObject_MockObject
48 */
49 private function setUpAndReturnDatabaseStub()
50 {
51 $GLOBALS['TYPO3_DB'] = $this->getAccessibleMock(
52 DatabaseConnection::class,
53 array('prepare_PREPAREDquery'),
54 array(),
55 '',
56 false,
57 false
58 );
59
60 return $GLOBALS['TYPO3_DB'];
61 }
62
63 /**
64 * Create an object fo the subject to be tested.
65 *
66 * @param string $query
67 * @return PreparedStatement
68 */
69 private function createPreparedStatement($query)
70 {
71 return new PreparedStatement($query, 'pages');
72 }
73
74 ////////////////////////////////////
75 // Tests for the utility functions
76 ////////////////////////////////////
77
78 /**
79 * @test
80 * @return void
81 */
82 public function setUpAndReturnDatabaseStubReturnsMockObjectOfDatabaseConnection()
83 {
84 $this->assertTrue($this->setUpAndReturnDatabaseStub() instanceof DatabaseConnection);
85 }
86
87 /**
88 * @test
89 * @return void
90 */
91 public function createPreparedStatementReturnsInstanceOfPreparedStatementClass()
92 {
93 $this->assertTrue($this->createPreparedStatement('dummy') instanceof PreparedStatement);
94 }
95
96 ///////////////////////////////////////
97 // Tests for \TYPO3\CMS\Core\Database\PreparedStatement
98 ///////////////////////////////////////
99 /**
100 * Data Provider for two tests, providing sample queries, parameters and expected result queries.
101 *
102 * @see parametersAreReplacedInQueryByCallingExecute
103 * @see parametersAreReplacedInQueryWhenBoundWithBindValues
104 * @return array
105 */
106 public function parametersAndQueriesDataProvider()
107 {
108 return [
109 'one named integer parameter' => [
110 'SELECT * FROM pages WHERE pid=:pid',
111 [':pid' => 1],
112 'SELECT * FROM pages WHERE pid=?'
113 ],
114 'one unnamed integer parameter' => [
115 'SELECT * FROM pages WHERE pid=?',
116 [1],
117 'SELECT * FROM pages WHERE pid=?'
118 ],
119 'one named integer parameter is replaced multiple times' => [
120 'SELECT * FROM pages WHERE pid=:pid OR uid=:pid',
121 [':pid' => 1],
122 'SELECT * FROM pages WHERE pid=? OR uid=?'
123 ],
124 'two named integer parameters are replaced' => [
125 'SELECT * FROM pages WHERE pid=:pid OR uid=:uid',
126 [':pid' => 1, ':uid' => 10],
127 'SELECT * FROM pages WHERE pid=? OR uid=?'
128 ],
129 'two unnamed integer parameters are replaced' => [
130 'SELECT * FROM pages WHERE pid=? OR uid=?',
131 [1, 1],
132 'SELECT * FROM pages WHERE pid=? OR uid=?'
133 ],
134 ];
135 }
136
137 /**
138 * Checking if calling execute() with parameters, they are
139 * properly replaced in the query.
140 *
141 * @test
142 * @dataProvider parametersAndQueriesDataProvider
143 * @param string $query Query with unreplaced markers
144 * @param array $parameters Array of parameters to be replaced in the query
145 * @param string $expectedResult Query with all markers replaced
146 * @return void
147 */
148 public function parametersAreReplacedByQuestionMarkInQueryByCallingExecute($query, $parameters, $expectedResult)
149 {
150 $statement = $this->createPreparedStatement($query);
151 $this->databaseStub->expects($this->any())
152 ->method('prepare_PREPAREDquery')
153 ->with($this->equalTo($expectedResult));
154 $statement->execute($parameters);
155 }
156
157 /**
158 * Checking if parameters bound to the statement by bindValues()
159 * are properly replaced in the query.
160 *
161 * @test
162 * @dataProvider parametersAndQueriesDataProvider
163 * @param string $query Query with unreplaced markers
164 * @param array $parameters Array of parameters to be replaced in the query
165 * @param string $expectedResult Query with all markers replaced
166 * @return void
167 */
168 public function parametersAreReplacedInQueryWhenBoundWithBindValues($query, $parameters, $expectedResult)
169 {
170 $statement = $this->createPreparedStatement($query);
171 $this->databaseStub->expects($this->any())
172 ->method('prepare_PREPAREDquery')
173 ->with($this->equalTo($expectedResult));
174 $statement->bindValues($parameters);
175 $statement->execute();
176 }
177
178 /**
179 * Data Provider with invalid parameters.
180 *
181 * @see invalidParameterTypesPassedToBindValueThrowsException
182 * @return array
183 */
184 public function invalidParameterTypesPassedToBindValueThrowsExceptionDataProvider()
185 {
186 return [
187 'integer passed with param type NULL' => [
188 1,
189 PreparedStatement::PARAM_NULL
190 ],
191 'string passed with param type NULL' => [
192 '1',
193 PreparedStatement::PARAM_NULL
194 ],
195 'bool passed with param type NULL' => [
196 true,
197 PreparedStatement::PARAM_NULL
198 ],
199 'NULL passed with param type INT' => [
200 null,
201 PreparedStatement::PARAM_INT
202 ],
203 'string passed with param type INT' => [
204 '1',
205 PreparedStatement::PARAM_INT
206 ],
207 'bool passed with param type INT' => [
208 true,
209 PreparedStatement::PARAM_INT
210 ],
211 'NULL passed with param type BOOL' => [
212 null,
213 PreparedStatement::PARAM_BOOL
214 ],
215 'string passed with param type BOOL' => [
216 '1',
217 PreparedStatement::PARAM_BOOL
218 ],
219 'integer passed with param type BOOL' => [
220 1,
221 PreparedStatement::PARAM_BOOL
222 ]
223 ];
224 }
225
226 /**
227 * Checking if an exception is thrown if invalid parameters are
228 * provided vor bindValue().
229 *
230 * @test
231 * @expectedException \InvalidArgumentException
232 * @dataProvider invalidParameterTypesPassedToBindValueThrowsExceptionDataProvider
233 * @param mixed $parameter Parameter to be replaced in the query
234 * @param int $type Type of the parameter value
235 * @return void
236 */
237 public function invalidParameterTypesPassedToBindValueThrowsException($parameter, $type)
238 {
239 $statement = $this->createPreparedStatement('');
240 $statement->bindValue(1, $parameter, $type);
241 }
242
243 /**
244 * Data Provider for invalid marker names.
245 *
246 * @see passingInvalidMarkersThrowsExeption
247 * @return array
248 */
249 public function passingInvalidMarkersThrowsExceptionDataProvider()
250 {
251 return [
252 'using other prefix than colon' => [
253 /** @lang text */
254 'SELECT * FROM pages WHERE pid=#pid',
255 ['#pid' => 1]
256 ],
257 'using non alphanumerical character' => [
258 /** @lang text */
259 'SELECT * FROM pages WHERE title=:stra≠e',
260 [':stra≠e' => 1]
261 ],
262 'no colon used' => [
263 /** @lang text */
264 'SELECT * FROM pages WHERE pid=pid',
265 ['pid' => 1]
266 ],
267 'colon at the end' => [
268 /** @lang text */
269 'SELECT * FROM pages WHERE pid=pid:',
270 ['pid:' => 1]
271 ],
272 'colon without alphanumerical character' => [
273 /** @lang text */
274 'SELECT * FROM pages WHERE pid=:',
275 [':' => 1]
276 ]
277 ];
278 }
279
280 /**
281 * Checks if an exception is thrown, if parameter have invalid marker named.
282 *
283 * @test
284 * @expectedException \InvalidArgumentException
285 * @dataProvider passingInvalidMarkersThrowsExceptionDataProvider
286 * @param string $query Query with unreplaced markers
287 * @param array $parameters Array of parameters to be replaced in the query
288 * @return void
289 */
290 public function passingInvalidMarkersThrowsException($query, $parameters)
291 {
292 $statement = $this->createPreparedStatement($query);
293 $statement->bindValues($parameters);
294 }
295 }