926589f1ccca468d87e6a2586d952c052a5467b6
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Unit / Database / DatabaseConnectionTest.php
1 <?php
2 namespace TYPO3\CMS\Core\Tests\Unit\Database;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2010-2013 Ernesto Baschny (ernst@cron-it.de)
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 * Test case
29 *
30 */
31 class DatabaseConnectionTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
32
33 //////////////////////////////////////////////////
34 // Write/Read tests for charsets and binaries
35 //////////////////////////////////////////////////
36
37 /**
38 * @test
39 */
40 public function storedFullAsciiRangeCallsLinkObjectWithGivenData() {
41 $binaryString = '';
42 for ($i = 0; $i < 256; $i++) {
43 $binaryString .= chr($i);
44 }
45
46 /** @var \TYPO3\CMS\Core\Database\DatabaseConnection|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface $subject */
47 $subject = $this->getAccessibleMock('TYPO3\\CMS\\Core\\Database\\DatabaseConnection', array('fullQuoteStr'), array(), '', FALSE);
48 $subject->_set('isConnected', TRUE);
49 $subject
50 ->expects($this->any())
51 ->method('fullQuoteStr')
52 ->will($this->returnCallback(function ($data) {
53 return $data;
54 }));
55 $mysqliMock = $this->getMock('mysqli');
56 $mysqliMock
57 ->expects($this->once())
58 ->method('query')
59 ->with('INSERT INTO aTable (fieldblob) VALUES (' . $binaryString . ')');
60 $subject->_set('link', $mysqliMock);
61
62 $subject->exec_INSERTquery('aTable', array('fieldblob' => $binaryString));
63 }
64
65 /**
66 * @test
67 */
68 public function storedGzipCompressedDataReturnsSameData() {
69 $testStringWithBinary = @gzcompress('sdfkljer4587');
70
71 /** @var \TYPO3\CMS\Core\Database\DatabaseConnection|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface $subject */
72 $subject = $this->getAccessibleMock('TYPO3\\CMS\\Core\\Database\\DatabaseConnection', array('fullQuoteStr'), array(), '', FALSE);
73 $subject->_set('isConnected', TRUE);
74 $subject
75 ->expects($this->any())
76 ->method('fullQuoteStr')
77 ->will($this->returnCallback(function ($data) {
78 return $data;
79 }));
80 $mysqliMock = $this->getMock('mysqli');
81 $mysqliMock
82 ->expects($this->once())
83 ->method('query')
84 ->with('INSERT INTO aTable (fieldblob) VALUES (' . $testStringWithBinary . ')');
85 $subject->_set('link', $mysqliMock);
86
87 $subject->exec_INSERTquery('aTable', array('fieldblob' => $testStringWithBinary));
88 }
89
90
91 ////////////////////////////////
92 // Tests concerning listQuery
93 ////////////////////////////////
94
95 /**
96 * @test
97 * @see http://forge.typo3.org/issues/23253
98 */
99 public function listQueryWithIntegerCommaAsValue() {
100 /** @var \TYPO3\CMS\Core\Database\DatabaseConnection|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface $subject */
101 $subject = $this->getAccessibleMock('TYPO3\\CMS\\Core\\Database\\DatabaseConnection', array('quoteStr'), array(), '', FALSE);
102 $subject->_set('isConnected', TRUE);
103 $subject
104 ->expects($this->any())
105 ->method('quoteStr')
106 ->will($this->returnCallback(function ($data) {
107 return $data;
108 }));
109 // Note: 44 = ord(',')
110 $this->assertEquals($subject->listQuery('dummy', 44, 'table'), $subject->listQuery('dummy', '44', 'table'));
111 }
112
113 /**
114 * @test
115 * @expectedException \InvalidArgumentException
116 */
117 public function listQueryThrowsExceptionIfValueContainsComma() {
118 /** @var \TYPO3\CMS\Core\Database\DatabaseConnection|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface $subject */
119 $subject = $this->getAccessibleMock('TYPO3\\CMS\\Core\\Database\\DatabaseConnection', array('quoteStr'), array(), '', FALSE);
120 $subject->_set('isConnected', TRUE);
121 $subject->listQuery('aField', 'foo,bar', 'aTable');
122 }
123
124
125 ////////////////////////////////
126 // Tests concerning searchQuery
127 ////////////////////////////////
128
129 /**
130 * Data provider for searchQueryCreatesQuery
131 *
132 * @return array
133 */
134 public function searchQueryDataProvider() {
135 return array(
136 'One search word in one field' => array(
137 '(pages.title LIKE \'%TYPO3%\')',
138 array('TYPO3'),
139 array('title'),
140 'pages',
141 'AND'
142 ),
143
144 'One search word in multiple fields' => array(
145 '(pages.title LIKE \'%TYPO3%\' OR pages.keyword LIKE \'%TYPO3%\' OR pages.description LIKE \'%TYPO3%\')',
146 array('TYPO3'),
147 array('title', 'keyword', 'description'),
148 'pages',
149 'AND'
150 ),
151
152 'Multiple search words in one field with AND constraint' => array(
153 '(pages.title LIKE \'%TYPO3%\') AND (pages.title LIKE \'%is%\') AND (pages.title LIKE \'%great%\')',
154 array('TYPO3', 'is', 'great'),
155 array('title'),
156 'pages',
157 'AND'
158 ),
159
160 'Multiple search words in one field with OR constraint' => array(
161 '(pages.title LIKE \'%TYPO3%\') OR (pages.title LIKE \'%is%\') OR (pages.title LIKE \'%great%\')',
162 array('TYPO3', 'is', 'great'),
163 array('title'),
164 'pages',
165 'OR'
166 ),
167
168 'Multiple search words in multiple fields with AND constraint' => array(
169 '(pages.title LIKE \'%TYPO3%\' OR pages.keywords LIKE \'%TYPO3%\' OR pages.description LIKE \'%TYPO3%\') AND ' .
170 '(pages.title LIKE \'%is%\' OR pages.keywords LIKE \'%is%\' OR pages.description LIKE \'%is%\') AND ' .
171 '(pages.title LIKE \'%great%\' OR pages.keywords LIKE \'%great%\' OR pages.description LIKE \'%great%\')',
172 array('TYPO3', 'is', 'great'),
173 array('title', 'keywords', 'description'),
174 'pages',
175 'AND'
176 ),
177
178 'Multiple search words in multiple fields with OR constraint' => array(
179 '(pages.title LIKE \'%TYPO3%\' OR pages.keywords LIKE \'%TYPO3%\' OR pages.description LIKE \'%TYPO3%\') OR ' .
180 '(pages.title LIKE \'%is%\' OR pages.keywords LIKE \'%is%\' OR pages.description LIKE \'%is%\') OR ' .
181 '(pages.title LIKE \'%great%\' OR pages.keywords LIKE \'%great%\' OR pages.description LIKE \'%great%\')',
182 array('TYPO3', 'is', 'great'),
183 array('title', 'keywords', 'description'),
184 'pages',
185 'OR'
186 ),
187 );
188 }
189
190 /**
191 * @test
192 * @dataProvider searchQueryDataProvider
193 */
194 public function searchQueryCreatesQuery($expectedResult, $searchWords, $fields, $table, $constraint) {
195 /** @var \TYPO3\CMS\Core\Database\DatabaseConnection|\PHPUnit_Framework_MockObject_MockObject $subject */
196 $subject = $this->getMock('TYPO3\\CMS\\Core\\Database\\DatabaseConnection', array('quoteStr'), array(), '', FALSE);
197 $subject
198 ->expects($this->any())
199 ->method('quoteStr')
200 ->will($this->returnCallback(function ($data) {
201 return $data;
202 }));
203
204 $this->assertSame($expectedResult, $subject->searchQuery($searchWords, $fields, $table, $constraint));
205 }
206
207
208 /////////////////////////////////////////////////
209 // Tests concerning escapeStringForLikeComparison
210 /////////////////////////////////////////////////
211
212 /**
213 * @test
214 */
215 public function escapeStringForLikeComparison() {
216 /** @var \TYPO3\CMS\Core\Database\DatabaseConnection|\PHPUnit_Framework_MockObject_MockObject $subject */
217 $subject = $this->getMock('TYPO3\\CMS\\Core\\Database\\DatabaseConnection', array('dummy'), array(), '', FALSE);
218 $this->assertEquals('foo\\_bar\\%', $subject->escapeStrForLike('foo_bar%', 'table'));
219 }
220
221
222 /////////////////////////////////////////////////
223 // Tests concerning stripOrderByForOrderByKeyword
224 /////////////////////////////////////////////////
225
226 /**
227 * Data Provider for stripGroupByForGroupByKeyword()
228 *
229 * @see stripOrderByForOrderByKeyword()
230 * @return array
231 */
232 public function stripOrderByForOrderByKeywordDataProvider() {
233 return array(
234 'single ORDER BY' => array('ORDER BY name, tstamp', 'name, tstamp'),
235 'single ORDER BY in lower case' => array('order by name, tstamp', 'name, tstamp'),
236 'ORDER BY with additional space behind' => array('ORDER BY name, tstamp', 'name, tstamp'),
237 'ORDER BY without space between the words' => array('ORDERBY name, tstamp', 'name, tstamp'),
238 'ORDER BY added twice' => array('ORDER BY ORDER BY name, tstamp', 'name, tstamp'),
239 'ORDER BY added twice without spaces in the first occurrence' => array('ORDERBY ORDER BY name, tstamp', 'name, tstamp'),
240 'ORDER BY added twice without spaces in the second occurrence' => array('ORDER BYORDERBY name, tstamp', 'name, tstamp'),
241 'ORDER BY added twice without spaces' => array('ORDERBYORDERBY name, tstamp', 'name, tstamp'),
242 'ORDER BY added twice without spaces afterwards' => array('ORDERBYORDERBYname, tstamp', 'name, tstamp'),
243 );
244 }
245
246 /**
247 * @test
248 * @dataProvider stripOrderByForOrderByKeywordDataProvider
249 * @param string $orderByClause The clause to test
250 * @param string $expectedResult The expected result
251 * @return void
252 */
253 public function stripOrderByForOrderByKeyword($orderByClause, $expectedResult) {
254 /** @var \TYPO3\CMS\Core\Database\DatabaseConnection|\PHPUnit_Framework_MockObject_MockObject $subject */
255 $subject = $this->getMock('TYPO3\\CMS\\Core\\Database\\DatabaseConnection', array('dummy'), array(), '', FALSE);
256 $strippedQuery = $subject->stripOrderBy($orderByClause);
257 $this->assertEquals($expectedResult, $strippedQuery);
258 }
259
260
261 /////////////////////////////////////////////////
262 // Tests concerning stripGroupByForGroupByKeyword
263 /////////////////////////////////////////////////
264
265 /**
266 * Data Provider for stripGroupByForGroupByKeyword()
267 *
268 * @see stripGroupByForGroupByKeyword()
269 * @return array
270 */
271 public function stripGroupByForGroupByKeywordDataProvider() {
272 return array(
273 'single GROUP BY' => array('GROUP BY name, tstamp', 'name, tstamp'),
274 'single GROUP BY in lower case' => array('group by name, tstamp', 'name, tstamp'),
275 'GROUP BY with additional space behind' => array('GROUP BY name, tstamp', 'name, tstamp'),
276 'GROUP BY without space between the words' => array('GROUPBY name, tstamp', 'name, tstamp'),
277 'GROUP BY added twice' => array('GROUP BY GROUP BY name, tstamp', 'name, tstamp'),
278 'GROUP BY added twice without spaces in the first occurrence' => array('GROUPBY GROUP BY name, tstamp', 'name, tstamp'),
279 'GROUP BY added twice without spaces in the second occurrence' => array('GROUP BYGROUPBY name, tstamp', 'name, tstamp'),
280 'GROUP BY added twice without spaces' => array('GROUPBYGROUPBY name, tstamp', 'name, tstamp'),
281 'GROUP BY added twice without spaces afterwards' => array('GROUPBYGROUPBYname, tstamp', 'name, tstamp'),
282 );
283 }
284
285 /**
286 * @test
287 * @dataProvider stripGroupByForGroupByKeywordDataProvider
288 * @param string $groupByClause The clause to test
289 * @param string $expectedResult The expected result
290 * @return void
291 */
292 public function stripGroupByForGroupByKeyword($groupByClause, $expectedResult) {
293 /** @var \TYPO3\CMS\Core\Database\DatabaseConnection|\PHPUnit_Framework_MockObject_MockObject $subject */
294 $subject = $this->getMock('TYPO3\\CMS\\Core\\Database\\DatabaseConnection', array('dummy'), array(), '', FALSE);
295 $strippedQuery = $subject->stripGroupBy($groupByClause);
296 $this->assertEquals($expectedResult, $strippedQuery);
297 }
298
299
300 /////////////////////////////////////////////////
301 // Tests concerning stripOrderByForOrderByKeyword
302 /////////////////////////////////////////////////
303
304 /**
305 * Data Provider for stripGroupByForGroupByKeyword()
306 *
307 * @see stripOrderByForOrderByKeyword()
308 * @return array
309 */
310 public function cleanIntArrayDataProvider() {
311 return array(
312 'simple array' => array(
313 array(1, 2, 3),
314 array(1, 2, 3)
315 ),
316 'string array' => array(
317 array('2', '4', '8'),
318 array(2, 4, 8)
319 ),
320 'string array with letters #1' => array(
321 array('3', '6letters', '12'),
322 array(3, 6, 12)
323 ),
324 'string array with letters #2' => array(
325 array('3', 'letters6', '12'),
326 array(3, 0, 12)
327 ),
328 'string array with letters #3' => array(
329 array('3', '6letters4', '12'),
330 array(3, 6, 12)
331 ),
332 'associative array' => array(
333 array('apples' => 3, 'bananas' => 4, 'kiwis' => 9),
334 array('apples' => 3, 'bananas' => 4, 'kiwis' => 9)
335 ),
336 'associative string array' => array(
337 array('apples' => '1', 'bananas' => '5', 'kiwis' => '7'),
338 array('apples' => 1, 'bananas' => 5, 'kiwis' => 7)
339 ),
340 'associative string array with letters #1' => array(
341 array('apples' => '1', 'bananas' => 'no5', 'kiwis' => '7'),
342 array('apples' => 1, 'bananas' => 0, 'kiwis' => 7)
343 ),
344 'associative string array with letters #2' => array(
345 array('apples' => '1', 'bananas' => '5yes', 'kiwis' => '7'),
346 array('apples' => 1, 'bananas' => 5, 'kiwis' => 7)
347 ),
348 'associative string array with letters #3' => array(
349 array('apples' => '1', 'bananas' => '5yes9', 'kiwis' => '7'),
350 array('apples' => 1, 'bananas' => 5, 'kiwis' => 7)
351 ),
352 'multidimensional associative array' => array(
353 array('apples' => '1', 'bananas' => array(3, 4), 'kiwis' => '7'),
354 // intval(array(...)) is 1
355 // But by specification "cleanIntArray" should only get used on one-dimensional arrays
356 array('apples' => 1, 'bananas' => 1, 'kiwis' => 7)
357 ),
358 );
359 }
360
361 /**
362 * @test
363 * @dataProvider cleanIntArrayDataProvider
364 * @param array $exampleData The array to sanitize
365 * @param array $expectedResult The expected result
366 * @return void
367 */
368 public function cleanIntArray($exampleData, $expectedResult) {
369 /** @var \TYPO3\CMS\Core\Database\DatabaseConnection $subject */
370 $subject = new \TYPO3\CMS\Core\Database\DatabaseConnection();
371 $sanitizedArray = $subject->cleanIntArray($exampleData);
372 $this->assertEquals($expectedResult, $sanitizedArray);
373 }
374
375 }