Merge "(bug 37209) Make TextContentTest and WikitextContentTest work in all cases"
[lhc/web/wiklou.git] / tests / phpunit / includes / RevisionTest.php
1 <?php
2
3 /**
4 * @group ContentHandler
5 */
6 class RevisionTest extends MediaWikiTestCase {
7 protected function setUp() {
8 global $wgContLang;
9
10 parent::setUp();
11
12 $this->setMwGlobals( array(
13 'wgContLang' => Language::factory( 'en' ),
14 'wgLanguageCode' => 'en',
15 'wgLegacyEncoding' => false,
16 'wgCompressRevisions' => false,
17
18 'wgContentHandlerTextFallback' => 'ignore',
19 ) );
20
21 $this->mergeMwGlobalArrayValue(
22 'wgExtraNamespaces',
23 array(
24 12312 => 'Dummy',
25 12313 => 'Dummy_talk',
26 )
27 );
28
29 $this->mergeMwGlobalArrayValue(
30 'wgNamespaceContentModels',
31 array(
32 12312 => 'testing',
33 )
34 );
35
36 $this->mergeMwGlobalArrayValue(
37 'wgContentHandlers',
38 array(
39 'testing' => 'DummyContentHandlerForTesting',
40 'RevisionTestModifyableContent' => 'RevisionTestModifyableContentHandler',
41 )
42 );
43
44 MWNamespace::getCanonicalNamespaces( true ); # reset namespace cache
45 $wgContLang->resetNamespaces(); # reset namespace cache
46 }
47
48 function tearDown() {
49 global $wgContLang;
50
51 MWNamespace::getCanonicalNamespaces( true ); # reset namespace cache
52 $wgContLang->resetNamespaces(); # reset namespace cache
53
54 parent::tearDown();
55 }
56
57 function testGetRevisionText() {
58 $row = new stdClass;
59 $row->old_flags = '';
60 $row->old_text = 'This is a bunch of revision text.';
61 $this->assertEquals(
62 'This is a bunch of revision text.',
63 Revision::getRevisionText( $row ) );
64 }
65
66 function testGetRevisionTextGzip() {
67 if ( !function_exists( 'gzdeflate' ) ) {
68 $this->markTestSkipped( 'Gzip compression is not enabled (requires zlib).' );
69 } else {
70 $row = new stdClass;
71 $row->old_flags = 'gzip';
72 $row->old_text = gzdeflate( 'This is a bunch of revision text.' );
73 $this->assertEquals(
74 'This is a bunch of revision text.',
75 Revision::getRevisionText( $row ) );
76 }
77 }
78
79 function testGetRevisionTextUtf8Native() {
80 $row = new stdClass;
81 $row->old_flags = 'utf-8';
82 $row->old_text = "Wiki est l'\xc3\xa9cole superieur !";
83 $GLOBALS['wgLegacyEncoding'] = 'iso-8859-1';
84 $this->assertEquals(
85 "Wiki est l'\xc3\xa9cole superieur !",
86 Revision::getRevisionText( $row ) );
87 }
88
89 function testGetRevisionTextUtf8Legacy() {
90 $row = new stdClass;
91 $row->old_flags = '';
92 $row->old_text = "Wiki est l'\xe9cole superieur !";
93 $GLOBALS['wgLegacyEncoding'] = 'iso-8859-1';
94 $this->assertEquals(
95 "Wiki est l'\xc3\xa9cole superieur !",
96 Revision::getRevisionText( $row ) );
97 }
98
99 function testGetRevisionTextUtf8NativeGzip() {
100 if ( !function_exists( 'gzdeflate' ) ) {
101 $this->markTestSkipped( 'Gzip compression is not enabled (requires zlib).' );
102 } else {
103 $row = new stdClass;
104 $row->old_flags = 'gzip,utf-8';
105 $row->old_text = gzdeflate( "Wiki est l'\xc3\xa9cole superieur !" );
106 $GLOBALS['wgLegacyEncoding'] = 'iso-8859-1';
107 $this->assertEquals(
108 "Wiki est l'\xc3\xa9cole superieur !",
109 Revision::getRevisionText( $row ) );
110 }
111 }
112
113 function testGetRevisionTextUtf8LegacyGzip() {
114 if ( !function_exists( 'gzdeflate' ) ) {
115 $this->markTestSkipped( 'Gzip compression is not enabled (requires zlib).' );
116 } else {
117 $row = new stdClass;
118 $row->old_flags = 'gzip';
119 $row->old_text = gzdeflate( "Wiki est l'\xe9cole superieur !" );
120 $GLOBALS['wgLegacyEncoding'] = 'iso-8859-1';
121 $this->assertEquals(
122 "Wiki est l'\xc3\xa9cole superieur !",
123 Revision::getRevisionText( $row ) );
124 }
125 }
126
127 function testCompressRevisionTextUtf8() {
128 $row = new stdClass;
129 $row->old_text = "Wiki est l'\xc3\xa9cole superieur !";
130 $row->old_flags = Revision::compressRevisionText( $row->old_text );
131 $this->assertTrue( false !== strpos( $row->old_flags, 'utf-8' ),
132 "Flags should contain 'utf-8'" );
133 $this->assertFalse( false !== strpos( $row->old_flags, 'gzip' ),
134 "Flags should not contain 'gzip'" );
135 $this->assertEquals( "Wiki est l'\xc3\xa9cole superieur !",
136 $row->old_text, "Direct check" );
137 $this->assertEquals( "Wiki est l'\xc3\xa9cole superieur !",
138 Revision::getRevisionText( $row ), "getRevisionText" );
139 }
140
141 function testCompressRevisionTextUtf8Gzip() {
142 global $wgCompressRevisions;
143
144 $wgCompressRevisions = true;
145
146 $row = new stdClass;
147 $row->old_text = "Wiki est l'\xc3\xa9cole superieur !";
148 $row->old_flags = Revision::compressRevisionText( $row->old_text );
149 $this->assertTrue( false !== strpos( $row->old_flags, 'utf-8' ),
150 "Flags should contain 'utf-8'" );
151 $this->assertTrue( false !== strpos( $row->old_flags, 'gzip' ),
152 "Flags should contain 'gzip'" );
153 $this->assertEquals( "Wiki est l'\xc3\xa9cole superieur !",
154 gzinflate( $row->old_text ), "Direct check" );
155 $this->assertEquals( "Wiki est l'\xc3\xa9cole superieur !",
156 Revision::getRevisionText( $row ), "getRevisionText" );
157 }
158
159 # =================================================================================================================
160
161 /**
162 * @param string $text
163 * @param string $title
164 * @param string $model
165 * @return Revision
166 */
167 function newTestRevision( $text, $title = "Test", $model = CONTENT_MODEL_WIKITEXT, $format = null ) {
168 if ( is_string( $title ) ) {
169 $title = Title::newFromText( $title );
170 }
171
172 $content = ContentHandler::makeContent( $text, $title, $model, $format );
173
174 $rev = new Revision(
175 array(
176 'id' => 42,
177 'page' => 23,
178 'title' => $title,
179
180 'content' => $content,
181 'length' => $content->getSize(),
182 'comment' => "testing",
183 'minor_edit' => false,
184
185 'content_format' => $format,
186 )
187 );
188
189 return $rev;
190 }
191
192 function dataGetContentModel() {
193 //NOTE: we expect the help namespace to always contain wikitext
194 return array(
195 array( 'hello world', 'Help:Hello', null, null, CONTENT_MODEL_WIKITEXT ),
196 array( 'hello world', 'User:hello/there.css', null, null, CONTENT_MODEL_CSS ),
197 array( serialize('hello world'), 'Dummy:Hello', null, null, "testing" ),
198 );
199 }
200
201 /**
202 * @group Database
203 * @dataProvider dataGetContentModel
204 */
205 function testGetContentModel( $text, $title, $model, $format, $expectedModel ) {
206 $rev = $this->newTestRevision( $text, $title, $model, $format );
207
208 $this->assertEquals( $expectedModel, $rev->getContentModel() );
209 }
210
211 function dataGetContentFormat() {
212 //NOTE: we expect the help namespace to always contain wikitext
213 return array(
214 array( 'hello world', 'Help:Hello', null, null, CONTENT_FORMAT_WIKITEXT ),
215 array( 'hello world', 'Help:Hello', CONTENT_MODEL_CSS, null, CONTENT_FORMAT_CSS ),
216 array( 'hello world', 'User:hello/there.css', null, null, CONTENT_FORMAT_CSS ),
217 array( serialize('hello world'), 'Dummy:Hello', null, null, "testing" ),
218 );
219 }
220
221 /**
222 * @group Database
223 * @dataProvider dataGetContentFormat
224 */
225 function testGetContentFormat( $text, $title, $model, $format, $expectedFormat ) {
226 $rev = $this->newTestRevision( $text, $title, $model, $format );
227
228 $this->assertEquals( $expectedFormat, $rev->getContentFormat() );
229 }
230
231 function dataGetContentHandler() {
232 //NOTE: we expect the help namespace to always contain wikitext
233 return array(
234 array( 'hello world', 'Help:Hello', null, null, 'WikitextContentHandler' ),
235 array( 'hello world', 'User:hello/there.css', null, null, 'CssContentHandler' ),
236 array( serialize('hello world'), 'Dummy:Hello', null, null, 'DummyContentHandlerForTesting' ),
237 );
238 }
239
240 /**
241 * @group Database
242 * @dataProvider dataGetContentHandler
243 */
244 function testGetContentHandler( $text, $title, $model, $format, $expectedClass ) {
245 $rev = $this->newTestRevision( $text, $title, $model, $format );
246
247 $this->assertEquals( $expectedClass, get_class( $rev->getContentHandler() ) );
248 }
249
250 function dataGetContent() {
251 //NOTE: we expect the help namespace to always contain wikitext
252 return array(
253 array( 'hello world', 'Help:Hello', null, null, Revision::FOR_PUBLIC, 'hello world' ),
254 array( serialize('hello world'), 'Hello', "testing", null, Revision::FOR_PUBLIC, serialize('hello world') ),
255 array( serialize('hello world'), 'Dummy:Hello', null, null, Revision::FOR_PUBLIC, serialize('hello world') ),
256 );
257 }
258
259 /**
260 * @group Database
261 * @dataProvider dataGetContent
262 */
263 function testGetContent( $text, $title, $model, $format, $audience, $expectedSerialization ) {
264 $rev = $this->newTestRevision( $text, $title, $model, $format );
265 $content = $rev->getContent( $audience );
266
267 $this->assertEquals( $expectedSerialization, is_null( $content ) ? null : $content->serialize( $format ) );
268 }
269
270 function dataGetText() {
271 //NOTE: we expect the help namespace to always contain wikitext
272 return array(
273 array( 'hello world', 'Help:Hello', null, null, Revision::FOR_PUBLIC, 'hello world' ),
274 array( serialize('hello world'), 'Hello', "testing", null, Revision::FOR_PUBLIC, null ),
275 array( serialize('hello world'), 'Dummy:Hello', null, null, Revision::FOR_PUBLIC, null ),
276 );
277 }
278
279 /**
280 * @group Database
281 * @dataProvider dataGetText
282 */
283 function testGetText( $text, $title, $model, $format, $audience, $expectedText ) {
284 $this->hideDeprecated( 'Revision::getText' );
285
286 $rev = $this->newTestRevision( $text, $title, $model, $format );
287
288 $this->assertEquals( $expectedText, $rev->getText( $audience ) );
289 }
290
291 /**
292 * @group Database
293 * @dataProvider dataGetText
294 */
295 function testGetRawText( $text, $title, $model, $format, $audience, $expectedText ) {
296 $this->hideDeprecated( 'Revision::getRawText' );
297
298 $rev = $this->newTestRevision( $text, $title, $model, $format );
299
300 $this->assertEquals( $expectedText, $rev->getRawText( $audience ) );
301 }
302
303
304 public function dataGetSize( ) {
305 return array(
306 array( "hello world.", CONTENT_MODEL_WIKITEXT, 12 ),
307 array( serialize( "hello world." ), "testing", 12 ),
308 );
309 }
310
311 /**
312 * @covers Revision::getSize
313 * @group Database
314 * @dataProvider dataGetSize
315 */
316 public function testGetSize( $text, $model, $expected_size )
317 {
318 $rev = $this->newTestRevision( $text, 'RevisionTest_testGetSize', $model );
319 $this->assertEquals( $expected_size, $rev->getSize() );
320 }
321
322 public function dataGetSha1( ) {
323 return array(
324 array( "hello world.", CONTENT_MODEL_WIKITEXT, Revision::base36Sha1( "hello world." ) ),
325 array( serialize( "hello world." ), "testing", Revision::base36Sha1( serialize( "hello world." ) ) ),
326 );
327 }
328
329 /**
330 * @covers Revision::getSha1
331 * @group Database
332 * @dataProvider dataGetSha1
333 */
334 public function testGetSha1( $text, $model, $expected_hash )
335 {
336 $rev = $this->newTestRevision( $text, 'RevisionTest_testGetSha1', $model );
337 $this->assertEquals( $expected_hash, $rev->getSha1() );
338 }
339
340 public function testConstructWithText() {
341 $this->hideDeprecated( "Revision::getText" );
342
343 $rev = new Revision( array(
344 'text' => 'hello world.',
345 'content_model' => CONTENT_MODEL_JAVASCRIPT
346 ));
347
348 $this->assertNotNull( $rev->getText(), 'no content text' );
349 $this->assertNotNull( $rev->getContent(), 'no content object available' );
350 $this->assertEquals( CONTENT_MODEL_JAVASCRIPT, $rev->getContent()->getModel() );
351 $this->assertEquals( CONTENT_MODEL_JAVASCRIPT, $rev->getContentModel() );
352 }
353
354 public function testConstructWithContent() {
355 $this->hideDeprecated( "Revision::getText" );
356
357 $title = Title::newFromText( 'RevisionTest_testConstructWithContent' );
358
359 $rev = new Revision( array(
360 'content' => ContentHandler::makeContent( 'hello world.', $title, CONTENT_MODEL_JAVASCRIPT ),
361 ));
362
363 $this->assertNotNull( $rev->getText(), 'no content text' );
364 $this->assertNotNull( $rev->getContent(), 'no content object available' );
365 $this->assertEquals( CONTENT_MODEL_JAVASCRIPT, $rev->getContent()->getModel() );
366 $this->assertEquals( CONTENT_MODEL_JAVASCRIPT, $rev->getContentModel() );
367 }
368
369 /**
370 * Tests whether $rev->getContent() returns a clone when needed.
371 *
372 * @group Database
373 */
374 function testGetContentClone( ) {
375 $content = new RevisionTestModifyableContent( "foo" );
376
377 $rev = new Revision(
378 array(
379 'id' => 42,
380 'page' => 23,
381 'title' => Title::newFromText( "testGetContentClone_dummy" ),
382
383 'content' => $content,
384 'length' => $content->getSize(),
385 'comment' => "testing",
386 'minor_edit' => false,
387 )
388 );
389
390 $content = $rev->getContent( Revision::RAW );
391 $content->setText( "bar" );
392
393 $content2 = $rev->getContent( Revision::RAW );
394 $this->assertNotSame( $content, $content2, "expected a clone" ); // content is mutable, expect clone
395 $this->assertEquals( "foo", $content2->getText() ); // clone should contain the original text
396
397 $content2->setText( "bla bla" );
398 $this->assertEquals( "bar", $content->getText() ); // clones should be independent
399 }
400
401
402 /**
403 * Tests whether $rev->getContent() returns the same object repeatedly if appropriate.
404 *
405 * @group Database
406 */
407 function testGetContentUncloned() {
408 $rev = $this->newTestRevision( "hello", "testGetContentUncloned_dummy", CONTENT_MODEL_WIKITEXT );
409 $content = $rev->getContent( Revision::RAW );
410 $content2 = $rev->getContent( Revision::RAW );
411
412 // for immutable content like wikitext, this should be the same object
413 $this->assertSame( $content, $content2 );
414 }
415
416 }
417
418 class RevisionTestModifyableContent extends TextContent {
419 public function __construct( $text ) {
420 parent::__construct( $text, "RevisionTestModifyableContent" );
421 }
422
423 public function copy( ) {
424 return new RevisionTestModifyableContent( $this->mText );
425 }
426
427 public function getText() {
428 return $this->mText;
429 }
430
431 public function setText( $text ) {
432 $this->mText = $text;
433 }
434
435 }
436
437 class RevisionTestModifyableContentHandler extends TextContentHandler {
438
439 public function __construct( ) {
440 parent::__construct( "RevisionTestModifyableContent", array( CONTENT_FORMAT_TEXT ) );
441 }
442
443 public function unserializeContent( $text, $format = null ) {
444 $this->checkFormat( $format );
445
446 return new RevisionTestModifyableContent( $text );
447 }
448
449 public function makeEmptyContent() {
450 return new RevisionTestModifyableContent( '' );
451 }
452 }