ConfigTest.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. <?php
  2. /**
  3. * Tests the Config lib that's shipped with kohana
  4. *
  5. * @group kohana
  6. * @group kohana.core
  7. * @group kohana.core.config
  8. *
  9. * @package Kohana
  10. * @category Tests
  11. * @author Kohana Team
  12. * @author Jeremy Bush <contractfrombelow@gmail.com>
  13. * @author Matt Button <matthew@sigswitch.com>
  14. * @copyright (c) Kohana Team
  15. * @license https://koseven.ga/LICENSE.md
  16. */
  17. class Kohana_ConfigTest extends Unittest_TestCase
  18. {
  19. /**
  20. * When a config object is initially created there should be
  21. * no readers attached
  22. *
  23. * @test
  24. * @covers Config
  25. */
  26. public function test_initially_there_are_no_sources()
  27. {
  28. $config = new Config;
  29. $this->assertAttributeSame([], '_sources', $config);
  30. }
  31. /**
  32. * Test that calling attach() on a kohana config object
  33. * adds the specified reader to the config object
  34. *
  35. * @test
  36. * @covers Config::attach
  37. */
  38. public function test_attach_adds_reader_and_returns_this()
  39. {
  40. $config = new Config;
  41. $reader = $this->createMock('Kohana_Config_Reader');
  42. $this->assertSame($config, $config->attach($reader));
  43. $this->assertAttributeContains($reader, '_sources', $config);
  44. }
  45. /**
  46. * By default (or by passing TRUE as the second parameter) the config object
  47. * should prepend the reader to the front of the readers queue
  48. *
  49. * @test
  50. * @covers Config::attach
  51. */
  52. public function test_attach_adds_reader_to_front_of_queue()
  53. {
  54. $config = new Config;
  55. $reader1 = $this->createMock('Kohana_Config_Reader');
  56. $reader2 = $this->createMock('Kohana_Config_Reader');
  57. $config->attach($reader1);
  58. $config->attach($reader2);
  59. // Rather than do two assertContains we'll do an assertSame to assert
  60. // the order of the readers
  61. $this->assertAttributeSame([$reader2, $reader1], '_sources', $config);
  62. // Now we test using the second parameter
  63. $config = new Config;
  64. $config->attach($reader1);
  65. $config->attach($reader2, TRUE);
  66. $this->assertAttributeSame([$reader2, $reader1], '_sources', $config);
  67. }
  68. /**
  69. * Test that attaching a new reader (and passing FALSE as second param) causes
  70. * phpunit to append the reader rather than prepend
  71. *
  72. * @test
  73. * @covers Config::attach
  74. */
  75. public function test_attach_can_add_reader_to_end_of_queue()
  76. {
  77. $config = new Config;
  78. $reader1 = $this->createMock('Kohana_Config_Reader');
  79. $reader2 = $this->createMock('Kohana_Config_Reader');
  80. $config->attach($reader1);
  81. $config->attach($reader2, FALSE);
  82. $this->assertAttributeSame([$reader1, $reader2], '_sources', $config);
  83. }
  84. /**
  85. * Calling detach() on a config object should remove it from the queue of readers
  86. *
  87. * @test
  88. * @covers Config::detach
  89. */
  90. public function test_detach_removes_reader_and_returns_this()
  91. {
  92. $config = new Config;
  93. // Due to the way phpunit mock generator works if you try and mock a class
  94. // that has already been used then it just re-uses the first's name
  95. // To get around this we have to specify a totally random name for the second mock object
  96. $reader1 = $this->createMock('Kohana_Config_Reader');
  97. $reader2 = $this->getMockForAbstractClass('Kohana_Config_Reader', [], 'MY_AWESOME_READER');
  98. $config->attach($reader1);
  99. $config->attach($reader2);
  100. $this->assertAttributeContains($reader1, '_sources', $config);
  101. $this->assertAttributeContains($reader2, '_sources', $config);
  102. $this->assertSame($config, $config->detach($reader2));
  103. $this->assertAttributeNotContains($reader2, '_sources', $config);
  104. $this->assertSame($config, $config->detach($reader1));
  105. $this->assertAttributeNotContains($reader1, '_sources', $config);
  106. }
  107. /**
  108. * detach() should return $this even if the specified reader does not exist
  109. *
  110. * @test
  111. * @covers Config::detach
  112. */
  113. public function test_detach_returns_this_even_when_reader_dnx()
  114. {
  115. $config = new Config;
  116. $reader = $this->createMock('Kohana_Config_Reader');
  117. $this->assertSame($config, $config->detach($reader));
  118. }
  119. /**
  120. * If we request a config variable with a dot path then
  121. * Config::load() should load the group and return the requested variable
  122. *
  123. * @test
  124. * @covers Config::load
  125. */
  126. public function test_load_can_get_var_from_dot_path()
  127. {
  128. $config = new Config;
  129. $reader = $this->createPartialMock('Kohana_Config_Reader', ['load']);
  130. $reader
  131. ->expects($this->once())
  132. ->method('load')
  133. ->with('beer')
  134. ->will($this->returnValue(['stout' => 'Guinness']));
  135. $config->attach($reader);
  136. $this->assertSame('Guinness', $config->load('beer.stout'));
  137. }
  138. /**
  139. * If we've already loaded a config group then the correct variable
  140. * should be returned if we use the dot path notation to to request
  141. * a var
  142. *
  143. * @test
  144. * @covers Config::load
  145. */
  146. public function test_load_can_get_var_from_dot_path_for_loaded_group()
  147. {
  148. $config = new Config;
  149. $reader = $this->createPartialMock('Kohana_Config_Reader', ['load']);
  150. $reader
  151. ->expects($this->once())
  152. ->method('load')
  153. ->with('beer')
  154. ->will($this->returnValue(['stout' => 'Guinness']));
  155. $config->attach($reader);
  156. $config->load('beer');
  157. $this->assertSame('Guinness', $config->load('beer.stout'));
  158. }
  159. /**
  160. * If load() is called and there are no readers present then it should throw
  161. * a kohana exception
  162. *
  163. * @test
  164. * @covers Config::load
  165. * @expectedException Kohana_Exception
  166. */
  167. public function test_load_throws_exception_if_there_are_no_sources()
  168. {
  169. // The following code should throw an exception and phpunit will catch / handle it
  170. // (see the @expectedException doccomment)
  171. $config = new Kohana_config;
  172. $config->load('random');
  173. }
  174. /**
  175. * Provides test data for test_load_throws_exception_if_no_group_is_given()
  176. *
  177. * @return array
  178. */
  179. public function provider_load_throws_exception_if_no_group_is_given()
  180. {
  181. return [
  182. [NULL],
  183. [''],
  184. [[]],
  185. [['foo' => 'bar']],
  186. [new StdClass],
  187. ];
  188. }
  189. /**
  190. * If an invalid group name is specified then an exception should be thrown.
  191. *
  192. * Invalid means it's either a non-string value, or empty
  193. *
  194. * @test
  195. * @dataProvider provider_load_throws_exception_if_no_group_is_given
  196. * @covers Config::load
  197. * @expectedException Kohana_Exception
  198. */
  199. public function test_load_throws_exception_if_invalid_group($value)
  200. {
  201. $config = new Kohana_Config;
  202. $reader = $this->createMock('Kohana_Config_Reader');
  203. $config->attach($reader);
  204. $config->load($value);
  205. }
  206. /**
  207. * Make sure that _write_config() passes the changed configuration to all
  208. * writers in the queue
  209. *
  210. * @test
  211. * @covers Kohana_Config
  212. */
  213. public function test_write_config_passes_changed_config_to_all_writers()
  214. {
  215. $config = new Kohana_Config;
  216. $reader1 = $this->createMock('Kohana_Config_Reader');
  217. $writer1 = $this->createPartialMock('Kohana_Config_Writer', ['write']);
  218. $writer2 = $this->createPartialMock('Kohana_Config_Writer', ['write']);
  219. $writer1
  220. ->expects($this->once())
  221. ->method('write')
  222. ->with('some_group', 'key', 'value');
  223. $writer2
  224. ->expects($this->once())
  225. ->method('write')
  226. ->with('some_group', 'key', 'value');
  227. $config->attach($reader1)->attach($writer1)->attach($writer2);
  228. $config->_write_config('some_group', 'key', 'value');
  229. }
  230. /**
  231. * Config sources are stored in a stack, make sure that config at the bottom
  232. * of the stack is overriden by config at the top
  233. *
  234. * @test
  235. * @covers Config::load
  236. */
  237. public function test_config_is_loaded_from_top_to_bottom_of_stack()
  238. {
  239. $group_name = 'lolumns';
  240. $reader1 = $this->getMockForAbstractClass('Kohana_Config_Reader', [],
  241. 'Unittest_Config_Reader_1',
  242. true,
  243. true,
  244. true,
  245. ['load']
  246. );
  247. $reader2 = $this->getMockForAbstractClass('Kohana_Config_Reader', [],
  248. 'Unittest_Config_Reader_2',
  249. true,
  250. true,
  251. true,
  252. ['load']
  253. );
  254. $reader1
  255. ->expects($this->once())
  256. ->method('load')
  257. ->with($group_name)
  258. ->will($this->returnValue(['foo' => 'bar', 'kohana' => 'awesome', 'life' => ['normal', 'fated']]));
  259. $reader2
  260. ->expects($this->once())
  261. ->method('load')
  262. ->with($group_name)
  263. ->will($this->returnValue(['kohana' => 'sweet', 'music' => 'tasteful', 'life' => ['extraordinary', 'destined']]));
  264. $config = new Kohana_Config;
  265. // Attach $reader1 at the "top" and reader2 at the "bottom"
  266. $config->attach($reader1)->attach($reader2, FALSE);
  267. $this->assertSame(
  268. [
  269. 'kohana' => 'awesome',
  270. 'music' => 'tasteful',
  271. 'life' => [
  272. 'extraordinary',
  273. 'destined',
  274. 'normal',
  275. 'fated',
  276. ],
  277. 'foo' => 'bar',
  278. ],
  279. $config->load($group_name)->as_array()
  280. );
  281. }
  282. /**
  283. * load() should keep a record of what config groups have been requested and if
  284. * a group is requested more than once the first instance should be returned
  285. *
  286. * @test
  287. * @covers Config::load
  288. */
  289. public function test_load_reuses_config_groups()
  290. {
  291. $reader = $this->createPartialMock('Kohana_Config_Reader', ['load']);
  292. $reader
  293. ->expects($this->once())
  294. ->method('load')
  295. ->with('something')
  296. ->will($this->returnValue([]));
  297. $config = new Kohana_Config;
  298. $config->attach($reader);
  299. $group = $config->load('something');
  300. $this->assertSame($group, $config->load('something'));
  301. }
  302. /**
  303. * When we call copy() we expect it to copy the merged config to all writers
  304. *
  305. * @TODO This test sucks due to limitations in the phpunit mock generator. MAKE THIS AWESOME AGAIN!
  306. * @test
  307. * @covers Kohana_Config::copy
  308. */
  309. public function test_copy_copies_merged_config_to_all_writers()
  310. {
  311. $config = new Kohana_Config;
  312. $reader1 = $this->createPartialMock('Kohana_Config_Reader', ['load']);
  313. $reader2 = $this->createPartialMock('Kohana_Config_Reader', ['load']);
  314. $reader1
  315. ->expects($this->once())
  316. ->method('load')
  317. ->with('something')
  318. ->will($this->returnValue(['pie' => 'good', 'kohana' => 'awesome']));
  319. $reader2
  320. ->expects($this->once())
  321. ->method('load')
  322. ->with('something')
  323. ->will($this->returnValue(['kohana' => 'good']));
  324. $writer1 = $this->createPartialMock('Kohana_Config_Writer', ['write']);
  325. $writer2 = $this->createPartialMock('Kohana_Config_Writer', ['write']);
  326. // Due to crazy limitations in phpunit's mocking engine we have to be fairly
  327. // liberal here as to what order we receive the config items
  328. // Good news is that order shouldn't matter *yay*
  329. //
  330. // Now save your eyes and skip the next... 13 lines!
  331. $key = $this->logicalOr('pie', 'kohana');
  332. $val = $this->logicalOr('good', 'awesome');
  333. $writer1
  334. ->expects($this->exactly(2))
  335. ->method('write')
  336. ->with('something', clone $key, clone $val);
  337. $writer2
  338. ->expects($this->exactly(2))
  339. ->method('write')
  340. ->with('something', clone $key, clone $val);
  341. $config
  342. ->attach($reader1)->attach($reader2, FALSE)
  343. ->attach($writer1)->attach($writer2);
  344. // Now let's get this thing going!
  345. $config->copy('something');
  346. }
  347. }