backup_PageTest.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. <?php
  2. namespace MediaWiki\Tests\Maintenance;
  3. use DumpBackup;
  4. use Title;
  5. use WikiExporter;
  6. use WikiPage;
  7. /**
  8. * Tests for page dumps of BackupDumper
  9. *
  10. * @group Database
  11. * @group Dump
  12. * @covers BackupDumper
  13. */
  14. class BackupDumperPageTest extends DumpTestCase {
  15. // We'll add several pages, revision and texts. The following variables hold the
  16. // corresponding ids.
  17. private $pageId1, $pageId2, $pageId3, $pageId4;
  18. private $pageTitle1, $pageTitle2, $pageTitle3, $pageTitle4;
  19. private $revId1_1, $textId1_1;
  20. private $revId2_1, $textId2_1, $revId2_2, $textId2_2;
  21. private $revId2_3, $textId2_3, $revId2_4, $textId2_4;
  22. private $revId3_1, $textId3_1, $revId3_2, $textId3_2;
  23. private $revId4_1, $textId4_1;
  24. private $namespace, $talk_namespace;
  25. function addDBData() {
  26. // be sure, titles created here using english namespace names
  27. $this->setContentLang( 'en' );
  28. $this->tablesUsed[] = 'page';
  29. $this->tablesUsed[] = 'revision';
  30. $this->tablesUsed[] = 'ip_changes';
  31. $this->tablesUsed[] = 'text';
  32. try {
  33. $this->namespace = $this->getDefaultWikitextNS();
  34. $this->talk_namespace = NS_TALK;
  35. if ( $this->namespace === $this->talk_namespace ) {
  36. // @todo work around this.
  37. throw new MWException( "The default wikitext namespace is the talk namespace. "
  38. . " We can't currently deal with that." );
  39. }
  40. $this->pageTitle1 = Title::newFromText( 'BackupDumperTestP1', $this->namespace );
  41. $page = WikiPage::factory( $this->pageTitle1 );
  42. list( $this->revId1_1, $this->textId1_1 ) = $this->addRevision( $page,
  43. "BackupDumperTestP1Text1", "BackupDumperTestP1Summary1" );
  44. $this->pageId1 = $page->getId();
  45. $this->pageTitle2 = Title::newFromText( 'BackupDumperTestP2', $this->namespace );
  46. $page = WikiPage::factory( $this->pageTitle2 );
  47. list( $this->revId2_1, $this->textId2_1 ) = $this->addRevision( $page,
  48. "BackupDumperTestP2Text1", "BackupDumperTestP2Summary1" );
  49. list( $this->revId2_2, $this->textId2_2 ) = $this->addRevision( $page,
  50. "BackupDumperTestP2Text2", "BackupDumperTestP2Summary2" );
  51. list( $this->revId2_3, $this->textId2_3 ) = $this->addRevision( $page,
  52. "BackupDumperTestP2Text3", "BackupDumperTestP2Summary3" );
  53. list( $this->revId2_4, $this->textId2_4 ) = $this->addRevision( $page,
  54. "BackupDumperTestP2Text4 some additional Text ",
  55. "BackupDumperTestP2Summary4 extra " );
  56. $this->pageId2 = $page->getId();
  57. $this->pageTitle3 = Title::newFromText( 'BackupDumperTestP3', $this->namespace );
  58. $page = WikiPage::factory( $this->pageTitle3 );
  59. list( $this->revId3_1, $this->textId3_1 ) = $this->addRevision( $page,
  60. "BackupDumperTestP3Text1", "BackupDumperTestP2Summary1" );
  61. list( $this->revId3_2, $this->textId3_2 ) = $this->addRevision( $page,
  62. "BackupDumperTestP3Text2", "BackupDumperTestP2Summary2" );
  63. $this->pageId3 = $page->getId();
  64. $page->doDeleteArticle( "Testing ;)" );
  65. $this->pageTitle4 = Title::newFromText( 'BackupDumperTestP1', $this->talk_namespace );
  66. $page = WikiPage::factory( $this->pageTitle4 );
  67. list( $this->revId4_1, $this->textId4_1 ) = $this->addRevision( $page,
  68. "Talk about BackupDumperTestP1 Text1",
  69. "Talk BackupDumperTestP1 Summary1" );
  70. $this->pageId4 = $page->getId();
  71. } catch ( Exception $e ) {
  72. // We'd love to pass $e directly. However, ... see
  73. // documentation of exceptionFromAddDBData in
  74. // DumpTestCase
  75. $this->exceptionFromAddDBData = $e;
  76. }
  77. }
  78. protected function setUp() {
  79. parent::setUp();
  80. // Since we will restrict dumping by page ranges (to allow
  81. // working tests, even if the db gets prepopulated by a base
  82. // class), we have to assert, that the page id are consecutively
  83. // increasing
  84. $this->assertEquals(
  85. [ $this->pageId2, $this->pageId3, $this->pageId4 ],
  86. [ $this->pageId1 + 1, $this->pageId2 + 1, $this->pageId3 + 1 ],
  87. "Page ids increasing without holes" );
  88. }
  89. function testFullTextPlain() {
  90. // Preparing the dump
  91. $fname = $this->getNewTempFile();
  92. $dumper = new DumpBackup();
  93. $dumper->loadWithArgv( [ '--full', '--quiet', '--output', 'file:' . $fname ] );
  94. $dumper->startId = $this->pageId1;
  95. $dumper->endId = $this->pageId4 + 1;
  96. $dumper->setDB( $this->db );
  97. // Performing the dump
  98. $dumper->execute();
  99. // Checking the dumped data
  100. $this->assertDumpStart( $fname );
  101. // Page 1
  102. $this->assertPageStart( $this->pageId1, $this->namespace, $this->pageTitle1->getPrefixedText() );
  103. $this->assertRevision( $this->revId1_1, "BackupDumperTestP1Summary1",
  104. $this->textId1_1, 23, "0bolhl6ol7i6x0e7yq91gxgaan39j87",
  105. "BackupDumperTestP1Text1" );
  106. $this->assertPageEnd();
  107. // Page 2
  108. $this->assertPageStart( $this->pageId2, $this->namespace, $this->pageTitle2->getPrefixedText() );
  109. $this->assertRevision( $this->revId2_1, "BackupDumperTestP2Summary1",
  110. $this->textId2_1, 23, "jprywrymfhysqllua29tj3sc7z39dl2",
  111. "BackupDumperTestP2Text1" );
  112. $this->assertRevision( $this->revId2_2, "BackupDumperTestP2Summary2",
  113. $this->textId2_2, 23, "b7vj5ks32po5m1z1t1br4o7scdwwy95",
  114. "BackupDumperTestP2Text2", $this->revId2_1 );
  115. $this->assertRevision( $this->revId2_3, "BackupDumperTestP2Summary3",
  116. $this->textId2_3, 23, "jfunqmh1ssfb8rs43r19w98k28gg56r",
  117. "BackupDumperTestP2Text3", $this->revId2_2 );
  118. $this->assertRevision( $this->revId2_4, "BackupDumperTestP2Summary4 extra",
  119. $this->textId2_4, 44, "6o1ciaxa6pybnqprmungwofc4lv00wv",
  120. "BackupDumperTestP2Text4 some additional Text", $this->revId2_3 );
  121. $this->assertPageEnd();
  122. // Page 3
  123. // -> Page is marked deleted. Hence not visible
  124. // Page 4
  125. $this->assertPageStart(
  126. $this->pageId4,
  127. $this->talk_namespace,
  128. $this->pageTitle4->getPrefixedText()
  129. );
  130. $this->assertRevision( $this->revId4_1, "Talk BackupDumperTestP1 Summary1",
  131. $this->textId4_1, 35, "nktofwzd0tl192k3zfepmlzxoax1lpe",
  132. "Talk about BackupDumperTestP1 Text1" );
  133. $this->assertPageEnd();
  134. $this->assertDumpEnd();
  135. }
  136. function testFullStubPlain() {
  137. // Preparing the dump
  138. $fname = $this->getNewTempFile();
  139. $dumper = new DumpBackup();
  140. $dumper->loadWithArgv( [ '--full', '--quiet', '--output', 'file:' . $fname, '--stub' ] );
  141. $dumper->startId = $this->pageId1;
  142. $dumper->endId = $this->pageId4 + 1;
  143. $dumper->setDB( $this->db );
  144. // Performing the dump
  145. $dumper->execute();
  146. // Checking the dumped data
  147. $this->assertDumpStart( $fname );
  148. // Page 1
  149. $this->assertPageStart( $this->pageId1, $this->namespace, $this->pageTitle1->getPrefixedText() );
  150. $this->assertRevision( $this->revId1_1, "BackupDumperTestP1Summary1",
  151. $this->textId1_1, 23, "0bolhl6ol7i6x0e7yq91gxgaan39j87" );
  152. $this->assertPageEnd();
  153. // Page 2
  154. $this->assertPageStart( $this->pageId2, $this->namespace, $this->pageTitle2->getPrefixedText() );
  155. $this->assertRevision( $this->revId2_1, "BackupDumperTestP2Summary1",
  156. $this->textId2_1, 23, "jprywrymfhysqllua29tj3sc7z39dl2" );
  157. $this->assertRevision( $this->revId2_2, "BackupDumperTestP2Summary2",
  158. $this->textId2_2, 23, "b7vj5ks32po5m1z1t1br4o7scdwwy95", false, $this->revId2_1 );
  159. $this->assertRevision( $this->revId2_3, "BackupDumperTestP2Summary3",
  160. $this->textId2_3, 23, "jfunqmh1ssfb8rs43r19w98k28gg56r", false, $this->revId2_2 );
  161. $this->assertRevision( $this->revId2_4, "BackupDumperTestP2Summary4 extra",
  162. $this->textId2_4, 44, "6o1ciaxa6pybnqprmungwofc4lv00wv", false, $this->revId2_3 );
  163. $this->assertPageEnd();
  164. // Page 3
  165. // -> Page is marked deleted. Hence not visible
  166. // Page 4
  167. $this->assertPageStart(
  168. $this->pageId4,
  169. $this->talk_namespace,
  170. $this->pageTitle4->getPrefixedText()
  171. );
  172. $this->assertRevision( $this->revId4_1, "Talk BackupDumperTestP1 Summary1",
  173. $this->textId4_1, 35, "nktofwzd0tl192k3zfepmlzxoax1lpe" );
  174. $this->assertPageEnd();
  175. $this->assertDumpEnd();
  176. }
  177. function testCurrentStubPlain() {
  178. // Preparing the dump
  179. $fname = $this->getNewTempFile();
  180. $dumper = new DumpBackup( [ '--output', 'file:' . $fname ] );
  181. $dumper->startId = $this->pageId1;
  182. $dumper->endId = $this->pageId4 + 1;
  183. $dumper->reporting = false;
  184. $dumper->setDB( $this->db );
  185. // Performing the dump
  186. $dumper->dump( WikiExporter::CURRENT, WikiExporter::STUB );
  187. // Checking the dumped data
  188. $this->assertDumpStart( $fname );
  189. // Page 1
  190. $this->assertPageStart( $this->pageId1, $this->namespace, $this->pageTitle1->getPrefixedText() );
  191. $this->assertRevision( $this->revId1_1, "BackupDumperTestP1Summary1",
  192. $this->textId1_1, 23, "0bolhl6ol7i6x0e7yq91gxgaan39j87" );
  193. $this->assertPageEnd();
  194. // Page 2
  195. $this->assertPageStart( $this->pageId2, $this->namespace, $this->pageTitle2->getPrefixedText() );
  196. $this->assertRevision( $this->revId2_4, "BackupDumperTestP2Summary4 extra",
  197. $this->textId2_4, 44, "6o1ciaxa6pybnqprmungwofc4lv00wv", false, $this->revId2_3 );
  198. $this->assertPageEnd();
  199. // Page 3
  200. // -> Page is marked deleted. Hence not visible
  201. // Page 4
  202. $this->assertPageStart(
  203. $this->pageId4,
  204. $this->talk_namespace,
  205. $this->pageTitle4->getPrefixedText()
  206. );
  207. $this->assertRevision( $this->revId4_1, "Talk BackupDumperTestP1 Summary1",
  208. $this->textId4_1, 35, "nktofwzd0tl192k3zfepmlzxoax1lpe" );
  209. $this->assertPageEnd();
  210. $this->assertDumpEnd();
  211. }
  212. function testCurrentStubGzip() {
  213. $this->checkHasGzip();
  214. // Preparing the dump
  215. $fname = $this->getNewTempFile();
  216. $dumper = new DumpBackup( [ '--output', 'gzip:' . $fname ] );
  217. $dumper->startId = $this->pageId1;
  218. $dumper->endId = $this->pageId4 + 1;
  219. $dumper->reporting = false;
  220. $dumper->setDB( $this->db );
  221. // Performing the dump
  222. $dumper->dump( WikiExporter::CURRENT, WikiExporter::STUB );
  223. // Checking the dumped data
  224. $this->gunzip( $fname );
  225. $this->assertDumpStart( $fname );
  226. // Page 1
  227. $this->assertPageStart( $this->pageId1, $this->namespace, $this->pageTitle1->getPrefixedText() );
  228. $this->assertRevision( $this->revId1_1, "BackupDumperTestP1Summary1",
  229. $this->textId1_1, 23, "0bolhl6ol7i6x0e7yq91gxgaan39j87" );
  230. $this->assertPageEnd();
  231. // Page 2
  232. $this->assertPageStart( $this->pageId2, $this->namespace, $this->pageTitle2->getPrefixedText() );
  233. $this->assertRevision( $this->revId2_4, "BackupDumperTestP2Summary4 extra",
  234. $this->textId2_4, 44, "6o1ciaxa6pybnqprmungwofc4lv00wv", false, $this->revId2_3 );
  235. $this->assertPageEnd();
  236. // Page 3
  237. // -> Page is marked deleted. Hence not visible
  238. // Page 4
  239. $this->assertPageStart(
  240. $this->pageId4,
  241. $this->talk_namespace,
  242. $this->pageTitle4->getPrefixedText()
  243. );
  244. $this->assertRevision( $this->revId4_1, "Talk BackupDumperTestP1 Summary1",
  245. $this->textId4_1, 35, "nktofwzd0tl192k3zfepmlzxoax1lpe" );
  246. $this->assertPageEnd();
  247. $this->assertDumpEnd();
  248. }
  249. /**
  250. * xmldumps-backup typically performs a single dump that that writes
  251. * out three files
  252. * - gzipped stubs of everything (meta-history)
  253. * - gzipped stubs of latest revisions of all pages (meta-current)
  254. * - gzipped stubs of latest revisions of all pages of namespage 0
  255. * (articles)
  256. *
  257. * We reproduce such a setup with our mini fixture, although we omit
  258. * chunks, and all the other gimmicks of xmldumps-backup.
  259. */
  260. function testXmlDumpsBackupUseCase() {
  261. $this->checkHasGzip();
  262. $fnameMetaHistory = $this->getNewTempFile();
  263. $fnameMetaCurrent = $this->getNewTempFile();
  264. $fnameArticles = $this->getNewTempFile();
  265. $dumper = new DumpBackup( [ "--full", "--stub", "--output=gzip:" . $fnameMetaHistory,
  266. "--output=gzip:" . $fnameMetaCurrent, "--filter=latest",
  267. "--output=gzip:" . $fnameArticles, "--filter=latest",
  268. "--filter=notalk", "--filter=namespace:!NS_USER",
  269. "--reporting=1000" ] );
  270. $dumper->startId = $this->pageId1;
  271. $dumper->endId = $this->pageId4 + 1;
  272. $dumper->setDB( $this->db );
  273. // xmldumps-backup uses reporting. We will not check the exact reported
  274. // message, as they are dependent on the processing power of the used
  275. // computer. We only check that reporting does not crash the dumping
  276. // and that something is reported
  277. $dumper->stderr = fopen( 'php://output', 'a' );
  278. if ( $dumper->stderr === false ) {
  279. $this->fail( "Could not open stream for stderr" );
  280. }
  281. // Performing the dump
  282. $dumper->dump( WikiExporter::FULL, WikiExporter::STUB );
  283. $this->assertTrue( fclose( $dumper->stderr ), "Closing stderr handle" );
  284. // Checking meta-history -------------------------------------------------
  285. $this->gunzip( $fnameMetaHistory );
  286. $this->assertDumpStart( $fnameMetaHistory );
  287. // Page 1
  288. $this->assertPageStart( $this->pageId1, $this->namespace, $this->pageTitle1->getPrefixedText() );
  289. $this->assertRevision( $this->revId1_1, "BackupDumperTestP1Summary1",
  290. $this->textId1_1, 23, "0bolhl6ol7i6x0e7yq91gxgaan39j87" );
  291. $this->assertPageEnd();
  292. // Page 2
  293. $this->assertPageStart( $this->pageId2, $this->namespace, $this->pageTitle2->getPrefixedText() );
  294. $this->assertRevision( $this->revId2_1, "BackupDumperTestP2Summary1",
  295. $this->textId2_1, 23, "jprywrymfhysqllua29tj3sc7z39dl2" );
  296. $this->assertRevision( $this->revId2_2, "BackupDumperTestP2Summary2",
  297. $this->textId2_2, 23, "b7vj5ks32po5m1z1t1br4o7scdwwy95", false, $this->revId2_1 );
  298. $this->assertRevision( $this->revId2_3, "BackupDumperTestP2Summary3",
  299. $this->textId2_3, 23, "jfunqmh1ssfb8rs43r19w98k28gg56r", false, $this->revId2_2 );
  300. $this->assertRevision( $this->revId2_4, "BackupDumperTestP2Summary4 extra",
  301. $this->textId2_4, 44, "6o1ciaxa6pybnqprmungwofc4lv00wv", false, $this->revId2_3 );
  302. $this->assertPageEnd();
  303. // Page 3
  304. // -> Page is marked deleted. Hence not visible
  305. // Page 4
  306. $this->assertPageStart(
  307. $this->pageId4,
  308. $this->talk_namespace,
  309. $this->pageTitle4->getPrefixedText()
  310. );
  311. $this->assertRevision( $this->revId4_1, "Talk BackupDumperTestP1 Summary1",
  312. $this->textId4_1, 35, "nktofwzd0tl192k3zfepmlzxoax1lpe" );
  313. $this->assertPageEnd();
  314. $this->assertDumpEnd();
  315. // Checking meta-current -------------------------------------------------
  316. $this->gunzip( $fnameMetaCurrent );
  317. $this->assertDumpStart( $fnameMetaCurrent );
  318. // Page 1
  319. $this->assertPageStart( $this->pageId1, $this->namespace, $this->pageTitle1->getPrefixedText() );
  320. $this->assertRevision( $this->revId1_1, "BackupDumperTestP1Summary1",
  321. $this->textId1_1, 23, "0bolhl6ol7i6x0e7yq91gxgaan39j87" );
  322. $this->assertPageEnd();
  323. // Page 2
  324. $this->assertPageStart( $this->pageId2, $this->namespace, $this->pageTitle2->getPrefixedText() );
  325. $this->assertRevision( $this->revId2_4, "BackupDumperTestP2Summary4 extra",
  326. $this->textId2_4, 44, "6o1ciaxa6pybnqprmungwofc4lv00wv", false, $this->revId2_3 );
  327. $this->assertPageEnd();
  328. // Page 3
  329. // -> Page is marked deleted. Hence not visible
  330. // Page 4
  331. $this->assertPageStart(
  332. $this->pageId4,
  333. $this->talk_namespace,
  334. $this->pageTitle4->getPrefixedText()
  335. );
  336. $this->assertRevision( $this->revId4_1, "Talk BackupDumperTestP1 Summary1",
  337. $this->textId4_1, 35, "nktofwzd0tl192k3zfepmlzxoax1lpe" );
  338. $this->assertPageEnd();
  339. $this->assertDumpEnd();
  340. // Checking articles -------------------------------------------------
  341. $this->gunzip( $fnameArticles );
  342. $this->assertDumpStart( $fnameArticles );
  343. // Page 1
  344. $this->assertPageStart( $this->pageId1, $this->namespace, $this->pageTitle1->getPrefixedText() );
  345. $this->assertRevision( $this->revId1_1, "BackupDumperTestP1Summary1",
  346. $this->textId1_1, 23, "0bolhl6ol7i6x0e7yq91gxgaan39j87" );
  347. $this->assertPageEnd();
  348. // Page 2
  349. $this->assertPageStart( $this->pageId2, $this->namespace, $this->pageTitle2->getPrefixedText() );
  350. $this->assertRevision( $this->revId2_4, "BackupDumperTestP2Summary4 extra",
  351. $this->textId2_4, 44, "6o1ciaxa6pybnqprmungwofc4lv00wv", false, $this->revId2_3 );
  352. $this->assertPageEnd();
  353. // Page 3
  354. // -> Page is marked deleted. Hence not visible
  355. // Page 4
  356. // -> Page is not in $this->namespace. Hence not visible
  357. $this->assertDumpEnd();
  358. $this->expectETAOutput();
  359. }
  360. }