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