7 class BlockTest
extends MediaWikiLangTestCase
{
13 /* variable used to save up the blockID we insert in this test suite */
16 function addDBData() {
18 $user = User
::newFromName( 'UTBlockee' );
19 if ( $user->getID() == 0 ) {
20 $user->addToDatabase();
21 TestUser
::setPasswordForUser( $user, 'UTBlockeePassword' );
23 $user->saveSettings();
26 // Delete the last round's block if it's still there
27 $oldBlock = Block
::newFromTarget( 'UTBlockee' );
29 // An old block will prevent our new one from saving.
34 'address' => 'UTBlockee',
35 'user' => $user->getID(),
36 'reason' => 'Parce que',
37 'expiry' => time() +
100500,
39 $this->block
= new Block( $blockOptions );
40 $this->madeAt
= wfTimestamp( TS_MW
);
42 $this->block
->insert();
43 // save up ID for use in assertion. Since ID is an autoincrement,
44 // its value might change depending on the order the tests are run.
45 // ApiBlockTest insert its own blocks!
46 $newBlockId = $this->block
->getId();
48 $this->blockId
= $newBlockId;
50 throw new MWException( "Failed to insert block for BlockTest; old leftover block remaining?" );
53 $this->addXffBlocks();
57 * debug function : dump the ipblocks table
59 function dumpBlocks() {
60 $v = $this->db
->select( 'ipblocks', '*' );
61 print "Got " . $v->numRows() . " rows. Full dump follow:\n";
62 foreach ( $v as $row ) {
68 * @covers Block::newFromTarget
70 public function testINewFromTargetReturnsCorrectBlock() {
72 $this->block
->equals( Block
::newFromTarget( 'UTBlockee' ) ),
73 "newFromTarget() returns the same block as the one that was made"
78 * @covers Block::newFromID
80 public function testINewFromIDReturnsCorrectBlock() {
82 $this->block
->equals( Block
::newFromID( $this->blockId
) ),
83 "newFromID() returns the same block as the one that was made"
90 public function testBug26425BlockTimestampDefaultsToTime() {
91 // delta to stop one-off errors when things happen to go over a second mark.
92 $delta = abs( $this->madeAt
- $this->block
->mTimestamp
);
93 $this->assertLessThan(
96 "If no timestamp is specified, the block is recorded as time()"
101 * CheckUser since being changed to use Block::newFromTarget started failing
102 * because the new function didn't accept empty strings like Block::load()
103 * had. Regression bug 29116.
105 * @dataProvider provideBug29116Data
106 * @covers Block::newFromTarget
108 public function testBug29116NewFromTargetWithEmptyIp( $vagueTarget ) {
109 $block = Block
::newFromTarget( 'UTBlockee', $vagueTarget );
111 $this->block
->equals( $block ),
112 "newFromTarget() returns the same block as the one that was made when "
113 . "given empty vagueTarget param " . var_export( $vagueTarget, true )
117 public static function provideBug29116Data() {
126 * @covers Block::prevents
128 public function testBlockedUserCanNotCreateAccount() {
129 $username = 'BlockedUserToCreateAccountWith';
130 $u = User
::newFromName( $username );
132 $userId = $u->getId();
133 $this->assertNotEquals( 0, $userId, 'sanity' );
134 TestUser
::setPasswordForUser( $u, 'NotRandomPass' );
139 Block
::newFromTarget( $username ),
140 "$username should not be blocked"
144 $u = User
::newFromName( $username );
146 $u->isBlockedFromCreateAccount(),
147 "Our sandbox user should be able to create account before being blocked"
150 // Foreign perspective (blockee not on current wiki)...
152 'address' => $username,
154 'reason' => 'crosswiki block...',
155 'timestamp' => wfTimestampNow(),
156 'expiry' => $this->db
->getInfinity(),
157 'createAccount' => true,
158 'enableAutoblock' => true,
160 'blockEmail' => true,
161 'byText' => 'MetaWikiUser',
163 $block = new Block( $blockOptions );
166 // Reload block from DB
167 $userBlock = Block
::newFromTarget( $username );
169 (bool)$block->prevents( 'createaccount' ),
170 "Block object in DB should prevents 'createaccount'"
173 $this->assertInstanceOf(
176 "'$username' block block object should be existent"
180 $u = User
::newFromName( $username );
182 (bool)$u->isBlockedFromCreateAccount(),
183 "Our sandbox user '$username' should NOT be able to create account"
188 * @covers Block::insert
190 public function testCrappyCrossWikiBlocks() {
191 // Delete the last round's block if it's still there
192 $oldBlock = Block
::newFromTarget( 'UserOnForeignWiki' );
194 // An old block will prevent our new one from saving.
198 // Local perspective (blockee on current wiki)...
199 $user = User
::newFromName( 'UserOnForeignWiki' );
200 $user->addToDatabase();
201 $userId = $user->getId();
202 $this->assertNotEquals( 0, $userId, 'sanity' );
204 // Foreign perspective (blockee not on current wiki)...
206 'address' => 'UserOnForeignWiki',
207 'user' => $user->getId(),
208 'reason' => 'crosswiki block...',
209 'timestamp' => wfTimestampNow(),
210 'expiry' => $this->db
->getInfinity(),
211 'createAccount' => true,
212 'enableAutoblock' => true,
214 'blockEmail' => true,
215 'byText' => 'MetaWikiUser',
217 $block = new Block( $blockOptions );
219 $res = $block->insert( $this->db
);
220 $this->assertTrue( (bool)$res['id'], 'Block succeeded' );
222 $user = null; // clear
224 $block = Block
::newFromID( $res['id'] );
227 $block->getTarget()->getName(),
228 'Correct blockee name'
230 $this->assertEquals( $userId, $block->getTarget()->getId(), 'Correct blockee id' );
231 $this->assertEquals( 'MetaWikiUser', $block->getBlocker(), 'Correct blocker name' );
232 $this->assertEquals( 'MetaWikiUser', $block->getByName(), 'Correct blocker name' );
233 $this->assertEquals( 0, $block->getBy(), 'Correct blocker id' );
236 protected function addXffBlocks() {
237 static $inited = false;
246 [ 'target' => '70.2.0.0/16',
247 'type' => Block
::TYPE_RANGE
,
248 'desc' => 'Range Hardblock',
249 'ACDisable' => false,
250 'isHardblock' => true,
251 'isAutoBlocking' => false,
253 [ 'target' => '2001:4860:4001::/48',
254 'type' => Block
::TYPE_RANGE
,
255 'desc' => 'Range6 Hardblock',
256 'ACDisable' => false,
257 'isHardblock' => true,
258 'isAutoBlocking' => false,
260 [ 'target' => '60.2.0.0/16',
261 'type' => Block
::TYPE_RANGE
,
262 'desc' => 'Range Softblock with AC Disabled',
264 'isHardblock' => false,
265 'isAutoBlocking' => false,
267 [ 'target' => '50.2.0.0/16',
268 'type' => Block
::TYPE_RANGE
,
269 'desc' => 'Range Softblock',
270 'ACDisable' => false,
271 'isHardblock' => false,
272 'isAutoBlocking' => false,
274 [ 'target' => '50.1.1.1',
275 'type' => Block
::TYPE_IP
,
276 'desc' => 'Exact Softblock',
277 'ACDisable' => false,
278 'isHardblock' => false,
279 'isAutoBlocking' => false,
283 foreach ( $blockList as $insBlock ) {
284 $target = $insBlock['target'];
286 if ( $insBlock['type'] === Block
::TYPE_IP
) {
287 $target = User
::newFromName( IP
::sanitizeIP( $target ), false )->getName();
288 } elseif ( $insBlock['type'] === Block
::TYPE_RANGE
) {
289 $target = IP
::sanitizeRange( $target );
292 $block = new Block();
293 $block->setTarget( $target );
294 $block->setBlocker( 'testblocker@global' );
295 $block->mReason
= $insBlock['desc'];
296 $block->mExpiry
= 'infinity';
297 $block->prevents( 'createaccount', $insBlock['ACDisable'] );
298 $block->isHardblock( $insBlock['isHardblock'] );
299 $block->isAutoblocking( $insBlock['isAutoBlocking'] );
304 public static function providerXff() {
306 [ 'xff' => '1.2.3.4, 70.2.1.1, 60.2.1.1, 2.3.4.5',
308 'result' => 'Range Hardblock'
310 [ 'xff' => '1.2.3.4, 50.2.1.1, 60.2.1.1, 2.3.4.5',
312 'result' => 'Range Softblock with AC Disabled'
314 [ 'xff' => '1.2.3.4, 70.2.1.1, 50.1.1.1, 2.3.4.5',
316 'result' => 'Exact Softblock'
318 [ 'xff' => '1.2.3.4, 70.2.1.1, 50.2.1.1, 50.1.1.1, 2.3.4.5',
320 'result' => 'Exact Softblock'
322 [ 'xff' => '1.2.3.4, 70.2.1.1, 50.2.1.1, 2.3.4.5',
324 'result' => 'Range Hardblock'
326 [ 'xff' => '1.2.3.4, 70.2.1.1, 60.2.1.1, 2.3.4.5',
328 'result' => 'Range Hardblock'
330 [ 'xff' => '50.2.1.1, 60.2.1.1, 2.3.4.5',
332 'result' => 'Range Softblock with AC Disabled'
334 [ 'xff' => '1.2.3.4, 50.1.1.1, 60.2.1.1, 2.3.4.5',
336 'result' => 'Exact Softblock'
338 [ 'xff' => '1.2.3.4, <$A_BUNCH-OF{INVALID}TEXT\>, 60.2.1.1, 2.3.4.5',
340 'result' => 'Range Softblock with AC Disabled'
342 [ 'xff' => '1.2.3.4, 50.2.1.1, 2001:4860:4001:802::1003, 2.3.4.5',
344 'result' => 'Range6 Hardblock'
350 * @dataProvider providerXff
351 * @covers Block::getBlocksForIPList
352 * @covers Block::chooseBlock
354 public function testBlocksOnXff( $xff, $exCount, $exResult ) {
355 $list = array_map( 'trim', explode( ',', $xff ) );
356 $xffblocks = Block
::getBlocksForIPList( $list, true );
357 $this->assertEquals( $exCount, count( $xffblocks ), 'Number of blocks for ' . $xff );
358 $block = Block
::chooseBlock( $xffblocks, $list );
359 $this->assertEquals( $exResult, $block->mReason
, 'Correct block type for XFF header ' . $xff );
362 public function testDeprecatedConstructor() {
363 $this->hideDeprecated( 'Block::__construct with multiple arguments' );
364 $username = 'UnthinkablySecretRandomUsername';
365 $reason = 'being irrational';
368 $u = User
::newFromName( $username );
369 if ( $u->getID() == 0 ) {
371 TestUser
::setPasswordForUser( $u, 'TotallyObvious' );
375 # Make sure the user isn't blocked
377 Block
::newFromTarget( $username ),
378 "$username should not be blocked"
383 /* address */ $username,
386 /* reason */ $reason,
395 $block->getTarget()->getName(),
397 "Target should be set properly"
400 # Check supplied parameter
404 "Reason should be non-default"
407 # Check default parameter
409 (bool)$block->prevents( 'createaccount' ),
410 "Account creation should not be blocked by default"