MediaWiki  1.32.0
RevisionTest.php
Go to the documentation of this file.
1 <?php
2 
13 
19 
20  public function setUp() {
21  parent::setUp();
22  $this->setMwGlobals(
23  'wgMultiContentRevisionSchemaMigrationStage',
25  );
26  }
27 
28  public function provideConstructFromArray() {
29  yield 'with text' => [
30  [
31  'text' => 'hello world.',
32  'content_model' => CONTENT_MODEL_JAVASCRIPT
33  ],
34  ];
35  yield 'with content' => [
36  [
37  'content' => new JavaScriptContent( 'hellow world.' )
38  ],
39  ];
40  // FIXME: test with and without user ID, and with a user object.
41  // We can't prepare that here though, since we don't yet have a dummy DB
42  }
43 
48  public function getMockTitle( $model = CONTENT_MODEL_WIKITEXT ) {
49  $mock = $this->getMockBuilder( Title::class )
50  ->disableOriginalConstructor()
51  ->getMock();
52  $mock->expects( $this->any() )
53  ->method( 'getNamespace' )
54  ->will( $this->returnValue( $this->getDefaultWikitextNS() ) );
55  $mock->expects( $this->any() )
56  ->method( 'getPrefixedText' )
57  ->will( $this->returnValue( 'RevisionTest' ) );
58  $mock->expects( $this->any() )
59  ->method( 'getDBkey' )
60  ->will( $this->returnValue( 'RevisionTest' ) );
61  $mock->expects( $this->any() )
62  ->method( 'getArticleID' )
63  ->will( $this->returnValue( 23 ) );
64  $mock->expects( $this->any() )
65  ->method( 'getContentModel' )
66  ->will( $this->returnValue( $model ) );
67 
68  return $mock;
69  }
70 
76  public function testConstructFromArray( $rowArray ) {
77  $rev = new Revision( $rowArray, 0, $this->getMockTitle() );
78  $this->assertNotNull( $rev->getContent(), 'no content object available' );
79  $this->assertEquals( CONTENT_MODEL_JAVASCRIPT, $rev->getContent()->getModel() );
80  $this->assertEquals( CONTENT_MODEL_JAVASCRIPT, $rev->getContentModel() );
81  }
82 
87  public function testConstructFromEmptyArray() {
88  $rev = new Revision( [], 0, $this->getMockTitle() );
89  $this->assertNull( $rev->getContent(), 'no content object should be available' );
90  }
91 
97  Wikimedia\suppressWarnings();
98  $rev = new Revision( [ 'page' => 77777777 ] );
99  $this->assertSame( 77777777, $rev->getPage() );
100  Wikimedia\restoreWarnings();
101  }
102 
104  yield 'no user defaults to wgUser' => [
105  [
106  'content' => new JavaScriptContent( 'hello world.' ),
107  ],
108  null,
109  null,
110  ];
111  yield 'user text and id' => [
112  [
113  'content' => new JavaScriptContent( 'hello world.' ),
114  'user_text' => 'SomeTextUserName',
115  'user' => 99,
116 
117  ],
118  99,
119  'SomeTextUserName',
120  ];
121  yield 'user text only' => [
122  [
123  'content' => new JavaScriptContent( 'hello world.' ),
124  'user_text' => '111.111.111.111',
125  ],
126  0,
127  '111.111.111.111',
128  ];
129  }
130 
141  array $rowArray,
142  $expectedUserId,
143  $expectedUserName
144  ) {
145  $testUser = $this->getTestUser()->getUser();
146  $this->setMwGlobals( 'wgUser', $testUser );
147  if ( $expectedUserId === null ) {
148  $expectedUserId = $testUser->getId();
149  }
150  if ( $expectedUserName === null ) {
151  $expectedUserName = $testUser->getName();
152  }
153 
154  $rev = new Revision( $rowArray, 0, $this->getMockTitle() );
155  $this->assertEquals( $expectedUserId, $rev->getUser() );
156  $this->assertEquals( $expectedUserName, $rev->getUserText() );
157  }
158 
160  yield 'content and text_id both not empty' => [
161  [
162  'content' => new WikitextContent( 'GOAT' ),
163  'text_id' => 'someid',
164  ],
165  new MWException( 'The text_id field is only available in the pre-MCR schema' )
166  ];
167 
168  yield 'with bad content object (class)' => [
169  [ 'content' => new stdClass() ],
170  new MWException( 'content field must contain a Content object' )
171  ];
172  yield 'with bad content object (string)' => [
173  [ 'content' => 'ImAGoat' ],
174  new MWException( 'content field must contain a Content object' )
175  ];
176  yield 'bad row format' => [
177  'imastring, not a row',
178  new InvalidArgumentException(
179  '$row must be a row object, an associative array, or a RevisionRecord'
180  )
181  ];
182  }
183 
189  public function testConstructFromArrayThrowsExceptions( $rowArray, Exception $expectedException ) {
190  $this->setExpectedException(
191  get_class( $expectedException ),
192  $expectedException->getMessage(),
193  $expectedException->getCode()
194  );
195  new Revision( $rowArray, 0, $this->getMockTitle() );
196  }
197 
202  public function testConstructFromNothing() {
203  $this->setExpectedException(
205  );
206  new Revision( [] );
207  }
208 
209  public function provideConstructFromRow() {
210  yield 'Full construction' => [
211  [
212  'rev_id' => '42',
213  'rev_page' => '23',
214  'rev_timestamp' => '20171017114835',
215  'rev_user_text' => '127.0.0.1',
216  'rev_user' => '0',
217  'rev_minor_edit' => '0',
218  'rev_deleted' => '0',
219  'rev_len' => '46',
220  'rev_parent_id' => '1',
221  'rev_sha1' => 'rdqbbzs3pkhihgbs8qf2q9jsvheag5z',
222  'rev_comment_text' => 'Goat Comment!',
223  'rev_comment_data' => null,
224  'rev_comment_cid' => null,
225  ],
226  function ( RevisionTest $testCase, Revision $rev ) {
227  $testCase->assertSame( 42, $rev->getId() );
228  $testCase->assertSame( 23, $rev->getPage() );
229  $testCase->assertSame( '20171017114835', $rev->getTimestamp() );
230  $testCase->assertSame( '127.0.0.1', $rev->getUserText() );
231  $testCase->assertSame( 0, $rev->getUser() );
232  $testCase->assertSame( false, $rev->isMinor() );
233  $testCase->assertSame( false, $rev->isDeleted( Revision::DELETED_TEXT ) );
234  $testCase->assertSame( 46, $rev->getSize() );
235  $testCase->assertSame( 1, $rev->getParentId() );
236  $testCase->assertSame( 'rdqbbzs3pkhihgbs8qf2q9jsvheag5z', $rev->getSha1() );
237  $testCase->assertSame( 'Goat Comment!', $rev->getComment() );
238  }
239  ];
240  yield 'default field values' => [
241  [
242  'rev_id' => '42',
243  'rev_page' => '23',
244  'rev_timestamp' => '20171017114835',
245  'rev_user_text' => '127.0.0.1',
246  'rev_user' => '0',
247  'rev_minor_edit' => '0',
248  'rev_deleted' => '0',
249  'rev_comment_text' => 'Goat Comment!',
250  'rev_comment_data' => null,
251  'rev_comment_cid' => null,
252  ],
253  function ( RevisionTest $testCase, Revision $rev ) {
254  // parent ID may be null
255  $testCase->assertSame( null, $rev->getParentId(), 'revision id' );
256 
257  // given fields
258  $testCase->assertSame( $rev->getTimestamp(), '20171017114835', 'timestamp' );
259  $testCase->assertSame( $rev->getUserText(), '127.0.0.1', 'user name' );
260  $testCase->assertSame( $rev->getUser(), 0, 'user id' );
261  $testCase->assertSame( $rev->getComment(), 'Goat Comment!' );
262  $testCase->assertSame( false, $rev->isMinor(), 'minor edit' );
263  $testCase->assertSame( 0, $rev->getVisibility(), 'visibility flags' );
264  }
265  ];
266  }
267 
273  public function testConstructFromRow( array $arrayData, callable $assertions ) {
274  $row = (object)$arrayData;
275  $rev = new Revision( $row, 0, $this->getMockTitle() );
276  $assertions( $this, $rev );
277  }
278 
284  $this->setMwGlobals( 'wgCommentTableSchemaMigrationStage', MIGRATION_OLD );
285  $this->overrideMwServices();
286  Wikimedia\suppressWarnings();
287  $rev = new Revision( (object)[ 'rev_page' => 77777777 ] );
288  $this->assertSame( 77777777, $rev->getPage() );
289  Wikimedia\restoreWarnings();
290  }
291 
292  public function provideGetRevisionText() {
293  yield 'Generic test' => [
294  'This is a goat of revision text.',
295  [
296  'old_flags' => '',
297  'old_text' => 'This is a goat of revision text.',
298  ],
299  ];
300  }
301 
302  public function provideGetId() {
303  yield [
304  [],
305  null
306  ];
307  yield [
308  [ 'id' => 998 ],
309  998
310  ];
311  }
312 
317  public function testGetId( $rowArray, $expectedId ) {
318  $rev = new Revision( $rowArray, 0, $this->getMockTitle() );
319  $this->assertEquals( $expectedId, $rev->getId() );
320  }
321 
322  public function provideSetId() {
323  yield [ '123', 123 ];
324  yield [ 456, 456 ];
325  }
326 
331  public function testSetId( $input, $expected ) {
332  $rev = new Revision( [], 0, $this->getMockTitle() );
333  $rev->setId( $input );
334  $this->assertSame( $expected, $rev->getId() );
335  }
336 
337  public function provideSetUserIdAndName() {
338  yield [ '123', 123, 'GOaT' ];
339  yield [ 456, 456, 'GOaT' ];
340  }
341 
346  public function testSetUserIdAndName( $inputId, $expectedId, $name ) {
347  $rev = new Revision( [], 0, $this->getMockTitle() );
348  $rev->setUserIdAndName( $inputId, $name );
349  $this->assertSame( $expectedId, $rev->getUser( Revision::RAW ) );
350  $this->assertEquals( $name, $rev->getUserText( Revision::RAW ) );
351  }
352 
353  public function provideGetParentId() {
354  yield [ [], null ];
355  yield [ [ 'parent_id' => '123' ], 123 ];
356  yield [ [ 'parent_id' => 456 ], 456 ];
357  }
358 
363  public function testGetParentId( $rowArray, $expected ) {
364  $rev = new Revision( $rowArray, 0, $this->getMockTitle() );
365  $this->assertSame( $expected, $rev->getParentId() );
366  }
367 
372  public function testGetRevisionText( $expected, $rowData, $prefix = 'old_', $wiki = false ) {
373  $this->assertEquals(
374  $expected,
375  Revision::getRevisionText( (object)$rowData, $prefix, $wiki ) );
376  }
377 
379  yield 'Generic gzip test' => [
380  'This is a small goat of revision text.',
381  [
382  'old_flags' => 'gzip',
383  'old_text' => gzdeflate( 'This is a small goat of revision text.' ),
384  ],
385  ];
386  }
387 
392  public function testGetRevisionWithZlibExtension( $expected, $rowData ) {
393  $this->checkPHPExtension( 'zlib' );
394  $this->testGetRevisionText( $expected, $rowData );
395  }
396 
398  yield 'Generic gzip test' => [
399  'This is a small goat of revision text.',
400  [
401  'old_flags' => 'gzip',
402  'old_text' => 'DEAD BEEF',
403  ],
404  ];
405  }
406 
411  public function testGetRevisionWithZlibExtension_badData( $expected, $rowData ) {
412  $this->checkPHPExtension( 'zlib' );
413  Wikimedia\suppressWarnings();
414  $this->assertFalse(
416  (object)$rowData
417  )
418  );
419  Wikimedia\suppressWarnings( true );
420  }
421 
422  private function getWANObjectCache() {
423  return new WANObjectCache( [ 'cache' => new HashBagOStuff() ] );
424  }
425 
429  private function getBlobStore() {
431  $lb = $this->getMockBuilder( LoadBalancer::class )
432  ->disableOriginalConstructor()
433  ->getMock();
434 
435  $cache = $this->getWANObjectCache();
436 
437  $blobStore = new SqlBlobStore( $lb, $cache );
438  return $blobStore;
439  }
440 
441  private function mockBlobStoreFactory( $blobStore ) {
443  $factory = $this->getMockBuilder( BlobStoreFactory::class )
444  ->disableOriginalConstructor()
445  ->getMock();
446  $factory->expects( $this->any() )
447  ->method( 'newBlobStore' )
448  ->willReturn( $blobStore );
449  $factory->expects( $this->any() )
450  ->method( 'newSqlBlobStore' )
451  ->willReturn( $blobStore );
452  return $factory;
453  }
454 
458  private function getRevisionStore() {
460  $lb = $this->getMockBuilder( LoadBalancer::class )
461  ->disableOriginalConstructor()
462  ->getMock();
463 
464  $cache = $this->getWANObjectCache();
465 
466  $blobStore = new RevisionStore(
467  $lb,
468  $this->getBlobStore(),
469  $cache,
470  MediaWikiServices::getInstance()->getCommentStore(),
471  MediaWikiServices::getInstance()->getContentModelStore(),
472  MediaWikiServices::getInstance()->getSlotRoleStore(),
474  MediaWikiServices::getInstance()->getActorMigration()
475  );
476  return $blobStore;
477  }
478 
480  yield 'Utf8Native' => [
481  "Wiki est l'\xc3\xa9cole superieur !",
482  'fr',
483  'iso-8859-1',
484  [
485  'old_flags' => 'utf-8',
486  'old_text' => "Wiki est l'\xc3\xa9cole superieur !",
487  ]
488  ];
489  yield 'Utf8Legacy' => [
490  "Wiki est l'\xc3\xa9cole superieur !",
491  'fr',
492  'iso-8859-1',
493  [
494  'old_flags' => '',
495  'old_text' => "Wiki est l'\xe9cole superieur !",
496  ]
497  ];
498  }
499 
504  public function testGetRevisionWithLegacyEncoding( $expected, $lang, $encoding, $rowData ) {
505  $blobStore = $this->getBlobStore();
506  $blobStore->setLegacyEncoding( $encoding, Language::factory( $lang ) );
507  $this->setService( 'BlobStoreFactory', $this->mockBlobStoreFactory( $blobStore ) );
508 
509  $this->testGetRevisionText( $expected, $rowData );
510  }
511 
518  yield 'Utf8NativeGzip' => [
519  "Wiki est l'\xc3\xa9cole superieur !",
520  'fr',
521  'iso-8859-1',
522  [
523  'old_flags' => 'gzip,utf-8',
524  'old_text' => gzdeflate( "Wiki est l'\xc3\xa9cole superieur !" ),
525  ]
526  ];
527  yield 'Utf8LegacyGzip' => [
528  "Wiki est l'\xc3\xa9cole superieur !",
529  'fr',
530  'iso-8859-1',
531  [
532  'old_flags' => 'gzip',
533  'old_text' => gzdeflate( "Wiki est l'\xe9cole superieur !" ),
534  ]
535  ];
536  }
537 
542  public function testGetRevisionWithGzipAndLegacyEncoding( $expected, $lang, $encoding, $rowData ) {
543  $this->checkPHPExtension( 'zlib' );
544 
545  $blobStore = $this->getBlobStore();
546  $blobStore->setLegacyEncoding( $encoding, Language::factory( $lang ) );
547  $this->setService( 'BlobStoreFactory', $this->mockBlobStoreFactory( $blobStore ) );
548 
549  $this->testGetRevisionText( $expected, $rowData );
550  }
551 
555  public function testCompressRevisionTextUtf8() {
556  $row = new stdClass;
557  $row->old_text = "Wiki est l'\xc3\xa9cole superieur !";
558  $row->old_flags = Revision::compressRevisionText( $row->old_text );
559  $this->assertTrue( false !== strpos( $row->old_flags, 'utf-8' ),
560  "Flags should contain 'utf-8'" );
561  $this->assertFalse( false !== strpos( $row->old_flags, 'gzip' ),
562  "Flags should not contain 'gzip'" );
563  $this->assertEquals( "Wiki est l'\xc3\xa9cole superieur !",
564  $row->old_text, "Direct check" );
565  $this->assertEquals( "Wiki est l'\xc3\xa9cole superieur !",
566  Revision::getRevisionText( $row ), "getRevisionText" );
567  }
568 
573  $this->checkPHPExtension( 'zlib' );
574 
575  $blobStore = $this->getBlobStore();
576  $blobStore->setCompressBlobs( true );
577  $this->setService( 'BlobStoreFactory', $this->mockBlobStoreFactory( $blobStore ) );
578 
579  $row = new stdClass;
580  $row->old_text = "Wiki est l'\xc3\xa9cole superieur !";
581  $row->old_flags = Revision::compressRevisionText( $row->old_text );
582  $this->assertTrue( false !== strpos( $row->old_flags, 'utf-8' ),
583  "Flags should contain 'utf-8'" );
584  $this->assertTrue( false !== strpos( $row->old_flags, 'gzip' ),
585  "Flags should contain 'gzip'" );
586  $this->assertEquals( "Wiki est l'\xc3\xa9cole superieur !",
587  gzinflate( $row->old_text ), "Direct check" );
588  $this->assertEquals( "Wiki est l'\xc3\xa9cole superieur !",
589  Revision::getRevisionText( $row ), "getRevisionText" );
590  }
591 
595  public function testLoadFromTitle() {
596  $this->setMwGlobals( 'wgCommentTableSchemaMigrationStage', MIGRATION_OLD );
597  $this->setMwGlobals( 'wgActorTableSchemaMigrationStage', SCHEMA_COMPAT_OLD );
598  $this->overrideMwServices();
599  $title = $this->getMockTitle();
600 
601  $conditions = [
602  'rev_id=page_latest',
603  'page_namespace' => $title->getNamespace(),
604  'page_title' => $title->getDBkey()
605  ];
606 
607  $row = (object)[
608  'rev_id' => '42',
609  'rev_page' => $title->getArticleID(),
610  'rev_timestamp' => '20171017114835',
611  'rev_user_text' => '127.0.0.1',
612  'rev_user' => '0',
613  'rev_minor_edit' => '0',
614  'rev_deleted' => '0',
615  'rev_len' => '46',
616  'rev_parent_id' => '1',
617  'rev_sha1' => 'rdqbbzs3pkhihgbs8qf2q9jsvheag5z',
618  'rev_comment_text' => 'Goat Comment!',
619  'rev_comment_data' => null,
620  'rev_comment_cid' => null,
621  'rev_content_format' => 'GOATFORMAT',
622  'rev_content_model' => 'GOATMODEL',
623  ];
624 
625  $domain = MediaWikiServices::getInstance()->getDBLoadBalancer()->getLocalDomainID();
626  $db = $this->getMock( IDatabase::class );
627  $db->expects( $this->any() )
628  ->method( 'getDomainId' )
629  ->will( $this->returnValue( $domain ) );
630  $db->expects( $this->once() )
631  ->method( 'selectRow' )
632  ->with(
633  $this->equalTo( [ 'revision', 'page', 'user' ] ),
634  // We don't really care about the fields are they come from the selectField methods
635  $this->isType( 'array' ),
636  $this->equalTo( $conditions ),
637  // Method name
638  $this->stringContains( 'fetchRevisionRowFromConds' ),
639  // We don't really care about the options here
640  $this->isType( 'array' ),
641  // We don't really care about the join conds are they come from the joinCond methods
642  $this->isType( 'array' )
643  )
644  ->willReturn( $row );
645 
646  $revision = Revision::loadFromTitle( $db, $title );
647 
648  $this->assertEquals( $title->getArticleID(), $revision->getTitle()->getArticleID() );
649  $this->assertEquals( $row->rev_id, $revision->getId() );
650  $this->assertEquals( $row->rev_len, $revision->getSize() );
651  $this->assertEquals( $row->rev_sha1, $revision->getSha1() );
652  $this->assertEquals( $row->rev_parent_id, $revision->getParentId() );
653  $this->assertEquals( $row->rev_timestamp, $revision->getTimestamp() );
654  $this->assertEquals( $row->rev_comment_text, $revision->getComment() );
655  $this->assertEquals( $row->rev_user_text, $revision->getUserText() );
656  }
657 
658  public function provideDecompressRevisionText() {
659  yield '(no legacy encoding), false in false out' => [ false, false, [], false ];
660  yield '(no legacy encoding), empty in empty out' => [ false, '', [], '' ];
661  yield '(no legacy encoding), empty in empty out' => [ false, 'A', [], 'A' ];
662  yield '(no legacy encoding), string in with gzip flag returns string' => [
663  // gzip string below generated with gzdeflate( 'AAAABBAAA' )
664  false, "sttttr\002\022\000", [ 'gzip' ], 'AAAABBAAA',
665  ];
666  yield '(no legacy encoding), string in with object flag returns false' => [
667  // gzip string below generated with serialize( 'JOJO' )
668  false, "s:4:\"JOJO\";", [ 'object' ], false,
669  ];
670  yield '(no legacy encoding), serialized object in with object flag returns string' => [
671  false,
672  // Using a TitleValue object as it has a getText method (which is needed)
673  serialize( new TitleValue( 0, 'HHJJDDFF' ) ),
674  [ 'object' ],
675  'HHJJDDFF',
676  ];
677  yield '(no legacy encoding), serialized object in with object & gzip flag returns string' => [
678  false,
679  // Using a TitleValue object as it has a getText method (which is needed)
680  gzdeflate( serialize( new TitleValue( 0, '8219JJJ840' ) ) ),
681  [ 'object', 'gzip' ],
682  '8219JJJ840',
683  ];
684  yield '(ISO-8859-1 encoding), string in string out' => [
685  'ISO-8859-1',
686  iconv( 'utf-8', 'ISO-8859-1', "1®Àþ1" ),
687  [],
688  '1®Àþ1',
689  ];
690  yield '(ISO-8859-1 encoding), serialized object in with gzip flags returns string' => [
691  'ISO-8859-1',
692  gzdeflate( iconv( 'utf-8', 'ISO-8859-1', "4®Àþ4" ) ),
693  [ 'gzip' ],
694  '4®Àþ4',
695  ];
696  yield '(ISO-8859-1 encoding), serialized object in with object flags returns string' => [
697  'ISO-8859-1',
698  serialize( new TitleValue( 0, iconv( 'utf-8', 'ISO-8859-1', "3®Àþ3" ) ) ),
699  [ 'object' ],
700  '3®Àþ3',
701  ];
702  yield '(ISO-8859-1 encoding), serialized object in with object & gzip flags returns string' => [
703  'ISO-8859-1',
704  gzdeflate( serialize( new TitleValue( 0, iconv( 'utf-8', 'ISO-8859-1', "2®Àþ2" ) ) ) ),
705  [ 'gzip', 'object' ],
706  '2®Àþ2',
707  ];
708  }
709 
719  public function testDecompressRevisionText( $legacyEncoding, $text, $flags, $expected ) {
720  $blobStore = $this->getBlobStore();
721  if ( $legacyEncoding ) {
722  $blobStore->setLegacyEncoding( $legacyEncoding, Language::factory( 'en' ) );
723  }
724 
725  $this->setService( 'BlobStoreFactory', $this->mockBlobStoreFactory( $blobStore ) );
726  $this->assertSame(
727  $expected,
728  Revision::decompressRevisionText( $text, $flags )
729  );
730  }
731 
736  $this->assertFalse( Revision::getRevisionText( new stdClass() ) );
737  }
738 
740  yield 'Just text' => [
741  (object)[ 'old_text' => 'SomeText' ],
742  'old_',
743  'SomeText'
744  ];
745  // gzip string below generated with gzdeflate( 'AAAABBAAA' )
746  yield 'gzip text' => [
747  (object)[
748  'old_text' => "sttttr\002\022\000",
749  'old_flags' => 'gzip'
750  ],
751  'old_',
752  'AAAABBAAA'
753  ];
754  yield 'gzip text and different prefix' => [
755  (object)[
756  'jojo_text' => "sttttr\002\022\000",
757  'jojo_flags' => 'gzip'
758  ],
759  'jojo_',
760  'AAAABBAAA'
761  ];
762  }
763 
769  $row,
770  $prefix,
771  $expected
772  ) {
773  $this->assertSame( $expected, Revision::getRevisionText( $row, $prefix ) );
774  }
775 
777  yield 'Just some text' => [ 'someNonUrlText' ];
778  yield 'No second URL part' => [ 'someProtocol://' ];
779  }
780 
786  $text
787  ) {
788  Wikimedia\suppressWarnings();
789  $this->assertFalse(
791  (object)[
792  'old_text' => $text,
793  'old_flags' => 'external',
794  ]
795  )
796  );
797  Wikimedia\suppressWarnings( true );
798  }
799 
804  $this->setService(
805  'ExternalStoreFactory',
806  new ExternalStoreFactory( [ 'ForTesting' ] )
807  );
808  $this->assertSame(
809  'AAAABBAAA',
811  (object)[
812  'old_text' => 'ForTesting://cluster1/12345',
813  'old_flags' => 'external,gzip',
814  ]
815  )
816  );
817  }
818 
823  $cache = $this->getWANObjectCache();
824  $this->setService( 'MainWANObjectCache', $cache );
825 
826  $this->setService(
827  'ExternalStoreFactory',
828  new ExternalStoreFactory( [ 'ForTesting' ] )
829  );
830 
831  $lb = $this->getMockBuilder( LoadBalancer::class )
832  ->disableOriginalConstructor()
833  ->getMock();
834 
835  $blobStore = new SqlBlobStore( $lb, $cache );
836  $this->setService( 'BlobStoreFactory', $this->mockBlobStoreFactory( $blobStore ) );
837 
838  $this->assertSame(
839  'AAAABBAAA',
841  (object)[
842  'old_text' => 'ForTesting://cluster1/12345',
843  'old_flags' => 'external,gzip',
844  'old_id' => '7777',
845  ]
846  )
847  );
848 
849  $cacheKey = $cache->makeGlobalKey(
850  'BlobStore',
851  'address',
852  $lb->getLocalDomainID(),
853  'tt:7777'
854  );
855  $this->assertSame( 'AAAABBAAA', $cache->get( $cacheKey ) );
856  }
857 
861  public function testGetSize() {
862  $title = $this->getMockTitle();
863 
864  $rec = new MutableRevisionRecord( $title );
865  $rev = new Revision( $rec, 0, $title );
866 
867  $this->assertSame( 0, $rev->getSize(), 'Size of no slots is 0' );
868 
869  $rec->setSize( 13 );
870  $this->assertSame( 13, $rev->getSize() );
871  }
872 
876  public function testGetSize_failure() {
877  $title = $this->getMockTitle();
878 
879  $rec = $this->getMockBuilder( RevisionRecord::class )
880  ->disableOriginalConstructor()
881  ->getMock();
882 
883  $rec->method( 'getSize' )
884  ->willThrowException( new RevisionAccessException( 'Oops!' ) );
885 
886  $rev = new Revision( $rec, 0, $title );
887  $this->assertNull( $rev->getSize() );
888  }
889 
893  public function testGetSha1() {
894  $title = $this->getMockTitle();
895 
896  $rec = new MutableRevisionRecord( $title );
897  $rev = new Revision( $rec, 0, $title );
898 
899  $emptyHash = SlotRecord::base36Sha1( '' );
900  $this->assertSame( $emptyHash, $rev->getSha1(), 'Sha1 of no slots is hash of empty string' );
901 
902  $rec->setSha1( 'deadbeef' );
903  $this->assertSame( 'deadbeef', $rev->getSha1() );
904  }
905 
909  public function testGetSha1_failure() {
910  $title = $this->getMockTitle();
911 
912  $rec = $this->getMockBuilder( RevisionRecord::class )
913  ->disableOriginalConstructor()
914  ->getMock();
915 
916  $rec->method( 'getSha1' )
917  ->willThrowException( new RevisionAccessException( 'Oops!' ) );
918 
919  $rev = new Revision( $rec, 0, $title );
920  $this->assertNull( $rev->getSha1() );
921  }
922 
926  public function testGetContent() {
927  $title = $this->getMockTitle();
928 
929  $rec = new MutableRevisionRecord( $title );
930  $rev = new Revision( $rec, 0, $title );
931 
932  $this->assertNull( $rev->getContent(), 'Content of no slots is null' );
933 
934  $content = new TextContent( 'Hello Kittens!' );
935  $rec->setContent( SlotRecord::MAIN, $content );
936  $this->assertSame( $content, $rev->getContent() );
937  }
938 
942  public function testGetContent_failure() {
943  $title = $this->getMockTitle();
944 
945  $rec = $this->getMockBuilder( RevisionRecord::class )
946  ->disableOriginalConstructor()
947  ->getMock();
948 
949  $rec->method( 'getContent' )
950  ->willThrowException( new RevisionAccessException( 'Oops!' ) );
951 
952  $rev = new Revision( $rec, 0, $title );
953  $this->assertNull( $rev->getContent() );
954  }
955 
956 }
RevisionTest\testSetId
testSetId( $input, $expected)
provideSetId Revision::setId
Definition: RevisionTest.php:331
RevisionTest\testGetSha1
testGetSha1()
Revision::getSha1.
Definition: RevisionTest.php:893
RevisionTest\testConstructFromEmptyArray
testConstructFromEmptyArray()
Revision::__construct \MediaWiki\Revision\RevisionStore::newMutableRevisionFromArray.
Definition: RevisionTest.php:87
Revision\RevisionAccessException
Exception representing a failure to look up a revision.
Definition: RevisionAccessException.php:33
Revision\RevisionRecord
Page revision base class.
Definition: RevisionRecord.php:45
SCHEMA_COMPAT_READ_NEW
const SCHEMA_COMPAT_READ_NEW
Definition: Defines.php:287
false
processing should stop and the error should be shown to the user * false
Definition: hooks.txt:187
RevisionTest\provideDecompressRevisionText
provideDecompressRevisionText()
Definition: RevisionTest.php:658
RevisionTest\testGetRevisionWithZlibExtension_badData
testGetRevisionWithZlibExtension_badData( $expected, $rowData)
Revision::getRevisionText provideGetRevisionTextWithZlibExtension_badData.
Definition: RevisionTest.php:411
HashBagOStuff
Simple store for keeping values in an associative array for the current process.
Definition: HashBagOStuff.php:31
MediaWikiTestCase\getTestUser
static getTestUser( $groups=[])
Convenience method for getting an immutable test user.
Definition: MediaWikiTestCase.php:179
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:33
RevisionTest\testConstructFromArray_userSetAsExpected
testConstructFromArray_userSetAsExpected(array $rowArray, $expectedUserId, $expectedUserName)
provideConstructFromArray_userSetAsExpected Revision::__construct \MediaWiki\Revision\RevisionStore::...
Definition: RevisionTest.php:140
Revision\RevisionStore
Service for looking up page revisions.
Definition: RevisionStore.php:76
MediaWiki\Storage\SqlBlobStore
Service for storing and loading Content objects.
Definition: SqlBlobStore.php:50
RevisionTest\testGetRevisionText_external_oldId
testGetRevisionText_external_oldId()
Revision::getRevisionText.
Definition: RevisionTest.php:822
RevisionTest\testConstructFromArrayThrowsExceptions
testConstructFromArrayThrowsExceptions( $rowArray, Exception $expectedException)
provideConstructFromArrayThrowsExceptions Revision::__construct \MediaWiki\Revision\RevisionStore::ne...
Definition: RevisionTest.php:189
RevisionTest\testGetRevisionText_returnsFalseWhenNoTextField
testGetRevisionText_returnsFalseWhenNoTextField()
Revision::getRevisionText.
Definition: RevisionTest.php:735
RevisionTest\provideGetRevisionTextWithZlibExtension
provideGetRevisionTextWithZlibExtension()
Definition: RevisionTest.php:378
Revision\getRevisionText
static getRevisionText( $row, $prefix='old_', $wiki=false)
Get revision text associated with an old or archive row.
Definition: Revision.php:1050
RevisionTest\testConstructFromRowWithBadPageId
testConstructFromRowWithBadPageId()
Revision::__construct \MediaWiki\Revision\RevisionStore::newMutableRevisionFromArray.
Definition: RevisionTest.php:283
RevisionTest\testConstructFromRow
testConstructFromRow(array $arrayData, callable $assertions)
provideConstructFromRow Revision::__construct \MediaWiki\Revision\RevisionStore::newMutableRevisionFr...
Definition: RevisionTest.php:273
RevisionTest\testGetSize_failure
testGetSize_failure()
Revision::getSize.
Definition: RevisionTest.php:876
CONTENT_MODEL_WIKITEXT
const CONTENT_MODEL_WIKITEXT
Definition: Defines.php:235
serialize
serialize()
Definition: ApiMessageTrait.php:131
RevisionTest\testGetRevisionWithGzipAndLegacyEncoding
testGetRevisionWithGzipAndLegacyEncoding( $expected, $lang, $encoding, $rowData)
Revision::getRevisionText provideGetRevisionTextWithGzipAndLegacyEncoding.
Definition: RevisionTest.php:542
php
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition: injection.txt:35
RevisionTest\provideConstructFromArray
provideConstructFromArray()
Definition: RevisionTest.php:28
Wikimedia\Rdbms\IDatabase
Basic database interface for live and lazy-loaded relation database handles.
Definition: IDatabase.php:38
RevisionTest\provideTestGetRevisionText_external_returnsFalseWhenNotEnoughUrlParts
provideTestGetRevisionText_external_returnsFalseWhenNotEnoughUrlParts()
Definition: RevisionTest.php:776
MediaWikiTestCase\overrideMwServices
overrideMwServices(Config $configOverrides=null, array $services=[])
Stashes the global instance of MediaWikiServices, and installs a new one, allowing test cases to over...
Definition: MediaWikiTestCase.php:934
RevisionTest\mockBlobStoreFactory
mockBlobStoreFactory( $blobStore)
Definition: RevisionTest.php:441
Revision
Definition: Revision.php:41
RevisionTest\testCompressRevisionTextUtf8Gzip
testCompressRevisionTextUtf8Gzip()
Revision::compressRevisionText.
Definition: RevisionTest.php:572
RevisionTest\getWANObjectCache
getWANObjectCache()
Definition: RevisionTest.php:422
RevisionTest\provideGetRevisionText
provideGetRevisionText()
Definition: RevisionTest.php:292
RevisionTest\provideGetParentId
provideGetParentId()
Definition: RevisionTest.php:353
MWException
MediaWiki exception.
Definition: MWException.php:26
$title
namespace and then decline to actually register it file or subcat img or subcat $title
Definition: hooks.txt:964
RevisionTest\testSetUserIdAndName
testSetUserIdAndName( $inputId, $expectedId, $name)
provideSetUserIdAndName Revision::setUserIdAndName
Definition: RevisionTest.php:346
RevisionTest\testGetRevisionWithLegacyEncoding
testGetRevisionWithLegacyEncoding( $expected, $lang, $encoding, $rowData)
Revision::getRevisionText provideGetRevisionTextWithLegacyEncoding.
Definition: RevisionTest.php:504
$input
if(is_array( $mode)) switch( $mode) $input
Definition: postprocess-phan.php:141
MediaWikiTestCase\setMwGlobals
setMwGlobals( $pairs, $value=null)
Sets a global, maintaining a stashed version of the previous global to be restored in tearDown.
Definition: MediaWikiTestCase.php:706
MediaWikiTestCase
Definition: MediaWikiTestCase.php:16
Revision\compressRevisionText
static compressRevisionText(&$text)
If $wgCompressRevisions is enabled, we will compress data.
Definition: Revision.php:1094
RevisionTest\provideGetRevisionTextWithGzipAndLegacyEncoding
provideGetRevisionTextWithGzipAndLegacyEncoding()
Definition: RevisionTest.php:512
RevisionTest\provideConstructFromArrayThrowsExceptions
provideConstructFromArrayThrowsExceptions()
Definition: RevisionTest.php:159
RevisionTest\setUp
setUp()
Definition: RevisionTest.php:20
use
as see the revision history and available at free of to any person obtaining a copy of this software and associated documentation to deal in the Software without including without limitation the rights to use
Definition: MIT-LICENSE.txt:10
MediaWiki\Storage\BlobStoreFactory
Service for instantiating BlobStores.
Definition: BlobStoreFactory.php:35
MediaWikiTestCase\getDefaultWikitextNS
getDefaultWikitextNS()
Returns the ID of a namespace that defaults to Wikitext.
Definition: MediaWikiTestCase.php:2177
RevisionTest\testGetContent
testGetContent()
Revision::getContent.
Definition: RevisionTest.php:926
WikitextContent
Content object for wiki text pages.
Definition: WikitextContent.php:35
array
The wiki should then use memcached to cache various data To use multiple just add more items to the array To increase the weight of a make its entry a array("192.168.0.1:11211", 2))
RevisionTest
Test cases in RevisionTest should not interact with the Database.
Definition: RevisionTest.php:18
JavaScriptContent
Content for JavaScript pages.
Definition: JavaScriptContent.php:33
RevisionTest\provideGetRevisionTextWithLegacyEncoding
provideGetRevisionTextWithLegacyEncoding()
Definition: RevisionTest.php:479
MIGRATION_OLD
const MIGRATION_OLD
Definition: Defines.php:315
Wikimedia\Rdbms\LoadBalancer
Database connection, tracking, load balancing, and transaction manager for a cluster.
Definition: LoadBalancer.php:41
$name
Allows to change the fields on the form that will be generated $name
Definition: hooks.txt:302
RevisionTest\testGetSize
testGetSize()
Revision::getSize.
Definition: RevisionTest.php:861
RevisionTest\provideGetRevisionTextWithZlibExtension_badData
provideGetRevisionTextWithZlibExtension_badData()
Definition: RevisionTest.php:397
ExternalStoreFactory
Definition: ExternalStoreFactory.php:9
any
they could even be mouse clicks or menu items whatever suits your program You should also get your if any
Definition: COPYING.txt:326
RevisionTest\provideSetUserIdAndName
provideSetUserIdAndName()
Definition: RevisionTest.php:337
RevisionTest\provideConstructFromArray_userSetAsExpected
provideConstructFromArray_userSetAsExpected()
Definition: RevisionTest.php:103
Revision\MutableRevisionRecord
Mutable RevisionRecord implementation, for building new revision entries programmatically.
Definition: MutableRevisionRecord.php:41
WANObjectCache
Multi-datacenter aware caching interface.
Definition: WANObjectCache.php:118
RevisionTest\testDecompressRevisionText
testDecompressRevisionText( $legacyEncoding, $text, $flags, $expected)
provideDecompressRevisionText Revision::decompressRevisionText
Definition: RevisionTest.php:719
RevisionTest\testConstructFromArray
testConstructFromArray( $rowArray)
provideConstructFromArray Revision::__construct \MediaWiki\Revision\RevisionStore::newMutableRevision...
Definition: RevisionTest.php:76
Revision\RAW
const RAW
Definition: Revision.php:57
RevisionTest\testGetRevisionText_external_noOldId
testGetRevisionText_external_noOldId()
Revision::getRevisionText.
Definition: RevisionTest.php:803
RevisionTest\testGetContent_failure
testGetContent_failure()
Revision::getContent.
Definition: RevisionTest.php:942
RevisionTest\testGetRevisionText_returnsDecompressedTextFieldWhenNotExternal
testGetRevisionText_returnsDecompressedTextFieldWhenNotExternal( $row, $prefix, $expected)
provideTestGetRevisionText_returnsDecompressedTextFieldWhenNotExternal Revision::getRevisionText
Definition: RevisionTest.php:768
TextContent
Content object implementation for representing flat text.
Definition: TextContent.php:37
RevisionTest\testGetRevisionText
testGetRevisionText( $expected, $rowData, $prefix='old_', $wiki=false)
Revision::getRevisionText provideGetRevisionText.
Definition: RevisionTest.php:372
RevisionTest\provideTestGetRevisionText_returnsDecompressedTextFieldWhenNotExternal
provideTestGetRevisionText_returnsDecompressedTextFieldWhenNotExternal()
Definition: RevisionTest.php:739
RevisionTest\testConstructFromArrayWithBadPageId
testConstructFromArrayWithBadPageId()
Revision::__construct \MediaWiki\Revision\RevisionStore::newMutableRevisionFromArray.
Definition: RevisionTest.php:96
RevisionTest\testGetRevisionText_external_returnsFalseWhenNotEnoughUrlParts
testGetRevisionText_external_returnsFalseWhenNotEnoughUrlParts( $text)
provideTestGetRevisionText_external_returnsFalseWhenNotEnoughUrlParts Revision::getRevisionText
Definition: RevisionTest.php:785
$cache
$cache
Definition: mcc.php:33
RevisionTest\testConstructFromNothing
testConstructFromNothing()
Revision::__construct \MediaWiki\Revision\RevisionStore::newMutableRevisionFromArray.
Definition: RevisionTest.php:202
RevisionTest\testGetId
testGetId( $rowArray, $expectedId)
provideGetId Revision::getId
Definition: RevisionTest.php:317
SCHEMA_COMPAT_OLD
const SCHEMA_COMPAT_OLD
Definition: Defines.php:290
$rev
presenting them properly to the user as errors is done by the caller return true use this to change the list i e etc $rev
Definition: hooks.txt:1808
RevisionTest\testLoadFromTitle
testLoadFromTitle()
Revision::loadFromTitle.
Definition: RevisionTest.php:595
RevisionTest\provideSetId
provideSetId()
Definition: RevisionTest.php:322
SCHEMA_COMPAT_WRITE_BOTH
const SCHEMA_COMPAT_WRITE_BOTH
Definition: Defines.php:288
RevisionTest\testGetSha1_failure
testGetSha1_failure()
Revision::getSha1.
Definition: RevisionTest.php:909
MediaWikiTestCase\checkPHPExtension
checkPHPExtension( $extName)
Check if $extName is a loaded PHP extension, will skip the test whenever it is not loaded.
Definition: MediaWikiTestCase.php:2254
$content
$content
Definition: pageupdater.txt:72
Language\factory
static factory( $code)
Get a cached or new language object for a given language code.
Definition: Language.php:214
class
you have access to all of the normal MediaWiki so you can get a DB use the etc For full docs on the Maintenance class
Definition: maintenance.txt:52
CONTENT_MODEL_JAVASCRIPT
const CONTENT_MODEL_JAVASCRIPT
Definition: Defines.php:236
RevisionTest\provideGetId
provideGetId()
Definition: RevisionTest.php:302
object
globals will be eliminated from MediaWiki replaced by an application object which would be passed to constructors Whether that would be an convenient solution remains to be but certainly PHP makes such object oriented programming models easier than they were in previous versions For the time being MediaWiki programmers will have to work in an environment with some global context At the time of globals were initialised on startup by MediaWiki of these were configuration which are documented in DefaultSettings php There is no comprehensive documentation for the remaining however some of the most important ones are listed below They are typically initialised either in index php or in Setup php $wgTitle Title object created from the request URL $wgOut OutputPage object for HTTP response $wgUser User object for the user associated with the current request $wgLang Language object selected by user preferences $wgContLang Language object associated with the wiki being viewed $wgParser Parser object Parser extensions register their hooks here $wgRequest WebRequest object
Definition: globals.txt:25
RevisionTest\getRevisionStore
getRevisionStore()
Definition: RevisionTest.php:458
MediaWikiServices
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency MediaWikiServices
Definition: injection.txt:23
Revision\decompressRevisionText
static decompressRevisionText( $text, $flags)
Re-converts revision text according to it's flags.
Definition: Revision.php:1105
Revision\loadFromTitle
static loadFromTitle( $db, $title, $id=0)
Load either the current, or a specified, revision that's attached to a given page.
Definition: Revision.php:273
RevisionTest\getBlobStore
getBlobStore()
Definition: RevisionTest.php:429
MediaWikiTestCase\setService
setService( $name, $object)
Sets a service, maintaining a stashed version of the previous service to be restored in tearDown.
Definition: MediaWikiTestCase.php:646
RevisionTest\provideConstructFromRow
provideConstructFromRow()
Definition: RevisionTest.php:209
Revision\DELETED_TEXT
const DELETED_TEXT
Definition: Revision.php:47
RevisionTest\getMockTitle
getMockTitle( $model=CONTENT_MODEL_WIKITEXT)
Definition: RevisionTest.php:48
MediaWikiTestCase\$db
Database $db
Primary database.
Definition: MediaWikiTestCase.php:60
RevisionTest\testCompressRevisionTextUtf8
testCompressRevisionTextUtf8()
Revision::compressRevisionText.
Definition: RevisionTest.php:555
RevisionTest\testGetRevisionWithZlibExtension
testGetRevisionWithZlibExtension( $expected, $rowData)
Revision::getRevisionText provideGetRevisionTextWithZlibExtension.
Definition: RevisionTest.php:392
Revision\SlotRecord
Value object representing a content slot associated with a page revision.
Definition: SlotRecord.php:39
RevisionTest\testGetParentId
testGetParentId( $rowArray, $expected)
provideGetParentId Revision::getParentId()
Definition: RevisionTest.php:363
TitleValue
Represents a page (or page fragment) title within MediaWiki.
Definition: TitleValue.php:36