Merge "Normalize `input[type="search"]`"
[lhc/web/wiklou.git] / tests / phpunit / includes / MediaWikiServicesTest.php
1 <?php
2 use MediaWiki\MediaWikiServices;
3 use MediaWiki\Services\ServiceDisabledException;
4
5 /**
6 * @covers MediaWiki\MediaWikiServices
7 *
8 * @group MediaWiki
9 */
10 class MediaWikiServicesTest extends PHPUnit_Framework_TestCase {
11
12 /**
13 * @return Config
14 */
15 private function newTestConfig() {
16 $globalConfig = new GlobalVarConfig();
17
18 $testConfig = new HashConfig();
19 $testConfig->set( 'ServiceWiringFiles', $globalConfig->get( 'ServiceWiringFiles' ) );
20 $testConfig->set( 'ConfigRegistry', $globalConfig->get( 'ConfigRegistry' ) );
21
22 return $testConfig;
23 }
24
25 /**
26 * @return MediaWikiServices
27 */
28 private function newMediaWikiServices( Config $config = null ) {
29 if ( $config === null ) {
30 $config = $this->newTestConfig();
31 }
32
33 $instance = new MediaWikiServices( $config );
34
35 // Load the default wiring from the specified files.
36 $wiringFiles = $config->get( 'ServiceWiringFiles' );
37 $instance->loadWiringFiles( $wiringFiles );
38
39 return $instance;
40 }
41
42 public function testGetInstance() {
43 $services = MediaWikiServices::getInstance();
44 $this->assertInstanceOf( 'MediaWiki\\MediaWikiServices', $services );
45 }
46
47 public function testForceGlobalInstance() {
48 $newServices = $this->newMediaWikiServices();
49 $oldServices = MediaWikiServices::forceGlobalInstance( $newServices );
50
51 $this->assertInstanceOf( 'MediaWiki\\MediaWikiServices', $oldServices );
52 $this->assertNotSame( $oldServices, $newServices );
53
54 $theServices = MediaWikiServices::getInstance();
55 $this->assertSame( $theServices, $newServices );
56
57 MediaWikiServices::forceGlobalInstance( $oldServices );
58
59 $theServices = MediaWikiServices::getInstance();
60 $this->assertSame( $theServices, $oldServices );
61 }
62
63 public function testResetGlobalInstance() {
64 $newServices = $this->newMediaWikiServices();
65 $oldServices = MediaWikiServices::forceGlobalInstance( $newServices );
66
67 MediaWikiServices::resetGlobalInstance( $this->newTestConfig() );
68 $theServices = MediaWikiServices::getInstance();
69
70 $this->assertNotSame( $theServices, $newServices );
71 $this->assertNotSame( $theServices, $oldServices );
72
73 MediaWikiServices::forceGlobalInstance( $oldServices );
74 }
75
76 public function testDisableStorageBackend() {
77 $newServices = $this->newMediaWikiServices();
78 $oldServices = MediaWikiServices::forceGlobalInstance( $newServices );
79
80 $lbFactory = $this->getMockBuilder( 'LBFactorySimple' )
81 ->disableOriginalConstructor()
82 ->getMock();
83
84 $lbFactory->expects( $this->once() )
85 ->method( 'destroy' );
86
87 $newServices->redefineService(
88 'DBLoadBalancerFactory',
89 function() use ( $lbFactory ) {
90 return $lbFactory;
91 }
92 );
93
94 // force the service to become active, so we can check that it does get destroyed
95 $newServices->getService( 'DBLoadBalancerFactory' );
96
97 MediaWikiServices::disableStorageBackend(); // should destroy DBLoadBalancerFactory
98
99 try {
100 MediaWikiServices::getInstance()->getService( 'DBLoadBalancerFactory' );
101 $this->fail( 'DBLoadBalancerFactory shoudl have been disabled' );
102 }
103 catch ( ServiceDisabledException $ex ) {
104 // ok, as expected
105 }
106 catch ( Throwable $ex ) {
107 $this->fail( 'ServiceDisabledException expected, caught ' . get_class( $ex ) );
108 }
109
110 MediaWikiServices::forceGlobalInstance( $oldServices );
111 }
112
113 public function testResetChildProcessServices() {
114 $newServices = $this->newMediaWikiServices();
115 $oldServices = MediaWikiServices::forceGlobalInstance( $newServices );
116
117 $lbFactory = $this->getMockBuilder( 'LBFactorySimple' )
118 ->disableOriginalConstructor()
119 ->getMock();
120
121 $lbFactory->expects( $this->once() )
122 ->method( 'destroy' );
123
124 $newServices->redefineService(
125 'DBLoadBalancerFactory',
126 function() use ( $lbFactory ) {
127 return $lbFactory;
128 }
129 );
130
131 // force the service to become active, so we can check that it does get destroyed
132 $oldLBFactory = $newServices->getService( 'DBLoadBalancerFactory' );
133
134 MediaWikiServices::resetChildProcessServices();
135 $finalServices = MediaWikiServices::getInstance();
136
137 $newLBFactory = $finalServices->getService( 'DBLoadBalancerFactory' );
138
139 $this->assertNotSame( $oldLBFactory, $newLBFactory );
140
141 MediaWikiServices::forceGlobalInstance( $oldServices );
142 }
143
144 public function testResetServiceForTesting() {
145 $services = $this->newMediaWikiServices();
146 $serviceCounter = 0;
147
148 $services->defineService(
149 'Test',
150 function() use ( &$serviceCounter ) {
151 $serviceCounter++;
152 $service = $this->getMock( 'MediaWiki\Services\DestructibleService' );
153 $service->expects( $this->once() )->method( 'destroy' );
154 return $service;
155 }
156 );
157
158 // This should do nothing. In particular, it should not create a service instance.
159 $services->resetServiceForTesting( 'Test' );
160 $this->assertEquals( 0, $serviceCounter, 'No service instance should be created yet.' );
161
162 $oldInstance = $services->getService( 'Test' );
163 $this->assertEquals( 1, $serviceCounter, 'A service instance should exit now.' );
164
165 // The old instance should be detached, and destroy() called.
166 $services->resetServiceForTesting( 'Test' );
167 $newInstance = $services->getService( 'Test' );
168
169 $this->assertNotSame( $oldInstance, $newInstance );
170
171 // Satisfy the expectation that destroy() is called also for the second service instance.
172 $newInstance->destroy();
173 }
174
175 public function testResetServiceForTesting_noDestroy() {
176 $services = $this->newMediaWikiServices();
177
178 $services->defineService(
179 'Test',
180 function() {
181 $service = $this->getMock( 'MediaWiki\Services\DestructibleService' );
182 $service->expects( $this->never() )->method( 'destroy' );
183 return $service;
184 }
185 );
186
187 $oldInstance = $services->getService( 'Test' );
188
189 // The old instance should be detached, but destroy() not called.
190 $services->resetServiceForTesting( 'Test', false );
191 $newInstance = $services->getService( 'Test' );
192
193 $this->assertNotSame( $oldInstance, $newInstance );
194 }
195
196 public function provideGetters() {
197 $getServiceCases = $this->provideGetService();
198 $getterCases = [];
199
200 // All getters should be named just like the service, with "get" added.
201 foreach ( $getServiceCases as $name => $case ) {
202 $getterCases[$name] = [
203 'get' . $case[0],
204 $case[1]
205 ];
206 }
207
208 return $getterCases;
209 }
210
211 /**
212 * @dataProvider provideGetters
213 */
214 public function testGetters( $getter, $type ) {
215 // Test against the default instance, since the dummy will not know the default services.
216 $services = MediaWikiServices::getInstance();
217 $service = $services->$getter();
218 $this->assertInstanceOf( $type, $service );
219 }
220
221 public function provideGetService() {
222 // NOTE: This should list all service getters defined in ServiceWiring.php.
223 // NOTE: For every test case defined here there should be a corresponding
224 // test case defined in provideGetters().
225 return [
226 'BootstrapConfig' => [ 'BootstrapConfig', Config::class ],
227 'ConfigFactory' => [ 'ConfigFactory', ConfigFactory::class ],
228 'MainConfig' => [ 'MainConfig', Config::class ],
229 'SiteStore' => [ 'SiteStore', SiteStore::class ],
230 'SiteLookup' => [ 'SiteLookup', SiteLookup::class ],
231 'DBLoadBalancerFactory' => [ 'DBLoadBalancerFactory', 'LBFactory' ],
232 'DBLoadBalancer' => [ 'DBLoadBalancer', 'LoadBalancer' ],
233 'WatchedItemStore' => [ 'WatchedItemStore', WatchedItemStore::class ],
234 ];
235 }
236
237 /**
238 * @dataProvider provideGetService
239 */
240 public function testGetService( $name, $type ) {
241 // Test against the default instance, since the dummy will not know the default services.
242 $services = MediaWikiServices::getInstance();
243
244 $service = $services->getService( $name );
245 $this->assertInstanceOf( $type, $service );
246 }
247
248 public function testDefaultServiceInstantiation() {
249 // Check all services in the default instance, not a dummy instance!
250 // Note that we instantiate all services here, including any that
251 // were registered by extensions.
252 $services = MediaWikiServices::getInstance();
253 $names = $services->getServiceNames();
254
255 foreach ( $names as $name ) {
256 $this->assertTrue( $services->hasService( $name ) );
257 $service = $services->getService( $name );
258 $this->assertInternalType( 'object', $service );
259 }
260 }
261
262 }