r104561 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r104560‎ | r104561 | r104562 >
Date:13:54, 29 November 2011
Author:hashar
Status:ok (Comments)
Tags:
Comment:
parserTest: delay hooks execution to the point we really need them

disabled and filtered out tests were still triggering hooks run. This patch
let us delay hooks running run a little bit until we know we will really need
their execution (i.e. when test is not filtered out and not disabled).

Saving all that unneeded code execution makes running a subset of parser tests
a bit faster when one has many extension enabled.

NOTE: '!!article' sections are still parsed regardless of their usage.
We would need to add an article/test dependency system to really filter them
Modified paths:
  • /trunk/phase3/tests/testHelpers.inc (modified) (history)

Diff [purge]

Index: trunk/phase3/tests/testHelpers.inc
@@ -365,6 +365,10 @@
366366 function readNextTest() {
367367 $this->clearSection();
368368
 369+ # Create a fake parser tests which never run anything unless
 370+ # asked to do so. This will avoid running hooks for a disabled test
 371+ $delayedParserTest = new DelayedParserTest();
 372+
369373 while ( false !== ( $line = fgets( $this->fh ) ) ) {
370374 $this->lineNum++;
371375 $matches = array();
@@ -390,9 +394,7 @@
391395 $line = trim( $line );
392396
393397 if ( $line ) {
394 - if ( !$this->parserTest->requireHook( $line ) ) {
395 - return false;
396 - }
 398+ $delayedParserTest->requireHook( $line );
397399 }
398400 }
399401
@@ -408,9 +410,7 @@
409411 $line = trim( $line );
410412
411413 if ( $line ) {
412 - if ( !$this->parserTest->requireFunctionHook( $line ) ) {
413 - return false;
414 - }
 414+ $delayedParserTest->requireFunctionHook( $line );
415415 }
416416 }
417417
@@ -437,9 +437,20 @@
438438 # disabled test
439439 $this->clearSection();
440440
 441+ # Forget any pending hooks call since test is disabled
 442+ $delayedParserTest->reset();
 443+
441444 continue;
442445 }
443446
 447+ # We are really going to run the test, run pending hooks and hooks function
 448+ wfDebug( __METHOD__ . " unleashing delayed test for: {$this->sectionData['test']}" );
 449+ $hooksResult = $delayedParserTest->unleash( $this->parserTest );
 450+ if( !$hooksResult ) {
 451+ # Some hook reported an issue. Abort.
 452+ return false;
 453+ }
 454+
444455 $this->test = array(
445456 'test' => ParserTest::chomp( $this->sectionData['test'] ),
446457 'input' => ParserTest::chomp( $this->sectionData['input'] ),
@@ -503,3 +514,69 @@
504515 return true;
505516 }
506517 }
 518+
 519+
 520+/**
 521+ * A class to delay execution of a parser test hooks.
 522+ *
 523+ */
 524+class DelayedParserTest {
 525+
 526+ /** Initialized on construction */
 527+ private $hooks;
 528+ private $fnHooks;
 529+
 530+ public function __construct() {
 531+ $this->reset();
 532+ }
 533+
 534+ /**
 535+ * Init/reset or forgot about the current delayed test.
 536+ * Call to this will erase any hooks function that were pending.
 537+ */
 538+ public function reset() {
 539+ $this->hooks = array();
 540+ $this->fnHooks = array();
 541+ }
 542+
 543+ /**
 544+ * Called whenever we actually want to run the hook.
 545+ * Should be the case if we found the parserTest is not disabled
 546+ */
 547+ public function unleash( ParserTest &$parserTest ) {
 548+ # Trigger delayed hooks. Any failure will make us abort
 549+ foreach( $this->hooks as $hook ) {
 550+ $ret = $parserTest->requireHook( $hook );
 551+ if( !$ret ) {
 552+ return false;
 553+ }
 554+ }
 555+
 556+ # Trigger delayed function hooks. Any failure will make us abort
 557+ foreach( $this->fnHooks as $fnHook ) {
 558+ $ret = $parserTest->requireFunctionHook( $fnHook );
 559+ if( !$ret ) {
 560+ return false;
 561+ }
 562+ }
 563+
 564+ # Delayed execution was successful.
 565+ return true;
 566+ }
 567+
 568+ /**
 569+ * Similar to ParserTest object but does not run anything
 570+ * Use unleash() to really execute the hook
 571+ */
 572+ public function requireHook( $hook ) {
 573+ $this->hooks[] = $hook;
 574+ }
 575+ /**
 576+ * Similar to ParserTest object but does not run anything
 577+ * Use unleash() to really execute the hook function
 578+ */
 579+ public function requireFunctionHook( $fnHook ) {
 580+ $this->fnHooks[] = $fnHook;
 581+ }
 582+
 583+}

Follow-up revisions

RevisionCommit summaryAuthorDate
r104563Fix fatal error when running newParserTest...hashar14:23, 29 November 2011

Comments

#Comment by Hashar (talk | contribs)   14:24, 29 November 2011

did not work with NewParserTest because of type hinting. Fixed that with r104563.

#Comment by Platonides (talk | contribs)   17:46, 29 November 2011

It used to avoid reading the rest of the file if it required an unavailable hook. Now it's always parsing the whole file.

#Comment by Brion VIBBER (talk | contribs)   23:12, 1 December 2011

Wouldn't it make more sense to simply .... not check any hooks until actually running the test case? I'm kinda confused by all this code.

#Comment by Brion VIBBER (talk | contribs)   23:15, 1 December 2011

(Is this just a side effect of the ancient code running things line-by-line/section-by-section? I'd recommend modernizing that code so you don't "run" anything until you've finished going through the whole case...?)

#Comment by Hashar (talk | contribs)   23:39, 1 December 2011

The original idea was to parse tests, and build an array of DelayedParserTests. Than trigger them all at the end (i.e. foreach( $delayedTests as $test) { $test->unleash(); }

I eventually had an issue with the way we forge Articles from the .txt file and abandoned the idea. So the code above might look a bit messy.

#Comment by Brion VIBBER (talk | contribs)   00:20, 2 December 2011

Aha I see! That's actually something you'd want in order to skip the Article sections (with deps added) so my objection is withdrawn, code'll get use later. :)

Status & tagging log