\nStrict Standards: Type: $type: $message in $file on line $line
\n";
}
// --------- End ---------
Also add/change this in LocalSettings.php:
// --------- Start ---------
$wgEnableProfileInfo = true;
$wgDBserver = "localhost"; // replace with DB server hostname
// --------- End ---------
Usage:
Run with "php fuzz-tester.php".
To see the various command-line options, run "php fuzz-tester.php --help".
To stop the script, press Ctrl-C.
Console output:
- If requested, first any previously failed tests will be rerun.
- Then new tests will be generated and run. Any tests that fail will be saved,
and a brief message about why they failed will be printed on the console.
- The console will show the number of tests run, time run, number of tests
failed, number of tests being done per minute, and the name of the current test.
TODO:
Some known things that could improve this script:
- Logging in with cookie jar storage needed for some tests (as there are some
pages that cannot be tested without being logged in, and which are currently
untested - e.g. Special:Emailuser, Special:Preferences, adding to Watchist).
- Testing of Timeline extension (I cannot test as ploticus has/had issues on
my architecture).
*/
/////////////////////////// COMMAND LINE HELP ////////////////////////////////////
// This is a command line script, load MediaWiki env (gives command line options);
require_once( dirname(__FILE__) . '/commandLine.inc' );
// if the user asked for an explanation of command line options.
if ( isset( $options["help"] ) ) {
print <<]
[--directory=] [--include-binary]
[--w3c-validate] [--delete-passed-retests] [--help]
[--user=] [--password=]
[--rerun-failed-tests] [--max-errors=]
[--max-runtime=]
[--specific-test=]
Options:
--quiet : Hides passed tests, shows only failed tests.
--base-url : URL to a wiki on which to run the tests.
The "http://" is optional and can be omitted.
--directory : Full path to directory for storing failed tests.
Will be created if it does not exist.
--include-binary : Includes non-alphanumeric characters in the tests.
--w3c-validate : Validates pages using the W3C's web validator.
Slow. Currently many pages fail validation.
--user : Login name of a valid user on your test wiki.
--password : Password for the valid user on your test wiki.
--delete-passed-retests : Will delete retests that now pass.
Requires --rerun-failed-tests to be meaningful.
--rerun-failed-tests : Whether to rerun any previously failed tests.
--max-errors : Maximum number of errors to report before exiting.
Does not include errors from --rerun-failed-tests
--max-runtime : Maximum runtime, in minutes, to run before exiting.
Only applies to new tests, not --rerun-failed-tests
--specific-test : Runs only the specified fuzz test.
Only applies to new tests, not --rerun-failed-tests
--keep-passed-tests : Saves all test files, even those that pass.
--help : Show this help message.
Example:
If you wanted to fuzz test a nightly MediaWiki checkout using cron for 1 hour,
and only wanted to be informed of errors, and did not want to redo previously
failed tests, and wanted a maximum of 100 errors, then you could do:
php {$_SERVER["SCRIPT_NAME"]} --quiet --max-errors=100 --max-runtime=60
ENDS;
exit( 0 );
}
// if we got command line options, check they look valid.
$validOptions = array ("quiet", "base-url", "directory", "include-binary",
"w3c-validate", "user", "password", "delete-passed-retests",
"rerun-failed-tests", "max-errors",
"max-runtime", "specific-test", "keep-passed-tests", "help" );
if (!empty($options)) {
$unknownArgs = array_diff (array_keys($options), $validOptions);
foreach ($unknownArgs as $invalidArg) {
print "Ignoring invalid command-line option: --$invalidArg\n";
}
}
///////////////////////////// CONFIGURATION ////////////////////////////////////
// URL to some wiki on which we can run our tests.
if (!empty($options["base-url"])) {
define("WIKI_BASE_URL", $options["base-url"]);
} else {
define("WIKI_BASE_URL", $wgServer . $wgScriptPath . '/');
}
// The directory name where we store the output.
// Example for Windows: "c:\\temp\\wiki-fuzz"
if (!empty($options["directory"])) {
define("DIRECTORY", $options["directory"] );
} else {
define("DIRECTORY", "{$wgUploadDirectory}/fuzz-tests");
}
// Should our test fuzz data include binary strings?
define("INCLUDE_BINARY", isset($options["include-binary"]) );
// Whether we want to validate HTML output on the web.
// At the moment very few generated pages will validate, so not recommended.
define("VALIDATE_ON_WEB", isset($options["w3c-validate"]) );
// URL to use to validate our output:
define("VALIDATOR_URL", "http://validator.w3.org/check");
// Location of Tidy standalone executable.
define("PATH_TO_TIDY", "/usr/bin/tidy");
// The name of a user who has edited on your wiki. Used
// when testing the Special:Contributions and Special:Userlogin page.
if (!empty($options["user"])) {
define("USER_ON_WIKI", $options["user"] );
} else {
define("USER_ON_WIKI", "nickj");
}
// The password of the above user. Used when testing the login page,
// and to do this we sometimes need to login successfully.
if (!empty($options["password"])) {
define("USER_PASSWORD", $options["password"] );
} else {
// And no, this is not a valid password on any public wiki.
define("USER_PASSWORD", "nickj");
}
// If we have a test that failed, and then we run it again, and it passes,
// do you want to delete it or keep it?
define("DELETE_PASSED_RETESTS", isset($options["delete-passed-retests"]) );
// Do we want to rerun old saved tests at script startup?
// Set to true to help catch regressions, or false if you only want new stuff.
define("RERUN_OLD_TESTS", isset($options["rerun-failed-tests"]) );
// File where the database errors are logged. Should be defined in LocalSettings.php.
define("DB_ERROR_LOG_FILE", $wgDBerrorLog );
// Run in chatty mode (all output, default), or run in quiet mode (only prints out details of failed tests)?
define("QUIET", isset($options["quiet"]) );
// Keep all test files, even those that pass. Potentially useful to tracking input that causes something
// unusual to happen, if you don't know what "unusual" is until later.
define("KEEP_PASSED_TESTS", isset($options["keep-passed-tests"]) );
// The maximum runtime, if specified.
if (!empty($options["max-runtime"]) && intval($options["max-runtime"])>0) {
define("MAX_RUNTIME", intval($options["max-runtime"]) );
}
// The maximum number of problems to find, if specified. Excludes retest errors.
if (!empty($options["max-errors"]) && intval($options["max-errors"])>0) {
define("MAX_ERRORS", intval($options["max-errors"]) );
}
// if the user has requested a specific test (instead of all tests), and the test they asked for looks valid.
if (!empty($options["specific-test"])) {
if (class_exists($options["specific-test"]) && get_parent_class($options["specific-test"])=="pageTest") {
define("SPECIFIC_TEST", $options["specific-test"] );
}
else {
print "Ignoring invalid --specific-test\n";
}
}
// Define the file extensions we'll use:
define("PHP_TEST" , ".test.php");
define("CURL_TEST", ".curl.sh" );
define("DATA_FILE", ".data.bin");
define("INFO_FILE", ".info.txt");
define("HTML_FILE", ".wiki_preview.html");
// If it goes wrong, we want to know about it.
error_reporting(E_ALL | E_STRICT);
//////////////// A CLASS THAT GENERATES RANDOM NASTY WIKI & HTML STRINGS //////////////////////
class wikiFuzz {
// Only some HTML tags are understood with params by MediaWiki, the rest are ignored.
// List the tags that accept params below, as well as what those params are.
public static $data = array(
"B" => array("CLASS", "ID", "STYLE", "lang", "dir", "title"),
"CAPTION" => array("CLASS", "ID", "STYLE", "align", "lang", "dir", "title"),
"CENTER" => array("CLASS", "STYLE", "ID", "lang", "dir", "title"),
"DIV" => array("CLASS", "STYLE", "ID", "align", "lang", "dir", "title"),
"FONT" => array("CLASS", "STYLE", "ID", "lang", "dir", "title", "face", "size", "color"),
"H1" => array("STYLE", "CLASS", "ID", "align", "lang", "dir", "title"),
"H2" => array("STYLE", "CLASS", "ID", "align", "lang", "dir", "title"),
"HR" => array("STYLE", "CLASS", "ID", "WIDTH", "lang", "dir", "title", "size", "noshade"),
"LI" => array("CLASS", "ID", "STYLE", "lang", "dir", "title", "type", "value"),
"TABLE" => array("STYLE", "CLASS", "ID", "BGCOLOR", "WIDTH", "ALIGN", "BORDER", "CELLPADDING",
"CELLSPACING", "lang", "dir", "title", "summary", "frame", "rules"),
"TD" => array("STYLE", "CLASS", "ID", "BGCOLOR", "WIDTH", "ALIGN", "COLSPAN", "ROWSPAN",
"VALIGN", "abbr", "axis", "headers", "scope", "nowrap", "height", "lang",
"dir", "title", "char", "charoff"),
"TH" => array("STYLE", "CLASS", "ID", "BGCOLOR", "WIDTH", "ALIGN", "COLSPAN", "ROWSPAN",
"VALIGN", "abbr", "axis", "headers", "scope", "nowrap", "height", "lang",
"dir", "title", "char", "charoff"),
"TR" => array("CLASS", "STYLE", "ID", "BGCOLOR", "ALIGN", "VALIGN", "lang", "dir", "title", "char", "charoff"),
"UL" => array("CLASS", "STYLE", "ID", "lang", "dir", "title", "type"),
"P" => array("style", "class", "id", "align", "lang", "dir", "title"),
"blockquote" => array("CLASS", "ID", "STYLE", "lang", "dir", "title", "cite"),
"span" => array("CLASS", "ID", "STYLE", "align", "lang", "dir", "title"),
"code" => array("CLASS", "ID", "STYLE", "lang", "dir", "title"),
"tt" => array("CLASS", "ID", "STYLE", "lang", "dir", "title"),
"small" => array("CLASS", "ID", "STYLE", "lang", "dir", "title"),
"big" => array("CLASS", "ID", "STYLE", "lang", "dir", "title"),
"s" => array("CLASS", "ID", "STYLE", "lang", "dir", "title"),
"u" => array("CLASS", "ID", "STYLE", "lang", "dir", "title"),
"del" => array("CLASS", "ID", "STYLE", "lang", "dir", "title", "datetime", "cite"),
"ins" => array("CLASS", "ID", "STYLE", "lang", "dir", "title", "datetime", "cite"),
"sub" => array("CLASS", "ID", "STYLE", "lang", "dir", "title"),
"sup" => array("CLASS", "ID", "STYLE", "lang", "dir", "title"),
"ol" => array("CLASS", "ID", "STYLE", "lang", "dir", "title", "type", "start"),
"br" => array("CLASS", "ID", "STYLE", "title", "clear"),
"cite" => array("CLASS", "ID", "STYLE", "lang", "dir", "title"),
"var" => array("CLASS", "ID", "STYLE", "lang", "dir", "title"),
"dl" => array("CLASS", "ID", "STYLE", "lang", "dir", "title"),
"ruby" => array("CLASS", "ID", "STYLE", "lang", "dir", "title"),
"rt" => array("CLASS", "ID", "STYLE", "lang", "dir", "title"),
"rp" => array("CLASS", "ID", "STYLE", "lang", "dir", "title"),
"dt" => array("CLASS", "ID", "STYLE", "lang", "dir", "title"),
"dl" => array("CLASS", "ID", "STYLE", "lang", "dir", "title"),
"em" => array("CLASS", "ID", "STYLE", "lang", "dir", "title"),
"strong" => array("CLASS", "ID", "STYLE", "lang", "dir", "title"),
"i" => array("CLASS", "ID", "STYLE", "lang", "dir", "title"),
"thead" => array("CLASS", "ID", "STYLE", "lang", "dir", "title", 'align', 'char', 'charoff', 'valign'),
"tfoot" => array("CLASS", "ID", "STYLE", "lang", "dir", "title", 'align', 'char', 'charoff', 'valign'),
"tbody" => array("CLASS", "ID", "STYLE", "lang", "dir", "title", 'align', 'char', 'charoff', 'valign'),
"colgroup" => array("CLASS", "ID", "STYLE", "lang", "dir", "title", 'align', 'char', 'charoff', 'valign', 'span', 'width'),
"col" => array("CLASS", "ID", "STYLE", "lang", "dir", "title", 'align', 'char', 'charoff', 'valign', 'span', 'width'),
"pre" => array("CLASS", "ID", "STYLE", "lang", "dir", "title", "width"),
// extension tags that accept parameters:
"sort" => array("order", "class"),
"ref" => array("name"),
"categorytree" => array("hideroot", "mode", "style"),
"chemform" => array("link", "wikilink", "query"),
"section" => array("begin", "new"),
// older MW transclusion.
"transclude" => array("page"),
);
// The types of the HTML that we will be testing were defined above
// Note: this needs to be initialized later to be equal to: array_keys(wikiFuzz::$data);
// as such, it also needs to also be publicly modifiable.
public static $types;
// Some attribute values.
static private $other = array("&","=",":","?","\"","\n","%n%n%n%n%n%n%n%n%n%n%n%n","\\");
static private $ints = array(
// various numbers
"0","-1","127","-7897","89000","808080","90928345",
"0xfffffff","ffff",
// Different ways of saying: '
"'", // Long UTF-8 Unicode encoding
"'", // dec version.
"'", // hex version.
"§", // malformed hex variant, MSB not zero.
// Different ways of saying: "
""", // Long UTF-8 Unicode encoding
""",
""", // hex version.
"¢", // malformed hex variant, MSB not zero.
// Different ways of saying: <
"<",
"<", // Long UTF-8 Unicode encoding without semicolon (Mediawiki wants the colon)
"<", // Long UTF-8 Unicode encoding with semicolon
"<",
"<", // hex version.
"¼", // malformed hex variant, MSB not zero.
"<", // mid-length hex version
"<", // slightly longer hex version, with capital "X"
// Different ways of saying: >
">",
">", // Long UTF-8 Unicode encoding
">",
">", // hex version.
"¾", // malformed variant, MSB not zero.
// Different ways of saying: [
"[", // Long UTF-8 Unicode encoding
"[",
"[", // hex version.
// Different ways of saying: {{
"{{", // Long UTF-8 Unicode encoding
"{{",
"{{", // hex version.
// Different ways of saying: |
"|", // Long UTF-8 Unicode encoding
"|",
"|", // hex version.
"ü", // malformed hex variant, MSB not zero.
// a "lignature" - http://www.robinlionheart.com/stds/html4/spchars#ligature
""
);
// Defines various wiki-related bits of syntax, that can potentially cause
// MediaWiki to do something other than just print that literal text.
static private $ext = array(
// links, templates, parameters.
"[[", "]]", "{{", "}}", "|", "[", "]", "{{{", "}}}", "|]]",
// wiki tables.
"\n{|", "\n|}",
"!",
"\n!",
"!!",
"||",
"\n|-", "| ", "\n|",
// section headings.
"=", "==", "===", "====", "=====", "======",
// lists (ordered and unordered) and indentation.
"\n*", "*", "\n:", ":",
"\n#", "#",
// definition lists (dl, dt, dd), newline, and newline with pre, and a tab.
"\n;", ";", "\n ",
// Whitespace: newline, tab, space.
"\n", "\t", " ",
// Some XSS attack vectors from http://ha.ckers.org/xss.html
" ", // tab
"
", // newline
"
", // carriage return
"\0", // null character
" ", // spaces and meta characters
"'';!--\"=&{()}", // compact injection of XSS & SQL tester
// various NULL fields
"%00",
"",
"\0",
// horizontal rule.
"-----", "\n-----",
// signature, redirect, bold, italics.
"~~~~", "#REDIRECT [[", "'''", "''",
// comments.
"",
// quotes.
"\"", "'",
// tag start and tag end.
"<", ">",
// implicit link creation on URIs.
"http://",
"https://",
"ftp://",
"irc://",
"news:",
'gopher://',
'telnet://',
'nntp://',
'worldwind://',
'mailto:',
// images.
"[[image:",
".gif",
".png",
".jpg",
".jpeg",
'thumbnail=',
'thumbnail',
'thumb=',
'thumb',
'right',
'none',
'left',
'framed',
'frame',
'enframed',
'centre',
'center',
"Image:",
"[[:Image",
'px',
'upright=',
'border',
// misc stuff to throw at the Parser.
'%08X',
'/',
":x{|",
"\n|+",
"",
"",
" \302\273",
" :",
" !",
" ;",
"\302\253",
"[[category:",
"?=",
"(",
")",
"]]]",
"../",
"{{{{",
"}}}}",
"[[Special:",
"",
"",
"',
// implicit link creation on booknum, RFC, and PubMed ID usage (both with and without IDs)
"ISBN 2",
"RFC 000",
"PMID 000",
"ISBN ",
"RFC ",
"PMID ",
// magic words:
'__NOTOC__',
'__FORCETOC__',
'__NOEDITSECTION__',
'__START__',
'__NOTITLECONVERT__',
'__NOCONTENTCONVERT__',
'__END__',
'__TOC__',
'__NOTC__',
'__NOCC__',
"__FORCETOC__",
"__NEWSECTIONLINK__",
"__NOGALLERY__",
// more magic words / internal templates.
'{{PAGENAME}}',
'{{PAGENAMEE}}',
'{{NAMESPACE}}',
"{{MSG:",
"}}",
"{{MSGNW:",
"}}",
"{{INT:",
"}}",
'{{SITENAME}}',
"{{NS:",
"}}",
"{{LOCALURL:",
"}}",
"{{LOCALURLE:",
"}}",
"{{SCRIPTPATH}}",
"{{GRAMMAR:gentiv|",
"}}",
"{{REVISIONID}}",
"{{SUBPAGENAME}}",
"{{SUBPAGENAMEE}}",
"{{ns:0}}",
"{{fullurle:",
"}}",
"{{subst::",
"}}",
"{{UCFIRST:",
"}}",
"{{UC:",
'{{SERVERNAME}}',
'{{SERVER}}',
"{{RAW:",
"}}",
"{{PLURAL:",
"}}",
"{{LCFIRST:",
"}}",
"{{LC:",
"}}",
'{{CURRENTWEEK}}',
'{{CURRENTDOW}}',
"{{INT:{{LC:contribs-showhideminor}}|",
"}}",
"{{INT:googlesearch|",
"}}",
"{{BASEPAGENAME}}",
"{{CONTENTLANGUAGE}}",
"{{PAGESINNAMESPACE:}}",
"{{#language:",
"}}",
"{{#special:",
"}}",
"{{#special:emailuser",
"}}",
// Some raw link for magic words.
"{{NUMBEROFPAGES:R",
"}}",
"{{NUMBEROFUSERS:R",
"}}",
"{{NUMBEROFARTICLES:R",
"}}",
"{{NUMBEROFFILES:R",
"}}",
"{{NUMBEROFADMINS:R",
"}}",
"{{padleft:",
"}}",
"{{padright:",
"}}",
"{{DEFAULTSORT:",
"}}",
// internal Math "extension":
"",
// Parser extension functions:
"{{#expr:",
"{{#if:",
"{{#ifeq:",
"{{#ifexist:",
"{{#ifexpr:",
"{{#switch:",
"{{#time:",
"}}",
// references table for the Cite extension.
"",
// Internal Parser tokens - try inserting some of these.
"UNIQ25f46b0524f13e67NOPARSE",
"UNIQ17197916557e7cd6-HTMLCommentStrip46238afc3bb0cf5f00000002",
"\x07UNIQ17197916557e7cd6-HTMLCommentStrip46238afc3bb0cf5f00000002-QINU",
// Inputbox extension:
"\ntype=search\nsearchbuttonlabel=\n",
"",
// charInsert extension:
"",
"",
// wikiHiero extension:
"",
"",
// Image gallery:
"",
"",
// FixedImage extension.
"",
// Timeline extension: currently untested.
// Nowiki:
"",
"",
// an external image to test the external image displaying code
"http://debian.org/Pics/debian.png",
// LabeledSectionTransclusion extension.
"{{#lstx:",
"}}",
"{{#lst:",
"}}",
"{{#lst:Main Page|",
"}}"
);
/**
** Randomly returns one element of the input array.
*/
static public function chooseInput(array $input) {
$randindex = wikiFuzz::randnum(count($input) - 1);
return $input[$randindex];
}
// Max number of parameters for HTML attributes.
static private $maxparams = 10;
/**
** Returns random number between finish and start.
*/
static public function randnum($finish,$start=0) {
return mt_rand($start,$finish);
}
/**
** Returns a mix of random text and random wiki syntax.
*/
static private function randstring() {
$thestring = "";
for ($i=0; $i<40; $i++) {
$what = wikiFuzz::randnum(1);
if ($what == 0) { // include some random wiki syntax
$which = wikiFuzz::randnum(count(wikiFuzz::$ext) - 1);
$thestring .= wikiFuzz::$ext[$which];
}
else { // include some random text
$char = INCLUDE_BINARY
// Decimal version:
// "" . wikiFuzz::randnum(255) . ";"
// Hex version:
? "" . str_pad(dechex(wikiFuzz::randnum(255)), wikiFuzz::randnum(2, 7), "0", STR_PAD_LEFT) . ";"
// A truly binary version:
// ? chr(wikiFuzz::randnum(0,255))
: chr(wikiFuzz::randnum(126,32));
$length = wikiFuzz::randnum(8);
$thestring .= str_repeat ($char, $length);
}
}
return $thestring;
}
/**
** Returns either random text, or random wiki syntax, or random data from "ints",
** or random data from "other".
*/
static private function makestring() {
$what = wikiFuzz::randnum(2);
if ($what == 0) {
return wikiFuzz::randstring();
}
elseif ($what == 1) {
return wikiFuzz::$ints[wikiFuzz::randnum(count(wikiFuzz::$ints) - 1)];
}
else {
return wikiFuzz::$other[wikiFuzz::randnum(count(wikiFuzz::$other) - 1)];
}
}
/**
** Strips out the stuff that Mediawiki balks at in a page's title.
** Implementation copied/pasted from cleanupTable.inc & cleanupImages.php
*/
static public function makeTitleSafe($str) {
$legalTitleChars = " %!\"$&'()*,\\-.\\/0-9:;=?@A-Z\\\\^_`a-z~\\x80-\\xFF";
return preg_replace_callback(
"/([^$legalTitleChars])/",
create_function(
// single quotes are essential here,
// or alternative escape all $ as \$
'$matches',
'return sprintf( "\\x%02x", ord( $matches[1] ) );'
),
$str );
}
/**
** Returns a string of fuzz text.
*/
static private function loop() {
switch ( wikiFuzz::randnum(3) ) {
case 1: // an opening tag, with parameters.
$string = "";
$i = wikiFuzz::randnum(count(wikiFuzz::$types) - 1);
$t = wikiFuzz::$types[$i];
$arr = wikiFuzz::$data[$t];
$string .= "<" . $t . " ";
$num_params = min(wikiFuzz::$maxparams, count($arr));
for ($z=0; $z<$num_params; $z++) {
$badparam = $arr[wikiFuzz::randnum(count($arr) - 1)];
$badstring = wikiFuzz::makestring();
$string .= $badparam . "=" . wikiFuzz::getRandQuote() . $badstring . wikiFuzz::getRandQuote() . " ";
}
$string .= ">\n";
return $string;
case 2: // a closing tag.
$i = wikiFuzz::randnum(count(wikiFuzz::$types) - 1);
return "". wikiFuzz::$types[$i] . ">";
case 3: // a random string, between tags.
return wikiFuzz::makeString();
}
return ""; // catch-all, should never be called.
}
/**
** Returns one of the three styles of random quote: ', ", and nothing.
*/
static private function getRandQuote() {
switch ( wikiFuzz::randnum(3) ) {
case 1 : return "'";
case 2 : return "\"";
default: return "";
}
}
/**
** Returns fuzz text, with the parameter indicating approximately how many lines of text you want.
*/
static public function makeFuzz($maxtypes = 2) {
$page = "";
for ($k=0; $k<$maxtypes; $k++) {
$page .= wikiFuzz::loop();
}
return $page;
}
}
//////// MEDIAWIKI PAGES TO TEST, AND HOW TO TEST THEM ///////
/**
** A page test has just these things:
** 1) Form parameters.
** 2) the URL we are going to test those parameters on.
** 3) Any cookies required for the test.
** 4) Whether Tidy should validate the page. Defaults to true, but can be turned off.
** Declared abstract because it should be extended by a class
** that supplies these parameters.
*/
abstract class pageTest {
protected $params;
protected $pagePath;
protected $cookie = "";
protected $tidyValidate = true;
public function getParams() {
return $this->params;
}
public function getPagePath() {
return $this->pagePath;
}
public function getCookie() {
return $this->cookie;
}
public function tidyValidate() {
return $this->tidyValidate;
}
}
/**
** a page test for the "Edit" page. Tests Parser.php and Sanitizer.php.
*/
class editPageTest extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=WIKIFUZZ";
$this->params = array (
"action" => "submit",
"wpMinoredit" => wikiFuzz::makeFuzz(2),
"wpPreview" => wikiFuzz::makeFuzz(2),
"wpSection" => wikiFuzz::makeFuzz(2),
"wpEdittime" => wikiFuzz::makeFuzz(2),
"wpSummary" => wikiFuzz::makeFuzz(2),
"wpScrolltop" => wikiFuzz::makeFuzz(2),
"wpStarttime" => wikiFuzz::makeFuzz(2),
"wpAutoSummary" => wikiFuzz::makeFuzz(2),
"wpTextbox1" => wikiFuzz::makeFuzz(40) // the main wiki text, need lots of this.
);
// sometimes we don't want to specify certain parameters.
if (wikiFuzz::randnum(6) == 0) unset($this->params["wpSection"]);
if (wikiFuzz::randnum(6) == 0) unset($this->params["wpEdittime"]);
if (wikiFuzz::randnum(6) == 0) unset($this->params["wpSummary"]);
if (wikiFuzz::randnum(6) == 0) unset($this->params["wpScrolltop"]);
if (wikiFuzz::randnum(6) == 0) unset($this->params["wpStarttime"]);
if (wikiFuzz::randnum(6) == 0) unset($this->params["wpAutoSummary"]);
if (wikiFuzz::randnum(6) == 0) unset($this->params["wpTextbox1"]);
}
}
/**
** a page test for "Special:Listusers".
*/
class listusersTest extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special:Listusers";
$this->params = array (
"title" => wikiFuzz::makeFuzz(2),
"group" => wikiFuzz::makeFuzz(2),
"username" => wikiFuzz::makeFuzz(2),
"Go" => wikiFuzz::makeFuzz(2),
"limit" => wikiFuzz::chooseInput( array("0", "-1", "---'----------0", "+1", "8134", wikiFuzz::makeFuzz(2)) ),
"offset" => wikiFuzz::chooseInput( array("0", "-1", "--------'-----0", "+1", "81343242346234234", wikiFuzz::makeFuzz(2)) )
);
}
}
/**
** a page test for "Special:Search".
*/
class searchTest extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special:Search";
$this->params = array (
"action" => "index.php?title=Special:Search",
"ns0" => wikiFuzz::makeFuzz(2),
"ns1" => wikiFuzz::makeFuzz(2),
"ns2" => wikiFuzz::makeFuzz(2),
"ns3" => wikiFuzz::makeFuzz(2),
"ns4" => wikiFuzz::makeFuzz(2),
"ns5" => wikiFuzz::makeFuzz(2),
"ns6" => wikiFuzz::makeFuzz(2),
"ns7" => wikiFuzz::makeFuzz(2),
"ns8" => wikiFuzz::makeFuzz(2),
"ns9" => wikiFuzz::makeFuzz(2),
"ns10" => wikiFuzz::makeFuzz(2),
"ns11" => wikiFuzz::makeFuzz(2),
"ns12" => wikiFuzz::makeFuzz(2),
"ns13" => wikiFuzz::makeFuzz(2),
"ns14" => wikiFuzz::makeFuzz(2),
"ns15" => wikiFuzz::makeFuzz(2),
"redirs" => wikiFuzz::makeFuzz(2),
"search" => wikiFuzz::makeFuzz(2),
"offset" => wikiFuzz::chooseInput( array("", "0", "-1", "--------'-----0", "+1", "81343242346234234", wikiFuzz::makeFuzz(2)) ),
"fulltext" => wikiFuzz::chooseInput( array("", "0", "1", "--------'-----0", "+1", wikiFuzz::makeFuzz(2)) ),
"searchx" => wikiFuzz::chooseInput( array("", "0", "1", "--------'-----0", "+1", wikiFuzz::makeFuzz(2)) )
);
}
}
/**
** a page test for "Special:Recentchanges".
*/
class recentchangesTest extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special:Recentchanges";
$this->params = array (
"action" => wikiFuzz::makeFuzz(2),
"title" => wikiFuzz::makeFuzz(2),
"namespace" => wikiFuzz::chooseInput( range(-1, 15) ),
"Go" => wikiFuzz::makeFuzz(2),
"invert" => wikiFuzz::chooseInput( array("-1", "---'----------0", "+1", "8134", wikiFuzz::makeFuzz(2)) ),
"hideanons" => wikiFuzz::chooseInput( array("-1", "------'-------0", "+1", "8134", wikiFuzz::makeFuzz(2)) ),
'limit' => wikiFuzz::chooseInput( array("0", "-1", "---------'----0", "+1", "81340909772349234", wikiFuzz::makeFuzz(2)) ),
"days" => wikiFuzz::chooseInput( array("-1", "----------'---0", "+1", "8134", wikiFuzz::makeFuzz(2)) ),
"hideminor" => wikiFuzz::chooseInput( array("-1", "-----------'--0", "+1", "8134", wikiFuzz::makeFuzz(2)) ),
"hidebots" => wikiFuzz::chooseInput( array("-1", "---------'----0", "+1", "8134", wikiFuzz::makeFuzz(2)) ),
"hideliu" => wikiFuzz::chooseInput( array("-1", "-------'------0", "+1", "8134", wikiFuzz::makeFuzz(2)) ),
"hidepatrolled" => wikiFuzz::chooseInput( array("-1", "-----'--------0", "+1", "8134", wikiFuzz::makeFuzz(2)) ),
"hidemyself" => wikiFuzz::chooseInput( array("-1", "--'-----------0", "+1", "8134", wikiFuzz::makeFuzz(2)) ),
'categories_any'=> wikiFuzz::chooseInput( array("-1", "--'-----------0", "+1", "8134", wikiFuzz::makeFuzz(2)) ),
'categories' => wikiFuzz::chooseInput( array("-1", "--'-----------0", "+1", "8134", wikiFuzz::makeFuzz(2)) ),
'feed' => wikiFuzz::chooseInput( array("-1", "--'-----------0", "+1", "8134", wikiFuzz::makeFuzz(2)) )
);
}
}
/**
** a page test for "Special:Prefixindex".
*/
class prefixindexTest extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special:Prefixindex";
$this->params = array (
"title" => "Special:Prefixindex",
"namespace" => wikiFuzz::randnum(-10,101),
"Go" => wikiFuzz::makeFuzz(2)
);
// sometimes we want 'prefix', sometimes we want 'from', and sometimes we want nothing.
if (wikiFuzz::randnum(3) == 0) {
$this->params["prefix"] = wikiFuzz::chooseInput( array("-1", "-----'--------0", "+++--+1",
wikiFuzz::randnum(-10,8134), wikiFuzz::makeFuzz(2)) );
}
if (wikiFuzz::randnum(3) == 0) {
$this->params["from"] = wikiFuzz::chooseInput( array("-1", "-----'--------0", "+++--+1",
wikiFuzz::randnum(-10,8134), wikiFuzz::makeFuzz(2)) );
}
}
}
/**
** a page test for "Special:MIMEsearch".
*/
class mimeSearchTest extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special:MIMEsearch";
$this->params = array (
"action" => "index.php?title=Special:MIMEsearch",
"mime" => wikiFuzz::makeFuzz(3),
'limit' => wikiFuzz::chooseInput( array("0", "-1", "-------'------0", "+1", "81342321351235325", wikiFuzz::makeFuzz(2)) ),
'offset' => wikiFuzz::chooseInput( array("0", "-1", "-----'--------0", "+1", "81341231235365252234324", wikiFuzz::makeFuzz(2)) )
);
}
}
/**
** a page test for "Special:Log".
*/
class specialLogTest extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special:Log";
$this->params = array (
"type" => wikiFuzz::chooseInput( array("", wikiFuzz::makeFuzz(2)) ),
"par" => wikiFuzz::makeFuzz(2),
"user" => wikiFuzz::makeFuzz(2),
"page" => wikiFuzz::makeFuzz(2),
"from" => wikiFuzz::makeFuzz(2),
"until" => wikiFuzz::makeFuzz(2),
"title" => wikiFuzz::makeFuzz(2)
);
}
}
/**
** a page test for "Special:Userlogin", with a successful login.
*/
class successfulUserLoginTest extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special:Userlogin&action=submitlogin&type=login&returnto=" . wikiFuzz::makeFuzz(2);
$this->params = array (
"wpName" => USER_ON_WIKI,
// sometimes real password, sometimes not:
'wpPassword' => wikiFuzz::chooseInput( array( wikiFuzz::makeFuzz(2), USER_PASSWORD ) ),
'wpRemember' => wikiFuzz::makeFuzz(2)
);
$this->cookie = "wikidb_session=" . wikiFuzz::chooseInput( array("1" , wikiFuzz::makeFuzz(2) ) );
}
}
/**
** a page test for "Special:Userlogin".
*/
class userLoginTest extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special:Userlogin";
$this->params = array (
'wpRetype' => wikiFuzz::makeFuzz(2),
'wpRemember' => wikiFuzz::makeFuzz(2),
'wpRealName' => wikiFuzz::makeFuzz(2),
'wpPassword' => wikiFuzz::makeFuzz(2),
'wpName' => wikiFuzz::makeFuzz(2),
'wpMailmypassword'=> wikiFuzz::makeFuzz(2),
'wpLoginattempt' => wikiFuzz::makeFuzz(2),
'wpEmail' => wikiFuzz::makeFuzz(2),
'wpDomain' => wikiFuzz::chooseInput( array("", "local", wikiFuzz::makeFuzz(2)) ),
'wpCreateaccountMail' => wikiFuzz::chooseInput( array("", wikiFuzz::makeFuzz(2)) ),
'wpCreateaccount' => wikiFuzz::chooseInput( array("", wikiFuzz::makeFuzz(2)) ),
'wpCookieCheck' => wikiFuzz::chooseInput( array("", wikiFuzz::makeFuzz(2)) ),
'type' => wikiFuzz::chooseInput( array("signup", "login", "", wikiFuzz::makeFuzz(2)) ),
'returnto' => wikiFuzz::makeFuzz(2),
'action' => wikiFuzz::chooseInput( array("", "submitlogin", wikiFuzz::makeFuzz(2)) )
);
$this->cookie = "wikidb_session=" . wikiFuzz::chooseInput( array("1" , wikiFuzz::makeFuzz(2) ) );
}
}
/**
** a page test for "Special:Ipblocklist" (also includes unblocking)
*/
class ipblocklistTest extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special:Ipblocklist";
$this->params = array (
'wpUnblockAddress'=> wikiFuzz::makeFuzz(2),
'ip' => wikiFuzz::chooseInput( array("20398702394", "", "Nickj2", wikiFuzz::makeFuzz(2),
// something like an IP address, sometimes invalid:
( wikiFuzz::randnum(300,-20) . "." . wikiFuzz::randnum(300,-20) . "."
. wikiFuzz::randnum(300,-20) . "." .wikiFuzz::randnum(300,-20) ) ) ),
'id' => wikiFuzz::makeFuzz(2),
'wpUnblockReason' => wikiFuzz::makeFuzz(2),
'action' => wikiFuzz::chooseInput( array(wikiFuzz::makeFuzz(2), "success", "submit", "unblock") ),
'wpEditToken' => wikiFuzz::makeFuzz(2),
'wpBlock' => wikiFuzz::chooseInput( array(wikiFuzz::makeFuzz(2), "") ),
'limit' => wikiFuzz::chooseInput( array("0", "-1", "--------'-----0", "+1",
"09700982312351132098234", wikiFuzz::makeFuzz(2)) ),
'offset' => wikiFuzz::chooseInput( array("0", "-1", "------'-------0", "+1",
"09700980982341535324234234", wikiFuzz::makeFuzz(2)) )
);
// sometimes we don't want to specify certain parameters.
if (wikiFuzz::randnum(4) == 0) unset($this->params["action"]);
if (wikiFuzz::randnum(3) == 0) unset($this->params["ip"]);
if (wikiFuzz::randnum(2) == 0) unset($this->params["id"]);
if (wikiFuzz::randnum(3) == 0) unset($this->params["wpUnblockAddress"]);
}
}
/**
** a page test for "Special:Newimages".
*/
class newImagesTest extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special:Newimages";
$this->params = array (
'hidebots' => wikiFuzz::chooseInput( array(wikiFuzz::makeFuzz(2), "1", "", "-1") ),
'wpIlMatch' => wikiFuzz::makeFuzz(2),
'until' => wikiFuzz::makeFuzz(2),
'from' => wikiFuzz::makeFuzz(2)
);
// sometimes we don't want to specify certain parameters.
if (wikiFuzz::randnum(6) == 0) unset($this->params["until"]);
if (wikiFuzz::randnum(6) == 0) unset($this->params["from"]);
}
}
/**
** a page test for the "Special:Imagelist" page.
*/
class imagelistTest extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special:Imagelist";
$this->params = array (
'sort' => wikiFuzz::chooseInput( array("bysize", "byname" , "bydate", wikiFuzz::makeFuzz(2)) ),
'limit' => wikiFuzz::chooseInput( array("0", "-1", "--------'-----0", "+1", "09700982312351132098234", wikiFuzz::makeFuzz(2)) ),
'offset' => wikiFuzz::chooseInput( array("0", "-1", "------'-------0", "+1", "09700980982341535324234234", wikiFuzz::makeFuzz(2)) ),
'wpIlMatch' => wikiFuzz::makeFuzz(2)
);
}
}
/**
** a page test for "Special:Export".
*/
class specialExportTest extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special:Export";
$this->params = array (
'action' => wikiFuzz::chooseInput( array("submit", "", wikiFuzz::makeFuzz(2)) ),
'pages' => wikiFuzz::makeFuzz(2),
'curonly' => wikiFuzz::chooseInput( array("", "0", "-1", wikiFuzz::makeFuzz(2)) ),
'listauthors' => wikiFuzz::chooseInput( array("", "0", "-1", wikiFuzz::makeFuzz(2)) ),
'history' => wikiFuzz::chooseInput( array("0", "-1", "------'-------0", "+1", "09700980982341535324234234", wikiFuzz::makeFuzz(2)) ),
);
// For the time being, need to disable "submit" action as Tidy barfs on MediaWiki's XML export.
if ($this->params['action'] == 'submit') $this->params['action'] = '';
// Sometimes remove the history field.
if (wikiFuzz::randnum(2) == 0) unset($this->params["history"]);
// page does not produce HTML.
$this->tidyValidate = false;
}
}
/**
** a page test for "Special:Booksources".
*/
class specialBooksourcesTest extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special:Booksources";
$this->params = array (
'go' => wikiFuzz::makeFuzz(2),
// ISBN codes have to contain some semi-numeric stuff or will be ignored:
'isbn' => "0X0" . wikiFuzz::makeFuzz(2)
);
}
}
/**
** a page test for "Special:Allpages".
*/
class specialAllpagesTest extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special%3AAllpages";
$this->params = array (
'from' => wikiFuzz::makeFuzz(2),
'namespace' => wikiFuzz::chooseInput( range(-1, 15) ),
'go' => wikiFuzz::makeFuzz(2)
);
}
}
/**
** a page test for the page History.
*/
class pageHistoryTest extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Main_Page&action=history";
$this->params = array (
'limit' => wikiFuzz::chooseInput( array("-1", "0", "-------'------0", "+1", "8134", wikiFuzz::makeFuzz(2)) ),
'offset' => wikiFuzz::chooseInput( array("-1", "0", "------'-------0", "+1", "9823412312312412435", wikiFuzz::makeFuzz(2)) ),
"go" => wikiFuzz::chooseInput( array("first", "last", wikiFuzz::makeFuzz(2)) ),
"dir" => wikiFuzz::chooseInput( array("prev", "next", wikiFuzz::makeFuzz(2)) ),
"diff" => wikiFuzz::chooseInput( array("-1", "--------'-----0", "+1", "8134", wikiFuzz::makeFuzz(2)) ),
"oldid" => wikiFuzz::chooseInput( array("prev", "-1", "+1", "8134", wikiFuzz::makeFuzz(2)) ),
"feed" => wikiFuzz::makeFuzz(2)
);
}
}
/**
** a page test for the Special:Contributions".
*/
class contributionsTest extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special:Contributions/" . USER_ON_WIKI;
$this->params = array (
'target' => wikiFuzz::chooseInput( array(wikiFuzz::makeFuzz(2), "newbies", USER_ON_WIKI) ),
'namespace' => wikiFuzz::chooseInput( array(-1, 15, 1, wikiFuzz::makeFuzz(2)) ),
'offset' => wikiFuzz::chooseInput( array("0", "-1", "------'-------0", "+1", "982342131232131231241", wikiFuzz::makeFuzz(2)) ),
'bot' => wikiFuzz::chooseInput( array("", "-1", "0", "1", wikiFuzz::makeFuzz(2)) ),
'go' => wikiFuzz::chooseInput( array("-1", 'prev', 'next', wikiFuzz::makeFuzz(2)) )
);
}
}
/**
** a page test for viewing a normal page, whilst posting various params.
*/
class viewPageTest extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Main_Page";
$this->params = array (
"useskin" => wikiFuzz::chooseInput( array("chick", "cologneblue", "myskin",
"nostalgia", "simple", "standard", wikiFuzz::makeFuzz(2)) ),
"uselang" => wikiFuzz::chooseInput( array( wikiFuzz::makeFuzz(2),
"ab", "af", "an", "ar", "arc", "as", "ast", "av", "ay", "az", "ba",
"bat-smg", "be", "bg", "bm", "bn", "bo", "bpy", "br", "bs", "ca",
"ce", "cs", "csb", "cv", "cy", "da", "de", "dv", "dz", "el", "en",
"eo", "es", "et", "eu", "fa", "fi", "fo", "fr", "fur", "fy", "ga",
"gn", "gsw", "gu", "he", "hi", "hr", "hu", "ia", "id", "ii", "is",
"it", "ja", "jv", "ka", "km", "kn", "ko", "ks", "ku", "kv", "la",
"li", "lo", "lt", "lv", "mk", "ml", "ms", "nah", "nap", "nds",
"nds-nl", "nl", "nn", "no", "non", "nv", "oc", "or", "os", "pa",
"pl", "pms", "ps", "pt", "pt-br", "qu", "rmy", "ro", "ru", "sc",
"sd", "sk", "sl", "sq", "sr", "sr-ec", "sr-el",
"su", "sv", "ta", "te", "th", "tr", "tt", "ty", "tyv", "udm",
"ug", "uk", "ur", "utf8", "vec", "vi", "wa", "xal", "yi", "za",
"zh", "zh-cn", "zh-hk", "zh-sg", "zh-tw", "zh-tw") ),
"returnto" => wikiFuzz::makeFuzz(2),
"feed" => wikiFuzz::chooseInput( array("atom", "rss", wikiFuzz::makeFuzz(2)) ),
"rcid" => wikiFuzz::makeFuzz(2),
"action" => wikiFuzz::chooseInput( array("view", "raw", "render", wikiFuzz::makeFuzz(2), "markpatrolled") ),
"printable" => wikiFuzz::makeFuzz(2),
"oldid" => wikiFuzz::makeFuzz(2),
"redirect" => wikiFuzz::makeFuzz(2),
"diff" => wikiFuzz::makeFuzz(2),
"search" => wikiFuzz::makeFuzz(2),
"rdfrom" => wikiFuzz::makeFuzz(2), // things from Article.php from here on:
"token" => wikiFuzz::makeFuzz(2),
"tbid" => wikiFuzz::makeFuzz(2),
"action" => wikiFuzz::chooseInput( array("purge", wikiFuzz::makeFuzz(2)) ),
"wpReason" => wikiFuzz::makeFuzz(2),
"wpEditToken" => wikiFuzz::makeFuzz(2),
"from" => wikiFuzz::makeFuzz(2),
"bot" => wikiFuzz::makeFuzz(2),
"summary" => wikiFuzz::makeFuzz(2),
"direction" => wikiFuzz::chooseInput( array("next", "prev", wikiFuzz::makeFuzz(2)) ),
"section" => wikiFuzz::makeFuzz(2),
"preload" => wikiFuzz::makeFuzz(2),
);
// Tidy does not know how to valid atom or rss, so exclude from testing for the time being.
if ($this->params["feed"] == "atom") { unset($this->params["feed"]); }
else if ($this->params["feed"] == "rss") { unset($this->params["feed"]); }
// Raw pages cannot really be validated
if ($this->params["action"] == "raw") unset($this->params["action"]);
// sometimes we don't want to specify certain parameters.
if (wikiFuzz::randnum(6) == 0) unset($this->params["rcid"]);
if (wikiFuzz::randnum(6) == 0) unset($this->params["diff"]);
if (wikiFuzz::randnum(6) == 0) unset($this->params["rdfrom"]);
if (wikiFuzz::randnum(3) == 0) unset($this->params["oldid"]);
// usually don't want action == purge.
if (wikiFuzz::randnum(6) > 1) unset($this->params["action"]);
}
}
/**
** a page test for "Special:Allmessages".
*/
class specialAllmessagesTest extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special:Allmessages";
// only really has one parameter
$this->params = array (
"ot" => wikiFuzz::chooseInput( array("php", "html", wikiFuzz::makeFuzz(2)) )
);
}
}
/**
** a page test for "Special:Newpages".
*/
class specialNewpages extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special:Newpages";
$this->params = array (
"namespace" => wikiFuzz::chooseInput( range(-1, 15) ),
"feed" => wikiFuzz::chooseInput( array("atom", "rss", wikiFuzz::makeFuzz(2)) ),
'limit' => wikiFuzz::chooseInput( array("-1", "0", "-------'------0", "+1", "8134", wikiFuzz::makeFuzz(2)) ),
'offset' => wikiFuzz::chooseInput( array("-1", "0", "------'-------0", "+1", "9823412312312412435", wikiFuzz::makeFuzz(2)) )
);
// Tidy does not know how to valid atom or rss, so exclude from testing for the time being.
if ($this->params["feed"] == "atom") { unset($this->params["feed"]); }
else if ($this->params["feed"] == "rss") { unset($this->params["feed"]); }
}
}
/**
** a page test for "redirect.php"
*/
class redirectTest extends pageTest {
function __construct() {
$this->pagePath = "redirect.php";
$this->params = array (
"wpDropdown" => wikiFuzz::makeFuzz(2)
);
// sometimes we don't want to specify certain parameters.
if (wikiFuzz::randnum(6) == 0) unset($this->params["wpDropdown"]);
}
}
/**
** a page test for "Special:Confirmemail"
*/
class confirmEmail extends pageTest {
function __construct() {
// sometimes we send a bogus confirmation code, and sometimes we don't.
$this->pagePath = "index.php?title=Special:Confirmemail" . wikiFuzz::chooseInput( array("", "/" . wikiFuzz::makeTitleSafe(wikiFuzz::makeFuzz(1)) ) );
$this->params = array (
"token" => wikiFuzz::makeFuzz(2)
);
}
}
/**
** a page test for "Special:Watchlist"
** Note: this test would be better if we were logged in.
*/
class watchlistTest extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special:Watchlist";
$this->params = array (
"remove" => wikiFuzz::chooseInput( array("Remove checked items from watchlist", wikiFuzz::makeFuzz(2))),
'days' => wikiFuzz::chooseInput( array(0, -1, -230, "--", 3, 9, wikiFuzz::makeFuzz(2)) ),
'hideOwn' => wikiFuzz::chooseInput( array("", "0", "1", wikiFuzz::makeFuzz(2)) ),
'hideBots' => wikiFuzz::chooseInput( array("", "0", "1", wikiFuzz::makeFuzz(2)) ),
'namespace'=> wikiFuzz::chooseInput( array("", "0", "1", wikiFuzz::makeFuzz(2)) ),
'action' => wikiFuzz::chooseInput( array("submit", "clear", wikiFuzz::makeFuzz(2)) ),
'id[]' => wikiFuzz::makeFuzz(2),
'edit' => wikiFuzz::makeFuzz(2),
'token' => wikiFuzz::chooseInput( array("", "1243213", wikiFuzz::makeFuzz(2)) )
);
// sometimes we specifiy "reset", and sometimes we don't.
if (wikiFuzz::randnum(3) == 0) $this->params["reset"] = wikiFuzz::chooseInput( array("", "0", "1", wikiFuzz::makeFuzz(2)) );
}
}
/**
** a page test for "Special:Blockme"
*/
class specialBlockmeTest extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special:Blockme";
$this->params = array ( );
// sometimes we specify "ip", and sometimes we don't.
if (wikiFuzz::randnum(1) == 0) {
$this->params["ip"] = wikiFuzz::chooseInput( array("10.12.41.213", wikiFuzz::randnum(-10,8134), wikiFuzz::makeFuzz(2)) );
}
}
}
/**
** a page test for "Special:Movepage"
*/
class specialMovePage extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special:Movepage";
$this->params = array (
"action" => wikiFuzz::chooseInput( array("success", "submit", "", wikiFuzz::makeFuzz(2)) ),
'wpEditToken' => wikiFuzz::chooseInput( array('', 0, 34987987, wikiFuzz::makeFuzz(2)) ),
'target' => wikiFuzz::chooseInput( array("x", wikiFuzz::makeTitleSafe(wikiFuzz::makeFuzz(2)) ) ),
'wpOldTitle' => wikiFuzz::chooseInput( array("z", wikiFuzz::makeTitleSafe(wikiFuzz::makeFuzz(2)), wikiFuzz::makeFuzz(2) ) ),
'wpNewTitle' => wikiFuzz::chooseInput( array("y", wikiFuzz::makeTitleSafe(wikiFuzz::makeFuzz(2)), wikiFuzz::makeFuzz(2) ) ),
'wpReason' => wikiFuzz::chooseInput( array(wikiFuzz::makeFuzz(2)) ),
'wpMovetalk' => wikiFuzz::chooseInput( array("0", "1", "++--34234", wikiFuzz::makeFuzz(2)) ),
'wpDeleteAndMove' => wikiFuzz::chooseInput( array("0", "1", "++--34234", wikiFuzz::makeFuzz(2)) ),
'wpConfirm' => wikiFuzz::chooseInput( array("0", "1", "++--34234", wikiFuzz::makeFuzz(2)) ),
'talkmoved' => wikiFuzz::chooseInput( array("1", wikiFuzz::makeFuzz(2), "articleexists", 'notalkpage') ),
'oldtitle' => wikiFuzz::makeFuzz(2),
'newtitle' => wikiFuzz::makeFuzz(2),
'wpMovetalk' => wikiFuzz::chooseInput( array("1", "0", wikiFuzz::makeFuzz(2)) )
);
// sometimes we don't want to specify certain parameters.
if (wikiFuzz::randnum(2) == 0) unset($this->params["wpEditToken"]);
if (wikiFuzz::randnum(3) == 0) unset($this->params["target"]);
if (wikiFuzz::randnum(3) == 0) unset($this->params["wpNewTitle"]);
if (wikiFuzz::randnum(4) == 0) unset($this->params["wpReason"]);
if (wikiFuzz::randnum(4) == 0) unset($this->params["wpOldTitle"]);
}
}
/**
** a page test for "Special:Undelete"
*/
class specialUndelete extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special:Undelete";
$this->params = array (
"action" => wikiFuzz::chooseInput( array("submit", "", wikiFuzz::makeFuzz(2)) ),
'wpEditToken' => wikiFuzz::chooseInput( array('', 0, 34987987, wikiFuzz::makeFuzz(2)) ),
'target' => wikiFuzz::chooseInput( array("x", wikiFuzz::makeTitleSafe(wikiFuzz::makeFuzz(2)) ) ),
'timestamp' => wikiFuzz::chooseInput( array("125223", wikiFuzz::makeFuzz(2) ) ),
'file' => wikiFuzz::chooseInput( array("0", "1", "++--34234", wikiFuzz::makeFuzz(2)) ),
'restore' => wikiFuzz::chooseInput( array("0", "1", wikiFuzz::makeFuzz(2)) ),
'preview' => wikiFuzz::chooseInput( array("0", "1", wikiFuzz::makeFuzz(2)) ),
'wpComment' => wikiFuzz::makeFuzz(2)
);
// sometimes we don't want to specify certain parameters.
if (wikiFuzz::randnum(2) == 0) unset($this->params["wpEditToken"]);
if (wikiFuzz::randnum(4) == 0) unset($this->params["target"]);
if (wikiFuzz::randnum(1) == 0) unset($this->params["restore"]);
if (wikiFuzz::randnum(1) == 0) unset($this->params["preview"]);
}
}
/**
** a page test for "Special:Unlockdb"
*/
class specialUnlockdb extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special:Unlockdb";
$this->params = array (
"action" => wikiFuzz::chooseInput( array("submit", "success", "", wikiFuzz::makeFuzz(2)) ),
'wpEditToken' => wikiFuzz::chooseInput( array("20398702394", "", wikiFuzz::makeFuzz(2)) ),
'wpLockConfirm' => wikiFuzz::chooseInput( array("0", "1", wikiFuzz::makeFuzz(2)) )
);
// sometimes we don't want to specify certain parameters.
if (wikiFuzz::randnum(4) == 0) unset($this->params["wpEditToken"]);
if (wikiFuzz::randnum(4) == 0) unset($this->params["action"]);
if (wikiFuzz::randnum(4) == 0) unset($this->params["wpLockConfirm"]);
}
}
/**
** a page test for "Special:Lockdb"
*/
class specialLockdb extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special:Lockdb";
$this->params = array (
"action" => wikiFuzz::chooseInput( array("submit", "success", "", wikiFuzz::makeFuzz(2)) ),
'wpEditToken' => wikiFuzz::chooseInput( array("20398702394", "", wikiFuzz::makeFuzz(2)) ),
'wpLockReason' => wikiFuzz::makeFuzz(2),
'wpLockConfirm'=> wikiFuzz::chooseInput( array("0", "1", "++--34234", wikiFuzz::makeFuzz(2)) )
);
// sometimes we don't want to specify certain parameters.
if (wikiFuzz::randnum(4) == 0) unset($this->params["wpEditToken"]);
if (wikiFuzz::randnum(4) == 0) unset($this->params["action"]);
if (wikiFuzz::randnum(4) == 0) unset($this->params["wpLockConfirm"]);
}
}
/**
** a page test for "Special:Userrights"
*/
class specialUserrights extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special:Userrights";
$this->params = array (
'wpEditToken' => wikiFuzz::chooseInput( array("20398702394", "", wikiFuzz::makeFuzz(2)) ),
'user-editname' => wikiFuzz::chooseInput( array("Nickj2", "Nickj2\n", wikiFuzz::makeFuzz(2)) ),
'ssearchuser' => wikiFuzz::chooseInput( array("0", "1", "++--34234", wikiFuzz::makeFuzz(2)) ),
'saveusergroups'=> wikiFuzz::chooseInput( array("0", "1", "++--34234", wikiFuzz::makeFuzz(2)), "Save User Groups"),
'member[]' => wikiFuzz::chooseInput( array("0", "bot", "1", "++--34234", wikiFuzz::makeFuzz(2)) ),
"available[]" => wikiFuzz::chooseInput( array("0", "sysop", "bureaucrat", "1", "++--34234", wikiFuzz::makeFuzz(2)) )
);
// sometimes we don't want to specify certain parameters.
if (wikiFuzz::randnum(3) == 0) unset($this->params['ssearchuser']);
if (wikiFuzz::randnum(3) == 0) unset($this->params['saveusergroups']);
}
}
/**
** a test for page protection and unprotection.
*/
class pageProtectionForm extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Main_Page";
$this->params = array (
"action" => "protect",
'wpEditToken' => wikiFuzz::chooseInput( array("20398702394", "", wikiFuzz::makeFuzz(2)) ),
"mwProtect-level-edit" => wikiFuzz::chooseInput( array('', 'autoconfirmed', 'sysop', wikifuzz::makeFuzz(2)) ),
"mwProtect-level-move" => wikiFuzz::chooseInput( array('', 'autoconfirmed', 'sysop', wikifuzz::makeFuzz(2)) ),
"mwProtectUnchained" => wikiFuzz::chooseInput( array("0", "1", "++--34234", wikiFuzz::makeFuzz(2)) ),
'mwProtect-reason' => wikiFuzz::chooseInput( array("because it was there", wikifuzz::makeFuzz(2)) )
);
// sometimes we don't want to specify certain parameters.
if (wikiFuzz::randnum(3) == 0) unset($this->params["mwProtectUnchained"]);
if (wikiFuzz::randnum(3) == 0) unset($this->params['mwProtect-reason']);
}
}
/**
** a page test for "Special:Blockip".
*/
class specialBlockip extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special:Blockip";
$this->params = array (
"action" => wikiFuzz::chooseInput( array("submit", "", wikiFuzz::makeFuzz(2)) ),
'wpEditToken' => wikiFuzz::chooseInput( array("20398702394", "", wikiFuzz::makeFuzz(2)) ),
"wpBlockAddress" => wikiFuzz::chooseInput( array("20398702394", "", "Nickj2", wikiFuzz::makeFuzz(2),
// something like an IP address, sometimes invalid:
( wikiFuzz::randnum(300,-20) . "." . wikiFuzz::randnum(300,-20) . "."
. wikiFuzz::randnum(300,-20) . "." .wikiFuzz::randnum(300,-20) ) ) ),
"ip" => wikiFuzz::chooseInput( array("20398702394", "", "Nickj2", wikiFuzz::makeFuzz(2),
// something like an IP address, sometimes invalid:
( wikiFuzz::randnum(300,-20) . "." . wikiFuzz::randnum(300,-20) . "."
. wikiFuzz::randnum(300,-20) . "." .wikiFuzz::randnum(300,-20) ) ) ),
"wpBlockOther" => wikiFuzz::chooseInput( array('', 'Nickj2', wikifuzz::makeFuzz(2)) ),
"wpBlockExpiry" => wikiFuzz::chooseInput( array("other", "2 hours", "1 day", "3 days", "1 week", "2 weeks",
"1 month", "3 months", "6 months", "1 year", "infinite", wikiFuzz::makeFuzz(2)) ),
"wpBlockReason" => wikiFuzz::chooseInput( array("because it was there", wikifuzz::makeFuzz(2)) ),
"wpAnonOnly" => wikiFuzz::chooseInput( array("0", "1", "++--34234", wikiFuzz::makeFuzz(2)) ),
"wpCreateAccount" => wikiFuzz::chooseInput( array("0", "1", "++--34234", wikiFuzz::makeFuzz(2)) ),
"wpBlock" => wikiFuzz::chooseInput( array("0", "1", "++--34234", wikiFuzz::makeFuzz(2)) )
);
// sometimes we don't want to specify certain parameters.
if (wikiFuzz::randnum(4) == 0) unset($this->params["wpBlockOther"]);
if (wikiFuzz::randnum(4) == 0) unset($this->params["wpBlockExpiry"]);
if (wikiFuzz::randnum(4) == 0) unset($this->params["wpBlockReason"]);
if (wikiFuzz::randnum(4) == 0) unset($this->params["wpAnonOnly"]);
if (wikiFuzz::randnum(4) == 0) unset($this->params["wpCreateAccount"]);
if (wikiFuzz::randnum(4) == 0) unset($this->params["wpBlockAddress"]);
if (wikiFuzz::randnum(4) == 0) unset($this->params["ip"]);
}
}
/**
** a test for the imagepage.
*/
class imagepageTest extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Image:Small-email.png";
$this->params = array (
"image" => wikiFuzz::chooseInput( array("Small-email.png", wikifuzz::makeFuzz(2)) ),
"wpReason" => wikifuzz::makeFuzz(2),
"oldimage" => wikiFuzz::chooseInput( array("Small-email.png", wikifuzz::makeFuzz(2)) ),
"wpEditToken" => wikiFuzz::chooseInput( array("20398702394", "", wikiFuzz::makeFuzz(2)) ),
);
// sometimes we don't want to specify certain parameters.
if (wikiFuzz::randnum(6) == 0) unset($this->params["image"]);
if (wikiFuzz::randnum(6) == 0) unset($this->params["wpReason"]);
if (wikiFuzz::randnum(6) == 0) unset($this->params["oldimage"]);
if (wikiFuzz::randnum(6) == 0) unset($this->params["wpEditToken"]);
}
}
/**
** a test for page deletion form.
*/
class pageDeletion extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Main_Page&action=delete";
$this->params = array (
"wpEditToken" => wikiFuzz::chooseInput( array("20398702394", "", wikiFuzz::makeFuzz(2)) ),
"wpReason" => wikiFuzz::chooseInput( array("0", "1", "++--34234", wikiFuzz::makeFuzz(2)) ),
"wpConfirm" => wikiFuzz::chooseInput( array("0", "1", "++--34234", wikiFuzz::makeFuzz(2)) ),
);
// sometimes we don't want to specify certain parameters.
if (wikiFuzz::randnum(5) == 0) unset($this->params["wpReason"]);
if (wikiFuzz::randnum(5) == 0) unset($this->params["wpEditToken"]);
if (wikiFuzz::randnum(5) == 0) unset($this->params["wpConfirm"]);
}
}
/**
** a test for Revision Deletion.
*/
class specialRevisionDelete extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special:Revisiondelete";
$this->params = array (
"target" => wikiFuzz::chooseInput( array("Main Page", wikifuzz::makeFuzz(2)) ),
"oldid" => wikifuzz::makeFuzz(2),
"oldid[]" => wikifuzz::makeFuzz(2),
"wpReason" => wikiFuzz::chooseInput( array("0", "1", "++--34234", wikiFuzz::makeFuzz(2)) ),
"revdelete-hide-text" => wikiFuzz::chooseInput( array("0", "1", "++--34234", wikiFuzz::makeFuzz(2)) ),
"revdelete-hide-comment" => wikiFuzz::chooseInput( array("0", "1", "++--34234", wikiFuzz::makeFuzz(2)) ),
"revdelete-hide-user" => wikiFuzz::chooseInput( array("0", "1", "++--34234", wikiFuzz::makeFuzz(2)) ),
"revdelete-hide-restricted" => wikiFuzz::chooseInput( array("0", "1", "++--34234", wikiFuzz::makeFuzz(2)) ),
);
// sometimes we don't want to specify certain parameters.
if (wikiFuzz::randnum(3) == 0) unset($this->params["target"]);
if (wikiFuzz::randnum(6) == 0) unset($this->params["oldid"]);
if (wikiFuzz::randnum(6) == 0) unset($this->params["oldid[]"]);
if (wikiFuzz::randnum(6) == 0) unset($this->params["wpReason"]);
if (wikiFuzz::randnum(6) == 0) unset($this->params["revdelete-hide-text"]);
if (wikiFuzz::randnum(6) == 0) unset($this->params["revdelete-hide-comment"]);
if (wikiFuzz::randnum(6) == 0) unset($this->params["revdelete-hide-user"]);
if (wikiFuzz::randnum(6) == 0) unset($this->params["revdelete-hide-restricted"]);
}
}
/**
** a test for Special:Import.
*/
class specialImport extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special:Import";
$this->params = array (
"action" => "submit",
"source" => wikiFuzz::chooseInput( array("upload", "interwiki", wikifuzz::makeFuzz(2)) ),
"MAX_FILE_SIZE" => wikiFuzz::chooseInput( array("0", "1", "++--34234", wikifuzz::makeFuzz(2)) ),
"xmlimport" => wikiFuzz::chooseInput( array("/var/www/hosts/mediawiki/wiki/AdminSettings.php", "1", "++--34234", wikiFuzz::makeFuzz(2)) ),
"namespace" => wikiFuzz::chooseInput( array(wikiFuzz::randnum(30,-6), wikiFuzz::makeFuzz(2)) ),
"interwiki" => wikiFuzz::makeFuzz(2),
"interwikiHistory" => wikiFuzz::makeFuzz(2),
"frompage" => wikiFuzz::makeFuzz(2),
);
// sometimes we don't want to specify certain parameters.
if (wikiFuzz::randnum(6) == 0) unset($this->params["action"]);
if (wikiFuzz::randnum(6) == 0) unset($this->params["source"]);
if (wikiFuzz::randnum(6) == 0) unset($this->params["MAX_FILE_SIZE"]);
if (wikiFuzz::randnum(6) == 0) unset($this->params["xmlimport"]);
if (wikiFuzz::randnum(6) == 0) unset($this->params["interwiki"]);
if (wikiFuzz::randnum(6) == 0) unset($this->params["interwikiHistory"]);
if (wikiFuzz::randnum(6) == 0) unset($this->params["frompage"]);
// Note: Need to do a file upload to fully test this Special page.
}
}
/**
** a test for thumb.php
*/
class thumbTest extends pageTest {
function __construct() {
$this->pagePath = "thumb.php";
$this->params = array (
"f" => wikiFuzz::chooseInput( array("..", "\\", "small-email.png", wikifuzz::makeFuzz(2)) ),
"w" => wikiFuzz::chooseInput( array("80", wikiFuzz::randnum(6000,-200), wikifuzz::makeFuzz(2)) ),
"r" => wikiFuzz::chooseInput( array("0", wikifuzz::makeFuzz(2)) ),
);
// sometimes we don't want to specify certain parameters.
if (wikiFuzz::randnum(6) == 0) unset($this->params["f"]);
if (wikiFuzz::randnum(6) == 0) unset($this->params["w"]);
if (wikiFuzz::randnum(6) == 0) unset($this->params["r"]);
}
}
/**
** a test for trackback.php
*/
class trackbackTest extends pageTest {
function __construct() {
$this->pagePath = "trackback.php";
$this->params = array (
"url" => wikifuzz::makeFuzz(2),
"blog_name" => wikiFuzz::chooseInput( array("80", wikiFuzz::randnum(6000,-200), wikifuzz::makeFuzz(2)) ),
"article" => wikiFuzz::chooseInput( array("Main Page", wikifuzz::makeFuzz(2)) ),
"title" => wikiFuzz::chooseInput( array("Main Page", wikifuzz::makeFuzz(2)) ),
"excerpt" => wikifuzz::makeFuzz(2),
);
// sometimes we don't want to specify certain parameters.
if (wikiFuzz::randnum(3) == 0) unset($this->params["title"]);
if (wikiFuzz::randnum(3) == 0) unset($this->params["excerpt"]);
// page does not produce HTML.
$this->tidyValidate = false;
}
}
/**
** a test for profileinfo.php
*/
class profileInfo extends pageTest {
function __construct() {
$this->pagePath = "profileinfo.php";
$this->params = array (
"expand" => wikifuzz::makeFuzz(2),
"sort" => wikiFuzz::chooseInput( array("time", "count", "name", wikifuzz::makeFuzz(2)) ),
"filter" => wikiFuzz::chooseInput( array("Main Page", wikifuzz::makeFuzz(2)) ),
);
// sometimes we don't want to specify certain parameters.
if (wikiFuzz::randnum(3) == 0) unset($this->params["sort"]);
if (wikiFuzz::randnum(3) == 0) unset($this->params["filter"]);
}
}
/**
** a test for Special:Cite (extension Special page).
*/
class specialCite extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special:Cite";
$this->params = array (
"page" => wikiFuzz::chooseInput( array("\" onmouseover=\"alert(1);\"", "Main Page", wikifuzz::makeFuzz(2)) ),
"id" => wikiFuzz::chooseInput( array("-1", "0", "------'-------0", "+1", "-9823412312312412435", wikiFuzz::makeFuzz(2)) ),
);
// sometimes we don't want to specify certain parameters.
if (wikiFuzz::randnum(6) == 0) unset($this->params["page"]);
if (wikiFuzz::randnum(6) == 0) unset($this->params["id"]);
}
}
/**
** a test for Special:Filepath (extension Special page).
*/
class specialFilepath extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special:Filepath";
$this->params = array (
"file" => wikiFuzz::chooseInput( array("Small-email.png", "Small-email.png" . wikifuzz::makeFuzz(1), wikiFuzz::makeFuzz(2)) ),
);
}
}
/**
** a test for Special:Makebot (extension Special page).
*/
class specialMakebot extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special:Makebot";
$this->params = array (
"username" => wikiFuzz::chooseInput( array("Nickj2", "192.168.0.2", wikifuzz::makeFuzz(1) ) ),
"dosearch" => wikiFuzz::chooseInput( array("0", "1", "++--34234", wikifuzz::makeFuzz(2)) ),
"grant" => wikiFuzz::chooseInput( array("0", "1", "++--34234", wikifuzz::makeFuzz(2)) ),
"comment" => wikiFuzz::chooseInput( array("20398702394", "", wikiFuzz::makeFuzz(2)) ),
"token" => wikiFuzz::chooseInput( array("20398702394", "", wikiFuzz::makeFuzz(2)) ),
);
// sometimes we don't want to specify certain parameters.
if (wikiFuzz::randnum(2) == 0) unset($this->params["dosearch"]);
if (wikiFuzz::randnum(2) == 0) unset($this->params["grant"]);
if (wikiFuzz::randnum(5) == 0) unset($this->params["token"]);
}
}
/**
** a test for Special:Makesysop (extension Special page).
*/
class specialMakesysop extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special:Makesysop";
$this->params = array (
"wpMakesysopUser" => wikiFuzz::chooseInput( array("Nickj2", "192.168.0.2", wikifuzz::makeFuzz(1) ) ),
"action" => wikiFuzz::chooseInput( array("0", "1", "++--34234", wikifuzz::makeFuzz(2)) ),
"wpMakesysopSubmit" => wikiFuzz::chooseInput( array("0", "1", "++--34234", wikifuzz::makeFuzz(2)) ),
"wpEditToken" => wikiFuzz::chooseInput( array("20398702394", "", wikiFuzz::makeFuzz(2)) ),
"wpSetBureaucrat" => wikiFuzz::chooseInput( array("20398702394", "", wikiFuzz::makeFuzz(2)) ),
);
// sometimes we don't want to specify certain parameters.
if (wikiFuzz::randnum(3) == 0) unset($this->params["wpMakesysopSubmit"]);
if (wikiFuzz::randnum(3) == 0) unset($this->params["wpEditToken"]);
if (wikiFuzz::randnum(3) == 0) unset($this->params["wpSetBureaucrat"]);
}
}
/**
** a test for Special:Renameuser (extension Special page).
*/
class specialRenameuser extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special:Renameuser";
$this->params = array (
"oldusername" => wikiFuzz::chooseInput( array("Nickj2", "192.168.0.2", wikifuzz::makeFuzz(1) ) ),
"newusername" => wikiFuzz::chooseInput( array("Nickj2", "192.168.0.2", wikifuzz::makeFuzz(1) ) ),
"token" => wikiFuzz::chooseInput( array("20398702394", "", wikiFuzz::makeFuzz(2)) ),
);
}
}
/**
** a test for Special:Linksearch (extension Special page).
*/
class specialLinksearch extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special%3ALinksearch";
$this->params = array (
"target" => wikifuzz::makeFuzz(2),
);
// sometimes we don't want to specify certain parameters.
if (wikiFuzz::randnum(10) == 0) unset($this->params["target"]);
}
}
/**
** a test for Special:CategoryTree (extension Special page).
*/
class specialCategoryTree extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special:CategoryTree";
$this->params = array (
"target" => wikifuzz::makeFuzz(2),
"from" => wikifuzz::makeFuzz(2),
"until" => wikifuzz::makeFuzz(2),
"showas" => wikifuzz::makeFuzz(2),
"mode" => wikiFuzz::chooseInput( array("pages", "categories", "all", wikifuzz::makeFuzz(2)) ),
);
// sometimes we do want to specify certain parameters.
if (wikiFuzz::randnum(5) == 0) $this->params["notree"] = wikiFuzz::chooseInput( array("1", 0, "", wikiFuzz::makeFuzz(2)) );
}
}
/**
** a test for "Special:Chemicalsources" (extension Special page).
*/
class specialChemicalsourcesTest extends pageTest {
function __construct() {
$this->pagePath = "index.php?title=Special:Chemicalsources";
// choose an input format to use.
$format = wikiFuzz::chooseInput(
array( 'go',
'CAS',
'EINECS',
'CHEBI',
'PubChem',
'SMILES',
'InChI',
'ATCCode',
'KEGG',
'RTECS',
'ECNumber',
'DrugBank',
'Formula',
'Name'
)
);
// values for different formats usually start with either letters or numbers.
switch ($format) {
case 'Name' : $value = "A"; break;
case 'InChI' :
case 'SMILES' :
case 'Formula': $value = "C"; break;
default : $value = "0"; break;
}
// and then we append the fuzz input.
$this->params = array ($format => $value . wikifuzz::makeFuzz(2) );
}
}
/**
** A test for api.php (programmatic interface to MediaWiki in XML/JSON/RSS/etc formats).
** Quite involved to test because there are lots of options/parameters, and because
** for a lot of the functionality if all the parameters don't make sense then it just
** returns the help screen - so currently a lot of the tests aren't actually doing much
** because something wasn't right in the query.
**
** @todo: Incomplete / unfinished; Runs too fast (suggests not much testing going on).
*/
class api extends pageTest {
// API login mode.
private static function loginMode() {
$arr = array ( "lgname" => wikifuzz::makeFuzz(2),
"lgpassword" => wikifuzz::makeFuzz(2),
);
// sometimes we want to specify the extra "lgdomain" parameter.
if (wikiFuzz::randnum(3) == 0) {
$arr["lgdomain"] = wikiFuzz::chooseInput( array("1", 0, "", wikiFuzz::makeFuzz(2)) );
}
return $arr;
}
// API OpenSearch mode.
private static function opensearchMode() {
return array ("search" => wikifuzz::makeFuzz(2));
}
// API watchlist feed mode.
private static function feedwatchlistMode() {
// FIXME: add "wikifuzz::makeFuzz(2)" as possible value below?
return array ("feedformat" => wikiFuzz::chooseInput( array("rss", "atom") ) );
}
// API query mode.
private static function queryMode() {
// FIXME: add "wikifuzz::makeFuzz(2)" as possible params for the elements below?
// Suspect this will stuff up the tests more, but need to check.
$params = array (
// FIXME: More titles.
"titles" => wikiFuzz::chooseInput( array("Main Page")),
// FIXME: More pageids.
"pageids" => 1,
"prop" => wikiFuzz::chooseInput( array("info", "revisions", "watchlist")),
"list" => wikiFuzz::chooseInput( array("allpages", "logevents", "watchlist", "usercontribs", "recentchanges", "backlinks", "embeddedin", "imagelinks") ),
"meta" => wikiFuzz::chooseInput( array("siteinfo")),
"generator" => wikiFuzz::chooseInput( array("allpages", "logevents", "watchlist", "info", "revisions") ),
"siprop" => wikiFuzz::chooseInput( array("general", "namespaces", "general|namespaces") ),
);
// Add extra parameters based on what list choice we got.
switch ($params["list"]) {
case "usercontribs" : self::addListParams ($params, "uc", array("limit", "start", "end", "user", "dir") ); break;
case "allpages" : self::addListParams ($params, "ap", array("from", "prefix", "namespace", "filterredir", "limit") ); break;
case "watchlist" : self::addListParams ($params, "wl", array("allrev", "start", "end", "namespace", "dir", "limit", "prop") ); break;
case "logevents" : self::addListParams ($params, "le", array("limit", "type", "start", "end", "user", "dir") ); break;
case "recentchanges": self::addListParams ($params, "rc", array("limit", "prop", "show", "namespace", "start", "end", "dir") ); break;
case "backlinks" : self::addListParams ($params, "bl", array("continue", "namespace", "redirect", "limit") ); break;
case "embeddedin" : self::addListParams ($params, "ei", array("continue", "namespace", "redirect", "limit") ); break;
case "imagelinks" : self::addListParams ($params, "il", array("continue", "namespace", "redirect", "limit") ); break;
}
if ($params["prop"] == "revisions") {
self::addListParams ($params, "rv", array("prop", "limit", "startid", "endid", "end", "dir") );
}
// Sometimes we want redirects, sometimes we don't.
if (wikiFuzz::randnum(3) == 0) {
$params["redirects"] = wikiFuzz::chooseInput( array("1", 0, "", wikiFuzz::makeFuzz(2)) );
}
return $params;
}
// Adds all the elements to the array, using the specified prefix.
private static function addListParams(&$array, $prefix, $elements) {
foreach ($elements as $element) {
$array[$prefix . $element] = self::getParamDetails($element);
}
}
// For a given element name, returns the data for that element.
private static function getParamDetails($element) {
switch ($element) {
case 'startid' :
case 'endid' :
case 'start' :
case 'end' :
case 'limit' : return wikiFuzz::chooseInput( array("0", "-1", "---'----------0", "+1", "8134", "320742734234235", "20060230121212", wikiFuzz::randnum(9000, -100), wikiFuzz::makeFuzz(2)) );
case 'dir' : return wikiFuzz::chooseInput( array("newer", "older", wikifuzz::makeFuzz(2) ) );
case 'user' : return wikiFuzz::chooseInput( array(USER_ON_WIKI, wikifuzz::makeFuzz(2) ) );
case 'namespace' : return wikiFuzz::chooseInput( array(-2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 200000, wikifuzz::makeFuzz(2)) );
case 'filterredir': return wikiFuzz::chooseInput( array("all", "redirects", "nonredirectsallpages", wikifuzz::makeFuzz(2)) );
case 'allrev' : return wikiFuzz::chooseInput( array("1", 0, "", wikiFuzz::makeFuzz(2)) );
case 'prop' : return wikiFuzz::chooseInput( array("user", "comment", "timestamp", "patrol", "flags", "user|user|comment|flags", wikifuzz::makeFuzz(2) ) );
case 'type' : return wikiFuzz::chooseInput( array("block", "protect", "rights", "delete", "upload", "move", "import", "renameuser", "newusers", "makebot", wikifuzz::makeFuzz(2) ) );
case 'hide' : return wikiFuzz::chooseInput( array("minor", "bots", "anons", "liu", "liu|bots|", wikifuzz::makeFuzz(2) ) );
case 'show' : return wikiFuzz::chooseInput( array('minor', '!minor', 'bot', '!bot', 'anon', '!anon', wikifuzz::makeFuzz(2) ) );
default : return wikifuzz::makeFuzz(2);
}
}
// Entry point.
function __construct() {
$this->pagePath = "api.php";
$modes = array ("help",
"login",
"opensearch",
"feedwatchlist",
"query");
$action = wikiFuzz::chooseInput( array_merge ($modes, array(wikifuzz::makeFuzz(2))) );
switch ($action) {
case "login" : $this->params = self::loginMode();
break;
case "opensearch" : $this->params = self::opensearchMode();
break;
case "feedwatchlist" : $this->params = self::feedwatchlistMode();
break;
case "query" : $this->params = self::queryMode();
break;
case "help" :
default : // Do something random - "Crazy Ivan" mode.
$random_mode = wikiFuzz::chooseInput( $modes ) . "Mode";
// There is no "helpMode".
if ($random_mode == "helpMode") $random_mode = "queryMode";
$this->params = self::$random_mode();
break;
}
// Save the selected action.
$this->params["action"] = $action;
// Set the cookie:
// FIXME: need to get this cookie dynamically set, rather than hard-coded.
$this->cookie = "wikidbUserID=10001; wikidbUserName=Test; wikidb_session=178df0fe68c75834643af65dec9ec98a; wikidbToken=1adc6753d62c44aec950c024d7ae0540";
// Output format
$this->params["format"] = wikiFuzz::chooseInput( array("json", "jsonfm", "php", "phpfm",
"wddx", "wddxfm", "xml", "xmlfm",
"yaml", "yamlfm", "raw", "rawfm",
wikifuzz::makeFuzz(2) ) );
// Page does not produce HTML (sometimes).
$this->tidyValidate = false;
}
}
/**
** a page test for the GeSHi extension.
*/
class GeSHi_Test extends pageTest {
private function getGeSHiContent() {
return "";
}
private function getLang() {
return wikiFuzz::chooseInput( array( "actionscript", "ada", "apache", "applescript", "asm", "asp", "autoit", "bash", "blitzbasic", "bnf", "c", "c_mac", "caddcl", "cadlisp",
"cfdg", "cfm", "cpp", "cpp-qt", "csharp", "css", "d", "delphi", "diff", "div", "dos", "eiffel", "fortran", "freebasic", "gml", "groovy", "html4strict", "idl",
"ini", "inno", "io", "java", "java5", "javascript", "latex", "lisp", "lua", "matlab", "mirc", "mpasm", "mysql", "nsis", "objc", "ocaml", "ocaml-brief", "oobas",
"oracle8", "pascal", "perl", "php", "php-brief", "plsql", "python", "qbasic", "rails", "reg", "robots", "ruby", "sas", "scheme", "sdlbasic", "smalltalk", "smarty",
"sql", "tcl", "text", "thinbasic", "tsql", "vb", "vbnet", "vhdl", "visualfoxpro", "winbatch", "xml", "xpp", "z80", wikifuzz::makeFuzz(1) ) );
}
function __construct() {
$this->pagePath = "index.php?title=WIKIFUZZ";
$this->params = array (
"action" => "submit",
"wpMinoredit" => "test",
"wpPreview" => "test",
"wpSection" => "test",
"wpEdittime" => "test",
"wpSummary" => "test",
"wpScrolltop" => "test",
"wpStarttime" => "test",
"wpAutoSummary" => "test",
"wpTextbox1" => $this->getGeSHiContent() // the main wiki text, contains fake GeSHi content.
);
}
}
/**
** selects a page test to run.
*/
function selectPageTest($count) {
// if the user only wants a specific test, then only ever give them that.
if (defined("SPECIFIC_TEST")) {
$testType = SPECIFIC_TEST;
return new $testType ();
}
// Some of the time we test Special pages, the remaining
// time we test using the standard edit page.
switch ($count % 100) {
case 0 : return new successfulUserLoginTest();
case 1 : return new listusersTest();
case 2 : return new searchTest();
case 3 : return new recentchangesTest();
case 4 : return new prefixindexTest();
case 5 : return new mimeSearchTest();
case 6 : return new specialLogTest();
case 7 : return new userLoginTest();
case 8 : return new ipblocklistTest();
case 9 : return new newImagesTest();
case 10: return new imagelistTest();
case 11: return new specialExportTest();
case 12: return new specialBooksourcesTest();
case 13: return new specialAllpagesTest();
case 14: return new pageHistoryTest();
case 15: return new contributionsTest();
case 16: return new viewPageTest();
case 17: return new specialAllmessagesTest();
case 18: return new specialNewpages();
case 19: return new searchTest();
case 20: return new redirectTest();
case 21: return new confirmEmail();
case 22: return new watchlistTest();
case 23: return new specialBlockmeTest();
case 24: return new specialUndelete();
case 25: return new specialMovePage();
case 26: return new specialUnlockdb();
case 27: return new specialLockdb();
case 28: return new specialUserrights();
case 29: return new pageProtectionForm();
case 30: return new specialBlockip();
case 31: return new imagepageTest();
case 32: return new pageDeletion();
case 33: return new specialRevisionDelete();
case 34: return new specialImport();
case 35: return new thumbTest();
case 36: return new trackbackTest();
case 37: return new profileInfo();
case 38: return new specialCite();
case 39: return new specialFilepath();
case 40: return new specialMakebot();
case 41: return new specialMakesysop();
case 42: return new specialRenameuser();
case 43: return new specialLinksearch();
case 44: return new specialCategoryTree();
case 45: return new api();
case 45: return new specialChemicalsourcesTest();
default: return new editPageTest();
}
}
/////////////////////// SAVING OUTPUT /////////////////////////
/**
** Utility function for saving a file. Currently has no error checking.
*/
function saveFile($data, $name) {
file_put_contents($name, $data);
}
/**
** Returns a test as an experimental GET-to-POST URL.
** This doesn't seem to always work though, and sometimes the output is too long
** to be a valid GET URL, so we also save in other formats.
*/
function getAsURL(pageTest $test) {
$used_question_mark = (strpos($test->getPagePath(), "?") !== false);
$retval = "http://get-to-post.nickj.org/?" . WIKI_BASE_URL . $test->getPagePath();
foreach ($test->getParams() as $param => $value) {
if (!$used_question_mark) {
$retval .= "?";
$used_question_mark = true;
}
else {
$retval .= "&";
}
$retval .= $param . "=" . urlencode($value);
}
return $retval;
}
/**
** Saves a plain-text human-readable version of a test.
*/
function saveTestAsText(pageTest $test, $filename) {
$str = "Test: " . $test->getPagePath();
foreach ($test->getParams() as $param => $value) {
$str .= "\n$param: $value";
}
$str .= "\nGet-to-post URL: " . getAsURL($test) . "\n";
saveFile($str, $filename);
}
/**
** Saves a test as a standalone basic PHP script that shows this one problem.
** Resulting script requires PHP-Curl be installed in order to work.
*/
function saveTestAsPHP(pageTest $test, $filename) {
$str = "getParams()), true) . ";\n"
. "\$ch = curl_init();\n"
. "curl_setopt(\$ch, CURLOPT_POST, 1);\n"
. "curl_setopt(\$ch, CURLOPT_POSTFIELDS, \$params );\n"
. "curl_setopt(\$ch, CURLOPT_URL, " . var_export(WIKI_BASE_URL . $test->getPagePath(), true) . ");\n"
. "curl_setopt(\$ch, CURLOPT_RETURNTRANSFER,1);\n"
. ($test->getCookie() ? "curl_setopt(\$ch, CURLOPT_COOKIE, " . var_export($test->getCookie(), true) . ");\n" : "")
. "\$result=curl_exec(\$ch);\n"
. "curl_close (\$ch);\n"
. "print \$result;\n"
. "?>\n";
saveFile($str, $filename);
}
/**
** Escapes a value so that it can be used on the command line by Curl.
** Specifically, "<" and "@" need to be escaped if they are the first character,
** otherwise curl interprets these as meaning that we want to insert a file.
*/
function escapeForCurl(array $input_params) {
$output_params = array();
foreach ($input_params as $param => $value) {
if (strlen($value) > 0 && ( $value[0] == "@" || $value[0] == "<")) {
$value = "\\" . $value;
}
$output_params[$param] = $value;
}
return $output_params;
}
/**
** Saves a test as a standalone CURL shell script that shows this one problem.
** Resulting script requires standalone Curl be installed in order to work.
*/
function saveTestAsCurl(pageTest $test, $filename) {
$str = "#!/bin/bash\n"
. "curl --silent --include --globoff \\\n"
. ($test->getCookie() ? " --cookie " . escapeshellarg($test->getCookie()) . " \\\n" : "");
foreach (escapeForCurl($test->getParams()) as $param => $value) {
$str .= " -F " . escapeshellarg($param) . "=" . escapeshellarg($value) . " \\\n";
}
$str .= " " . escapeshellarg(WIKI_BASE_URL . $test->getPagePath()); // beginning space matters.
$str .= "\n";
saveFile($str, $filename);
chmod($filename, 0755); // make executable
}
/**
** Saves the internal data structure to file.
*/
function saveTestData (pageTest $test, $filename) {
saveFile(serialize($test), $filename);
}
/**
** saves a test in the various formats.
*/
function saveTest(pageTest $test, $testname) {
$base_name = DIRECTORY . "/" . $testname;
saveTestAsText($test, $base_name . INFO_FILE);
saveTestAsPHP ($test, $base_name . PHP_TEST );
saveTestAsCurl($test, $base_name . CURL_TEST);
saveTestData ($test, $base_name . DATA_FILE);
}
//////////////////// MEDIAWIKI OUTPUT /////////////////////////
/**
** Asks MediaWiki for the HTML output of a test.
*/
function wikiTestOutput(pageTest $test) {
$ch = curl_init();
// specify the cookie, if required.
if ($test->getCookie()) curl_setopt($ch, CURLOPT_COOKIE, $test->getCookie());
curl_setopt($ch, CURLOPT_POST, 1); // save form using a POST
$params = escapeForCurl($test->getParams());
curl_setopt($ch, CURLOPT_POSTFIELDS, $params ); // load the POST variables
curl_setopt($ch, CURLOPT_URL, WIKI_BASE_URL . $test->getPagePath() ); // set url to post to
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); // return into a variable
$result=curl_exec ($ch);
// if we encountered an error, then say so, and return an empty string.
if (curl_error($ch)) {
print "\nCurl error #: " . curl_errno($ch) . " - " . curl_error ($ch);
$result = "";
}
curl_close ($ch);
return $result;
}
//////////////////// HTML VALIDATION /////////////////////////
/*
** Asks the validator whether this is valid HTML, or not.
*/
function validateHTML($text) {
$params = array ("fragment" => $text);
$ch = curl_init();
curl_setopt($ch, CURLOPT_POST, 1); // save form using a POST
curl_setopt($ch, CURLOPT_POSTFIELDS, $params); // load the POST variables
curl_setopt($ch, CURLOPT_URL, VALIDATOR_URL); // set url to post to
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); // return into a variable
$result=curl_exec ($ch);
// if we encountered an error, then log it, and exit.
if (curl_error($ch)) {
trigger_error("Curl error #: " . curl_errno($ch) . " - " . curl_error ($ch) );
print "Curl error #: " . curl_errno($ch) . " - " . curl_error ($ch) . " - exiting.\n";
exit(1);
}
curl_close ($ch);
$valid = (strpos($result, "Failed validation") === false ? true : false);
return array($valid, $result);
}
/**
** Get tidy to check for no HTML errors in the output file (e.g. unescaped strings).
*/
function tidyCheckFile($name) {
$file = DIRECTORY . "/" . $name;
$command = PATH_TO_TIDY . " -output /tmp/out.html -quiet $file 2>&1";
$x = `$command`;
// Look for the most interesting Tidy errors and warnings.
if ( strpos($x,"end of file while parsing attributes") !== false
|| strpos($x,"attribute with missing trailing quote mark") !== false
|| strpos($x,"missing '>' for end of tag") !== false
|| strpos($x,"Error:") !== false) {
print "\nTidy found something - view details with: $command";
return false;
} else {
return true;
}
}
/**
** Returns whether or not an database error log file has changed in size since
** the last time this was run. This is used to tell if a test caused a DB error.
*/
function dbErrorLogged() {
static $filesize;
// first time running this function
if (!isset($filesize)) {
// create log if it does not exist
if (!file_exists(DB_ERROR_LOG_FILE)) {
saveFile("", DB_ERROR_LOG_FILE);
}
$filesize = filesize(DB_ERROR_LOG_FILE);
return false;
}
$newsize = filesize(DB_ERROR_LOG_FILE);
// if the log has grown, then assume the current test caused it.
if ($newsize != $filesize) {
$filesize = $newsize;
return true;
}
return false;
}
////////////////// TOP-LEVEL PROBLEM-FINDING FUNCTION ////////////////////////
/**
** takes a page test, and runs it and tests it for problems in the output.
** Returns: False on finding a problem, or True on no problems being found.
*/
function runWikiTest(pageTest $test, &$testname, $can_overwrite = false) {
// by default don't overwrite a previous test of the same name.
while ( ! $can_overwrite && file_exists(DIRECTORY . "/" . $testname . DATA_FILE)) {
$testname .= "-" . mt_rand(0,9);
}
$filename = DIRECTORY . "/" . $testname . DATA_FILE;
// Store the time before and after, to find slow pages.
$before = microtime(true);
// Get MediaWiki to give us the output of this test.
$wiki_preview = wikiTestOutput($test);
$after = microtime(true);
// if we received no response, then that's interesting.
if ($wiki_preview == "") {
print "\nNo response received for: $filename";
return false;
}
// save output HTML to file.
$html_file = DIRECTORY . "/" . $testname . HTML_FILE;
saveFile($wiki_preview, $html_file);
// if there were PHP errors in the output, then that's interesting too.
if ( strpos($wiki_preview, "Warning: " ) !== false
|| strpos($wiki_preview, "Fatal error: " ) !== false
|| strpos($wiki_preview, "Notice: " ) !== false
|| strpos($wiki_preview, "Error: " ) !== false
|| strpos($wiki_preview, "Strict Standards:") !== false
) {
$error = substr($wiki_preview, strpos($wiki_preview, ":") + 7, 50);
// Avoid probable PHP bug with bad session ids; http://bugs.php.net/bug.php?id=38224
if ($error != "Unknown: The session id contains illegal character") {
print "\nPHP error/warning/notice in HTML output: $html_file ; $error";
return false;
}
}
// if there was a MediaWiki Backtrace message in the output, then that's also interesting.
if( strpos($wiki_preview, "Backtrace:") !== false ) {
print "\nInternal MediaWiki error in HTML output: $html_file";
return false;
}
// if there was a Parser error comment in the output, then that's potentially interesting.
if( strpos($wiki_preview, "!-- ERR") !== false ) {
print "\nParser Error comment in HTML output: $html_file";
return false;
}
// if a database error was logged, then that's definitely interesting.
if( dbErrorLogged() ) {
print "\nDatabase Error logged for: $filename";
return false;
}
// validate result
$valid = true;
if( VALIDATE_ON_WEB ) {
list ($valid, $validator_output) = validateHTML($wiki_preview);
if (!$valid) print "\nW3C web validation failed - view details with: html2text " . DIRECTORY . "/" . $testname . ".validator_output.html";
}
// Get tidy to check the page, unless we already know it produces non-XHTML output.
if( $test->tidyValidate() ) {
$valid = tidyCheckFile( $testname . HTML_FILE ) && $valid;
}
// if it took more than 2 seconds to render, then it may be interesting too. (Possible DoS attack?)
if (($after - $before) >= 2) {
print "\nParticularly slow to render (" . round($after - $before, 2) . " seconds): $filename";
return false;
}
if( $valid ) {
// Remove temp HTML file if test was valid:
unlink( $html_file );
} elseif( VALIDATE_ON_WEB ) {
saveFile($validator_output, DIRECTORY . "/" . $testname . ".validator_output.html");
}
return $valid;
}
/////////////////// RERUNNING OLD TESTS ///////////////////
/**
** We keep our failed tests so that they can be rerun.
** This function does that retesting.
*/
function rerunPreviousTests() {
print "Retesting previously found problems.\n";
$dir_contents = scandir (DIRECTORY);
// sort file into the order a normal person would use.
natsort ($dir_contents);
foreach ($dir_contents as $file) {
// if file is not a test, then skip it.
// Note we need to escape any periods or will be treated as "any character".
$matches = array();
if (!ereg("(.*)" . str_replace(".", "\.", DATA_FILE) . "$", $file, $matches)) continue;
// reload the test.
$full_path = DIRECTORY . "/" . $file;
$test = unserialize(file_get_contents($full_path));
// if this is not a valid test, then skip it.
if (! $test instanceof pageTest) {
print "\nSkipping invalid test - $full_path";
continue;
}
// The date format is in Apache log format, which makes it easier to locate
// which retest caused which error in the Apache logs (only happens usually if
// apache segfaults).
if (!QUIET) print "[" . date ("D M d H:i:s Y") . "] Retesting $file (" . get_class($test) . ")";
// run test
$testname = $matches[1];
$valid = runWikiTest($test, $testname, true);
if (!$valid) {
saveTest($test, $testname);
if (QUIET) {
print "\nTest: " . get_class($test) . " ; Testname: $testname\n------";
} else {
print "\n";
}
}
else {
if (!QUIET) print "\r";
if (DELETE_PASSED_RETESTS) {
$prefix = DIRECTORY . "/" . $testname;
if (is_file($prefix . DATA_FILE)) unlink($prefix . DATA_FILE);
if (is_file($prefix . PHP_TEST )) unlink($prefix . PHP_TEST );
if (is_file($prefix . CURL_TEST)) unlink($prefix . CURL_TEST);
if (is_file($prefix . INFO_FILE)) unlink($prefix . INFO_FILE);
}
}
}
print "\nDone retesting.\n";
}
////////////////////// MAIN LOOP ////////////////////////
// first check whether CURL is installed, because sometimes it's not.
if( ! function_exists('curl_init') ) {
die("Could not find 'curl_init' function. Is the curl extension compiled into PHP?\n");
}
// Initialization of types. wikiFuzz doesn't have a constructor because we want to
// access it staticly and not have any globals.
wikiFuzz::$types = array_keys(wikiFuzz::$data);
// Make directory if doesn't exist
if (!is_dir(DIRECTORY)) {
mkdir (DIRECTORY, 0700 );
}
// otherwise, we first retest the things that we have found in previous runs
else if (RERUN_OLD_TESTS) {
rerunPreviousTests();
}
// main loop.
$start_time = date("U");
$num_errors = 0;
if (!QUIET) {
print "Beginning main loop. Results are stored in the " . DIRECTORY . " directory.\n";
print "Press CTRL+C to stop testing.\n";
}
for ($count=0; true; $count++) {
if (!QUIET) {
// spinning progress indicator.
switch( $count % 4 ) {
case '0': print "\r/"; break;
case '1': print "\r-"; break;
case '2': print "\r\\"; break;
case '3': print "\r|"; break;
}
print " $count";
}
// generate a page test to run.
$test = selectPageTest($count);
$mins = ( date("U") - $start_time ) / 60;
if (!QUIET && $mins > 0) {
print ". $num_errors poss errors. "
. floor($mins) . " mins. "
. round ($count / $mins, 0) . " tests/min. "
. get_class($test); // includes the current test name.
}
// run this test against MediaWiki, and see if the output was valid.
$testname = $count;
$valid = runWikiTest($test, $testname, false);
// save the failed test
if ( ! $valid ) {
if (QUIET) {
print "\nTest: " . get_class($test) . " ; Testname: $testname\n------";
} else {
print "\n";
}
saveTest($test, $testname);
$num_errors += 1;
} else if ( KEEP_PASSED_TESTS ) {
// print current time, with microseconds (matches "strace" format), and the test name.
print " " . date("H:i:s.") . substr(current(explode(" ", microtime())), 2) . " " . $testname;
saveTest($test, $testname);
}
// stop if we have reached max number of errors.
if (defined("MAX_ERRORS") && $num_errors>=MAX_ERRORS) {
break;
}
// stop if we have reached max number of mins runtime.
if (defined("MAX_RUNTIME") && $mins>=MAX_RUNTIME) {
break;
}
}