MediaWiki  REL1_24
UserTest.php
Go to the documentation of this file.
00001 <?php
00002 
00003 define( 'NS_UNITTEST', 5600 );
00004 define( 'NS_UNITTEST_TALK', 5601 );
00005 
00009 class UserTest extends MediaWikiTestCase {
00013     protected $user;
00014 
00015     protected function setUp() {
00016         parent::setUp();
00017 
00018         $this->setMwGlobals( array(
00019             'wgGroupPermissions' => array(),
00020             'wgRevokePermissions' => array(),
00021         ) );
00022 
00023         $this->setUpPermissionGlobals();
00024 
00025         $this->user = new User;
00026         $this->user->addGroup( 'unittesters' );
00027     }
00028 
00029     private function setUpPermissionGlobals() {
00030         global $wgGroupPermissions, $wgRevokePermissions;
00031 
00032         # Data for regular $wgGroupPermissions test
00033         $wgGroupPermissions['unittesters'] = array(
00034             'test' => true,
00035             'runtest' => true,
00036             'writetest' => false,
00037             'nukeworld' => false,
00038         );
00039         $wgGroupPermissions['testwriters'] = array(
00040             'test' => true,
00041             'writetest' => true,
00042             'modifytest' => true,
00043         );
00044 
00045         # Data for regular $wgRevokePermissions test
00046         $wgRevokePermissions['formertesters'] = array(
00047             'runtest' => true,
00048         );
00049 
00050         # For the options test
00051         $wgGroupPermissions['*'] = array(
00052             'editmyoptions' => true,
00053         );
00054     }
00055 
00059     public function testGroupPermissions() {
00060         $rights = User::getGroupPermissions( array( 'unittesters' ) );
00061         $this->assertContains( 'runtest', $rights );
00062         $this->assertNotContains( 'writetest', $rights );
00063         $this->assertNotContains( 'modifytest', $rights );
00064         $this->assertNotContains( 'nukeworld', $rights );
00065 
00066         $rights = User::getGroupPermissions( array( 'unittesters', 'testwriters' ) );
00067         $this->assertContains( 'runtest', $rights );
00068         $this->assertContains( 'writetest', $rights );
00069         $this->assertContains( 'modifytest', $rights );
00070         $this->assertNotContains( 'nukeworld', $rights );
00071     }
00072 
00076     public function testRevokePermissions() {
00077         $rights = User::getGroupPermissions( array( 'unittesters', 'formertesters' ) );
00078         $this->assertNotContains( 'runtest', $rights );
00079         $this->assertNotContains( 'writetest', $rights );
00080         $this->assertNotContains( 'modifytest', $rights );
00081         $this->assertNotContains( 'nukeworld', $rights );
00082     }
00083 
00087     public function testUserPermissions() {
00088         $rights = $this->user->getRights();
00089         $this->assertContains( 'runtest', $rights );
00090         $this->assertNotContains( 'writetest', $rights );
00091         $this->assertNotContains( 'modifytest', $rights );
00092         $this->assertNotContains( 'nukeworld', $rights );
00093     }
00094 
00099     public function testGetGroupsWithPermission( $expected, $right ) {
00100         $result = User::getGroupsWithPermission( $right );
00101         sort( $result );
00102         sort( $expected );
00103 
00104         $this->assertEquals( $expected, $result, "Groups with permission $right" );
00105     }
00106 
00107     public static function provideGetGroupsWithPermission() {
00108         return array(
00109             array(
00110                 array( 'unittesters', 'testwriters' ),
00111                 'test'
00112             ),
00113             array(
00114                 array( 'unittesters' ),
00115                 'runtest'
00116             ),
00117             array(
00118                 array( 'testwriters' ),
00119                 'writetest'
00120             ),
00121             array(
00122                 array( 'testwriters' ),
00123                 'modifytest'
00124             ),
00125         );
00126     }
00127 
00132     public function testIsIP( $value, $result, $message ) {
00133         $this->assertEquals( $this->user->isIP( $value ), $result, $message );
00134     }
00135 
00136     public static function provideIPs() {
00137         return array(
00138             array( '', false, 'Empty string' ),
00139             array( ' ', false, 'Blank space' ),
00140             array( '10.0.0.0', true, 'IPv4 private 10/8' ),
00141             array( '10.255.255.255', true, 'IPv4 private 10/8' ),
00142             array( '192.168.1.1', true, 'IPv4 private 192.168/16' ),
00143             array( '203.0.113.0', true, 'IPv4 example' ),
00144             array( '2002:ffff:ffff:ffff:ffff:ffff:ffff:ffff', true, 'IPv6 example' ),
00145             // Not valid IPs but classified as such by MediaWiki for negated asserting
00146             // of whether this might be the identifier of a logged-out user or whether
00147             // to allow usernames like it.
00148             array( '300.300.300.300', true, 'Looks too much like an IPv4 address' ),
00149             array( '203.0.113.xxx', true, 'Assigned by UseMod to cloaked logged-out users' ),
00150         );
00151     }
00152 
00157     public function testIsValidUserName( $username, $result, $message ) {
00158         $this->assertEquals( $this->user->isValidUserName( $username ), $result, $message );
00159     }
00160 
00161     public static function provideUserNames() {
00162         return array(
00163             array( '', false, 'Empty string' ),
00164             array( ' ', false, 'Blank space' ),
00165             array( 'abcd', false, 'Starts with small letter' ),
00166             array( 'Ab/cd', false, 'Contains slash' ),
00167             array( 'Ab cd', true, 'Whitespace' ),
00168             array( '192.168.1.1', false, 'IP' ),
00169             array( 'User:Abcd', false, 'Reserved Namespace' ),
00170             array( '12abcd232', true, 'Starts with Numbers' ),
00171             array( '?abcd', true, 'Start with ? mark' ),
00172             array( '#abcd', false, 'Start with #' ),
00173             array( 'Abcdകഖഗഘ', true, ' Mixed scripts' ),
00174             array( 'ജോസ്‌തോമസ്', false, 'ZWNJ- Format control character' ),
00175             array( 'Ab cd', false, ' Ideographic space' ),
00176             array( '300.300.300.300', false, 'Looks too much like an IPv4 address' ),
00177             array( '302.113.311.900', false, 'Looks too much like an IPv4 address' ),
00178             array( '203.0.113.xxx', false, 'Reserved for usage by UseMod for cloaked logged-out users' ),
00179         );
00180     }
00181 
00187     public function testAllRightsWithMessage() {
00188         // Getting all user rights, for core: User::$mCoreRights, for extensions: $wgAvailableRights
00189         $allRights = User::getAllRights();
00190         $allMessageKeys = Language::getMessageKeysFor( 'en' );
00191 
00192         $rightsWithMessage = array();
00193         foreach ( $allMessageKeys as $message ) {
00194             // === 0: must be at beginning of string (position 0)
00195             if ( strpos( $message, 'right-' ) === 0 ) {
00196                 $rightsWithMessage[] = substr( $message, strlen( 'right-' ) );
00197             }
00198         }
00199 
00200         sort( $allRights );
00201         sort( $rightsWithMessage );
00202 
00203         $this->assertEquals(
00204             $allRights,
00205             $rightsWithMessage,
00206             'Each user rights (core/extensions) has a corresponding right- message.'
00207         );
00208     }
00209 
00215     public function testEditCount() {
00216         $user = User::newFromName( 'UnitTestUser' );
00217         $user->loadDefaults();
00218         $user->addToDatabase();
00219 
00220         // let the user have a few (3) edits
00221         $page = WikiPage::factory( Title::newFromText( 'Help:UserTest_EditCount' ) );
00222         for ( $i = 0; $i < 3; $i++ ) {
00223             $page->doEdit( (string)$i, 'test', 0, false, $user );
00224         }
00225 
00226         $user->clearInstanceCache();
00227         $this->assertEquals(
00228             3,
00229             $user->getEditCount(),
00230             'After three edits, the user edit count should be 3'
00231         );
00232 
00233         // increase the edit count and clear the cache
00234         $user->incEditCount();
00235 
00236         $user->clearInstanceCache();
00237         $this->assertEquals(
00238             4,
00239             $user->getEditCount(),
00240             'After increasing the edit count manually, the user edit count should be 4'
00241         );
00242     }
00243 
00249     public function testOptions() {
00250         $user = User::newFromName( 'UnitTestUser' );
00251         $user->addToDatabase();
00252 
00253         $user->setOption( 'someoption', 'test' );
00254         $user->setOption( 'cols', 200 );
00255         $user->saveSettings();
00256 
00257         $user = User::newFromName( 'UnitTestUser' );
00258         $this->assertEquals( 'test', $user->getOption( 'someoption' ) );
00259         $this->assertEquals( 200, $user->getOption( 'cols' ) );
00260     }
00261 
00267     public function testAnonOptions() {
00268         global $wgDefaultUserOptions;
00269         $this->user->setOption( 'someoption', 'test' );
00270         $this->assertEquals( $wgDefaultUserOptions['cols'], $this->user->getOption( 'cols' ) );
00271         $this->assertEquals( 'test', $this->user->getOption( 'someoption' ) );
00272     }
00273 
00278     public function testPasswordExpire() {
00279         global $wgPasswordExpireGrace;
00280         $wgTemp = $wgPasswordExpireGrace;
00281         $wgPasswordExpireGrace = 3600 * 24 * 7; // 7 days
00282 
00283         $user = User::newFromName( 'UnitTestUser' );
00284         $user->loadDefaults();
00285         $this->assertEquals( false, $user->getPasswordExpired() );
00286 
00287         $ts = time() - ( 3600 * 24 * 1 ); // 1 day ago
00288         $user->expirePassword( $ts );
00289         $this->assertEquals( 'soft', $user->getPasswordExpired() );
00290 
00291         $ts = time() - ( 3600 * 24 * 10 ); // 10 days ago
00292         $user->expirePassword( $ts );
00293         $this->assertEquals( 'hard', $user->getPasswordExpired() );
00294 
00295         $wgPasswordExpireGrace = $wgTemp;
00296     }
00297 
00307     public function testCheckPasswordValidity() {
00308         $this->setMwGlobals( 'wgMinimalPasswordLength', 6 );
00309         $user = User::newFromName( 'Useruser' );
00310         // Sanity
00311         $this->assertTrue( $user->isValidPassword( 'Password1234' ) );
00312 
00313         // Minimum length
00314         $this->assertFalse( $user->isValidPassword( 'a' ) );
00315         $this->assertFalse( $user->checkPasswordValidity( 'a' )->isGood() );
00316         $this->assertEquals( 'passwordtooshort', $user->getPasswordValidity( 'a' ) );
00317 
00318         // Matches username
00319         $this->assertFalse( $user->checkPasswordValidity( 'Useruser' )->isGood() );
00320         $this->assertEquals( 'password-name-match', $user->getPasswordValidity( 'Useruser' ) );
00321 
00322         // On the forbidden list
00323         $this->assertFalse( $user->checkPasswordValidity( 'Passpass' )->isGood() );
00324         $this->assertEquals( 'password-login-forbidden', $user->getPasswordValidity( 'Passpass' ) );
00325     }
00326 
00331     public function testGetCanonicalName( $name, $expectedArray, $msg ) {
00332         foreach ( $expectedArray as $validate => $expected ) {
00333             $this->assertEquals(
00334                 User::getCanonicalName( $name, $validate === 'false' ? false : $validate ),
00335                 $expected,
00336                 $msg . ' (' . $validate . ')'
00337             );
00338         }
00339     }
00340 
00341     public static function provideGetCanonicalName() {
00342         return array(
00343             array( ' trailing space ', array( 'creatable' => 'Trailing space' ), 'Trailing spaces' ),
00344             // @todo FIXME: Maybe the createable name should be 'Talk:Username' or false to reject?
00345             array( 'Talk:Username', array( 'creatable' => 'Username', 'usable' => 'Username',
00346                 'valid' => 'Username', 'false' => 'Talk:Username' ), 'Namespace prefix' ),
00347             array( ' name with # hash', array( 'creatable' => false, 'usable' => false ), 'With hash' ),
00348             array( 'Multi  spaces', array( 'creatable' => 'Multi spaces',
00349                 'usable' => 'Multi spaces' ), 'Multi spaces' ),
00350             array( 'lowercase', array( 'creatable' => 'Lowercase' ), 'Lowercase' ),
00351             array( 'in[]valid', array( 'creatable' => false, 'usable' => false, 'valid' => false,
00352                 'false' => 'In[]valid' ), 'Invalid' ),
00353             array( 'with / slash', array( 'creatable' => false, 'usable' => false, 'valid' => false,
00354                 'false' => 'With / slash' ), 'With slash' ),
00355         );
00356     }
00357 }