1<?php 2 3namespace MediaWiki\Tests\User\CentralId; 4 5use CentralIdLookup; 6use InvalidArgumentException; 7use LogicException; 8use MediaWiki\Permissions\Authority; 9use MediaWiki\Tests\Unit\Permissions\MockAuthorityTrait; 10use MediaWiki\User\UserIdentity; 11use MediaWiki\User\UserIdentityLookup; 12use MediaWiki\User\UserIdentityValue; 13use MediaWikiUnitTestCase; 14use User; 15use Wikimedia\TestingAccessWrapper; 16 17/** 18 * @covers CentralIdLookup 19 */ 20class CentralIdLookupTest extends MediaWikiUnitTestCase { 21 use MockAuthorityTrait; 22 23 public function testGetProviderId() { 24 $mock = $this->getMockForAbstractClass( CentralIdLookup::class ); 25 $mock->init( 'this is a test', $this->createNoOpMock( UserIdentityLookup::class ) ); 26 $this->assertSame( 'this is a test', $mock->getProviderId() ); 27 } 28 29 public function testRepeatingInitThrows() { 30 $mock = $this->getMockForAbstractClass( CentralIdLookup::class ); 31 $mock->init( 'foo', $this->createNoOpMock( UserIdentityLookup::class ) ); 32 $this->expectException( LogicException::class ); 33 $mock->init( 'bar', $this->createNoOpMock( UserIdentityLookup::class ) ); 34 } 35 36 public function testCheckAudience() { 37 $mock = TestingAccessWrapper::newFromObject( 38 $this->getMockForAbstractClass( CentralIdLookup::class ) 39 ); 40 41 $authority = $this->mockAnonUltimateAuthority(); 42 $this->assertSame( $authority, $mock->checkAudience( $authority ) ); 43 44 $authority = $mock->checkAudience( CentralIdLookup::AUDIENCE_PUBLIC ); 45 $this->assertInstanceOf( Authority::class, $authority ); 46 // Should be an empty User object, don't trigger loading that requires integration 47 // if a user is created from "defaults" then its an anonymous default user 48 $this->assertInstanceOf( User::class, $authority ); 49 $this->assertSame( 'defaults', $authority->mFrom ); 50 51 $this->assertNull( $mock->checkAudience( CentralIdLookup::AUDIENCE_RAW ) ); 52 53 try { 54 $mock->checkAudience( 100 ); 55 $this->fail( 'Expected exception not thrown' ); 56 } catch ( InvalidArgumentException $ex ) { 57 $this->assertSame( 'Invalid audience', $ex->getMessage() ); 58 } 59 } 60 61 public function testNameFromCentralId() { 62 $mock = $this->getMockForAbstractClass( CentralIdLookup::class ); 63 $mock->expects( $this->once() )->method( 'lookupCentralIds' ) 64 ->with( 65 [ 15 => null ], 66 CentralIdLookup::AUDIENCE_RAW, 67 CentralIdLookup::READ_LATEST 68 ) 69 ->willReturn( [ 15 => 'FooBar' ] ); 70 71 $this->assertSame( 72 'FooBar', 73 $mock->nameFromCentralId( 15, CentralIdLookup::AUDIENCE_RAW, CentralIdLookup::READ_LATEST ) 74 ); 75 } 76 77 /** 78 * @dataProvider provideLocalUserFromCentralId 79 * @param string $name 80 * @param bool $succeeds 81 */ 82 public function testLocalUserFromCentralId( $name, $succeeds ) { 83 // UserIdentityLookup expects to be asked for a UserIdentity with the 84 // name $name, and will return one only if its for UTSysop, no other 85 // users are registered 86 $lookupResult = ( $name === 'UTSysop' ? ( new UserIdentityValue( 5, $name ) ) : null ); 87 $userIdentityLookup = $this->createMock( UserIdentityLookup::class ); 88 $userIdentityLookup->method( 'getUserIdentityByName' ) 89 ->with( $name ) 90 ->willReturn( $lookupResult ); 91 92 $mock = $this->getMockForAbstractClass( CentralIdLookup::class ); 93 $mock->method( 'isAttached' ) 94 ->willReturn( true ); 95 $mock->expects( $this->once() )->method( 'lookupCentralIds' ) 96 ->with( 97 [ 42 => null ], 98 CentralIdLookup::AUDIENCE_RAW, 99 CentralIdLookup::READ_LATEST 100 ) 101 ->willReturn( [ 42 => $name ] ); 102 103 $mock->init( 'test', $userIdentityLookup ); 104 $user = $mock->localUserFromCentralId( 105 42, CentralIdLookup::AUDIENCE_RAW, CentralIdLookup::READ_LATEST 106 ); 107 if ( $succeeds ) { 108 $this->assertInstanceOf( UserIdentity::class, $user ); 109 $this->assertSame( $name, $user->getName() ); 110 } else { 111 $this->assertNull( $user ); 112 } 113 114 $mock = $this->getMockForAbstractClass( CentralIdLookup::class ); 115 $mock->method( 'isAttached' ) 116 ->willReturn( false ); 117 $mock->expects( $this->once() )->method( 'lookupCentralIds' ) 118 ->with( 119 [ 42 => null ], 120 CentralIdLookup::AUDIENCE_RAW, 121 CentralIdLookup::READ_LATEST 122 ) 123 ->willReturn( [ 42 => $name ] ); 124 $mock->init( 'test', $userIdentityLookup ); 125 126 $this->assertNull( 127 $mock->localUserFromCentralId( 42, CentralIdLookup::AUDIENCE_RAW, CentralIdLookup::READ_LATEST ) 128 ); 129 } 130 131 public static function provideLocalUserFromCentralId() { 132 return [ 133 [ 'UTSysop', true ], 134 [ 'UTDoesNotExist', false ], 135 [ null, false ], 136 [ '', false ], 137 [ '<X>', false ], 138 ]; 139 } 140 141 public function testCentralIdFromName() { 142 $mock = $this->getMockForAbstractClass( CentralIdLookup::class ); 143 $mock->expects( $this->once() )->method( 'lookupUserNames' ) 144 ->with( 145 [ 'FooBar' => 0 ], 146 CentralIdLookup::AUDIENCE_RAW, 147 CentralIdLookup::READ_LATEST 148 ) 149 ->willReturn( [ 'FooBar' => 23 ] ); 150 151 $this->assertSame( 152 23, 153 $mock->centralIdFromName( 'FooBar', CentralIdLookup::AUDIENCE_RAW, CentralIdLookup::READ_LATEST ) 154 ); 155 } 156 157 public function testCentralIdFromLocalUser() { 158 $mock = $this->getMockForAbstractClass( CentralIdLookup::class ); 159 $mock->method( 'isAttached' ) 160 ->willReturn( true ); 161 $mock->expects( $this->once() )->method( 'lookupUserNames' ) 162 ->with( 163 [ 'FooBar' => 0 ], 164 CentralIdLookup::AUDIENCE_RAW, 165 CentralIdLookup::READ_LATEST 166 ) 167 ->willReturn( [ 'FooBar' => 23 ] ); 168 169 $this->assertSame( 170 23, 171 $mock->centralIdFromLocalUser( 172 new UserIdentityValue( 10, 'FooBar' ), 173 CentralIdLookup::AUDIENCE_RAW, 174 CentralIdLookup::READ_LATEST 175 ) 176 ); 177 178 $mock = $this->getMockForAbstractClass( CentralIdLookup::class ); 179 $mock->method( 'isAttached' ) 180 ->willReturn( false ); 181 $mock->expects( $this->never() )->method( 'lookupUserNames' ); 182 183 $this->assertSame( 184 0, 185 $mock->centralIdFromLocalUser( 186 new UserIdentityValue( 10, 'FooBar' ), 187 CentralIdLookup::AUDIENCE_RAW, 188 CentralIdLookup::READ_LATEST 189 ) 190 ); 191 } 192 193} 194