X-Git-Url: http://git.heureux-cyclage.org/?a=blobdiff_plain;f=tests%2Fphpunit%2Fincludes%2Fuser%2FUserTest.php;h=ea7f715b5f3221da047030d7043fb142c3432efa;hb=61a7a5463de9c4d1073f3c0fd17b35b797923c2d;hp=2721c18e9f96c689fdef4fd8f2c2280e7b1a53e6;hpb=0773e0b86b7ff7fe45f09d806d7b946a41638c3b;p=lhc%2Fweb%2Fwiklou.git diff --git a/tests/phpunit/includes/user/UserTest.php b/tests/phpunit/includes/user/UserTest.php index 2721c18e9f..ebfecbca11 100644 --- a/tests/phpunit/includes/user/UserTest.php +++ b/tests/phpunit/includes/user/UserTest.php @@ -21,7 +21,9 @@ class UserTest extends MediaWikiTestCase { $this->setMwGlobals( [ 'wgGroupPermissions' => [], 'wgRevokePermissions' => [], + 'wgActorTableSchemaMigrationStage' => MIGRATION_WRITE_BOTH, ] ); + $this->overrideMwServices(); $this->setUpPermissionGlobals(); @@ -121,7 +123,7 @@ class UserTest extends MediaWikiTestCase { $this->assertContains( 'nukeworld', $rights ); // Add a Session that limits rights - $mock = $this->getMockBuilder( stdclass::class ) + $mock = $this->getMockBuilder( stdClass::class ) ->setMethods( [ 'getAllowedUserRights', 'deregisterSession', 'getSessionId' ] ) ->getMock(); $mock->method( 'getAllowedUserRights' )->willReturn( [ 'test', 'writetest' ] ); @@ -236,6 +238,8 @@ class UserTest extends MediaWikiTestCase { * Test, if for all rights a right- message exist, * which is used on Special:ListGroupRights as help text * Extensions and core + * + * @coversNothing */ public function testAllRightsWithMessage() { // Getting all user rights, for core: User::$mCoreRights, for extensions: $wgAvailableRights @@ -346,6 +350,7 @@ class UserTest extends MediaWikiTestCase { $user->setOption( 'userjs-someoption', 'test' ); $user->setOption( 'rclimit', 200 ); + $user->setOption( 'wpwatchlistdays', '0' ); $user->saveSettings(); $user = User::newFromName( $user->getName() ); @@ -357,6 +362,11 @@ class UserTest extends MediaWikiTestCase { MediaWikiServices::getInstance()->getMainWANObjectCache()->clearProcessCache(); $this->assertEquals( 'test', $user->getOption( 'userjs-someoption' ) ); $this->assertEquals( 200, $user->getOption( 'rclimit' ) ); + + // Check that an option saved as a string '0' is returned as an integer. + $user = User::newFromName( $user->getName() ); + $user->load( User::READ_LATEST ); + $this->assertSame( 0, $user->getOption( 'wpwatchlistdays' ) ); } /** @@ -615,6 +625,7 @@ class UserTest extends MediaWikiTestCase { 'enableAutoblock' => true, 'expiry' => wfTimestamp( TS_MW, $expiryFiveHours ), ] ); + $block->setBlocker( $this->getTestSysop()->getUser() ); $block->setTarget( $user1tmp ); $block->setBlocker( $userBlocker ); $res = $block->insert(); @@ -692,6 +703,7 @@ class UserTest extends MediaWikiTestCase { $request1 = new FauxRequest(); $request1->getSession()->setUser( $testUser ); $block = new Block( [ 'enableAutoblock' => true ] ); + $block->setBlocker( $this->getTestSysop()->getUser() ); $block->setTarget( $testUser ); $block->setBlocker( $userBlocker ); $res = $block->insert(); @@ -737,6 +749,7 @@ class UserTest extends MediaWikiTestCase { $request1 = new FauxRequest(); $request1->getSession()->setUser( $user1Tmp ); $block = new Block( [ 'enableAutoblock' => true, 'expiry' => 'infinity' ] ); + $block->setBlocker( $this->getTestSysop()->getUser() ); $block->setTarget( $user1Tmp ); $block->setBlocker( $userBlocker ); $res = $block->insert(); @@ -782,30 +795,36 @@ class UserTest extends MediaWikiTestCase { } public function testSoftBlockRanges() { - global $wgUser; - - $this->setMwGlobals( [ - 'wgSoftBlockRanges' => [ '10.0.0.0/8' ], - 'wgUser' => null, - ] ); + $setSessionUser = function ( User $user, WebRequest $request ) { + $this->setMwGlobals( 'wgUser', $user ); + RequestContext::getMain()->setUser( $user ); + RequestContext::getMain()->setRequest( $request ); + TestingAccessWrapper::newFromObject( $user )->mRequest = $request; + $request->getSession()->setUser( $user ); + }; + $this->setMwGlobals( 'wgSoftBlockRanges', [ '10.0.0.0/8' ] ); // IP isn't in $wgSoftBlockRanges + $wgUser = new User(); $request = new FauxRequest(); $request->setIP( '192.168.0.1' ); - $wgUser = User::newFromSession( $request ); + $setSessionUser( $wgUser, $request ); $this->assertNull( $wgUser->getBlock() ); // IP is in $wgSoftBlockRanges + $wgUser = new User(); $request = new FauxRequest(); $request->setIP( '10.20.30.40' ); - $wgUser = User::newFromSession( $request ); + $setSessionUser( $wgUser, $request ); $block = $wgUser->getBlock(); $this->assertInstanceOf( Block::class, $block ); $this->assertSame( 'wgSoftBlockRanges', $block->getSystemBlockType() ); // Make sure the block is really soft - $request->getSession()->setUser( $this->getTestUser()->getUser() ); - $wgUser = User::newFromSession( $request ); + $wgUser = $this->getTestUser()->getUser(); + $request = new FauxRequest(); + $request->setIP( '10.20.30.40' ); + $setSessionUser( $wgUser, $request ); $this->assertFalse( $wgUser->isAnon(), 'sanity check' ); $this->assertNull( $wgUser->getBlock() ); } @@ -832,6 +851,7 @@ class UserTest extends MediaWikiTestCase { $request1 = new FauxRequest(); $request1->getSession()->setUser( $user1tmp ); $block = new Block( [ 'enableAutoblock' => true ] ); + $block->setBlocker( $this->getTestSysop()->getUser() ); $block->setTarget( $user1tmp ); $block->setBlocker( $userBlocker ); $res = $block->insert(); @@ -877,6 +897,7 @@ class UserTest extends MediaWikiTestCase { $request1 = new FauxRequest(); $request1->getSession()->setUser( $user1tmp ); $block = new Block( [ 'enableAutoblock' => true ] ); + $block->setBlocker( $this->getTestSysop()->getUser() ); $block->setTarget( $user1tmp ); $block->setBlocker( $userBlocker ); $res = $block->insert(); @@ -903,6 +924,9 @@ class UserTest extends MediaWikiTestCase { $block->delete(); } + /** + * @covers User::isPingLimitable + */ public function testIsPingLimitable() { $request = new FauxRequest(); $request->setIP( '1.2.3.4' ); @@ -939,6 +963,7 @@ class UserTest extends MediaWikiTestCase { } /** + * @covers User::getExperienceLevel * @dataProvider provideExperienceLevel */ public function testExperienceLevel( $editCount, $memberSince, $expLevel ) { @@ -950,24 +975,25 @@ class UserTest extends MediaWikiTestCase { ] ); $db = wfGetDB( DB_MASTER ); - - $data = new stdClass(); - $data->user_id = 1; - $data->user_name = 'name'; - $data->user_real_name = 'Real Name'; - $data->user_touched = 1; - $data->user_token = 'token'; - $data->user_email = 'a@a.a'; - $data->user_email_authenticated = null; - $data->user_email_token = 'token'; - $data->user_email_token_expires = null; - $data->user_editcount = $editCount; - $data->user_registration = $db->timestamp( time() - $memberSince * 86400 ); - $user = User::newFromRow( $data ); + $userQuery = User::getQueryInfo(); + $row = $db->selectRow( + $userQuery['tables'], + $userQuery['fields'], + [ 'user_id' => $this->getTestUser()->getUser()->getId() ], + __METHOD__, + [], + $userQuery['joins'] + ); + $row->user_editcount = $editCount; + $row->user_registration = $db->timestamp( time() - $memberSince * 86400 ); + $user = User::newFromRow( $row ); $this->assertEquals( $expLevel, $user->getExperienceLevel() ); } + /** + * @covers User::getExperienceLevel + */ public function testExperienceLevelAnon() { $user = User::newFromName( '10.11.12.13', false ); @@ -1019,4 +1045,164 @@ class UserTest extends MediaWikiTestCase { ); $this->assertTrue( User::isLocallyBlockedProxy( $ip ) ); } + + public function testActorId() { + $this->hideDeprecated( 'User::selectFields' ); + + // Newly-created user has an actor ID + $user = User::createNew( 'UserTestActorId1' ); + $id = $user->getId(); + $this->assertTrue( $user->getActorId() > 0, 'User::createNew sets an actor ID' ); + + $user = User::newFromName( 'UserTestActorId2' ); + $user->addToDatabase(); + $this->assertTrue( $user->getActorId() > 0, 'User::addToDatabase sets an actor ID' ); + + $user = User::newFromName( 'UserTestActorId1' ); + $this->assertTrue( $user->getActorId() > 0, 'Actor ID can be retrieved for user loaded by name' ); + + $user = User::newFromId( $id ); + $this->assertTrue( $user->getActorId() > 0, 'Actor ID can be retrieved for user loaded by ID' ); + + $user2 = User::newFromActorId( $user->getActorId() ); + $this->assertEquals( $user->getId(), $user2->getId(), + 'User::newFromActorId works for an existing user' ); + + $row = $this->db->selectRow( 'user', User::selectFields(), [ 'user_id' => $id ], __METHOD__ ); + $user = User::newFromRow( $row ); + $this->assertTrue( $user->getActorId() > 0, + 'Actor ID can be retrieved for user loaded with User::selectFields()' ); + + $this->db->delete( 'actor', [ 'actor_user' => $id ], __METHOD__ ); + User::purge( wfWikiId(), $id ); + // Because WANObjectCache->delete() stupidly doesn't delete from the process cache. + ObjectCache::getMainWANInstance()->clearProcessCache(); + + $user = User::newFromId( $id ); + $this->assertFalse( $user->getActorId() > 0, 'No Actor ID by default if none in database' ); + $this->assertTrue( $user->getActorId( $this->db ) > 0, 'Actor ID can be created if none in db' ); + + $user->setName( 'UserTestActorId4-renamed' ); + $user->saveSettings(); + $this->assertEquals( + $user->getName(), + $this->db->selectField( + 'actor', 'actor_name', [ 'actor_id' => $user->getActorId() ], __METHOD__ + ), + 'User::saveSettings updates actor table for name change' + ); + + // For sanity + $ip = '192.168.12.34'; + $this->db->delete( 'actor', [ 'actor_name' => $ip ], __METHOD__ ); + + $user = User::newFromName( $ip, false ); + $this->assertFalse( $user->getActorId() > 0, 'Anonymous user has no actor ID by default' ); + $this->assertTrue( $user->getActorId( $this->db ) > 0, + 'Actor ID can be created for an anonymous user' ); + + $user = User::newFromName( $ip, false ); + $this->assertTrue( $user->getActorId() > 0, 'Actor ID can be loaded for an anonymous user' ); + $user2 = User::newFromActorId( $user->getActorId() ); + $this->assertEquals( $user->getName(), $user2->getName(), + 'User::newFromActorId works for an anonymous user' ); + } + + public function testNewFromAnyId() { + // Registered user + $user = $this->getTestUser()->getUser(); + for ( $i = 1; $i <= 7; $i++ ) { + $test = User::newFromAnyId( + ( $i & 1 ) ? $user->getId() : null, + ( $i & 2 ) ? $user->getName() : null, + ( $i & 4 ) ? $user->getActorId() : null + ); + $this->assertSame( $user->getId(), $test->getId() ); + $this->assertSame( $user->getName(), $test->getName() ); + $this->assertSame( $user->getActorId(), $test->getActorId() ); + } + + // Anon user. Can't load by only user ID when that's 0. + $user = User::newFromName( '192.168.12.34', false ); + $user->getActorId( $this->db ); // Make sure an actor ID exists + + $test = User::newFromAnyId( null, '192.168.12.34', null ); + $this->assertSame( $user->getId(), $test->getId() ); + $this->assertSame( $user->getName(), $test->getName() ); + $this->assertSame( $user->getActorId(), $test->getActorId() ); + $test = User::newFromAnyId( null, null, $user->getActorId() ); + $this->assertSame( $user->getId(), $test->getId() ); + $this->assertSame( $user->getName(), $test->getName() ); + $this->assertSame( $user->getActorId(), $test->getActorId() ); + + // Bogus data should still "work" as long as nothing triggers a ->load(), + // and accessing the specified data shouldn't do that. + $test = User::newFromAnyId( 123456, 'Bogus', 654321 ); + $this->assertSame( 123456, $test->getId() ); + $this->assertSame( 'Bogus', $test->getName() ); + $this->assertSame( 654321, $test->getActorId() ); + + // Exceptional cases + try { + User::newFromAnyId( null, null, null ); + $this->fail( 'Expected exception not thrown' ); + } catch ( InvalidArgumentException $ex ) { + } + try { + User::newFromAnyId( 0, null, 0 ); + $this->fail( 'Expected exception not thrown' ); + } catch ( InvalidArgumentException $ex ) { + } + } + + /** + * @covers User::getBlockedStatus + * @covers User::getBlock + * @covers User::blockedBy + * @covers User::blockedFor + * @covers User::isHidden + * @covers User::isBlockedFrom + */ + public function testBlockInstanceCache() { + // First, check the user isn't blocked + $user = $this->getMutableTestUser()->getUser(); + $ut = Title::makeTitle( NS_USER_TALK, $user->getName() ); + $this->assertNull( $user->getBlock( false ), 'sanity check' ); + $this->assertSame( '', $user->blockedBy(), 'sanity check' ); + $this->assertSame( '', $user->blockedFor(), 'sanity check' ); + $this->assertFalse( (bool)$user->isHidden(), 'sanity check' ); + $this->assertFalse( $user->isBlockedFrom( $ut ), 'sanity check' ); + + // Block the user + $blocker = $this->getTestSysop()->getUser(); + $block = new Block( [ + 'hideName' => true, + 'allowUsertalk' => false, + 'reason' => 'Because', + ] ); + $block->setTarget( $user ); + $block->setBlocker( $blocker ); + $res = $block->insert(); + $this->assertTrue( (bool)$res['id'], 'sanity check: Failed to insert block' ); + + // Clear cache and confirm it loaded the block properly + $user->clearInstanceCache(); + $this->assertInstanceOf( Block::class, $user->getBlock( false ) ); + $this->assertSame( $blocker->getName(), $user->blockedBy() ); + $this->assertSame( 'Because', $user->blockedFor() ); + $this->assertTrue( (bool)$user->isHidden() ); + $this->assertTrue( $user->isBlockedFrom( $ut ) ); + + // Unblock + $block->delete(); + + // Clear cache and confirm it loaded the not-blocked properly + $user->clearInstanceCache(); + $this->assertNull( $user->getBlock( false ) ); + $this->assertSame( '', $user->blockedBy() ); + $this->assertSame( '', $user->blockedFor() ); + $this->assertFalse( (bool)$user->isHidden() ); + $this->assertFalse( $user->isBlockedFrom( $ut ) ); + } + }