3 use MediaWiki\User\UserIdentity
;
4 use MediaWiki\MediaWikiServices
;
5 use Wikimedia\TestingAccessWrapper
;
9 * @covers ActorMigration
11 class ActorMigrationTest
extends MediaWikiLangTestCase
{
13 protected $tablesUsed = [
15 'revision_actor_temp',
22 * @dataProvider provideConstructor
24 * @param string|null $exceptionMsg
26 public function testConstructor( $stage, $exceptionMsg ) {
28 $m = new ActorMigration( $stage );
29 if ( $exceptionMsg !== null ) {
30 $this->fail( 'Expected exception not thrown' );
32 $this->assertInstanceOf( ActorMigration
::class, $m );
33 } catch ( InvalidArgumentException
$ex ) {
34 $this->assertSame( $exceptionMsg, $ex->getMessage() );
38 public static function provideConstructor() {
40 [ 0, '$stage must include a write mode' ],
41 [ SCHEMA_COMPAT_READ_OLD
, '$stage must include a write mode' ],
42 [ SCHEMA_COMPAT_READ_NEW
, '$stage must include a write mode' ],
43 [ SCHEMA_COMPAT_READ_BOTH
, '$stage must include a write mode' ],
45 [ SCHEMA_COMPAT_WRITE_OLD
, '$stage must include a read mode' ],
46 [ SCHEMA_COMPAT_WRITE_OLD | SCHEMA_COMPAT_READ_OLD
, null ],
48 SCHEMA_COMPAT_WRITE_OLD | SCHEMA_COMPAT_READ_NEW
,
49 'Cannot read the new schema without also writing it'
51 [ SCHEMA_COMPAT_WRITE_OLD | SCHEMA_COMPAT_READ_BOTH
, 'Cannot read both schemas' ],
53 [ SCHEMA_COMPAT_WRITE_NEW
, '$stage must include a read mode' ],
55 SCHEMA_COMPAT_WRITE_NEW | SCHEMA_COMPAT_READ_OLD
,
56 'Cannot read the old schema without also writing it'
58 [ SCHEMA_COMPAT_WRITE_NEW | SCHEMA_COMPAT_READ_NEW
, null ],
59 [ SCHEMA_COMPAT_WRITE_NEW | SCHEMA_COMPAT_READ_BOTH
, 'Cannot read both schemas' ],
61 [ SCHEMA_COMPAT_WRITE_BOTH
, '$stage must include a read mode' ],
62 [ SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
, null ],
63 [ SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
, null ],
64 [ SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_BOTH
, 'Cannot read both schemas' ],
69 * @dataProvider provideGetJoin
72 * @param array $expect
74 public function testGetJoin( $stage, $key, $expect ) {
75 $m = new ActorMigration( $stage );
76 $result = $m->getJoin( $key );
77 $this->assertEquals( $expect, $result );
80 public static function provideGetJoin() {
82 'Simple table, old' => [
83 SCHEMA_COMPAT_OLD
, 'rc_user', [
86 'rc_user' => 'rc_user',
87 'rc_user_text' => 'rc_user_text',
93 'Simple table, read-old' => [
94 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
, 'rc_user', [
97 'rc_user' => 'rc_user',
98 'rc_user_text' => 'rc_user_text',
104 'Simple table, read-new' => [
105 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
, 'rc_user', [
106 'tables' => [ 'actor_rc_user' => 'actor' ],
108 'rc_user' => 'actor_rc_user.actor_user',
109 'rc_user_text' => 'actor_rc_user.actor_name',
110 'rc_actor' => 'rc_actor',
113 'actor_rc_user' => [ 'JOIN', 'actor_rc_user.actor_id = rc_actor' ],
117 'Simple table, new' => [
118 SCHEMA_COMPAT_NEW
, 'rc_user', [
119 'tables' => [ 'actor_rc_user' => 'actor' ],
121 'rc_user' => 'actor_rc_user.actor_user',
122 'rc_user_text' => 'actor_rc_user.actor_name',
123 'rc_actor' => 'rc_actor',
126 'actor_rc_user' => [ 'JOIN', 'actor_rc_user.actor_id = rc_actor' ],
132 SCHEMA_COMPAT_OLD
, 'ipb_by', [
135 'ipb_by' => 'ipb_by',
136 'ipb_by_text' => 'ipb_by_text',
137 'ipb_by_actor' => 'NULL',
142 'ipblocks, read-old' => [
143 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
, 'ipb_by', [
146 'ipb_by' => 'ipb_by',
147 'ipb_by_text' => 'ipb_by_text',
148 'ipb_by_actor' => 'NULL',
153 'ipblocks, read-new' => [
154 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
, 'ipb_by', [
155 'tables' => [ 'actor_ipb_by' => 'actor' ],
157 'ipb_by' => 'actor_ipb_by.actor_user',
158 'ipb_by_text' => 'actor_ipb_by.actor_name',
159 'ipb_by_actor' => 'ipb_by_actor',
162 'actor_ipb_by' => [ 'JOIN', 'actor_ipb_by.actor_id = ipb_by_actor' ],
167 SCHEMA_COMPAT_NEW
, 'ipb_by', [
168 'tables' => [ 'actor_ipb_by' => 'actor' ],
170 'ipb_by' => 'actor_ipb_by.actor_user',
171 'ipb_by_text' => 'actor_ipb_by.actor_name',
172 'ipb_by_actor' => 'ipb_by_actor',
175 'actor_ipb_by' => [ 'JOIN', 'actor_ipb_by.actor_id = ipb_by_actor' ],
181 SCHEMA_COMPAT_OLD
, 'rev_user', [
184 'rev_user' => 'rev_user',
185 'rev_user_text' => 'rev_user_text',
186 'rev_actor' => 'NULL',
191 'Revision, read-old' => [
192 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
, 'rev_user', [
195 'rev_user' => 'rev_user',
196 'rev_user_text' => 'rev_user_text',
197 'rev_actor' => 'NULL',
202 'Revision, read-new' => [
203 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
, 'rev_user', [
205 'temp_rev_user' => 'revision_actor_temp',
206 'actor_rev_user' => 'actor',
209 'rev_user' => 'actor_rev_user.actor_user',
210 'rev_user_text' => 'actor_rev_user.actor_name',
211 'rev_actor' => 'temp_rev_user.revactor_actor',
214 'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
215 'actor_rev_user' => [ 'JOIN', 'actor_rev_user.actor_id = temp_rev_user.revactor_actor' ],
220 SCHEMA_COMPAT_NEW
, 'rev_user', [
222 'temp_rev_user' => 'revision_actor_temp',
223 'actor_rev_user' => 'actor',
226 'rev_user' => 'actor_rev_user.actor_user',
227 'rev_user_text' => 'actor_rev_user.actor_name',
228 'rev_actor' => 'temp_rev_user.revactor_actor',
231 'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
232 'actor_rev_user' => [ 'JOIN', 'actor_rev_user.actor_id = temp_rev_user.revactor_actor' ],
240 * @dataProvider provideGetWhere
243 * @param UserIdentity[] $users
245 * @param array $expect
247 public function testGetWhere( $stage, $key, $users, $useId, $expect ) {
248 $expect['conds'] = '(' . implode( ') OR (', $expect['orconds'] ) . ')';
250 if ( count( $users ) === 1 ) {
251 $users = reset( $users );
254 $m = new ActorMigration( $stage );
255 $result = $m->getWhere( $this->db
, $key, $users, $useId );
256 $this->assertEquals( $expect, $result );
259 public function provideGetWhere() {
260 $makeUserIdentity = function ( $id, $name, $actor ) {
261 $u = $this->getMock( UserIdentity
::class );
262 $u->method( 'getId' )->willReturn( $id );
263 $u->method( 'getName' )->willReturn( $name );
264 $u->method( 'getActorId' )->willReturn( $actor );
268 $genericUser = [ $makeUserIdentity( 1, 'User1', 11 ) ];
269 $complicatedUsers = [
270 $makeUserIdentity( 1, 'User1', 11 ),
271 $makeUserIdentity( 2, 'User2', 12 ),
272 $makeUserIdentity( 3, 'User3', 0 ),
273 $makeUserIdentity( 0, '192.168.12.34', 34 ),
274 $makeUserIdentity( 0, '192.168.12.35', 0 ),
278 'Simple table, old' => [
279 SCHEMA_COMPAT_OLD
, 'rc_user', $genericUser, true, [
281 'orconds' => [ 'userid' => "rc_user = '1'" ],
285 'Simple table, read-old' => [
286 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
, 'rc_user', $genericUser, true, [
288 'orconds' => [ 'userid' => "rc_user = '1'" ],
292 'Simple table, read-new' => [
293 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
, 'rc_user', $genericUser, true, [
295 'orconds' => [ 'actor' => "rc_actor = '11'" ],
299 'Simple table, new' => [
300 SCHEMA_COMPAT_NEW
, 'rc_user', $genericUser, true, [
302 'orconds' => [ 'actor' => "rc_actor = '11'" ],
308 SCHEMA_COMPAT_OLD
, 'ipb_by', $genericUser, true, [
310 'orconds' => [ 'userid' => "ipb_by = '1'" ],
314 'ipblocks, read-old' => [
315 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
, 'ipb_by', $genericUser, true, [
317 'orconds' => [ 'userid' => "ipb_by = '1'" ],
321 'ipblocks, read-new' => [
322 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
, 'ipb_by', $genericUser, true, [
324 'orconds' => [ 'actor' => "ipb_by_actor = '11'" ],
329 SCHEMA_COMPAT_NEW
, 'ipb_by', $genericUser, true, [
331 'orconds' => [ 'actor' => "ipb_by_actor = '11'" ],
337 SCHEMA_COMPAT_OLD
, 'rev_user', $genericUser, true, [
339 'orconds' => [ 'userid' => "rev_user = '1'" ],
343 'Revision, read-old' => [
344 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
, 'rev_user', $genericUser, true, [
346 'orconds' => [ 'userid' => "rev_user = '1'" ],
350 'Revision, read-new' => [
351 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
, 'rev_user', $genericUser, true, [
353 'temp_rev_user' => 'revision_actor_temp',
355 'orconds' => [ 'actor' => "temp_rev_user.revactor_actor = '11'" ],
357 'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
362 SCHEMA_COMPAT_NEW
, 'rev_user', $genericUser, true, [
364 'temp_rev_user' => 'revision_actor_temp',
366 'orconds' => [ 'actor' => "temp_rev_user.revactor_actor = '11'" ],
368 'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
373 'Multiple users, old' => [
374 SCHEMA_COMPAT_OLD
, 'rc_user', $complicatedUsers, true, [
377 'userid' => "rc_user IN ('1','2','3') ",
378 'username' => "rc_user_text IN ('192.168.12.34','192.168.12.35') "
383 'Multiple users, read-old' => [
384 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
, 'rc_user', $complicatedUsers, true, [
387 'userid' => "rc_user IN ('1','2','3') ",
388 'username' => "rc_user_text IN ('192.168.12.34','192.168.12.35') "
393 'Multiple users, read-new' => [
394 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
, 'rc_user', $complicatedUsers, true, [
396 'orconds' => [ 'actor' => "rc_actor IN ('11','12','34') " ],
400 'Multiple users, new' => [
401 SCHEMA_COMPAT_NEW
, 'rc_user', $complicatedUsers, true, [
403 'orconds' => [ 'actor' => "rc_actor IN ('11','12','34') " ],
408 'Multiple users, no use ID, old' => [
409 SCHEMA_COMPAT_OLD
, 'rc_user', $complicatedUsers, false, [
412 'username' => "rc_user_text IN ('User1','User2','User3','192.168.12.34','192.168.12.35') "
417 'Multiple users, read-old' => [
418 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
, 'rc_user', $complicatedUsers, false, [
421 'username' => "rc_user_text IN ('User1','User2','User3','192.168.12.34','192.168.12.35') "
426 'Multiple users, read-new' => [
427 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
, 'rc_user', $complicatedUsers, false, [
429 'orconds' => [ 'actor' => "rc_actor IN ('11','12','34') " ],
433 'Multiple users, new' => [
434 SCHEMA_COMPAT_NEW
, 'rc_user', $complicatedUsers, false, [
436 'orconds' => [ 'actor' => "rc_actor IN ('11','12','34') " ],
444 * @dataProvider provideInsertRoundTrip
445 * @param string $table
448 * @param array $extraFields
450 public function testInsertRoundTrip( $table, $key, $pk, $extraFields ) {
451 $u = $this->getTestUser()->getUser();
452 $user = $this->getMock( UserIdentity
::class );
453 $user->method( 'getId' )->willReturn( $u->getId() );
454 $user->method( 'getName' )->willReturn( $u->getName() );
455 if ( $u->getActorId( $this->db
) ) {
456 $user->method( 'getActorId' )->willReturn( $u->getActorId() );
460 [ 'actor_user' => $u->getId(), 'actor_name' => $u->getName() ],
463 $user->method( 'getActorId' )->willReturn( $this->db
->insertId() );
467 SCHEMA_COMPAT_OLD
=> 'old',
468 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
=> 'write-both-read-old',
469 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
=> 'write-both-read-new',
470 SCHEMA_COMPAT_NEW
=> 'new',
474 SCHEMA_COMPAT_OLD
=> [
476 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
,
478 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
=> [
480 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
,
481 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
,
484 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
=> [
486 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
,
487 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
,
490 SCHEMA_COMPAT_NEW
=> [
491 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
,
496 $nameKey = $key . '_text';
497 $actorKey = $key === 'ipb_by' ?
'ipb_by_actor' : substr( $key, 0, -5 ) . '_actor';
499 foreach ( $stages as $writeStage => $possibleReadStages ) {
500 if ( $key === 'ipb_by' ) {
501 $extraFields['ipb_address'] = __CLASS__
. "#{$stageNames[$writeStage]}";
504 $w = new ActorMigration( $writeStage );
505 $usesTemp = $key === 'rev_user';
508 list( $fields, $callback ) = $w->getInsertValuesWithTempTable( $this->db
, $key, $user );
510 $fields = $w->getInsertValues( $this->db
, $key, $user );
513 if ( $writeStage & SCHEMA_COMPAT_WRITE_OLD
) {
514 $this->assertSame( $user->getId(), $fields[$key],
515 "old field, stage={$stageNames[$writeStage]}" );
516 $this->assertSame( $user->getName(), $fields[$nameKey],
517 "old field, stage={$stageNames[$writeStage]}" );
519 $this->assertArrayNotHasKey( $key, $fields, "old field, stage={$stageNames[$writeStage]}" );
520 $this->assertArrayNotHasKey( $nameKey, $fields, "old field, stage={$stageNames[$writeStage]}" );
522 if ( ( $writeStage & SCHEMA_COMPAT_WRITE_NEW
) && !$usesTemp ) {
523 $this->assertSame( $user->getActorId(), $fields[$actorKey],
524 "new field, stage={$stageNames[$writeStage]}" );
526 $this->assertArrayNotHasKey( $actorKey, $fields,
527 "new field, stage={$stageNames[$writeStage]}" );
530 $this->db
->insert( $table, $extraFields +
$fields, __METHOD__
);
531 $id = $this->db
->insertId();
533 $callback( $id, $extraFields );
536 foreach ( $possibleReadStages as $readStage ) {
537 $r = new ActorMigration( $readStage );
539 $queryInfo = $r->getJoin( $key );
540 $row = $this->db
->selectRow(
541 [ $table ] +
$queryInfo['tables'],
542 $queryInfo['fields'],
549 $this->assertSame( $user->getId(), (int)$row->$key,
550 "w={$stageNames[$writeStage]}, r={$stageNames[$readStage]}, id" );
551 $this->assertSame( $user->getName(), $row->$nameKey,
552 "w={$stageNames[$writeStage]}, r={$stageNames[$readStage]}, name" );
554 ( $readStage & SCHEMA_COMPAT_READ_OLD
) ?
0 : $user->getActorId(),
555 (int)$row->$actorKey,
556 "w={$stageNames[$writeStage]}, r={$stageNames[$readStage]}, actor"
562 public static function provideInsertRoundTrip() {
563 $db = wfGetDB( DB_REPLICA
); // for timestamps
565 $comment = MediaWikiServices
::getInstance()->getCommentStore()
566 ->createComment( wfGetDB( DB_MASTER
), '' );
569 'recentchanges' => [ 'recentchanges', 'rc_user', 'rc_id', [
570 'rc_timestamp' => $db->timestamp(),
572 'rc_title' => 'Test',
573 'rc_this_oldid' => 42,
574 'rc_last_oldid' => 41,
575 'rc_source' => 'test',
576 'rc_comment_id' => $comment->id
,
578 'ipblocks' => [ 'ipblocks', 'ipb_by', 'ipb_id', [
579 'ipb_range_start' => '',
580 'ipb_range_end' => '',
581 'ipb_timestamp' => $db->timestamp(),
582 'ipb_expiry' => $db->getInfinity(),
583 'ipb_reason_id' => $comment->id
,
585 'revision' => [ 'revision', 'rev_user', 'rev_id', [
588 'rev_timestamp' => $db->timestamp(),
593 public static function provideStages() {
595 'old' => [ SCHEMA_COMPAT_OLD
],
596 'read-old' => [ SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
],
597 'read-new' => [ SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
],
598 'new' => [ SCHEMA_COMPAT_NEW
],
603 * @dataProvider provideStages
605 * @expectedException InvalidArgumentException
606 * @expectedExceptionMessage Must use getInsertValuesWithTempTable() for rev_user
608 public function testInsertWrong( $stage ) {
609 $m = new ActorMigration( $stage );
610 $m->getInsertValues( $this->db
, 'rev_user', $this->getTestUser()->getUser() );
614 * @dataProvider provideStages
616 * @expectedException InvalidArgumentException
617 * @expectedExceptionMessage Must use getInsertValues() for rc_user
619 public function testInsertWithTempTableWrong( $stage ) {
620 $m = new ActorMigration( $stage );
621 $m->getInsertValuesWithTempTable( $this->db
, 'rc_user', $this->getTestUser()->getUser() );
625 * @dataProvider provideStages
628 public function testInsertWithTempTableDeprecated( $stage ) {
629 $wrap = TestingAccessWrapper
::newFromClass( ActorMigration
::class );
630 $wrap->formerTempTables +
= [ 'rc_user' => '1.30' ];
632 $this->hideDeprecated( 'ActorMigration::getInsertValuesWithTempTable for rc_user' );
633 $m = new ActorMigration( $stage );
634 list( $fields, $callback )
635 = $m->getInsertValuesWithTempTable( $this->db
, 'rc_user', $this->getTestUser()->getUser() );
636 $this->assertTrue( is_callable( $callback ) );
640 * @dataProvider provideStages
642 * @expectedException InvalidArgumentException
643 * @expectedExceptionMessage $extra[rev_timestamp] is not provided
645 public function testInsertWithTempTableCallbackMissingFields( $stage ) {
646 $m = new ActorMigration( $stage );
647 list( $fields, $callback )
648 = $m->getInsertValuesWithTempTable( $this->db
, 'rev_user', $this->getTestUser()->getUser() );
653 * @dataProvider provideStages
656 public function testInsertUserIdentity( $stage ) {
657 $this->setMwGlobals( [
658 // for User::getActorId()
659 'wgActorTableSchemaMigrationStage' => $stage
661 $this->overrideMwServices();
663 $user = $this->getMutableTestUser()->getUser();
664 $userIdentity = $this->getMock( UserIdentity
::class );
665 $userIdentity->method( 'getId' )->willReturn( $user->getId() );
666 $userIdentity->method( 'getName' )->willReturn( $user->getName() );
667 $userIdentity->method( 'getActorId' )->willReturn( 0 );
669 list( $cFields, $cCallback ) = MediaWikiServices
::getInstance()->getCommentStore()
670 ->insertWithTempTable( $this->db
, 'rev_comment', '' );
671 $m = new ActorMigration( $stage );
672 list( $fields, $callback ) =
673 $m->getInsertValuesWithTempTable( $this->db
, 'rev_user', $userIdentity );
677 'rev_timestamp' => $this->db
->timestamp(),
679 $this->db
->insert( 'revision', $extraFields +
$fields, __METHOD__
);
680 $id = $this->db
->insertId();
681 $callback( $id, $extraFields );
684 $qi = $m->getJoin( 'rev_user' );
685 $row = $this->db
->selectRow(
686 [ 'revision' ] +
$qi['tables'], $qi['fields'], [ 'rev_id' => $id ], __METHOD__
, [], $qi['joins']
688 $this->assertSame( $user->getId(), (int)$row->rev_user
);
689 $this->assertSame( $user->getName(), $row->rev_user_text
);
691 ( $stage & SCHEMA_COMPAT_READ_NEW
) ?
$user->getActorId() : 0,
695 $m = new ActorMigration( $stage );
696 $fields = $m->getInsertValues( $this->db
, 'dummy_user', $userIdentity );
697 if ( $stage & SCHEMA_COMPAT_WRITE_OLD
) {
698 $this->assertSame( $user->getId(), $fields['dummy_user'] );
699 $this->assertSame( $user->getName(), $fields['dummy_user_text'] );
701 $this->assertArrayNotHasKey( 'dummy_user', $fields );
702 $this->assertArrayNotHasKey( 'dummy_user_text', $fields );
704 if ( $stage & SCHEMA_COMPAT_WRITE_NEW
) {
705 $this->assertSame( $user->getActorId(), $fields['dummy_actor'] );
707 $this->assertArrayNotHasKey( 'dummy_actor', $fields );
711 public function testNewMigration() {
712 $m = ActorMigration
::newMigration();
713 $this->assertInstanceOf( ActorMigration
::class, $m );
714 $this->assertSame( $m, ActorMigration
::newMigration() );
718 * @dataProvider provideIsAnon
720 * @param string $isAnon
721 * @param string $isNotAnon
723 public function testIsAnon( $stage, $isAnon, $isNotAnon ) {
724 $m = new ActorMigration( $stage );
725 $this->assertSame( $isAnon, $m->isAnon( 'foo' ) );
726 $this->assertSame( $isNotAnon, $m->isNotAnon( 'foo' ) );
729 public static function provideIsAnon() {
731 'old' => [ SCHEMA_COMPAT_OLD
, 'foo = 0', 'foo != 0' ],
732 'read-old' => [ SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
, 'foo = 0', 'foo != 0' ],
734 SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
, 'foo IS NULL', 'foo IS NOT NULL'
736 'new' => [ SCHEMA_COMPAT_NEW
, 'foo IS NULL', 'foo IS NOT NULL' ],