summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/.htaccess1
-rw-r--r--tests/.svnignore6
-rw-r--r--tests/ArticleTest.php150
-rw-r--r--tests/DatabaseTest.php93
-rw-r--r--tests/GlobalTest.php211
-rw-r--r--tests/ImageTest.php66
-rw-r--r--tests/LocalTestSettings.sample29
-rw-r--r--tests/Makefile15
-rw-r--r--tests/README8
-rw-r--r--tests/RunTests.php100
-rw-r--r--tests/SanitizerTest.php65
-rw-r--r--tests/SearchEngineTest.php136
-rw-r--r--tests/SearchMySQL4Test.php34
-rw-r--r--tests/test-prefetch-current.xml75
-rw-r--r--tests/test-prefetch-previous.xml57
-rw-r--r--tests/test-prefetch-stub.xml75
16 files changed, 1121 insertions, 0 deletions
diff --git a/tests/.htaccess b/tests/.htaccess
new file mode 100644
index 00000000..3a428827
--- /dev/null
+++ b/tests/.htaccess
@@ -0,0 +1 @@
+Deny from all
diff --git a/tests/.svnignore b/tests/.svnignore
new file mode 100644
index 00000000..20cb61e9
--- /dev/null
+++ b/tests/.svnignore
@@ -0,0 +1,6 @@
+LocalTestSettings.php
+*~
+bin
+.classpath
+.project
+project.index
diff --git a/tests/ArticleTest.php b/tests/ArticleTest.php
new file mode 100644
index 00000000..bd678565
--- /dev/null
+++ b/tests/ArticleTest.php
@@ -0,0 +1,150 @@
+<?php
+
+require_once( 'PHPUnit.php' );
+require_once( '../includes/Defines.php' );
+require_once( '../includes/Article.php' );
+
+class ArticleTest extends PHPUnit_TestCase {
+ var $saveGlobals = array();
+
+ function ArticleTest( $name ) {
+ $this->PHPUnit_TestCase( $name );
+ }
+
+ function setUp() {
+ $globalSet = array(
+ 'wgLegacyEncoding' => false,
+ 'wgUseLatin1' => false,
+ 'wgCompressRevisions' => false,
+ 'wgInputEncoding' => 'utf-8',
+ 'wgOutputEncoding' => 'utf-8' );
+ foreach( $globalSet as $var => $data ) {
+ $this->saveGlobals[$var] = $GLOBALS[$var];
+ $GLOBALS[$var] = $data;
+ }
+ }
+
+ function tearDown() {
+ foreach( $this->saveGlobals as $var => $data ) {
+ $GLOBALS[$var] = $data;
+ }
+ }
+
+ function testGetRevisionText() {
+ $row = new stdClass;
+ $row->old_flags = '';
+ $row->old_text = 'This is a bunch of revision text.';
+ $this->assertEquals(
+ 'This is a bunch of revision text.',
+ Revision::getRevisionText( $row ) );
+ }
+
+ function testGetRevisionTextGzip() {
+ $row = new stdClass;
+ $row->old_flags = 'gzip';
+ $row->old_text = gzdeflate( 'This is a bunch of revision text.' );
+ $this->assertEquals(
+ 'This is a bunch of revision text.',
+ Revision::getRevisionText( $row ) );
+ }
+
+ function testGetRevisionTextUtf8Native() {
+ $row = new stdClass;
+ $row->old_flags = 'utf-8';
+ $row->old_text = "Wiki est l'\xc3\xa9cole superieur !";
+ $GLOBALS['wgLegacyEncoding'] = 'iso-8859-1';
+ $this->assertEquals(
+ "Wiki est l'\xc3\xa9cole superieur !",
+ Revision::getRevisionText( $row ) );
+ }
+
+ function testGetRevisionTextUtf8Legacy() {
+ $row = new stdClass;
+ $row->old_flags = '';
+ $row->old_text = "Wiki est l'\xe9cole superieur !";
+ $GLOBALS['wgLegacyEncoding'] = 'iso-8859-1';
+ $this->assertEquals(
+ "Wiki est l'\xc3\xa9cole superieur !",
+ Revision::getRevisionText( $row ) );
+ }
+
+ function testGetRevisionTextUtf8NativeGzip() {
+ $row = new stdClass;
+ $row->old_flags = 'gzip,utf-8';
+ $row->old_text = gzdeflate( "Wiki est l'\xc3\xa9cole superieur !" );
+ $GLOBALS['wgLegacyEncoding'] = 'iso-8859-1';
+ $this->assertEquals(
+ "Wiki est l'\xc3\xa9cole superieur !",
+ Revision::getRevisionText( $row ) );
+ }
+
+ function testGetRevisionTextUtf8LegacyGzip() {
+ $row = new stdClass;
+ $row->old_flags = 'gzip';
+ $row->old_text = gzdeflate( "Wiki est l'\xe9cole superieur !" );
+ $GLOBALS['wgLegacyEncoding'] = 'iso-8859-1';
+ $this->assertEquals(
+ "Wiki est l'\xc3\xa9cole superieur !",
+ Revision::getRevisionText( $row ) );
+ }
+
+ function testCompressRevisionTextUtf8() {
+ $row->old_text = "Wiki est l'\xc3\xa9cole superieur !";
+ $row->old_flags = Revision::compressRevisionText( $row->old_text );
+ $this->assertTrue( false !== strpos( $row->old_flags, 'utf-8' ),
+ "Flags should contain 'utf-8'" );
+ $this->assertFalse( false !== strpos( $row->old_flags, 'gzip' ),
+ "Flags should not contain 'gzip'" );
+ $this->assertEquals( "Wiki est l'\xc3\xa9cole superieur !",
+ $row->old_text, "Direct check" );
+ $this->assertEquals( "Wiki est l'\xc3\xa9cole superieur !",
+ Revision::getRevisionText( $row ), "getRevisionText" );
+ }
+
+ function testCompressRevisionTextLatin1() {
+ $GLOBALS['wgUseLatin1'] = true;
+ $row->old_text = "Wiki est l'\xe9cole superieur !";
+ $row->old_flags = Revision::compressRevisionText( $row->old_text );
+ $this->assertFalse( false !== strpos( $row->old_flags, 'utf-8' ),
+ "Flags should not contain 'utf-8'" );
+ $this->assertFalse( false !== strpos( $row->old_flags, 'gzip' ),
+ "Flags should not contain 'gzip'" );
+ $this->assertEquals( "Wiki est l'\xe9cole superieur !",
+ $row->old_text, "Direct check" );
+ $this->assertEquals( "Wiki est l'\xe9cole superieur !",
+ Revision::getRevisionText( $row ), "getRevisionText" );
+ }
+
+ function testCompressRevisionTextUtf8Gzip() {
+ $GLOBALS['wgCompressRevisions'] = true;
+ $row->old_text = "Wiki est l'\xc3\xa9cole superieur !";
+ $row->old_flags = Revision::compressRevisionText( $row->old_text );
+ $this->assertTrue( false !== strpos( $row->old_flags, 'utf-8' ),
+ "Flags should contain 'utf-8'" );
+ $this->assertTrue( false !== strpos( $row->old_flags, 'gzip' ),
+ "Flags should contain 'gzip'" );
+ $this->assertEquals( "Wiki est l'\xc3\xa9cole superieur !",
+ gzinflate( $row->old_text ), "Direct check" );
+ $this->assertEquals( "Wiki est l'\xc3\xa9cole superieur !",
+ Revision::getRevisionText( $row ), "getRevisionText" );
+ }
+
+ function testCompressRevisionTextLatin1Gzip() {
+ $GLOBALS['wgCompressRevisions'] = true;
+ $GLOBALS['wgUseLatin1'] = true;
+ $row = new stdClass;
+ $row->old_text = "Wiki est l'\xe9cole superieur !";
+ $row->old_flags = Revision::compressRevisionText( $row->old_text );
+ $this->assertFalse( false !== strpos( $row->old_flags, 'utf-8' ),
+ "Flags should not contain 'utf-8'" );
+ $this->assertTrue( false !== strpos( $row->old_flags, 'gzip' ),
+ "Flags should contain 'gzip'" );
+ $this->assertEquals( "Wiki est l'\xe9cole superieur !",
+ gzinflate( $row->old_text ), "Direct check" );
+ $this->assertEquals( "Wiki est l'\xe9cole superieur !",
+ Revision::getRevisionText( $row ), "getRevisionText" );
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/tests/DatabaseTest.php b/tests/DatabaseTest.php
new file mode 100644
index 00000000..a721c98d
--- /dev/null
+++ b/tests/DatabaseTest.php
@@ -0,0 +1,93 @@
+<?php
+
+require_once( 'PHPUnit.php' );
+require_once( '../includes/Defines.php' );
+require_once( '../includes/Database.php' );
+require_once( '../includes/GlobalFunctions.php' );
+
+class DatabaseTest extends PHPUnit_TestCase {
+ var $db;
+
+ function DatabaseTest( $name ) {
+ $this->PHPUnit_TestCase( $name );
+ }
+
+ function setUp() {
+ $this->db =& new Database();
+ }
+
+ function tearDown() {
+ unset( $this->db );
+ }
+
+ function testAddQuotesNull() {
+ $this->assertEquals(
+ 'NULL',
+ $this->db->addQuotes( NULL ) );
+ }
+
+ function testAddQuotesInt() {
+ # returning just "1234" should be ok too, though...
+ # maybe
+ $this->assertEquals(
+ "'1234'",
+ $this->db->addQuotes( 1234 ) );
+ }
+
+ function testAddQuotesFloat() {
+ # returning just "1234.5678" would be ok too, though
+ $this->assertEquals(
+ "'1234.5678'",
+ $this->db->addQuotes( 1234.5678 ) );
+ }
+
+ function testAddQuotesString() {
+ $this->assertEquals(
+ "'string'",
+ $this->db->addQuotes( 'string' ) );
+ }
+
+ function testAddQuotesStringQuote() {
+ $this->assertEquals(
+ "'string\'s cause trouble'",
+ $this->db->addQuotes( "string's cause trouble" ) );
+ }
+
+ function testFillPreparedEmpty() {
+ $sql = $this->db->fillPrepared(
+ 'SELECT * FROM interwiki', array() );
+ $this->assertEquals(
+ "SELECT * FROM interwiki",
+ $sql);
+ }
+
+ function testFillPreparedQuestion() {
+ $sql = $this->db->fillPrepared(
+ 'SELECT * FROM cur WHERE cur_namespace=? AND cur_title=?',
+ array( 4, "Snicker's_paradox" ) );
+ $this->assertEquals(
+ "SELECT * FROM cur WHERE cur_namespace='4' AND cur_title='Snicker\'s_paradox'",
+ $sql);
+ }
+
+ function testFillPreparedBang() {
+ $sql = $this->db->fillPrepared(
+ 'SELECT user_id FROM ! WHERE user_name=?',
+ array( '"user"', "Slash's Dot" ) );
+ $this->assertEquals(
+ "SELECT user_id FROM \"user\" WHERE user_name='Slash\'s Dot'",
+ $sql);
+ }
+
+ function testFillPreparedRaw() {
+ $sql = $this->db->fillPrepared(
+ "SELECT * FROM cur WHERE cur_title='This_\\&_that,_WTF\\?\\!'",
+ array( '"user"', "Slash's Dot" ) );
+ $this->assertEquals(
+ "SELECT * FROM cur WHERE cur_title='This_&_that,_WTF?!'",
+ $sql);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/tests/GlobalTest.php b/tests/GlobalTest.php
new file mode 100644
index 00000000..1567a189
--- /dev/null
+++ b/tests/GlobalTest.php
@@ -0,0 +1,211 @@
+<?php
+
+require_once( 'PHPUnit.php' );
+require_once( '../includes/Defines.php' );
+require_once( '../includes/Profiling.php' );
+require_once( '../includes/GlobalFunctions.php' );
+
+class GlobalTest extends PHPUnit_TestCase {
+ function GlobalTest( $name ) {
+ $this->PHPUnit_TestCase( $name );
+ }
+
+ function setUp() {
+ $this->save = array();
+ $saveVars = array( 'wgReadOnlyFile' );
+ foreach( $saveVars as $var ) {
+ if( isset( $GLOBALS[$var] ) ) {
+ $this->save[$var] = $GLOBALS[$var];
+ }
+ }
+ $GLOBALS['wgReadOnlyFile'] = wfTempDir() . '/testReadOnly-' . mt_rand();
+ }
+
+ function tearDown() {
+ foreach( $this->save as $var => $data ) {
+ $GLOBALS[$var] = $data;
+ }
+ }
+
+ function testRandom() {
+ # This could hypothetically fail, but it shouldn't ;)
+ $this->assertFalse(
+ wfRandom() == wfRandom() );
+ }
+
+ function testUrlencode() {
+ $this->assertEquals(
+ "%E7%89%B9%E5%88%A5:Contributions/Foobar",
+ wfUrlencode( "\xE7\x89\xB9\xE5\x88\xA5:Contributions/Foobar" ) );
+ }
+
+ function testReadOnlyEmpty() {
+ $this->assertFalse( wfReadOnly() );
+ }
+
+ function testReadOnlySet() {
+ $f = fopen( $GLOBALS['wgReadOnlyFile'], "wt" );
+ fwrite( $f, 'Message' );
+ fclose( $f );
+ $this->assertTrue( wfReadOnly() );
+
+ unlink( $GLOBALS['wgReadOnlyFile'] );
+ $this->assertFalse( wfReadOnly() );
+ }
+
+ function testQuotedPrintable() {
+ $this->assertEquals(
+ "=?UTF-8?Q?=C4=88u=20legebla=3F?=",
+ wfQuotedPrintable( "\xc4\x88u legebla?", "UTF-8" ) );
+ }
+
+ function testTime() {
+ $start = wfTime();
+ $this->assertType( 'double', $start );
+ $end = wfTime();
+ $this->assertTrue( $end > $start, "Time is running backwards!" );
+ }
+
+ function testArrayToCGI() {
+ $this->assertEquals(
+ "baz=AT%26T&foo=bar",
+ wfArrayToCGI(
+ array( 'baz' => 'AT&T', 'ignore' => '' ),
+ array( 'foo' => 'bar', 'baz' => 'overridden value' ) ) );
+ }
+
+ function testMimeTypeMatch() {
+ $this->assertEquals(
+ 'text/html',
+ mimeTypeMatch( 'text/html',
+ array( 'application/xhtml+xml' => 1.0,
+ 'text/html' => 0.7,
+ 'text/plain' => 0.3 ) ) );
+ $this->assertEquals(
+ 'text/*',
+ mimeTypeMatch( 'text/html',
+ array( 'image/*' => 1.0,
+ 'text/*' => 0.5 ) ) );
+ $this->assertEquals(
+ '*/*',
+ mimeTypeMatch( 'text/html',
+ array( '*/*' => 1.0 ) ) );
+ $this->assertNull(
+ mimeTypeMatch( 'text/html',
+ array( 'image/png' => 1.0,
+ 'image/svg+xml' => 0.5 ) ) );
+ }
+
+ function testNegotiateType() {
+ $this->assertEquals(
+ 'text/html',
+ wfNegotiateType(
+ array( 'application/xhtml+xml' => 1.0,
+ 'text/html' => 0.7,
+ 'text/plain' => 0.5,
+ 'text/*' => 0.2 ),
+ array( 'text/html' => 1.0 ) ) );
+ $this->assertEquals(
+ 'application/xhtml+xml',
+ wfNegotiateType(
+ array( 'application/xhtml+xml' => 1.0,
+ 'text/html' => 0.7,
+ 'text/plain' => 0.5,
+ 'text/*' => 0.2 ),
+ array( 'application/xhtml+xml' => 1.0,
+ 'text/html' => 0.5 ) ) );
+ $this->assertEquals(
+ 'text/html',
+ wfNegotiateType(
+ array( 'text/html' => 1.0,
+ 'text/plain' => 0.5,
+ 'text/*' => 0.5,
+ 'application/xhtml+xml' => 0.2 ),
+ array( 'application/xhtml+xml' => 1.0,
+ 'text/html' => 0.5 ) ) );
+ $this->assertEquals(
+ 'text/html',
+ wfNegotiateType(
+ array( 'text/*' => 1.0,
+ 'image/*' => 0.7,
+ '*/*' => 0.3 ),
+ array( 'application/xhtml+xml' => 1.0,
+ 'text/html' => 0.5 ) ) );
+ $this->assertNull(
+ wfNegotiateType(
+ array( 'text/*' => 1.0 ),
+ array( 'application/xhtml+xml' => 1.0 ) ) );
+ }
+
+ function testTimestamp() {
+ $t = gmmktime( 12, 34, 56, 1, 15, 2001 );
+ $this->assertEquals(
+ '20010115123456',
+ wfTimestamp( TS_MW, $t ),
+ 'TS_UNIX to TS_MW' );
+ $this->assertEquals(
+ 979562096,
+ wfTimestamp( TS_UNIX, $t ),
+ 'TS_UNIX to TS_UNIX' );
+ $this->assertEquals(
+ '2001-01-15 12:34:56',
+ wfTimestamp( TS_DB, $t ),
+ 'TS_UNIX to TS_DB' );
+
+ $this->assertEquals(
+ '20010115123456',
+ wfTimestamp( TS_MW, '20010115123456' ),
+ 'TS_MW to TS_MW' );
+ $this->assertEquals(
+ 979562096,
+ wfTimestamp( TS_UNIX, '20010115123456' ),
+ 'TS_MW to TS_UNIX' );
+ $this->assertEquals(
+ '2001-01-15 12:34:56',
+ wfTimestamp( TS_DB, '20010115123456' ),
+ 'TS_MW to TS_DB' );
+
+ $this->assertEquals(
+ '20010115123456',
+ wfTimestamp( TS_MW, '2001-01-15 12:34:56' ),
+ 'TS_DB to TS_MW' );
+ $this->assertEquals(
+ 979562096,
+ wfTimestamp( TS_UNIX, '2001-01-15 12:34:56' ),
+ 'TS_DB to TS_UNIX' );
+ $this->assertEquals(
+ '2001-01-15 12:34:56',
+ wfTimestamp( TS_DB, '2001-01-15 12:34:56' ),
+ 'TS_DB to TS_DB' );
+ }
+
+ function testBasename() {
+ $sets = array(
+ '' => '',
+ '/' => '',
+ '\\' => '',
+ '//' => '',
+ '\\\\' => '',
+ 'a' => 'a',
+ 'aaaa' => 'aaaa',
+ '/a' => 'a',
+ '\\a' => 'a',
+ '/aaaa' => 'aaaa',
+ '\\aaaa' => 'aaaa',
+ '/aaaa/' => 'aaaa',
+ '\\aaaa\\' => 'aaaa',
+ '\\aaaa\\' => 'aaaa',
+ '/mnt/upload3/wikipedia/en/thumb/8/8b/Zork_Grand_Inquisitor_box_cover.jpg/93px-Zork_Grand_Inquisitor_box_cover.jpg' => '93px-Zork_Grand_Inquisitor_box_cover.jpg',
+ 'C:\\Progra~1\\Wikime~1\\Wikipe~1\\VIEWER.EXE' => 'VIEWER.EXE',
+ 'Östergötland_coat_of_arms.png' => 'Östergötland_coat_of_arms.png',
+ );
+ foreach( $sets as $from => $to ) {
+ $this->assertEquals( $to, wfBaseName( $from ),
+ "wfBaseName('$from') => '$to'");
+ }
+ }
+
+ /* TODO: many more! */
+}
+
+?> \ No newline at end of file
diff --git a/tests/ImageTest.php b/tests/ImageTest.php
new file mode 100644
index 00000000..b06d4cbf
--- /dev/null
+++ b/tests/ImageTest.php
@@ -0,0 +1,66 @@
+<?php
+
+require_once( 'PHPUnit.php' );
+require_once( '../includes/Defines.php' );
+require_once( '../includes/Profiling.php' );
+require_once( '../includes/GlobalFunctions.php' );
+require_once( '../includes/Image.php' );
+
+class ImageTest extends PHPUnit_TestCase {
+ function ImageTest( $name ) {
+ $this->PHPUnit_TestCase( $name );
+ }
+
+ function setUp() {
+ }
+
+ function tearDown() {
+ }
+
+ function testFitBoxWidth() {
+ $vals = array(
+ array(
+ 'width' => 50,
+ 'height' => 50,
+ 'tests' => array(
+ 50 => 50,
+ 17 => 17,
+ 18 => 18 ) ),
+ array(
+ 'width' => 366,
+ 'height' => 300,
+ 'tests' => array(
+ 50 => 61,
+ 17 => 21,
+ 18 => 22 ) ),
+ array(
+ 'width' => 300,
+ 'height' => 366,
+ 'tests' => array(
+ 50 => 41,
+ 17 => 14,
+ 18 => 15 ) ),
+ array(
+ 'width' => 100,
+ 'height' => 400,
+ 'tests' => array(
+ 50 => 12,
+ 17 => 4,
+ 18 => 4 ) ) );
+ foreach( $vals as $row ) {
+ extract( $row );
+ foreach( $tests as $max => $expected ) {
+ $y = round( $expected * $height / $width );
+ $result = wfFitBoxWidth( $width, $height, $max );
+ $y2 = round( $result * $height / $width );
+ $this->assertEquals( $expected,
+ $result,
+ "($width, $height, $max) wanted: {$expected}x$y, got: {$result}x$y2" );
+ }
+ }
+ }
+
+ /* TODO: many more! */
+}
+
+?> \ No newline at end of file
diff --git a/tests/LocalTestSettings.sample b/tests/LocalTestSettings.sample
new file mode 100644
index 00000000..7ada2fda
--- /dev/null
+++ b/tests/LocalTestSettings.sample
@@ -0,0 +1,29 @@
+<?php
+# This contains basic configuration values that are needed
+# for RunTests.php.
+
+# Full path to the mediawiki source code you want to test
+$IP = '/var/www/mediawiki-cvs';
+
+# Now we add that path to the default include_path
+ini_set('include_path',ini_get('include_path').':'.$IP);
+
+# Some options needed for database testing
+$testOptions = array(
+ 'mysql3' => array(
+ 'server' => null,
+ 'user' => null,
+ 'password' => null,
+ 'database' => null ),
+ 'mysql4' => array(
+ 'server' => null,
+ 'user' => null,
+ 'password' => null,
+ 'database' => null ),
+ 'postgres' => array(
+ 'server' => null,
+ 'user' => null,
+ 'password' => null,
+ 'database' => null ),
+ );
+?>
diff --git a/tests/Makefile b/tests/Makefile
new file mode 100644
index 00000000..0a649927
--- /dev/null
+++ b/tests/Makefile
@@ -0,0 +1,15 @@
+.PHONY: help test
+all test:
+ php RunTests.php
+install:
+ cvs -z9 -d:pserver:cvsread:@cvs.php.net:/repository/ co -P pear/PHPUnit
+ mv pear/PHPUnit .
+ rm -rf pear
+clean:
+ rm -rf PHPUnit pear
+help:
+ # Options:
+ # test (default) Run the unit tests
+ # install Install PHPUnit from CVS
+ # clean Remove local PHPUnit install
+ # help You're looking at it!
diff --git a/tests/README b/tests/README
new file mode 100644
index 00000000..de153184
--- /dev/null
+++ b/tests/README
@@ -0,0 +1,8 @@
+Some quickie unit tests done with the PHPUnit testing framework. To run the
+test suite, run 'make test' in this dir or 'php RunTests.php'
+
+You can install PHPUnit via pear like this:
+# pear install PHPUnit
+
+Or fetch and install it manually:
+http://pear.php.net/package/PHPUnit
diff --git a/tests/RunTests.php b/tests/RunTests.php
new file mode 100644
index 00000000..ec04fc03
--- /dev/null
+++ b/tests/RunTests.php
@@ -0,0 +1,100 @@
+<?php
+
+if( php_sapi_name() != 'cli' ) {
+ echo 'Must be run from the command line.';
+ die( -1 );
+}
+
+error_reporting( E_ALL );
+define( "MEDIAWIKI", true );
+
+set_include_path( get_include_path() . PATH_SEPARATOR . 'PHPUnit' );
+set_include_path( get_include_path() . PATH_SEPARATOR . '..' );
+require_once( 'PHPUnit.php' );
+
+$testOptions = array(
+ 'mysql4' => array(
+ 'server' => null,
+ 'user' => null,
+ 'password' => null,
+ 'database' => null ),
+ 'postgres' => array(
+ 'server' => null,
+ 'user' => null,
+ 'password' => null,
+ 'database' => null ),
+ );
+
+if( file_exists( 'LocalTestSettings.php' ) ) {
+ include( './LocalTestSettings.php' );
+}
+
+$tests = array(
+ 'GlobalTest',
+ 'DatabaseTest',
+ 'SearchMySQL4Test',
+ 'ArticleTest',
+ 'SanitizerTest',
+ 'ImageTest'
+ );
+
+if( isset( $_SERVER['argv'][1] ) ) {
+ // to override...
+ $tests = array( $_SERVER['argv'][1] );
+}
+
+foreach( $tests as $test ) {
+ require_once( $test . '.php' );
+ $suite = new PHPUnit_TestSuite( $test );
+ $result = PHPUnit::run( $suite );
+ echo $result->toString();
+}
+
+/**
+ * @param string $serverType
+ * @param array $tables
+ */
+function &buildTestDatabase( $serverType, $tables ) {
+ global $testOptions, $wgDBprefix;
+ $wgDBprefix = 'parsertest';
+ $db =& new Database(
+ $testOptions[$serverType]['server'],
+ $testOptions[$serverType]['user'],
+ $testOptions[$serverType]['password'],
+ $testOptions[$serverType]['database'] );
+ if( $db->isOpen() ) {
+ if (!(strcmp($db->getServerVersion(), '4.1') < 0 and stristr($db->getSoftwareLink(), 'MySQL'))) {
+ # Database that supports CREATE TABLE ... LIKE
+ foreach ($tables as $tbl) {
+ $newTableName = $db->tableName( $tbl );
+ #$tableName = $this->oldTableNames[$tbl];
+ $tableName = $tbl;
+ $db->query("CREATE TEMPORARY TABLE $newTableName (LIKE $tableName INCLUDING DEFAULTS)");
+ }
+ } else {
+ # Hack for MySQL versions < 4.1, which don't support
+ # "CREATE TABLE ... LIKE". Note that
+ # "CREATE TEMPORARY TABLE ... SELECT * FROM ... LIMIT 0"
+ # would not create the indexes we need....
+ foreach ($tables as $tbl) {
+ $res = $db->query("SHOW CREATE TABLE $tbl");
+ $row = $db->fetchRow($res);
+ $create = $row[1];
+ $create_tmp = preg_replace('/CREATE TABLE `(.*?)`/', 'CREATE TEMPORARY TABLE `'
+ . $wgDBprefix . '\\1`', $create);
+ if ($create === $create_tmp) {
+ # Couldn't do replacement
+ wfDie( "could not create temporary table $tbl" );
+ }
+ $db->query($create_tmp);
+ }
+
+ }
+ return $db;
+ } else {
+ // Something amiss
+ return null;
+ }
+}
+
+?>
diff --git a/tests/SanitizerTest.php b/tests/SanitizerTest.php
new file mode 100644
index 00000000..5babf0ae
--- /dev/null
+++ b/tests/SanitizerTest.php
@@ -0,0 +1,65 @@
+<?php
+
+require_once( 'PHPUnit.php' );
+require_once( '../includes/Defines.php' );
+require_once( '../includes/Profiling.php' );
+require_once( '../includes/GlobalFunctions.php' );
+require_once( '../includes/Sanitizer.php' );
+
+class SanitizerTest extends PHPUnit_TestCase {
+ function SanitizerTest( $name ) {
+ $this->PHPUnit_TestCase( $name );
+ }
+
+ function setUp() {
+ }
+
+ function tearDown() {
+ }
+
+ function testDecodeNamed() {
+ $this->assertEquals(
+ "\xc3\xa9cole",
+ Sanitizer::decodeCharReferences( '&eacute;cole' ) );
+ }
+
+ function testDecodeNumbered() {
+ $this->assertEquals(
+ "\xc4\x88io bonas dans l'\xc3\xa9cole!",
+ Sanitizer::decodeCharReferences( "&#x108;io bonas dans l'&#233;cole!" ) );
+ }
+
+ function testDecodeMixed() {
+ $this->assertEquals(
+ "\xc4\x88io bonas dans l'\xc3\xa9cole!",
+ Sanitizer::decodeCharReferences( "&#x108;io bonas dans l'&eacute;cole!" ) );
+ }
+
+ function testDecodeMixedComplex() {
+ $this->assertEquals(
+ "\xc4\x88io bonas dans l'\xc3\xa9cole! (mais pas &#x108;io dans l'&eacute;cole)",
+ Sanitizer::decodeCharReferences( "&#x108;io bonas dans l'&eacute;cole! (mais pas &amp;#x108;io dans l'&#38;eacute;cole)" ) );
+ }
+
+ function testDecodeInvalidAmp() {
+ $this->assertEquals(
+ "a & b",
+ Sanitizer::decodeCharReferences( "a & b" ) );
+ }
+
+ function testDecodeInvalidNamed() {
+ $this->assertEquals(
+ "&foo;",
+ Sanitizer::decodeCharReferences( "&foo;" ) );
+ }
+
+ function testDecodeInvalidNumbered() {
+ $this->assertEquals(
+ UTF8_REPLACEMENT,
+ Sanitizer::decodeCharReferences( "&#88888888888888;" ) );
+ }
+
+ /* TODO: many more! */
+}
+
+?> \ No newline at end of file
diff --git a/tests/SearchEngineTest.php b/tests/SearchEngineTest.php
new file mode 100644
index 00000000..20d8017e
--- /dev/null
+++ b/tests/SearchEngineTest.php
@@ -0,0 +1,136 @@
+<?php
+
+$IP = '..';
+require_once( 'PHPUnit.php' );
+require_once( '../includes/Defines.php' );
+require_once( '../includes/DefaultSettings.php' );
+require_once( '../includes/Profiling.php' );
+require_once( '../includes/Hooks.php' );
+require_once( '../includes/MagicWord.php' );
+require_once( '../languages/Language.php' );
+require_once( '../languages/LanguageUtf8.php' );
+
+require_once( '../includes/SearchEngine.php' );
+
+/** @todo document */
+class SearchEngine_TestCase extends PHPUnit_TestCase {
+ var $db, $search;
+
+ function insertSearchData() {
+ $this->db->safeQuery( <<<END
+ INSERT INTO ! (page_id,page_namespace,page_title,page_latest)
+ VALUES (1, 0, 'Main_Page', 1),
+ (2, 1, 'Main_Page', 2),
+ (3, 0, 'Smithee', 3),
+ (4, 1, 'Smithee', 4),
+ (5, 0, 'Unrelated_page', 5),
+ (6, 0, 'Another_page', 6),
+ (7, 4, 'Help', 7),
+ (8, 0, 'Thppt', 8),
+ (9, 0, 'Alan_Smithee', 9),
+ (10, 0, 'Pages', 10)
+END
+ , $this->db->tableName( 'page' ) );
+ $this->db->safeQuery( <<<END
+ INSERT INTO ! (rev_id,rev_page)
+ VALUES (1, 1),
+ (2, 2),
+ (3, 3),
+ (4, 4),
+ (5, 5),
+ (6, 6),
+ (7, 7),
+ (8, 8),
+ (9, 9),
+ (10, 10)
+END
+ , $this->db->tableName( 'revision' ) );
+ $this->db->safeQuery( <<<END
+ INSERT INTO ! (old_id,old_text)
+ VALUES (1, 'This is a main page'),
+ (2, 'This is a talk page to the main page, see [[smithee]]'),
+ (3, 'A smithee is one who smiths. See also [[Alan Smithee]]'),
+ (4, 'This article sucks.'),
+ (5, 'Nothing in this page is about the S word.'),
+ (6, 'This page also is unrelated.'),
+ (7, 'Help me!'),
+ (8, 'Blah blah'),
+ (9, 'yum'),
+ (10,'are food')
+END
+ , $this->db->tableName( 'text' ) );
+ $this->db->safeQuery( <<<END
+ INSERT INTO ! (si_page,si_title,si_text)
+ VALUES (1, 'main page', 'this is a main page'),
+ (2, 'main page', 'this is a talk page to the main page, see smithee'),
+ (3, 'smithee', 'a smithee is one who smiths see also alan smithee'),
+ (4, 'smithee', 'this article sucks'),
+ (5, 'unrelated page', 'nothing in this page is about the s word'),
+ (6, 'another page', 'this page also is unrelated'),
+ (7, 'help', 'help me'),
+ (8, 'thppt', 'blah blah'),
+ (9, 'alan smithee', 'yum'),
+ (10, 'pages', 'are food')
+END
+ , $this->db->tableName( 'searchindex' ) );
+ }
+
+ function fetchIds( &$results ) {
+ $matches = array();
+ while( $row = $results->fetchObject() ) {
+ $matches[] = intval( $row->page_id );
+ }
+ $results->free();
+ # Search is not guaranteed to return results in a certain order;
+ # sort them numerically so we will compare simply that we received
+ # the expected matches.
+ sort( $matches );
+ return $matches;
+ }
+
+ function testTextSearch() {
+ $this->assertFalse( is_null( $this->db ), "Can't find a database to test with." );
+ if( !is_null( $this->db ) ) {
+ $this->assertEquals(
+ array( 3 ),
+ $this->fetchIds( $this->search->searchText( 'smithee' ) ),
+ "Plain search failed" );
+ }
+ }
+
+ function testTextPowerSearch() {
+ $this->assertFalse( is_null( $this->db ), "Can't find a database to test with." );
+ if( !is_null( $this->db ) ) {
+ $this->search->setNamespaces( array( 0, 1, 4 ) );
+ $this->assertEquals(
+ array( 2, 3 ),
+ $this->fetchIds( $this->search->searchText( 'smithee' ) ),
+ "Power search failed" );
+ }
+ }
+
+ function testTitleSearch() {
+ $this->assertFalse( is_null( $this->db ), "Can't find a database to test with." );
+ if( !is_null( $this->db ) ) {
+ $this->assertEquals(
+ array( 3, 9 ),
+ $this->fetchIds( $this->search->searchTitle( 'smithee' ) ),
+ "Title search failed" );
+ }
+ }
+
+ function testTextTitlePowerSearch() {
+ $this->assertFalse( is_null( $this->db ), "Can't find a database to test with." );
+ if( !is_null( $this->db ) ) {
+ $this->search->setNamespaces( array( 0, 1, 4 ) );
+ $this->assertEquals(
+ array( 3, 4, 9 ),
+ $this->fetchIds( $this->search->searchTitle( 'smithee' ) ),
+ "Title power search failed" );
+ }
+ }
+
+}
+
+
+?>
diff --git a/tests/SearchMySQL4Test.php b/tests/SearchMySQL4Test.php
new file mode 100644
index 00000000..545af230
--- /dev/null
+++ b/tests/SearchMySQL4Test.php
@@ -0,0 +1,34 @@
+<?php
+
+require_once( 'SearchEngineTest.php' );
+require_once( '../includes/SearchMySQL4.php' );
+
+class SearchMySQL4Test extends SearchEngine_TestCase {
+ var $db;
+
+ function SearchMySQL4Test( $name ) {
+ $this->PHPUnit_TestCase( $name );
+ }
+
+ function setUp() {
+ $GLOBALS['wgContLang'] = new LanguageUtf8;
+ $this->db =& buildTestDatabase(
+ 'mysql4',
+ array( 'page', 'revision', 'text', 'searchindex' ) );
+ if( $this->db ) {
+ $this->insertSearchData();
+ }
+ $this->search =& new SearchMySQL4( $this->db );
+ }
+
+ function tearDown() {
+ if( !is_null( $this->db ) ) {
+ $this->db->close();
+ }
+ unset( $this->db );
+ unset( $this->search );
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/tests/test-prefetch-current.xml b/tests/test-prefetch-current.xml
new file mode 100644
index 00000000..a4c8bda3
--- /dev/null
+++ b/tests/test-prefetch-current.xml
@@ -0,0 +1,75 @@
+<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.3/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.3/ http://www.mediawiki.org/xml/export-0.3.xsd" version="0.3" xml:lang="en">
+<siteinfo>
+ <sitename>DemoWiki</sitename>
+ <base>http://example.com/wiki/Main_Page</base>
+ <generator>MediaWiki 1.5.0</generator>
+ <case>first-letter</case>
+ <namespaces>
+ <namespace key="-2">Media</namespace>
+ <namespace key="-1">Special</namespace>
+ <namespace key="0"></namespace>
+ <namespace key="1">Talk</namespace>
+ <namespace key="2">User</namespace>
+ <namespace key="3">User talk</namespace>
+ <namespace key="4">DemoWiki</namespace>
+ <namespace key="5">DemoWIki talk</namespace>
+ <namespace key="6">Image</namespace>
+ <namespace key="7">Image talk</namespace>
+ <namespace key="8">MediaWiki</namespace>
+ <namespace key="9">MediaWiki talk</namespace>
+ <namespace key="10">Template</namespace>
+ <namespace key="11">Template talk</namespace>
+ <namespace key="12">Help</namespace>
+ <namespace key="13">Help talk</namespace>
+ <namespace key="14">Category</namespace>
+ <namespace key="15">Category talk</namespace>
+ </namespaces>
+</siteinfo>
+<page>
+ <title>First page</title>
+ <id>1</id>
+ <revision>
+ <id>1</id>
+ <timestamp>2001-01-15T12:00:00Z</timestamp>
+ <contributor><ip>10.0.0.1</ip></contributor>
+ <comment>page 1, rev 1</comment>
+ <text>page 1, rev 1</text>
+ </revision>
+ <revision>
+ <id>2</id>
+ <timestamp>2001-01-15T12:00:00Z</timestamp>
+ <contributor><ip>10.0.0.1</ip></contributor>
+ <comment>page 1, rev 2</comment>
+ <text>page 1, rev 2</text>
+ </revision>
+ <revision>
+ <id>4</id>
+ <timestamp>2001-01-15T12:00:00Z</timestamp>
+ <contributor><ip>10.0.0.1</ip></contributor>
+ <comment>page 1, rev 4</comment>
+ <text>page 1, rev 4</text>
+ </revision>
+</page>
+<page>
+ <title>Second page</title>
+ <id>2</id>
+ <revision>
+ <id>3</id>
+ <timestamp>2001-01-15T12:00:00Z</timestamp>
+ <contributor><ip>10.0.0.1</ip></contributor>
+ <comment>page 2, rev 3</comment>
+ <text>page 2, rev 3</text>
+ </revision>
+</page>
+<page>
+ <title>Third page</title>
+ <id>3</id>
+ <revision>
+ <id>5</id>
+ <timestamp>2001-01-15T12:00:00Z</timestamp>
+ <contributor><ip>10.0.0.1</ip></contributor>
+ <comment>page 3, rev 5</comment>
+ <text>page 3, rev 5</text>
+ </revision>
+</page>
+</mediawiki>
diff --git a/tests/test-prefetch-previous.xml b/tests/test-prefetch-previous.xml
new file mode 100644
index 00000000..95eb82dd
--- /dev/null
+++ b/tests/test-prefetch-previous.xml
@@ -0,0 +1,57 @@
+<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.3/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.3/ http://www.mediawiki.org/xml/export-0.3.xsd" version="0.3" xml:lang="en">
+<siteinfo>
+ <sitename>DemoWiki</sitename>
+ <base>http://example.com/wiki/Main_Page</base>
+ <generator>MediaWiki 1.5.0</generator>
+ <case>first-letter</case>
+ <namespaces>
+ <namespace key="-2">Media</namespace>
+ <namespace key="-1">Special</namespace>
+ <namespace key="0"></namespace>
+ <namespace key="1">Talk</namespace>
+ <namespace key="2">User</namespace>
+ <namespace key="3">User talk</namespace>
+ <namespace key="4">DemoWiki</namespace>
+ <namespace key="5">DemoWIki talk</namespace>
+ <namespace key="6">Image</namespace>
+ <namespace key="7">Image talk</namespace>
+ <namespace key="8">MediaWiki</namespace>
+ <namespace key="9">MediaWiki talk</namespace>
+ <namespace key="10">Template</namespace>
+ <namespace key="11">Template talk</namespace>
+ <namespace key="12">Help</namespace>
+ <namespace key="13">Help talk</namespace>
+ <namespace key="14">Category</namespace>
+ <namespace key="15">Category talk</namespace>
+ </namespaces>
+</siteinfo>
+<page>
+ <title>First page</title>
+ <id>1</id>
+ <revision>
+ <id>1</id>
+ <timestamp>2001-01-15T12:00:00Z</timestamp>
+ <contributor><ip>10.0.0.1</ip></contributor>
+ <comment>page 1, rev 1</comment>
+ <text>page 1, rev 1</text>
+ </revision>
+ <revision>
+ <id>2</id>
+ <timestamp>2001-01-15T12:00:00Z</timestamp>
+ <contributor><ip>10.0.0.1</ip></contributor>
+ <comment>page 1, rev 2</comment>
+ <text>page 1, rev 2</text>
+ </revision>
+</page>
+<page>
+ <title>Second page</title>
+ <id>2</id>
+ <revision>
+ <id>3</id>
+ <timestamp>2001-01-15T12:00:00Z</timestamp>
+ <contributor><ip>10.0.0.1</ip></contributor>
+ <comment>page 2, rev 3</comment>
+ <text>page 2, rev 3</text>
+ </revision>
+</page>
+</mediawiki>
diff --git a/tests/test-prefetch-stub.xml b/tests/test-prefetch-stub.xml
new file mode 100644
index 00000000..59d43d2f
--- /dev/null
+++ b/tests/test-prefetch-stub.xml
@@ -0,0 +1,75 @@
+<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.3/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.3/ http://www.mediawiki.org/xml/export-0.3.xsd" version="0.3" xml:lang="en">
+<siteinfo>
+ <sitename>DemoWiki</sitename>
+ <base>http://example.com/wiki/Main_Page</base>
+ <generator>MediaWiki 1.5.0</generator>
+ <case>first-letter</case>
+ <namespaces>
+ <namespace key="-2">Media</namespace>
+ <namespace key="-1">Special</namespace>
+ <namespace key="0"></namespace>
+ <namespace key="1">Talk</namespace>
+ <namespace key="2">User</namespace>
+ <namespace key="3">User talk</namespace>
+ <namespace key="4">DemoWiki</namespace>
+ <namespace key="5">DemoWIki talk</namespace>
+ <namespace key="6">Image</namespace>
+ <namespace key="7">Image talk</namespace>
+ <namespace key="8">MediaWiki</namespace>
+ <namespace key="9">MediaWiki talk</namespace>
+ <namespace key="10">Template</namespace>
+ <namespace key="11">Template talk</namespace>
+ <namespace key="12">Help</namespace>
+ <namespace key="13">Help talk</namespace>
+ <namespace key="14">Category</namespace>
+ <namespace key="15">Category talk</namespace>
+ </namespaces>
+</siteinfo>
+<page>
+ <title>First page</title>
+ <id>1</id>
+ <revision>
+ <id>1</id>
+ <timestamp>2001-01-15T12:00:00Z</timestamp>
+ <contributor><ip>10.0.0.1</ip></contributor>
+ <comment>page 1, rev 1</comment>
+ <text id="1" />
+ </revision>
+ <revision>
+ <id>2</id>
+ <timestamp>2001-01-15T12:00:00Z</timestamp>
+ <contributor><ip>10.0.0.1</ip></contributor>
+ <comment>page 1, rev 2</comment>
+ <text id="2" />
+ </revision>
+ <revision>
+ <id>4</id>
+ <timestamp>2001-01-15T12:00:00Z</timestamp>
+ <contributor><ip>10.0.0.1</ip></contributor>
+ <comment>page 1, rev 4</comment>
+ <text id="4" />
+ </revision>
+</page>
+<page>
+ <title>Second page</title>
+ <id>2</id>
+ <revision>
+ <id>3</id>
+ <timestamp>2001-01-15T12:00:00Z</timestamp>
+ <contributor><ip>10.0.0.1</ip></contributor>
+ <comment>page 2, rev 3</comment>
+ <text id="3" />
+ </revision>
+</page>
+<page>
+ <title>Third page</title>
+ <id>3</id>
+ <revision>
+ <id>5</id>
+ <timestamp>2001-01-15T12:00:00Z</timestamp>
+ <contributor><ip>10.0.0.1</ip></contributor>
+ <comment>page 3, rev 5</comment>
+ <text id="5" />
+ </revision>
+</page>
+</mediawiki>