Merge "maintenance: Script to rename titles for Unicode uppercasing changes"
[lhc/web/wiklou.git] / tests / phpunit / includes / block / BlockManagerTest.php
1 <?php
2
3 use MediaWiki\Block\BlockManager;
4 use MediaWiki\Block\DatabaseBlock;
5 use MediaWiki\Block\SystemBlock;
6
7 /**
8 * @group Blocking
9 * @group Database
10 * @coversDefaultClass \MediaWiki\Block\BlockManager
11 */
12 class BlockManagerTest extends MediaWikiTestCase {
13
14 /** @var User */
15 protected $user;
16
17 /** @var int */
18 protected $sysopId;
19
20 protected function setUp() {
21 parent::setUp();
22
23 $this->user = $this->getTestUser()->getUser();
24 $this->sysopId = $this->getTestSysop()->getUser()->getId();
25 $this->blockManagerConfig = [
26 'wgApplyIpBlocksToXff' => true,
27 'wgCookieSetOnAutoblock' => true,
28 'wgCookieSetOnIpBlock' => true,
29 'wgDnsBlacklistUrls' => [],
30 'wgEnableDnsBlacklist' => true,
31 'wgProxyList' => [],
32 'wgProxyWhitelist' => [],
33 'wgSecretKey' => false,
34 'wgSoftBlockRanges' => [],
35 ];
36 }
37
38 private function getBlockManager( $overrideConfig ) {
39 $blockManagerConfig = array_merge( $this->blockManagerConfig, $overrideConfig );
40 return new BlockManager(
41 $this->user,
42 $this->user->getRequest(),
43 ...array_values( $blockManagerConfig )
44 );
45 }
46
47 /**
48 * @dataProvider provideGetBlockFromCookieValue
49 * @covers ::getBlockFromCookieValue
50 */
51 public function testGetBlockFromCookieValue( $options, $expected ) {
52 $blockManager = $this->getBlockManager( [
53 'wgCookieSetOnAutoblock' => true,
54 'wgCookieSetOnIpBlock' => true,
55 ] );
56
57 $block = new DatabaseBlock( array_merge( [
58 'address' => $options[ 'target' ] ?: $this->user,
59 'by' => $this->sysopId,
60 ], $options[ 'blockOptions' ] ) );
61 $block->insert();
62
63 $class = new ReflectionClass( BlockManager::class );
64 $method = $class->getMethod( 'getBlockFromCookieValue' );
65 $method->setAccessible( true );
66
67 $user = $options[ 'loggedIn' ] ? $this->user : new User();
68 $user->getRequest()->setCookie( 'BlockID', $block->getCookieValue() );
69
70 $this->assertSame( $expected, (bool)$method->invoke(
71 $blockManager,
72 $user,
73 $user->getRequest()
74 ) );
75
76 $block->delete();
77 }
78
79 public static function provideGetBlockFromCookieValue() {
80 return [
81 'Autoblocking user block' => [
82 [
83 'target' => '',
84 'loggedIn' => true,
85 'blockOptions' => [
86 'enableAutoblock' => true
87 ],
88 ],
89 true,
90 ],
91 'Non-autoblocking user block' => [
92 [
93 'target' => '',
94 'loggedIn' => true,
95 'blockOptions' => [],
96 ],
97 false,
98 ],
99 'IP block for anonymous user' => [
100 [
101 'target' => '127.0.0.1',
102 'loggedIn' => false,
103 'blockOptions' => [],
104 ],
105 true,
106 ],
107 'IP block for logged in user' => [
108 [
109 'target' => '127.0.0.1',
110 'loggedIn' => true,
111 'blockOptions' => [],
112 ],
113 false,
114 ],
115 'IP range block for anonymous user' => [
116 [
117 'target' => '127.0.0.0/8',
118 'loggedIn' => false,
119 'blockOptions' => [],
120 ],
121 true,
122 ],
123 ];
124 }
125
126 /**
127 * @dataProvider provideIsLocallyBlockedProxy
128 * @covers ::isLocallyBlockedProxy
129 */
130 public function testIsLocallyBlockedProxy( $proxyList, $expected ) {
131 $class = new ReflectionClass( BlockManager::class );
132 $method = $class->getMethod( 'isLocallyBlockedProxy' );
133 $method->setAccessible( true );
134
135 $blockManager = $this->getBlockManager( [
136 'wgProxyList' => $proxyList
137 ] );
138
139 $ip = '1.2.3.4';
140 $this->assertSame( $expected, $method->invoke( $blockManager, $ip ) );
141 }
142
143 public static function provideIsLocallyBlockedProxy() {
144 return [
145 'Proxy list is empty' => [ [], false ],
146 'Proxy list contains IP' => [ [ '1.2.3.4' ], true ],
147 'Proxy list contains IP as value' => [ [ 'test' => '1.2.3.4' ], true ],
148 'Proxy list contains range that covers IP' => [ [ '1.2.3.0/16' ], true ],
149 ];
150 }
151
152 /**
153 * @covers ::isLocallyBlockedProxy
154 */
155 public function testIsLocallyBlockedProxyDeprecated() {
156 $proxy = '1.2.3.4';
157
158 $this->hideDeprecated(
159 'IP addresses in the keys of $wgProxyList (found the following IP ' .
160 'addresses in keys: ' . $proxy . ', please move them to values)'
161 );
162
163 $class = new ReflectionClass( BlockManager::class );
164 $method = $class->getMethod( 'isLocallyBlockedProxy' );
165 $method->setAccessible( true );
166
167 $blockManager = $this->getBlockManager( [
168 'wgProxyList' => [ $proxy => 'test' ]
169 ] );
170
171 $ip = '1.2.3.4';
172 $this->assertSame( true, $method->invoke( $blockManager, $ip ) );
173 }
174
175 /**
176 * @dataProvider provideIsDnsBlacklisted
177 * @covers ::isDnsBlacklisted
178 * @covers ::inDnsBlacklist
179 */
180 public function testIsDnsBlacklisted( $options, $expected ) {
181 $blockManagerConfig = array_merge( $this->blockManagerConfig, [
182 'wgEnableDnsBlacklist' => true,
183 'wgDnsBlacklistUrls' => $options['blacklist'],
184 'wgProxyWhitelist' => $options['whitelist'],
185 ] );
186
187 $blockManager = $this->getMockBuilder( BlockManager::class )
188 ->setConstructorArgs(
189 array_merge( [
190 $this->user,
191 $this->user->getRequest(),
192 ], $blockManagerConfig ) )
193 ->setMethods( [ 'checkHost' ] )
194 ->getMock();
195
196 $blockManager->expects( $this->any() )
197 ->method( 'checkHost' )
198 ->will( $this->returnValueMap( [ [
199 $options['dnsblQuery'],
200 $options['dnsblResponse'],
201 ] ] ) );
202
203 $this->assertSame(
204 $expected,
205 $blockManager->isDnsBlacklisted( $options['ip'], $options['checkWhitelist'] )
206 );
207 }
208
209 public static function provideIsDnsBlacklisted() {
210 $dnsblFound = [ '127.0.0.2' ];
211 $dnsblNotFound = false;
212 return [
213 'IP is blacklisted' => [
214 [
215 'blacklist' => [ 'dnsbl.test' ],
216 'ip' => '127.0.0.1',
217 'dnsblQuery' => '1.0.0.127.dnsbl.test',
218 'dnsblResponse' => $dnsblFound,
219 'whitelist' => [],
220 'checkWhitelist' => false,
221 ],
222 true,
223 ],
224 'IP is blacklisted; blacklist has key' => [
225 [
226 'blacklist' => [ [ 'dnsbl.test', 'key' ] ],
227 'ip' => '127.0.0.1',
228 'dnsblQuery' => 'key.1.0.0.127.dnsbl.test',
229 'dnsblResponse' => $dnsblFound,
230 'whitelist' => [],
231 'checkWhitelist' => false,
232 ],
233 true,
234 ],
235 'IP is blacklisted; blacklist is array' => [
236 [
237 'blacklist' => [ [ 'dnsbl.test' ] ],
238 'ip' => '127.0.0.1',
239 'dnsblQuery' => '1.0.0.127.dnsbl.test',
240 'dnsblResponse' => $dnsblFound,
241 'whitelist' => [],
242 'checkWhitelist' => false,
243 ],
244 true,
245 ],
246 'IP is not blacklisted' => [
247 [
248 'blacklist' => [ 'dnsbl.test' ],
249 'ip' => '1.2.3.4',
250 'dnsblQuery' => '4.3.2.1.dnsbl.test',
251 'dnsblResponse' => $dnsblNotFound,
252 'whitelist' => [],
253 'checkWhitelist' => false,
254 ],
255 false,
256 ],
257 'Blacklist is empty' => [
258 [
259 'blacklist' => [],
260 'ip' => '127.0.0.1',
261 'dnsblQuery' => '1.0.0.127.dnsbl.test',
262 'dnsblResponse' => $dnsblFound,
263 'whitelist' => [],
264 'checkWhitelist' => false,
265 ],
266 false,
267 ],
268 'IP is blacklisted and whitelisted; whitelist is not checked' => [
269 [
270 'blacklist' => [ 'dnsbl.test' ],
271 'ip' => '127.0.0.1',
272 'dnsblQuery' => '1.0.0.127.dnsbl.test',
273 'dnsblResponse' => $dnsblFound,
274 'whitelist' => [ '127.0.0.1' ],
275 'checkWhitelist' => false,
276 ],
277 true,
278 ],
279 'IP is blacklisted and whitelisted; whitelist is checked' => [
280 [
281 'blacklist' => [ 'dnsbl.test' ],
282 'ip' => '127.0.0.1',
283 'dnsblQuery' => '1.0.0.127.dnsbl.test',
284 'dnsblResponse' => $dnsblFound,
285 'whitelist' => [ '127.0.0.1' ],
286 'checkWhitelist' => true,
287 ],
288 false,
289 ],
290 ];
291 }
292
293 /**
294 * @covers ::getUniqueBlocks
295 */
296 public function testGetUniqueBlocks() {
297 $blockId = 100;
298
299 $class = new ReflectionClass( BlockManager::class );
300 $method = $class->getMethod( 'getUniqueBlocks' );
301 $method->setAccessible( true );
302
303 $blockManager = $this->getBlockManager( [] );
304
305 $block = $this->getMockBuilder( DatabaseBlock::class )
306 ->setMethods( [ 'getId' ] )
307 ->getMock();
308 $block->expects( $this->any() )
309 ->method( 'getId' )
310 ->willReturn( $blockId );
311
312 $autoblock = $this->getMockBuilder( DatabaseBlock::class )
313 ->setMethods( [ 'getParentBlockId', 'getType' ] )
314 ->getMock();
315 $autoblock->expects( $this->any() )
316 ->method( 'getParentBlockId' )
317 ->willReturn( $blockId );
318 $autoblock->expects( $this->any() )
319 ->method( 'getType' )
320 ->willReturn( DatabaseBlock::TYPE_AUTO );
321
322 $blocks = [ $block, $block, $autoblock, new SystemBlock() ];
323
324 $this->assertSame( 2, count( $method->invoke( $blockManager, $blocks ) ) );
325 }
326
327 /**
328 * @covers ::trackBlockWithCookie
329 * @dataProvider provideTrackBlockWithCookie
330 * @param bool $expectCookieSet
331 * @param bool $hasCookie
332 * @param bool $isBlocked
333 */
334 public function testTrackBlockWithCookie( $expectCookieSet, $hasCookie, $isBlocked ) {
335 $blockID = 123;
336 $this->setMwGlobals( 'wgCookiePrefix', '' );
337
338 $request = new FauxRequest();
339 if ( $hasCookie ) {
340 $request->setCookie( 'BlockID', 'the value does not matter' );
341 }
342
343 if ( $isBlocked ) {
344 $block = $this->getMockBuilder( DatabaseBlock::class )
345 ->setMethods( [ 'getType', 'getId' ] )
346 ->getMock();
347 $block->method( 'getType' )
348 ->willReturn( DatabaseBlock::TYPE_IP );
349 $block->method( 'getId' )
350 ->willReturn( $blockID );
351 } else {
352 $block = null;
353 }
354
355 $user = $this->getMockBuilder( User::class )
356 ->setMethods( [ 'getBlock', 'getRequest' ] )
357 ->getMock();
358 $user->method( 'getBlock' )
359 ->willReturn( $block );
360 $user->method( 'getRequest' )
361 ->willReturn( $request );
362 /** @var User $user */
363
364 // Although the block cookie is set via DeferredUpdates, in command line mode updates are
365 // processed immediately
366 $blockManager = $this->getBlockManager( [] );
367 $blockManager->trackBlockWithCookie( $user );
368
369 /** @var FauxResponse $response */
370 $response = $request->response();
371 $this->assertCount( $expectCookieSet ? 1 : 0, $response->getCookies() );
372 $this->assertEquals( $expectCookieSet ? $blockID : null, $response->getCookie( 'BlockID' ) );
373 }
374
375 public function provideTrackBlockWithCookie() {
376 return [
377 // $expectCookieSet, $hasCookie, $isBlocked
378 [ false, false, false ],
379 [ false, true, false ],
380 [ true, false, true ],
381 [ false, true, true ],
382 ];
383 }
384 }