r79435 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r79434‎ | r79435 | r79436 >
Date:18:10, 1 January 2011
Author:soxred93
Status:ok
Tags:
Comment:
Add fuzz tests to new parser tests (someone else should make sure this works as expected)
Modified paths:
  • /trunk/phase3/tests/phpunit/includes/parser/NewParserTest.php (modified) (history)

Diff [purge]

Index: trunk/phase3/tests/phpunit/includes/parser/NewParserTest.php
@@ -16,6 +16,11 @@
1717 public $hooks = array();
1818 public $functionHooks = array();
1919
 20+ //Fuzz test
 21+ public $maxFuzzTestLength = 300;
 22+ public $fuzzSeed = 0;
 23+ public $memoryLimit = 50;
 24+
2025 function setUp() {
2126 global $wgContLang;
2227 $wgContLang = Language::factory( 'en' );
@@ -311,12 +316,145 @@
312317 }
313318
314319 }
 320+
 321+ }
 322+
 323+ /**
 324+ * Run a fuzz test series
 325+ * Draw input from a set of test files
 326+ */
 327+ function testFuzzTests() {
315328
 329+ global $wgParserTestFiles;
 330+
 331+ $files = $wgParserTestFiles;
 332+
 333+ if( $this->getCliArg( 'file=' ) ) {
 334+ $files = array( $this->getCliArg( 'file=' ) );
 335+ }
 336+
 337+ $dict = $this->getFuzzInput( $files );
 338+ $dictSize = strlen( $dict );
 339+ $logMaxLength = log( $this->maxFuzzTestLength );
 340+
 341+ ini_set( 'memory_limit', $this->memoryLimit * 1048576 );
 342+
 343+ $user = new User;
 344+ $opts = ParserOptions::newFromUser( $user );
 345+ $title = Title::makeTitle( NS_MAIN, 'Parser_test' );
 346+
 347+ $id = 1;
 348+
 349+ while ( true ) {
316350
 351+ // Generate test input
 352+ mt_srand( ++$this->fuzzSeed );
 353+ $totalLength = mt_rand( 1, $this->maxFuzzTestLength );
 354+ $input = '';
 355+
 356+ while ( strlen( $input ) < $totalLength ) {
 357+ $logHairLength = mt_rand( 0, 1000000 ) / 1000000 * $logMaxLength;
 358+ $hairLength = min( intval( exp( $logHairLength ) ), $dictSize );
 359+ $offset = mt_rand( 0, $dictSize - $hairLength );
 360+ $input .= substr( $dict, $offset, $hairLength );
 361+ }
 362+
 363+ $this->setupGlobals();
 364+ $parser = $this->getParser();
 365+
 366+ // Run the test
 367+ try {
 368+ $parser->parse( $input, $title, $opts );
 369+ $this->assertTrue( true, "Test $id, fuzz seed {$this->fuzzSeed}" );
 370+ } catch ( Exception $exception ) {
 371+
 372+ ob_start();
 373+ var_dump( $input );
 374+ $input_dump = ob_get_contents();
 375+ ob_end_clean();
 376+
 377+ $this->assertTrue( false, "Test $id, fuzz seed {$this->fuzzSeed}. \n\nInput: $input_dump\n\nError: {$exception->getMessage()}\n\nBacktrace: {$exception->getTraceAsString()}" );
 378+ }
 379+
 380+ $this->teardownGlobals();
 381+ $parser->__destruct();
 382+
 383+ if ( $id % 100 == 0 ) {
 384+ $usage = intval( memory_get_usage( true ) / $this->memoryLimit / 1048576 * 100 );
 385+ //echo "{$this->fuzzSeed}: $numSuccess/$numTotal (mem: $usage%)\n";
 386+ if ( $usage > 90 ) {
 387+ $ret = "Out of memory:\n";
 388+ $memStats = $this->getMemoryBreakdown();
 389+
 390+ foreach ( $memStats as $name => $usage ) {
 391+ $ret .= "$name: $usage\n";
 392+ }
 393+
 394+ throw new MWException( $ret );
 395+ return;
 396+ }
 397+ }
 398+
 399+ $id++;
 400+
 401+ }
317402 }
318403
 404+ /**
 405+ * Get an input dictionary from a set of parser test files
 406+ */
 407+ function getFuzzInput( $filenames ) {
 408+ $dict = '';
 409+
 410+ foreach ( $filenames as $filename ) {
 411+ $contents = file_get_contents( $filename );
 412+ preg_match_all( '/!!\s*input\n(.*?)\n!!\s*result/s', $contents, $matches );
 413+
 414+ foreach ( $matches[1] as $match ) {
 415+ $dict .= $match . "\n";
 416+ }
 417+ }
 418+
 419+ return $dict;
 420+ }
319421
320422 /**
 423+ * Get a memory usage breakdown
 424+ */
 425+ function getMemoryBreakdown() {
 426+ $memStats = array();
 427+
 428+ foreach ( $GLOBALS as $name => $value ) {
 429+ $memStats['$' . $name] = strlen( serialize( $value ) );
 430+ }
 431+
 432+ $classes = get_declared_classes();
 433+
 434+ foreach ( $classes as $class ) {
 435+ $rc = new ReflectionClass( $class );
 436+ $props = $rc->getStaticProperties();
 437+ $memStats[$class] = strlen( serialize( $props ) );
 438+ $methods = $rc->getMethods();
 439+
 440+ foreach ( $methods as $method ) {
 441+ $memStats[$class] += strlen( serialize( $method->getStaticVariables() ) );
 442+ }
 443+ }
 444+
 445+ $functions = get_defined_functions();
 446+
 447+ foreach ( $functions['user'] as $function ) {
 448+ $rf = new ReflectionFunction( $function );
 449+ $memStats["$function()"] = strlen( serialize( $rf->getStaticVariables() ) );
 450+ }
 451+
 452+ asort( $memStats );
 453+
 454+ return $memStats;
 455+ }
 456+
 457+
 458+ /**
321459 * Run a given wikitext input through a freshly-constructed wiki parser,
322460 * and compare the output against the expected results.
323461 * Prints status and explanatory messages to stdout.

Status & tagging log