MediaWiki
REL1_24
|
00001 <?php 00002 00003 require_once __DIR__ . "/../../../maintenance/backupTextPass.inc"; 00004 00012 class TextPassDumperTest extends DumpTestCase { 00013 00014 // We'll add several pages, revision and texts. The following variables hold the 00015 // corresponding ids. 00016 private $pageId1, $pageId2, $pageId3, $pageId4; 00017 private static $numOfPages = 4; 00018 private $revId1_1, $textId1_1; 00019 private $revId2_1, $textId2_1, $revId2_2, $textId2_2; 00020 private $revId2_3, $textId2_3, $revId2_4, $textId2_4; 00021 private $revId3_1, $textId3_1, $revId3_2, $textId3_2; 00022 private $revId4_1, $textId4_1; 00023 private static $numOfRevs = 8; 00024 00025 function addDBData() { 00026 $this->tablesUsed[] = 'page'; 00027 $this->tablesUsed[] = 'revision'; 00028 $this->tablesUsed[] = 'text'; 00029 00030 $ns = $this->getDefaultWikitextNS(); 00031 00032 try { 00033 // Simple page 00034 $title = Title::newFromText( 'BackupDumperTestP1', $ns ); 00035 $page = WikiPage::factory( $title ); 00036 list( $this->revId1_1, $this->textId1_1 ) = $this->addRevision( $page, 00037 "BackupDumperTestP1Text1", "BackupDumperTestP1Summary1" ); 00038 $this->pageId1 = $page->getId(); 00039 00040 // Page with more than one revision 00041 $title = Title::newFromText( 'BackupDumperTestP2', $ns ); 00042 $page = WikiPage::factory( $title ); 00043 list( $this->revId2_1, $this->textId2_1 ) = $this->addRevision( $page, 00044 "BackupDumperTestP2Text1", "BackupDumperTestP2Summary1" ); 00045 list( $this->revId2_2, $this->textId2_2 ) = $this->addRevision( $page, 00046 "BackupDumperTestP2Text2", "BackupDumperTestP2Summary2" ); 00047 list( $this->revId2_3, $this->textId2_3 ) = $this->addRevision( $page, 00048 "BackupDumperTestP2Text3", "BackupDumperTestP2Summary3" ); 00049 list( $this->revId2_4, $this->textId2_4 ) = $this->addRevision( $page, 00050 "BackupDumperTestP2Text4 some additional Text ", 00051 "BackupDumperTestP2Summary4 extra " ); 00052 $this->pageId2 = $page->getId(); 00053 00054 // Deleted page. 00055 $title = Title::newFromText( 'BackupDumperTestP3', $ns ); 00056 $page = WikiPage::factory( $title ); 00057 list( $this->revId3_1, $this->textId3_1 ) = $this->addRevision( $page, 00058 "BackupDumperTestP3Text1", "BackupDumperTestP2Summary1" ); 00059 list( $this->revId3_2, $this->textId3_2 ) = $this->addRevision( $page, 00060 "BackupDumperTestP3Text2", "BackupDumperTestP2Summary2" ); 00061 $this->pageId3 = $page->getId(); 00062 $page->doDeleteArticle( "Testing ;)" ); 00063 00064 // Page from non-default namespace 00065 00066 if ( $ns === NS_TALK ) { 00067 // @todo work around this. 00068 throw new MWException( "The default wikitext namespace is the talk namespace. " 00069 . " We can't currently deal with that." ); 00070 } 00071 00072 $title = Title::newFromText( 'BackupDumperTestP1', NS_TALK ); 00073 $page = WikiPage::factory( $title ); 00074 list( $this->revId4_1, $this->textId4_1 ) = $this->addRevision( $page, 00075 "Talk about BackupDumperTestP1 Text1", 00076 "Talk BackupDumperTestP1 Summary1" ); 00077 $this->pageId4 = $page->getId(); 00078 } catch ( Exception $e ) { 00079 // We'd love to pass $e directly. However, ... see 00080 // documentation of exceptionFromAddDBData in 00081 // DumpTestCase 00082 $this->exceptionFromAddDBData = $e; 00083 } 00084 } 00085 00086 protected function setUp() { 00087 parent::setUp(); 00088 00089 // Since we will restrict dumping by page ranges (to allow 00090 // working tests, even if the db gets prepopulated by a base 00091 // class), we have to assert, that the page id are consecutively 00092 // increasing 00093 $this->assertEquals( 00094 array( $this->pageId2, $this->pageId3, $this->pageId4 ), 00095 array( $this->pageId1 + 1, $this->pageId2 + 1, $this->pageId3 + 1 ), 00096 "Page ids increasing without holes" ); 00097 } 00098 00099 function testPlain() { 00100 // Setting up the dump 00101 $nameStub = $this->setUpStub(); 00102 $nameFull = $this->getNewTempFile(); 00103 $dumper = new TextPassDumper( array( "--stub=file:" . $nameStub, 00104 "--output=file:" . $nameFull ) ); 00105 $dumper->reporting = false; 00106 $dumper->setDb( $this->db ); 00107 00108 // Performing the dump 00109 $dumper->dump( WikiExporter::FULL, WikiExporter::TEXT ); 00110 00111 // Checking for correctness of the dumped data 00112 $this->assertDumpStart( $nameFull ); 00113 00114 // Page 1 00115 $this->assertPageStart( $this->pageId1, NS_MAIN, "BackupDumperTestP1" ); 00116 $this->assertRevision( $this->revId1_1, "BackupDumperTestP1Summary1", 00117 $this->textId1_1, false, "0bolhl6ol7i6x0e7yq91gxgaan39j87", 00118 "BackupDumperTestP1Text1" ); 00119 $this->assertPageEnd(); 00120 00121 // Page 2 00122 $this->assertPageStart( $this->pageId2, NS_MAIN, "BackupDumperTestP2" ); 00123 $this->assertRevision( $this->revId2_1, "BackupDumperTestP2Summary1", 00124 $this->textId2_1, false, "jprywrymfhysqllua29tj3sc7z39dl2", 00125 "BackupDumperTestP2Text1" ); 00126 $this->assertRevision( $this->revId2_2, "BackupDumperTestP2Summary2", 00127 $this->textId2_2, false, "b7vj5ks32po5m1z1t1br4o7scdwwy95", 00128 "BackupDumperTestP2Text2", $this->revId2_1 ); 00129 $this->assertRevision( $this->revId2_3, "BackupDumperTestP2Summary3", 00130 $this->textId2_3, false, "jfunqmh1ssfb8rs43r19w98k28gg56r", 00131 "BackupDumperTestP2Text3", $this->revId2_2 ); 00132 $this->assertRevision( $this->revId2_4, "BackupDumperTestP2Summary4 extra", 00133 $this->textId2_4, false, "6o1ciaxa6pybnqprmungwofc4lv00wv", 00134 "BackupDumperTestP2Text4 some additional Text", $this->revId2_3 ); 00135 $this->assertPageEnd(); 00136 00137 // Page 3 00138 // -> Page is marked deleted. Hence not visible 00139 00140 // Page 4 00141 $this->assertPageStart( $this->pageId4, NS_TALK, "Talk:BackupDumperTestP1" ); 00142 $this->assertRevision( $this->revId4_1, "Talk BackupDumperTestP1 Summary1", 00143 $this->textId4_1, false, "nktofwzd0tl192k3zfepmlzxoax1lpe", 00144 "Talk about BackupDumperTestP1 Text1" ); 00145 $this->assertPageEnd(); 00146 00147 $this->assertDumpEnd(); 00148 } 00149 00150 function testPrefetchPlain() { 00151 // The mapping between ids and text, for the hits of the prefetch mock 00152 $prefetchMap = array( 00153 array( $this->pageId1, $this->revId1_1, "Prefetch_________1Text1" ), 00154 array( $this->pageId2, $this->revId2_3, "Prefetch_________2Text3" ) 00155 ); 00156 00157 // The mock itself 00158 $prefetchMock = $this->getMock( 'BaseDump', array( 'prefetch' ), array(), '', false ); 00159 $prefetchMock->expects( $this->exactly( 6 ) ) 00160 ->method( 'prefetch' ) 00161 ->will( $this->returnValueMap( $prefetchMap ) ); 00162 00163 // Setting up of the dump 00164 $nameStub = $this->setUpStub(); 00165 $nameFull = $this->getNewTempFile(); 00166 $dumper = new TextPassDumper( array( "--stub=file:" 00167 . $nameStub, "--output=file:" . $nameFull ) ); 00168 $dumper->prefetch = $prefetchMock; 00169 $dumper->reporting = false; 00170 $dumper->setDb( $this->db ); 00171 00172 // Performing the dump 00173 $dumper->dump( WikiExporter::FULL, WikiExporter::TEXT ); 00174 00175 // Checking for correctness of the dumped data 00176 $this->assertDumpStart( $nameFull ); 00177 00178 // Page 1 00179 $this->assertPageStart( $this->pageId1, NS_MAIN, "BackupDumperTestP1" ); 00180 // Prefetch kicks in. This is still the SHA-1 of the original text, 00181 // But the actual text (with different SHA-1) comes from prefetch. 00182 $this->assertRevision( $this->revId1_1, "BackupDumperTestP1Summary1", 00183 $this->textId1_1, false, "0bolhl6ol7i6x0e7yq91gxgaan39j87", 00184 "Prefetch_________1Text1" ); 00185 $this->assertPageEnd(); 00186 00187 // Page 2 00188 $this->assertPageStart( $this->pageId2, NS_MAIN, "BackupDumperTestP2" ); 00189 $this->assertRevision( $this->revId2_1, "BackupDumperTestP2Summary1", 00190 $this->textId2_1, false, "jprywrymfhysqllua29tj3sc7z39dl2", 00191 "BackupDumperTestP2Text1" ); 00192 $this->assertRevision( $this->revId2_2, "BackupDumperTestP2Summary2", 00193 $this->textId2_2, false, "b7vj5ks32po5m1z1t1br4o7scdwwy95", 00194 "BackupDumperTestP2Text2", $this->revId2_1 ); 00195 // Prefetch kicks in. This is still the SHA-1 of the original text, 00196 // But the actual text (with different SHA-1) comes from prefetch. 00197 $this->assertRevision( $this->revId2_3, "BackupDumperTestP2Summary3", 00198 $this->textId2_3, false, "jfunqmh1ssfb8rs43r19w98k28gg56r", 00199 "Prefetch_________2Text3", $this->revId2_2 ); 00200 $this->assertRevision( $this->revId2_4, "BackupDumperTestP2Summary4 extra", 00201 $this->textId2_4, false, "6o1ciaxa6pybnqprmungwofc4lv00wv", 00202 "BackupDumperTestP2Text4 some additional Text", $this->revId2_3 ); 00203 $this->assertPageEnd(); 00204 00205 // Page 3 00206 // -> Page is marked deleted. Hence not visible 00207 00208 // Page 4 00209 $this->assertPageStart( $this->pageId4, NS_TALK, "Talk:BackupDumperTestP1" ); 00210 $this->assertRevision( $this->revId4_1, "Talk BackupDumperTestP1 Summary1", 00211 $this->textId4_1, false, "nktofwzd0tl192k3zfepmlzxoax1lpe", 00212 "Talk about BackupDumperTestP1 Text1" ); 00213 $this->assertPageEnd(); 00214 00215 $this->assertDumpEnd(); 00216 } 00217 00225 private function checkpointHelper( $checkpointFormat = "file" ) { 00226 // Getting temporary names 00227 $nameStub = $this->getNewTempFile(); 00228 $nameOutputDir = $this->getNewTempDirectory(); 00229 00230 $stderr = fopen( 'php://output', 'a' ); 00231 if ( $stderr === false ) { 00232 $this->fail( "Could not open stream for stderr" ); 00233 } 00234 00235 $iterations = 32; // We'll start with that many iterations of revisions in stub 00236 $lastDuration = 0; 00237 $minDuration = 2; // We want the dump to take at least this many seconds 00238 $checkpointAfter = 0.5; // Generate checkpoint after this many seconds 00239 00240 // Until a dump takes at least $minDuration seconds, perform a dump and check 00241 // duration. If the dump did not take long enough increase the iteration 00242 // count, to generate a bigger stub file next time. 00243 while ( $lastDuration < $minDuration ) { 00244 00245 // Setting up the dump 00246 wfRecursiveRemoveDir( $nameOutputDir ); 00247 $this->assertTrue( wfMkdirParents( $nameOutputDir ), 00248 "Creating temporary output directory " ); 00249 $this->setUpStub( $nameStub, $iterations ); 00250 $dumper = new TextPassDumper( array( "--stub=file:" . $nameStub, 00251 "--output=" . $checkpointFormat . ":" . $nameOutputDir . "/full", 00252 "--maxtime=1" /*This is in minutes. Fixup is below*/, 00253 "--checkpointfile=checkpoint-%s-%s.xml.gz" ) ); 00254 $dumper->setDb( $this->db ); 00255 $dumper->maxTimeAllowed = $checkpointAfter; // Patching maxTime from 1 minute 00256 $dumper->stderr = $stderr; 00257 00258 // The actual dump and taking time 00259 $ts_before = microtime( true ); 00260 $dumper->dump( WikiExporter::FULL, WikiExporter::TEXT ); 00261 $ts_after = microtime( true ); 00262 $lastDuration = $ts_after - $ts_before; 00263 00264 // Handling increasing the iteration count for the stubs 00265 if ( $lastDuration < $minDuration ) { 00266 $old_iterations = $iterations; 00267 if ( $lastDuration > 0.2 ) { 00268 // lastDuration is big enough, to allow an educated guess 00269 $factor = ( $minDuration + 0.5 ) / $lastDuration; 00270 if ( ( $factor > 1.1 ) && ( $factor < 100 ) ) { 00271 // educated guess is reasonable 00272 $iterations = (int)( $iterations * $factor ); 00273 } 00274 } 00275 00276 if ( $old_iterations == $iterations ) { 00277 // Heuristics were not applied, so we just *2. 00278 $iterations *= 2; 00279 } 00280 00281 $this->assertLessThan( 50000, $iterations, 00282 "Emergency stop against infinitely increasing iteration " 00283 . "count ( last duration: $lastDuration )" ); 00284 } 00285 } 00286 00287 // The dump (hopefully) did take long enough to produce more than one 00288 // checkpoint file. 00289 // 00290 // We now check all the checkpoint files for validity. 00291 00292 $files = scandir( $nameOutputDir ); 00293 $this->assertTrue( asort( $files ), "Sorting files in temporary directory" ); 00294 $fileOpened = false; 00295 $lookingForPage = 1; 00296 $checkpointFiles = 0; 00297 00298 // Each run of the following loop body tries to handle exactly 1 /page/ (not 00299 // iteration of stub content). $i is only increased after having treated page 4. 00300 for ( $i = 0; $i < $iterations; ) { 00301 00302 // 1. Assuring a file is opened and ready. Skipping across header if 00303 // necessary. 00304 if ( !$fileOpened ) { 00305 $this->assertNotEmpty( $files, "No more existing dump files, " 00306 . "but not yet all pages found" ); 00307 $fname = array_shift( $files ); 00308 while ( $fname == "." || $fname == ".." ) { 00309 $this->assertNotEmpty( $files, "No more existing dump" 00310 . " files, but not yet all pages found" ); 00311 $fname = array_shift( $files ); 00312 } 00313 if ( $checkpointFormat == "gzip" ) { 00314 $this->gunzip( $nameOutputDir . "/" . $fname ); 00315 } 00316 $this->assertDumpStart( $nameOutputDir . "/" . $fname ); 00317 $fileOpened = true; 00318 $checkpointFiles++; 00319 } 00320 00321 // 2. Performing a single page check 00322 switch ( $lookingForPage ) { 00323 case 1: 00324 // Page 1 00325 $this->assertPageStart( $this->pageId1 + $i * self::$numOfPages, NS_MAIN, 00326 "BackupDumperTestP1" ); 00327 $this->assertRevision( $this->revId1_1 + $i * self::$numOfRevs, "BackupDumperTestP1Summary1", 00328 $this->textId1_1, false, "0bolhl6ol7i6x0e7yq91gxgaan39j87", 00329 "BackupDumperTestP1Text1" ); 00330 $this->assertPageEnd(); 00331 00332 $lookingForPage = 2; 00333 break; 00334 00335 case 2: 00336 // Page 2 00337 $this->assertPageStart( $this->pageId2 + $i * self::$numOfPages, NS_MAIN, 00338 "BackupDumperTestP2" ); 00339 $this->assertRevision( $this->revId2_1 + $i * self::$numOfRevs, "BackupDumperTestP2Summary1", 00340 $this->textId2_1, false, "jprywrymfhysqllua29tj3sc7z39dl2", 00341 "BackupDumperTestP2Text1" ); 00342 $this->assertRevision( $this->revId2_2 + $i * self::$numOfRevs, "BackupDumperTestP2Summary2", 00343 $this->textId2_2, false, "b7vj5ks32po5m1z1t1br4o7scdwwy95", 00344 "BackupDumperTestP2Text2", $this->revId2_1 + $i * self::$numOfRevs ); 00345 $this->assertRevision( $this->revId2_3 + $i * self::$numOfRevs, "BackupDumperTestP2Summary3", 00346 $this->textId2_3, false, "jfunqmh1ssfb8rs43r19w98k28gg56r", 00347 "BackupDumperTestP2Text3", $this->revId2_2 + $i * self::$numOfRevs ); 00348 $this->assertRevision( $this->revId2_4 + $i * self::$numOfRevs, 00349 "BackupDumperTestP2Summary4 extra", 00350 $this->textId2_4, false, "6o1ciaxa6pybnqprmungwofc4lv00wv", 00351 "BackupDumperTestP2Text4 some additional Text", 00352 $this->revId2_3 + $i * self::$numOfRevs ); 00353 $this->assertPageEnd(); 00354 00355 $lookingForPage = 4; 00356 break; 00357 00358 case 4: 00359 // Page 4 00360 $this->assertPageStart( $this->pageId4 + $i * self::$numOfPages, NS_TALK, 00361 "Talk:BackupDumperTestP1" ); 00362 $this->assertRevision( $this->revId4_1 + $i * self::$numOfRevs, 00363 "Talk BackupDumperTestP1 Summary1", 00364 $this->textId4_1, false, "nktofwzd0tl192k3zfepmlzxoax1lpe", 00365 "Talk about BackupDumperTestP1 Text1" ); 00366 $this->assertPageEnd(); 00367 00368 $lookingForPage = 1; 00369 00370 // We dealt with the whole iteration. 00371 $i++; 00372 break; 00373 00374 default: 00375 $this->fail( "Bad setting for lookingForPage ($lookingForPage)" ); 00376 } 00377 00378 // 3. Checking for the end of the current checkpoint file 00379 if ( $this->xml->nodeType == XMLReader::END_ELEMENT 00380 && $this->xml->name == "mediawiki" 00381 ) { 00382 $this->assertDumpEnd(); 00383 $fileOpened = false; 00384 } 00385 } 00386 00387 // Assuring we completely read all files ... 00388 $this->assertFalse( $fileOpened, "Currently read file still open?" ); 00389 $this->assertEmpty( $files, "Remaining unchecked files" ); 00390 00391 // ... and have dealt with more than one checkpoint file 00392 $this->assertGreaterThan( 00393 1, 00394 $checkpointFiles, 00395 "expected more than 1 checkpoint to have been created. " 00396 . "Checkpoint interval is $checkpointAfter seconds, maybe your computer is too fast?" 00397 ); 00398 00399 $this->expectETAOutput(); 00400 } 00401 00405 function testCheckpointPlain() { 00406 $this->checkpointHelper(); 00407 } 00408 00421 function testCheckpointGzip() { 00422 $this->checkHasGzip(); 00423 $this->checkpointHelper( "gzip" ); 00424 } 00425 00439 private function setUpStub( $fname = null, $iterations = 1 ) { 00440 if ( $fname === null ) { 00441 $fname = $this->getNewTempFile(); 00442 } 00443 $header = '<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.7/" ' 00444 . 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ' 00445 . 'xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.7/ ' 00446 . 'http://www.mediawiki.org/xml/export-0.7.xsd" version="0.7" xml:lang="en"> 00447 <siteinfo> 00448 <sitename>wikisvn</sitename> 00449 <base>http://localhost/wiki-svn/index.php/Main_Page</base> 00450 <generator>MediaWiki 1.21alpha</generator> 00451 <case>first-letter</case> 00452 <namespaces> 00453 <namespace key="-2" case="first-letter">Media</namespace> 00454 <namespace key="-1" case="first-letter">Special</namespace> 00455 <namespace key="0" case="first-letter" /> 00456 <namespace key="1" case="first-letter">Talk</namespace> 00457 <namespace key="2" case="first-letter">User</namespace> 00458 <namespace key="3" case="first-letter">User talk</namespace> 00459 <namespace key="4" case="first-letter">Wikisvn</namespace> 00460 <namespace key="5" case="first-letter">Wikisvn talk</namespace> 00461 <namespace key="6" case="first-letter">File</namespace> 00462 <namespace key="7" case="first-letter">File talk</namespace> 00463 <namespace key="8" case="first-letter">MediaWiki</namespace> 00464 <namespace key="9" case="first-letter">MediaWiki talk</namespace> 00465 <namespace key="10" case="first-letter">Template</namespace> 00466 <namespace key="11" case="first-letter">Template talk</namespace> 00467 <namespace key="12" case="first-letter">Help</namespace> 00468 <namespace key="13" case="first-letter">Help talk</namespace> 00469 <namespace key="14" case="first-letter">Category</namespace> 00470 <namespace key="15" case="first-letter">Category talk</namespace> 00471 </namespaces> 00472 </siteinfo> 00473 '; 00474 $tail = '</mediawiki> 00475 '; 00476 00477 $content = $header; 00478 $iterations = intval( $iterations ); 00479 for ( $i = 0; $i < $iterations; $i++ ) { 00480 00481 $page1 = ' <page> 00482 <title>BackupDumperTestP1</title> 00483 <ns>0</ns> 00484 <id>' . ( $this->pageId1 + $i * self::$numOfPages ) . '</id> 00485 <revision> 00486 <id>' . ( $this->revId1_1 + $i * self::$numOfRevs ) . '</id> 00487 <timestamp>2012-04-01T16:46:05Z</timestamp> 00488 <contributor> 00489 <ip>127.0.0.1</ip> 00490 </contributor> 00491 <comment>BackupDumperTestP1Summary1</comment> 00492 <sha1>0bolhl6ol7i6x0e7yq91gxgaan39j87</sha1> 00493 <model>wikitext</model> 00494 <format>text/x-wiki</format> 00495 <text id="' . $this->textId1_1 . '" bytes="23" /> 00496 </revision> 00497 </page> 00498 '; 00499 $page2 = ' <page> 00500 <title>BackupDumperTestP2</title> 00501 <ns>0</ns> 00502 <id>' . ( $this->pageId2 + $i * self::$numOfPages ) . '</id> 00503 <revision> 00504 <id>' . ( $this->revId2_1 + $i * self::$numOfRevs ) . '</id> 00505 <timestamp>2012-04-01T16:46:05Z</timestamp> 00506 <contributor> 00507 <ip>127.0.0.1</ip> 00508 </contributor> 00509 <comment>BackupDumperTestP2Summary1</comment> 00510 <sha1>jprywrymfhysqllua29tj3sc7z39dl2</sha1> 00511 <model>wikitext</model> 00512 <format>text/x-wiki</format> 00513 <text id="' . $this->textId2_1 . '" bytes="23" /> 00514 </revision> 00515 <revision> 00516 <id>' . ( $this->revId2_2 + $i * self::$numOfRevs ) . '</id> 00517 <parentid>' . ( $this->revId2_1 + $i * self::$numOfRevs ) . '</parentid> 00518 <timestamp>2012-04-01T16:46:05Z</timestamp> 00519 <contributor> 00520 <ip>127.0.0.1</ip> 00521 </contributor> 00522 <comment>BackupDumperTestP2Summary2</comment> 00523 <sha1>b7vj5ks32po5m1z1t1br4o7scdwwy95</sha1> 00524 <model>wikitext</model> 00525 <format>text/x-wiki</format> 00526 <text id="' . $this->textId2_2 . '" bytes="23" /> 00527 </revision> 00528 <revision> 00529 <id>' . ( $this->revId2_3 + $i * self::$numOfRevs ) . '</id> 00530 <parentid>' . ( $this->revId2_2 + $i * self::$numOfRevs ) . '</parentid> 00531 <timestamp>2012-04-01T16:46:05Z</timestamp> 00532 <contributor> 00533 <ip>127.0.0.1</ip> 00534 </contributor> 00535 <comment>BackupDumperTestP2Summary3</comment> 00536 <sha1>jfunqmh1ssfb8rs43r19w98k28gg56r</sha1> 00537 <model>wikitext</model> 00538 <format>text/x-wiki</format> 00539 <text id="' . $this->textId2_3 . '" bytes="23" /> 00540 </revision> 00541 <revision> 00542 <id>' . ( $this->revId2_4 + $i * self::$numOfRevs ) . '</id> 00543 <parentid>' . ( $this->revId2_3 + $i * self::$numOfRevs ) . '</parentid> 00544 <timestamp>2012-04-01T16:46:05Z</timestamp> 00545 <contributor> 00546 <ip>127.0.0.1</ip> 00547 </contributor> 00548 <comment>BackupDumperTestP2Summary4 extra</comment> 00549 <sha1>6o1ciaxa6pybnqprmungwofc4lv00wv</sha1> 00550 <model>wikitext</model> 00551 <format>text/x-wiki</format> 00552 <text id="' . $this->textId2_4 . '" bytes="44" /> 00553 </revision> 00554 </page> 00555 '; 00556 // page 3 not in stub 00557 00558 $page4 = ' <page> 00559 <title>Talk:BackupDumperTestP1</title> 00560 <ns>1</ns> 00561 <id>' . ( $this->pageId4 + $i * self::$numOfPages ) . '</id> 00562 <revision> 00563 <id>' . ( $this->revId4_1 + $i * self::$numOfRevs ) . '</id> 00564 <timestamp>2012-04-01T16:46:05Z</timestamp> 00565 <contributor> 00566 <ip>127.0.0.1</ip> 00567 </contributor> 00568 <comment>Talk BackupDumperTestP1 Summary1</comment> 00569 <sha1>nktofwzd0tl192k3zfepmlzxoax1lpe</sha1> 00570 <model>wikitext</model> 00571 <format>text/x-wiki</format> 00572 <text id="' . $this->textId4_1 . '" bytes="35" /> 00573 </revision> 00574 </page> 00575 '; 00576 $content .= $page1 . $page2 . $page4; 00577 } 00578 $content .= $tail; 00579 $this->assertEquals( strlen( $content ), file_put_contents( 00580 $fname, $content ), "Length of prepared stub" ); 00581 00582 return $fname; 00583 } 00584 }