1<?php
2
3use MediaWiki\MediaWikiServices;
4
5class ConfigFactoryTest extends \MediaWikiIntegrationTestCase {
6
7	/**
8	 * @covers ConfigFactory::register
9	 */
10	public function testRegister() {
11		$factory = new ConfigFactory();
12		$factory->register( 'unittest', 'GlobalVarConfig::newInstance' );
13		$this->assertInstanceOf( GlobalVarConfig::class, $factory->makeConfig( 'unittest' ) );
14	}
15
16	/**
17	 * @covers ConfigFactory::register
18	 */
19	public function testRegisterInvalid() {
20		$factory = new ConfigFactory();
21		$this->expectException( InvalidArgumentException::class );
22		$factory->register( 'invalid', 'Invalid callback' );
23	}
24
25	/**
26	 * @covers ConfigFactory::register
27	 */
28	public function testRegisterInvalidInstance() {
29		$factory = new ConfigFactory();
30		$this->expectException( InvalidArgumentException::class );
31		$factory->register( 'invalidInstance', (object)[] );
32	}
33
34	/**
35	 * @covers ConfigFactory::register
36	 */
37	public function testRegisterInstance() {
38		$config = GlobalVarConfig::newInstance();
39		$factory = new ConfigFactory();
40		$factory->register( 'unittest', $config );
41		$this->assertSame( $config, $factory->makeConfig( 'unittest' ) );
42	}
43
44	/**
45	 * @covers ConfigFactory::register
46	 */
47	public function testRegisterAgain() {
48		$factory = new ConfigFactory();
49		$factory->register( 'unittest', 'GlobalVarConfig::newInstance' );
50		$config1 = $factory->makeConfig( 'unittest' );
51
52		$factory->register( 'unittest', 'GlobalVarConfig::newInstance' );
53		$config2 = $factory->makeConfig( 'unittest' );
54
55		$this->assertNotSame( $config1, $config2 );
56	}
57
58	/**
59	 * @covers ConfigFactory::salvage
60	 */
61	public function testSalvage() {
62		$oldFactory = new ConfigFactory();
63		$oldFactory->register( 'foo', 'GlobalVarConfig::newInstance' );
64		$oldFactory->register( 'bar', 'GlobalVarConfig::newInstance' );
65		$oldFactory->register( 'quux', 'GlobalVarConfig::newInstance' );
66
67		// instantiate two of the three defined configurations
68		$foo = $oldFactory->makeConfig( 'foo' );
69		$bar = $oldFactory->makeConfig( 'bar' );
70		$quux = $oldFactory->makeConfig( 'quux' );
71
72		// define new config instance
73		$newFactory = new ConfigFactory();
74		$newFactory->register( 'foo', 'GlobalVarConfig::newInstance' );
75		$newFactory->register( 'bar', function () {
76			return new HashConfig();
77		} );
78
79		// "foo" and "quux" are defined in the old and the new factory.
80		// The old factory has instances for "foo" and "bar", but not "quux".
81		$newFactory->salvage( $oldFactory );
82
83		$newFoo = $newFactory->makeConfig( 'foo' );
84		$this->assertSame( $foo, $newFoo, 'existing instance should be salvaged' );
85
86		$newBar = $newFactory->makeConfig( 'bar' );
87		$this->assertNotSame( $bar, $newBar, 'don\'t salvage if callbacks differ' );
88
89		// the new factory doesn't have quux defined, so the quux instance should not be salvaged
90		$this->expectException( ConfigException::class );
91		$newFactory->makeConfig( 'quux' );
92	}
93
94	/**
95	 * @covers ConfigFactory::getConfigNames
96	 */
97	public function testGetConfigNames() {
98		$factory = new ConfigFactory();
99		$factory->register( 'foo', 'GlobalVarConfig::newInstance' );
100		$factory->register( 'bar', new HashConfig() );
101
102		$this->assertEquals( [ 'foo', 'bar' ], $factory->getConfigNames() );
103	}
104
105	/**
106	 * @covers ConfigFactory::makeConfig
107	 */
108	public function testMakeConfigWithCallback() {
109		$factory = new ConfigFactory();
110		$factory->register( 'unittest', 'GlobalVarConfig::newInstance' );
111
112		$conf = $factory->makeConfig( 'unittest' );
113		$this->assertInstanceOf( Config::class, $conf );
114		$this->assertSame( $conf, $factory->makeConfig( 'unittest' ) );
115	}
116
117	/**
118	 * @covers ConfigFactory::makeConfig
119	 */
120	public function testMakeConfigWithObject() {
121		$factory = new ConfigFactory();
122		$conf = new HashConfig();
123		$factory->register( 'test', $conf );
124		$this->assertSame( $conf, $factory->makeConfig( 'test' ) );
125	}
126
127	/**
128	 * @covers ConfigFactory::makeConfig
129	 */
130	public function testMakeConfigFallback() {
131		$factory = new ConfigFactory();
132		$factory->register( '*', 'GlobalVarConfig::newInstance' );
133		$conf = $factory->makeConfig( 'unittest' );
134		$this->assertInstanceOf( Config::class, $conf );
135	}
136
137	/**
138	 * @covers ConfigFactory::makeConfig
139	 */
140	public function testMakeConfigWithNoBuilders() {
141		$factory = new ConfigFactory();
142		$this->expectException( ConfigException::class );
143		$factory->makeConfig( 'nobuilderregistered' );
144	}
145
146	/**
147	 * @covers ConfigFactory::makeConfig
148	 */
149	public function testMakeConfigWithInvalidCallback() {
150		$factory = new ConfigFactory();
151		$factory->register( 'unittest', function () {
152			return true; // Not a Config object
153		} );
154		$this->expectException( UnexpectedValueException::class );
155		$factory->makeConfig( 'unittest' );
156	}
157
158	/**
159	 * @covers ConfigFactory::getDefaultInstance
160	 */
161	public function testGetDefaultInstance() {
162		// NOTE: the global config factory returned here has been overwritten
163		// for operation in test mode. It may not reflect LocalSettings.
164		$factory = MediaWikiServices::getInstance()->getConfigFactory();
165		$this->assertInstanceOf( Config::class, $factory->makeConfig( 'main' ) );
166	}
167
168}
169