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