MediaWiki  master
backupTextPassTest.php
Go to the documentation of this file.
1 <?php
2 
4 
10 use Title;
13 
27 
28  // We'll add several pages, revision and texts. The following variables hold the
29  // corresponding ids.
31  private static $numOfPages = 4;
37  private static $numOfRevs = 8;
38 
39  function addDBData() {
40  $this->tablesUsed[] = 'page';
41  $this->tablesUsed[] = 'revision';
42  $this->tablesUsed[] = 'ip_changes';
43  $this->tablesUsed[] = 'text';
44 
45  $this->mergeMwGlobalArrayValue( 'wgContentHandlers', [
46  "BackupTextPassTestModel" => BackupTextPassTestModelHandler::class,
47  ] );
48 
49  $ns = $this->getDefaultWikitextNS();
50 
51  try {
52  // Simple page
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();
58 
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();
72 
73  // Deleted page.
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 ;)" );
82 
83  // Page from non-default namespace and model.
84  // ExportTransform applies.
85 
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." );
90  }
91 
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
102  // DumpTestCase
103  $this->exceptionFromAddDBData = $e;
104  }
105  }
106 
107  protected function setUp() {
108  parent::setUp();
109 
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
113  // increasing
114  $this->assertEquals(
115  [ $this->pageId2, $this->pageId3, $this->pageId4 ],
116  [ $this->pageId1 + 1, $this->pageId1 + 2, $this->pageId1 + 3 ],
117  "Page ids increasing without holes" );
118  }
119 
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 );
128 
129  // Performing the dump
130  $dumper->dump( WikiExporter::FULL, WikiExporter::TEXT );
131 
132  // Checking for correctness of the dumped data
133  $asserter = $this->getDumpAsserter();
134  $asserter->assertDumpStart( $nameFull );
135 
136  // Page 1
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();
142 
143  // Page 2
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();
158 
159  // Page 3
160  // -> Page is marked deleted. Hence not visible
161 
162  // Page 4
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",
167  false,
168  "BackupTextPassTestModel",
169  "text/plain" );
170  $asserter->assertPageEnd();
171 
172  $asserter->assertDumpEnd();
173  }
174 
175  function testPrefetchPlain() {
176  // The mapping between ids and text, for the hits of the prefetch mock
177  $prefetchMap = [
178  [ $this->pageId1, $this->revId1_1, "Prefetch_________1Text1" ],
179  [ $this->pageId2, $this->revId2_3, "Prefetch_________2Text3" ]
180  ];
181 
182  // The mock itself
183  $prefetchMock = $this->getMockBuilder( BaseDump::class )
184  ->setMethods( [ 'prefetch' ] )
185  ->disableOriginalConstructor()
186  ->getMock();
187  $prefetchMock->expects( $this->exactly( 6 ) )
188  ->method( 'prefetch' )
189  ->will( $this->returnValueMap( $prefetchMap ) );
190 
191  // Setting up of the dump
192  $nameStub = $this->setUpStub();
193  $nameFull = $this->getNewTempFile();
194 
195  $dumper = new TextPassDumper( [ "--stub=file:" . $nameStub,
196  "--output=file:" . $nameFull ] );
197 
198  $dumper->prefetch = $prefetchMock;
199  $dumper->reporting = false;
200  $dumper->setDB( $this->db );
201 
202  // Performing the dump
203  $dumper->dump( WikiExporter::FULL, WikiExporter::TEXT );
204 
205  // Checking for correctness of the dumped data
206  $asserter = $this->getDumpAsserter();
207  $asserter->assertDumpStart( $nameFull );
208 
209  // Page 1
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();
217 
218  // Page 2
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();
235 
236  // Page 3
237  // -> Page is marked deleted. Hence not visible
238 
239  // Page 4
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",
244  false,
245  "BackupTextPassTestModel",
246  "text/plain" );
247  $asserter->assertPageEnd();
248 
249  $asserter->assertDumpEnd();
250  }
251 
259  private function checkpointHelper( $checkpointFormat = "file" ) {
260  // Getting temporary names
261  $nameStub = $this->getNewTempFile();
262  $nameOutputDir = $this->getNewTempDirectory();
263 
264  $stderr = fopen( 'php://output', 'a' );
265  if ( $stderr === false ) {
266  $this->fail( "Could not open stream for stderr" );
267  }
268 
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.
272  $lastDuration = 0;
273  $minDuration = 2; // We want the dump to take at least this many seconds
274  $checkpointAfter = 0.5; // Generate checkpoint after this many seconds
275 
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;
294 
295  // The actual dump and taking time
296  $ts_before = microtime( true );
297  $dumper->execute();
298  $ts_after = microtime( true );
299  $lastDuration = $ts_after - $ts_before;
300 
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 );
310  }
311  }
312 
313  if ( $old_iterations == $iterations ) {
314  // Heuristics were not applied, so we just *2.
315  $iterations *= 2;
316  }
317 
318  $this->assertLessThan( 50000, $iterations,
319  "Emergency stop against infinitely increasing iteration "
320  . "count ( last duration: $lastDuration )" );
321  }
322  }
323 
324  // The dump (hopefully) did take long enough to produce more than one
325  // checkpoint file.
326  // We now check all the checkpoint files for validity.
327 
328  $files = scandir( $nameOutputDir );
329  $this->assertTrue( asort( $files ), "Sorting files in temporary directory" );
330  $fileOpened = false;
331  $lookingForPage = 1;
332  $checkpointFiles = 0;
333 
334  $asserter = $this->getDumpAsserter();
335 
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
340  // necessary.
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 );
349  }
350  if ( $checkpointFormat == "gzip" ) {
351  $this->gunzip( $nameOutputDir . "/" . $fname );
352  }
353  $asserter->assertDumpStart( $nameOutputDir . "/" . $fname );
354  $fileOpened = true;
355  $checkpointFiles++;
356  }
357 
358  // 2. Performing a single page check
359  switch ( $lookingForPage ) {
360  case 1:
361  // Page 1
362  $asserter->assertPageStart(
363  $this->pageId1 + $i * self::$numOfPages,
364  NS_MAIN,
365  "BackupDumperTestP1"
366  );
367  $asserter->assertRevision(
368  $this->revId1_1 + $i * self::$numOfRevs,
369  "BackupDumperTestP1Summary1",
370  $this->textId1_1,
371  false,
372  "0bolhl6ol7i6x0e7yq91gxgaan39j87",
373  "BackupDumperTestP1Text1"
374  );
375  $asserter->assertPageEnd();
376 
377  $lookingForPage = 2;
378  break;
379 
380  case 2:
381  // Page 2
382  $asserter->assertPageStart(
383  $this->pageId2 + $i * self::$numOfPages,
384  NS_MAIN,
385  "BackupDumperTestP2"
386  );
387  $asserter->assertRevision(
388  $this->revId2_1 + $i * self::$numOfRevs,
389  "BackupDumperTestP2Summary1",
390  $this->textId2_1,
391  false,
392  "jprywrymfhysqllua29tj3sc7z39dl2",
393  "BackupDumperTestP2Text1"
394  );
395  $asserter->assertRevision(
396  $this->revId2_2 + $i * self::$numOfRevs,
397  "BackupDumperTestP2Summary2",
398  $this->textId2_2,
399  false,
400  "b7vj5ks32po5m1z1t1br4o7scdwwy95",
401  "BackupDumperTestP2Text2",
402  $this->revId2_1 + $i * self::$numOfRevs
403  );
404  $asserter->assertRevision(
405  $this->revId2_3 + $i * self::$numOfRevs,
406  "BackupDumperTestP2Summary3",
407  $this->textId2_3,
408  false,
409  "jfunqmh1ssfb8rs43r19w98k28gg56r",
410  "BackupDumperTestP2Text3",
411  $this->revId2_2 + $i * self::$numOfRevs
412  );
413  $asserter->assertRevision(
414  $this->revId2_4 + $i * self::$numOfRevs,
415  "BackupDumperTestP2Summary4 extra",
416  $this->textId2_4,
417  false,
418  "6o1ciaxa6pybnqprmungwofc4lv00wv",
419  "BackupDumperTestP2Text4 some additional Text",
420  $this->revId2_3 + $i * self::$numOfRevs
421  );
422  $asserter->assertPageEnd();
423 
424  $lookingForPage = 4;
425  break;
426 
427  case 4:
428  // Page 4
429  $asserter->assertPageStart(
430  $this->pageId4 + $i * self::$numOfPages,
431  NS_TALK,
432  "Talk:BackupDumperTestP1"
433  );
434  $asserter->assertRevision(
435  $this->revId4_1 + $i * self::$numOfRevs,
436  "Talk BackupDumperTestP1 Summary1",
437  $this->textId4_1,
438  false,
439  "nktofwzd0tl192k3zfepmlzxoax1lpe",
440  "TALK ABOUT BACKUPDUMPERTESTP1 TEXT1",
441  false,
442  "BackupTextPassTestModel",
443  "text/plain"
444  );
445  $asserter->assertPageEnd();
446 
447  $lookingForPage = 1;
448 
449  // We dealt with the whole iteration.
450  $i++;
451  break;
452 
453  default:
454  $this->fail( "Bad setting for lookingForPage ($lookingForPage)" );
455  }
456 
457  // 3. Checking for the end of the current checkpoint file
458  if ( $this->xml->nodeType == XMLReader::END_ELEMENT
459  && $this->xml->name == "mediawiki"
460  ) {
461  $asserter->assertDumpEnd();
462  $fileOpened = false;
463  }
464  }
465 
466  // Assuring we completely read all files ...
467  $this->assertFalse( $fileOpened, "Currently read file still open?" );
468  $this->assertEmpty( $files, "Remaining unchecked files" );
469 
470  // ... and have dealt with more than one checkpoint file
471  $this->assertGreaterThan(
472  1,
473  $checkpointFiles,
474  "expected more than 1 checkpoint to have been created. "
475  . "Checkpoint interval is $checkpointAfter seconds, maybe your computer is too fast?"
476  );
477 
478  $this->expectETAOutput();
479  }
480 
487  function testCheckpointPlain() {
488  $this->checkpointHelper();
489  }
490 
506  function testCheckpointGzip() {
507  $this->checkHasGzip();
508  $this->checkpointHelper( "gzip" );
509  }
510 
524  private function setUpStub( $fname = null, $iterations = 1 ) {
525  if ( $fname === null ) {
526  $fname = $this->getNewTempFile();
527  }
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">
532  <siteinfo>
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>
537  <namespaces>
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>
556  </namespaces>
557  </siteinfo>
558 ';
559  $tail = '</mediawiki>
560 ';
561 
562  $content = $header;
563  $iterations = intval( $iterations );
564  $username = $this->getTestUser()->getUser()->getName();
565  $userid = $this->getTestUser()->getUser()->getId();
566  for ( $i = 0; $i < $iterations; $i++ ) {
567  $page1 = ' <page>
568  <title>BackupDumperTestP1</title>
569  <ns>0</ns>
570  <id>' . ( $this->pageId1 + $i * self::$numOfPages ) . '</id>
571  <revision>
572  <id>' . ( $this->revId1_1 + $i * self::$numOfRevs ) . '</id>
573  <timestamp>2012-04-01T16:46:05Z</timestamp>
574  <contributor>
575  <username>' . $username . '</username>
576  <id>' . $userid . '</id>
577  </contributor>
578  <comment>BackupDumperTestP1Summary1</comment>
579  <model>wikitext</model>
580  <format>text/x-wiki</format>
581  <text id="' . $this->textId1_1 . '" bytes="23" />
582  <sha1>0bolhl6ol7i6x0e7yq91gxgaan39j87</sha1>
583  </revision>
584  </page>
585 ';
586  $page2 = ' <page>
587  <title>BackupDumperTestP2</title>
588  <ns>0</ns>
589  <id>' . ( $this->pageId2 + $i * self::$numOfPages ) . '</id>
590  <revision>
591  <id>' . ( $this->revId2_1 + $i * self::$numOfRevs ) . '</id>
592  <timestamp>2012-04-01T16:46:05Z</timestamp>
593  <contributor>
594  <username>' . $username . '</username>
595  <id>' . $userid . '</id>
596  </contributor>
597  <comment>BackupDumperTestP2Summary1</comment>
598  <model>wikitext</model>
599  <format>text/x-wiki</format>
600  <text id="' . $this->textId2_1 . '" bytes="23" />
601  <sha1>jprywrymfhysqllua29tj3sc7z39dl2</sha1>
602  </revision>
603  <revision>
604  <id>' . ( $this->revId2_2 + $i * self::$numOfRevs ) . '</id>
605  <parentid>' . ( $this->revId2_1 + $i * self::$numOfRevs ) . '</parentid>
606  <timestamp>2012-04-01T16:46:05Z</timestamp>
607  <contributor>
608  <username>' . $username . '</username>
609  <id>' . $userid . '</id>
610  </contributor>
611  <comment>BackupDumperTestP2Summary2</comment>
612  <model>wikitext</model>
613  <format>text/x-wiki</format>
614  <text id="' . $this->textId2_2 . '" bytes="23" />
615  <sha1>b7vj5ks32po5m1z1t1br4o7scdwwy95</sha1>
616  </revision>
617  <revision>
618  <id>' . ( $this->revId2_3 + $i * self::$numOfRevs ) . '</id>
619  <parentid>' . ( $this->revId2_2 + $i * self::$numOfRevs ) . '</parentid>
620  <timestamp>2012-04-01T16:46:05Z</timestamp>
621  <contributor>
622  <username>' . $username . '</username>
623  <id>' . $userid . '</id>
624  </contributor>
625  <comment>BackupDumperTestP2Summary3</comment>
626  <model>wikitext</model>
627  <format>text/x-wiki</format>
628  <text id="' . $this->textId2_3 . '" bytes="23" />
629  <sha1>jfunqmh1ssfb8rs43r19w98k28gg56r</sha1>
630  </revision>
631  <revision>
632  <id>' . ( $this->revId2_4 + $i * self::$numOfRevs ) . '</id>
633  <parentid>' . ( $this->revId2_3 + $i * self::$numOfRevs ) . '</parentid>
634  <timestamp>2012-04-01T16:46:05Z</timestamp>
635  <contributor>
636  <username>' . $username . '</username>
637  <id>' . $userid . '</id>
638  </contributor>
639  <comment>BackupDumperTestP2Summary4 extra</comment>
640  <model>wikitext</model>
641  <format>text/x-wiki</format>
642  <text id="' . $this->textId2_4 . '" bytes="44" />
643  <sha1>6o1ciaxa6pybnqprmungwofc4lv00wv</sha1>
644  </revision>
645  </page>
646 ';
647  // page 3 not in stub
648 
649  $page4 = ' <page>
650  <title>Talk:BackupDumperTestP1</title>
651  <ns>1</ns>
652  <id>' . ( $this->pageId4 + $i * self::$numOfPages ) . '</id>
653  <revision>
654  <id>' . ( $this->revId4_1 + $i * self::$numOfRevs ) . '</id>
655  <timestamp>2012-04-01T16:46:05Z</timestamp>
656  <contributor>
657  <username>' . $username . '</username>
658  <id>' . $userid . '</id>
659  </contributor>
660  <comment>Talk BackupDumperTestP1 Summary1</comment>
661  <model>BackupTextPassTestModel</model>
662  <format>text/plain</format>
663  <text id="' . $this->textId4_1 . '" bytes="35" />
664  <sha1>nktofwzd0tl192k3zfepmlzxoax1lpe</sha1>
665  </revision>
666  </page>
667 ';
668  $content .= $page1 . $page2 . $page4;
669  }
670  $content .= $tail;
671  $this->assertEquals( strlen( $content ), file_put_contents(
672  $fname, $content ), "Length of prepared stub" );
673 
674  return $fname;
675  }
676 }
677 
679 
680  public function __construct() {
681  parent::__construct( 'BackupTextPassTestModel' );
682  }
683 
684  public function exportTransform( $text, $format = null ) {
685  return strtoupper( $text );
686  }
687 
688 }
689 
705  function testBufferSizeSetting( $expected, $size, $msg ) {
706  $dumper = new TextPassDumperAccessor();
707  $dumper->loadWithArgv( [ "--buffersize=" . $size ] );
708  $dumper->execute();
709  $this->assertEquals( $expected, $dumper->getBufferSize(), $msg );
710  }
711 
717  function bufferSizeProvider() {
718  // expected, bufferSize to initialize with, message
719  return [
720  [ 512 * 1024, 512 * 1024, "Setting 512KB is not effective" ],
721  [ 8192, 8192, "Setting 8KB is not effective" ],
722  [ 4096, 2048, "Could set buffer size below lower bound" ]
723  ];
724  }
725 }
726 
745  public function getBufferSize() {
746  return $this->bufferSize;
747  }
748 
749  function dump( $history, $text = null ) {
750  return true;
751  }
752 }
static factory(Title $title)
Create a WikiPage object of the appropriate class for the given title.
Definition: WikiPage.php:138
deferred txt A few of the database updates required by various functions here can be deferred until after the result page is displayed to the user For updating the view updating the linked to tables after a etc PHP does not yet have any way to tell the server to actually return and disconnect while still running these but it might have such a feature in the future We handle these by creating a deferred update object and putting those objects on a global list
Definition: deferred.txt:11
const NS_MAIN
Definition: Defines.php:60
Tests for TextPassDumper that do not rely on the database.
Apache License January AND DISTRIBUTION Definitions License shall mean the terms and conditions for use
div flags Integer display flags(NO_ACTION_LINK, NO_EXTRA_USER_LINKS) 'LogException' returning false will NOT prevent logging $e
Definition: hooks.txt:2159
Accessor for internal state of TextPassDumper.
wfRecursiveRemoveDir( $dir)
Remove a directory and all its content.
gunzip( $fname)
gunzips the given file and stores the result in the original file name
mergeMwGlobalArrayValue( $name, $values)
Merges the given values into a MW global array variable.
Tests for TextPassDumper that rely on the database.
bufferSizeProvider()
Ensures that setting the buffer size is effective.
getNewTempFile()
Obtains a new temporary file name.
getDefaultWikitextNS()
Returns the ID of a namespace that defaults to Wikitext.
setUpStub( $fname=null, $iterations=1)
Creates a stub file that is used for testing the text pass of dumps.
addRevision(WikiPage $page, $text, $summary, $model=CONTENT_MODEL_WIKITEXT)
Adds a revision to a page, while returning the resuting revision&#39;s id.
testCheckpointGzip()
tests for working checkpoint generation in gzip format work.
this hook is for auditing only or null if authentication failed before getting that far or null if we can t even determine that When $user is not null
Definition: hooks.txt:780
namespace and then decline to actually register it file or subcat img or subcat $title
Definition: hooks.txt:925
$header
if(defined( 'MW_SETUP_CALLBACK')) $fname
Customization point after all loading (constants, functions, classes, DefaultSettings, LocalSettings).
Definition: Setup.php:123
checkHasGzip()
Skip the test if &#39;gzip&#39; is not in $PATH.
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition: injection.txt:35
this hook is for auditing only or null if authentication failed before getting that far $username
Definition: hooks.txt:780
testBufferSizeSetting( $expected, $size, $msg)
Ensures that setting the buffer size is effective.
you have access to all of the normal MediaWiki so you can get a DB use the etc For full docs on the Maintenance class
Definition: maintenance.txt:52
wfMkdirParents( $dir, $mode=null, $caller=null)
Make directory, and make all parent directories if they don&#39;t exist.
checkpointHelper( $checkpointFormat="file")
Ensures that checkpoint dumps are used and written, by successively increasing the stub size and dump...
getNewTempDirectory()
obtains a new temporary directory
const NS_TALK
Definition: Defines.php:61
$content
Definition: pageupdater.txt:72
static getTestUser( $groups=[])
Convenience method for getting an immutable test user.
expectETAOutput()
Checks for test output consisting only of lines containing ETA announcements.
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:319