3 namespace MediaWiki\Tests\Maintenance
;
6 use MediaWikiLangTestCase
;
8 use TextContentHandler
;
15 * Tests for TextPassDumper that rely on the database
17 * Some of these tests use the old constuctor for TextPassDumper
18 * and the dump() function, while others use the new loadWithArgv( $args )
19 * function and execute(). This is to ensure both the old and new methods
24 * @covers TextPassDumper
26 class TextPassDumperDatabaseTest
extends DumpTestCase
{
28 // We'll add several pages, revision and texts. The following variables hold the
30 private $pageId1, $pageId2, $pageId3, $pageId4;
31 private static $numOfPages = 4;
32 private $revId1_1, $textId1_1;
33 private $revId2_1, $textId2_1, $revId2_2, $textId2_2;
34 private $revId2_3, $textId2_3, $revId2_4, $textId2_4;
35 private $revId3_1, $textId3_1, $revId3_2, $textId3_2;
36 private $revId4_1, $textId4_1;
37 private static $numOfRevs = 8;
39 function addDBData() {
40 $this->tablesUsed
[] = 'page';
41 $this->tablesUsed
[] = 'revision';
42 $this->tablesUsed
[] = 'ip_changes';
43 $this->tablesUsed
[] = 'text';
45 $this->mergeMwGlobalArrayValue( 'wgContentHandlers', [
46 "BackupTextPassTestModel" => BackupTextPassTestModelHandler
::class,
49 $ns = $this->getDefaultWikitextNS();
53 $title = Title
::newFromText( 'BackupDumperTestP1', $ns );
54 $page = WikiPage
::factory( $title );
55 list( $this->revId1_1
, $this->textId1_1
) = $this->addRevision( $page,
56 "BackupDumperTestP1Text1", "BackupDumperTestP1Summary1" );
57 $this->pageId1
= $page->getId();
59 // Page with more than one revision
60 $title = Title
::newFromText( 'BackupDumperTestP2', $ns );
61 $page = WikiPage
::factory( $title );
62 list( $this->revId2_1
, $this->textId2_1
) = $this->addRevision( $page,
63 "BackupDumperTestP2Text1", "BackupDumperTestP2Summary1" );
64 list( $this->revId2_2
, $this->textId2_2
) = $this->addRevision( $page,
65 "BackupDumperTestP2Text2", "BackupDumperTestP2Summary2" );
66 list( $this->revId2_3
, $this->textId2_3
) = $this->addRevision( $page,
67 "BackupDumperTestP2Text3", "BackupDumperTestP2Summary3" );
68 list( $this->revId2_4
, $this->textId2_4
) = $this->addRevision( $page,
69 "BackupDumperTestP2Text4 some additional Text ",
70 "BackupDumperTestP2Summary4 extra " );
71 $this->pageId2
= $page->getId();
74 $title = Title
::newFromText( 'BackupDumperTestP3', $ns );
75 $page = WikiPage
::factory( $title );
76 list( $this->revId3_1
, $this->textId3_1
) = $this->addRevision( $page,
77 "BackupDumperTestP3Text1", "BackupDumperTestP2Summary1" );
78 list( $this->revId3_2
, $this->textId3_2
) = $this->addRevision( $page,
79 "BackupDumperTestP3Text2", "BackupDumperTestP2Summary2" );
80 $this->pageId3
= $page->getId();
81 $page->doDeleteArticle( "Testing ;)" );
83 // Page from non-default namespace and model.
84 // ExportTransform applies.
86 if ( $ns === NS_TALK
) {
87 // @todo work around this.
88 throw new MWException( "The default wikitext namespace is the talk namespace. "
89 . " We can't currently deal with that." );
92 $title = Title
::newFromText( 'BackupDumperTestP1', NS_TALK
);
93 $page = WikiPage
::factory( $title );
94 list( $this->revId4_1
, $this->textId4_1
) = $this->addRevision( $page,
95 "Talk about BackupDumperTestP1 Text1",
96 "Talk BackupDumperTestP1 Summary1",
97 "BackupTextPassTestModel" );
98 $this->pageId4
= $page->getId();
99 } catch ( Exception
$e ) {
100 // We'd love to pass $e directly. However, ... see
101 // documentation of exceptionFromAddDBData in
103 $this->exceptionFromAddDBData
= $e;
107 protected function setUp() {
110 // Since we will restrict dumping by page ranges (to allow
111 // working tests, even if the db gets prepopulated by a base
112 // class), we have to assert, that the page id are consecutively
115 [ $this->pageId2
, $this->pageId3
, $this->pageId4
],
116 [ $this->pageId1 +
1, $this->pageId1 +
2, $this->pageId1 +
3 ],
117 "Page ids increasing without holes" );
120 function testPlain() {
121 // Setting up the dump
122 $nameStub = $this->setUpStub();
123 $nameFull = $this->getNewTempFile();
124 $dumper = new TextPassDumper( [ "--stub=file:" . $nameStub,
125 "--output=file:" . $nameFull ] );
126 $dumper->reporting
= false;
127 $dumper->setDB( $this->db
);
129 // Performing the dump
130 $dumper->dump( WikiExporter
::FULL
, WikiExporter
::TEXT
);
132 // Checking for correctness of the dumped data
133 $asserter = $this->getDumpAsserter();
134 $asserter->assertDumpStart( $nameFull );
137 $asserter->assertPageStart( $this->pageId1
, NS_MAIN
, "BackupDumperTestP1" );
138 $asserter->assertRevision( $this->revId1_1
, "BackupDumperTestP1Summary1",
139 $this->textId1_1
, false, "0bolhl6ol7i6x0e7yq91gxgaan39j87",
140 "BackupDumperTestP1Text1" );
141 $asserter->assertPageEnd();
144 $asserter->assertPageStart( $this->pageId2
, NS_MAIN
, "BackupDumperTestP2" );
145 $asserter->assertRevision( $this->revId2_1
, "BackupDumperTestP2Summary1",
146 $this->textId2_1
, false, "jprywrymfhysqllua29tj3sc7z39dl2",
147 "BackupDumperTestP2Text1" );
148 $asserter->assertRevision( $this->revId2_2
, "BackupDumperTestP2Summary2",
149 $this->textId2_2
, false, "b7vj5ks32po5m1z1t1br4o7scdwwy95",
150 "BackupDumperTestP2Text2", $this->revId2_1
);
151 $asserter->assertRevision( $this->revId2_3
, "BackupDumperTestP2Summary3",
152 $this->textId2_3
, false, "jfunqmh1ssfb8rs43r19w98k28gg56r",
153 "BackupDumperTestP2Text3", $this->revId2_2
);
154 $asserter->assertRevision( $this->revId2_4
, "BackupDumperTestP2Summary4 extra",
155 $this->textId2_4
, false, "6o1ciaxa6pybnqprmungwofc4lv00wv",
156 "BackupDumperTestP2Text4 some additional Text", $this->revId2_3
);
157 $asserter->assertPageEnd();
160 // -> Page is marked deleted. Hence not visible
163 $asserter->assertPageStart( $this->pageId4
, NS_TALK
, "Talk:BackupDumperTestP1" );
164 $asserter->assertRevision( $this->revId4_1
, "Talk BackupDumperTestP1 Summary1",
165 $this->textId4_1
, false, "nktofwzd0tl192k3zfepmlzxoax1lpe",
166 "TALK ABOUT BACKUPDUMPERTESTP1 TEXT1",
168 "BackupTextPassTestModel",
170 $asserter->assertPageEnd();
172 $asserter->assertDumpEnd();
175 function testPrefetchPlain() {
176 // The mapping between ids and text, for the hits of the prefetch mock
178 [ $this->pageId1
, $this->revId1_1
, "Prefetch_________1Text1" ],
179 [ $this->pageId2
, $this->revId2_3
, "Prefetch_________2Text3" ]
183 $prefetchMock = $this->getMockBuilder( BaseDump
::class )
184 ->setMethods( [ 'prefetch' ] )
185 ->disableOriginalConstructor()
187 $prefetchMock->expects( $this->exactly( 6 ) )
188 ->method( 'prefetch' )
189 ->will( $this->returnValueMap( $prefetchMap ) );
191 // Setting up of the dump
192 $nameStub = $this->setUpStub();
193 $nameFull = $this->getNewTempFile();
195 $dumper = new TextPassDumper( [ "--stub=file:" . $nameStub,
196 "--output=file:" . $nameFull ] );
198 $dumper->prefetch
= $prefetchMock;
199 $dumper->reporting
= false;
200 $dumper->setDB( $this->db
);
202 // Performing the dump
203 $dumper->dump( WikiExporter
::FULL
, WikiExporter
::TEXT
);
205 // Checking for correctness of the dumped data
206 $asserter = $this->getDumpAsserter();
207 $asserter->assertDumpStart( $nameFull );
210 $asserter->assertPageStart( $this->pageId1
, NS_MAIN
, "BackupDumperTestP1" );
211 // Prefetch kicks in. This is still the SHA-1 of the original text,
212 // But the actual text (with different SHA-1) comes from prefetch.
213 $asserter->assertRevision( $this->revId1_1
, "BackupDumperTestP1Summary1",
214 $this->textId1_1
, false, "0bolhl6ol7i6x0e7yq91gxgaan39j87",
215 "Prefetch_________1Text1" );
216 $asserter->assertPageEnd();
219 $asserter->assertPageStart( $this->pageId2
, NS_MAIN
, "BackupDumperTestP2" );
220 $asserter->assertRevision( $this->revId2_1
, "BackupDumperTestP2Summary1",
221 $this->textId2_1
, false, "jprywrymfhysqllua29tj3sc7z39dl2",
222 "BackupDumperTestP2Text1" );
223 $asserter->assertRevision( $this->revId2_2
, "BackupDumperTestP2Summary2",
224 $this->textId2_2
, false, "b7vj5ks32po5m1z1t1br4o7scdwwy95",
225 "BackupDumperTestP2Text2", $this->revId2_1
);
226 // Prefetch kicks in. This is still the SHA-1 of the original text,
227 // But the actual text (with different SHA-1) comes from prefetch.
228 $asserter->assertRevision( $this->revId2_3
, "BackupDumperTestP2Summary3",
229 $this->textId2_3
, false, "jfunqmh1ssfb8rs43r19w98k28gg56r",
230 "Prefetch_________2Text3", $this->revId2_2
);
231 $asserter->assertRevision( $this->revId2_4
, "BackupDumperTestP2Summary4 extra",
232 $this->textId2_4
, false, "6o1ciaxa6pybnqprmungwofc4lv00wv",
233 "BackupDumperTestP2Text4 some additional Text", $this->revId2_3
);
234 $asserter->assertPageEnd();
237 // -> Page is marked deleted. Hence not visible
240 $asserter->assertPageStart( $this->pageId4
, NS_TALK
, "Talk:BackupDumperTestP1" );
241 $asserter->assertRevision( $this->revId4_1
, "Talk BackupDumperTestP1 Summary1",
242 $this->textId4_1
, false, "nktofwzd0tl192k3zfepmlzxoax1lpe",
243 "TALK ABOUT BACKUPDUMPERTESTP1 TEXT1",
245 "BackupTextPassTestModel",
247 $asserter->assertPageEnd();
249 $asserter->assertDumpEnd();
253 * Ensures that checkpoint dumps are used and written, by successively increasing the
254 * stub size and dumping until the duration crosses a threshold.
256 * @param string $checkpointFormat Either "file" for plain text or "gzip" for gzipped
259 private function checkpointHelper( $checkpointFormat = "file" ) {
260 // Getting temporary names
261 $nameStub = $this->getNewTempFile();
262 $nameOutputDir = $this->getNewTempDirectory();
264 $stderr = fopen( 'php://output', 'a' );
265 if ( $stderr === false ) {
266 $this->fail( "Could not open stream for stderr" );
269 $iterations = 32; // We'll start with that many iterations of revisions
270 // in stub. Make sure that the generated volume is above the buffer size
271 // set below. Otherwise, the checkpointing does not trigger.
273 $minDuration = 2; // We want the dump to take at least this many seconds
274 $checkpointAfter = 0.5; // Generate checkpoint after this many seconds
276 // Until a dump takes at least $minDuration seconds, perform a dump and check
277 // duration. If the dump did not take long enough increase the iteration
278 // count, to generate a bigger stub file next time.
279 while ( $lastDuration < $minDuration ) {
280 // Setting up the dump
281 wfRecursiveRemoveDir( $nameOutputDir );
282 $this->assertTrue( wfMkdirParents( $nameOutputDir ),
283 "Creating temporary output directory " );
284 $this->setUpStub( $nameStub, $iterations );
285 $dumper = new TextPassDumper();
286 $dumper->loadWithArgv( [ "--stub=file:" . $nameStub,
287 "--output=" . $checkpointFormat . ":" . $nameOutputDir . "/full",
288 "--maxtime=1" /*This is in minutes. Fixup is below*/,
289 "--buffersize=32768", // The default of 32 iterations fill up 32KB about twice
290 "--checkpointfile=checkpoint-%s-%s.xml.gz" ] );
291 $dumper->setDB( $this->db
);
292 $dumper->maxTimeAllowed
= $checkpointAfter; // Patching maxTime from 1 minute
293 $dumper->stderr
= $stderr;
295 // The actual dump and taking time
296 $ts_before = microtime( true );
298 $ts_after = microtime( true );
299 $lastDuration = $ts_after - $ts_before;
301 // Handling increasing the iteration count for the stubs
302 if ( $lastDuration < $minDuration ) {
303 $old_iterations = $iterations;
304 if ( $lastDuration > 0.2 ) {
305 // lastDuration is big enough, to allow an educated guess
306 $factor = ( $minDuration +
0.5 ) / $lastDuration;
307 if ( ( $factor > 1.1 ) && ( $factor < 100 ) ) {
308 // educated guess is reasonable
309 $iterations = (int)( $iterations * $factor );
313 if ( $old_iterations == $iterations ) {
314 // Heuristics were not applied, so we just *2.
318 $this->assertLessThan( 50000, $iterations,
319 "Emergency stop against infinitely increasing iteration "
320 . "count ( last duration: $lastDuration )" );
324 // The dump (hopefully) did take long enough to produce more than one
326 // We now check all the checkpoint files for validity.
328 $files = scandir( $nameOutputDir );
329 $this->assertTrue( asort( $files ), "Sorting files in temporary directory" );
332 $checkpointFiles = 0;
334 $asserter = $this->getDumpAsserter();
336 // Each run of the following loop body tries to handle exactly 1 /page/ (not
337 // iteration of stub content). $i is only increased after having treated page 4.
338 for ( $i = 0; $i < $iterations; ) {
339 // 1. Assuring a file is opened and ready. Skipping across header if
341 if ( !$fileOpened ) {
342 $this->assertNotEmpty( $files, "No more existing dump files, "
343 . "but not yet all pages found" );
344 $fname = array_shift( $files );
345 while ( $fname == "." ||
$fname == ".." ) {
346 $this->assertNotEmpty( $files, "No more existing dump"
347 . " files, but not yet all pages found" );
348 $fname = array_shift( $files );
350 if ( $checkpointFormat == "gzip" ) {
351 $this->gunzip( $nameOutputDir . "/" . $fname );
353 $asserter->assertDumpStart( $nameOutputDir . "/" . $fname );
358 // 2. Performing a single page check
359 switch ( $lookingForPage ) {
362 $asserter->assertPageStart(
363 $this->pageId1 +
$i * self
::$numOfPages,
367 $asserter->assertRevision(
368 $this->revId1_1 +
$i * self
::$numOfRevs,
369 "BackupDumperTestP1Summary1",
372 "0bolhl6ol7i6x0e7yq91gxgaan39j87",
373 "BackupDumperTestP1Text1"
375 $asserter->assertPageEnd();
382 $asserter->assertPageStart(
383 $this->pageId2 +
$i * self
::$numOfPages,
387 $asserter->assertRevision(
388 $this->revId2_1 +
$i * self
::$numOfRevs,
389 "BackupDumperTestP2Summary1",
392 "jprywrymfhysqllua29tj3sc7z39dl2",
393 "BackupDumperTestP2Text1"
395 $asserter->assertRevision(
396 $this->revId2_2 +
$i * self
::$numOfRevs,
397 "BackupDumperTestP2Summary2",
400 "b7vj5ks32po5m1z1t1br4o7scdwwy95",
401 "BackupDumperTestP2Text2",
402 $this->revId2_1 +
$i * self
::$numOfRevs
404 $asserter->assertRevision(
405 $this->revId2_3 +
$i * self
::$numOfRevs,
406 "BackupDumperTestP2Summary3",
409 "jfunqmh1ssfb8rs43r19w98k28gg56r",
410 "BackupDumperTestP2Text3",
411 $this->revId2_2 +
$i * self
::$numOfRevs
413 $asserter->assertRevision(
414 $this->revId2_4 +
$i * self
::$numOfRevs,
415 "BackupDumperTestP2Summary4 extra",
418 "6o1ciaxa6pybnqprmungwofc4lv00wv",
419 "BackupDumperTestP2Text4 some additional Text",
420 $this->revId2_3 +
$i * self
::$numOfRevs
422 $asserter->assertPageEnd();
429 $asserter->assertPageStart(
430 $this->pageId4 +
$i * self
::$numOfPages,
432 "Talk:BackupDumperTestP1"
434 $asserter->assertRevision(
435 $this->revId4_1 +
$i * self
::$numOfRevs,
436 "Talk BackupDumperTestP1 Summary1",
439 "nktofwzd0tl192k3zfepmlzxoax1lpe",
440 "TALK ABOUT BACKUPDUMPERTESTP1 TEXT1",
442 "BackupTextPassTestModel",
445 $asserter->assertPageEnd();
449 // We dealt with the whole iteration.
454 $this->fail( "Bad setting for lookingForPage ($lookingForPage)" );
457 // 3. Checking for the end of the current checkpoint file
458 if ( $this->xml
->nodeType
== XMLReader
::END_ELEMENT
459 && $this->xml
->name
== "mediawiki"
461 $asserter->assertDumpEnd();
466 // Assuring we completely read all files ...
467 $this->assertFalse( $fileOpened, "Currently read file still open?" );
468 $this->assertEmpty( $files, "Remaining unchecked files" );
470 // ... and have dealt with more than one checkpoint file
471 $this->assertGreaterThan(
474 "expected more than 1 checkpoint to have been created. "
475 . "Checkpoint interval is $checkpointAfter seconds, maybe your computer is too fast?"
478 $this->expectETAOutput();
487 function testCheckpointPlain() {
488 $this->checkpointHelper();
492 * tests for working checkpoint generation in gzip format work.
494 * We keep this test in addition to the simpler self::testCheckpointPlain, as there
495 * were once problems when the used sinks were DumpPipeOutputs.
497 * xmldumps-backup typically uses bzip2 instead of gzip. However, as bzip2 requires
498 * PHP extensions, we go for gzip instead, which triggers the same relevant code
499 * paths while still being testable on more systems.
506 function testCheckpointGzip() {
507 $this->checkHasGzip();
508 $this->checkpointHelper( "gzip" );
512 * Creates a stub file that is used for testing the text pass of dumps
514 * @param string $fname (Optional) Absolute name of the file to write
515 * the stub into. If this parameter is null, a new temporary
516 * file is generated that is automatically removed upon tearDown.
517 * @param int $iterations (Optional) specifies how often the block
518 * of 3 pages should go into the stub file. The page and
519 * revision id increase further and further, while the text
520 * id of the first iteration is reused. The pages and revision
521 * of iteration > 1 have no corresponding representation in the database.
522 * @return string Absolute filename of the stub
524 private function setUpStub( $fname = null, $iterations = 1 ) {
525 if ( $fname === null ) {
526 $fname = $this->getNewTempFile();
528 $header = '<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.10/" '
529 . 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" '
530 . 'xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.10/ '
531 . 'http://www.mediawiki.org/xml/export-0.10.xsd" version="0.10" xml:lang="en">
533 <sitename>wikisvn</sitename>
534 <base>http://localhost/wiki-svn/index.php/Main_Page</base>
535 <generator>MediaWiki 1.21alpha</generator>
536 <case>first-letter</case>
538 <namespace key="-2" case="first-letter">Media</namespace>
539 <namespace key="-1" case="first-letter">Special</namespace>
540 <namespace key="0" case="first-letter" />
541 <namespace key="1" case="first-letter">Talk</namespace>
542 <namespace key="2" case="first-letter">User</namespace>
543 <namespace key="3" case="first-letter">User talk</namespace>
544 <namespace key="4" case="first-letter">Wikisvn</namespace>
545 <namespace key="5" case="first-letter">Wikisvn talk</namespace>
546 <namespace key="6" case="first-letter">File</namespace>
547 <namespace key="7" case="first-letter">File talk</namespace>
548 <namespace key="8" case="first-letter">MediaWiki</namespace>
549 <namespace key="9" case="first-letter">MediaWiki talk</namespace>
550 <namespace key="10" case="first-letter">Template</namespace>
551 <namespace key="11" case="first-letter">Template talk</namespace>
552 <namespace key="12" case="first-letter">Help</namespace>
553 <namespace key="13" case="first-letter">Help talk</namespace>
554 <namespace key="14" case="first-letter">Category</namespace>
555 <namespace key="15" case="first-letter">Category talk</namespace>
559 $tail = '</mediawiki>
563 $iterations = intval( $iterations );
564 for ( $i = 0; $i < $iterations; $i++
) {
566 <title>BackupDumperTestP1</title>
568 <id>' . ( $this->pageId1 +
$i * self
::$numOfPages ) . '</id>
570 <id>' . ( $this->revId1_1 +
$i * self
::$numOfRevs ) . '</id>
571 <timestamp>2012-04-01T16:46:05Z</timestamp>
575 <comment>BackupDumperTestP1Summary1</comment>
576 <model>wikitext</model>
577 <format>text/x-wiki</format>
578 <text id="' . $this->textId1_1
. '" bytes="23" />
579 <sha1>0bolhl6ol7i6x0e7yq91gxgaan39j87</sha1>
584 <title>BackupDumperTestP2</title>
586 <id>' . ( $this->pageId2 +
$i * self
::$numOfPages ) . '</id>
588 <id>' . ( $this->revId2_1 +
$i * self
::$numOfRevs ) . '</id>
589 <timestamp>2012-04-01T16:46:05Z</timestamp>
593 <comment>BackupDumperTestP2Summary1</comment>
594 <model>wikitext</model>
595 <format>text/x-wiki</format>
596 <text id="' . $this->textId2_1
. '" bytes="23" />
597 <sha1>jprywrymfhysqllua29tj3sc7z39dl2</sha1>
600 <id>' . ( $this->revId2_2 +
$i * self
::$numOfRevs ) . '</id>
601 <parentid>' . ( $this->revId2_1 +
$i * self
::$numOfRevs ) . '</parentid>
602 <timestamp>2012-04-01T16:46:05Z</timestamp>
606 <comment>BackupDumperTestP2Summary2</comment>
607 <model>wikitext</model>
608 <format>text/x-wiki</format>
609 <text id="' . $this->textId2_2
. '" bytes="23" />
610 <sha1>b7vj5ks32po5m1z1t1br4o7scdwwy95</sha1>
613 <id>' . ( $this->revId2_3 +
$i * self
::$numOfRevs ) . '</id>
614 <parentid>' . ( $this->revId2_2 +
$i * self
::$numOfRevs ) . '</parentid>
615 <timestamp>2012-04-01T16:46:05Z</timestamp>
619 <comment>BackupDumperTestP2Summary3</comment>
620 <model>wikitext</model>
621 <format>text/x-wiki</format>
622 <text id="' . $this->textId2_3
. '" bytes="23" />
623 <sha1>jfunqmh1ssfb8rs43r19w98k28gg56r</sha1>
626 <id>' . ( $this->revId2_4 +
$i * self
::$numOfRevs ) . '</id>
627 <parentid>' . ( $this->revId2_3 +
$i * self
::$numOfRevs ) . '</parentid>
628 <timestamp>2012-04-01T16:46:05Z</timestamp>
632 <comment>BackupDumperTestP2Summary4 extra</comment>
633 <model>wikitext</model>
634 <format>text/x-wiki</format>
635 <text id="' . $this->textId2_4
. '" bytes="44" />
636 <sha1>6o1ciaxa6pybnqprmungwofc4lv00wv</sha1>
640 // page 3 not in stub
643 <title>Talk:BackupDumperTestP1</title>
645 <id>' . ( $this->pageId4 +
$i * self
::$numOfPages ) . '</id>
647 <id>' . ( $this->revId4_1 +
$i * self
::$numOfRevs ) . '</id>
648 <timestamp>2012-04-01T16:46:05Z</timestamp>
652 <comment>Talk BackupDumperTestP1 Summary1</comment>
653 <model>BackupTextPassTestModel</model>
654 <format>text/plain</format>
655 <text id="' . $this->textId4_1
. '" bytes="35" />
656 <sha1>nktofwzd0tl192k3zfepmlzxoax1lpe</sha1>
660 $content .= $page1 . $page2 . $page4;
663 $this->assertEquals( strlen( $content ), file_put_contents(
664 $fname, $content ), "Length of prepared stub" );
670 class BackupTextPassTestModelHandler
extends TextContentHandler
{
672 public function __construct() {
673 parent
::__construct( 'BackupTextPassTestModel' );
676 public function exportTransform( $text, $format = null ) {
677 return strtoupper( $text );
683 * Tests for TextPassDumper that do not rely on the database
685 * (As the Database group is only detected at class level (not method level), we
686 * cannot bring this test case's tests into the above main test case.)
689 * @covers TextPassDumper
691 class TextPassDumperDatabaselessTest
extends MediaWikiLangTestCase
{
693 * Ensures that setting the buffer size is effective.
695 * @dataProvider bufferSizeProvider
697 function testBufferSizeSetting( $expected, $size, $msg ) {
698 $dumper = new TextPassDumperAccessor();
699 $dumper->loadWithArgv( [ "--buffersize=" . $size ] );
701 $this->assertEquals( $expected, $dumper->getBufferSize(), $msg );
705 * Ensures that setting the buffer size is effective.
707 * @dataProvider bufferSizeProvider
709 function bufferSizeProvider() {
710 // expected, bufferSize to initialize with, message
712 [ 512 * 1024, 512 * 1024, "Setting 512KB is not effective" ],
713 [ 8192, 8192, "Setting 8KB is not effective" ],
714 [ 4096, 2048, "Could set buffer size below lower bound" ]
720 * Accessor for internal state of TextPassDumper
722 * Do not warrentless add getters here.
724 class TextPassDumperAccessor
extends TextPassDumper
{
726 * Gets the bufferSize.
728 * If bufferSize setting does not work correctly, testCheckpoint... tests
729 * fail and point in the wrong direction. To aid in troubleshooting when
730 * testCheckpoint... tests break at some point in the future, we test the
731 * bufferSize setting, hence need this accessor.
733 * (Yes, bufferSize is internal state of the TextPassDumper, but aiding
734 * debugging of testCheckpoint... in the future seems to be worth testing
735 * against it nonetheless.)
737 public function getBufferSize() {
738 return $this->bufferSize
;
741 function dump( $history, $text = null ) {