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