2 use Liuggio\StatsdClient\Factory\StatsdDataFactory
;
3 use MediaWiki\MediaWikiServices
;
4 use MediaWiki\Services\ServiceDisabledException
;
7 * @covers MediaWiki\MediaWikiServices
11 class MediaWikiServicesTest
extends PHPUnit_Framework_TestCase
{
16 private function newTestConfig() {
17 $globalConfig = new GlobalVarConfig();
19 $testConfig = new HashConfig();
20 $testConfig->set( 'ServiceWiringFiles', $globalConfig->get( 'ServiceWiringFiles' ) );
21 $testConfig->set( 'ConfigRegistry', $globalConfig->get( 'ConfigRegistry' ) );
27 * @return MediaWikiServices
29 private function newMediaWikiServices( Config
$config = null ) {
30 if ( $config === null ) {
31 $config = $this->newTestConfig();
34 $instance = new MediaWikiServices( $config );
36 // Load the default wiring from the specified files.
37 $wiringFiles = $config->get( 'ServiceWiringFiles' );
38 $instance->loadWiringFiles( $wiringFiles );
43 public function testGetInstance() {
44 $services = MediaWikiServices
::getInstance();
45 $this->assertInstanceOf( 'MediaWiki\\MediaWikiServices', $services );
48 public function testForceGlobalInstance() {
49 $newServices = $this->newMediaWikiServices();
50 $oldServices = MediaWikiServices
::forceGlobalInstance( $newServices );
52 $this->assertInstanceOf( 'MediaWiki\\MediaWikiServices', $oldServices );
53 $this->assertNotSame( $oldServices, $newServices );
55 $theServices = MediaWikiServices
::getInstance();
56 $this->assertSame( $theServices, $newServices );
58 MediaWikiServices
::forceGlobalInstance( $oldServices );
60 $theServices = MediaWikiServices
::getInstance();
61 $this->assertSame( $theServices, $oldServices );
64 public function testResetGlobalInstance() {
65 $newServices = $this->newMediaWikiServices();
66 $oldServices = MediaWikiServices
::forceGlobalInstance( $newServices );
68 MediaWikiServices
::resetGlobalInstance( $this->newTestConfig() );
69 $theServices = MediaWikiServices
::getInstance();
71 $this->assertNotSame( $theServices, $newServices );
72 $this->assertNotSame( $theServices, $oldServices );
74 MediaWikiServices
::forceGlobalInstance( $oldServices );
77 public function testDisableStorageBackend() {
78 $newServices = $this->newMediaWikiServices();
79 $oldServices = MediaWikiServices
::forceGlobalInstance( $newServices );
81 $lbFactory = $this->getMockBuilder( 'LBFactorySimple' )
82 ->disableOriginalConstructor()
85 $lbFactory->expects( $this->once() )
86 ->method( 'destroy' );
88 $newServices->redefineService(
89 'DBLoadBalancerFactory',
90 function() use ( $lbFactory ) {
95 // force the service to become active, so we can check that it does get destroyed
96 $newServices->getService( 'DBLoadBalancerFactory' );
98 MediaWikiServices
::disableStorageBackend(); // should destroy DBLoadBalancerFactory
101 MediaWikiServices
::getInstance()->getService( 'DBLoadBalancerFactory' );
102 $this->fail( 'DBLoadBalancerFactory shoudl have been disabled' );
104 catch ( ServiceDisabledException
$ex ) {
107 catch ( Throwable
$ex ) {
108 $this->fail( 'ServiceDisabledException expected, caught ' . get_class( $ex ) );
111 MediaWikiServices
::forceGlobalInstance( $oldServices );
114 public function testResetChildProcessServices() {
115 $newServices = $this->newMediaWikiServices();
116 $oldServices = MediaWikiServices
::forceGlobalInstance( $newServices );
118 $lbFactory = $this->getMockBuilder( 'LBFactorySimple' )
119 ->disableOriginalConstructor()
122 $lbFactory->expects( $this->once() )
123 ->method( 'destroy' );
125 $newServices->redefineService(
126 'DBLoadBalancerFactory',
127 function() use ( $lbFactory ) {
132 // force the service to become active, so we can check that it does get destroyed
133 $oldLBFactory = $newServices->getService( 'DBLoadBalancerFactory' );
135 MediaWikiServices
::resetChildProcessServices();
136 $finalServices = MediaWikiServices
::getInstance();
138 $newLBFactory = $finalServices->getService( 'DBLoadBalancerFactory' );
140 $this->assertNotSame( $oldLBFactory, $newLBFactory );
142 MediaWikiServices
::forceGlobalInstance( $oldServices );
145 public function testResetServiceForTesting() {
146 $services = $this->newMediaWikiServices();
149 $services->defineService(
151 function() use ( &$serviceCounter ) {
153 $service = $this->getMock( 'MediaWiki\Services\DestructibleService' );
154 $service->expects( $this->once() )->method( 'destroy' );
159 // This should do nothing. In particular, it should not create a service instance.
160 $services->resetServiceForTesting( 'Test' );
161 $this->assertEquals( 0, $serviceCounter, 'No service instance should be created yet.' );
163 $oldInstance = $services->getService( 'Test' );
164 $this->assertEquals( 1, $serviceCounter, 'A service instance should exit now.' );
166 // The old instance should be detached, and destroy() called.
167 $services->resetServiceForTesting( 'Test' );
168 $newInstance = $services->getService( 'Test' );
170 $this->assertNotSame( $oldInstance, $newInstance );
172 // Satisfy the expectation that destroy() is called also for the second service instance.
173 $newInstance->destroy();
176 public function testResetServiceForTesting_noDestroy() {
177 $services = $this->newMediaWikiServices();
179 $services->defineService(
182 $service = $this->getMock( 'MediaWiki\Services\DestructibleService' );
183 $service->expects( $this->never() )->method( 'destroy' );
188 $oldInstance = $services->getService( 'Test' );
190 // The old instance should be detached, but destroy() not called.
191 $services->resetServiceForTesting( 'Test', false );
192 $newInstance = $services->getService( 'Test' );
194 $this->assertNotSame( $oldInstance, $newInstance );
197 public function provideGetters() {
198 $getServiceCases = $this->provideGetService();
201 // All getters should be named just like the service, with "get" added.
202 foreach ( $getServiceCases as $name => $case ) {
203 list( $service, $class ) = $case;
204 $getterCases[$name] = [
214 * @dataProvider provideGetters
216 public function testGetters( $getter, $type ) {
217 // Test against the default instance, since the dummy will not know the default services.
218 $services = MediaWikiServices
::getInstance();
219 $service = $services->$getter();
220 $this->assertInstanceOf( $type, $service );
223 public function provideGetService() {
224 // NOTE: This should list all service getters defined in ServiceWiring.php.
225 // NOTE: For every test case defined here there should be a corresponding
226 // test case defined in provideGetters().
228 'BootstrapConfig' => [ 'BootstrapConfig', Config
::class ],
229 'ConfigFactory' => [ 'ConfigFactory', ConfigFactory
::class ],
230 'MainConfig' => [ 'MainConfig', Config
::class ],
231 'SiteStore' => [ 'SiteStore', SiteStore
::class ],
232 'SiteLookup' => [ 'SiteLookup', SiteLookup
::class ],
233 'StatsdDataFactory' => [ 'StatsdDataFactory', StatsdDataFactory
::class ],
234 'EventRelayerGroup' => [ 'EventRelayerGroup', EventRelayerGroup
::class ],
235 'SearchEngineFactory' => [ 'SearchEngineFactory', SearchEngineFactory
::class ],
236 'SearchEngineConfig' => [ 'SearchEngineConfig', SearchEngineConfig
::class ],
237 'SkinFactory' => [ 'SkinFactory', SkinFactory
::class ],
238 'DBLoadBalancerFactory' => [ 'DBLoadBalancerFactory', 'LBFactory' ],
239 'DBLoadBalancer' => [ 'DBLoadBalancer', 'LoadBalancer' ],
240 'WatchedItemStore' => [ 'WatchedItemStore', WatchedItemStore
::class ],
245 * @dataProvider provideGetService
247 public function testGetService( $name, $type ) {
248 // Test against the default instance, since the dummy will not know the default services.
249 $services = MediaWikiServices
::getInstance();
251 $service = $services->getService( $name );
252 $this->assertInstanceOf( $type, $service );
255 public function testDefaultServiceInstantiation() {
256 // Check all services in the default instance, not a dummy instance!
257 // Note that we instantiate all services here, including any that
258 // were registered by extensions.
259 $services = MediaWikiServices
::getInstance();
260 $names = $services->getServiceNames();
262 foreach ( $names as $name ) {
263 $this->assertTrue( $services->hasService( $name ) );
264 $service = $services->getService( $name );
265 $this->assertInternalType( 'object', $service );