blob: 2d0a26830584bf8598214443ff362f1f198b39b0 [file] [log] [blame]
Pascal Kriete69c97a72011-04-20 21:44:54 -04001<?php
2
Pascal Krietefe372e32011-04-21 00:59:45 -04003class CI_TestCase extends PHPUnit_Framework_TestCase {
Andrey Andreevf243ce12012-06-09 23:34:21 +03004
dchill427ecc5cd2012-10-12 16:25:51 -04005 public $ci_vfs_root;
6 public $ci_app_root;
7 public $ci_base_root;
Pascal Krieteae7b3f92011-04-21 01:21:27 -04008 protected $ci_instance;
9 protected static $ci_test_instance;
Andrey Andreevf243ce12012-06-09 23:34:21 +030010
Pascal Krieteae7b3f92011-04-21 01:21:27 -040011 private $global_map = array(
Pascal Kriete69c97a72011-04-20 21:44:54 -040012 'benchmark' => 'bm',
13 'config' => 'cfg',
14 'hooks' => 'ext',
15 'utf8' => 'uni',
16 'router' => 'rtr',
17 'output' => 'out',
18 'security' => 'sec',
19 'input' => 'in',
20 'lang' => 'lang',
Greg Aker8da69032011-04-21 11:28:27 -050021 'loader' => 'load',
22 'model' => 'model'
Pascal Kriete69c97a72011-04-20 21:44:54 -040023 );
Andrey Andreevf243ce12012-06-09 23:34:21 +030024
Eric Barnes68286a42011-04-21 22:00:33 -040025 // --------------------------------------------------------------------
Andrey Andreevf243ce12012-06-09 23:34:21 +030026
Pascal Krietefe372e32011-04-21 00:59:45 -040027 public function __construct()
Pascal Kriete69c97a72011-04-20 21:44:54 -040028 {
29 parent::__construct();
dchill427ecc5cd2012-10-12 16:25:51 -040030 $this->ci_instance = new StdClass();
Pascal Kriete69c97a72011-04-20 21:44:54 -040031 }
Andrey Andreevf243ce12012-06-09 23:34:21 +030032
Pascal Kriete69c97a72011-04-20 21:44:54 -040033 // --------------------------------------------------------------------
Andrey Andreevf243ce12012-06-09 23:34:21 +030034
Eric Barnes68286a42011-04-21 22:00:33 -040035 public function setUp()
36 {
dchill427ecc5cd2012-10-12 16:25:51 -040037 // Setup VFS with base directories
38 $this->ci_vfs_root = vfsStream::setup();
39 $this->ci_app_root = vfsStream::newDirectory('application')->at($this->ci_vfs_root);
40 $this->ci_base_root = vfsStream::newDirectory('system')->at($this->ci_vfs_root);
dchill424f42be52012-10-21 21:31:19 -040041 $this->ci_view_root = vfsStream::newDirectory('views')->at($this->ci_app_root);
Andrey Andreevdd8d3d32012-11-03 02:09:05 +020042 vfsStream::newDirectory('config')->at($this->ci_app_root);
43 $this->ci_vfs_clone('application/config/autoload.php');
dchill427ecc5cd2012-10-12 16:25:51 -040044
Eric Barnes68286a42011-04-21 22:00:33 -040045 if (method_exists($this, 'set_up'))
46 {
47 $this->set_up();
48 }
49 }
Andrey Andreevf243ce12012-06-09 23:34:21 +030050
Eric Barnes68286a42011-04-21 22:00:33 -040051 // --------------------------------------------------------------------
Andrey Andreevf243ce12012-06-09 23:34:21 +030052
53 public function tearDown()
Eric Barnes68286a42011-04-21 22:00:33 -040054 {
55 if (method_exists($this, 'tear_down'))
56 {
57 $this->tear_down();
58 }
59 }
Taufan Adityae1dc9ea2012-03-28 16:49:49 +070060
61 // --------------------------------------------------------------------
Andrey Andreevf243ce12012-06-09 23:34:21 +030062
Taufan Adityae1dc9ea2012-03-28 16:49:49 +070063 public static function instance()
64 {
65 return self::$ci_test_instance;
66 }
Andrey Andreevf243ce12012-06-09 23:34:21 +030067
Eric Barnes68286a42011-04-21 22:00:33 -040068 // --------------------------------------------------------------------
Andrey Andreevf243ce12012-06-09 23:34:21 +030069
dchill427ecc5cd2012-10-12 16:25:51 -040070 public function ci_set_config($key = '', $val = '')
Pascal Kriete69c97a72011-04-20 21:44:54 -040071 {
dchill427ecc5cd2012-10-12 16:25:51 -040072 // Add test config
73 if ( ! isset($this->ci_instance->config))
74 {
75 $this->ci_instance->config = new CI_TestConfig();
76 }
77
78 // Empty key means just do setup above
79 if ($key === '')
80 {
81 return;
82 }
83
Pascal Krieteae7b3f92011-04-21 01:21:27 -040084 if (is_array($key))
85 {
dchill427ecc5cd2012-10-12 16:25:51 -040086 $this->ci_instance->config->config = $key;
Pascal Krieteae7b3f92011-04-21 01:21:27 -040087 }
88 else
89 {
dchill427ecc5cd2012-10-12 16:25:51 -040090 $this->ci_instance->config->config[$key] = $val;
Pascal Krieteae7b3f92011-04-21 01:21:27 -040091 }
Pascal Krietefe372e32011-04-21 00:59:45 -040092 }
Taufan Adityae1dc9ea2012-03-28 16:49:49 +070093
94 // --------------------------------------------------------------------
Andrey Andreevf243ce12012-06-09 23:34:21 +030095
96 public function ci_get_config()
Taufan Adityae1dc9ea2012-03-28 16:49:49 +070097 {
dchill427ecc5cd2012-10-12 16:25:51 -040098 return isset($this->ci_instance->config) ? $this->ci_instance->config->config : array();
Taufan Adityae1dc9ea2012-03-28 16:49:49 +070099 }
Andrey Andreevf243ce12012-06-09 23:34:21 +0300100
Pascal Krietefe372e32011-04-21 00:59:45 -0400101 // --------------------------------------------------------------------
Andrey Andreevf243ce12012-06-09 23:34:21 +0300102
103 public function ci_instance($obj = FALSE)
Pascal Krietefe372e32011-04-21 00:59:45 -0400104 {
105 if ( ! is_object($obj))
106 {
107 return $this->ci_instance;
108 }
Andrey Andreevf243ce12012-06-09 23:34:21 +0300109
Pascal Kriete69c97a72011-04-20 21:44:54 -0400110 $this->ci_instance = $obj;
111 }
Andrey Andreevf243ce12012-06-09 23:34:21 +0300112
Pascal Kriete69c97a72011-04-20 21:44:54 -0400113 // --------------------------------------------------------------------
Andrey Andreevf243ce12012-06-09 23:34:21 +0300114
115 public function ci_instance_var($name, $obj = FALSE)
Pascal Kriete69c97a72011-04-20 21:44:54 -0400116 {
Pascal Krietefe372e32011-04-21 00:59:45 -0400117 if ( ! is_object($obj))
118 {
119 return $this->ci_instance->$name;
120 }
Andrey Andreevf243ce12012-06-09 23:34:21 +0300121
Pascal Kriete69c97a72011-04-20 21:44:54 -0400122 $this->ci_instance->$name =& $obj;
123 }
Andrey Andreevf243ce12012-06-09 23:34:21 +0300124
Pascal Kriete69c97a72011-04-20 21:44:54 -0400125 // --------------------------------------------------------------------
Pascal Kriete69c97a72011-04-20 21:44:54 -0400126
127 /**
128 * Grab a core class
129 *
130 * Loads the correct core class without extensions
131 * and returns a reference to the class name in the
132 * globals array with the correct key. This way the
133 * test can modify the variable it assigns to and
134 * still maintain the global.
135 */
Andrey Andreevf243ce12012-06-09 23:34:21 +0300136 public function &ci_core_class($name)
Pascal Kriete69c97a72011-04-20 21:44:54 -0400137 {
138 $name = strtolower($name);
Andrey Andreevf243ce12012-06-09 23:34:21 +0300139
Pascal Krieteae7b3f92011-04-21 01:21:27 -0400140 if (isset($this->global_map[$name]))
Pascal Kriete69c97a72011-04-20 21:44:54 -0400141 {
142 $class_name = ucfirst($name);
Pascal Krieteae7b3f92011-04-21 01:21:27 -0400143 $global_name = $this->global_map[$name];
Pascal Kriete69c97a72011-04-20 21:44:54 -0400144 }
Pascal Krieteae7b3f92011-04-21 01:21:27 -0400145 elseif (in_array($name, $this->global_map))
Pascal Kriete69c97a72011-04-20 21:44:54 -0400146 {
Pascal Krieteae7b3f92011-04-21 01:21:27 -0400147 $class_name = ucfirst(array_search($name, $this->global_map));
Pascal Kriete69c97a72011-04-20 21:44:54 -0400148 $global_name = $name;
149 }
150 else
151 {
152 throw new Exception('Not a valid core class.');
153 }
Andrey Andreevf243ce12012-06-09 23:34:21 +0300154
Pascal Kriete69c97a72011-04-20 21:44:54 -0400155 if ( ! class_exists('CI_'.$class_name))
156 {
dchill427ecc5cd2012-10-12 16:25:51 -0400157 require_once SYSTEM_PATH.'core/'.$class_name.'.php';
Pascal Kriete69c97a72011-04-20 21:44:54 -0400158 }
Andrey Andreevf243ce12012-06-09 23:34:21 +0300159
Pascal Kriete69c97a72011-04-20 21:44:54 -0400160 $GLOBALS[strtoupper($global_name)] = 'CI_'.$class_name;
161 return $GLOBALS[strtoupper($global_name)];
162 }
Andrey Andreevf243ce12012-06-09 23:34:21 +0300163
Pascal Kriete69c97a72011-04-20 21:44:54 -0400164 // --------------------------------------------------------------------
Andrey Andreevf243ce12012-06-09 23:34:21 +0300165
Pascal Kriete69c97a72011-04-20 21:44:54 -0400166 // convenience function for global mocks
Andrey Andreevf243ce12012-06-09 23:34:21 +0300167 public function ci_set_core_class($name, $obj)
Pascal Kriete69c97a72011-04-20 21:44:54 -0400168 {
169 $orig =& $this->ci_core_class($name);
170 $orig = $obj;
171 }
Andrey Andreevf243ce12012-06-09 23:34:21 +0300172
dchill427ecc5cd2012-10-12 16:25:51 -0400173 /**
174 * Create VFS directory
175 *
176 * @param string Directory name
177 * @param object Optional root to create in
178 * @return object New directory object
179 */
180 public function ci_vfs_mkdir($name, $root = NULL)
181 {
182 // Check for root
183 if ( ! $root)
184 {
185 $root = $this->ci_vfs_root;
186 }
187
188 // Return new directory object
189 return vfsStream::newDirectory($name)->at($root);
190 }
191
192 // --------------------------------------------------------------------
193
194 /**
195 * Create VFS content
196 *
197 * @param string File name
198 * @param string File content
199 * @param object VFS directory object
200 * @param mixed Optional subdirectory path or array of subs
201 * @return void
202 */
203 public function ci_vfs_create($file, $content = '', $root = NULL, $path = NULL)
204 {
205 // Check for array
206 if (is_array($file))
207 {
208 foreach ($file as $name => $content)
209 {
210 $this->ci_vfs_create($name, $content, $root, $path);
211 }
212 return;
213 }
214
215 // Assert .php extension if none given
216 if (pathinfo($file, PATHINFO_EXTENSION) == '')
217 {
218 $file .= '.php';
219 }
220
221 // Build content
222 $tree = array($file => $content);
223
224 // Check for path
225 $subs = array();
226 if ($path)
227 {
228 // Explode if not array
229 $subs = is_array($path) ? $path : explode('/', trim($path, '/'));
230 }
231
232 // Check for root
233 if ( ! $root)
234 {
235 // Use base VFS root
236 $root = $this->ci_vfs_root;
237 }
238
239 // Handle subdirectories
240 while (($dir = array_shift($subs)))
241 {
242 // See if subdir exists under current root
243 $dir_root = $root->getChild($dir);
244 if ($dir_root)
245 {
246 // Yes - recurse into subdir
247 $root = $dir_root;
248 }
249 else
250 {
251 // No - put subdirectory back and quit
252 array_unshift($subs, $dir);
253 break;
254 }
255 }
256
257 // Create any remaining subdirectories
258 if ($subs)
259 {
260 foreach (array_reverse($subs) as $dir)
261 {
262 // Wrap content in subdirectory for creation
263 $tree = array($dir => $tree);
264 }
265 }
266
267 // Create tree
268 vfsStream::create($tree, $root);
269 }
270
271 // --------------------------------------------------------------------
272
273 /**
274 * Clone a real file into VFS
275 *
276 * @param string Path from base directory
277 * @return bool TRUE on success, otherwise FALSE
278 */
279 public function ci_vfs_clone($path)
280 {
dchill42e9435dc2012-10-14 15:44:39 -0400281 // Check for array
282 if (is_array($path))
283 {
284 foreach ($path as $file)
285 {
286 $this->ci_vfs_clone($file);
287 }
288 return;
289 }
290
dchill427ecc5cd2012-10-12 16:25:51 -0400291 // Get real file contents
292 $content = file_get_contents(PROJECT_BASE.$path);
293 if ($content === FALSE)
294 {
295 // Couldn't find file to clone
296 return FALSE;
297 }
298
299 $this->ci_vfs_create(basename($path), $content, NULL, dirname($path));
300 return TRUE;
301 }
302
303 // --------------------------------------------------------------------
304
305 /**
306 * Helper to get a VFS URL path
307 *
308 * @param string Path
309 * @param string Optional base path
310 * @return string Path URL
311 */
312 public function ci_vfs_path($path, $base = '')
313 {
314 // Check for base path
315 if ($base)
316 {
317 // Prepend to path
318 $path = rtrim($base, '/').'/'.ltrim($path, '/');
319
320 // Is it already in URL form?
321 if (strpos($path, '://') !== FALSE)
322 {
323 // Done - return path
324 return $path;
325 }
326 }
327
328 // Trim leading slash and return URL
329 return vfsStream::url(ltrim($path, '/'));
330 }
331
Pascal Kriete69c97a72011-04-20 21:44:54 -0400332 // --------------------------------------------------------------------
Pascal Krieteae7b3f92011-04-21 01:21:27 -0400333 // Internals
334 // --------------------------------------------------------------------
Andrey Andreevf243ce12012-06-09 23:34:21 +0300335
Pascal Krieteae7b3f92011-04-21 01:21:27 -0400336 /**
337 * Overwrite runBare
338 *
339 * PHPUnit instantiates the test classes before
340 * running them individually. So right before a test
341 * runs we set our instance. Normally this step would
342 * happen in setUp, but someone is bound to forget to
343 * call the parent method and debugging this is no fun.
344 */
345 public function runBare()
Pascal Krietefe372e32011-04-21 00:59:45 -0400346 {
Pascal Krieteae7b3f92011-04-21 01:21:27 -0400347 self::$ci_test_instance = $this;
348 parent::runBare();
Pascal Krietefe372e32011-04-21 00:59:45 -0400349 }
Taufan Adityae1dc9ea2012-03-28 16:49:49 +0700350
Pascal Krietefe372e32011-04-21 00:59:45 -0400351 // --------------------------------------------------------------------
Andrey Andreevf243ce12012-06-09 23:34:21 +0300352
353 public function helper($name)
Pascal Krieteae7b3f92011-04-21 01:21:27 -0400354 {
dchill427ecc5cd2012-10-12 16:25:51 -0400355 require_once(SYSTEM_PATH.'helpers/'.$name.'_helper.php');
356 }
357
358 // --------------------------------------------------------------------
359
360 public function lang($name)
361 {
362 require(SYSTEM_PATH.'language/english/'.$name.'_lang.php');
363 return $lang;
Pascal Krietefe372e32011-04-21 00:59:45 -0400364 }
Taufan Aditya8749bc72012-03-11 05:43:45 +0700365
366 // --------------------------------------------------------------------
Andrey Andreevf243ce12012-06-09 23:34:21 +0300367
Taufan Aditya8749bc72012-03-11 05:43:45 +0700368 /**
369 * This overload is useful to create a stub, that need to have a specific method.
370 */
Andrey Andreevf243ce12012-06-09 23:34:21 +0300371 public function __call($method, $args)
Taufan Aditya8749bc72012-03-11 05:43:45 +0700372 {
Andrey Andreevf243ce12012-06-09 23:34:21 +0300373 if ($this->{$method} instanceof Closure)
Taufan Aditya8749bc72012-03-11 05:43:45 +0700374 {
375 return call_user_func_array($this->{$method},$args);
Andrey Andreevf243ce12012-06-09 23:34:21 +0300376 }
377 else
Taufan Aditya8749bc72012-03-11 05:43:45 +0700378 {
379 return parent::__call($method, $args);
380 }
381 }
Pascal Kriete69c97a72011-04-20 21:44:54 -0400382
Andrey Andreevf243ce12012-06-09 23:34:21 +0300383}