wiki.techinc.nl/tests/phpunit/tests/MediaWikiIntegrationTestCaseTest.php
Umherirrender a1de8b8700 Tests: Mark more more closures as static
Result of a new sniff I25a17fb22b6b669e817317a0f45051ae9c608208

Bug: T274036
Change-Id: I695873737167a75f0d94901fa40383a33984ca55
2021-02-09 02:55:57 +00:00

445 lines
13 KiB
PHP

<?php
use MediaWiki\Logger\LoggerFactory;
use MediaWiki\MediaWikiServices;
use MediaWiki\Revision\RevisionRecord;
use MediaWiki\Storage\SlotRecord;
use PHPUnit\Framework\AssertionFailedError;
use Psr\Log\LoggerInterface;
use Wikimedia\Rdbms\LoadBalancer;
use Wikimedia\TestingAccessWrapper;
/**
* @covers MediaWikiIntegrationTestCase
* @group MediaWikiIntegrationTestCaseTest
* @group Database
*
* @author Addshore
*/
class MediaWikiIntegrationTestCaseTest extends MediaWikiIntegrationTestCase {
private static $startGlobals = [
'MediaWikiIntegrationTestCaseTestGLOBAL-ExistingString' => 'foo',
'MediaWikiIntegrationTestCaseTestGLOBAL-ExistingStringEmpty' => '',
'MediaWikiIntegrationTestCaseTestGLOBAL-ExistingArray' => [ 1, 'foo' => 'bar' ],
'MediaWikiIntegrationTestCaseTestGLOBAL-ExistingArrayEmpty' => [],
];
public static function setUpBeforeClass() : void {
parent::setUpBeforeClass();
foreach ( self::$startGlobals as $key => $value ) {
$GLOBALS[$key] = $value;
}
}
public static function tearDownAfterClass() : void {
parent::tearDownAfterClass();
foreach ( self::$startGlobals as $key => $value ) {
unset( $GLOBALS[$key] );
}
}
public function provideExistingKeysAndNewValues() {
$providedArray = [];
foreach ( array_keys( self::$startGlobals ) as $key ) {
$providedArray[] = [ $key, 'newValue' ];
$providedArray[] = [ $key, [ 'newValue' ] ];
}
return $providedArray;
}
/**
* @dataProvider provideExistingKeysAndNewValues
*
* @covers MediaWikiIntegrationTestCase::setMwGlobals
* @covers MediaWikiIntegrationTestCase::tearDown
*/
public function testSetGlobalsAreRestoredOnTearDown( $globalKey, $newValue ) {
$this->setMwGlobals( $globalKey, $newValue );
$this->assertEquals(
$newValue,
$GLOBALS[$globalKey],
'Global failed to correctly set'
);
$this->mediaWikiTearDown();
$this->assertEquals(
self::$startGlobals[$globalKey],
$GLOBALS[$globalKey],
'Global failed to be restored on tearDown'
);
}
/**
* @covers MediaWikiIntegrationTestCase::setMwGlobals
* @covers MediaWikiIntegrationTestCase::tearDown
*/
public function testSetNonExistentGlobalsAreUnsetOnTearDown() {
$globalKey = 'abcdefg1234567';
$this->setMwGlobals( $globalKey, true );
$this->assertTrue(
$GLOBALS[$globalKey],
'Global failed to correctly set'
);
$this->mediaWikiTearDown();
$this->assertFalse(
isset( $GLOBALS[$globalKey] ),
'Global failed to be correctly unset'
);
}
public function testOverrideMwServices() {
$initialServices = MediaWikiServices::getInstance();
$this->overrideMwServices();
$this->assertNotSame( $initialServices, MediaWikiServices::getInstance() );
}
public function testSetService() {
$initialServices = MediaWikiServices::getInstance();
$initialService = $initialServices->getDBLoadBalancer();
$mockService = $this->getMockBuilder( LoadBalancer::class )
->disableOriginalConstructor()->getMock();
$this->setService( 'DBLoadBalancer', $mockService );
$this->assertNotSame(
$initialService,
MediaWikiServices::getInstance()->getDBLoadBalancer()
);
$this->assertSame( $mockService, MediaWikiServices::getInstance()->getDBLoadBalancer() );
}
/**
* @covers MediaWikiIntegrationTestCase::setLogger
* @covers MediaWikiIntegrationTestCase::restoreLoggers
*/
public function testLoggersAreRestoredOnTearDown_replacingExistingLogger() {
$logger1 = LoggerFactory::getInstance( 'foo' );
$this->setLogger( 'foo', $this->createMock( LoggerInterface::class ) );
$logger2 = LoggerFactory::getInstance( 'foo' );
$this->mediaWikiTearDown();
$logger3 = LoggerFactory::getInstance( 'foo' );
$this->assertSame( $logger1, $logger3 );
$this->assertNotSame( $logger1, $logger2 );
}
/**
* @covers MediaWikiIntegrationTestCase::setLogger
* @covers MediaWikiIntegrationTestCase::restoreLoggers
*/
public function testLoggersAreRestoredOnTearDown_replacingNonExistingLogger() {
$this->setLogger( 'foo', $this->createMock( LoggerInterface::class ) );
$logger1 = LoggerFactory::getInstance( 'foo' );
$this->mediaWikiTearDown();
$logger2 = LoggerFactory::getInstance( 'foo' );
$this->assertNotSame( $logger1, $logger2 );
$this->assertInstanceOf( \Psr\Log\LoggerInterface::class, $logger2 );
}
/**
* @covers MediaWikiIntegrationTestCase::setLogger
* @covers MediaWikiIntegrationTestCase::restoreLoggers
*/
public function testLoggersAreRestoredOnTearDown_replacingSameLoggerTwice() {
$logger1 = LoggerFactory::getInstance( 'baz' );
$this->setLogger( 'foo', $this->createMock( LoggerInterface::class ) );
$this->setLogger( 'foo', $this->createMock( LoggerInterface::class ) );
$this->mediaWikiTearDown();
$logger2 = LoggerFactory::getInstance( 'baz' );
$this->assertSame( $logger1, $logger2 );
}
/**
* @covers MediaWikiIntegrationTestCase::setNullLogger
* @covers MediaWikiIntegrationTestCase::restoreLoggers
*/
public function testNullLogger_createAndRemove() {
$this->setNullLogger( 'tocreate' );
$logger = LoggerFactory::getInstance( 'tocreate' );
$this->assertInstanceOf( \Psr\Log\NullLogger::class, $logger );
$this->mediaWikiTearDown();
$logger = LoggerFactory::getInstance( 'tocreate' );
// Unwrap from LogCapturingSpi
$inner = TestingAccessWrapper::newFromObject( $logger )->logger;
$this->assertInstanceOf( \MediaWiki\Logger\LegacyLogger::class, $inner );
}
/**
* @covers MediaWikiIntegrationTestCase::setNullLogger
* @covers MediaWikiIntegrationTestCase::restoreLoggers
*/
public function testNullLogger_mutateAndRestore() {
// Don't rely on the $wgDebugLogGroups and $wgDebugLogFile settings in
// WMF CI to make LEVEL_DEBUG (100) the default. Control this in the test.
$this->setMwGlobals( 'wgDebugToolbar', true );
$logger = LoggerFactory::getInstance( 'tomutate' );
// Unwrap from LogCapturingSpi
$inner = TestingAccessWrapper::newFromObject( $logger )->logger;
$this->assertInstanceOf( \MediaWiki\Logger\LegacyLogger::class, $inner );
$this->assertSame(
100,
TestingAccessWrapper::newFromObject( $inner )->minimumLevel,
'original minimumLevel'
);
$this->setNullLogger( 'tomutate' );
$this->assertSame(
999,
TestingAccessWrapper::newFromObject( $inner )->minimumLevel,
'changed minimumLevel'
);
$this->mediaWikiTearDown();
$this->assertSame(
100,
TestingAccessWrapper::newFromObject( $inner )->minimumLevel,
'restored minimumLevel'
);
}
/**
* @covers MediaWikiIntegrationTestCase::setupDatabaseWithTestPrefix
* @covers MediaWikiIntegrationTestCase::copyTestData
*/
public function testCopyTestData() {
$this->markTestSkippedIfDbType( 'sqlite' );
$this->tablesUsed[] = 'objectcache';
$this->db->insert(
'objectcache',
[ 'keyname' => __METHOD__, 'value' => 'TEST', 'exptime' => $this->db->timestamp( 11 ) ],
__METHOD__
);
$lbFactory = $this->getServiceContainer()->getDBLoadBalancerFactory();
$lb = $lbFactory->newMainLB();
$db = $lb->getConnection( DB_REPLICA );
// sanity
$this->assertNotSame( $this->db, $db );
// Make sure the DB connection has the fake table clones and the fake table prefix
MediaWikiIntegrationTestCase::setupDatabaseWithTestPrefix( $db, $this->dbPrefix(), false );
$this->assertSame( $this->db->tablePrefix(), $db->tablePrefix(), 'tablePrefix' );
// Make sure the DB connection has all the test data
$this->copyTestData( $this->db, $db );
$value = $db->selectField( 'objectcache', 'value', [ 'keyname' => __METHOD__ ], __METHOD__ );
$this->assertSame( 'TEST', $value, 'Copied Data' );
}
/**
* @covers MediaWikiIntegrationTestCase::resetServices
*/
public function testResetServices() {
$services = MediaWikiServices::getInstance();
// override a service instance
$myReadOnlyMode = $this->getMockBuilder( ReadOnlyMode::class )
->disableOriginalConstructor()
->getMock();
$this->setService( 'ReadOnlyMode', $myReadOnlyMode );
$this->setTemporaryHook( 'MyTestHook', static function ( &$n ) {
$n++;
}, true );
// sanity check
$this->assertSame( $myReadOnlyMode, $services->getService( 'ReadOnlyMode' ) );
// define a custom service
$services->defineService(
'_TEST_ResetService_Dummy',
static function ( MediaWikiServices $services ) {
$conf = $services->getMainConfig();
return (object)[ 'lang' => $conf->get( 'LanguageCode' ) ];
}
);
// sanity check
$lang = $services->getMainConfig()->get( 'LanguageCode' );
$dummy = $services->getService( '_TEST_ResetService_Dummy' );
$this->assertSame( $lang, $dummy->lang );
// the actual test: change config, reset services.
$this->setMwGlobals( 'wgLanguageCode', 'qqx' );
$this->resetServices();
// the overridden service instance should still be there
$this->assertSame( $myReadOnlyMode, $services->getService( 'ReadOnlyMode' ) );
// the temporary hook should still be there
$this->assertTrue(
$this->getServiceContainer()->getHookContainer()->isRegistered( 'MyTestHook' )
);
// our custom service should have been re-created with the new language code
$dummy2 = $services->getService( '_TEST_ResetService_Dummy' );
$this->assertNotSame( $dummy2, $dummy );
$this->assertSame( 'qqx', $dummy2->lang );
}
/**
* @covers MediaWikiIntegrationTestCase::getServiceContainer
*/
public function testGetServiceContainer() {
$this->assertSame( MediaWikiServices::getInstance(), $this->getServiceContainer() );
}
/**
* @covers MediaWikiIntegrationTestCase::setTemporaryHook
* @covers MediaWikiIntegrationTestCase::clearHook
*/
public function testSetTemporaryHook() {
$hookContainer = $this->getServiceContainer()->getHookContainer();
$name = 'MWITCT_Dummy_Hook';
$inc = static function ( &$n ) {
$n++;
};
// add two handlers
$this->setTemporaryHook( $name, $inc, false );
$this->setTemporaryHook( $name, $inc, false );
$count = 0;
$hookContainer->run( $name, [ &$count ] );
$this->assertSame( 2, $count );
// replace existing hooks
$this->setTemporaryHook( $name, $inc );
$count = 0;
$hookContainer->run( $name, [ &$count ] );
$this->assertSame( 1, $count );
// clear all hooks
$this->clearHook( $name );
$count = 0;
$hookContainer->run( $name, [ &$count ] );
$this->assertSame( 0, $count );
// Put back a hook handler, so we can check in testSetTemporaryHookGetsReset
// that hooks get reset between tests.
$this->setTemporaryHook( $name, $inc );
$this->assertTrue( $hookContainer->isRegistered( 'MWITCT_Dummy_Hook' ) );
}
public function testSetTemporaryHookGetsReset() {
// We just check here that the hook we added in testSetTemporaryHook() is no longer present.
$hookContainer = $this->getServiceContainer()->getHookContainer();
$this->assertFalse( $hookContainer->isRegistered( 'MWITCT_Dummy_Hook' ) );
}
/**
* @covers NullHttpRequestFactory
* @covers NullMultiHttpClient
*/
public function testHttpRequestsArePrevented() {
$httpRequestFactory = $this->getServiceContainer()->getHttpRequestFactory();
$prevented = true;
try {
$httpRequestFactory->get( 'http://0.0.0.0/' );
$prevented = false;
} catch ( AssertionFailedError $e ) {
// pass
}
$this->assertTrue( $prevented, 'get() should fail' );
try {
$httpRequestFactory->post( 'http://0.0.0.0/' );
$prevented = false;
} catch ( AssertionFailedError $e ) {
// pass
}
$this->assertTrue( $prevented, 'post() should fail' );
try {
$httpRequestFactory->request( 'HEAD', 'http://0.0.0.0/' );
$prevented = false;
} catch ( AssertionFailedError $e ) {
// pass
}
$this->assertTrue( $prevented, 'request() should fail' );
try {
$httpRequestFactory->create( 'http://0.0.0.0/' );
$prevented = false;
} catch ( AssertionFailedError $e ) {
// pass
}
$this->assertTrue( $prevented, 'create() should fail' );
try {
$httpRequestFactory->createGuzzleClient();
$prevented = false;
} catch ( AssertionFailedError $e ) {
// pass
}
$this->assertTrue( $prevented, 'createGuzzleClient() should fail' );
$multiClient = $httpRequestFactory->createMultiClient();
$req = [ 'url' => 'http://0.0.0.0/' ];
try {
$multiClient->run( $req );
$prevented = false;
} catch ( AssertionFailedError $e ) {
// pass
}
$this->assertTrue( $prevented, 'MultiHttpRequest::run() should fail' );
try {
$multiClient->runMulti( [ $req ] );
$prevented = false;
} catch ( AssertionFailedError $e ) {
// pass
}
$this->assertTrue( $prevented, 'MultiHttpRequest::runMulti() should fail' );
}
public function testEditPage() {
// NOTE: can't use a data provider, since creating Title or WikiPage instances
// is not safe without the test DB having been initialized.
$this->assertEditPage( 'Hello Wörld A', __METHOD__, 'Hello Wörld A' );
$this->assertEditPage( 'Hello Wörld B', __METHOD__, new TextContent( 'Hello Wörld B' ) );
$this->assertEditPage( 'Hello Wörld C', Title::newFromText( __METHOD__ ), 'Hello Wörld C' );
$this->assertEditPage(
'Hello Wörld D',
new WikiPage( Title::newFromText( __METHOD__ ) ),
'Hello Wörld D'
);
}
public function assertEditPage( $expected, $page, $content ) {
$status = $this->editPage( $page, $content );
$this->assertTrue( $status->isOK() );
$this->assertNotNull( $status->getValue()['revision-record'] );
/** @var RevisionRecord $rev */
$rev = $status->getValue()['revision-record'];
$cnt = $rev->getContent( SlotRecord::MAIN );
$this->assertSame( $expected, $cnt->serialize() );
}
}