+++ /dev/null
-<?php
-
-/**
- * Note: this is not a unit test, as it touches the file system and reads an actual file.
- * If unit tests are added for MediaWikiVersionFetcher, this should be done in a distinct test case.
- *
- * @covers MediaWikiVersionFetcher
- *
- * @group ComposerHooks
- *
- * @author Jeroen De Dauw < jeroendedauw@gmail.com >
- */
-class MediaWikiVersionFetcherTest extends MediaWikiTestCase {
-
- public function testReturnsResult() {
- global $wgVersion;
- $versionFetcher = new MediaWikiVersionFetcher();
- $this->assertSame( $wgVersion, $versionFetcher->fetchVersion() );
- }
-
-}
+++ /dev/null
-<?php
-
-namespace MediaWiki\Tests\Rest;
-
-use EmptyBagOStuff;
-use GuzzleHttp\Psr7\Uri;
-use GuzzleHttp\Psr7\Stream;
-use MediaWiki\Rest\Handler;
-use MediaWikiTestCase;
-use MediaWiki\Rest\EntryPoint;
-use MediaWiki\Rest\RequestData;
-use MediaWiki\Rest\ResponseFactory;
-use MediaWiki\Rest\Router;
-use WebResponse;
-
-/**
- * @covers \MediaWiki\Rest\EntryPoint
- * @covers \MediaWiki\Rest\Router
- */
-class EntryPointTest extends MediaWikiTestCase {
- private static $mockHandler;
-
- private function createRouter() {
- return new Router(
- [ __DIR__ . '/testRoutes.json' ],
- [],
- '/rest',
- new EmptyBagOStuff(),
- new ResponseFactory() );
- }
-
- private function createWebResponse() {
- return $this->getMockBuilder( WebResponse::class )
- ->setMethods( [ 'header' ] )
- ->getMock();
- }
-
- public static function mockHandlerHeader() {
- return new class extends Handler {
- public function execute() {
- $response = $this->getResponseFactory()->create();
- $response->setHeader( 'Foo', 'Bar' );
- return $response;
- }
- };
- }
-
- public function testHeader() {
- $webResponse = $this->createWebResponse();
- $webResponse->expects( $this->any() )
- ->method( 'header' )
- ->withConsecutive(
- [ 'HTTP/1.1 200 OK', true, null ],
- [ 'Foo: Bar', true, null ]
- );
-
- $entryPoint = new EntryPoint(
- new RequestData( [ 'uri' => new Uri( '/rest/mock/EntryPoint/header' ) ] ),
- $webResponse,
- $this->createRouter() );
- $entryPoint->execute();
- $this->assertTrue( true );
- }
-
- public static function mockHandlerBodyRewind() {
- return new class extends Handler {
- public function execute() {
- $response = $this->getResponseFactory()->create();
- $stream = new Stream( fopen( 'php://memory', 'w+' ) );
- $stream->write( 'hello' );
- $response->setBody( $stream );
- return $response;
- }
- };
- }
-
- /**
- * Make sure EntryPoint rewinds a seekable body stream before reading.
- */
- public function testBodyRewind() {
- $entryPoint = new EntryPoint(
- new RequestData( [ 'uri' => new Uri( '/rest/mock/EntryPoint/bodyRewind' ) ] ),
- $this->createWebResponse(),
- $this->createRouter() );
- ob_start();
- $entryPoint->execute();
- $this->assertSame( 'hello', ob_get_clean() );
- }
-
-}
+++ /dev/null
-<?php
-
-namespace MediaWiki\Tests\Rest\Handler;
-
-use EmptyBagOStuff;
-use GuzzleHttp\Psr7\Uri;
-use MediaWiki\Rest\RequestData;
-use MediaWiki\Rest\ResponseFactory;
-use MediaWiki\Rest\Router;
-use MediaWikiTestCase;
-
-/**
- * @covers \MediaWiki\Rest\Handler\HelloHandler
- */
-class HelloHandlerTest extends MediaWikiTestCase {
- public static function provideTestViaRouter() {
- return [
- 'normal' => [
- [
- 'method' => 'GET',
- 'uri' => self::makeUri( '/user/Tim/hello' ),
- ],
- [
- 'statusCode' => 200,
- 'reasonPhrase' => 'OK',
- 'protocolVersion' => '1.1',
- 'body' => '{"message":"Hello, Tim!"}',
- ],
- ],
- 'method not allowed' => [
- [
- 'method' => 'POST',
- 'uri' => self::makeUri( '/user/Tim/hello' ),
- ],
- [
- 'statusCode' => 405,
- 'reasonPhrase' => 'Method Not Allowed',
- 'protocolVersion' => '1.1',
- 'body' => '{"httpCode":405,"httpReason":"Method Not Allowed"}',
- ],
- ],
- ];
- }
-
- private static function makeUri( $path ) {
- return new Uri( "http://www.example.com/rest$path" );
- }
-
- /** @dataProvider provideTestViaRouter */
- public function testViaRouter( $requestInfo, $responseInfo ) {
- $router = new Router(
- [ __DIR__ . '/../testRoutes.json' ],
- [],
- '/rest',
- new EmptyBagOStuff(),
- new ResponseFactory() );
- $request = new RequestData( $requestInfo );
- $response = $router->execute( $request );
- if ( isset( $responseInfo['statusCode'] ) ) {
- $this->assertSame( $responseInfo['statusCode'], $response->getStatusCode() );
- }
- if ( isset( $responseInfo['reasonPhrase'] ) ) {
- $this->assertSame( $responseInfo['reasonPhrase'], $response->getReasonPhrase() );
- }
- if ( isset( $responseInfo['protocolVersion'] ) ) {
- $this->assertSame( $responseInfo['protocolVersion'], $response->getProtocolVersion() );
- }
- if ( isset( $responseInfo['body'] ) ) {
- $this->assertSame( $responseInfo['body'], $response->getBody()->getContents() );
- }
- $this->assertSame(
- [],
- array_diff( array_keys( $responseInfo ), [
- 'statusCode',
- 'reasonPhrase',
- 'protocolVersion',
- 'body'
- ] ),
- '$responseInfo may not contain unknown keys' );
- }
-}
+++ /dev/null
-[
- {
- "path": "/user/{name}/hello",
- "class": "MediaWiki\\Rest\\Handler\\HelloHandler"
- },
- {
- "path": "/mock/EntryPoint/header",
- "factory": "MediaWiki\\Tests\\Rest\\EntryPointTest::mockHandlerHeader"
- },
- {
- "path": "/mock/EntryPoint/bodyRewind",
- "factory": "MediaWiki\\Tests\\Rest\\EntryPointTest::mockHandlerBodyRewind"
- }
-]
+++ /dev/null
-<?php
-
-namespace MediaWiki\Tests\Revision;
-
-use ActorMigration;
-use CommentStore;
-use MediaWiki\Logger\Spi as LoggerSpi;
-use MediaWiki\Revision\RevisionStore;
-use MediaWiki\Revision\RevisionStoreFactory;
-use MediaWiki\Revision\SlotRoleRegistry;
-use MediaWiki\Storage\BlobStore;
-use MediaWiki\Storage\BlobStoreFactory;
-use MediaWiki\Storage\NameTableStore;
-use MediaWiki\Storage\NameTableStoreFactory;
-use MediaWiki\Storage\SqlBlobStore;
-use MediaWikiTestCase;
-use Psr\Log\LoggerInterface;
-use Psr\Log\NullLogger;
-use WANObjectCache;
-use Wikimedia\Rdbms\ILBFactory;
-use Wikimedia\Rdbms\ILoadBalancer;
-use Wikimedia\TestingAccessWrapper;
-
-class RevisionStoreFactoryTest extends MediaWikiTestCase {
-
- /**
- * @covers \MediaWiki\Revision\RevisionStoreFactory::__construct
- */
- public function testValidConstruction_doesntCauseErrors() {
- new RevisionStoreFactory(
- $this->getMockLoadBalancerFactory(),
- $this->getMockBlobStoreFactory(),
- $this->getNameTableStoreFactory(),
- $this->getMockSlotRoleRegistry(),
- $this->getHashWANObjectCache(),
- $this->getMockCommentStore(),
- ActorMigration::newMigration(),
- MIGRATION_OLD,
- $this->getMockLoggerSpi(),
- true
- );
- $this->assertTrue( true );
- }
-
- public function provideWikiIds() {
- yield [ true ];
- yield [ false ];
- yield [ 'somewiki' ];
- yield [ 'somewiki', MIGRATION_OLD , false ];
- yield [ 'somewiki', MIGRATION_NEW , true ];
- }
-
- /**
- * @dataProvider provideWikiIds
- * @covers \MediaWiki\Revision\RevisionStoreFactory::getRevisionStore
- */
- public function testGetRevisionStore(
- $dbDomain,
- $mcrMigrationStage = MIGRATION_OLD,
- $contentHandlerUseDb = true
- ) {
- $lbFactory = $this->getMockLoadBalancerFactory();
- $blobStoreFactory = $this->getMockBlobStoreFactory();
- $nameTableStoreFactory = $this->getNameTableStoreFactory();
- $slotRoleRegistry = $this->getMockSlotRoleRegistry();
- $cache = $this->getHashWANObjectCache();
- $commentStore = $this->getMockCommentStore();
- $actorMigration = ActorMigration::newMigration();
- $loggerProvider = $this->getMockLoggerSpi();
-
- $factory = new RevisionStoreFactory(
- $lbFactory,
- $blobStoreFactory,
- $nameTableStoreFactory,
- $slotRoleRegistry,
- $cache,
- $commentStore,
- $actorMigration,
- $mcrMigrationStage,
- $loggerProvider,
- $contentHandlerUseDb
- );
-
- $store = $factory->getRevisionStore( $dbDomain );
- $wrapper = TestingAccessWrapper::newFromObject( $store );
-
- // ensure the correct object type is returned
- $this->assertInstanceOf( RevisionStore::class, $store );
-
- // ensure the RevisionStore is for the given wikiId
- $this->assertSame( $dbDomain, $wrapper->dbDomain );
-
- // ensure all other required services are correctly set
- $this->assertSame( $cache, $wrapper->cache );
- $this->assertSame( $commentStore, $wrapper->commentStore );
- $this->assertSame( $mcrMigrationStage, $wrapper->mcrMigrationStage );
- $this->assertSame( $actorMigration, $wrapper->actorMigration );
- $this->assertSame( $contentHandlerUseDb, $store->getContentHandlerUseDB() );
-
- $this->assertInstanceOf( ILoadBalancer::class, $wrapper->loadBalancer );
- $this->assertInstanceOf( BlobStore::class, $wrapper->blobStore );
- $this->assertInstanceOf( NameTableStore::class, $wrapper->contentModelStore );
- $this->assertInstanceOf( NameTableStore::class, $wrapper->slotRoleStore );
- $this->assertInstanceOf( LoggerInterface::class, $wrapper->logger );
- }
-
- /**
- * @return \PHPUnit_Framework_MockObject_MockObject|ILoadBalancer
- */
- private function getMockLoadBalancer() {
- return $this->getMockBuilder( ILoadBalancer::class )
- ->disableOriginalConstructor()->getMock();
- }
-
- /**
- * @return \PHPUnit_Framework_MockObject_MockObject|ILBFactory
- */
- private function getMockLoadBalancerFactory() {
- $mock = $this->getMockBuilder( ILBFactory::class )
- ->disableOriginalConstructor()->getMock();
-
- $mock->method( 'getMainLB' )
- ->willReturnCallback( function () {
- return $this->getMockLoadBalancer();
- } );
-
- return $mock;
- }
-
- /**
- * @return \PHPUnit_Framework_MockObject_MockObject|SqlBlobStore
- */
- private function getMockSqlBlobStore() {
- return $this->getMockBuilder( SqlBlobStore::class )
- ->disableOriginalConstructor()->getMock();
- }
-
- /**
- * @return \PHPUnit_Framework_MockObject_MockObject|BlobStoreFactory
- */
- private function getMockBlobStoreFactory() {
- $mock = $this->getMockBuilder( BlobStoreFactory::class )
- ->disableOriginalConstructor()->getMock();
-
- $mock->method( 'newSqlBlobStore' )
- ->willReturnCallback( function () {
- return $this->getMockSqlBlobStore();
- } );
-
- return $mock;
- }
-
- /**
- * @return SlotRoleRegistry
- */
- private function getMockSlotRoleRegistry() {
- return $this->createMock( SlotRoleRegistry::class );
- }
-
- /**
- * @return NameTableStoreFactory
- */
- private function getNameTableStoreFactory() {
- return new NameTableStoreFactory(
- $this->getMockLoadBalancerFactory(),
- $this->getHashWANObjectCache(),
- new NullLogger() );
- }
-
- /**
- * @return \PHPUnit_Framework_MockObject_MockObject|CommentStore
- */
- private function getMockCommentStore() {
- return $this->getMockBuilder( CommentStore::class )
- ->disableOriginalConstructor()->getMock();
- }
-
- private function getHashWANObjectCache() {
- return new WANObjectCache( [ 'cache' => new \HashBagOStuff() ] );
- }
-
- /**
- * @return \PHPUnit_Framework_MockObject_MockObject|LoggerSpi
- */
- private function getMockLoggerSpi() {
- $mock = $this->getMock( LoggerSpi::class );
-
- $mock->method( 'getLogger' )
- ->willReturn( new NullLogger() );
-
- return $mock;
- }
-
-}
+++ /dev/null
-<?php
-
-use MediaWiki\MediaWikiServices;
-
-class ConfigFactoryTest extends MediaWikiTestCase {
-
- /**
- * @covers ConfigFactory::register
- */
- public function testRegister() {
- $factory = new ConfigFactory();
- $factory->register( 'unittest', 'GlobalVarConfig::newInstance' );
- $this->assertInstanceOf( GlobalVarConfig::class, $factory->makeConfig( 'unittest' ) );
- }
-
- /**
- * @covers ConfigFactory::register
- */
- public function testRegisterInvalid() {
- $factory = new ConfigFactory();
- $this->setExpectedException( InvalidArgumentException::class );
- $factory->register( 'invalid', 'Invalid callback' );
- }
-
- /**
- * @covers ConfigFactory::register
- */
- public function testRegisterInvalidInstance() {
- $factory = new ConfigFactory();
- $this->setExpectedException( InvalidArgumentException::class );
- $factory->register( 'invalidInstance', new stdClass );
- }
-
- /**
- * @covers ConfigFactory::register
- */
- public function testRegisterInstance() {
- $config = GlobalVarConfig::newInstance();
- $factory = new ConfigFactory();
- $factory->register( 'unittest', $config );
- $this->assertSame( $config, $factory->makeConfig( 'unittest' ) );
- }
-
- /**
- * @covers ConfigFactory::register
- */
- public function testRegisterAgain() {
- $factory = new ConfigFactory();
- $factory->register( 'unittest', 'GlobalVarConfig::newInstance' );
- $config1 = $factory->makeConfig( 'unittest' );
-
- $factory->register( 'unittest', 'GlobalVarConfig::newInstance' );
- $config2 = $factory->makeConfig( 'unittest' );
-
- $this->assertNotSame( $config1, $config2 );
- }
-
- /**
- * @covers ConfigFactory::salvage
- */
- public function testSalvage() {
- $oldFactory = new ConfigFactory();
- $oldFactory->register( 'foo', 'GlobalVarConfig::newInstance' );
- $oldFactory->register( 'bar', 'GlobalVarConfig::newInstance' );
- $oldFactory->register( 'quux', 'GlobalVarConfig::newInstance' );
-
- // instantiate two of the three defined configurations
- $foo = $oldFactory->makeConfig( 'foo' );
- $bar = $oldFactory->makeConfig( 'bar' );
- $quux = $oldFactory->makeConfig( 'quux' );
-
- // define new config instance
- $newFactory = new ConfigFactory();
- $newFactory->register( 'foo', 'GlobalVarConfig::newInstance' );
- $newFactory->register( 'bar', function () {
- return new HashConfig();
- } );
-
- // "foo" and "quux" are defined in the old and the new factory.
- // The old factory has instances for "foo" and "bar", but not "quux".
- $newFactory->salvage( $oldFactory );
-
- $newFoo = $newFactory->makeConfig( 'foo' );
- $this->assertSame( $foo, $newFoo, 'existing instance should be salvaged' );
-
- $newBar = $newFactory->makeConfig( 'bar' );
- $this->assertNotSame( $bar, $newBar, 'don\'t salvage if callbacks differ' );
-
- // the new factory doesn't have quux defined, so the quux instance should not be salvaged
- $this->setExpectedException( ConfigException::class );
- $newFactory->makeConfig( 'quux' );
- }
-
- /**
- * @covers ConfigFactory::getConfigNames
- */
- public function testGetConfigNames() {
- $factory = new ConfigFactory();
- $factory->register( 'foo', 'GlobalVarConfig::newInstance' );
- $factory->register( 'bar', new HashConfig() );
-
- $this->assertEquals( [ 'foo', 'bar' ], $factory->getConfigNames() );
- }
-
- /**
- * @covers ConfigFactory::makeConfig
- */
- public function testMakeConfigWithCallback() {
- $factory = new ConfigFactory();
- $factory->register( 'unittest', 'GlobalVarConfig::newInstance' );
-
- $conf = $factory->makeConfig( 'unittest' );
- $this->assertInstanceOf( Config::class, $conf );
- $this->assertSame( $conf, $factory->makeConfig( 'unittest' ) );
- }
-
- /**
- * @covers ConfigFactory::makeConfig
- */
- public function testMakeConfigWithObject() {
- $factory = new ConfigFactory();
- $conf = new HashConfig();
- $factory->register( 'test', $conf );
- $this->assertSame( $conf, $factory->makeConfig( 'test' ) );
- }
-
- /**
- * @covers ConfigFactory::makeConfig
- */
- public function testMakeConfigFallback() {
- $factory = new ConfigFactory();
- $factory->register( '*', 'GlobalVarConfig::newInstance' );
- $conf = $factory->makeConfig( 'unittest' );
- $this->assertInstanceOf( Config::class, $conf );
- }
-
- /**
- * @covers ConfigFactory::makeConfig
- */
- public function testMakeConfigWithNoBuilders() {
- $factory = new ConfigFactory();
- $this->setExpectedException( ConfigException::class );
- $factory->makeConfig( 'nobuilderregistered' );
- }
-
- /**
- * @covers ConfigFactory::makeConfig
- */
- public function testMakeConfigWithInvalidCallback() {
- $factory = new ConfigFactory();
- $factory->register( 'unittest', function () {
- return true; // Not a Config object
- } );
- $this->setExpectedException( UnexpectedValueException::class );
- $factory->makeConfig( 'unittest' );
- }
-
- /**
- * @covers ConfigFactory::getDefaultInstance
- */
- public function testGetDefaultInstance() {
- // NOTE: the global config factory returned here has been overwritten
- // for operation in test mode. It may not reflect LocalSettings.
- $factory = MediaWikiServices::getInstance()->getConfigFactory();
- $this->assertInstanceOf( Config::class, $factory->makeConfig( 'main' ) );
- }
-
-}
+++ /dev/null
-<?php
-
-/**
- * @group Media
- */
-class GIFMetadataExtractorTest extends MediaWikiTestCase {
-
- protected function setUp() {
- parent::setUp();
-
- $this->mediaPath = __DIR__ . '/../../data/media/';
- }
-
- /**
- * Put in a file, and see if the metadata coming out is as expected.
- * @param string $filename
- * @param array $expected The extracted metadata.
- * @dataProvider provideGetMetadata
- * @covers GIFMetadataExtractor::getMetadata
- */
- public function testGetMetadata( $filename, $expected ) {
- $actual = GIFMetadataExtractor::getMetadata( $this->mediaPath . $filename );
- $this->assertEquals( $expected, $actual );
- }
-
- public static function provideGetMetadata() {
- $xmpNugget = <<<EOF
-<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?>
-<x:xmpmeta xmlns:x='adobe:ns:meta/' x:xmptk='Image::ExifTool 7.30'>
-<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>
-
- <rdf:Description rdf:about=''
- xmlns:Iptc4xmpCore='http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/'>
- <Iptc4xmpCore:Location>The interwebs</Iptc4xmpCore:Location>
- </rdf:Description>
-
- <rdf:Description rdf:about=''
- xmlns:tiff='http://ns.adobe.com/tiff/1.0/'>
- <tiff:Artist>Bawolff</tiff:Artist>
- <tiff:ImageDescription>
- <rdf:Alt>
- <rdf:li xml:lang='x-default'>A file to test GIF</rdf:li>
- </rdf:Alt>
- </tiff:ImageDescription>
- </rdf:Description>
-</rdf:RDF>
-</x:xmpmeta>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-<?xpacket end='w'?>
-EOF;
- $xmpNugget = str_replace( "\r", '', $xmpNugget ); // Windows compat
-
- return [
- [
- 'nonanimated.gif',
- [
- 'comment' => [ 'GIF test file ⁕ Created with GIMP' ],
- 'duration' => 0.1,
- 'frameCount' => 1,
- 'looped' => false,
- 'xmp' => '',
- ]
- ],
- [
- 'animated.gif',
- [
- 'comment' => [ 'GIF test file . Created with GIMP' ],
- 'duration' => 2.4,
- 'frameCount' => 4,
- 'looped' => true,
- 'xmp' => '',
- ]
- ],
-
- [
- 'animated-xmp.gif',
- [
- 'xmp' => $xmpNugget,
- 'duration' => 2.4,
- 'frameCount' => 4,
- 'looped' => true,
- 'comment' => [ 'GIƒ·test·file' ],
- ]
- ],
- ];
- }
-}
+++ /dev/null
-<?php
-
-/**
- * @group Media
- * @covers SVGMetadataExtractor
- */
-class SVGMetadataExtractorTest extends MediaWikiTestCase {
-
- /**
- * @dataProvider provideSvgFiles
- */
- public function testGetMetadata( $infile, $expected ) {
- $this->assertMetadata( $infile, $expected );
- }
-
- /**
- * @dataProvider provideSvgFilesWithXMLMetadata
- */
- public function testGetXMLMetadata( $infile, $expected ) {
- $r = new XMLReader();
- $this->assertMetadata( $infile, $expected );
- }
-
- /**
- * @dataProvider provideSvgUnits
- */
- public function testScaleSVGUnit( $inUnit, $expected ) {
- $this->assertEquals(
- $expected,
- SVGReader::scaleSVGUnit( $inUnit ),
- 'SVG unit conversion and scaling failure'
- );
- }
-
- function assertMetadata( $infile, $expected ) {
- try {
- $data = SVGMetadataExtractor::getMetadata( $infile );
- $this->assertEquals( $expected, $data, 'SVG metadata extraction test' );
- } catch ( MWException $e ) {
- if ( $expected === false ) {
- $this->assertTrue( true, 'SVG metadata extracted test (expected failure)' );
- } else {
- throw $e;
- }
- }
- }
-
- public static function provideSvgFiles() {
- $base = __DIR__ . '/../../data/media';
-
- return [
- [
- "$base/Wikimedia-logo.svg",
- [
- 'width' => 1024,
- 'height' => 1024,
- 'originalWidth' => '1024',
- 'originalHeight' => '1024',
- 'translations' => [],
- ]
- ],
- [
- "$base/QA_icon.svg",
- [
- 'width' => 60,
- 'height' => 60,
- 'originalWidth' => '60',
- 'originalHeight' => '60',
- 'translations' => [],
- ]
- ],
- [
- "$base/Gtk-media-play-ltr.svg",
- [
- 'width' => 60,
- 'height' => 60,
- 'originalWidth' => '60.0000000',
- 'originalHeight' => '60.0000000',
- 'translations' => [],
- ]
- ],
- [
- "$base/Toll_Texas_1.svg",
- // This file triggered T33719, needs entity expansion in the xmlns checks
- [
- 'width' => 385,
- 'height' => 385,
- 'originalWidth' => '385',
- 'originalHeight' => '385.0004883',
- 'translations' => [],
- ]
- ],
- [
- "$base/Tux.svg",
- [
- 'width' => 512,
- 'height' => 594,
- 'originalWidth' => '100%',
- 'originalHeight' => '100%',
- 'title' => 'Tux',
- 'translations' => [],
- 'description' => 'For more information see: http://commons.wikimedia.org/wiki/Image:Tux.svg',
- ]
- ],
- [
- "$base/Speech_bubbles.svg",
- [
- 'width' => 627,
- 'height' => 461,
- 'originalWidth' => '17.7cm',
- 'originalHeight' => '13cm',
- 'translations' => [
- 'de' => SVGReader::LANG_FULL_MATCH,
- 'fr' => SVGReader::LANG_FULL_MATCH,
- 'nl' => SVGReader::LANG_FULL_MATCH,
- 'tlh-ca' => SVGReader::LANG_FULL_MATCH,
- 'tlh' => SVGReader::LANG_PREFIX_MATCH
- ],
- ]
- ],
- [
- "$base/Soccer_ball_animated.svg",
- [
- 'width' => 150,
- 'height' => 150,
- 'originalWidth' => '150',
- 'originalHeight' => '150',
- 'animated' => true,
- 'translations' => []
- ],
- ],
- [
- "$base/comma_separated_viewbox.svg",
- [
- 'width' => 512,
- 'height' => 594,
- 'originalWidth' => '100%',
- 'originalHeight' => '100%',
- 'translations' => []
- ],
- ],
- ];
- }
-
- public static function provideSvgFilesWithXMLMetadata() {
- $base = __DIR__ . '/../../data/media';
- // phpcs:disable Generic.Files.LineLength
- $metadata = '<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
- <ns4:Work xmlns:ns4="http://creativecommons.org/ns#" rdf:about="">
- <ns5:format xmlns:ns5="http://purl.org/dc/elements/1.1/">image/svg+xml</ns5:format>
- <ns5:type xmlns:ns5="http://purl.org/dc/elements/1.1/" rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
- </ns4:Work>
- </rdf:RDF>';
- // phpcs:enable
-
- $metadata = str_replace( "\r", '', $metadata ); // Windows compat
- return [
- [
- "$base/US_states_by_total_state_tax_revenue.svg",
- [
- 'height' => 593,
- 'metadata' => $metadata,
- 'width' => 959,
- 'originalWidth' => '958.69',
- 'originalHeight' => '592.78998',
- 'translations' => [],
- ]
- ],
- ];
- }
-
- public static function provideSvgUnits() {
- return [
- [ '1' , 1 ],
- [ '1.1' , 1.1 ],
- [ '0.1' , 0.1 ],
- [ '.1' , 0.1 ],
- [ '1e2' , 100 ],
- [ '1E2' , 100 ],
- [ '+1' , 1 ],
- [ '-1' , -1 ],
- [ '-1.1' , -1.1 ],
- [ '1e+2' , 100 ],
- [ '1e-2' , 0.01 ],
- [ '10px' , 10 ],
- [ '10pt' , 10 * 1.25 ],
- [ '10pc' , 10 * 15 ],
- [ '10mm' , 10 * 3.543307 ],
- [ '10cm' , 10 * 35.43307 ],
- [ '10in' , 10 * 90 ],
- [ '10em' , 10 * 16 ],
- [ '10ex' , 10 * 12 ],
- [ '10%' , 51.2 ],
- [ '10 px' , 10 ],
- // Invalid values
- [ '1e1.1', 10 ],
- [ '10bp', 10 ],
- [ 'p10', null ],
- ];
- }
-}
+++ /dev/null
-<?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
- * @since 1.25
- *
- * @ingroup Site
- * @ingroup Test
- *
- * @group Site
- * @group Database
- *
- * @author Jeroen De Dauw < jeroendedauw@gmail.com >
- */
-class CachingSiteStoreTest extends MediaWikiTestCase {
-
- /**
- * @covers CachingSiteStore::getSites
- */
- public function testGetSites() {
- $testSites = TestSites::getSites();
-
- $store = new CachingSiteStore(
- $this->getHashSiteStore( $testSites ),
- ObjectCache::getLocalClusterInstance()
- );
-
- $sites = $store->getSites();
-
- $this->assertInstanceOf( SiteList::class, $sites );
-
- /**
- * @var Site $site
- */
- foreach ( $sites as $site ) {
- $this->assertInstanceOf( Site::class, $site );
- }
-
- foreach ( $testSites as $site ) {
- if ( $site->getGlobalId() !== null ) {
- $this->assertTrue( $sites->hasSite( $site->getGlobalId() ) );
- }
- }
- }
-
- /**
- * @covers CachingSiteStore::saveSites
- */
- public function testSaveSites() {
- $store = new CachingSiteStore(
- new HashSiteStore(), ObjectCache::getLocalClusterInstance()
- );
-
- $sites = [];
-
- $site = new Site();
- $site->setGlobalId( 'ertrywuutr' );
- $site->setLanguageCode( 'en' );
- $sites[] = $site;
-
- $site = new MediaWikiSite();
- $site->setGlobalId( 'sdfhxujgkfpth' );
- $site->setLanguageCode( 'nl' );
- $sites[] = $site;
-
- $this->assertTrue( $store->saveSites( $sites ) );
-
- $site = $store->getSite( 'ertrywuutr' );
- $this->assertInstanceOf( Site::class, $site );
- $this->assertEquals( 'en', $site->getLanguageCode() );
-
- $site = $store->getSite( 'sdfhxujgkfpth' );
- $this->assertInstanceOf( Site::class, $site );
- $this->assertEquals( 'nl', $site->getLanguageCode() );
- }
-
- /**
- * @covers CachingSiteStore::reset
- */
- public function testReset() {
- $dbSiteStore = $this->getMockBuilder( SiteStore::class )
- ->disableOriginalConstructor()
- ->getMock();
-
- $dbSiteStore->expects( $this->any() )
- ->method( 'getSite' )
- ->will( $this->returnValue( $this->getTestSite() ) );
-
- $dbSiteStore->expects( $this->any() )
- ->method( 'getSites' )
- ->will( $this->returnCallback( function () {
- $siteList = new SiteList();
- $siteList->setSite( $this->getTestSite() );
-
- return $siteList;
- } ) );
-
- $store = new CachingSiteStore( $dbSiteStore, ObjectCache::getLocalClusterInstance() );
-
- // initialize internal cache
- $this->assertGreaterThan( 0, $store->getSites()->count(), 'count sites' );
-
- $store->getSite( 'enwiki' )->setLanguageCode( 'en-ca' );
-
- // sanity check: $store should have the new language code for 'enwiki'
- $this->assertEquals( 'en-ca', $store->getSite( 'enwiki' )->getLanguageCode(), 'sanity check' );
-
- // purge cache
- $store->reset();
-
- // the internal cache of $store should be updated, and now pulling
- // the site from the 'fallback' DBSiteStore with the original language code.
- $this->assertEquals( 'en', $store->getSite( 'enwiki' )->getLanguageCode(), 'reset' );
- }
-
- public function getTestSite() {
- $enwiki = new MediaWikiSite();
- $enwiki->setGlobalId( 'enwiki' );
- $enwiki->setLanguageCode( 'en' );
-
- return $enwiki;
- }
-
- /**
- * @covers CachingSiteStore::clear
- */
- public function testClear() {
- $store = new CachingSiteStore(
- new HashSiteStore(), ObjectCache::getLocalClusterInstance()
- );
- $this->assertTrue( $store->clear() );
-
- $site = $store->getSite( 'enwiki' );
- $this->assertNull( $site );
-
- $sites = $store->getSites();
- $this->assertEquals( 0, $sites->count() );
- }
-
- /**
- * @param Site[] $sites
- *
- * @return SiteStore
- */
- private function getHashSiteStore( array $sites ) {
- $siteStore = new HashSiteStore();
- $siteStore->saveSites( $sites );
-
- return $siteStore;
- }
-
-}
+++ /dev/null
-<?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
- * @since 1.25
- *
- * @ingroup Site
- * @group Site
- *
- * @author Katie Filbert < aude.wiki@gmail.com >
- */
-class HashSiteStoreTest extends MediaWikiTestCase {
-
- /**
- * @covers HashSiteStore::getSites
- */
- public function testGetSites() {
- $expectedSites = [];
-
- foreach ( TestSites::getSites() as $testSite ) {
- $siteId = $testSite->getGlobalId();
- $expectedSites[$siteId] = $testSite;
- }
-
- $siteStore = new HashSiteStore( $expectedSites );
-
- $this->assertEquals( new SiteList( $expectedSites ), $siteStore->getSites() );
- }
-
- /**
- * @covers HashSiteStore::saveSite
- * @covers HashSiteStore::getSite
- */
- public function testSaveSite() {
- $store = new HashSiteStore();
-
- $site = new Site();
- $site->setGlobalId( 'dewiki' );
-
- $this->assertCount( 0, $store->getSites(), '0 sites in store' );
-
- $store->saveSite( $site );
-
- $this->assertCount( 1, $store->getSites(), 'Store has 1 sites' );
- $this->assertEquals( $site, $store->getSite( 'dewiki' ), 'Store has dewiki' );
- }
-
- /**
- * @covers HashSiteStore::saveSites
- */
- public function testSaveSites() {
- $store = new HashSiteStore();
-
- $sites = [];
-
- $site = new Site();
- $site->setGlobalId( 'enwiki' );
- $site->setLanguageCode( 'en' );
- $sites[] = $site;
-
- $site = new MediaWikiSite();
- $site->setGlobalId( 'eswiki' );
- $site->setLanguageCode( 'es' );
- $sites[] = $site;
-
- $this->assertCount( 0, $store->getSites(), '0 sites in store' );
-
- $store->saveSites( $sites );
-
- $this->assertCount( 2, $store->getSites(), 'Store has 2 sites' );
- $this->assertTrue( $store->getSites()->hasSite( 'enwiki' ), 'Store has enwiki' );
- $this->assertTrue( $store->getSites()->hasSite( 'eswiki' ), 'Store has eswiki' );
- }
-
- /**
- * @covers HashSiteStore::clear
- */
- public function testClear() {
- $store = new HashSiteStore();
-
- $site = new Site();
- $site->setGlobalId( 'arwiki' );
- $store->saveSite( $site );
-
- $this->assertCount( 1, $store->getSites(), '1 site in store' );
-
- $store->clear();
- $this->assertCount( 0, $store->getSites(), '0 sites in store' );
- }
-}
--- /dev/null
+<?php
+
+/**
+ * Note: this is not a unit test, as it touches the file system and reads an actual file.
+ * If unit tests are added for MediaWikiVersionFetcher, this should be done in a distinct test case.
+ *
+ * @covers MediaWikiVersionFetcher
+ *
+ * @group ComposerHooks
+ *
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class MediaWikiVersionFetcherTest extends \MediaWikiUnitTestCase {
+
+ public function testReturnsResult() {
+ global $wgVersion;
+ $versionFetcher = new MediaWikiVersionFetcher();
+ $this->assertSame( $wgVersion, $versionFetcher->fetchVersion() );
+ }
+
+}
--- /dev/null
+<?php
+
+namespace MediaWiki\Tests\Rest;
+
+use EmptyBagOStuff;
+use GuzzleHttp\Psr7\Uri;
+use GuzzleHttp\Psr7\Stream;
+use MediaWiki\Rest\Handler;
+use MediaWiki\Rest\EntryPoint;
+use MediaWiki\Rest\RequestData;
+use MediaWiki\Rest\ResponseFactory;
+use MediaWiki\Rest\Router;
+use WebResponse;
+
+/**
+ * @covers \MediaWiki\Rest\EntryPoint
+ * @covers \MediaWiki\Rest\Router
+ */
+class EntryPointTest extends \MediaWikiUnitTestCase {
+ private static $mockHandler;
+
+ private function createRouter() {
+ return new Router(
+ [ __DIR__ . '/testRoutes.json' ],
+ [],
+ '/rest',
+ new EmptyBagOStuff(),
+ new ResponseFactory() );
+ }
+
+ private function createWebResponse() {
+ return $this->getMockBuilder( WebResponse::class )
+ ->setMethods( [ 'header' ] )
+ ->getMock();
+ }
+
+ public static function mockHandlerHeader() {
+ return new class extends Handler {
+ public function execute() {
+ $response = $this->getResponseFactory()->create();
+ $response->setHeader( 'Foo', 'Bar' );
+ return $response;
+ }
+ };
+ }
+
+ public function testHeader() {
+ $webResponse = $this->createWebResponse();
+ $webResponse->expects( $this->any() )
+ ->method( 'header' )
+ ->withConsecutive(
+ [ 'HTTP/1.1 200 OK', true, null ],
+ [ 'Foo: Bar', true, null ]
+ );
+
+ $entryPoint = new EntryPoint(
+ new RequestData( [ 'uri' => new Uri( '/rest/mock/EntryPoint/header' ) ] ),
+ $webResponse,
+ $this->createRouter() );
+ $entryPoint->execute();
+ $this->assertTrue( true );
+ }
+
+ public static function mockHandlerBodyRewind() {
+ return new class extends Handler {
+ public function execute() {
+ $response = $this->getResponseFactory()->create();
+ $stream = new Stream( fopen( 'php://memory', 'w+' ) );
+ $stream->write( 'hello' );
+ $response->setBody( $stream );
+ return $response;
+ }
+ };
+ }
+
+ /**
+ * Make sure EntryPoint rewinds a seekable body stream before reading.
+ */
+ public function testBodyRewind() {
+ $entryPoint = new EntryPoint(
+ new RequestData( [ 'uri' => new Uri( '/rest/mock/EntryPoint/bodyRewind' ) ] ),
+ $this->createWebResponse(),
+ $this->createRouter() );
+ ob_start();
+ $entryPoint->execute();
+ $this->assertSame( 'hello', ob_get_clean() );
+ }
+
+}
--- /dev/null
+<?php
+
+namespace MediaWiki\Tests\Rest\Handler;
+
+use EmptyBagOStuff;
+use GuzzleHttp\Psr7\Uri;
+use MediaWiki\Rest\RequestData;
+use MediaWiki\Rest\ResponseFactory;
+use MediaWiki\Rest\Router;
+
+/**
+ * @covers \MediaWiki\Rest\Handler\HelloHandler
+ */
+class HelloHandlerTest extends \MediaWikiUnitTestCase {
+ public static function provideTestViaRouter() {
+ return [
+ 'normal' => [
+ [
+ 'method' => 'GET',
+ 'uri' => self::makeUri( '/user/Tim/hello' ),
+ ],
+ [
+ 'statusCode' => 200,
+ 'reasonPhrase' => 'OK',
+ 'protocolVersion' => '1.1',
+ 'body' => '{"message":"Hello, Tim!"}',
+ ],
+ ],
+ 'method not allowed' => [
+ [
+ 'method' => 'POST',
+ 'uri' => self::makeUri( '/user/Tim/hello' ),
+ ],
+ [
+ 'statusCode' => 405,
+ 'reasonPhrase' => 'Method Not Allowed',
+ 'protocolVersion' => '1.1',
+ 'body' => '{"httpCode":405,"httpReason":"Method Not Allowed"}',
+ ],
+ ],
+ ];
+ }
+
+ private static function makeUri( $path ) {
+ return new Uri( "http://www.example.com/rest$path" );
+ }
+
+ /** @dataProvider provideTestViaRouter */
+ public function testViaRouter( $requestInfo, $responseInfo ) {
+ $router = new Router(
+ [ __DIR__ . '/../testRoutes.json' ],
+ [],
+ '/rest',
+ new EmptyBagOStuff(),
+ new ResponseFactory() );
+ $request = new RequestData( $requestInfo );
+ $response = $router->execute( $request );
+ if ( isset( $responseInfo['statusCode'] ) ) {
+ $this->assertSame( $responseInfo['statusCode'], $response->getStatusCode() );
+ }
+ if ( isset( $responseInfo['reasonPhrase'] ) ) {
+ $this->assertSame( $responseInfo['reasonPhrase'], $response->getReasonPhrase() );
+ }
+ if ( isset( $responseInfo['protocolVersion'] ) ) {
+ $this->assertSame( $responseInfo['protocolVersion'], $response->getProtocolVersion() );
+ }
+ if ( isset( $responseInfo['body'] ) ) {
+ $this->assertSame( $responseInfo['body'], $response->getBody()->getContents() );
+ }
+ $this->assertSame(
+ [],
+ array_diff( array_keys( $responseInfo ), [
+ 'statusCode',
+ 'reasonPhrase',
+ 'protocolVersion',
+ 'body'
+ ] ),
+ '$responseInfo may not contain unknown keys' );
+ }
+}
--- /dev/null
+[
+ {
+ "path": "/user/{name}/hello",
+ "class": "MediaWiki\\Rest\\Handler\\HelloHandler"
+ },
+ {
+ "path": "/mock/EntryPoint/header",
+ "factory": "MediaWiki\\Tests\\Rest\\EntryPointTest::mockHandlerHeader"
+ },
+ {
+ "path": "/mock/EntryPoint/bodyRewind",
+ "factory": "MediaWiki\\Tests\\Rest\\EntryPointTest::mockHandlerBodyRewind"
+ }
+]
--- /dev/null
+<?php
+
+namespace MediaWiki\Tests\Revision;
+
+use ActorMigration;
+use CommentStore;
+use MediaWiki\Logger\Spi as LoggerSpi;
+use MediaWiki\Revision\RevisionStore;
+use MediaWiki\Revision\RevisionStoreFactory;
+use MediaWiki\Revision\SlotRoleRegistry;
+use MediaWiki\Storage\BlobStore;
+use MediaWiki\Storage\BlobStoreFactory;
+use MediaWiki\Storage\NameTableStore;
+use MediaWiki\Storage\NameTableStoreFactory;
+use MediaWiki\Storage\SqlBlobStore;
+use Psr\Log\LoggerInterface;
+use Psr\Log\NullLogger;
+use WANObjectCache;
+use Wikimedia\Rdbms\ILBFactory;
+use Wikimedia\Rdbms\ILoadBalancer;
+use Wikimedia\TestingAccessWrapper;
+
+class RevisionStoreFactoryTest extends \MediaWikiUnitTestCase {
+
+ /**
+ * @covers \MediaWiki\Revision\RevisionStoreFactory::__construct
+ */
+ public function testValidConstruction_doesntCauseErrors() {
+ new RevisionStoreFactory(
+ $this->getMockLoadBalancerFactory(),
+ $this->getMockBlobStoreFactory(),
+ $this->getNameTableStoreFactory(),
+ $this->getMockSlotRoleRegistry(),
+ $this->getHashWANObjectCache(),
+ $this->getMockCommentStore(),
+ ActorMigration::newMigration(),
+ MIGRATION_OLD,
+ $this->getMockLoggerSpi(),
+ true
+ );
+ $this->assertTrue( true );
+ }
+
+ public function provideWikiIds() {
+ yield [ true ];
+ yield [ false ];
+ yield [ 'somewiki' ];
+ yield [ 'somewiki', MIGRATION_OLD , false ];
+ yield [ 'somewiki', MIGRATION_NEW , true ];
+ }
+
+ /**
+ * @dataProvider provideWikiIds
+ * @covers \MediaWiki\Revision\RevisionStoreFactory::getRevisionStore
+ */
+ public function testGetRevisionStore(
+ $dbDomain,
+ $mcrMigrationStage = MIGRATION_OLD,
+ $contentHandlerUseDb = true
+ ) {
+ $lbFactory = $this->getMockLoadBalancerFactory();
+ $blobStoreFactory = $this->getMockBlobStoreFactory();
+ $nameTableStoreFactory = $this->getNameTableStoreFactory();
+ $slotRoleRegistry = $this->getMockSlotRoleRegistry();
+ $cache = $this->getHashWANObjectCache();
+ $commentStore = $this->getMockCommentStore();
+ $actorMigration = ActorMigration::newMigration();
+ $loggerProvider = $this->getMockLoggerSpi();
+
+ $factory = new RevisionStoreFactory(
+ $lbFactory,
+ $blobStoreFactory,
+ $nameTableStoreFactory,
+ $slotRoleRegistry,
+ $cache,
+ $commentStore,
+ $actorMigration,
+ $mcrMigrationStage,
+ $loggerProvider,
+ $contentHandlerUseDb
+ );
+
+ $store = $factory->getRevisionStore( $dbDomain );
+ $wrapper = TestingAccessWrapper::newFromObject( $store );
+
+ // ensure the correct object type is returned
+ $this->assertInstanceOf( RevisionStore::class, $store );
+
+ // ensure the RevisionStore is for the given wikiId
+ $this->assertSame( $dbDomain, $wrapper->dbDomain );
+
+ // ensure all other required services are correctly set
+ $this->assertSame( $cache, $wrapper->cache );
+ $this->assertSame( $commentStore, $wrapper->commentStore );
+ $this->assertSame( $mcrMigrationStage, $wrapper->mcrMigrationStage );
+ $this->assertSame( $actorMigration, $wrapper->actorMigration );
+ $this->assertSame( $contentHandlerUseDb, $store->getContentHandlerUseDB() );
+
+ $this->assertInstanceOf( ILoadBalancer::class, $wrapper->loadBalancer );
+ $this->assertInstanceOf( BlobStore::class, $wrapper->blobStore );
+ $this->assertInstanceOf( NameTableStore::class, $wrapper->contentModelStore );
+ $this->assertInstanceOf( NameTableStore::class, $wrapper->slotRoleStore );
+ $this->assertInstanceOf( LoggerInterface::class, $wrapper->logger );
+ }
+
+ /**
+ * @return \PHPUnit_Framework_MockObject_MockObject|ILoadBalancer
+ */
+ private function getMockLoadBalancer() {
+ return $this->getMockBuilder( ILoadBalancer::class )
+ ->disableOriginalConstructor()->getMock();
+ }
+
+ /**
+ * @return \PHPUnit_Framework_MockObject_MockObject|ILBFactory
+ */
+ private function getMockLoadBalancerFactory() {
+ $mock = $this->getMockBuilder( ILBFactory::class )
+ ->disableOriginalConstructor()->getMock();
+
+ $mock->method( 'getMainLB' )
+ ->willReturnCallback( function () {
+ return $this->getMockLoadBalancer();
+ } );
+
+ return $mock;
+ }
+
+ /**
+ * @return \PHPUnit_Framework_MockObject_MockObject|SqlBlobStore
+ */
+ private function getMockSqlBlobStore() {
+ return $this->getMockBuilder( SqlBlobStore::class )
+ ->disableOriginalConstructor()->getMock();
+ }
+
+ /**
+ * @return \PHPUnit_Framework_MockObject_MockObject|BlobStoreFactory
+ */
+ private function getMockBlobStoreFactory() {
+ $mock = $this->getMockBuilder( BlobStoreFactory::class )
+ ->disableOriginalConstructor()->getMock();
+
+ $mock->method( 'newSqlBlobStore' )
+ ->willReturnCallback( function () {
+ return $this->getMockSqlBlobStore();
+ } );
+
+ return $mock;
+ }
+
+ /**
+ * @return SlotRoleRegistry
+ */
+ private function getMockSlotRoleRegistry() {
+ return $this->createMock( SlotRoleRegistry::class );
+ }
+
+ /**
+ * @return NameTableStoreFactory
+ */
+ private function getNameTableStoreFactory() {
+ return new NameTableStoreFactory(
+ $this->getMockLoadBalancerFactory(),
+ $this->getHashWANObjectCache(),
+ new NullLogger() );
+ }
+
+ /**
+ * @return \PHPUnit_Framework_MockObject_MockObject|CommentStore
+ */
+ private function getMockCommentStore() {
+ return $this->getMockBuilder( CommentStore::class )
+ ->disableOriginalConstructor()->getMock();
+ }
+
+ private function getHashWANObjectCache() {
+ return new WANObjectCache( [ 'cache' => new \HashBagOStuff() ] );
+ }
+
+ /**
+ * @return \PHPUnit_Framework_MockObject_MockObject|LoggerSpi
+ */
+ private function getMockLoggerSpi() {
+ $mock = $this->getMock( LoggerSpi::class );
+
+ $mock->method( 'getLogger' )
+ ->willReturn( new NullLogger() );
+
+ return $mock;
+ }
+
+}
--- /dev/null
+<?php
+
+use MediaWiki\MediaWikiServices;
+
+class ConfigFactoryTest extends \MediaWikiUnitTestCase {
+
+ /**
+ * @covers ConfigFactory::register
+ */
+ public function testRegister() {
+ $factory = new ConfigFactory();
+ $factory->register( 'unittest', 'GlobalVarConfig::newInstance' );
+ $this->assertInstanceOf( GlobalVarConfig::class, $factory->makeConfig( 'unittest' ) );
+ }
+
+ /**
+ * @covers ConfigFactory::register
+ */
+ public function testRegisterInvalid() {
+ $factory = new ConfigFactory();
+ $this->setExpectedException( InvalidArgumentException::class );
+ $factory->register( 'invalid', 'Invalid callback' );
+ }
+
+ /**
+ * @covers ConfigFactory::register
+ */
+ public function testRegisterInvalidInstance() {
+ $factory = new ConfigFactory();
+ $this->setExpectedException( InvalidArgumentException::class );
+ $factory->register( 'invalidInstance', new stdClass );
+ }
+
+ /**
+ * @covers ConfigFactory::register
+ */
+ public function testRegisterInstance() {
+ $config = GlobalVarConfig::newInstance();
+ $factory = new ConfigFactory();
+ $factory->register( 'unittest', $config );
+ $this->assertSame( $config, $factory->makeConfig( 'unittest' ) );
+ }
+
+ /**
+ * @covers ConfigFactory::register
+ */
+ public function testRegisterAgain() {
+ $factory = new ConfigFactory();
+ $factory->register( 'unittest', 'GlobalVarConfig::newInstance' );
+ $config1 = $factory->makeConfig( 'unittest' );
+
+ $factory->register( 'unittest', 'GlobalVarConfig::newInstance' );
+ $config2 = $factory->makeConfig( 'unittest' );
+
+ $this->assertNotSame( $config1, $config2 );
+ }
+
+ /**
+ * @covers ConfigFactory::salvage
+ */
+ public function testSalvage() {
+ $oldFactory = new ConfigFactory();
+ $oldFactory->register( 'foo', 'GlobalVarConfig::newInstance' );
+ $oldFactory->register( 'bar', 'GlobalVarConfig::newInstance' );
+ $oldFactory->register( 'quux', 'GlobalVarConfig::newInstance' );
+
+ // instantiate two of the three defined configurations
+ $foo = $oldFactory->makeConfig( 'foo' );
+ $bar = $oldFactory->makeConfig( 'bar' );
+ $quux = $oldFactory->makeConfig( 'quux' );
+
+ // define new config instance
+ $newFactory = new ConfigFactory();
+ $newFactory->register( 'foo', 'GlobalVarConfig::newInstance' );
+ $newFactory->register( 'bar', function () {
+ return new HashConfig();
+ } );
+
+ // "foo" and "quux" are defined in the old and the new factory.
+ // The old factory has instances for "foo" and "bar", but not "quux".
+ $newFactory->salvage( $oldFactory );
+
+ $newFoo = $newFactory->makeConfig( 'foo' );
+ $this->assertSame( $foo, $newFoo, 'existing instance should be salvaged' );
+
+ $newBar = $newFactory->makeConfig( 'bar' );
+ $this->assertNotSame( $bar, $newBar, 'don\'t salvage if callbacks differ' );
+
+ // the new factory doesn't have quux defined, so the quux instance should not be salvaged
+ $this->setExpectedException( ConfigException::class );
+ $newFactory->makeConfig( 'quux' );
+ }
+
+ /**
+ * @covers ConfigFactory::getConfigNames
+ */
+ public function testGetConfigNames() {
+ $factory = new ConfigFactory();
+ $factory->register( 'foo', 'GlobalVarConfig::newInstance' );
+ $factory->register( 'bar', new HashConfig() );
+
+ $this->assertEquals( [ 'foo', 'bar' ], $factory->getConfigNames() );
+ }
+
+ /**
+ * @covers ConfigFactory::makeConfig
+ */
+ public function testMakeConfigWithCallback() {
+ $factory = new ConfigFactory();
+ $factory->register( 'unittest', 'GlobalVarConfig::newInstance' );
+
+ $conf = $factory->makeConfig( 'unittest' );
+ $this->assertInstanceOf( Config::class, $conf );
+ $this->assertSame( $conf, $factory->makeConfig( 'unittest' ) );
+ }
+
+ /**
+ * @covers ConfigFactory::makeConfig
+ */
+ public function testMakeConfigWithObject() {
+ $factory = new ConfigFactory();
+ $conf = new HashConfig();
+ $factory->register( 'test', $conf );
+ $this->assertSame( $conf, $factory->makeConfig( 'test' ) );
+ }
+
+ /**
+ * @covers ConfigFactory::makeConfig
+ */
+ public function testMakeConfigFallback() {
+ $factory = new ConfigFactory();
+ $factory->register( '*', 'GlobalVarConfig::newInstance' );
+ $conf = $factory->makeConfig( 'unittest' );
+ $this->assertInstanceOf( Config::class, $conf );
+ }
+
+ /**
+ * @covers ConfigFactory::makeConfig
+ */
+ public function testMakeConfigWithNoBuilders() {
+ $factory = new ConfigFactory();
+ $this->setExpectedException( ConfigException::class );
+ $factory->makeConfig( 'nobuilderregistered' );
+ }
+
+ /**
+ * @covers ConfigFactory::makeConfig
+ */
+ public function testMakeConfigWithInvalidCallback() {
+ $factory = new ConfigFactory();
+ $factory->register( 'unittest', function () {
+ return true; // Not a Config object
+ } );
+ $this->setExpectedException( UnexpectedValueException::class );
+ $factory->makeConfig( 'unittest' );
+ }
+
+ /**
+ * @covers ConfigFactory::getDefaultInstance
+ */
+ public function testGetDefaultInstance() {
+ // NOTE: the global config factory returned here has been overwritten
+ // for operation in test mode. It may not reflect LocalSettings.
+ $factory = MediaWikiServices::getInstance()->getConfigFactory();
+ $this->assertInstanceOf( Config::class, $factory->makeConfig( 'main' ) );
+ }
+
+}
--- /dev/null
+<?php
+
+/**
+ * @group Media
+ */
+class GIFMetadataExtractorTest extends \MediaWikiUnitTestCase {
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->mediaPath = __DIR__ . '/../../../data/media/';
+ }
+
+ /**
+ * Put in a file, and see if the metadata coming out is as expected.
+ * @param string $filename
+ * @param array $expected The extracted metadata.
+ * @dataProvider provideGetMetadata
+ * @covers GIFMetadataExtractor::getMetadata
+ */
+ public function testGetMetadata( $filename, $expected ) {
+ $actual = GIFMetadataExtractor::getMetadata( $this->mediaPath . $filename );
+ $this->assertEquals( $expected, $actual );
+ }
+
+ public static function provideGetMetadata() {
+ $xmpNugget = <<<EOF
+<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?>
+<x:xmpmeta xmlns:x='adobe:ns:meta/' x:xmptk='Image::ExifTool 7.30'>
+<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>
+
+ <rdf:Description rdf:about=''
+ xmlns:Iptc4xmpCore='http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/'>
+ <Iptc4xmpCore:Location>The interwebs</Iptc4xmpCore:Location>
+ </rdf:Description>
+
+ <rdf:Description rdf:about=''
+ xmlns:tiff='http://ns.adobe.com/tiff/1.0/'>
+ <tiff:Artist>Bawolff</tiff:Artist>
+ <tiff:ImageDescription>
+ <rdf:Alt>
+ <rdf:li xml:lang='x-default'>A file to test GIF</rdf:li>
+ </rdf:Alt>
+ </tiff:ImageDescription>
+ </rdf:Description>
+</rdf:RDF>
+</x:xmpmeta>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<?xpacket end='w'?>
+EOF;
+ $xmpNugget = str_replace( "\r", '', $xmpNugget ); // Windows compat
+
+ return [
+ [
+ 'nonanimated.gif',
+ [
+ 'comment' => [ 'GIF test file ⁕ Created with GIMP' ],
+ 'duration' => 0.1,
+ 'frameCount' => 1,
+ 'looped' => false,
+ 'xmp' => '',
+ ]
+ ],
+ [
+ 'animated.gif',
+ [
+ 'comment' => [ 'GIF test file . Created with GIMP' ],
+ 'duration' => 2.4,
+ 'frameCount' => 4,
+ 'looped' => true,
+ 'xmp' => '',
+ ]
+ ],
+
+ [
+ 'animated-xmp.gif',
+ [
+ 'xmp' => $xmpNugget,
+ 'duration' => 2.4,
+ 'frameCount' => 4,
+ 'looped' => true,
+ 'comment' => [ 'GIƒ·test·file' ],
+ ]
+ ],
+ ];
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @group Media
+ * @covers SVGMetadataExtractor
+ */
+class SVGMetadataExtractorTest extends \MediaWikiUnitTestCase {
+
+ /**
+ * @dataProvider provideSvgFiles
+ */
+ public function testGetMetadata( $infile, $expected ) {
+ $this->assertMetadata( $infile, $expected );
+ }
+
+ /**
+ * @dataProvider provideSvgFilesWithXMLMetadata
+ */
+ public function testGetXMLMetadata( $infile, $expected ) {
+ $r = new XMLReader();
+ $this->assertMetadata( $infile, $expected );
+ }
+
+ /**
+ * @dataProvider provideSvgUnits
+ */
+ public function testScaleSVGUnit( $inUnit, $expected ) {
+ $this->assertEquals(
+ $expected,
+ SVGReader::scaleSVGUnit( $inUnit ),
+ 'SVG unit conversion and scaling failure'
+ );
+ }
+
+ function assertMetadata( $infile, $expected ) {
+ try {
+ $data = SVGMetadataExtractor::getMetadata( $infile );
+ $this->assertEquals( $expected, $data, 'SVG metadata extraction test' );
+ } catch ( MWException $e ) {
+ if ( $expected === false ) {
+ $this->assertTrue( true, 'SVG metadata extracted test (expected failure)' );
+ } else {
+ throw $e;
+ }
+ }
+ }
+
+ public static function provideSvgFiles() {
+ $base = __DIR__ . '/../../../data/media';
+
+ return [
+ [
+ "$base/Wikimedia-logo.svg",
+ [
+ 'width' => 1024,
+ 'height' => 1024,
+ 'originalWidth' => '1024',
+ 'originalHeight' => '1024',
+ 'translations' => [],
+ ]
+ ],
+ [
+ "$base/QA_icon.svg",
+ [
+ 'width' => 60,
+ 'height' => 60,
+ 'originalWidth' => '60',
+ 'originalHeight' => '60',
+ 'translations' => [],
+ ]
+ ],
+ [
+ "$base/Gtk-media-play-ltr.svg",
+ [
+ 'width' => 60,
+ 'height' => 60,
+ 'originalWidth' => '60.0000000',
+ 'originalHeight' => '60.0000000',
+ 'translations' => [],
+ ]
+ ],
+ [
+ "$base/Toll_Texas_1.svg",
+ // This file triggered T33719, needs entity expansion in the xmlns checks
+ [
+ 'width' => 385,
+ 'height' => 385,
+ 'originalWidth' => '385',
+ 'originalHeight' => '385.0004883',
+ 'translations' => [],
+ ]
+ ],
+ [
+ "$base/Tux.svg",
+ [
+ 'width' => 512,
+ 'height' => 594,
+ 'originalWidth' => '100%',
+ 'originalHeight' => '100%',
+ 'title' => 'Tux',
+ 'translations' => [],
+ 'description' => 'For more information see: http://commons.wikimedia.org/wiki/Image:Tux.svg',
+ ]
+ ],
+ [
+ "$base/Speech_bubbles.svg",
+ [
+ 'width' => 627,
+ 'height' => 461,
+ 'originalWidth' => '17.7cm',
+ 'originalHeight' => '13cm',
+ 'translations' => [
+ 'de' => SVGReader::LANG_FULL_MATCH,
+ 'fr' => SVGReader::LANG_FULL_MATCH,
+ 'nl' => SVGReader::LANG_FULL_MATCH,
+ 'tlh-ca' => SVGReader::LANG_FULL_MATCH,
+ 'tlh' => SVGReader::LANG_PREFIX_MATCH
+ ],
+ ]
+ ],
+ [
+ "$base/Soccer_ball_animated.svg",
+ [
+ 'width' => 150,
+ 'height' => 150,
+ 'originalWidth' => '150',
+ 'originalHeight' => '150',
+ 'animated' => true,
+ 'translations' => []
+ ],
+ ],
+ [
+ "$base/comma_separated_viewbox.svg",
+ [
+ 'width' => 512,
+ 'height' => 594,
+ 'originalWidth' => '100%',
+ 'originalHeight' => '100%',
+ 'translations' => []
+ ],
+ ],
+ ];
+ }
+
+ public static function provideSvgFilesWithXMLMetadata() {
+ $base = __DIR__ . '/../../../data/media';
+ // phpcs:disable Generic.Files.LineLength
+ $metadata = '<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+ <ns4:Work xmlns:ns4="http://creativecommons.org/ns#" rdf:about="">
+ <ns5:format xmlns:ns5="http://purl.org/dc/elements/1.1/">image/svg+xml</ns5:format>
+ <ns5:type xmlns:ns5="http://purl.org/dc/elements/1.1/" rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
+ </ns4:Work>
+ </rdf:RDF>';
+ // phpcs:enable
+
+ $metadata = str_replace( "\r", '', $metadata ); // Windows compat
+ return [
+ [
+ "$base/US_states_by_total_state_tax_revenue.svg",
+ [
+ 'height' => 593,
+ 'metadata' => $metadata,
+ 'width' => 959,
+ 'originalWidth' => '958.69',
+ 'originalHeight' => '592.78998',
+ 'translations' => [],
+ ]
+ ],
+ ];
+ }
+
+ public static function provideSvgUnits() {
+ return [
+ [ '1' , 1 ],
+ [ '1.1' , 1.1 ],
+ [ '0.1' , 0.1 ],
+ [ '.1' , 0.1 ],
+ [ '1e2' , 100 ],
+ [ '1E2' , 100 ],
+ [ '+1' , 1 ],
+ [ '-1' , -1 ],
+ [ '-1.1' , -1.1 ],
+ [ '1e+2' , 100 ],
+ [ '1e-2' , 0.01 ],
+ [ '10px' , 10 ],
+ [ '10pt' , 10 * 1.25 ],
+ [ '10pc' , 10 * 15 ],
+ [ '10mm' , 10 * 3.543307 ],
+ [ '10cm' , 10 * 35.43307 ],
+ [ '10in' , 10 * 90 ],
+ [ '10em' , 10 * 16 ],
+ [ '10ex' , 10 * 12 ],
+ [ '10%' , 51.2 ],
+ [ '10 px' , 10 ],
+ // Invalid values
+ [ '1e1.1', 10 ],
+ [ '10bp', 10 ],
+ [ 'p10', null ],
+ ];
+ }
+}
--- /dev/null
+<?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
+ * @since 1.25
+ *
+ * @ingroup Site
+ * @ingroup Test
+ *
+ * @group Site
+ * @group Database
+ *
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class CachingSiteStoreTest extends \MediaWikiUnitTestCase {
+
+ /**
+ * @covers CachingSiteStore::getSites
+ */
+ public function testGetSites() {
+ $testSites = TestSites::getSites();
+
+ $store = new CachingSiteStore(
+ $this->getHashSiteStore( $testSites ),
+ ObjectCache::getLocalClusterInstance()
+ );
+
+ $sites = $store->getSites();
+
+ $this->assertInstanceOf( SiteList::class, $sites );
+
+ /**
+ * @var Site $site
+ */
+ foreach ( $sites as $site ) {
+ $this->assertInstanceOf( Site::class, $site );
+ }
+
+ foreach ( $testSites as $site ) {
+ if ( $site->getGlobalId() !== null ) {
+ $this->assertTrue( $sites->hasSite( $site->getGlobalId() ) );
+ }
+ }
+ }
+
+ /**
+ * @covers CachingSiteStore::saveSites
+ */
+ public function testSaveSites() {
+ $store = new CachingSiteStore(
+ new HashSiteStore(), ObjectCache::getLocalClusterInstance()
+ );
+
+ $sites = [];
+
+ $site = new Site();
+ $site->setGlobalId( 'ertrywuutr' );
+ $site->setLanguageCode( 'en' );
+ $sites[] = $site;
+
+ $site = new MediaWikiSite();
+ $site->setGlobalId( 'sdfhxujgkfpth' );
+ $site->setLanguageCode( 'nl' );
+ $sites[] = $site;
+
+ $this->assertTrue( $store->saveSites( $sites ) );
+
+ $site = $store->getSite( 'ertrywuutr' );
+ $this->assertInstanceOf( Site::class, $site );
+ $this->assertEquals( 'en', $site->getLanguageCode() );
+
+ $site = $store->getSite( 'sdfhxujgkfpth' );
+ $this->assertInstanceOf( Site::class, $site );
+ $this->assertEquals( 'nl', $site->getLanguageCode() );
+ }
+
+ /**
+ * @covers CachingSiteStore::reset
+ */
+ public function testReset() {
+ $dbSiteStore = $this->getMockBuilder( SiteStore::class )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dbSiteStore->expects( $this->any() )
+ ->method( 'getSite' )
+ ->will( $this->returnValue( $this->getTestSite() ) );
+
+ $dbSiteStore->expects( $this->any() )
+ ->method( 'getSites' )
+ ->will( $this->returnCallback( function () {
+ $siteList = new SiteList();
+ $siteList->setSite( $this->getTestSite() );
+
+ return $siteList;
+ } ) );
+
+ $store = new CachingSiteStore( $dbSiteStore, ObjectCache::getLocalClusterInstance() );
+
+ // initialize internal cache
+ $this->assertGreaterThan( 0, $store->getSites()->count(), 'count sites' );
+
+ $store->getSite( 'enwiki' )->setLanguageCode( 'en-ca' );
+
+ // sanity check: $store should have the new language code for 'enwiki'
+ $this->assertEquals( 'en-ca', $store->getSite( 'enwiki' )->getLanguageCode(), 'sanity check' );
+
+ // purge cache
+ $store->reset();
+
+ // the internal cache of $store should be updated, and now pulling
+ // the site from the 'fallback' DBSiteStore with the original language code.
+ $this->assertEquals( 'en', $store->getSite( 'enwiki' )->getLanguageCode(), 'reset' );
+ }
+
+ public function getTestSite() {
+ $enwiki = new MediaWikiSite();
+ $enwiki->setGlobalId( 'enwiki' );
+ $enwiki->setLanguageCode( 'en' );
+
+ return $enwiki;
+ }
+
+ /**
+ * @covers CachingSiteStore::clear
+ */
+ public function testClear() {
+ $store = new CachingSiteStore(
+ new HashSiteStore(), ObjectCache::getLocalClusterInstance()
+ );
+ $this->assertTrue( $store->clear() );
+
+ $site = $store->getSite( 'enwiki' );
+ $this->assertNull( $site );
+
+ $sites = $store->getSites();
+ $this->assertEquals( 0, $sites->count() );
+ }
+
+ /**
+ * @param Site[] $sites
+ *
+ * @return SiteStore
+ */
+ private function getHashSiteStore( array $sites ) {
+ $siteStore = new HashSiteStore();
+ $siteStore->saveSites( $sites );
+
+ return $siteStore;
+ }
+
+}
--- /dev/null
+<?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
+ * @since 1.25
+ *
+ * @ingroup Site
+ * @group Site
+ *
+ * @author Katie Filbert < aude.wiki@gmail.com >
+ */
+class HashSiteStoreTest extends \MediaWikiUnitTestCase {
+
+ /**
+ * @covers HashSiteStore::getSites
+ */
+ public function testGetSites() {
+ $expectedSites = [];
+
+ foreach ( TestSites::getSites() as $testSite ) {
+ $siteId = $testSite->getGlobalId();
+ $expectedSites[$siteId] = $testSite;
+ }
+
+ $siteStore = new HashSiteStore( $expectedSites );
+
+ $this->assertEquals( new SiteList( $expectedSites ), $siteStore->getSites() );
+ }
+
+ /**
+ * @covers HashSiteStore::saveSite
+ * @covers HashSiteStore::getSite
+ */
+ public function testSaveSite() {
+ $store = new HashSiteStore();
+
+ $site = new Site();
+ $site->setGlobalId( 'dewiki' );
+
+ $this->assertCount( 0, $store->getSites(), '0 sites in store' );
+
+ $store->saveSite( $site );
+
+ $this->assertCount( 1, $store->getSites(), 'Store has 1 sites' );
+ $this->assertEquals( $site, $store->getSite( 'dewiki' ), 'Store has dewiki' );
+ }
+
+ /**
+ * @covers HashSiteStore::saveSites
+ */
+ public function testSaveSites() {
+ $store = new HashSiteStore();
+
+ $sites = [];
+
+ $site = new Site();
+ $site->setGlobalId( 'enwiki' );
+ $site->setLanguageCode( 'en' );
+ $sites[] = $site;
+
+ $site = new MediaWikiSite();
+ $site->setGlobalId( 'eswiki' );
+ $site->setLanguageCode( 'es' );
+ $sites[] = $site;
+
+ $this->assertCount( 0, $store->getSites(), '0 sites in store' );
+
+ $store->saveSites( $sites );
+
+ $this->assertCount( 2, $store->getSites(), 'Store has 2 sites' );
+ $this->assertTrue( $store->getSites()->hasSite( 'enwiki' ), 'Store has enwiki' );
+ $this->assertTrue( $store->getSites()->hasSite( 'eswiki' ), 'Store has eswiki' );
+ }
+
+ /**
+ * @covers HashSiteStore::clear
+ */
+ public function testClear() {
+ $store = new HashSiteStore();
+
+ $site = new Site();
+ $site->setGlobalId( 'arwiki' );
+ $store->saveSite( $site );
+
+ $this->assertCount( 1, $store->getSites(), '1 site in store' );
+
+ $store->clear();
+ $this->assertCount( 0, $store->getSites(), '0 sites in store' );
+ }
+}