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