39f7e5c304f2ed17478031c786aac7e6af887275
4 * @group ContentHandler
6 class RevisionTest
extends MediaWikiTestCase
{
8 protected function setUp() {
13 $this->setMwGlobals( [
14 'wgContLang' => Language
::factory( 'en' ),
15 'wgLanguageCode' => 'en',
16 'wgLegacyEncoding' => false,
17 'wgCompressRevisions' => false,
19 'wgContentHandlerTextFallback' => 'ignore',
22 $this->mergeMwGlobalArrayValue(
26 12313 => 'Dummy_talk',
30 $this->mergeMwGlobalArrayValue(
31 'wgNamespaceContentModels',
37 $this->mergeMwGlobalArrayValue(
40 'testing' => 'DummyContentHandlerForTesting',
41 'RevisionTestModifyableContent' => 'RevisionTestModifyableContentHandler',
45 MWNamespace
::clearCaches();
46 // Reset namespace cache
47 $wgContLang->resetNamespaces();
50 protected function tearDown() {
53 MWNamespace
::clearCaches();
54 // Reset namespace cache
55 $wgContLang->resetNamespaces();
60 public function provideConstruct() {
61 yield
'with text' => [
63 'text' => 'hello world.',
64 'content_model' => CONTENT_MODEL_JAVASCRIPT
67 yield
'with content' => [
69 'content' => new JavaScriptContent( 'hellow world.' )
75 * @dataProvider provideConstruct
77 public function testConstruct( $rowArray ) {
78 $rev = new Revision( $rowArray );
79 $this->assertNotNull( $rev->getContent(), 'no content object available' );
80 $this->assertEquals( CONTENT_MODEL_JAVASCRIPT
, $rev->getContent()->getModel() );
81 $this->assertEquals( CONTENT_MODEL_JAVASCRIPT
, $rev->getContentModel() );
84 public function provideConstructThrowsExceptions() {
85 yield
'content and text_id both not empty' => [
87 'content' => new WikitextContent( 'GOAT' ),
88 'text_id' => 'someid',
90 new MWException( "Text already stored in external store (id someid), " .
91 "can't serialize content object" )
93 yield
'with bad content object (class)' => [
94 [ 'content' => new stdClass() ],
95 new MWException( '`content` field must contain a Content object.' )
97 yield
'with bad content object (string)' => [
98 [ 'content' => 'ImAGoat' ],
99 new MWException( '`content` field must contain a Content object.' )
101 yield
'bad row format' => [
102 'imastring, not a row',
103 new MWException( 'Revision constructor passed invalid row format.' )
108 * @dataProvider provideConstructThrowsExceptions
110 public function testConstructThrowsExceptions( $rowArray, Exception
$expectedException ) {
111 $this->setExpectedException(
112 get_class( $expectedException ),
113 $expectedException->getMessage(),
114 $expectedException->getCode()
116 new Revision( $rowArray );
119 public function provideGetRevisionText() {
120 yield
'Generic test' => [
121 'This is a goat of revision text.',
124 'old_text' => 'This is a goat of revision text.',
130 * @covers Revision::getRevisionText
131 * @dataProvider provideGetRevisionText
133 public function testGetRevisionText( $expected, $rowData, $prefix = 'old_', $wiki = false ) {
136 Revision
::getRevisionText( (object)$rowData, $prefix, $wiki ) );
139 public function provideGetRevisionTextWithZlibExtension() {
140 yield
'Generic gzip test' => [
141 'This is a small goat of revision text.',
143 'old_flags' => 'gzip',
144 'old_text' => gzdeflate( 'This is a small goat of revision text.' ),
150 * @covers Revision::getRevisionText
151 * @dataProvider provideGetRevisionTextWithZlibExtension
153 public function testGetRevisionWithZlibExtension( $expected, $rowData ) {
154 $this->checkPHPExtension( 'zlib' );
155 $this->testGetRevisionText( $expected, $rowData );
158 public function provideGetRevisionTextWithLegacyEncoding() {
159 yield
'Utf8Native' => [
160 "Wiki est l'\xc3\xa9cole superieur !",
163 'old_flags' => 'utf-8',
164 'old_text' => "Wiki est l'\xc3\xa9cole superieur !",
167 yield
'Utf8Legacy' => [
168 "Wiki est l'\xc3\xa9cole superieur !",
172 'old_text' => "Wiki est l'\xe9cole superieur !",
178 * @covers Revision::getRevisionText
179 * @dataProvider provideGetRevisionTextWithLegacyEncoding
181 public function testGetRevisionWithLegacyEncoding( $expected, $encoding, $rowData ) {
182 $GLOBALS['wgLegacyEncoding'] = $encoding;
183 $this->testGetRevisionText( $expected, $rowData );
186 public function provideGetRevisionTextWithGzipAndLegacyEncoding() {
187 yield
'Utf8NativeGzip' => [
188 "Wiki est l'\xc3\xa9cole superieur !",
191 'old_flags' => 'gzip,utf-8',
192 'old_text' => gzdeflate( "Wiki est l'\xc3\xa9cole superieur !" ),
195 yield
'Utf8LegacyGzip' => [
196 "Wiki est l'\xc3\xa9cole superieur !",
199 'old_flags' => 'gzip',
200 'old_text' => gzdeflate( "Wiki est l'\xe9cole superieur !" ),
206 * @covers Revision::getRevisionText
207 * @dataProvider provideGetRevisionTextWithGzipAndLegacyEncoding
209 public function testGetRevisionWithGzipAndLegacyEncoding( $expected, $encoding, $rowData ) {
210 $this->checkPHPExtension( 'zlib' );
211 $GLOBALS['wgLegacyEncoding'] = $encoding;
212 $this->testGetRevisionText( $expected, $rowData );
216 * @covers Revision::compressRevisionText
218 public function testCompressRevisionTextUtf8() {
220 $row->old_text
= "Wiki est l'\xc3\xa9cole superieur !";
221 $row->old_flags
= Revision
::compressRevisionText( $row->old_text
);
222 $this->assertTrue( false !== strpos( $row->old_flags
, 'utf-8' ),
223 "Flags should contain 'utf-8'" );
224 $this->assertFalse( false !== strpos( $row->old_flags
, 'gzip' ),
225 "Flags should not contain 'gzip'" );
226 $this->assertEquals( "Wiki est l'\xc3\xa9cole superieur !",
227 $row->old_text
, "Direct check" );
228 $this->assertEquals( "Wiki est l'\xc3\xa9cole superieur !",
229 Revision
::getRevisionText( $row ), "getRevisionText" );
233 * @covers Revision::compressRevisionText
235 public function testCompressRevisionTextUtf8Gzip() {
236 $this->checkPHPExtension( 'zlib' );
237 $this->setMwGlobals( 'wgCompressRevisions', true );
240 $row->old_text
= "Wiki est l'\xc3\xa9cole superieur !";
241 $row->old_flags
= Revision
::compressRevisionText( $row->old_text
);
242 $this->assertTrue( false !== strpos( $row->old_flags
, 'utf-8' ),
243 "Flags should contain 'utf-8'" );
244 $this->assertTrue( false !== strpos( $row->old_flags
, 'gzip' ),
245 "Flags should contain 'gzip'" );
246 $this->assertEquals( "Wiki est l'\xc3\xa9cole superieur !",
247 gzinflate( $row->old_text
), "Direct check" );
248 $this->assertEquals( "Wiki est l'\xc3\xa9cole superieur !",
249 Revision
::getRevisionText( $row ), "getRevisionText" );
253 * @param string $text
254 * @param string $title
255 * @param string $model
256 * @param string $format
260 private function newTestRevision( $text, $title = "Test",
261 $model = CONTENT_MODEL_WIKITEXT
, $format = null
263 if ( is_string( $title ) ) {
264 $title = Title
::newFromText( $title );
267 $content = ContentHandler
::makeContent( $text, $title, $model, $format );
275 'content' => $content,
276 'length' => $content->getSize(),
277 'comment' => "testing",
278 'minor_edit' => false,
280 'content_format' => $format,
287 public function provideGetContentModel() {
288 // NOTE: we expect the help namespace to always contain wikitext
290 [ 'hello world', 'Help:Hello', null, null, CONTENT_MODEL_WIKITEXT
],
291 [ 'hello world', 'User:hello/there.css', null, null, CONTENT_MODEL_CSS
],
292 [ serialize( 'hello world' ), 'Dummy:Hello', null, null, "testing" ],
298 * @dataProvider provideGetContentModel
299 * @covers Revision::getContentModel
301 public function testGetContentModel( $text, $title, $model, $format, $expectedModel ) {
302 $rev = $this->newTestRevision( $text, $title, $model, $format );
304 $this->assertEquals( $expectedModel, $rev->getContentModel() );
307 public function provideGetContentFormat() {
308 // NOTE: we expect the help namespace to always contain wikitext
310 [ 'hello world', 'Help:Hello', null, null, CONTENT_FORMAT_WIKITEXT
],
311 [ 'hello world', 'Help:Hello', CONTENT_MODEL_CSS
, null, CONTENT_FORMAT_CSS
],
312 [ 'hello world', 'User:hello/there.css', null, null, CONTENT_FORMAT_CSS
],
313 [ serialize( 'hello world' ), 'Dummy:Hello', null, null, "testing" ],
319 * @dataProvider provideGetContentFormat
320 * @covers Revision::getContentFormat
322 public function testGetContentFormat( $text, $title, $model, $format, $expectedFormat ) {
323 $rev = $this->newTestRevision( $text, $title, $model, $format );
325 $this->assertEquals( $expectedFormat, $rev->getContentFormat() );
328 public function provideGetContentHandler() {
329 // NOTE: we expect the help namespace to always contain wikitext
331 [ 'hello world', 'Help:Hello', null, null, 'WikitextContentHandler' ],
332 [ 'hello world', 'User:hello/there.css', null, null, 'CssContentHandler' ],
333 [ serialize( 'hello world' ), 'Dummy:Hello', null, null, 'DummyContentHandlerForTesting' ],
339 * @dataProvider provideGetContentHandler
340 * @covers Revision::getContentHandler
342 public function testGetContentHandler( $text, $title, $model, $format, $expectedClass ) {
343 $rev = $this->newTestRevision( $text, $title, $model, $format );
345 $this->assertEquals( $expectedClass, get_class( $rev->getContentHandler() ) );
348 public function provideGetContent() {
349 // NOTE: we expect the help namespace to always contain wikitext
351 [ 'hello world', 'Help:Hello', null, null, Revision
::FOR_PUBLIC
, 'hello world' ],
353 serialize( 'hello world' ),
357 Revision
::FOR_PUBLIC
,
358 serialize( 'hello world' )
361 serialize( 'hello world' ),
365 Revision
::FOR_PUBLIC
,
366 serialize( 'hello world' )
373 * @dataProvider provideGetContent
374 * @covers Revision::getContent
376 public function testGetContent( $text, $title, $model, $format,
377 $audience, $expectedSerialization
379 $rev = $this->newTestRevision( $text, $title, $model, $format );
380 $content = $rev->getContent( $audience );
383 $expectedSerialization,
384 is_null( $content ) ?
null : $content->serialize( $format )
388 public function provideGetSize() {
390 [ "hello world.", CONTENT_MODEL_WIKITEXT
, 12 ],
391 [ serialize( "hello world." ), "testing", 12 ],
396 * @covers Revision::getSize
398 * @dataProvider provideGetSize
400 public function testGetSize( $text, $model, $expected_size ) {
401 $rev = $this->newTestRevision( $text, 'RevisionTest_testGetSize', $model );
402 $this->assertEquals( $expected_size, $rev->getSize() );
405 public function provideGetSha1() {
407 [ "hello world.", CONTENT_MODEL_WIKITEXT
, Revision
::base36Sha1( "hello world." ) ],
409 serialize( "hello world." ),
411 Revision
::base36Sha1( serialize( "hello world." ) )
417 * @covers Revision::getSha1
419 * @dataProvider provideGetSha1
421 public function testGetSha1( $text, $model, $expected_hash ) {
422 $rev = $this->newTestRevision( $text, 'RevisionTest_testGetSha1', $model );
423 $this->assertEquals( $expected_hash, $rev->getSha1() );
427 * Tests whether $rev->getContent() returns a clone when needed.
430 * @covers Revision::getContent
432 public function testGetContentClone() {
433 $content = new RevisionTestModifyableContent( "foo" );
439 'title' => Title
::newFromText( "testGetContentClone_dummy" ),
441 'content' => $content,
442 'length' => $content->getSize(),
443 'comment' => "testing",
444 'minor_edit' => false,
448 /** @var RevisionTestModifyableContent $content */
449 $content = $rev->getContent( Revision
::RAW
);
450 $content->setText( "bar" );
452 /** @var RevisionTestModifyableContent $content2 */
453 $content2 = $rev->getContent( Revision
::RAW
);
454 // content is mutable, expect clone
455 $this->assertNotSame( $content, $content2, "expected a clone" );
456 // clone should contain the original text
457 $this->assertEquals( "foo", $content2->getText() );
459 $content2->setText( "bla bla" );
460 // clones should be independent
461 $this->assertEquals( "bar", $content->getText() );
465 * Tests whether $rev->getContent() returns the same object repeatedly if appropriate.
468 * @covers Revision::getContent
470 public function testGetContentUncloned() {
471 $rev = $this->newTestRevision( "hello", "testGetContentUncloned_dummy", CONTENT_MODEL_WIKITEXT
);
472 $content = $rev->getContent( Revision
::RAW
);
473 $content2 = $rev->getContent( Revision
::RAW
);
475 // for immutable content like wikitext, this should be the same object
476 $this->assertSame( $content, $content2 );