PageRenderTime 40ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/phpunit/includes/RevisionTest.php

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