55e48d13c616332d4319481e443fd9dda45bb637
[lhc/web/wiklou.git] / tests / phpunit / includes / db / DatabaseMysqlBaseTest.php
1 <?php
2 /**
3 * Holds tests for DatabaseMysqlBase MediaWiki class.
4 *
5 * @section LICENSE
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 * http://www.gnu.org/copyleft/gpl.html
20 *
21 * @file
22 * @author Antoine Musso
23 * @author Bryan Davis
24 * @copyright © 2013 Antoine Musso
25 * @copyright © 2013 Bryan Davis
26 * @copyright © 2013 Wikimedia Foundation Inc.
27 */
28
29 /**
30 * Fake class around abstract class so we can call concrete methods.
31 */
32 class FakeDatabaseMysqlBase extends DatabaseMysqlBase {
33 // From DatabaseBase
34 function __construct() {
35 }
36
37 protected function closeConnection() {
38 }
39
40 protected function doQuery( $sql ) {
41 }
42
43 // From DatabaseMysql
44 protected function mysqlConnect( $realServer ) {
45 }
46
47 protected function mysqlSetCharset( $charset ) {
48 }
49
50 protected function mysqlFreeResult( $res ) {
51 }
52
53 protected function mysqlFetchObject( $res ) {
54 }
55
56 protected function mysqlFetchArray( $res ) {
57 }
58
59 protected function mysqlNumRows( $res ) {
60 }
61
62 protected function mysqlNumFields( $res ) {
63 }
64
65 protected function mysqlFieldName( $res, $n ) {
66 }
67
68 protected function mysqlFieldType( $res, $n ) {
69 }
70
71 protected function mysqlDataSeek( $res, $row ) {
72 }
73
74 protected function mysqlError( $conn = null ) {
75 }
76
77 protected function mysqlFetchField( $res, $n ) {
78 }
79
80 protected function mysqlPing() {
81 }
82
83 // From interface DatabaseType
84 function insertId() {
85 }
86
87 function lastErrno() {
88 }
89
90 function affectedRows() {
91 }
92
93 function getServerVersion() {
94 }
95 }
96
97 class DatabaseMysqlBaseTest extends MediaWikiTestCase {
98 /**
99 * @dataProvider provideDiapers
100 * @covers DatabaseMysqlBase::addIdentifierQuotes
101 */
102 public function testAddIdentifierQuotes( $expected, $in ) {
103 $db = new FakeDatabaseMysqlBase();
104 $quoted = $db->addIdentifierQuotes( $in );
105 $this->assertEquals( $expected, $quoted );
106 }
107
108 /**
109 * Feeds testAddIdentifierQuotes
110 *
111 * Named per bug 20281 convention.
112 */
113 function provideDiapers() {
114 return array(
115 // Format: expected, input
116 array( '``', '' ),
117
118 // Yeah I really hate loosely typed PHP idiocies nowadays
119 array( '``', null ),
120
121 // Dear codereviewer, guess what addIdentifierQuotes()
122 // will return with thoses:
123 array( '``', false ),
124 array( '`1`', true ),
125
126 // We never know what could happen
127 array( '`0`', 0 ),
128 array( '`1`', 1 ),
129
130 // Whatchout! Should probably use something more meaningful
131 array( "`'`", "'" ), # single quote
132 array( '`"`', '"' ), # double quote
133 array( '````', '`' ), # backtick
134 array( '`’`', '’' ), # apostrophe (look at your encyclopedia)
135
136 // sneaky NUL bytes are lurking everywhere
137 array( '``', "\0" ),
138 array( '`xyzzy`', "\0x\0y\0z\0z\0y\0" ),
139
140 // unicode chars
141 array(
142 self::createUnicodeString( '`\u0001a\uFFFFb`' ),
143 self::createUnicodeString( '\u0001a\uFFFFb' )
144 ),
145 array(
146 self::createUnicodeString( '`\u0001\uFFFF`' ),
147 self::createUnicodeString( '\u0001\u0000\uFFFF\u0000' )
148 ),
149 array( '`☃`', '☃' ),
150 array( '`メインページ`', 'メインページ' ),
151 array( '`Басты_бет`', 'Басты_бет' ),
152
153 // Real world:
154 array( '`Alix`', 'Alix' ), # while( ! $recovered ) { sleep(); }
155 array( '`Backtick: ```', 'Backtick: `' ),
156 array( '`This is a test`', 'This is a test' ),
157 );
158 }
159
160 private static function createUnicodeString( $str ) {
161 return json_decode( '"' . $str . '"' );
162 }
163
164 function getMockForViews() {
165 $db = $this->getMockBuilder( 'DatabaseMysql' )
166 ->disableOriginalConstructor()
167 ->setMethods( array( 'fetchRow', 'query' ) )
168 ->getMock();
169
170 $db->expects( $this->any() )
171 ->method( 'query' )
172 ->with( $this->anything() )
173 ->will(
174 $this->returnValue( null )
175 );
176
177 $db->expects( $this->any() )
178 ->method( 'fetchRow' )
179 ->with( $this->anything() )
180 ->will( $this->onConsecutiveCalls(
181 array( 'Tables_in_' => 'view1' ),
182 array( 'Tables_in_' => 'view2' ),
183 array( 'Tables_in_' => 'myview' ),
184 false # no more rows
185 ));
186 return $db;
187 }
188 /**
189 * @covers DatabaseMysqlBase::listViews
190 */
191 function testListviews() {
192 $db = $this->getMockForViews();
193
194 // The first call populate an internal cache of views
195 $this->assertEquals( array( 'view1', 'view2', 'myview' ),
196 $db->listViews() );
197 $this->assertEquals( array( 'view1', 'view2', 'myview' ),
198 $db->listViews() );
199
200 // Prefix filtering
201 $this->assertEquals( array( 'view1', 'view2' ),
202 $db->listViews( 'view' ) );
203 $this->assertEquals( array( 'myview' ),
204 $db->listViews( 'my' ) );
205 $this->assertEquals( array(),
206 $db->listViews( 'UNUSED_PREFIX' ) );
207 $this->assertEquals( array( 'view1', 'view2', 'myview' ),
208 $db->listViews( '' ) );
209 }
210
211 /**
212 * @covers DatabaseMysqlBase::isView
213 * @dataProvider provideViewExistanceChecks
214 */
215 function testIsView( $isView, $viewName ) {
216 $db = $this->getMockForViews();
217
218 switch ( $isView ) {
219 case true:
220 $this->assertTrue( $db->isView( $viewName ),
221 "$viewName should be considered a view" );
222 break;
223
224 case false:
225 $this->assertFalse( $db->isView( $viewName ),
226 "$viewName has not been defined as a view" );
227 break;
228 }
229
230 }
231
232 function provideViewExistanceChecks() {
233 return array(
234 // format: whether it is a view, view name
235 array( true, 'view1' ),
236 array( true, 'view2' ),
237 array( true, 'myview' ),
238
239 array( false, 'user' ),
240
241 array( false, 'view10' ),
242 array( false, 'my' ),
243 array( false, 'OH_MY_GOD' ), # they killed kenny!
244 );
245 }
246
247 }