summaryrefslogtreecommitdiff
path: root/tests/phpunit/includes/libs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/phpunit/includes/libs')
-rw-r--r--tests/phpunit/includes/libs/ArrayUtilsTest.php311
-rw-r--r--tests/phpunit/includes/libs/CSSMinTest.php49
-rw-r--r--tests/phpunit/includes/libs/DeferredStringifierTest.php50
-rw-r--r--tests/phpunit/includes/libs/GenericArrayObjectTest.php3
-rw-r--r--tests/phpunit/includes/libs/HashRingTest.php2
-rw-r--r--tests/phpunit/includes/libs/IEUrlExtensionTest.php2
-rw-r--r--tests/phpunit/includes/libs/IPSetTest.php2
-rw-r--r--tests/phpunit/includes/libs/JavaScriptMinifierTest.php11
-rw-r--r--tests/phpunit/includes/libs/MWMessagePackTest.php2
-rw-r--r--tests/phpunit/includes/libs/ObjectFactoryTest.php60
-rw-r--r--tests/phpunit/includes/libs/ProcessCacheLRUTest.php50
-rw-r--r--tests/phpunit/includes/libs/RunningStatTest.php2
-rw-r--r--tests/phpunit/includes/libs/StringUtilsTest.php149
-rw-r--r--tests/phpunit/includes/libs/XhprofTest.php320
-rw-r--r--tests/phpunit/includes/libs/XmlTypeCheckTest.php49
-rw-r--r--tests/phpunit/includes/libs/composer/ComposerJsonTest.php57
-rw-r--r--tests/phpunit/includes/libs/composer/ComposerLockTest.php62
17 files changed, 1156 insertions, 25 deletions
diff --git a/tests/phpunit/includes/libs/ArrayUtilsTest.php b/tests/phpunit/includes/libs/ArrayUtilsTest.php
new file mode 100644
index 00000000..b5ea7b72
--- /dev/null
+++ b/tests/phpunit/includes/libs/ArrayUtilsTest.php
@@ -0,0 +1,311 @@
+<?php
+/**
+ * Test class for ArrayUtils class
+ *
+ * @group Database
+ */
+
+class ArrayUtilsTest extends PHPUnit_Framework_TestCase {
+ private $search;
+
+ /**
+ * @covers ArrayUtils::findLowerBound
+ * @dataProvider provideFindLowerBound
+ */
+ function testFindLowerBound(
+ $valueCallback, $valueCount, $comparisonCallback, $target, $expected
+ ) {
+ $this->assertSame(
+ ArrayUtils::findLowerBound(
+ $valueCallback, $valueCount, $comparisonCallback, $target
+ ), $expected
+ );
+ }
+
+ function provideFindLowerBound() {
+ $self = $this;
+ $indexValueCallback = function ( $size ) use ( $self ) {
+ return function ( $val ) use ( $self, $size ) {
+ $self->assertTrue( $val >= 0 );
+ $self->assertTrue( $val < $size );
+ return $val;
+ };
+ };
+ $comparisonCallback = function ( $a, $b ) {
+ return $a - $b;
+ };
+
+ return array(
+ array(
+ $indexValueCallback( 0 ),
+ 0,
+ $comparisonCallback,
+ 1,
+ false,
+ ),
+ array(
+ $indexValueCallback( 1 ),
+ 1,
+ $comparisonCallback,
+ -1,
+ false,
+ ),
+ array(
+ $indexValueCallback( 1 ),
+ 1,
+ $comparisonCallback,
+ 0,
+ 0,
+ ),
+ array(
+ $indexValueCallback( 1 ),
+ 1,
+ $comparisonCallback,
+ 1,
+ 0,
+ ),
+ array(
+ $indexValueCallback( 2 ),
+ 2,
+ $comparisonCallback,
+ -1,
+ false,
+ ),
+ array(
+ $indexValueCallback( 2 ),
+ 2,
+ $comparisonCallback,
+ 0,
+ 0,
+ ),
+ array(
+ $indexValueCallback( 2 ),
+ 2,
+ $comparisonCallback,
+ 0.5,
+ 0,
+ ),
+ array(
+ $indexValueCallback( 2 ),
+ 2,
+ $comparisonCallback,
+ 1,
+ 1,
+ ),
+ array(
+ $indexValueCallback( 2 ),
+ 2,
+ $comparisonCallback,
+ 1.5,
+ 1,
+ ),
+ array(
+ $indexValueCallback( 3 ),
+ 3,
+ $comparisonCallback,
+ 1,
+ 1,
+ ),
+ array(
+ $indexValueCallback( 3 ),
+ 3,
+ $comparisonCallback,
+ 1.5,
+ 1,
+ ),
+ array(
+ $indexValueCallback( 3 ),
+ 3,
+ $comparisonCallback,
+ 2,
+ 2,
+ ),
+ array(
+ $indexValueCallback( 3 ),
+ 3,
+ $comparisonCallback,
+ 3,
+ 2,
+ ),
+ );
+ }
+
+ /**
+ * @covers ArrayUtils::arrayDiffAssocRecursive
+ * @dataProvider provideArrayDiffAssocRecursive
+ */
+ function testArrayDiffAssocRecursive( $expected ) {
+ $args = func_get_args();
+ array_shift( $args );
+ $this->assertEquals( call_user_func_array(
+ 'ArrayUtils::arrayDiffAssocRecursive', $args
+ ), $expected );
+ }
+
+ function provideArrayDiffAssocRecursive() {
+ return array(
+ array(
+ array(),
+ array(),
+ array(),
+ ),
+ array(
+ array(),
+ array(),
+ array(),
+ array(),
+ ),
+ array(
+ array( 1 ),
+ array( 1 ),
+ array(),
+ ),
+ array(
+ array( 1 ),
+ array( 1 ),
+ array(),
+ array(),
+ ),
+ array(
+ array(),
+ array(),
+ array( 1 ),
+ ),
+ array(
+ array(),
+ array(),
+ array( 1 ),
+ array( 2 ),
+ ),
+ array(
+ array( '' => 1 ),
+ array( '' => 1 ),
+ array(),
+ ),
+ array(
+ array(),
+ array(),
+ array( '' => 1 ),
+ ),
+ array(
+ array( 1 ),
+ array( 1 ),
+ array( 2 ),
+ ),
+ array(
+ array(),
+ array( 1 ),
+ array( 2 ),
+ array( 1 ),
+ ),
+ array(
+ array(),
+ array( 1 ),
+ array( 1, 2 ),
+ ),
+ array(
+ array( 1 => 1 ),
+ array( 1 => 1 ),
+ array( 1 ),
+ ),
+ array(
+ array(),
+ array( 1 => 1 ),
+ array( 1 ),
+ array( 1 => 1),
+ ),
+ array(
+ array(),
+ array( 1 => 1 ),
+ array( 1, 1, 1 ),
+ ),
+ array(
+ array(),
+ array( array() ),
+ array(),
+ ),
+ array(
+ array(),
+ array( array( array() ) ),
+ array(),
+ ),
+ array(
+ array( 1, array( 1 ) ),
+ array( 1, array( 1 ) ),
+ array(),
+ ),
+ array(
+ array( 1 ),
+ array( 1, array( 1 ) ),
+ array( 2, array( 1 ) ),
+ ),
+ array(
+ array(),
+ array( 1, array( 1 ) ),
+ array( 2, array( 1 ) ),
+ array( 1, array( 2 ) ),
+ ),
+ array(
+ array( 1 ),
+ array( 1, array() ),
+ array( 2 ),
+ ),
+ array(
+ array(),
+ array( 1, array() ),
+ array( 2 ),
+ array( 1 ),
+ ),
+ array(
+ array( 1, array( 1 => 2 ) ),
+ array( 1, array( 1, 2 ) ),
+ array( 2, array( 1 ) ),
+ ),
+ array(
+ array( 1 ),
+ array( 1, array( 1, 2 ) ),
+ array( 2, array( 1 ) ),
+ array( 2, array( 1 => 2 ) ),
+ ),
+ array(
+ array( 1 => array( 1, 2 ) ),
+ array( 1, array( 1, 2 ) ),
+ array( 1, array( 2 ) ),
+ ),
+ array(
+ array( 1 => array( array( 2, 3 ), 2 ) ),
+ array( 1, array( array( 2, 3 ), 2 ) ),
+ array( 1, array( 2 ) ),
+ ),
+ array(
+ array( 1 => array( array( 2 ), 2 ) ),
+ array( 1, array( array( 2, 3 ), 2 ) ),
+ array( 1, array( array( 1 => 3 ) ) ),
+ ),
+ array(
+ array( 1 => array( 1 => 2 ) ),
+ array( 1, array( array( 2, 3 ), 2 ) ),
+ array( 1, array( array( 1 => 3, 0 => 2 ) ) ),
+ ),
+ array(
+ array( 1 => array( 1 => 2 ) ),
+ array( 1, array( array( 2, 3 ), 2 ) ),
+ array( 1, array( array( 1 => 3 ) ) ),
+ array( 1 => array( array( 2 ) ) ),
+ ),
+ array(
+ array(),
+ array( 1, array( array( 2, 3 ), 2 ) ),
+ array( 1 => array( 1 => 2, 0 => array( 1 => 3, 0 => 2 ) ), 0 => 1 ),
+ ),
+ array(
+ array(),
+ array( 1, array( array( 2, 3 ), 2 ) ),
+ array( 1 => array( 1 => 2 ) ),
+ array( 1 => array( array( 1 => 3 ) ) ),
+ array( 1 => array( array( 2 ) ) ),
+ array( 1 ),
+ ),
+ );
+ }
+}
diff --git a/tests/phpunit/includes/libs/CSSMinTest.php b/tests/phpunit/includes/libs/CSSMinTest.php
index 43c50869..6142f967 100644
--- a/tests/phpunit/includes/libs/CSSMinTest.php
+++ b/tests/phpunit/includes/libs/CSSMinTest.php
@@ -141,15 +141,57 @@ class CSSMinTest extends MediaWikiTestCase {
);
}
+ public static function provideIsRemoteUrl() {
+ return array(
+ array( true, 'http://localhost/w/red.gif?123' ),
+ array( true, 'https://example.org/x.png' ),
+ array( true, '//example.org/x.y.z/image.png' ),
+ array( true, '//localhost/styles.css?query=yes' ),
+ array( true, 'data:image/gif;base64,R0lGODlhAQABAIAAAP8AADAAACwAAAAAAQABAAACAkQBADs=' ),
+ array( false, 'x.gif' ),
+ array( false, '/x.gif' ),
+ array( false, './x.gif' ),
+ array( false, '../x.gif' ),
+ );
+ }
+
+ /**
+ * @dataProvider provideIsRemoteUrl
+ * @cover CSSMin::isRemoteUrl
+ */
+ public function testIsRemoteUrl( $expect, $url ) {
+ $this->assertEquals( CSSMin::isRemoteUrl( $url ), $expect );
+ }
+
+ public static function provideIsLocalUrls() {
+ return array(
+ array( false, 'x.gif' ),
+ array( true, '/x.gif' ),
+ array( false, './x.gif' ),
+ array( false, '../x.gif' ),
+ );
+ }
+
+ /**
+ * @dataProvider provideIsLocalUrls
+ * @cover CSSMin::isLocalUrl
+ */
+ public function testIsLocalUrl( $expect, $url ) {
+ $this->assertEquals( CSSMin::isLocalUrl( $url ), $expect );
+ }
+
public static function provideRemapRemappingCases() {
// red.gif and green.gif are one-pixel 35-byte GIFs.
// large.png is a 35K PNG that should be non-embeddable.
// Full paths start with http://localhost/w/.
// Timestamps in output are replaced with 'timestamp'.
- // data: URIs for red.gif and green.gif
+ // data: URIs for red.gif, green.gif, circle.svg
$red = 'data:image/gif;base64,R0lGODlhAQABAIAAAP8AADAAACwAAAAAAQABAAACAkQBADs=';
$green = 'data:image/gif;base64,R0lGODlhAQABAIAAAACAADAAACwAAAAAAQABAAACAkQBADs=';
+ $svg = 'data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%0A'
+ . '%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D'
+ . '%228%22%3E%0A%3Ccircle%20cx%3D%224%22%20cy%3D%224%22%20r%3D%222%22%2F%3E%0A%3C%2Fsvg%3E%0A';
return array(
array(
@@ -234,6 +276,11 @@ class CSSMinTest extends MediaWikiTestCase {
"foo { background: url(http://localhost/w/large.png?timestamp); }",
),
array(
+ 'SVG files are embedded without base64 encoding and unnecessary IE 6 and 7 fallback',
+ 'foo { /* @embed */ background: url(circle.svg); }',
+ "foo { background: url($svg); }",
+ ),
+ array(
'Two regular files in one rule',
'foo { background: url(red.gif), url(green.gif); }',
'foo { background: url(http://localhost/w/red.gif?timestamp), '
diff --git a/tests/phpunit/includes/libs/DeferredStringifierTest.php b/tests/phpunit/includes/libs/DeferredStringifierTest.php
new file mode 100644
index 00000000..8b7610ae
--- /dev/null
+++ b/tests/phpunit/includes/libs/DeferredStringifierTest.php
@@ -0,0 +1,50 @@
+<?php
+
+class DeferredStringifierTest extends PHPUnit_Framework_TestCase {
+
+ /**
+ * @covers DeferredStringifier
+ * @dataProvider provideToString
+ */
+ public function testToString( $params, $expected ) {
+ $class = new ReflectionClass( 'DeferredStringifier' );
+ $ds = $class->newInstanceArgs( $params );
+ $this->assertEquals( $expected, (string)$ds );
+ }
+
+ public static function provideToString() {
+ return array(
+ // No args
+ array(
+ array(
+ function() {
+ return 'foo';
+ }
+ ),
+ 'foo'
+ ),
+ // Has args
+ array(
+ array(
+ function( $i ) {
+ return $i;
+ },
+ 'bar'
+ ),
+ 'bar'
+ ),
+ );
+ }
+
+ /**
+ * Verify that the callback is not called if
+ * it is never converted to a string
+ */
+ public function testCallbackNotCalled() {
+ $ds = new DeferredStringifier( function() {
+ throw new Exception( 'This should not be reached!' );
+ } );
+ // No exception was thrown
+ $this->assertTrue( true );
+ }
+}
diff --git a/tests/phpunit/includes/libs/GenericArrayObjectTest.php b/tests/phpunit/includes/libs/GenericArrayObjectTest.php
index 4911f73a..315bc7ed 100644
--- a/tests/phpunit/includes/libs/GenericArrayObjectTest.php
+++ b/tests/phpunit/includes/libs/GenericArrayObjectTest.php
@@ -24,10 +24,9 @@
* @ingroup Test
* @group GenericArrayObject
*
- * @licence GNU GPL v2+
* @author Jeroen De Dauw < jeroendedauw@gmail.com >
*/
-abstract class GenericArrayObjectTest extends MediaWikiTestCase {
+abstract class GenericArrayObjectTest extends PHPUnit_Framework_TestCase {
/**
* Returns objects that can serve as elements in the concrete
diff --git a/tests/phpunit/includes/libs/HashRingTest.php b/tests/phpunit/includes/libs/HashRingTest.php
index 68dfea1f..b51eb3f4 100644
--- a/tests/phpunit/includes/libs/HashRingTest.php
+++ b/tests/phpunit/includes/libs/HashRingTest.php
@@ -3,7 +3,7 @@
/**
* @group HashRing
*/
-class HashRingTest extends MediaWikiTestCase {
+class HashRingTest extends PHPUnit_Framework_TestCase {
/**
* @covers HashRing
*/
diff --git a/tests/phpunit/includes/libs/IEUrlExtensionTest.php b/tests/phpunit/includes/libs/IEUrlExtensionTest.php
index b7071230..e96953ee 100644
--- a/tests/phpunit/includes/libs/IEUrlExtensionTest.php
+++ b/tests/phpunit/includes/libs/IEUrlExtensionTest.php
@@ -5,7 +5,7 @@
* @todo tests below for findIE6Extension should be split into...
* ...a dataprovider and test method.
*/
-class IEUrlExtensionTest extends MediaWikiTestCase {
+class IEUrlExtensionTest extends PHPUnit_Framework_TestCase {
/**
* @covers IEUrlExtension::findIE6Extension
*/
diff --git a/tests/phpunit/includes/libs/IPSetTest.php b/tests/phpunit/includes/libs/IPSetTest.php
index d4e5214a..5bbacef4 100644
--- a/tests/phpunit/includes/libs/IPSetTest.php
+++ b/tests/phpunit/includes/libs/IPSetTest.php
@@ -3,7 +3,7 @@
/**
* @group IPSet
*/
-class IPSetTest extends MediaWikiTestCase {
+class IPSetTest extends PHPUnit_Framework_TestCase {
/**
* Provides test cases for IPSetTest::testIPSet
*
diff --git a/tests/phpunit/includes/libs/JavaScriptMinifierTest.php b/tests/phpunit/includes/libs/JavaScriptMinifierTest.php
index c8795b2e..149a28c1 100644
--- a/tests/phpunit/includes/libs/JavaScriptMinifierTest.php
+++ b/tests/phpunit/includes/libs/JavaScriptMinifierTest.php
@@ -1,6 +1,6 @@
<?php
-class JavaScriptMinifierTest extends MediaWikiTestCase {
+class JavaScriptMinifierTest extends PHPUnit_Framework_TestCase {
public static function provideCases() {
return array(
@@ -164,7 +164,7 @@ class JavaScriptMinifierTest extends MediaWikiTestCase {
);
}
- public static function provideBug32548() {
+ public static function provideExponentLineBreaking() {
return array(
array(
// This one gets interpreted all together by the prior code;
@@ -183,14 +183,13 @@ class JavaScriptMinifierTest extends MediaWikiTestCase {
}
/**
- * @dataProvider provideBug32548
+ * @dataProvider provideExponentLineBreaking
* @covers JavaScriptMinifier::minify
- * @todo give this test a real name explaining what is being tested here
*/
- public function testBug32548Exponent( $num ) {
+ public function testExponentLineBreaking( $num ) {
// Long line breaking was being incorrectly done between the base and
// exponent part of a number, causing a syntax error. The line should
- // instead break at the start of the number.
+ // instead break at the start of the number. (T34548)
$prefix = 'var longVarName' . str_repeat( '_', 973 ) . '=';
$suffix = ',shortVarName=0;';
diff --git a/tests/phpunit/includes/libs/MWMessagePackTest.php b/tests/phpunit/includes/libs/MWMessagePackTest.php
index f80f78df..ec145836 100644
--- a/tests/phpunit/includes/libs/MWMessagePackTest.php
+++ b/tests/phpunit/includes/libs/MWMessagePackTest.php
@@ -3,7 +3,7 @@
* PHP Unit tests for MWMessagePack
* @covers MWMessagePack
*/
-class MWMessagePackTest extends MediaWikiTestCase {
+class MWMessagePackTest extends PHPUnit_Framework_TestCase {
/**
* Provides test cases for MWMessagePackTest::testMessagePack
diff --git a/tests/phpunit/includes/libs/ObjectFactoryTest.php b/tests/phpunit/includes/libs/ObjectFactoryTest.php
new file mode 100644
index 00000000..92207325
--- /dev/null
+++ b/tests/phpunit/includes/libs/ObjectFactoryTest.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+class ObjectFactoryTest extends PHPUnit_Framework_TestCase {
+
+ /**
+ * @covers ObjectFactory::getObjectFromSpec
+ */
+ public function testClosureExpansionDisabled() {
+ $obj = ObjectFactory::getObjectFromSpec( array(
+ 'class' => 'ObjectFactoryTest_Fixture',
+ 'args' => array( function (){ return 'unwrapped'; }, ),
+ 'closure_expansion' => false,
+ ) );
+ $this->assertInstanceOf( 'Closure', $obj->args[0] );
+ $this->assertSame( 'unwrapped', $obj->args[0]() );
+ }
+
+ /**
+ * @covers ObjectFactory::getObjectFromSpec
+ */
+ public function testClosureExpansionEnabled() {
+ $obj = ObjectFactory::getObjectFromSpec( array(
+ 'class' => 'ObjectFactoryTest_Fixture',
+ 'args' => array( function (){ return 'unwrapped'; }, ),
+ 'closure_expansion' => true,
+ ) );
+ $this->assertInternalType( 'string', $obj->args[0] );
+ $this->assertSame( 'unwrapped', $obj->args[0] );
+
+ $obj = ObjectFactory::getObjectFromSpec( array(
+ 'class' => 'ObjectFactoryTest_Fixture',
+ 'args' => array( function (){ return 'unwrapped'; }, ),
+ ) );
+ $this->assertInternalType( 'string', $obj->args[0] );
+ $this->assertSame( 'unwrapped', $obj->args[0] );
+ }
+}
+
+class ObjectFactoryTest_Fixture {
+ public $args;
+ public function __construct( /*...*/ ) { $this->args = func_get_args(); }
+}
diff --git a/tests/phpunit/includes/libs/ProcessCacheLRUTest.php b/tests/phpunit/includes/libs/ProcessCacheLRUTest.php
index 1a8a1e56..43001979 100644
--- a/tests/phpunit/includes/libs/ProcessCacheLRUTest.php
+++ b/tests/phpunit/includes/libs/ProcessCacheLRUTest.php
@@ -9,20 +9,20 @@
*
* @group Cache
*/
-class ProcessCacheLRUTest extends MediaWikiTestCase {
+class ProcessCacheLRUTest extends PHPUnit_Framework_TestCase {
/**
* Helper to verify emptiness of a cache object.
* Compare against an array so we get the cache content difference.
*/
- function assertCacheEmpty( $cache, $msg = 'Cache should be empty' ) {
+ protected function assertCacheEmpty( $cache, $msg = 'Cache should be empty' ) {
$this->assertAttributeEquals( array(), 'cache', $cache, $msg );
}
/**
* Helper to fill a cache object passed by reference
*/
- function fillCache( &$cache, $numEntries ) {
+ protected function fillCache( &$cache, $numEntries ) {
// Fill cache with three values
for ( $i = 1; $i <= $numEntries; $i++ ) {
$cache->set( "cache-key-$i", "prop-$i", "value-$i" );
@@ -33,17 +33,17 @@ class ProcessCacheLRUTest extends MediaWikiTestCase {
* Generates an array of what would be expected in cache for a given cache
* size and a number of entries filled in sequentially
*/
- function getExpectedCache( $cacheMaxEntries, $entryToFill ) {
+ protected function getExpectedCache( $cacheMaxEntries, $entryToFill ) {
$expected = array();
if ( $entryToFill === 0 ) {
- # The cache is empty!
+ // The cache is empty!
return array();
} elseif ( $entryToFill <= $cacheMaxEntries ) {
- # Cache is not fully filled
+ // Cache is not fully filled
$firstKey = 1;
} else {
- # Cache overflowed
+ // Cache overflowed
$firstKey = 1 + $entryToFill - $cacheMaxEntries;
}
@@ -62,13 +62,16 @@ class ProcessCacheLRUTest extends MediaWikiTestCase {
public function testPhpUnitArrayEquality() {
$one = array( 'A' => 1, 'B' => 2 );
$two = array( 'B' => 2, 'A' => 1 );
- $this->assertEquals( $one, $two ); // ==
- $this->assertNotSame( $one, $two ); // ===
+ // ==
+ $this->assertEquals( $one, $two );
+ // ===
+ $this->assertNotSame( $one, $two );
}
/**
* @dataProvider provideInvalidConstructorArg
* @expectedException UnexpectedValueException
+ * @covers ProcessCacheLRU::__construct
*/
public function testConstructorGivenInvalidValue( $maxSize ) {
new ProcessCacheLRUTestable( $maxSize );
@@ -88,6 +91,11 @@ class ProcessCacheLRUTest extends MediaWikiTestCase {
);
}
+ /**
+ * @covers ProcessCacheLRU::get
+ * @covers ProcessCacheLRU::set
+ * @covers ProcessCacheLRU::het
+ */
public function testAddAndGetAKey() {
$oneCache = new ProcessCacheLRUTestable( 1 );
$this->assertCacheEmpty( $oneCache );
@@ -99,6 +107,10 @@ class ProcessCacheLRUTest extends MediaWikiTestCase {
$this->assertEquals( 'value1', $oneCache->get( 'cache-key', 'prop1' ) );
}
+ /**
+ * @covers ProcessCacheLRU::set
+ * @covers ProcessCacheLRU::get
+ */
public function testDeleteOldKey() {
$oneCache = new ProcessCacheLRUTestable( 1 );
$this->assertCacheEmpty( $oneCache );
@@ -113,6 +125,7 @@ class ProcessCacheLRUTest extends MediaWikiTestCase {
* a sequence of always different cache-keys. Meant to verify we correclty
* delete the older key.
*
+ * @covers ProcessCacheLRU::set
* @dataProvider provideCacheFilling
* @param int $cacheMaxEntries Maximum entry the created cache will hold
* @param int $entryToFill Number of entries to insert in the created cache.
@@ -136,14 +149,18 @@ class ProcessCacheLRUTest extends MediaWikiTestCase {
return array(
array( 1, 0 ),
array( 1, 1 ),
- array( 1, 2 ), # overflow
- array( 5, 33 ), # overflow
+ // overflow
+ array( 1, 2 ),
+ // overflow
+ array( 5, 33 ),
);
}
/**
* Create a cache with only one remaining entry then update
* the first inserted entry. Should bump it to the top.
+ *
+ * @covers ProcessCacheLRU::set
*/
public function testReplaceExistingKeyShouldBumpEntryToTop() {
$maxEntries = 3;
@@ -164,6 +181,11 @@ class ProcessCacheLRUTest extends MediaWikiTestCase {
);
}
+ /**
+ * @covers ProcessCacheLRU::get
+ * @covers ProcessCacheLRU::set
+ * @covers ProcessCacheLRU::het
+ */
public function testRecentlyAccessedKeyStickIn() {
$cache = new ProcessCacheLRUTestable( 2 );
$cache->set( 'first', 'prop1', 'value1' );
@@ -182,6 +204,9 @@ class ProcessCacheLRUTest extends MediaWikiTestCase {
* filled entry.
* Given a cache having 1,2,3 as key, updating 2 should bump 2 to
* the top of the queue with the new value: 1,3,2* (* = updated).
+ *
+ * @covers ProcessCacheLRU::set
+ * @covers ProcessCacheLRU::get
*/
public function testReplaceExistingKeyInAFullCacheShouldBumpToTop() {
$maxEntries = 3;
@@ -204,6 +229,9 @@ class ProcessCacheLRUTest extends MediaWikiTestCase {
);
}
+ /**
+ * @covers ProcessCacheLRU::set
+ */
public function testBumpExistingKeyToTop() {
$cache = new ProcessCacheLRUTestable( 3 );
$this->fillCache( $cache, 3 );
diff --git a/tests/phpunit/includes/libs/RunningStatTest.php b/tests/phpunit/includes/libs/RunningStatTest.php
index dc5db82c..edfaf162 100644
--- a/tests/phpunit/includes/libs/RunningStatTest.php
+++ b/tests/phpunit/includes/libs/RunningStatTest.php
@@ -3,7 +3,7 @@
* PHP Unit tests for RunningStat class.
* @covers RunningStat
*/
-class RunningStatTest extends MediaWikiTestCase {
+class RunningStatTest extends PHPUnit_Framework_TestCase {
public $points = array(
49.7168, 74.3804, 7.0115, 96.5769, 34.9458,
diff --git a/tests/phpunit/includes/libs/StringUtilsTest.php b/tests/phpunit/includes/libs/StringUtilsTest.php
new file mode 100644
index 00000000..7c24fae6
--- /dev/null
+++ b/tests/phpunit/includes/libs/StringUtilsTest.php
@@ -0,0 +1,149 @@
+<?php
+
+class StringUtilsTest extends PHPUnit_Framework_TestCase {
+
+ /**
+ * This tests StringUtils::isUtf8 whenever we have the mbstring extension
+ * loaded.
+ *
+ * @covers StringUtils::isUtf8
+ * @dataProvider provideStringsForIsUtf8Check
+ */
+ public function testIsUtf8WithMbstring( $expected, $string ) {
+ if ( !function_exists( 'mb_check_encoding' ) ) {
+ $this->markTestSkipped( 'Test requires the mbstring PHP extension' );
+ }
+ $this->assertEquals( $expected,
+ StringUtils::isUtf8( $string ),
+ 'Testing string "' . $this->escaped( $string ) . '" with mb_check_encoding'
+ );
+ }
+
+ /**
+ * This tests StringUtils::isUtf8 making sure we use the pure PHP
+ * implementation used as a fallback when mb_check_encoding() is
+ * not available.
+ *
+ * @covers StringUtils::isUtf8
+ * @dataProvider provideStringsForIsUtf8Check
+ */
+ public function testIsUtf8WithPhpFallbackImplementation( $expected, $string ) {
+ $this->assertEquals( $expected,
+ StringUtils::isUtf8( $string, /** disable mbstring: */true ),
+ 'Testing string "' . $this->escaped( $string ) . '" with pure PHP implementation'
+ );
+ }
+
+ /**
+ * Print high range characters as a hexadecimal
+ * @param string $string
+ * @return string
+ */
+ function escaped( $string ) {
+ $escaped = '';
+ $length = strlen( $string );
+ for ( $i = 0; $i < $length; $i++ ) {
+ $char = $string[$i];
+ $val = ord( $char );
+ if ( $val > 127 ) {
+ $escaped .= '\x' . dechex( $val );
+ } else {
+ $escaped .= $char;
+ }
+ }
+
+ return $escaped;
+ }
+
+ /**
+ * See also "UTF-8 decoder capability and stress test" by
+ * Markus Kuhn:
+ * http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
+ */
+ public static function provideStringsForIsUtf8Check() {
+ // Expected return values for StringUtils::isUtf8()
+ $PASS = true;
+ $FAIL = false;
+
+ return array(
+ 'some ASCII' => array( $PASS, 'Some ASCII' ),
+ 'euro sign' => array( $PASS, "Euro sign €" ),
+
+ 'first possible sequence 1 byte' => array( $PASS, "\x00" ),
+ 'first possible sequence 2 bytes' => array( $PASS, "\xc2\x80" ),
+ 'first possible sequence 3 bytes' => array( $PASS, "\xe0\xa0\x80" ),
+ 'first possible sequence 4 bytes' => array( $PASS, "\xf0\x90\x80\x80" ),
+ 'first possible sequence 5 bytes' => array( $FAIL, "\xf8\x88\x80\x80\x80" ),
+ 'first possible sequence 6 bytes' => array( $FAIL, "\xfc\x84\x80\x80\x80\x80" ),
+
+ 'last possible sequence 1 byte' => array( $PASS, "\x7f" ),
+ 'last possible sequence 2 bytes' => array( $PASS, "\xdf\xbf" ),
+ 'last possible sequence 3 bytes' => array( $PASS, "\xef\xbf\xbf" ),
+ 'last possible sequence 4 bytes (U+1FFFFF)' => array( $FAIL, "\xf7\xbf\xbf\xbf" ),
+ 'last possible sequence 5 bytes' => array( $FAIL, "\xfb\xbf\xbf\xbf\xbf" ),
+ 'last possible sequence 6 bytes' => array( $FAIL, "\xfd\xbf\xbf\xbf\xbf\xbf" ),
+
+ 'boundary 1' => array( $PASS, "\xed\x9f\xbf" ),
+ 'boundary 2' => array( $PASS, "\xee\x80\x80" ),
+ 'boundary 3' => array( $PASS, "\xef\xbf\xbd" ),
+ 'boundary 4' => array( $PASS, "\xf2\x80\x80\x80" ),
+ 'boundary 5 (U+FFFFF)' => array( $PASS, "\xf3\xbf\xbf\xbf" ),
+ 'boundary 6 (U+100000)' => array( $PASS, "\xf4\x80\x80\x80" ),
+ 'boundary 7 (U+10FFFF)' => array( $PASS, "\xf4\x8f\xbf\xbf" ),
+ 'boundary 8 (U+110000)' => array( $FAIL, "\xf4\x90\x80\x80" ),
+
+ 'malformed 1' => array( $FAIL, "\x80" ),
+ 'malformed 2' => array( $FAIL, "\xbf" ),
+ 'malformed 3' => array( $FAIL, "\x80\xbf" ),
+ 'malformed 4' => array( $FAIL, "\x80\xbf\x80" ),
+ 'malformed 5' => array( $FAIL, "\x80\xbf\x80\xbf" ),
+ 'malformed 6' => array( $FAIL, "\x80\xbf\x80\xbf\x80" ),
+ 'malformed 7' => array( $FAIL, "\x80\xbf\x80\xbf\x80\xbf" ),
+ 'malformed 8' => array( $FAIL, "\x80\xbf\x80\xbf\x80\xbf\x80" ),
+
+ 'last byte missing 1' => array( $FAIL, "\xc0" ),
+ 'last byte missing 2' => array( $FAIL, "\xe0\x80" ),
+ 'last byte missing 3' => array( $FAIL, "\xf0\x80\x80" ),
+ 'last byte missing 4' => array( $FAIL, "\xf8\x80\x80\x80" ),
+ 'last byte missing 5' => array( $FAIL, "\xfc\x80\x80\x80\x80" ),
+ 'last byte missing 6' => array( $FAIL, "\xdf" ),
+ 'last byte missing 7' => array( $FAIL, "\xef\xbf" ),
+ 'last byte missing 8' => array( $FAIL, "\xf7\xbf\xbf" ),
+ 'last byte missing 9' => array( $FAIL, "\xfb\xbf\xbf\xbf" ),
+ 'last byte missing 10' => array( $FAIL, "\xfd\xbf\xbf\xbf\xbf" ),
+
+ 'extra continuation byte 1' => array( $FAIL, "e\xaf" ),
+ 'extra continuation byte 2' => array( $FAIL, "\xc3\x89\xaf" ),
+ 'extra continuation byte 3' => array( $FAIL, "\xef\xbc\xa5\xaf" ),
+ 'extra continuation byte 4' => array( $FAIL, "\xf0\x9d\x99\xb4\xaf" ),
+
+ 'impossible bytes 1' => array( $FAIL, "\xfe" ),
+ 'impossible bytes 2' => array( $FAIL, "\xff" ),
+ 'impossible bytes 3' => array( $FAIL, "\xfe\xfe\xff\xff" ),
+
+ 'overlong sequences 1' => array( $FAIL, "\xc0\xaf" ),
+ 'overlong sequences 2' => array( $FAIL, "\xc1\xaf" ),
+ 'overlong sequences 3' => array( $FAIL, "\xe0\x80\xaf" ),
+ 'overlong sequences 4' => array( $FAIL, "\xf0\x80\x80\xaf" ),
+ 'overlong sequences 5' => array( $FAIL, "\xf8\x80\x80\x80\xaf" ),
+ 'overlong sequences 6' => array( $FAIL, "\xfc\x80\x80\x80\x80\xaf" ),
+
+ 'maximum overlong sequences 1' => array( $FAIL, "\xc1\xbf" ),
+ 'maximum overlong sequences 2' => array( $FAIL, "\xe0\x9f\xbf" ),
+ 'maximum overlong sequences 3' => array( $FAIL, "\xf0\x8f\xbf\xbf" ),
+ 'maximum overlong sequences 4' => array( $FAIL, "\xf8\x87\xbf\xbf" ),
+ 'maximum overlong sequences 5' => array( $FAIL, "\xfc\x83\xbf\xbf\xbf\xbf" ),
+
+ 'surrogates 1 (U+D799)' => array( $PASS, "\xed\x9f\xbf" ),
+ 'surrogates 2 (U+E000)' => array( $PASS, "\xee\x80\x80" ),
+ 'surrogates 3 (U+D800)' => array( $FAIL, "\xed\xa0\x80" ),
+ 'surrogates 4 (U+DBFF)' => array( $FAIL, "\xed\xaf\xbf" ),
+ 'surrogates 5 (U+DC00)' => array( $FAIL, "\xed\xb0\x80" ),
+ 'surrogates 6 (U+DFFF)' => array( $FAIL, "\xed\xbf\xbf" ),
+ 'surrogates 7 (U+D800 U+DC00)' => array( $FAIL, "\xed\xa0\x80\xed\xb0\x80" ),
+
+ 'noncharacters 1' => array( $PASS, "\xef\xbf\xbe" ),
+ 'noncharacters 2' => array( $PASS, "\xef\xbf\xbf" ),
+ );
+ }
+}
diff --git a/tests/phpunit/includes/libs/XhprofTest.php b/tests/phpunit/includes/libs/XhprofTest.php
new file mode 100644
index 00000000..2440fc08
--- /dev/null
+++ b/tests/phpunit/includes/libs/XhprofTest.php
@@ -0,0 +1,320 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+/**
+ * @uses Xhprof
+ * @uses AutoLoader
+ * @author Bryan Davis <bd808@wikimedia.org>
+ * @copyright © 2014 Bryan Davis and Wikimedia Foundation.
+ * @since 1.25
+ */
+class XhprofTest extends PHPUnit_Framework_TestCase {
+
+ public function setUp() {
+ if ( !function_exists( 'xhprof_enable' ) ) {
+ $this->markTestSkipped( 'No xhprof support detected.' );
+ }
+ }
+
+ /**
+ * @covers Xhprof::splitKey
+ * @dataProvider provideSplitKey
+ */
+ public function testSplitKey( $key, $expect ) {
+ $this->assertSame( $expect, Xhprof::splitKey( $key ) );
+ }
+
+ public function provideSplitKey() {
+ return array(
+ array( 'main()', array( null, 'main()' ) ),
+ array( 'foo==>bar', array( 'foo', 'bar' ) ),
+ array( 'bar@1==>bar@2', array( 'bar@1', 'bar@2' ) ),
+ array( 'foo==>bar==>baz', array( 'foo', 'bar==>baz' ) ),
+ array( '==>bar', array( '', 'bar' ) ),
+ array( '', array( null, '' ) ),
+ );
+ }
+
+ /**
+ * @covers Xhprof::__construct
+ * @covers Xhprof::stop
+ * @covers Xhprof::getRawData
+ * @dataProvider provideRawData
+ */
+ public function testRawData( $flags, $keys ) {
+ $xhprof = new Xhprof( array( 'flags' => $flags ) );
+ $raw = $xhprof->getRawData();
+ $this->assertArrayHasKey( 'main()', $raw );
+ foreach ( $keys as $key ) {
+ $this->assertArrayHasKey( $key, $raw['main()'] );
+ }
+ }
+
+ public function provideRawData() {
+ $tests = array(
+ array( 0, array( 'ct', 'wt' ) ),
+ );
+
+ if ( defined( 'XHPROF_FLAGS_CPU' ) && defined( 'XHPROF_FLAGS_CPU' ) ) {
+ $tests[] = array( XHPROF_FLAGS_MEMORY, array(
+ 'ct', 'wt', 'mu', 'pmu',
+ ) );
+ $tests[] = array( XHPROF_FLAGS_CPU, array(
+ 'ct', 'wt', 'cpu',
+ ) );
+ $tests[] = array( XHPROF_FLAGS_MEMORY | XHPROF_FLAGS_CPU, array(
+ 'ct', 'wt', 'mu', 'pmu', 'cpu',
+ ) );
+ }
+
+ return $tests;
+ }
+
+ /**
+ * @covers Xhprof::pruneData
+ */
+ public function testInclude() {
+ $xhprof = $this->getXhprofFixture( array(
+ 'include' => array( 'main()' ),
+ ) );
+ $raw = $xhprof->getRawData();
+ $this->assertArrayHasKey( 'main()', $raw );
+ $this->assertArrayHasKey( 'main()==>foo', $raw );
+ $this->assertArrayHasKey( 'main()==>xhprof_disable', $raw );
+ $this->assertSame( 3, count( $raw ) );
+ }
+
+ /**
+ * Validate the structure of data returned by
+ * Xhprof::getInclusiveMetrics(). This acts as a guard against unexpected
+ * structural changes to the returned data in lieu of using a more heavy
+ * weight typed response object.
+ *
+ * @covers Xhprof::getInclusiveMetrics
+ */
+ public function testInclusiveMetricsStructure() {
+ $metricStruct = array(
+ 'ct' => 'int',
+ 'wt' => 'array',
+ 'cpu' => 'array',
+ 'mu' => 'array',
+ 'pmu' => 'array',
+ );
+ $statStruct = array(
+ 'total' => 'numeric',
+ 'min' => 'numeric',
+ 'mean' => 'numeric',
+ 'max' => 'numeric',
+ 'variance' => 'numeric',
+ 'percent' => 'numeric',
+ );
+
+ $xhprof = $this->getXhprofFixture();
+ $metrics = $xhprof->getInclusiveMetrics();
+
+ foreach ( $metrics as $name => $metric ) {
+ $this->assertArrayStructure( $metricStruct, $metric );
+
+ foreach ( $metricStruct as $key => $type ) {
+ if ( $type === 'array' ) {
+ $this->assertArrayStructure( $statStruct, $metric[$key] );
+ if ( $name === 'main()' ) {
+ $this->assertEquals( 100, $metric[$key]['percent'] );
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Validate the structure of data returned by
+ * Xhprof::getCompleteMetrics(). This acts as a guard against unexpected
+ * structural changes to the returned data in lieu of using a more heavy
+ * weight typed response object.
+ *
+ * @covers Xhprof::getCompleteMetrics
+ */
+ public function testCompleteMetricsStructure() {
+ $metricStruct = array(
+ 'ct' => 'int',
+ 'wt' => 'array',
+ 'cpu' => 'array',
+ 'mu' => 'array',
+ 'pmu' => 'array',
+ 'calls' => 'array',
+ 'subcalls' => 'array',
+ );
+ $statsMetrics = array( 'wt', 'cpu', 'mu', 'pmu' );
+ $statStruct = array(
+ 'total' => 'numeric',
+ 'min' => 'numeric',
+ 'mean' => 'numeric',
+ 'max' => 'numeric',
+ 'variance' => 'numeric',
+ 'percent' => 'numeric',
+ 'exclusive' => 'numeric',
+ );
+
+ $xhprof = $this->getXhprofFixture();
+ $metrics = $xhprof->getCompleteMetrics();
+
+ foreach ( $metrics as $name => $metric ) {
+ $this->assertArrayStructure( $metricStruct, $metric, $name );
+
+ foreach ( $metricStruct as $key => $type ) {
+ if ( in_array( $key, $statsMetrics ) ) {
+ $this->assertArrayStructure(
+ $statStruct, $metric[$key], $key
+ );
+ $this->assertLessThanOrEqual(
+ $metric[$key]['total'], $metric[$key]['exclusive']
+ );
+ }
+ }
+ }
+ }
+
+ /**
+ * @covers Xhprof::getCallers
+ * @covers Xhprof::getCallees
+ * @uses Xhprof
+ */
+ public function testEdges() {
+ $xhprof = $this->getXhprofFixture();
+ $this->assertSame( array(), $xhprof->getCallers( 'main()' ) );
+ $this->assertSame( array( 'foo', 'xhprof_disable' ),
+ $xhprof->getCallees( 'main()' )
+ );
+ $this->assertSame( array( 'main()' ),
+ $xhprof->getCallers( 'foo' )
+ );
+ $this->assertSame( array(), $xhprof->getCallees( 'strlen' ) );
+ }
+
+ /**
+ * @covers Xhprof::getCriticalPath
+ * @uses Xhprof
+ */
+ public function testCriticalPath() {
+ $xhprof = $this->getXhprofFixture();
+ $path = $xhprof->getCriticalPath();
+
+ $last = null;
+ foreach ( $path as $key => $value ) {
+ list( $func, $call ) = Xhprof::splitKey( $key );
+ $this->assertSame( $last, $func );
+ $last = $call;
+ }
+ $this->assertSame( $last, 'bar@1' );
+ }
+
+ /**
+ * Get an Xhprof instance that has been primed with a set of known testing
+ * data. Tests for the Xhprof class should laregly be concerned with
+ * evaluating the manipulations of the data collected by xhprof rather
+ * than the data collection process itself.
+ *
+ * The returned Xhprof instance primed will be with a data set created by
+ * running this trivial program using the PECL xhprof implementation:
+ * @code
+ * function bar( $x ) {
+ * if ( $x > 0 ) {
+ * bar($x - 1);
+ * }
+ * }
+ * function foo() {
+ * for ( $idx = 0; $idx < 2; $idx++ ) {
+ * bar( $idx );
+ * $x = strlen( 'abc' );
+ * }
+ * }
+ * xhprof_enable( XHPROF_FLAGS_CPU | XHPROF_FLAGS_MEMORY );
+ * foo();
+ * $x = xhprof_disable();
+ * var_export( $x );
+ * @endcode
+ *
+ * @return Xhprof
+ */
+ protected function getXhprofFixture( array $opts = array() ) {
+ $xhprof = new Xhprof( $opts );
+ $xhprof->loadRawData( array (
+ 'foo==>bar' => array (
+ 'ct' => 2,
+ 'wt' => 57,
+ 'cpu' => 92,
+ 'mu' => 1896,
+ 'pmu' => 0,
+ ),
+ 'foo==>strlen' => array (
+ 'ct' => 2,
+ 'wt' => 21,
+ 'cpu' => 141,
+ 'mu' => 752,
+ 'pmu' => 0,
+ ),
+ 'bar==>bar@1' => array (
+ 'ct' => 1,
+ 'wt' => 18,
+ 'cpu' => 19,
+ 'mu' => 752,
+ 'pmu' => 0,
+ ),
+ 'main()==>foo' => array (
+ 'ct' => 1,
+ 'wt' => 304,
+ 'cpu' => 307,
+ 'mu' => 4008,
+ 'pmu' => 0,
+ ),
+ 'main()==>xhprof_disable' => array (
+ 'ct' => 1,
+ 'wt' => 8,
+ 'cpu' => 10,
+ 'mu' => 768,
+ 'pmu' => 392,
+ ),
+ 'main()' => array (
+ 'ct' => 1,
+ 'wt' => 353,
+ 'cpu' => 351,
+ 'mu' => 6112,
+ 'pmu' => 1424,
+ ),
+ ) );
+ return $xhprof;
+ }
+
+ /**
+ * Assert that the given array has the described structure.
+ *
+ * @param array $struct Array of key => type mappings
+ * @param array $actual Array to check
+ * @param string $label
+ */
+ protected function assertArrayStructure( $struct, $actual, $label = null ) {
+ $this->assertInternalType( 'array', $actual, $label );
+ $this->assertCount( count($struct), $actual, $label );
+ foreach ( $struct as $key => $type ) {
+ $this->assertArrayHasKey( $key, $actual );
+ $this->assertInternalType( $type, $actual[$key] );
+ }
+ }
+}
diff --git a/tests/phpunit/includes/libs/XmlTypeCheckTest.php b/tests/phpunit/includes/libs/XmlTypeCheckTest.php
new file mode 100644
index 00000000..f0ba934e
--- /dev/null
+++ b/tests/phpunit/includes/libs/XmlTypeCheckTest.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * PHPUnit tests for XMLTypeCheck.
+ * @author physikerwelt
+ * @group Xml
+ * @covers XMLTypeCheck
+ */
+class XmlTypeCheckTest extends PHPUnit_Framework_TestCase {
+ const WELL_FORMED_XML = "<root><child /></root>";
+ const MAL_FORMED_XML = "<root><child /></error>";
+ const XML_WITH_PIH = '<?xml version="1.0"?><?xml-stylesheet type="text/xsl" href="/w/index.php"?><svg><child /></svg>';
+
+ /**
+ * @covers XMLTypeCheck::newFromString
+ * @covers XMLTypeCheck::getRootElement
+ */
+ public function testWellFormedXML() {
+ $testXML = XmlTypeCheck::newFromString( self::WELL_FORMED_XML );
+ $this->assertTrue( $testXML->wellFormed );
+ $this->assertEquals( 'root', $testXML->getRootElement() );
+ }
+
+ /**
+ * @covers XMLTypeCheck::newFromString
+ */
+ public function testMalFormedXML() {
+ $testXML = XmlTypeCheck::newFromString( self::MAL_FORMED_XML );
+ $this->assertFalse( $testXML->wellFormed );
+ }
+
+ /**
+ * @covers XMLTypeCheck::processingInstructionHandler
+ */
+ public function testProcessingInstructionHandler() {
+ $called = false;
+ $testXML = new XmlTypeCheck(
+ self::XML_WITH_PIH,
+ null,
+ false,
+ array(
+ 'processing_instruction_handler' => function() use ( &$called ) {
+ $called = true;
+ }
+ )
+ );
+ $this->assertTrue( $called );
+ }
+
+}
diff --git a/tests/phpunit/includes/libs/composer/ComposerJsonTest.php b/tests/phpunit/includes/libs/composer/ComposerJsonTest.php
new file mode 100644
index 00000000..0c58b65a
--- /dev/null
+++ b/tests/phpunit/includes/libs/composer/ComposerJsonTest.php
@@ -0,0 +1,57 @@
+<?php
+
+class ComposerJsonTest extends MediaWikiTestCase {
+
+ private $json, $json2;
+
+ public function setUp() {
+ parent::setUp();
+ global $IP;
+ $this->json = "$IP/tests/phpunit/data/composer/composer.json";
+ $this->json2 = "$IP/tests/phpunit/data/composer/new-composer.json";
+ }
+
+ public static function provideGetHash() {
+ return array(
+ array( 'json', 'cc6e7fc565b246cb30b0cac103a2b31e' ),
+ array( 'json2', '19921dd1fc457f1b00561da932432001' ),
+ );
+ }
+
+ /**
+ * @dataProvider provideGetHash
+ * @covers ComposerJson::getHash
+ */
+ public function testIsHashUpToDate( $file, $expected ) {
+ $json = new ComposerJson( $this->$file );
+ $this->assertEquals( $expected, $json->getHash() );
+ }
+
+ /**
+ * @covers ComposerJson::getRequiredDependencies
+ */
+ public function testGetRequiredDependencies() {
+ $json = new ComposerJson( $this->json );
+ $this->assertArrayEquals( array(
+ 'cdb/cdb' => '1.0.0',
+ 'cssjanus/cssjanus' => '1.1.1',
+ 'leafo/lessphp' => '0.5.0',
+ 'psr/log' => '1.0.0',
+ ), $json->getRequiredDependencies(), false, true );
+ }
+
+ public static function provideNormalizeVersion() {
+ return array(
+ array( 'v1.0.0', '1.0.0' ),
+ array( '0.0.5', '0.0.5' ),
+ );
+ }
+
+ /**
+ * @dataProvider provideNormalizeVersion
+ * @covers ComposerJson::normalizeVersion
+ */
+ public function testNormalizeVersion( $input, $expected ) {
+ $this->assertEquals( $expected, ComposerJson::normalizeVersion( $input ) );
+ }
+}
diff --git a/tests/phpunit/includes/libs/composer/ComposerLockTest.php b/tests/phpunit/includes/libs/composer/ComposerLockTest.php
new file mode 100644
index 00000000..b5fd5f6e
--- /dev/null
+++ b/tests/phpunit/includes/libs/composer/ComposerLockTest.php
@@ -0,0 +1,62 @@
+<?php
+
+class ComposerLockTest extends MediaWikiTestCase {
+
+ private $lock;
+
+ public function setUp() {
+ parent::setUp();
+ global $IP;
+ $this->lock = "$IP/tests/phpunit/data/composer/composer.lock";
+ }
+
+ /**
+ * @covers ComposerLock::getHash
+ */
+ public function testGetHash() {
+ $lock = new ComposerLock( $this->lock );
+ $this->assertEquals( 'a3bb80b0ac4c4a31e52574d48c032923', $lock->getHash() );
+ }
+
+ /**
+ * @covers ComposerLock::getInstalledDependencies
+ */
+ public function testGetInstalledDependencies() {
+ $lock = new ComposerLock( $this->lock );
+ $this->assertArrayEquals( array(
+ 'wikimedia/cdb' => array(
+ 'version' => '1.0.1',
+ 'type' => 'library',
+ ),
+ 'cssjanus/cssjanus' => array(
+ 'version' => '1.1.1',
+ 'type' => 'library',
+ ),
+ 'leafo/lessphp' => array(
+ 'version' => '0.5.0',
+ 'type' => 'library',
+ ),
+ 'psr/log' => array(
+ 'version' => '1.0.0',
+ 'type' => 'library',
+ ),
+ 'oojs/oojs-ui' => array(
+ 'version' => '0.6.0',
+ 'type' => 'library',
+ ),
+ 'composer/installers' => array(
+ 'version' => '1.0.19',
+ 'type' => 'composer-installer',
+ ),
+ 'mediawiki/translate' => array(
+ 'version' => '2014.12',
+ 'type' => 'mediawiki-extension',
+ ),
+ 'mediawiki/universal-language-selector' => array(
+ 'version' => '2014.12',
+ 'type' => 'mediawiki-extension',
+ ),
+ ), $lock->getInstalledDependencies(), false, true );
+ }
+
+}