3 use MediaWiki\User\UserIdentity
;
4 use Wikimedia\ScopedCallback
;
5 use Wikimedia\TestingAccessWrapper
;
9 * @covers ActorMigration
11 class ActorMigrationTest
extends MediaWikiLangTestCase
{
13 protected $resetActorMigration = null;
14 protected static $amId = 0;
16 protected $tablesUsed = [
20 protected function setUp() {
23 $w = TestingAccessWrapper
::newFromClass( ActorMigration
::class );
25 'tempTables' => $w->tempTables
,
26 'formerTempTables' => $w->formerTempTables
,
27 'deprecated' => $w->deprecated
,
28 'removed' => $w->removed
,
29 'specialFields' => $w->specialFields
,
31 $this->resetActorMigration
= new ScopedCallback( function ( $w, $data ) {
32 foreach ( $data as $k => $v ) {
39 'table' => 'actormigration2_temp',
41 'field' => 'am2t_actor',
47 'am3_xxx' => [ 'am3_xxx_text', 'am3_xxx_actor' ],
51 protected function tearDown() {
53 ScopedCallback
::consume( $this->resetActorMigration
);
56 protected function getSchemaOverrides( IMaintainableDatabase
$db ) {
59 __DIR__
. '/ActorMigrationTest.sql',
62 'create' => [ 'actormigration1', 'actormigration2', 'actormigration2_temp', 'actormigration3' ],
68 * @dataProvider provideConstructor
70 * @param string|null $exceptionMsg
72 public function testConstructor( $stage, $exceptionMsg ) {
74 $m = new ActorMigration( $stage );
75 if ( $exceptionMsg !== null ) {
76 $this->fail( 'Expected exception not thrown' );
78 $this->assertInstanceOf( ActorMigration
::class, $m );
79 } catch ( InvalidArgumentException
$ex ) {
80 $this->assertSame( $exceptionMsg, $ex->getMessage() );
84 public static function provideConstructor() {
86 [ 0, '$stage must include a write mode' ],
87 [ SCHEMA_COMPAT_READ_OLD
, '$stage must include a write mode' ],
88 [ SCHEMA_COMPAT_READ_NEW
, '$stage must include a write mode' ],
89 [ SCHEMA_COMPAT_READ_BOTH
, '$stage must include a write mode' ],
91 [ SCHEMA_COMPAT_WRITE_OLD
, '$stage must include a read mode' ],
92 [ SCHEMA_COMPAT_WRITE_OLD | SCHEMA_COMPAT_READ_OLD
, null ],
94 SCHEMA_COMPAT_WRITE_OLD | SCHEMA_COMPAT_READ_NEW
,
95 'Cannot read the new schema without also writing it'
97 [ SCHEMA_COMPAT_WRITE_OLD | SCHEMA_COMPAT_READ_BOTH
, 'Cannot read both schemas' ],
99 [ SCHEMA_COMPAT_WRITE_NEW
, '$stage must include a read mode' ],
101 SCHEMA_COMPAT_WRITE_NEW | SCHEMA_COMPAT_READ_OLD
,
102 'Cannot read the old schema without also writing it'
104 [ SCHEMA_COMPAT_WRITE_NEW | SCHEMA_COMPAT_READ_NEW
, null ],
105 [ SCHEMA_COMPAT_WRITE_NEW | SCHEMA_COMPAT_READ_BOTH
, 'Cannot read both schemas' ],
107 [ SCHEMA_COMPAT_WRITE_BOTH
, '$stage must include a read mode' ],
108 [ SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
, null ],
109 [ SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
, null ],
110 [ SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_BOTH
, 'Cannot read both schemas' ],
115 * @dataProvider provideGetJoin
118 * @param array $expect
120 public function testGetJoin( $stage, $key, $expect ) {
121 $m = new ActorMigration( $stage );
122 $result = $m->getJoin( $key );
123 $this->assertEquals( $expect, $result );
126 public static function provideGetJoin() {
128 'Simple table, old' => [
129 SCHEMA_COMPAT_OLD
, 'am1_user', [
132 'am1_user' => 'am1_user',
133 'am1_user_text' => 'am1_user_text',
134 'am1_actor' => 'NULL',
139 'Simple table, read-old' => [
140 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
, 'am1_user', [
143 'am1_user' => 'am1_user',
144 'am1_user_text' => 'am1_user_text',
145 'am1_actor' => 'NULL',
150 'Simple table, read-new' => [
151 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
, 'am1_user', [
152 'tables' => [ 'actor_am1_user' => 'actor' ],
154 'am1_user' => 'actor_am1_user.actor_user',
155 'am1_user_text' => 'actor_am1_user.actor_name',
156 'am1_actor' => 'am1_actor',
159 'actor_am1_user' => [ 'JOIN', 'actor_am1_user.actor_id = am1_actor' ],
163 'Simple table, new' => [
164 SCHEMA_COMPAT_NEW
, 'am1_user', [
165 'tables' => [ 'actor_am1_user' => 'actor' ],
167 'am1_user' => 'actor_am1_user.actor_user',
168 'am1_user_text' => 'actor_am1_user.actor_name',
169 'am1_actor' => 'am1_actor',
172 'actor_am1_user' => [ 'JOIN', 'actor_am1_user.actor_id = am1_actor' ],
177 'Special name, old' => [
178 SCHEMA_COMPAT_OLD
, 'am3_xxx', [
181 'am3_xxx' => 'am3_xxx',
182 'am3_xxx_text' => 'am3_xxx_text',
183 'am3_xxx_actor' => 'NULL',
188 'Special name, read-old' => [
189 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
, 'am3_xxx', [
192 'am3_xxx' => 'am3_xxx',
193 'am3_xxx_text' => 'am3_xxx_text',
194 'am3_xxx_actor' => 'NULL',
199 'Special name, read-new' => [
200 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
, 'am3_xxx', [
201 'tables' => [ 'actor_am3_xxx' => 'actor' ],
203 'am3_xxx' => 'actor_am3_xxx.actor_user',
204 'am3_xxx_text' => 'actor_am3_xxx.actor_name',
205 'am3_xxx_actor' => 'am3_xxx_actor',
208 'actor_am3_xxx' => [ 'JOIN', 'actor_am3_xxx.actor_id = am3_xxx_actor' ],
212 'Special name, new' => [
213 SCHEMA_COMPAT_NEW
, 'am3_xxx', [
214 'tables' => [ 'actor_am3_xxx' => 'actor' ],
216 'am3_xxx' => 'actor_am3_xxx.actor_user',
217 'am3_xxx_text' => 'actor_am3_xxx.actor_name',
218 'am3_xxx_actor' => 'am3_xxx_actor',
221 'actor_am3_xxx' => [ 'JOIN', 'actor_am3_xxx.actor_id = am3_xxx_actor' ],
226 'Temp table, old' => [
227 SCHEMA_COMPAT_OLD
, 'am2_user', [
230 'am2_user' => 'am2_user',
231 'am2_user_text' => 'am2_user_text',
232 'am2_actor' => 'NULL',
237 'Temp table, read-old' => [
238 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
, 'am2_user', [
241 'am2_user' => 'am2_user',
242 'am2_user_text' => 'am2_user_text',
243 'am2_actor' => 'NULL',
248 'Temp table, read-new' => [
249 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
, 'am2_user', [
251 'temp_am2_user' => 'actormigration2_temp',
252 'actor_am2_user' => 'actor',
255 'am2_user' => 'actor_am2_user.actor_user',
256 'am2_user_text' => 'actor_am2_user.actor_name',
257 'am2_actor' => 'temp_am2_user.am2t_actor',
260 'temp_am2_user' => [ 'JOIN', 'temp_am2_user.am2t_id = am2_id' ],
261 'actor_am2_user' => [ 'JOIN', 'actor_am2_user.actor_id = temp_am2_user.am2t_actor' ],
265 'Temp table, new' => [
266 SCHEMA_COMPAT_NEW
, 'am2_user', [
268 'temp_am2_user' => 'actormigration2_temp',
269 'actor_am2_user' => 'actor',
272 'am2_user' => 'actor_am2_user.actor_user',
273 'am2_user_text' => 'actor_am2_user.actor_name',
274 'am2_actor' => 'temp_am2_user.am2t_actor',
277 'temp_am2_user' => [ 'JOIN', 'temp_am2_user.am2t_id = am2_id' ],
278 'actor_am2_user' => [ 'JOIN', 'actor_am2_user.actor_id = temp_am2_user.am2t_actor' ],
286 * @dataProvider provideGetWhere
289 * @param UserIdentity[] $users
291 * @param array $expect
293 public function testGetWhere( $stage, $key, $users, $useId, $expect ) {
294 $expect['conds'] = '(' . implode( ') OR (', $expect['orconds'] ) . ')';
296 if ( count( $users ) === 1 ) {
297 $users = reset( $users );
300 $m = new ActorMigration( $stage );
301 $result = $m->getWhere( $this->db
, $key, $users, $useId );
302 $this->assertEquals( $expect, $result );
305 public function provideGetWhere() {
306 $makeUserIdentity = function ( $id, $name, $actor ) {
307 $u = $this->getMock( UserIdentity
::class );
308 $u->method( 'getId' )->willReturn( $id );
309 $u->method( 'getName' )->willReturn( $name );
310 $u->method( 'getActorId' )->willReturn( $actor );
314 $genericUser = [ $makeUserIdentity( 1, 'User1', 11 ) ];
315 $complicatedUsers = [
316 $makeUserIdentity( 1, 'User1', 11 ),
317 $makeUserIdentity( 2, 'User2', 12 ),
318 $makeUserIdentity( 3, 'User3', 0 ),
319 $makeUserIdentity( 0, '192.168.12.34', 34 ),
320 $makeUserIdentity( 0, '192.168.12.35', 0 ),
324 'Simple table, old' => [
325 SCHEMA_COMPAT_OLD
, 'am1_user', $genericUser, true, [
327 'orconds' => [ 'userid' => "am1_user = '1'" ],
331 'Simple table, read-old' => [
332 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
, 'am1_user', $genericUser, true, [
334 'orconds' => [ 'userid' => "am1_user = '1'" ],
338 'Simple table, read-new' => [
339 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
, 'am1_user', $genericUser, true, [
341 'orconds' => [ 'actor' => "am1_actor = '11'" ],
345 'Simple table, new' => [
346 SCHEMA_COMPAT_NEW
, 'am1_user', $genericUser, true, [
348 'orconds' => [ 'actor' => "am1_actor = '11'" ],
353 'Special name, old' => [
354 SCHEMA_COMPAT_OLD
, 'am3_xxx', $genericUser, true, [
356 'orconds' => [ 'userid' => "am3_xxx = '1'" ],
360 'Special name, read-old' => [
361 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
, 'am3_xxx', $genericUser, true, [
363 'orconds' => [ 'userid' => "am3_xxx = '1'" ],
367 'Special name, read-new' => [
368 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
, 'am3_xxx', $genericUser, true, [
370 'orconds' => [ 'actor' => "am3_xxx_actor = '11'" ],
374 'Special name, new' => [
375 SCHEMA_COMPAT_NEW
, 'am3_xxx', $genericUser, true, [
377 'orconds' => [ 'actor' => "am3_xxx_actor = '11'" ],
382 'Temp table, old' => [
383 SCHEMA_COMPAT_OLD
, 'am2_user', $genericUser, true, [
385 'orconds' => [ 'userid' => "am2_user = '1'" ],
389 'Temp table, read-old' => [
390 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
, 'am2_user', $genericUser, true, [
392 'orconds' => [ 'userid' => "am2_user = '1'" ],
396 'Temp table, read-new' => [
397 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
, 'am2_user', $genericUser, true, [
399 'temp_am2_user' => 'actormigration2_temp',
401 'orconds' => [ 'actor' => "temp_am2_user.am2t_actor = '11'" ],
403 'temp_am2_user' => [ 'JOIN', 'temp_am2_user.am2t_id = am2_id' ],
407 'Temp table, new' => [
408 SCHEMA_COMPAT_NEW
, 'am2_user', $genericUser, true, [
410 'temp_am2_user' => 'actormigration2_temp',
412 'orconds' => [ 'actor' => "temp_am2_user.am2t_actor = '11'" ],
414 'temp_am2_user' => [ 'JOIN', 'temp_am2_user.am2t_id = am2_id' ],
419 'Multiple users, old' => [
420 SCHEMA_COMPAT_OLD
, 'am1_user', $complicatedUsers, true, [
423 'userid' => "am1_user IN ('1','2','3') ",
424 'username' => "am1_user_text IN ('192.168.12.34','192.168.12.35') "
429 'Multiple users, read-old' => [
430 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
, 'am1_user', $complicatedUsers, true, [
433 'userid' => "am1_user IN ('1','2','3') ",
434 'username' => "am1_user_text IN ('192.168.12.34','192.168.12.35') "
439 'Multiple users, read-new' => [
440 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
, 'am1_user', $complicatedUsers, true, [
442 'orconds' => [ 'actor' => "am1_actor IN ('11','12','34') " ],
446 'Multiple users, new' => [
447 SCHEMA_COMPAT_NEW
, 'am1_user', $complicatedUsers, true, [
449 'orconds' => [ 'actor' => "am1_actor IN ('11','12','34') " ],
454 'Multiple users, no use ID, old' => [
455 SCHEMA_COMPAT_OLD
, 'am1_user', $complicatedUsers, false, [
458 'username' => "am1_user_text IN ('User1','User2','User3','192.168.12.34','192.168.12.35') "
463 'Multiple users, read-old' => [
464 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
, 'am1_user', $complicatedUsers, false, [
467 'username' => "am1_user_text IN ('User1','User2','User3','192.168.12.34','192.168.12.35') "
472 'Multiple users, read-new' => [
473 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
, 'am1_user', $complicatedUsers, false, [
475 'orconds' => [ 'actor' => "am1_actor IN ('11','12','34') " ],
479 'Multiple users, new' => [
480 SCHEMA_COMPAT_NEW
, 'am1_user', $complicatedUsers, false, [
482 'orconds' => [ 'actor' => "am1_actor IN ('11','12','34') " ],
490 * @dataProvider provideInsertRoundTrip
491 * @param string $table
494 * @param bool $usesTemp
496 public function testInsertRoundTrip( $table, $key, $pk, $usesTemp ) {
497 $u = $this->getTestUser()->getUser();
498 $user = $this->getMock( UserIdentity
::class );
499 $user->method( 'getId' )->willReturn( $u->getId() );
500 $user->method( 'getName' )->willReturn( $u->getName() );
501 $user->method( 'getActorId' )->willReturn( $u->getActorId( $this->db
) );
504 SCHEMA_COMPAT_OLD
=> 'old',
505 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
=> 'write-both-read-old',
506 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
=> 'write-both-read-new',
507 SCHEMA_COMPAT_NEW
=> 'new',
511 SCHEMA_COMPAT_OLD
=> [
513 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
,
515 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
=> [
517 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
,
518 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
,
521 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
=> [
523 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
,
524 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
,
527 SCHEMA_COMPAT_NEW
=> [
528 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
,
533 $nameKey = $key . '_text';
534 $actorKey = ( $key === 'am3_xxx' ?
$key : substr( $key, 0, -5 ) ) . '_actor';
536 foreach ( $stages as $writeStage => $possibleReadStages ) {
537 $w = new ActorMigration( $writeStage );
540 list( $fields, $callback ) = $w->getInsertValuesWithTempTable( $this->db
, $key, $user );
542 $fields = $w->getInsertValues( $this->db
, $key, $user );
545 if ( $writeStage & SCHEMA_COMPAT_WRITE_OLD
) {
546 $this->assertSame( $user->getId(), $fields[$key],
547 "old field, stage={$stageNames[$writeStage]}" );
548 $this->assertSame( $user->getName(), $fields[$nameKey],
549 "old field, stage={$stageNames[$writeStage]}" );
551 $this->assertArrayNotHasKey( $key, $fields, "old field, stage={$stageNames[$writeStage]}" );
552 $this->assertArrayNotHasKey( $nameKey, $fields, "old field, stage={$stageNames[$writeStage]}" );
554 if ( ( $writeStage & SCHEMA_COMPAT_WRITE_NEW
) && !$usesTemp ) {
555 $this->assertSame( $user->getActorId(), $fields[$actorKey],
556 "new field, stage={$stageNames[$writeStage]}" );
558 $this->assertArrayNotHasKey( $actorKey, $fields,
559 "new field, stage={$stageNames[$writeStage]}" );
563 $this->db
->insert( $table, [ $pk => $id ] +
$fields, __METHOD__
);
565 $callback( $id, [] );
568 foreach ( $possibleReadStages as $readStage ) {
569 $r = new ActorMigration( $readStage );
571 $queryInfo = $r->getJoin( $key );
572 $row = $this->db
->selectRow(
573 [ $table ] +
$queryInfo['tables'],
574 $queryInfo['fields'],
581 $this->assertSame( $user->getId(), (int)$row->$key,
582 "w={$stageNames[$writeStage]}, r={$stageNames[$readStage]}, id" );
583 $this->assertSame( $user->getName(), $row->$nameKey,
584 "w={$stageNames[$writeStage]}, r={$stageNames[$readStage]}, name" );
586 ( $readStage & SCHEMA_COMPAT_READ_OLD
) ?
0 : $user->getActorId(),
587 (int)$row->$actorKey,
588 "w={$stageNames[$writeStage]}, r={$stageNames[$readStage]}, actor"
594 public static function provideInsertRoundTrip() {
596 'normal' => [ 'actormigration1', 'am1_user', 'am1_id', false ],
597 'temp table' => [ 'actormigration2', 'am2_user', 'am2_id', true ],
598 'special name' => [ 'actormigration3', 'am3_xxx', 'am3_id', false ],
602 public static function provideStages() {
604 'old' => [ SCHEMA_COMPAT_OLD
],
605 'read-old' => [ SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
],
606 'read-new' => [ SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
],
607 'new' => [ SCHEMA_COMPAT_NEW
],
612 * @dataProvider provideStages
614 * @expectedException InvalidArgumentException
615 * @expectedExceptionMessage Must use getInsertValuesWithTempTable() for am2_user
617 public function testInsertWrong( $stage ) {
618 $m = new ActorMigration( $stage );
619 $m->getInsertValues( $this->db
, 'am2_user', $this->getTestUser()->getUser() );
623 * @dataProvider provideStages
625 * @expectedException InvalidArgumentException
626 * @expectedExceptionMessage Must use getInsertValues() for am1_user
628 public function testInsertWithTempTableWrong( $stage ) {
629 $m = new ActorMigration( $stage );
630 $m->getInsertValuesWithTempTable( $this->db
, 'am1_user', $this->getTestUser()->getUser() );
634 * @dataProvider provideStages
637 public function testInsertWithTempTableDeprecated( $stage ) {
638 $wrap = TestingAccessWrapper
::newFromClass( ActorMigration
::class );
639 $wrap->formerTempTables +
= [ 'am1_user' => '1.30' ];
641 $this->hideDeprecated( 'ActorMigration::getInsertValuesWithTempTable for am1_user' );
642 $m = new ActorMigration( $stage );
643 list( $fields, $callback )
644 = $m->getInsertValuesWithTempTable( $this->db
, 'am1_user', $this->getTestUser()->getUser() );
645 $this->assertTrue( is_callable( $callback ) );
649 * @dataProvider provideStages
651 * @expectedException InvalidArgumentException
652 * @expectedExceptionMessage $extra[foo_timestamp] is not provided
654 public function testInsertWithTempTableCallbackMissingFields( $stage ) {
655 $w = TestingAccessWrapper
::newFromClass( ActorMigration
::class );
658 'table' => 'foo_temp',
660 'field' => 'footmp_actor',
661 'joinPK' => 'foo_id',
662 'extra' => [ 'footmp_timestamp' => 'foo_timestamp' ],
666 $m = new ActorMigration( $stage );
667 list( $fields, $callback )
668 = $m->getInsertValuesWithTempTable( $this->db
, 'foo_user', $this->getTestUser()->getUser() );
673 * @dataProvider provideStages
676 public function testInsertUserIdentity( $stage ) {
677 $user = $this->getMutableTestUser()->getUser();
678 $userIdentity = $this->getMock( UserIdentity
::class );
679 $userIdentity->method( 'getId' )->willReturn( $user->getId() );
680 $userIdentity->method( 'getName' )->willReturn( $user->getName() );
681 $userIdentity->method( 'getActorId' )->willReturn( 0 );
683 $m = new ActorMigration( $stage );
684 list( $fields, $callback ) =
685 $m->getInsertValuesWithTempTable( $this->db
, 'am2_user', $userIdentity );
687 $this->db
->insert( 'actormigration2', [ 'am2_id' => $id ] +
$fields, __METHOD__
);
688 $callback( $id, [] );
690 $qi = $m->getJoin( 'am2_user' );
691 $row = $this->db
->selectRow(
692 [ 'actormigration2' ] +
$qi['tables'],
699 $this->assertSame( $user->getId(), (int)$row->am2_user
);
700 $this->assertSame( $user->getName(), $row->am2_user_text
);
702 ( $stage & SCHEMA_COMPAT_READ_NEW
) ?
$user->getActorId() : 0,
706 $m = new ActorMigration( $stage );
707 $fields = $m->getInsertValues( $this->db
, 'dummy_user', $userIdentity );
708 if ( $stage & SCHEMA_COMPAT_WRITE_OLD
) {
709 $this->assertSame( $user->getId(), $fields['dummy_user'] );
710 $this->assertSame( $user->getName(), $fields['dummy_user_text'] );
712 $this->assertArrayNotHasKey( 'dummy_user', $fields );
713 $this->assertArrayNotHasKey( 'dummy_user_text', $fields );
715 if ( $stage & SCHEMA_COMPAT_WRITE_NEW
) {
716 $this->assertSame( $user->getActorId(), $fields['dummy_actor'] );
718 $this->assertArrayNotHasKey( 'dummy_actor', $fields );
722 public function testNewMigration() {
723 $m = ActorMigration
::newMigration();
724 $this->assertInstanceOf( ActorMigration
::class, $m );
725 $this->assertSame( $m, ActorMigration
::newMigration() );
729 * @dataProvider provideIsAnon
731 * @param string $isAnon
732 * @param string $isNotAnon
734 public function testIsAnon( $stage, $isAnon, $isNotAnon ) {
735 $m = new ActorMigration( $stage );
736 $this->assertSame( $isAnon, $m->isAnon( 'foo' ) );
737 $this->assertSame( $isNotAnon, $m->isNotAnon( 'foo' ) );
740 public static function provideIsAnon() {
742 'old' => [ SCHEMA_COMPAT_OLD
, 'foo = 0', 'foo != 0' ],
743 'read-old' => [ SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
, 'foo = 0', 'foo != 0' ],
745 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
, 'foo IS NULL', 'foo IS NOT NULL'
747 'new' => [ SCHEMA_COMPAT_NEW
, 'foo IS NULL', 'foo IS NOT NULL' ],
751 public function testCheckDeprecation() {
752 $wrap = TestingAccessWrapper
::newFromClass( ActorMigration
::class );
753 $wrap->deprecated +
= [ 'soft' => null, 'hard' => '1.34' ];
754 $wrap->removed +
= [ 'gone' => '1.34' ];
756 $this->hideDeprecated( 'ActorMigration for \'hard\'' );
758 $wrap->checkDeprecation( 'valid' );
759 $wrap->checkDeprecation( 'soft' );
760 $wrap->checkDeprecation( 'hard' );
762 $wrap->checkDeprecation( 'gone' );
763 } catch ( InvalidArgumentException
$ex ) {
765 'Use of ActorMigration for \'gone\' was removed in MediaWiki 1.34',