[TASK] Increase test coverage of DatabaseConnection classes 93/47393/4
authorMorton Jonuschat <m.jonuschat@mojocode.de>
Fri, 25 Mar 2016 20:07:03 +0000 (21:07 +0100)
committerChristian Kuhn <lolli@schwarzbu.ch>
Wed, 30 Mar 2016 20:42:53 +0000 (22:42 +0200)
Increase the test coverage of the DatabaseConnection class by adding
unit and functional tests for core methods.

Reformat the tests to use short array notation and fix PSR-2 warnings.

Resolves: #60081
Releases: master
Change-Id: Id839c88de75eb4174b3f0cd95d3954b9631fc23d
Reviewed-on: https://review.typo3.org/47393
Reviewed-by: Tymoteusz Motylewski <t.motylewski@gmail.com>
Tested-by: Tymoteusz Motylewski <t.motylewski@gmail.com>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
typo3/sysext/core/Tests/Functional/Database/DatabaseConnectionTest.php [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Database/PreparedStatementTest.php [new file with mode: 0644]
typo3/sysext/core/Tests/Unit/Database/DatabaseConnectionTest.php
typo3/sysext/core/Tests/Unit/Database/PreparedStatementTest.php

diff --git a/typo3/sysext/core/Tests/Functional/Database/DatabaseConnectionTest.php b/typo3/sysext/core/Tests/Functional/Database/DatabaseConnectionTest.php
new file mode 100644 (file)
index 0000000..5e19608
--- /dev/null
@@ -0,0 +1,759 @@
+<?php
+namespace TYPO3\CMS\Core\Tests\Functional\Database;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+use TYPO3\CMS\Core\Database\DatabaseConnection;
+use TYPO3\CMS\Core\Tests\AccessibleObjectInterface;
+use TYPO3\CMS\Core\Tests\FunctionalTestCase;
+
+/**
+ * Test case for \TYPO3\CMS\Core\Database\DatabaseConnection
+ */
+class DatabaseConnectionTest extends FunctionalTestCase
+{
+    /**
+     * @var DatabaseConnection
+     */
+    protected $subject = null;
+
+    /**
+     * @var string
+     */
+    protected $testTable = 'test_database_connection';
+
+    /**
+     * @var string
+     */
+    protected $testField = 'test_field';
+
+    /**
+     * @var string
+     */
+    protected $anotherTestField = 'another_test_field';
+
+    /**
+     * Set the test up
+     *
+     * @return void
+     */
+    protected function setUp()
+    {
+        parent::setUp();
+        $this->subject = $GLOBALS['TYPO3_DB'];
+        $this->subject->sql_query(
+            "CREATE TABLE {$this->testTable} (" .
+            '   id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,' .
+            "   {$this->testField} MEDIUMBLOB," .
+            "   {$this->anotherTestField} MEDIUMBLOB," .
+            '   PRIMARY KEY (id)' .
+            ') ENGINE=MyISAM DEFAULT CHARSET=utf8;'
+        );
+    }
+
+    /**
+     * Tear the test down
+     *
+     * @return void
+     */
+    protected function tearDown()
+    {
+        $this->subject->sql_query("DROP TABLE {$this->testTable};");
+        unset($this->subject);
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function selectDbReturnsTrue()
+    {
+        $this->assertTrue($this->subject->sql_select_db());
+    }
+
+    /**
+     * @test
+     * @expectedException \RuntimeException
+     * @expectedExceptionMessage TYPO3 Fatal Error: Cannot connect to the current database, "Foo"!
+     * @return void
+     */
+    public function selectDbReturnsFalse()
+    {
+        $this->subject->setDatabaseName('Foo');
+        $this->assertFalse($this->subject->sql_select_db());
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function sqlAffectedRowsReturnsCorrectAmountOfRows()
+    {
+        $this->subject->exec_INSERTquery($this->testTable, [$this->testField => 'test']);
+        $this->assertEquals(1, $this->subject->sql_affected_rows());
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function sqlInsertIdReturnsCorrectId()
+    {
+        $this->subject->exec_INSERTquery($this->testTable, [$this->testField => 'test']);
+        $this->assertEquals(1, $this->subject->sql_insert_id());
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function noSqlError()
+    {
+        $this->subject->exec_INSERTquery($this->testTable, [$this->testField => 'test']);
+        $this->assertEquals('', $this->subject->sql_error());
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function sqlErrorWhenInsertIntoInexistentField()
+    {
+        $this->subject->exec_INSERTquery($this->testTable, ['test' => 'test']);
+        $this->assertEquals('Unknown column \'test\' in \'field list\'', $this->subject->sql_error());
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function noSqlErrorCode()
+    {
+        $this->subject->exec_INSERTquery($this->testTable, [$this->testField => 'test']);
+        $this->assertEquals(0, $this->subject->sql_errno());
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function sqlErrorNoWhenInsertIntoInexistentField()
+    {
+        $this->subject->exec_INSERTquery($this->testTable, ['test' => 'test']);
+        $this->assertEquals(1054, $this->subject->sql_errno());
+    }
+
+    /**
+     * @test
+     */
+    public function sqlPconnectReturnsInstanceOfMySqli()
+    {
+        $this->assertInstanceOf('mysqli', $this->subject->sql_pconnect());
+    }
+
+    /**
+     * @test
+     * @expectedException \RuntimeException
+     */
+    public function connectDbThrowsExeptionsWhenNoDatabaseIsGiven()
+    {
+        /** @var DatabaseConnection|\PHPUnit_Framework_MockObject_MockObject|AccessibleObjectInterface $subject */
+        $subject = $this->getAccessibleMock(DatabaseConnection::class, ['dummy'], [], '', false);
+        $subject->connectDB();
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function connectDbConnectsToDatabaseWithoutErrors()
+    {
+        $this->subject->connectDB();
+        $this->assertTrue($this->subject->isConnected());
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function disconnectIfConnectedDisconnects()
+    {
+        $this->assertTrue($this->subject->isConnected());
+        $this->subject->setDatabaseHost('127.0.0.1');
+        $this->assertFalse($this->subject->isConnected());
+    }
+
+    /**
+     * Data Provider for fullQuoteStrReturnsQuotedString()
+     *
+     * @see fullQuoteStrReturnsQuotedString()
+     *
+     * @return array
+     */
+    public function fullQuoteStrReturnsQuotedStringDataProvider()
+    {
+        return [
+            'NULL string with ReturnNull is allowed' => [
+                [null, true],
+                'NULL',
+            ],
+            'NULL string with ReturnNull is false' => [
+                [null, false],
+                "''",
+            ],
+            'Normal string' => [
+                ['Foo', false],
+                "'Foo'",
+            ],
+            'Single quoted string' => [
+                ["'Hello'", false],
+                "'\\'Hello\\''",
+            ],
+            'Double quoted string' => [
+                ['"Hello"', false],
+                "'\\\"Hello\\\"'",
+            ],
+            'String with internal single tick' => [
+                ['It\'s me', false],
+                "'It\\'s me'",
+            ],
+            'Slashes' => [
+                ['/var/log/syslog.log', false],
+                "'/var/log/syslog.log'",
+            ],
+            'Backslashes' => [
+                ['\\var\\log\\syslog.log', false],
+                "'\\\\var\\\\log\\\\syslog.log'",
+            ],
+        ];
+    }
+
+    /**
+     * @test
+     * @dataProvider fullQuoteStrReturnsQuotedStringDataProvider
+     *
+     * @param string $values
+     * @param string $expectedResult
+     *
+     * @return void
+     */
+    public function fullQuoteStrReturnsQuotedString($values, $expectedResult)
+    {
+        /** @var DatabaseConnection $subject */
+        $quotedStr = $this->subject->fullQuoteStr($values[0], 'tt_content', $values[1]);
+        $this->assertEquals($expectedResult, $quotedStr);
+    }
+
+    /**
+     * Data Provider for fullQuoteArrayQuotesArray()
+     *
+     * @see fullQuoteArrayQuotesArray()
+     *
+     * @return array
+     */
+    public function fullQuoteArrayQuotesArrayDataProvider()
+    {
+        return [
+            'NULL array with ReturnNull is allowed' => [
+                [
+                    [null, null],
+                    false,
+                    true,
+                ],
+                ['NULL', 'NULL'],
+            ],
+
+            'NULL array with ReturnNull is false' => [
+                [
+                    [null, null],
+                    false,
+                    false,
+                ],
+                ["''", "''"],
+            ],
+
+            'Strings in array' => [
+                [
+                    ['Foo', 'Bar'],
+                    false,
+                    false,
+                ],
+                ["'Foo'", "'Bar'"],
+            ],
+
+            'Single quotes in array' => [
+                [
+                    ["'Hello'"],
+                    false,
+                    false,
+                ],
+                ["'\\'Hello\\''"],
+            ],
+
+            'Double quotes in array' => [
+                [
+                    ['"Hello"'],
+                    false,
+                    false,
+                ],
+                ["'\\\"Hello\\\"'"],
+            ],
+
+            'Slashes in array' => [
+                [
+                    ['/var/log/syslog.log'],
+                    false,
+                    false,
+                ],
+                ["'/var/log/syslog.log'"],
+            ],
+
+            'Backslashes in array' => [
+                [
+                    ['\var\log\syslog.log'],
+                    false,
+                    false,
+                ],
+                ["'\\\\var\\\\log\\\\syslog.log'"],
+            ],
+
+            'Strings with internal single tick' => [
+                [
+                    ['Hey!', 'It\'s me'],
+                    false,
+                    false,
+                ],
+                ["'Hey!'", "'It\\'s me'"],
+            ],
+
+            'no quotes strings from array' => [
+                [
+                    [
+                        'First' => 'Hey!',
+                        'Second' => 'It\'s me',
+                        'Third' => 'O\' Reily',
+                    ],
+                    ['First', 'Third'],
+                    false,
+                ],
+                ['First' => 'Hey!', 'Second' => "'It\\'s me'", 'Third' => "O' Reily"],
+            ],
+
+            'no quotes strings from string' => [
+                [
+                    [
+                        'First' => 'Hey!',
+                        'Second' => 'It\'s me',
+                        'Third' => 'O\' Reily',
+                    ],
+                    'First,Third',
+                    false,
+                ],
+                ['First' => 'Hey!', 'Second' => "'It\\'s me'", 'Third' => "O' Reily"],
+            ],
+        ];
+    }
+
+    /**
+     * @test
+     * @dataProvider fullQuoteArrayQuotesArrayDataProvider
+     *
+     * @param string $values
+     * @param string $expectedResult
+     *
+     * @return void
+     */
+    public function fullQuoteArrayQuotesArray($values, $expectedResult)
+    {
+        $quotedResult = $this->subject->fullQuoteArray($values[0], $this->testTable, $values[1], $values[2]);
+        $this->assertSame($expectedResult, $quotedResult);
+    }
+
+    /**
+     * Data Provider for quoteStrQuotesDoubleQuotesCorrectly()
+     *
+     * @see quoteStrQuotesDoubleQuotesCorrectly()
+     *
+     * @return array
+     */
+    public function quoteStrQuotesCorrectlyDataProvider()
+    {
+        return [
+            'Double Quotes' => [
+                '"Hello"',
+                '\\"Hello\\"'
+            ],
+            'Single Quotes' => [
+                '\'Hello\'',
+                "\\'Hello\\'"
+            ],
+            'Slashes' => [
+                '/var/log/syslog.log',
+                '/var/log/syslog.log'
+            ],
+            'Literal Backslashes' => [
+                '\\var\\log\\syslog.log',
+                '\\\\var\\\\log\\\\syslog.log'
+            ],
+            'Fallback Literal Backslashes' => [
+                '\var\log\syslog.log',
+                '\\\\var\\\\log\\\\syslog.log'
+            ],
+        ];
+    }
+
+    /**
+     * @test
+     * @dataProvider quoteStrQuotesCorrectlyDataProvider
+     *
+     * @param string $string String to quote
+     * @param string $expectedResult Quoted string we expect
+     *
+     * @return void
+     */
+    public function quoteStrQuotesDoubleQuotesCorrectly($string, $expectedResult)
+    {
+        $quotedString = $this->subject->quoteStr($string, $this->testTable);
+        $this->assertSame($expectedResult, $quotedString);
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function adminQueryReturnsTrueForInsertQuery()
+    {
+        $this->assertTrue(
+            $this->subject->admin_query("INSERT INTO {$this->testTable} ({$this->testField}) VALUES ('foo')")
+        );
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function adminQueryReturnsTrueForUpdateQuery()
+    {
+        $this->assertTrue(
+            $this->subject->admin_query("INSERT INTO {$this->testTable} ({$this->testField}) VALUES ('foo')")
+        );
+        $id = $this->subject->sql_insert_id();
+        $this->assertTrue(
+            $this->subject->admin_query("UPDATE {$this->testTable} SET {$this->testField}='bar' WHERE id={$id}")
+        );
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function adminQueryReturnsTrueForDeleteQuery()
+    {
+        $this->assertTrue(
+            $this->subject->admin_query("INSERT INTO {$this->testTable} ({$this->testField}) VALUES ('foo')")
+        );
+        $id = $this->subject->sql_insert_id();
+        $this->assertTrue($this->subject->admin_query("DELETE FROM {$this->testTable} WHERE id={$id}"));
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function adminQueryReturnsResultForSelectQuery()
+    {
+        $this->assertTrue(
+            $this->subject->admin_query("INSERT INTO {$this->testTable} ({$this->testField}) VALUES ('foo')")
+        );
+        $res = $this->subject->admin_query("SELECT {$this->testField} FROM {$this->testTable}");
+        $this->assertInstanceOf('mysqli_result', $res);
+        $result = $res->fetch_assoc();
+        $this->assertEquals('foo', $result[$this->testField]);
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function adminGetCharsetsReturnsArrayWithCharsets()
+    {
+        $columnsRes = $this->subject->admin_query('SHOW CHARACTER SET');
+        $result = $this->subject->admin_get_charsets();
+        $this->assertEquals(count($result), $columnsRes->num_rows);
+
+        /** @var array $row */
+        while (($row = $columnsRes->fetch_assoc())) {
+            $this->assertArrayHasKey($row['Charset'], $result);
+        }
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function adminGetKeysReturnIndexKeysOfTable()
+    {
+        $result = $this->subject->admin_get_keys($this->testTable);
+        $this->assertEquals('id', $result[0]['Column_name']);
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function adminGetFieldsReturnFieldInformationsForTable()
+    {
+        $result = $this->subject->admin_get_fields($this->testTable);
+        $this->assertArrayHasKey('id', $result);
+        $this->assertArrayHasKey($this->testField, $result);
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function adminGetTablesReturnAllTablesFromDatabase()
+    {
+        $result = $this->subject->admin_get_tables();
+        $this->assertArrayHasKey('tt_content', $result);
+        $this->assertArrayHasKey('pages', $result);
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function adminGetDbsReturnsAllDatabases()
+    {
+        /** @noinspection SqlResolve */
+        $databases = $this->subject->admin_query('SELECT SCHEMA_NAME FROM information_schema.SCHEMATA');
+        $result = $this->subject->admin_get_dbs();
+        $this->assertSame(count($result), $databases->num_rows);
+
+        $i = 0;
+        while ($database = $databases->fetch_assoc()) {
+            $this->assertSame($database['SCHEMA_NAME'], $result[$i]);
+            $i++;
+        }
+    }
+
+    /**
+     * Data Provider for sqlNumRowsReturnsCorrectAmountOfRows()
+     *
+     * @see sqlNumRowsReturnsCorrectAmountOfRows()
+     *
+     * @return array
+     */
+    public function sqlNumRowsReturnsCorrectAmountOfRowsProvider()
+    {
+        $sql1 = "SELECT * FROM {$this->testTable} WHERE {$this->testField}='baz'";
+        $sql2 = "SELECT * FROM {$this->testTable} WHERE {$this->testField}='baz' OR {$this->testField}='bar'";
+        $sql3 = "SELECT * FROM {$this->testTable} WHERE {$this->testField} IN ('baz', 'bar', 'foo')";
+
+        return [
+            'One result' => [$sql1, 1],
+            'Two results' => [$sql2, 2],
+            'Three results' => [$sql3, 3],
+        ];
+    }
+
+    /**
+     * @test
+     * @dataProvider sqlNumRowsReturnsCorrectAmountOfRowsProvider
+     *
+     * @param string $sql
+     * @param string $expectedResult
+     *
+     * @return void
+     */
+    public function sqlNumRowsReturnsCorrectAmountOfRows($sql, $expectedResult)
+    {
+        $this->assertTrue(
+            $this->subject->admin_query(
+                "INSERT INTO {$this->testTable} ({$this->testField}) VALUES ('foo'), ('bar'), ('baz')"
+            )
+        );
+
+        $res = $this->subject->admin_query($sql);
+        $numRows = $this->subject->sql_num_rows($res);
+        $this->assertSame($expectedResult, $numRows);
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function sqlNumRowsReturnsFalse()
+    {
+        $res = $this->subject->admin_query("SELECT * FROM {$this->testTable} WHERE test='baz'");
+        $numRows = $this->subject->sql_num_rows($res);
+        $this->assertFalse($numRows);
+    }
+
+    /**
+     * Prepares the test table for the fetch* Tests
+     *
+     * @return void
+     */
+    protected function prepareTableForFetchTests()
+    {
+        $this->assertTrue(
+            $this->subject->sql_query(
+                "ALTER TABLE {$this->testTable} " .
+                'ADD name mediumblob, ' .
+                'ADD deleted int, ' .
+                'ADD street varchar(100), ' .
+                'ADD city varchar(50), ' .
+                'ADD country varchar(100)'
+            )
+        );
+
+        $this->assertTrue(
+            $this->subject->admin_query(
+                "INSERT INTO {$this->testTable} (name,street,city,country,deleted) VALUES " .
+                "('Mr. Smith','Oakland Road','Los Angeles','USA',0)," .
+                "('Ms. Smith','Oakland Road','Los Angeles','USA',0)," .
+                "('Alice im Wunderland','Große Straße','Königreich der Herzen','Wunderland',0)," .
+                "('Agent Smith','Unbekannt','Unbekannt','Matrix',1)"
+            )
+        );
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function sqlFetchAssocReturnsAssocArray()
+    {
+        $this->prepareTableForFetchTests();
+
+        $res = $this->subject->admin_query("SELECT * FROM {$this->testTable} ORDER BY id");
+        $expectedResult = [
+            [
+                'id' => '1',
+                $this->testField => null,
+                $this->anotherTestField => null,
+                'name' => 'Mr. Smith',
+                'deleted' => '0',
+                'street' => 'Oakland Road',
+                'city' => 'Los Angeles',
+                'country' => 'USA',
+            ],
+            [
+                'id' => '2',
+                $this->testField => null,
+                $this->anotherTestField => null,
+                'name' => 'Ms. Smith',
+                'deleted' => '0',
+                'street' => 'Oakland Road',
+                'city' => 'Los Angeles',
+                'country' => 'USA',
+            ],
+            [
+                'id' => '3',
+                $this->testField => null,
+                $this->anotherTestField => null,
+                'name' => 'Alice im Wunderland',
+                'deleted' => '0',
+                'street' => 'Große Straße',
+                'city' => 'Königreich der Herzen',
+                'country' => 'Wunderland',
+            ],
+            [
+                'id' => '4',
+                $this->testField => null,
+                $this->anotherTestField => null,
+                'name' => 'Agent Smith',
+                'deleted' => '1',
+                'street' => 'Unbekannt',
+                'city' => 'Unbekannt',
+                'country' => 'Matrix',
+            ],
+        ];
+        $i = 0;
+        while ($row = $this->subject->sql_fetch_assoc($res)) {
+            $this->assertSame($expectedResult[$i], $row);
+            $i++;
+        }
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function sqlFetchRowReturnsNumericArray()
+    {
+        $this->prepareTableForFetchTests();
+        $res = $this->subject->admin_query("SELECT * FROM {$this->testTable} ORDER BY id");
+        $expectedResult = [
+            ['1', null, null, 'Mr. Smith', '0', 'Oakland Road', 'Los Angeles', 'USA'],
+            ['2', null, null, 'Ms. Smith', '0', 'Oakland Road', 'Los Angeles', 'USA'],
+            ['3', null, null, 'Alice im Wunderland', '0', 'Große Straße', 'Königreich der Herzen', 'Wunderland'],
+            ['4', null, null, 'Agent Smith', '1', 'Unbekannt', 'Unbekannt', 'Matrix'],
+        ];
+        $i = 0;
+        while ($row = $this->subject->sql_fetch_row($res)) {
+            $this->assertSame($expectedResult[$i], $row);
+            $i++;
+        }
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function sqlFreeResultReturnsFalseOnFailure()
+    {
+        $this->assertTrue(
+            $this->subject->admin_query("INSERT INTO {$this->testTable} ({$this->testField}) VALUES ('baz')")
+        );
+        $res = $this->subject->admin_query("SELECT * FROM {$this->testTable} WHERE {$this->testField}=baz");
+        $this->assertFalse($this->subject->sql_free_result($res));
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function sqlFreeResultReturnsTrueOnSuccess()
+    {
+        $this->assertTrue(
+            $this->subject->admin_query("INSERT INTO {$this->testTable} ({$this->testField}) VALUES ('baz')")
+        );
+        $res = $this->subject->admin_query("SELECT * FROM {$this->testTable} WHERE {$this->testField}='baz'");
+        $this->assertTrue($this->subject->sql_free_result($res));
+    }
+}
diff --git a/typo3/sysext/core/Tests/Functional/Database/PreparedStatementTest.php b/typo3/sysext/core/Tests/Functional/Database/PreparedStatementTest.php
new file mode 100644 (file)
index 0000000..2d4d28a
--- /dev/null
@@ -0,0 +1,102 @@
+<?php
+namespace TYPO3\CMS\Core\Tests\Functional\Database;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Core\Database\DatabaseConnection;
+use TYPO3\CMS\Core\Tests\FunctionalTestCase;
+
+/**
+ * Test case for \TYPO3\CMS\Core\Database\PreparedStatement
+ */
+class PreparedStatementTest extends FunctionalTestCase
+{
+    /**
+     * @var DatabaseConnection
+     */
+    protected $subject = null;
+
+    /**
+     * @var string
+     */
+    protected $testTable = 'test_database_connection';
+
+    /**
+     * @var string
+     */
+    protected $testField = 'test_field';
+
+    /**
+     * @var string
+     */
+    protected $anotherTestField = 'another_test_field';
+
+    /**
+     * Set the test up
+     *
+     * @return void
+     */
+    protected function setUp()
+    {
+        parent::setUp();
+        $this->subject = $GLOBALS['TYPO3_DB'];
+        $this->subject->sql_query(
+            "CREATE TABLE {$this->testTable} (" .
+            '   id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,' .
+            "   {$this->testField} MEDIUMBLOB," .
+            "   {$this->anotherTestField} MEDIUMBLOB," .
+            '   PRIMARY KEY (id)' .
+            ') ENGINE=MyISAM DEFAULT CHARSET=utf8;'
+        );
+    }
+
+    /**
+     * Tear the test down
+     *
+     * @return void
+     */
+    protected function tearDown()
+    {
+        $this->subject->sql_query("DROP TABLE {$this->testTable};");
+        unset($this->subject);
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function prepareSelectQueryCreateValidQuery()
+    {
+        $this->assertTrue(
+            $this->subject->admin_query("INSERT INTO {$this->testTable} ({$this->testField}) VALUES ('aTestValue')")
+        );
+        $preparedQuery = $this->subject->prepare_SELECTquery(
+            "{$this->testField},{$this->anotherTestField}",
+            $this->testTable,
+            'id=:id',
+            '',
+            '',
+            '',
+            [':id' => 1]
+        );
+        $preparedQuery->execute();
+        $result = $preparedQuery->fetch();
+        $expectedResult = [
+            $this->testField => 'aTestValue',
+            $this->anotherTestField => null,
+        ];
+        $this->assertSame($expectedResult, $result);
+    }
+}
index 6065ee8..a14cf81 100644 (file)
@@ -14,12 +14,48 @@ namespace TYPO3\CMS\Core\Tests\Unit\Database;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Database\DatabaseConnection;
+use TYPO3\CMS\Core\Tests\AccessibleObjectInterface;
+use TYPO3\CMS\Core\Tests\UnitTestCase;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
 /**
  * Test case
  *
  */
-class DatabaseConnectionTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
+class DatabaseConnectionTest extends UnitTestCase
 {
+    /**
+     * @var DatabaseConnection
+     */
+    protected $subject;
+    /**
+     * @var string
+     */
+    protected $testTable = 'test_database_connection';
+
+    /**
+     * @var string
+     */
+    protected $testField = 'test_field';
+
+    /**
+     * @var string
+     */
+    protected $anotherTestField = 'another_test_field';
+
+    /**
+     * Set the test up
+     *
+     * @return void
+     */
+    protected function setUp()
+    {
+        parent::setUp();
+        $this->subject = $this->getAccessibleMock(DatabaseConnection::class, ['dummy'], [], '', false);
+        $this->subject->_set('databaseName', 'typo3_test');
+    }
+
     //////////////////////////////////////////////////
     // Write/Read tests for charsets and binaries
     //////////////////////////////////////////////////
@@ -34,8 +70,8 @@ class DatabaseConnectionTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
             $binaryString .= chr($i);
         }
 
-        /** @var \TYPO3\CMS\Core\Database\DatabaseConnection|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface $subject */
-        $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Database\DatabaseConnection::class, array('fullQuoteStr'), array(), '', false);
+        /** @var DatabaseConnection|\PHPUnit_Framework_MockObject_MockObject|AccessibleObjectInterface $subject */
+        $subject = $this->getAccessibleMock(DatabaseConnection::class, ['fullQuoteStr'], [], '', false);
         $subject->_set('isConnected', true);
         $subject
             ->expects($this->any())
@@ -47,21 +83,22 @@ class DatabaseConnectionTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
         $mysqliMock
             ->expects($this->once())
             ->method('query')
-            ->with('INSERT INTO aTable (fieldblob) VALUES (' . $binaryString . ')');
+            ->with("INSERT INTO {$this->testTable} ({$this->testField}) VALUES ({$binaryString})");
         $subject->_set('link', $mysqliMock);
 
-        $subject->exec_INSERTquery('aTable', array('fieldblob' => $binaryString));
+        $subject->exec_INSERTquery($this->testTable, [$this->testField => $binaryString]);
     }
 
     /**
      * @test
+     * @requires function gzcompress
      */
     public function storedGzipCompressedDataReturnsSameData()
     {
-        $testStringWithBinary = @gzcompress('sdfkljer4587');
+        $testStringWithBinary = gzcompress('sdfkljer4587');
 
-        /** @var \TYPO3\CMS\Core\Database\DatabaseConnection|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface $subject */
-        $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Database\DatabaseConnection::class, array('fullQuoteStr'), array(), '', false);
+        /** @var DatabaseConnection|\PHPUnit_Framework_MockObject_MockObject|AccessibleObjectInterface $subject */
+        $subject = $this->getAccessibleMock(DatabaseConnection::class, ['fullQuoteStr'], [], '', false);
         $subject->_set('isConnected', true);
         $subject
             ->expects($this->any())
@@ -73,10 +110,10 @@ class DatabaseConnectionTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
         $mysqliMock
             ->expects($this->once())
             ->method('query')
-            ->with('INSERT INTO aTable (fieldblob) VALUES (' . $testStringWithBinary . ')');
+            ->with("INSERT INTO {$this->testTable} ({$this->testField}) VALUES ({$testStringWithBinary})");
         $subject->_set('link', $mysqliMock);
 
-        $subject->exec_INSERTquery('aTable', array('fieldblob' => $testStringWithBinary));
+        $subject->exec_INSERTquery($this->testTable, [$this->testField => $testStringWithBinary]);
     }
 
     ////////////////////////////////
@@ -89,8 +126,8 @@ class DatabaseConnectionTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
      */
     public function listQueryWithIntegerCommaAsValue()
     {
-        /** @var \TYPO3\CMS\Core\Database\DatabaseConnection|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface $subject */
-        $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Database\DatabaseConnection::class, array('quoteStr'), array(), '', false);
+        /** @var DatabaseConnection|\PHPUnit_Framework_MockObject_MockObject|AccessibleObjectInterface $subject */
+        $subject = $this->getAccessibleMock(DatabaseConnection::class, ['quoteStr'], [], '', false);
         $subject->_set('isConnected', true);
         $subject
             ->expects($this->any())
@@ -108,8 +145,8 @@ class DatabaseConnectionTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
      */
     public function listQueryThrowsExceptionIfValueContainsComma()
     {
-        /** @var \TYPO3\CMS\Core\Database\DatabaseConnection|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface $subject */
-        $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Database\DatabaseConnection::class, array('quoteStr'), array(), '', false);
+        /** @var DatabaseConnection|\PHPUnit_Framework_MockObject_MockObject|AccessibleObjectInterface $subject */
+        $subject = $this->getAccessibleMock(DatabaseConnection::class, ['quoteStr'], [], '', false);
         $subject->_set('isConnected', true);
         $subject->listQuery('aField', 'foo,bar', 'aTable');
     }
@@ -125,77 +162,76 @@ class DatabaseConnectionTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
      */
     public function searchQueryDataProvider()
     {
-        return array(
-            'One search word in one field' => array(
+        return [
+            'One search word in one field' => [
                 '(pages.title LIKE \'%TYPO3%\')',
-                array('TYPO3'),
-                array('title'),
+                ['TYPO3'],
+                ['title'],
                 'pages',
-                'AND'
-            ),
-
-            'One search word with special chars (for like)' => array(
+                'AND',
+            ],
+            'One search word with special chars (for like)' => [
                 '(pages.title LIKE \'%TYPO3\\_100\\%%\')',
-                array('TYPO3_100%'),
-                array('title'),
+                ['TYPO3_100%'],
+                ['title'],
                 'pages',
-                'AND'
-            ),
-
-            'One search word in multiple fields' => array(
-                '(pages.title LIKE \'%TYPO3%\' OR pages.keyword LIKE \'%TYPO3%\' OR pages.description LIKE \'%TYPO3%\')',
-                array('TYPO3'),
-                array('title', 'keyword', 'description'),
+                'AND',
+            ],
+            'One search word in multiple fields' => [
+                "(pages.title LIKE '%TYPO3%' OR pages.keyword LIKE '%TYPO3%' OR pages.description LIKE '%TYPO3%')",
+                ['TYPO3'],
+                ['title', 'keyword', 'description'],
                 'pages',
-                'AND'
-            ),
-
-            'Multiple search words in one field with AND constraint' => array(
-                '(pages.title LIKE \'%TYPO3%\') AND (pages.title LIKE \'%is%\') AND (pages.title LIKE \'%great%\')',
-                array('TYPO3', 'is', 'great'),
-                array('title'),
+                'AND',
+            ],
+            'Multiple search words in one field with AND constraint' => [
+                "(pages.title LIKE '%TYPO3%') AND (pages.title LIKE '%is%') AND (pages.title LIKE '%great%')",
+                ['TYPO3', 'is', 'great'],
+                ['title'],
                 'pages',
-                'AND'
-            ),
-
-            'Multiple search words in one field with OR constraint' => array(
-                '(pages.title LIKE \'%TYPO3%\') OR (pages.title LIKE \'%is%\') OR (pages.title LIKE \'%great%\')',
-                array('TYPO3', 'is', 'great'),
-                array('title'),
+                'AND',
+            ],
+            'Multiple search words in one field with OR constraint' => [
+                "(pages.title LIKE '%TYPO3%') OR (pages.title LIKE '%is%') OR (pages.title LIKE '%great%')",
+                ['TYPO3', 'is', 'great'],
+                ['title'],
                 'pages',
-                'OR'
-            ),
-
-            'Multiple search words in multiple fields with AND constraint' => array(
-                '(pages.title LIKE \'%TYPO3%\' OR pages.keywords LIKE \'%TYPO3%\' OR pages.description LIKE \'%TYPO3%\') AND ' .
-                    '(pages.title LIKE \'%is%\' OR pages.keywords LIKE \'%is%\' OR pages.description LIKE \'%is%\') AND ' .
-                    '(pages.title LIKE \'%great%\' OR pages.keywords LIKE \'%great%\' OR pages.description LIKE \'%great%\')',
-                array('TYPO3', 'is', 'great'),
-                array('title', 'keywords', 'description'),
+                'OR',
+            ],
+            'Multiple search words in multiple fields with AND constraint' => [
+                "(pages.title LIKE '%TYPO3%' OR pages.keywords LIKE '%TYPO3%' OR pages.description LIKE '%TYPO3%') " .
+                "AND (pages.title LIKE '%is%' OR pages.keywords LIKE '%is%' OR pages.description LIKE '%is%') " .
+                "AND (pages.title LIKE '%great%' OR pages.keywords LIKE '%great%' OR pages.description LIKE '%great%')",
+                ['TYPO3', 'is', 'great'],
+                ['title', 'keywords', 'description'],
                 'pages',
-                'AND'
-            ),
-
-            'Multiple search words in multiple fields with OR constraint' => array(
-                '(pages.title LIKE \'%TYPO3%\' OR pages.keywords LIKE \'%TYPO3%\' OR pages.description LIKE \'%TYPO3%\') OR ' .
-                    '(pages.title LIKE \'%is%\' OR pages.keywords LIKE \'%is%\' OR pages.description LIKE \'%is%\') OR ' .
-                    '(pages.title LIKE \'%great%\' OR pages.keywords LIKE \'%great%\' OR pages.description LIKE \'%great%\')',
-                array('TYPO3', 'is', 'great'),
-                array('title', 'keywords', 'description'),
+                'AND',
+            ],
+            'Multiple search words in multiple fields with OR constraint' => [
+                "(pages.title LIKE '%TYPO3%' OR pages.keywords LIKE '%TYPO3%' OR pages.description LIKE '%TYPO3%') " .
+                "OR (pages.title LIKE '%is%' OR pages.keywords LIKE '%is%' OR pages.description LIKE '%is%') " .
+                "OR (pages.title LIKE '%great%' OR pages.keywords LIKE '%great%' OR pages.description LIKE '%great%')",
+                ['TYPO3', 'is', 'great'],
+                ['title', 'keywords', 'description'],
                 'pages',
-                'OR'
-            ),
-        );
+                'OR',
+            ],
+        ];
     }
 
     /**
      * @test
      * @dataProvider searchQueryDataProvider
+     * @param string $expectedResult
+     * @param array $searchWords
+     * @param array $fields
+     * @param string $table
+     * @param string $constraint
      */
-    public function searchQueryCreatesQuery($expectedResult, $searchWords, $fields, $table, $constraint)
+    public function searchQueryCreatesQuery($expectedResult, array $searchWords, array $fields, $table, $constraint)
     {
-        /** @var \TYPO3\CMS\Core\Database\DatabaseConnection|\PHPUnit_Framework_MockObject_MockObject $subject */
-        $subject = $this->getMock(\TYPO3\CMS\Core\Database\DatabaseConnection::class, array('quoteStr'), array(), '', false);
+        /** @var DatabaseConnection|\PHPUnit_Framework_MockObject_MockObject $subject */
+        $subject = $this->getMock(DatabaseConnection::class, ['quoteStr'], [], '', false);
         $subject
             ->expects($this->any())
             ->method('quoteStr')
@@ -215,8 +251,8 @@ class DatabaseConnectionTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
      */
     public function escapeStringForLikeComparison()
     {
-        /** @var \TYPO3\CMS\Core\Database\DatabaseConnection|\PHPUnit_Framework_MockObject_MockObject $subject */
-        $subject = $this->getMock(\TYPO3\CMS\Core\Database\DatabaseConnection::class, array('dummy'), array(), '', false);
+        /** @var DatabaseConnection|\PHPUnit_Framework_MockObject_MockObject $subject */
+        $subject = $this->getMock(DatabaseConnection::class, ['dummy'], [], '', false);
         $this->assertEquals('foo\\_bar\\%', $subject->escapeStrForLike('foo_bar%', 'table'));
     }
 
@@ -232,17 +268,44 @@ class DatabaseConnectionTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
      */
     public function stripOrderByForOrderByKeywordDataProvider()
     {
-        return array(
-            'single ORDER BY' => array('ORDER BY name, tstamp', 'name, tstamp'),
-            'single ORDER BY in lower case' => array('order by name, tstamp', 'name, tstamp'),
-            'ORDER BY with additional space behind' => array('ORDER BY  name, tstamp', 'name, tstamp'),
-            'ORDER BY without space between the words' => array('ORDERBY name, tstamp', 'name, tstamp'),
-            'ORDER BY added twice' => array('ORDER BY ORDER BY name, tstamp', 'name, tstamp'),
-            'ORDER BY added twice without spaces in the first occurrence' => array('ORDERBY ORDER BY  name, tstamp', 'name, tstamp'),
-            'ORDER BY added twice without spaces in the second occurrence' => array('ORDER BYORDERBY name, tstamp', 'name, tstamp'),
-            'ORDER BY added twice without spaces' => array('ORDERBYORDERBY name, tstamp', 'name, tstamp'),
-            'ORDER BY added twice without spaces afterwards' => array('ORDERBYORDERBYname, tstamp', 'name, tstamp'),
-        );
+        return [
+            'single ORDER BY' => [
+                'ORDER BY name, tstamp',
+                'name, tstamp'
+            ],
+            'single ORDER BY in lower case' => [
+                'order by name, tstamp',
+                'name, tstamp'
+            ],
+            'ORDER BY with additional space behind' => [
+                'ORDER BY  name, tstamp',
+                'name, tstamp'
+            ],
+            'ORDER BY without space between the words' => [
+                'ORDERBY name, tstamp',
+                'name, tstamp'
+            ],
+            'ORDER BY added twice' => [
+                'ORDER BY ORDER BY name, tstamp',
+                'name, tstamp'
+            ],
+            'ORDER BY added twice without spaces in the first occurrence' => [
+                'ORDERBY ORDER BY  name, tstamp',
+                'name, tstamp',
+            ],
+            'ORDER BY added twice without spaces in the second occurrence' => [
+                'ORDER BYORDERBY name, tstamp',
+                'name, tstamp',
+            ],
+            'ORDER BY added twice without spaces' => [
+                'ORDERBYORDERBY name, tstamp',
+                'name, tstamp'
+            ],
+            'ORDER BY added twice without spaces afterwards' => [
+                'ORDERBYORDERBYname, tstamp',
+                'name, tstamp'
+            ],
+        ];
     }
 
     /**
@@ -254,8 +317,8 @@ class DatabaseConnectionTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
      */
     public function stripOrderByForOrderByKeyword($orderByClause, $expectedResult)
     {
-        /** @var \TYPO3\CMS\Core\Database\DatabaseConnection|\PHPUnit_Framework_MockObject_MockObject $subject */
-        $subject = $this->getMock(\TYPO3\CMS\Core\Database\DatabaseConnection::class, array('dummy'), array(), '', false);
+        /** @var DatabaseConnection|\PHPUnit_Framework_MockObject_MockObject $subject */
+        $subject = $this->getMock(DatabaseConnection::class, ['dummy'], [], '', false);
         $strippedQuery = $subject->stripOrderBy($orderByClause);
         $this->assertEquals($expectedResult, $strippedQuery);
     }
@@ -272,17 +335,44 @@ class DatabaseConnectionTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
      */
     public function stripGroupByForGroupByKeywordDataProvider()
     {
-        return array(
-            'single GROUP BY' => array('GROUP BY name, tstamp', 'name, tstamp'),
-            'single GROUP BY in lower case' => array('group by name, tstamp', 'name, tstamp'),
-            'GROUP BY with additional space behind' => array('GROUP BY  name, tstamp', 'name, tstamp'),
-            'GROUP BY without space between the words' => array('GROUPBY name, tstamp', 'name, tstamp'),
-            'GROUP BY added twice' => array('GROUP BY GROUP BY name, tstamp', 'name, tstamp'),
-            'GROUP BY added twice without spaces in the first occurrence' => array('GROUPBY GROUP BY  name, tstamp', 'name, tstamp'),
-            'GROUP BY added twice without spaces in the second occurrence' => array('GROUP BYGROUPBY name, tstamp', 'name, tstamp'),
-            'GROUP BY added twice without spaces' => array('GROUPBYGROUPBY name, tstamp', 'name, tstamp'),
-            'GROUP BY added twice without spaces afterwards' => array('GROUPBYGROUPBYname, tstamp', 'name, tstamp'),
-        );
+        return [
+            'single GROUP BY' => [
+                'GROUP BY name, tstamp',
+                'name, tstamp'
+            ],
+            'single GROUP BY in lower case' => [
+                'group by name, tstamp',
+                'name, tstamp'
+            ],
+            'GROUP BY with additional space behind' => [
+                'GROUP BY  name, tstamp',
+                'name, tstamp'
+            ],
+            'GROUP BY without space between the words' => [
+                'GROUPBY name, tstamp',
+                'name, tstamp'
+            ],
+            'GROUP BY added twice' => [
+                'GROUP BY GROUP BY name, tstamp',
+                'name, tstamp'
+            ],
+            'GROUP BY added twice without spaces in the first occurrence' => [
+                'GROUPBY GROUP BY  name, tstamp',
+                'name, tstamp',
+            ],
+            'GROUP BY added twice without spaces in the second occurrence' => [
+                'GROUP BYGROUPBY name, tstamp',
+                'name, tstamp',
+            ],
+            'GROUP BY added twice without spaces' => [
+                'GROUPBYGROUPBY name, tstamp',
+                'name, tstamp'
+            ],
+            'GROUP BY added twice without spaces afterwards' => [
+                'GROUPBYGROUPBYname, tstamp',
+                'name, tstamp'
+            ],
+        ];
     }
 
     /**
@@ -294,8 +384,8 @@ class DatabaseConnectionTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
      */
     public function stripGroupByForGroupByKeyword($groupByClause, $expectedResult)
     {
-        /** @var \TYPO3\CMS\Core\Database\DatabaseConnection|\PHPUnit_Framework_MockObject_MockObject $subject */
-        $subject = $this->getMock(\TYPO3\CMS\Core\Database\DatabaseConnection::class, array('dummy'), array(), '', false);
+        /** @var DatabaseConnection|\PHPUnit_Framework_MockObject_MockObject $subject */
+        $subject = $this->getMock(DatabaseConnection::class, ['dummy'], [], '', false);
         $strippedQuery = $subject->stripGroupBy($groupByClause);
         $this->assertEquals($expectedResult, $strippedQuery);
     }
@@ -312,54 +402,54 @@ class DatabaseConnectionTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
      */
     public function cleanIntArrayDataProvider()
     {
-        return array(
-            'simple array' => array(
-                array(1, 2, 3),
-                array(1, 2, 3)
-            ),
-            'string array' => array(
-                array('2', '4', '8'),
-                array(2, 4, 8)
-            ),
-            'string array with letters #1' => array(
-                array('3', '6letters', '12'),
-                array(3, 6, 12)
-            ),
-            'string array with letters #2' => array(
-                array('3', 'letters6', '12'),
-                array(3, 0, 12)
-            ),
-            'string array with letters #3' => array(
-                array('3', '6letters4', '12'),
-                array(3, 6, 12)
-            ),
-            'associative array' => array(
-                array('apples' => 3, 'bananas' => 4, 'kiwis' => 9),
-                array('apples' => 3, 'bananas' => 4, 'kiwis' => 9)
-            ),
-            'associative string array' => array(
-                array('apples' => '1', 'bananas' => '5', 'kiwis' => '7'),
-                array('apples' => 1, 'bananas' => 5, 'kiwis' => 7)
-            ),
-            'associative string array with letters #1' => array(
-                array('apples' => '1', 'bananas' => 'no5', 'kiwis' => '7'),
-                array('apples' => 1, 'bananas' => 0, 'kiwis' => 7)
-            ),
-            'associative string array with letters #2' => array(
-                array('apples' => '1', 'bananas' => '5yes', 'kiwis' => '7'),
-                array('apples' => 1, 'bananas' => 5, 'kiwis' => 7)
-            ),
-            'associative string array with letters #3' => array(
-                array('apples' => '1', 'bananas' => '5yes9', 'kiwis' => '7'),
-                array('apples' => 1, 'bananas' => 5, 'kiwis' => 7)
-            ),
-            'multidimensional associative array' => array(
-                array('apples' => '1', 'bananas' => array(3, 4), 'kiwis' => '7'),
+        return [
+            'simple array' => [
+                [1, 2, 3],
+                [1, 2, 3],
+            ],
+            'string array' => [
+                ['2', '4', '8'],
+                [2, 4, 8],
+            ],
+            'string array with letters #1' => [
+                ['3', '6letters', '12'],
+                [3, 6, 12],
+            ],
+            'string array with letters #2' => [
+                ['3', 'letters6', '12'],
+                [3, 0, 12],
+            ],
+            'string array with letters #3' => [
+                ['3', '6letters4', '12'],
+                [3, 6, 12],
+            ],
+            'associative array' => [
+                ['apples' => 3, 'bananas' => 4, 'kiwis' => 9],
+                ['apples' => 3, 'bananas' => 4, 'kiwis' => 9],
+            ],
+            'associative string array' => [
+                ['apples' => '1', 'bananas' => '5', 'kiwis' => '7'],
+                ['apples' => 1, 'bananas' => 5, 'kiwis' => 7],
+            ],
+            'associative string array with letters #1' => [
+                ['apples' => '1', 'bananas' => 'no5', 'kiwis' => '7'],
+                ['apples' => 1, 'bananas' => 0, 'kiwis' => 7],
+            ],
+            'associative string array with letters #2' => [
+                ['apples' => '1', 'bananas' => '5yes', 'kiwis' => '7'],
+                ['apples' => 1, 'bananas' => 5, 'kiwis' => 7],
+            ],
+            'associative string array with letters #3' => [
+                ['apples' => '1', 'bananas' => '5yes9', 'kiwis' => '7'],
+                ['apples' => 1, 'bananas' => 5, 'kiwis' => 7],
+            ],
+            'multidimensional associative array' => [
+                ['apples' => '1', 'bananas' => [3, 4], 'kiwis' => '7'],
                 // intval(array(...)) is 1
                 // But by specification "cleanIntArray" should only get used on one-dimensional arrays
-                array('apples' => 1, 'bananas' => 1, 'kiwis' => 7)
-            ),
-        );
+                ['apples' => 1, 'bananas' => 1, 'kiwis' => 7],
+            ],
+        ];
     }
 
     /**
@@ -371,20 +461,40 @@ class DatabaseConnectionTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
      */
     public function cleanIntArray($exampleData, $expectedResult)
     {
-        /** @var \TYPO3\CMS\Core\Database\DatabaseConnection $subject */
-        $subject = new \TYPO3\CMS\Core\Database\DatabaseConnection();
-        $sanitizedArray = $subject->cleanIntArray($exampleData);
+        $sanitizedArray = $this->subject->cleanIntArray($exampleData);
         $this->assertEquals($expectedResult, $sanitizedArray);
     }
 
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function cleanIntListReturnsCleanedString()
+    {
+        $str = '234,-434,4.3,0, 1';
+        $result = $this->subject->cleanIntList($str);
+        $this->assertSame('234,-434,4,0,1', $result);
+    }
+
     /**
      * @test
      */
     public function sqlForSelectMmQuery()
     {
-        $subject = new \TYPO3\CMS\Core\Database\DatabaseConnection();
-        $result = $subject->SELECT_mm_query('*', 'sys_category', 'sys_category_record_mm', 'tt_content', 'AND sys_category.uid = 1', '', 'sys_category.title DESC');
-        $expected = 'SELECT * FROM sys_category,sys_category_record_mm,tt_content WHERE sys_category.uid=sys_category_record_mm.uid_local AND tt_content.uid=sys_category_record_mm.uid_foreign AND sys_category.uid = 1 ORDER BY sys_category.title DESC';
+        $result = $this->subject->SELECT_mm_query(
+            '*',
+            'sys_category',
+            'sys_category_record_mm',
+            'tt_content',
+            'AND sys_category.uid = 1',
+            '',
+            'sys_category.title DESC'
+        );
+        $expected = 'SELECT * FROM sys_category,sys_category_record_mm,tt_content ' .
+            'WHERE sys_category.uid=sys_category_record_mm.uid_local ' .
+            'AND tt_content.uid=sys_category_record_mm.uid_foreign ' .
+            'AND sys_category.uid = 1 ORDER BY sys_category.title DESC';
         $this->assertEquals($expected, $result);
     }
 
@@ -395,28 +505,28 @@ class DatabaseConnectionTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
      */
     public function noQuoteForFullQuoteArrayDataProvider()
     {
-        return array(
-            'noQuote boolean false' => array(
-                array('aField' => 'aValue', 'anotherField' => 'anotherValue'),
-                array('aField' => '\'aValue\'', 'anotherField' => '\'anotherValue\''),
-                false
-            ),
-            'noQuote boolean true' => array(
-                array('aField' => 'aValue', 'anotherField' => 'anotherValue'),
-                array('aField' => 'aValue', 'anotherField' => 'anotherValue'),
-                true
-            ),
-            'noQuote list of fields' => array(
-                array('aField' => 'aValue', 'anotherField' => 'anotherValue'),
-                array('aField' => '\'aValue\'', 'anotherField' => 'anotherValue'),
-                'anotherField'
-            ),
-            'noQuote array of fields' => array(
-                array('aField' => 'aValue', 'anotherField' => 'anotherValue'),
-                array('aField' => 'aValue', 'anotherField' => '\'anotherValue\''),
-                array('aField')
-            ),
-        );
+        return [
+            'noQuote boolean false' => [
+                ['aField' => 'aValue', 'anotherField' => 'anotherValue'],
+                ['aField' => "'aValue'", 'anotherField' => "'anotherValue'"],
+                false,
+            ],
+            'noQuote boolean true' => [
+                ['aField' => 'aValue', 'anotherField' => 'anotherValue'],
+                ['aField' => 'aValue', 'anotherField' => 'anotherValue'],
+                true,
+            ],
+            'noQuote list of fields' => [
+                ['aField' => 'aValue', 'anotherField' => 'anotherValue'],
+                ['aField' => "'aValue'", 'anotherField' => 'anotherValue'],
+                'anotherField',
+            ],
+            'noQuote array of fields' => [
+                ['aField' => 'aValue', 'anotherField' => 'anotherValue'],
+                ['aField' => 'aValue', 'anotherField' => "'anotherValue'"],
+                ['aField'],
+            ],
+        ];
     }
 
     /**
@@ -428,11 +538,11 @@ class DatabaseConnectionTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
      */
     public function noQuoteForFullQuoteArray(array $input, array $expected, $noQuote)
     {
-        /** @var \TYPO3\CMS\Core\Database\DatabaseConnection|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface $subject */
+        /** @var DatabaseConnection|\PHPUnit_Framework_MockObject_MockObject|AccessibleObjectInterface $subject */
         $subject = $this->getMock(
-            \TYPO3\CMS\Core\Database\DatabaseConnection::class,
-            array('fullQuoteStr'),
-            array(),
+            DatabaseConnection::class,
+            ['fullQuoteStr'],
+            [],
             '',
             false
         );
@@ -444,4 +554,230 @@ class DatabaseConnectionTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
             }));
         $this->assertSame($expected, $subject->fullQuoteArray($input, 'aTable', $noQuote));
     }
+
+    /**
+     * @test
+     */
+    public function sqlSelectDbReturnsTrue()
+    {
+        /** @var DatabaseConnection|\PHPUnit_Framework_MockObject_MockObject|AccessibleObjectInterface $subject */
+        $subject = $this->getAccessibleMock(DatabaseConnection::class, ['dummy'], [], '', false);
+        $subject->_set('isConnected', true);
+        $subject->_set('databaseName', $this->testTable);
+
+        $mysqliMock = $this->getMock('mysqli');
+        $mysqliMock
+            ->expects($this->once())
+            ->method('select_db')
+            ->with($this->equalTo($this->testTable))->will($this->returnValue(true));
+        $subject->_set('link', $mysqliMock);
+
+        $this->assertTrue($subject->sql_select_db());
+    }
+
+    /**
+     * @test
+     */
+    public function sqlSelectDbReturnsFalse()
+    {
+        $GLOBALS['TYPO3_CONF_VARS']['SYS']['systemLogLevel'] = GeneralUtility::SYSLOG_SEVERITY_WARNING;
+
+        /** @var DatabaseConnection|\PHPUnit_Framework_MockObject_MockObject|AccessibleObjectInterface $subject */
+        $subject = $this->getAccessibleMock(DatabaseConnection::class, ['dummy'], [], '', false);
+        $subject->_set('isConnected', true);
+        $subject->_set('databaseName', $this->testTable);
+
+        $mysqliMock = $this->getMock('mysqli');
+        $mysqliMock
+            ->expects($this->once())
+            ->method('select_db')
+            ->with($this->equalTo($this->testTable))->will($this->returnValue(false));
+        $subject->_set('link', $mysqliMock);
+
+        $this->assertFalse($subject->sql_select_db());
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function insertQueryCreateValidQuery()
+    {
+        $this->subject = $this->getAccessibleMock(DatabaseConnection::class, ['fullQuoteStr'], [], '', false);
+        $this->subject->expects($this->any())
+            ->method('fullQuoteStr')
+            ->will($this->returnCallback(function ($data) {
+                return '\'' . (string)$data . '\'';
+            }));
+
+        $fieldValues = [$this->testField => 'Foo'];
+        $queryExpected = "INSERT INTO {$this->testTable} ({$this->testField}) VALUES ('Foo')";
+        $queryGenerated = $this->subject->INSERTquery($this->testTable, $fieldValues);
+        $this->assertSame($queryExpected, $queryGenerated);
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function insertQueryCreateValidQueryFromMultipleValues()
+    {
+        $this->subject = $this->getAccessibleMock(DatabaseConnection::class, ['fullQuoteStr'], [], '', false);
+        $this->subject->expects($this->any())
+            ->method('fullQuoteStr')
+            ->will($this->returnCallback(function ($data) {
+                return '\'' . (string)$data . '\'';
+            }));
+        $fieldValues = [
+            $this->testField => 'Foo',
+            $this->anotherTestField => 'Bar',
+        ];
+        $queryExpected = "INSERT INTO {$this->testTable} ({$this->testField},{$this->anotherTestField}) " .
+            "VALUES ('Foo','Bar')";
+        $queryGenerated = $this->subject->INSERTquery($this->testTable, $fieldValues);
+        $this->assertSame($queryExpected, $queryGenerated);
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function insertMultipleRowsCreateValidQuery()
+    {
+        $this->subject = $this->getAccessibleMock(DatabaseConnection::class, ['fullQuoteStr'], [], '', false);
+        $this->subject->expects($this->any())
+            ->method('fullQuoteStr')
+            ->will($this->returnCallback(function ($data) {
+                return '\'' . (string)$data . '\'';
+            }));
+        $fields = [$this->testField, $this->anotherTestField];
+        $values = [
+            ['Foo', 100],
+            ['Bar', 200],
+            ['Baz', 300],
+        ];
+        $queryExpected = "INSERT INTO {$this->testTable} ({$this->testField}, {$this->anotherTestField}) " .
+            "VALUES ('Foo', '100'), ('Bar', '200'), ('Baz', '300')";
+        $queryGenerated = $this->subject->INSERTmultipleRows($this->testTable, $fields, $values);
+        $this->assertSame($queryExpected, $queryGenerated);
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function updateQueryCreateValidQuery()
+    {
+        $this->subject = $this->getAccessibleMock(DatabaseConnection::class, ['fullQuoteStr'], [], '', false);
+        $this->subject->expects($this->any())
+            ->method('fullQuoteStr')
+            ->will($this->returnCallback(function ($data) {
+                return '\'' . (string)$data . '\'';
+            }));
+
+        $fieldsValues = [$this->testField => 'aTestValue'];
+        $queryExpected = "UPDATE {$this->testTable} SET {$this->testField}='aTestValue' WHERE id=1";
+        $queryGenerated = $this->subject->UPDATEquery($this->testTable, 'id=1', $fieldsValues);
+        $this->assertSame($queryExpected, $queryGenerated);
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function deleteQueryCreateValidQuery()
+    {
+        $queryExpected = "DELETE FROM {$this->testTable} WHERE id=1";
+        $queryGenerated = $this->subject->DELETEquery($this->testTable, 'id=1');
+        $this->assertSame($queryExpected, $queryGenerated);
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function selectQueryCreateValidQuery()
+    {
+        $queryExpected = "SELECT {$this->testField} FROM {$this->testTable} WHERE id=1";
+        $queryGenerated = $this->subject->SELECTquery($this->testField, $this->testTable, 'id=1');
+        $this->assertSame($queryExpected, $queryGenerated);
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function selectQueryCreateValidQueryWithEmptyWhereClause()
+    {
+        $queryExpected = "SELECT {$this->testField} FROM {$this->testTable}";
+        $queryGenerated = $this->subject->SELECTquery($this->testField, $this->testTable, '');
+        $this->assertSame($queryExpected, $queryGenerated);
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function selectQueryCreateValidQueryWithGroupByClause()
+    {
+        $queryExpected = "SELECT {$this->testField} FROM {$this->testTable} WHERE id=1 GROUP BY id";
+        $queryGenerated = $this->subject->SELECTquery($this->testField, $this->testTable, 'id=1', 'id');
+        $this->assertSame($queryExpected, $queryGenerated);
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function selectQueryCreateValidQueryWithOrderByClause()
+    {
+        $queryExpected = "SELECT {$this->testField} FROM {$this->testTable} WHERE id=1 ORDER BY id";
+        $queryGenerated = $this->subject->SELECTquery($this->testField, $this->testTable, 'id=1', '', 'id');
+        $this->assertSame($queryExpected, $queryGenerated);
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function selectQueryCreateValidQueryWithLimitClause()
+    {
+        $queryGenerated = $this->subject->SELECTquery($this->testField, $this->testTable, 'id=1', '', '', '1,2');
+        $queryExpected = "SELECT {$this->testField} FROM {$this->testTable} WHERE id=1 LIMIT 1,2";
+        $this->assertSame($queryExpected, $queryGenerated);
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function selectSubQueryCreateValidQuery()
+    {
+        $queryExpected = "SELECT {$this->testField} FROM {$this->testTable} WHERE id=1";
+        $queryGenerated = $this->subject->SELECTsubquery($this->testField, $this->testTable, 'id=1');
+        $this->assertSame($queryExpected, $queryGenerated);
+    }
+
+    /**
+     * @test
+     *
+     * @return void
+     */
+    public function truncateQueryCreateValidQuery()
+    {
+        $queryExpected = "TRUNCATE TABLE {$this->testTable}";
+        $queryGenerated = $this->subject->TRUNCATEquery($this->testTable);
+        $this->assertSame($queryExpected, $queryGenerated);
+    }
 }
index 19d544b..432f5d7 100644 (file)
@@ -14,13 +14,16 @@ namespace TYPO3\CMS\Core\Tests\Unit\Database;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Database\DatabaseConnection;
+use TYPO3\CMS\Core\Database\PreparedStatement;
+
 /**
  * Test case
  */
 class PreparedStatementTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
 {
     /**
-     * @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Database\DatabaseConnection
+     * @var \PHPUnit_Framework_MockObject_MockObject|DatabaseConnection
      */
     protected $databaseStub;
 
@@ -46,7 +49,7 @@ class PreparedStatementTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
     private function setUpAndReturnDatabaseStub()
     {
         $GLOBALS['TYPO3_DB'] = $this->getAccessibleMock(
-            \TYPO3\CMS\Core\Database\DatabaseConnection::class,
+            DatabaseConnection::class,
             array('prepare_PREPAREDquery'),
             array(),
             '',
@@ -61,11 +64,11 @@ class PreparedStatementTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
      * Create an object fo the subject to be tested.
      *
      * @param string $query
-     * @return \TYPO3\CMS\Core\Database\PreparedStatement
+     * @return PreparedStatement
      */
     private function createPreparedStatement($query)
     {
-        return new \TYPO3\CMS\Core\Database\PreparedStatement($query, 'pages');
+        return new PreparedStatement($query, 'pages');
     }
 
     ////////////////////////////////////
@@ -78,7 +81,7 @@ class PreparedStatementTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
      */
     public function setUpAndReturnDatabaseStubReturnsMockObjectOfDatabaseConnection()
     {
-        $this->assertTrue($this->setUpAndReturnDatabaseStub() instanceof \TYPO3\CMS\Core\Database\DatabaseConnection);
+        $this->assertTrue($this->setUpAndReturnDatabaseStub() instanceof DatabaseConnection);
     }
 
     /**
@@ -87,7 +90,7 @@ class PreparedStatementTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
      */
     public function createPreparedStatementReturnsInstanceOfPreparedStatementClass()
     {
-        $this->assertTrue($this->createPreparedStatement('dummy') instanceof \TYPO3\CMS\Core\Database\PreparedStatement);
+        $this->assertTrue($this->createPreparedStatement('dummy') instanceof PreparedStatement);
     }
 
     ///////////////////////////////////////
@@ -102,13 +105,33 @@ class PreparedStatementTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
      */
     public function parametersAndQueriesDataProvider()
     {
-        return array(
-            'one named integer parameter' => array('SELECT * FROM pages WHERE pid=:pid', array(':pid' => 1), 'SELECT * FROM pages WHERE pid=?'),
-            'one unnamed integer parameter' => array('SELECT * FROM pages WHERE pid=?', array(1), 'SELECT * FROM pages WHERE pid=?'),
-            '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=? OR uid=?'),
-            '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=? OR uid=?'),
-            'two unnamed integer parameters are replaced' => array('SELECT * FROM pages WHERE pid=? OR uid=?', array(1, 1), 'SELECT * FROM pages WHERE pid=? OR uid=?'),
-        );
+        return [
+            'one named integer parameter' => [
+                'SELECT * FROM pages WHERE pid=:pid',
+                [':pid' => 1],
+                'SELECT * FROM pages WHERE pid=?'
+            ],
+            'one unnamed integer parameter' => [
+                'SELECT * FROM pages WHERE pid=?',
+                [1],
+                'SELECT * FROM pages WHERE pid=?'
+            ],
+            'one named integer parameter is replaced multiple times' => [
+                'SELECT * FROM pages WHERE pid=:pid OR uid=:pid',
+                [':pid' => 1],
+                'SELECT * FROM pages WHERE pid=? OR uid=?'
+            ],
+            'two named integer parameters are replaced' => [
+                'SELECT * FROM pages WHERE pid=:pid OR uid=:uid',
+                [':pid' => 1, ':uid' => 10],
+                'SELECT * FROM pages WHERE pid=? OR uid=?'
+            ],
+            'two unnamed integer parameters are replaced' => [
+                'SELECT * FROM pages WHERE pid=? OR uid=?',
+                [1, 1],
+                'SELECT * FROM pages WHERE pid=? OR uid=?'
+            ],
+        ];
     }
 
     /**
@@ -125,7 +148,9 @@ class PreparedStatementTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
     public function parametersAreReplacedByQuestionMarkInQueryByCallingExecute($query, $parameters, $expectedResult)
     {
         $statement = $this->createPreparedStatement($query);
-        $this->databaseStub->expects($this->any())->method('prepare_PREPAREDquery')->with($this->equalTo($expectedResult));
+        $this->databaseStub->expects($this->any())
+            ->method('prepare_PREPAREDquery')
+            ->with($this->equalTo($expectedResult));
         $statement->execute($parameters);
     }
 
@@ -143,7 +168,9 @@ class PreparedStatementTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
     public function parametersAreReplacedInQueryWhenBoundWithBindValues($query, $parameters, $expectedResult)
     {
         $statement = $this->createPreparedStatement($query);
-        $this->databaseStub->expects($this->any())->method('prepare_PREPAREDquery')->with($this->equalTo($expectedResult));
+        $this->databaseStub->expects($this->any())
+            ->method('prepare_PREPAREDquery')
+            ->with($this->equalTo($expectedResult));
         $statement->bindValues($parameters);
         $statement->execute();
     }
@@ -156,17 +183,44 @@ class PreparedStatementTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
      */
     public function invalidParameterTypesPassedToBindValueThrowsExceptionDataProvider()
     {
-        return array(
-            'integer passed with param type NULL' => array(1, \TYPO3\CMS\Core\Database\PreparedStatement::PARAM_NULL),
-            'string passed with param type NULL' => array('1', \TYPO3\CMS\Core\Database\PreparedStatement::PARAM_NULL),
-            'bool passed with param type NULL' => array(true, \TYPO3\CMS\Core\Database\PreparedStatement::PARAM_NULL),
-            'NULL passed with param type INT' => array(null, \TYPO3\CMS\Core\Database\PreparedStatement::PARAM_INT),
-            'string passed with param type INT' => array('1', \TYPO3\CMS\Core\Database\PreparedStatement::PARAM_INT),
-            'bool passed with param type INT' => array(true, \TYPO3\CMS\Core\Database\PreparedStatement::PARAM_INT),
-            'NULL passed with param type BOOL' => array(null, \TYPO3\CMS\Core\Database\PreparedStatement::PARAM_BOOL),
-            'string passed with param type BOOL' => array('1', \TYPO3\CMS\Core\Database\PreparedStatement::PARAM_BOOL),
-            'integer passed with param type BOOL' => array(1, \TYPO3\CMS\Core\Database\PreparedStatement::PARAM_BOOL)
-        );
+        return [
+            'integer passed with param type NULL' => [
+                1,
+                PreparedStatement::PARAM_NULL
+            ],
+            'string passed with param type NULL' => [
+                '1',
+                PreparedStatement::PARAM_NULL
+            ],
+            'bool passed with param type NULL' => [
+                true,
+                PreparedStatement::PARAM_NULL
+            ],
+            'NULL passed with param type INT' => [
+                null,
+                PreparedStatement::PARAM_INT
+            ],
+            'string passed with param type INT' => [
+                '1',
+                PreparedStatement::PARAM_INT
+            ],
+            'bool passed with param type INT' => [
+                true,
+                PreparedStatement::PARAM_INT
+            ],
+            'NULL passed with param type BOOL' => [
+                null,
+                PreparedStatement::PARAM_BOOL
+            ],
+            'string passed with param type BOOL' => [
+                '1',
+                PreparedStatement::PARAM_BOOL
+            ],
+            'integer passed with param type BOOL' => [
+                1,
+                PreparedStatement::PARAM_BOOL
+            ]
+        ];
     }
 
     /**
@@ -194,13 +248,33 @@ class PreparedStatementTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
      */
     public function passingInvalidMarkersThrowsExceptionDataProvider()
     {
-        return array(
-            'using other prefix than colon' => array('SELECT * FROM pages WHERE pid=#pid', array('#pid' => 1)),
-            'using non alphanumerical character' => array('SELECT * FROM pages WHERE title=:stra≠e', array(':stra≠e' => 1)),
-            'no colon used' => array('SELECT * FROM pages WHERE pid=pid', array('pid' => 1)),
-            'colon at the end' => array('SELECT * FROM pages WHERE pid=pid:', array('pid:' => 1)),
-            'colon without alphanumerical character' => array('SELECT * FROM pages WHERE pid=:', array(':' => 1))
-        );
+        return [
+            'using other prefix than colon' => [
+                /** @lang text */
+                'SELECT * FROM pages WHERE pid=#pid',
+                ['#pid' => 1]
+            ],
+            'using non alphanumerical character' => [
+                /** @lang text */
+                'SELECT * FROM pages WHERE title=:stra≠e',
+                [':stra≠e' => 1]
+            ],
+            'no colon used' => [
+                /** @lang text */
+                'SELECT * FROM pages WHERE pid=pid',
+                ['pid' => 1]
+            ],
+            'colon at the end' => [
+                /** @lang text */
+                'SELECT * FROM pages WHERE pid=pid:',
+                ['pid:' => 1]
+            ],
+            'colon without alphanumerical character' => [
+                /** @lang text */
+                'SELECT * FROM pages WHERE pid=:',
+                [':' => 1]
+            ]
+        ];
     }
 
     /**