c9387507c2ba35ee16388cb4974e9d4c45c79aea
[lhc/web/wiklou.git] / tests / phpunit / includes / ActorMigrationTest.php
1 <?php
2
3 use MediaWiki\User\UserIdentity;
4 use MediaWiki\MediaWikiServices;
5 use Wikimedia\TestingAccessWrapper;
6
7 /**
8 * @group Database
9 * @covers ActorMigration
10 */
11 class ActorMigrationTest extends MediaWikiLangTestCase {
12
13 protected $tablesUsed = [
14 'revision',
15 'revision_actor_temp',
16 'ipblocks',
17 'recentchanges',
18 'actor',
19 ];
20
21 /**
22 * Create an ActorMigration for a particular stage
23 * @param int $stage
24 * @return ActorMigration
25 */
26 protected function makeMigration( $stage ) {
27 return new ActorMigration( $stage );
28 }
29
30 /**
31 * @dataProvider provideGetJoin
32 * @param int $stage
33 * @param string $key
34 * @param array $expect
35 */
36 public function testGetJoin( $stage, $key, $expect ) {
37 $m = $this->makeMigration( $stage );
38 $result = $m->getJoin( $key );
39 $this->assertEquals( $expect, $result );
40 }
41
42 public static function provideGetJoin() {
43 return [
44 'Simple table, old' => [
45 MIGRATION_OLD, 'rc_user', [
46 'tables' => [],
47 'fields' => [
48 'rc_user' => 'rc_user',
49 'rc_user_text' => 'rc_user_text',
50 'rc_actor' => 'NULL',
51 ],
52 'joins' => [],
53 ],
54 ],
55 'Simple table, write-both' => [
56 MIGRATION_WRITE_BOTH, 'rc_user', [
57 'tables' => [ 'actor_rc_user' => 'actor' ],
58 'fields' => [
59 'rc_user' => 'COALESCE( actor_rc_user.actor_user, rc_user )',
60 'rc_user_text' => 'COALESCE( actor_rc_user.actor_name, rc_user_text )',
61 'rc_actor' => 'rc_actor',
62 ],
63 'joins' => [
64 'actor_rc_user' => [ 'LEFT JOIN', 'actor_rc_user.actor_id = rc_actor' ],
65 ],
66 ],
67 ],
68 'Simple table, write-new' => [
69 MIGRATION_WRITE_NEW, 'rc_user', [
70 'tables' => [ 'actor_rc_user' => 'actor' ],
71 'fields' => [
72 'rc_user' => 'COALESCE( actor_rc_user.actor_user, rc_user )',
73 'rc_user_text' => 'COALESCE( actor_rc_user.actor_name, rc_user_text )',
74 'rc_actor' => 'rc_actor',
75 ],
76 'joins' => [
77 'actor_rc_user' => [ 'LEFT JOIN', 'actor_rc_user.actor_id = rc_actor' ],
78 ],
79 ],
80 ],
81 'Simple table, new' => [
82 MIGRATION_NEW, 'rc_user', [
83 'tables' => [ 'actor_rc_user' => 'actor' ],
84 'fields' => [
85 'rc_user' => 'actor_rc_user.actor_user',
86 'rc_user_text' => 'actor_rc_user.actor_name',
87 'rc_actor' => 'rc_actor',
88 ],
89 'joins' => [
90 'actor_rc_user' => [ 'JOIN', 'actor_rc_user.actor_id = rc_actor' ],
91 ],
92 ],
93 ],
94
95 'ipblocks, old' => [
96 MIGRATION_OLD, 'ipb_by', [
97 'tables' => [],
98 'fields' => [
99 'ipb_by' => 'ipb_by',
100 'ipb_by_text' => 'ipb_by_text',
101 'ipb_by_actor' => 'NULL',
102 ],
103 'joins' => [],
104 ],
105 ],
106 'ipblocks, write-both' => [
107 MIGRATION_WRITE_BOTH, 'ipb_by', [
108 'tables' => [ 'actor_ipb_by' => 'actor' ],
109 'fields' => [
110 'ipb_by' => 'COALESCE( actor_ipb_by.actor_user, ipb_by )',
111 'ipb_by_text' => 'COALESCE( actor_ipb_by.actor_name, ipb_by_text )',
112 'ipb_by_actor' => 'ipb_by_actor',
113 ],
114 'joins' => [
115 'actor_ipb_by' => [ 'LEFT JOIN', 'actor_ipb_by.actor_id = ipb_by_actor' ],
116 ],
117 ],
118 ],
119 'ipblocks, write-new' => [
120 MIGRATION_WRITE_NEW, 'ipb_by', [
121 'tables' => [ 'actor_ipb_by' => 'actor' ],
122 'fields' => [
123 'ipb_by' => 'COALESCE( actor_ipb_by.actor_user, ipb_by )',
124 'ipb_by_text' => 'COALESCE( actor_ipb_by.actor_name, ipb_by_text )',
125 'ipb_by_actor' => 'ipb_by_actor',
126 ],
127 'joins' => [
128 'actor_ipb_by' => [ 'LEFT JOIN', 'actor_ipb_by.actor_id = ipb_by_actor' ],
129 ],
130 ],
131 ],
132 'ipblocks, new' => [
133 MIGRATION_NEW, 'ipb_by', [
134 'tables' => [ 'actor_ipb_by' => 'actor' ],
135 'fields' => [
136 'ipb_by' => 'actor_ipb_by.actor_user',
137 'ipb_by_text' => 'actor_ipb_by.actor_name',
138 'ipb_by_actor' => 'ipb_by_actor',
139 ],
140 'joins' => [
141 'actor_ipb_by' => [ 'JOIN', 'actor_ipb_by.actor_id = ipb_by_actor' ],
142 ],
143 ],
144 ],
145
146 'Revision, old' => [
147 MIGRATION_OLD, 'rev_user', [
148 'tables' => [],
149 'fields' => [
150 'rev_user' => 'rev_user',
151 'rev_user_text' => 'rev_user_text',
152 'rev_actor' => 'NULL',
153 ],
154 'joins' => [],
155 ],
156 ],
157 'Revision, write-both' => [
158 MIGRATION_WRITE_BOTH, 'rev_user', [
159 'tables' => [
160 'temp_rev_user' => 'revision_actor_temp',
161 'actor_rev_user' => 'actor',
162 ],
163 'fields' => [
164 'rev_user' => 'COALESCE( actor_rev_user.actor_user, rev_user )',
165 'rev_user_text' => 'COALESCE( actor_rev_user.actor_name, rev_user_text )',
166 'rev_actor' => 'temp_rev_user.revactor_actor',
167 ],
168 'joins' => [
169 'temp_rev_user' => [ 'LEFT JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
170 'actor_rev_user' => [ 'LEFT JOIN', 'actor_rev_user.actor_id = temp_rev_user.revactor_actor' ],
171 ],
172 ],
173 ],
174 'Revision, write-new' => [
175 MIGRATION_WRITE_NEW, 'rev_user', [
176 'tables' => [
177 'temp_rev_user' => 'revision_actor_temp',
178 'actor_rev_user' => 'actor',
179 ],
180 'fields' => [
181 'rev_user' => 'COALESCE( actor_rev_user.actor_user, rev_user )',
182 'rev_user_text' => 'COALESCE( actor_rev_user.actor_name, rev_user_text )',
183 'rev_actor' => 'temp_rev_user.revactor_actor',
184 ],
185 'joins' => [
186 'temp_rev_user' => [ 'LEFT JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
187 'actor_rev_user' => [ 'LEFT JOIN', 'actor_rev_user.actor_id = temp_rev_user.revactor_actor' ],
188 ],
189 ],
190 ],
191 'Revision, new' => [
192 MIGRATION_NEW, 'rev_user', [
193 'tables' => [
194 'temp_rev_user' => 'revision_actor_temp',
195 'actor_rev_user' => 'actor',
196 ],
197 'fields' => [
198 'rev_user' => 'actor_rev_user.actor_user',
199 'rev_user_text' => 'actor_rev_user.actor_name',
200 'rev_actor' => 'temp_rev_user.revactor_actor',
201 ],
202 'joins' => [
203 'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
204 'actor_rev_user' => [ 'JOIN', 'actor_rev_user.actor_id = temp_rev_user.revactor_actor' ],
205 ],
206 ],
207 ],
208 ];
209 }
210
211 /**
212 * @dataProvider provideGetWhere
213 * @param int $stage
214 * @param string $key
215 * @param UserIdentity[] $users
216 * @param bool $useId
217 * @param array $expect
218 */
219 public function testGetWhere( $stage, $key, $users, $useId, $expect ) {
220 $expect['conds'] = '(' . implode( ') OR (', $expect['orconds'] ) . ')';
221
222 if ( count( $users ) === 1 ) {
223 $users = reset( $users );
224 }
225
226 $m = $this->makeMigration( $stage );
227 $result = $m->getWhere( $this->db, $key, $users, $useId );
228 $this->assertEquals( $expect, $result );
229 }
230
231 public function provideGetWhere() {
232 $makeUserIdentity = function ( $id, $name, $actor ) {
233 $u = $this->getMock( UserIdentity::class );
234 $u->method( 'getId' )->willReturn( $id );
235 $u->method( 'getName' )->willReturn( $name );
236 $u->method( 'getActorId' )->willReturn( $actor );
237 return $u;
238 };
239
240 $genericUser = [ $makeUserIdentity( 1, 'User1', 11 ) ];
241 $complicatedUsers = [
242 $makeUserIdentity( 1, 'User1', 11 ),
243 $makeUserIdentity( 2, 'User2', 12 ),
244 $makeUserIdentity( 3, 'User3', 0 ),
245 $makeUserIdentity( 0, '192.168.12.34', 34 ),
246 $makeUserIdentity( 0, '192.168.12.35', 0 ),
247 ];
248
249 return [
250 'Simple table, old' => [
251 MIGRATION_OLD, 'rc_user', $genericUser, true, [
252 'tables' => [],
253 'orconds' => [ 'userid' => "rc_user = '1'" ],
254 'joins' => [],
255 ],
256 ],
257 'Simple table, write-both' => [
258 MIGRATION_WRITE_BOTH, 'rc_user', $genericUser, true, [
259 'tables' => [],
260 'orconds' => [
261 'actor' => "rc_actor = '11'",
262 'userid' => "rc_actor = '0' AND rc_user = '1'"
263 ],
264 'joins' => [],
265 ],
266 ],
267 'Simple table, write-new' => [
268 MIGRATION_WRITE_NEW, 'rc_user', $genericUser, true, [
269 'tables' => [],
270 'orconds' => [
271 'actor' => "rc_actor = '11'",
272 'userid' => "rc_actor = '0' AND rc_user = '1'"
273 ],
274 'joins' => [],
275 ],
276 ],
277 'Simple table, new' => [
278 MIGRATION_NEW, 'rc_user', $genericUser, true, [
279 'tables' => [],
280 'orconds' => [ 'actor' => "rc_actor = '11'" ],
281 'joins' => [],
282 ],
283 ],
284
285 'ipblocks, old' => [
286 MIGRATION_OLD, 'ipb_by', $genericUser, true, [
287 'tables' => [],
288 'orconds' => [ 'userid' => "ipb_by = '1'" ],
289 'joins' => [],
290 ],
291 ],
292 'ipblocks, write-both' => [
293 MIGRATION_WRITE_BOTH, 'ipb_by', $genericUser, true, [
294 'tables' => [],
295 'orconds' => [
296 'actor' => "ipb_by_actor = '11'",
297 'userid' => "ipb_by_actor = '0' AND ipb_by = '1'"
298 ],
299 'joins' => [],
300 ],
301 ],
302 'ipblocks, write-new' => [
303 MIGRATION_WRITE_NEW, 'ipb_by', $genericUser, true, [
304 'tables' => [],
305 'orconds' => [
306 'actor' => "ipb_by_actor = '11'",
307 'userid' => "ipb_by_actor = '0' AND ipb_by = '1'"
308 ],
309 'joins' => [],
310 ],
311 ],
312 'ipblocks, new' => [
313 MIGRATION_NEW, 'ipb_by', $genericUser, true, [
314 'tables' => [],
315 'orconds' => [ 'actor' => "ipb_by_actor = '11'" ],
316 'joins' => [],
317 ],
318 ],
319
320 'Revision, old' => [
321 MIGRATION_OLD, 'rev_user', $genericUser, true, [
322 'tables' => [],
323 'orconds' => [ 'userid' => "rev_user = '1'" ],
324 'joins' => [],
325 ],
326 ],
327 'Revision, write-both' => [
328 MIGRATION_WRITE_BOTH, 'rev_user', $genericUser, true, [
329 'tables' => [
330 'temp_rev_user' => 'revision_actor_temp',
331 ],
332 'orconds' => [
333 'actor' =>
334 "(temp_rev_user.revactor_actor IS NOT NULL) AND temp_rev_user.revactor_actor = '11'",
335 'userid' => "temp_rev_user.revactor_actor IS NULL AND rev_user = '1'"
336 ],
337 'joins' => [
338 'temp_rev_user' => [ 'LEFT JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
339 ],
340 ],
341 ],
342 'Revision, write-new' => [
343 MIGRATION_WRITE_NEW, 'rev_user', $genericUser, true, [
344 'tables' => [
345 'temp_rev_user' => 'revision_actor_temp',
346 ],
347 'orconds' => [
348 'actor' =>
349 "(temp_rev_user.revactor_actor IS NOT NULL) AND temp_rev_user.revactor_actor = '11'",
350 'userid' => "temp_rev_user.revactor_actor IS NULL AND rev_user = '1'"
351 ],
352 'joins' => [
353 'temp_rev_user' => [ 'LEFT JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
354 ],
355 ],
356 ],
357 'Revision, new' => [
358 MIGRATION_NEW, 'rev_user', $genericUser, true, [
359 'tables' => [
360 'temp_rev_user' => 'revision_actor_temp',
361 ],
362 'orconds' => [ 'actor' => "temp_rev_user.revactor_actor = '11'" ],
363 'joins' => [
364 'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
365 ],
366 ],
367 ],
368
369 'Multiple users, old' => [
370 MIGRATION_OLD, 'rc_user', $complicatedUsers, true, [
371 'tables' => [],
372 'orconds' => [
373 'userid' => "rc_user IN ('1','2','3') ",
374 'username' => "rc_user_text IN ('192.168.12.34','192.168.12.35') "
375 ],
376 'joins' => [],
377 ],
378 ],
379 'Multiple users, write-both' => [
380 MIGRATION_WRITE_BOTH, 'rc_user', $complicatedUsers, true, [
381 'tables' => [],
382 'orconds' => [
383 'actor' => "rc_actor IN ('11','12','34') ",
384 'userid' => "rc_actor = '0' AND rc_user IN ('1','2','3') ",
385 'username' => "rc_actor = '0' AND rc_user_text IN ('192.168.12.34','192.168.12.35') "
386 ],
387 'joins' => [],
388 ],
389 ],
390 'Multiple users, write-new' => [
391 MIGRATION_WRITE_NEW, 'rc_user', $complicatedUsers, true, [
392 'tables' => [],
393 'orconds' => [
394 'actor' => "rc_actor IN ('11','12','34') ",
395 'userid' => "rc_actor = '0' AND rc_user IN ('1','2','3') ",
396 'username' => "rc_actor = '0' AND rc_user_text IN ('192.168.12.34','192.168.12.35') "
397 ],
398 'joins' => [],
399 ],
400 ],
401 'Multiple users, new' => [
402 MIGRATION_NEW, 'rc_user', $complicatedUsers, true, [
403 'tables' => [],
404 'orconds' => [ 'actor' => "rc_actor IN ('11','12','34') " ],
405 'joins' => [],
406 ],
407 ],
408
409 'Multiple users, no use ID, old' => [
410 MIGRATION_OLD, 'rc_user', $complicatedUsers, false, [
411 'tables' => [],
412 'orconds' => [
413 'username' => "rc_user_text IN ('User1','User2','User3','192.168.12.34','192.168.12.35') "
414 ],
415 'joins' => [],
416 ],
417 ],
418 'Multiple users, write-both' => [
419 MIGRATION_WRITE_BOTH, 'rc_user', $complicatedUsers, false, [
420 'tables' => [],
421 'orconds' => [
422 'actor' => "rc_actor IN ('11','12','34') ",
423 'username' => "rc_actor = '0' AND "
424 . "rc_user_text IN ('User1','User2','User3','192.168.12.34','192.168.12.35') "
425 ],
426 'joins' => [],
427 ],
428 ],
429 'Multiple users, write-new' => [
430 MIGRATION_WRITE_NEW, 'rc_user', $complicatedUsers, false, [
431 'tables' => [],
432 'orconds' => [
433 'actor' => "rc_actor IN ('11','12','34') ",
434 'username' => "rc_actor = '0' AND "
435 . "rc_user_text IN ('User1','User2','User3','192.168.12.34','192.168.12.35') "
436 ],
437 'joins' => [],
438 ],
439 ],
440 'Multiple users, new' => [
441 MIGRATION_NEW, 'rc_user', $complicatedUsers, false, [
442 'tables' => [],
443 'orconds' => [ 'actor' => "rc_actor IN ('11','12','34') " ],
444 'joins' => [],
445 ],
446 ],
447 ];
448 }
449
450 /**
451 * @dataProvider provideInsertRoundTrip
452 * @param string $table
453 * @param string $key
454 * @param string $pk
455 * @param array $extraFields
456 */
457 public function testInsertRoundTrip( $table, $key, $pk, $extraFields ) {
458 $u = $this->getTestUser()->getUser();
459 $user = $this->getMock( UserIdentity::class );
460 $user->method( 'getId' )->willReturn( $u->getId() );
461 $user->method( 'getName' )->willReturn( $u->getName() );
462 if ( $u->getActorId( $this->db ) ) {
463 $user->method( 'getActorId' )->willReturn( $u->getActorId() );
464 } else {
465 $this->db->insert(
466 'actor',
467 [ 'actor_user' => $u->getId(), 'actor_name' => $u->getName() ],
468 __METHOD__
469 );
470 $user->method( 'getActorId' )->willReturn( $this->db->insertId() );
471 }
472
473 $stages = [
474 MIGRATION_OLD => [ MIGRATION_OLD, MIGRATION_WRITE_BOTH, MIGRATION_WRITE_NEW ],
475 MIGRATION_WRITE_BOTH => [ MIGRATION_OLD, MIGRATION_WRITE_BOTH, MIGRATION_WRITE_NEW,
476 MIGRATION_NEW ],
477 MIGRATION_WRITE_NEW => [ MIGRATION_WRITE_BOTH, MIGRATION_WRITE_NEW, MIGRATION_NEW ],
478 MIGRATION_NEW => [ MIGRATION_WRITE_BOTH, MIGRATION_WRITE_NEW, MIGRATION_NEW ],
479 ];
480
481 $nameKey = $key . '_text';
482 $actorKey = $key === 'ipb_by' ? 'ipb_by_actor' : substr( $key, 0, -5 ) . '_actor';
483
484 foreach ( $stages as $writeStage => $possibleReadStages ) {
485 if ( $key === 'ipb_by' ) {
486 $extraFields['ipb_address'] = __CLASS__ . "#$writeStage";
487 }
488
489 $w = $this->makeMigration( $writeStage );
490 $usesTemp = $key === 'rev_user';
491
492 if ( $usesTemp ) {
493 list( $fields, $callback ) = $w->getInsertValuesWithTempTable( $this->db, $key, $user );
494 } else {
495 $fields = $w->getInsertValues( $this->db, $key, $user );
496 }
497
498 if ( $writeStage <= MIGRATION_WRITE_BOTH ) {
499 $this->assertSame( $user->getId(), $fields[$key], "old field, stage=$writeStage" );
500 $this->assertSame( $user->getName(), $fields[$nameKey], "old field, stage=$writeStage" );
501 } else {
502 $this->assertArrayNotHasKey( $key, $fields, "old field, stage=$writeStage" );
503 $this->assertArrayNotHasKey( $nameKey, $fields, "old field, stage=$writeStage" );
504 }
505 if ( $writeStage >= MIGRATION_WRITE_BOTH && !$usesTemp ) {
506 $this->assertSame( $user->getActorId(), $fields[$actorKey], "new field, stage=$writeStage" );
507 } else {
508 $this->assertArrayNotHasKey( $actorKey, $fields, "new field, stage=$writeStage" );
509 }
510
511 $this->db->insert( $table, $extraFields + $fields, __METHOD__ );
512 $id = $this->db->insertId();
513 if ( $usesTemp ) {
514 $callback( $id, $extraFields );
515 }
516
517 foreach ( $possibleReadStages as $readStage ) {
518 $r = $this->makeMigration( $readStage );
519
520 $queryInfo = $r->getJoin( $key );
521 $row = $this->db->selectRow(
522 [ $table ] + $queryInfo['tables'],
523 $queryInfo['fields'],
524 [ $pk => $id ],
525 __METHOD__,
526 [],
527 $queryInfo['joins']
528 );
529
530 $this->assertSame( $user->getId(), (int)$row->$key, "w=$writeStage, r=$readStage, id" );
531 $this->assertSame( $user->getName(), $row->$nameKey, "w=$writeStage, r=$readStage, name" );
532 $this->assertSame(
533 $readStage === MIGRATION_OLD || $writeStage === MIGRATION_OLD ? 0 : $user->getActorId(),
534 (int)$row->$actorKey,
535 "w=$writeStage, r=$readStage, actor"
536 );
537 }
538 }
539 }
540
541 public static function provideInsertRoundTrip() {
542 $db = wfGetDB( DB_REPLICA ); // for timestamps
543
544 $ipbfields = [
545 ];
546 $revfields = [
547 ];
548
549 return [
550 'recentchanges' => [ 'recentchanges', 'rc_user', 'rc_id', [
551 'rc_timestamp' => $db->timestamp(),
552 'rc_namespace' => 0,
553 'rc_title' => 'Test',
554 'rc_this_oldid' => 42,
555 'rc_last_oldid' => 41,
556 'rc_source' => 'test',
557 ] ],
558 'ipblocks' => [ 'ipblocks', 'ipb_by', 'ipb_id', [
559 'ipb_range_start' => '',
560 'ipb_range_end' => '',
561 'ipb_timestamp' => $db->timestamp(),
562 'ipb_expiry' => $db->getInfinity(),
563 ] ],
564 'revision' => [ 'revision', 'rev_user', 'rev_id', [
565 'rev_page' => 42,
566 'rev_text_id' => 42,
567 'rev_len' => 0,
568 'rev_timestamp' => $db->timestamp(),
569 ] ],
570 ];
571 }
572
573 public static function provideStages() {
574 return [
575 'MIGRATION_OLD' => [ MIGRATION_OLD ],
576 'MIGRATION_WRITE_BOTH' => [ MIGRATION_WRITE_BOTH ],
577 'MIGRATION_WRITE_NEW' => [ MIGRATION_WRITE_NEW ],
578 'MIGRATION_NEW' => [ MIGRATION_NEW ],
579 ];
580 }
581
582 /**
583 * @dataProvider provideStages
584 * @param int $stage
585 * @expectedException InvalidArgumentException
586 * @expectedExceptionMessage Must use getInsertValuesWithTempTable() for rev_user
587 */
588 public function testInsertWrong( $stage ) {
589 $m = $this->makeMigration( $stage );
590 $m->getInsertValues( $this->db, 'rev_user', $this->getTestUser()->getUser() );
591 }
592
593 /**
594 * @dataProvider provideStages
595 * @param int $stage
596 * @expectedException InvalidArgumentException
597 * @expectedExceptionMessage Must use getInsertValues() for rc_user
598 */
599 public function testInsertWithTempTableWrong( $stage ) {
600 $m = $this->makeMigration( $stage );
601 $m->getInsertValuesWithTempTable( $this->db, 'rc_user', $this->getTestUser()->getUser() );
602 }
603
604 /**
605 * @dataProvider provideStages
606 * @param int $stage
607 */
608 public function testInsertWithTempTableDeprecated( $stage ) {
609 $wrap = TestingAccessWrapper::newFromClass( ActorMigration::class );
610 $wrap->formerTempTables += [ 'rc_user' => '1.30' ];
611
612 $this->hideDeprecated( 'ActorMigration::getInsertValuesWithTempTable for rc_user' );
613 $m = $this->makeMigration( $stage );
614 list( $fields, $callback )
615 = $m->getInsertValuesWithTempTable( $this->db, 'rc_user', $this->getTestUser()->getUser() );
616 $this->assertTrue( is_callable( $callback ) );
617 }
618
619 /**
620 * @dataProvider provideStages
621 * @param int $stage
622 * @expectedException InvalidArgumentException
623 * @expectedExceptionMessage $extra[rev_timestamp] is not provided
624 */
625 public function testInsertWithTempTableCallbackMissingFields( $stage ) {
626 $m = $this->makeMigration( $stage );
627 list( $fields, $callback )
628 = $m->getInsertValuesWithTempTable( $this->db, 'rev_user', $this->getTestUser()->getUser() );
629 $callback( 1, [] );
630 }
631
632 public function testInsertUserIdentity() {
633 $user = $this->getTestUser()->getUser();
634 $userIdentity = $this->getMock( UserIdentity::class );
635 $userIdentity->method( 'getId' )->willReturn( $user->getId() );
636 $userIdentity->method( 'getName' )->willReturn( $user->getName() );
637 $userIdentity->method( 'getActorId' )->willReturn( 0 );
638
639 list( $cFields, $cCallback ) = MediaWikiServices::getInstance()->getCommentStore()
640 ->insertWithTempTable( $this->db, 'rev_comment', '' );
641 $m = $this->makeMigration( MIGRATION_WRITE_BOTH );
642 list( $fields, $callback ) =
643 $m->getInsertValuesWithTempTable( $this->db, 'rev_user', $userIdentity );
644 $extraFields = [
645 'rev_page' => 42,
646 'rev_text_id' => 42,
647 'rev_len' => 0,
648 'rev_timestamp' => $this->db->timestamp(),
649 ] + $cFields;
650 $this->db->insert( 'revision', $extraFields + $fields, __METHOD__ );
651 $id = $this->db->insertId();
652 $callback( $id, $extraFields );
653 $cCallback( $id );
654
655 $qi = Revision::getQueryInfo();
656 $row = $this->db->selectRow(
657 $qi['tables'], $qi['fields'], [ 'rev_id' => $id ], __METHOD__, [], $qi['joins']
658 );
659 $this->assertSame( $user->getId(), (int)$row->rev_user );
660 $this->assertSame( $user->getName(), $row->rev_user_text );
661 $this->assertSame( $user->getActorId(), (int)$row->rev_actor );
662
663 $m = $this->makeMigration( MIGRATION_WRITE_BOTH );
664 $fields = $m->getInsertValues( $this->db, 'dummy_user', $userIdentity );
665 $this->assertSame( $user->getId(), $fields['dummy_user'] );
666 $this->assertSame( $user->getName(), $fields['dummy_user_text'] );
667 $this->assertSame( $user->getActorId(), $fields['dummy_actor'] );
668 }
669
670 public function testConstructor() {
671 $m = ActorMigration::newMigration();
672 $this->assertInstanceOf( ActorMigration::class, $m );
673 $this->assertSame( $m, ActorMigration::newMigration() );
674 }
675
676 /**
677 * @dataProvider provideIsAnon
678 * @param int $stage
679 * @param string $isAnon
680 * @param string $isNotAnon
681 */
682 public function testIsAnon( $stage, $isAnon, $isNotAnon ) {
683 $m = $this->makeMigration( $stage );
684 $this->assertSame( $isAnon, $m->isAnon( 'foo' ) );
685 $this->assertSame( $isNotAnon, $m->isNotAnon( 'foo' ) );
686 }
687
688 public static function provideIsAnon() {
689 return [
690 'MIGRATION_OLD' => [ MIGRATION_OLD, 'foo = 0', 'foo != 0' ],
691 'MIGRATION_WRITE_BOTH' => [ MIGRATION_WRITE_BOTH, 'foo = 0', 'foo != 0' ],
692 'MIGRATION_WRITE_NEW' => [ MIGRATION_WRITE_NEW, 'foo = 0', 'foo != 0' ],
693 'MIGRATION_NEW' => [ MIGRATION_NEW, 'foo IS NULL', 'foo IS NOT NULL' ],
694 ];
695 }
696
697 }