blob: f164929458a9ed926758a9127a1877273c7681f6 [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);
dchill427ecc5cd2012-10-12 16:25:51 -040042
Eric Barnes68286a42011-04-21 22:00:33 -040043 if (method_exists($this, 'set_up'))
44 {
45 $this->set_up();
46 }
47 }
Andrey Andreevf243ce12012-06-09 23:34:21 +030048
Eric Barnes68286a42011-04-21 22:00:33 -040049 // --------------------------------------------------------------------
Andrey Andreevf243ce12012-06-09 23:34:21 +030050
51 public function tearDown()
Eric Barnes68286a42011-04-21 22:00:33 -040052 {
53 if (method_exists($this, 'tear_down'))
54 {
55 $this->tear_down();
56 }
57 }
Taufan Adityae1dc9ea2012-03-28 16:49:49 +070058
59 // --------------------------------------------------------------------
Andrey Andreevf243ce12012-06-09 23:34:21 +030060
Taufan Adityae1dc9ea2012-03-28 16:49:49 +070061 public static function instance()
62 {
63 return self::$ci_test_instance;
64 }
Andrey Andreevf243ce12012-06-09 23:34:21 +030065
Eric Barnes68286a42011-04-21 22:00:33 -040066 // --------------------------------------------------------------------
Andrey Andreevf243ce12012-06-09 23:34:21 +030067
dchill427ecc5cd2012-10-12 16:25:51 -040068 public function ci_set_config($key = '', $val = '')
Pascal Kriete69c97a72011-04-20 21:44:54 -040069 {
dchill427ecc5cd2012-10-12 16:25:51 -040070 // Add test config
71 if ( ! isset($this->ci_instance->config))
72 {
73 $this->ci_instance->config = new CI_TestConfig();
74 }
75
76 // Empty key means just do setup above
77 if ($key === '')
78 {
79 return;
80 }
81
Pascal Krieteae7b3f92011-04-21 01:21:27 -040082 if (is_array($key))
83 {
dchill427ecc5cd2012-10-12 16:25:51 -040084 $this->ci_instance->config->config = $key;
Pascal Krieteae7b3f92011-04-21 01:21:27 -040085 }
86 else
87 {
dchill427ecc5cd2012-10-12 16:25:51 -040088 $this->ci_instance->config->config[$key] = $val;
Pascal Krieteae7b3f92011-04-21 01:21:27 -040089 }
Pascal Krietefe372e32011-04-21 00:59:45 -040090 }
Taufan Adityae1dc9ea2012-03-28 16:49:49 +070091
92 // --------------------------------------------------------------------
Andrey Andreevf243ce12012-06-09 23:34:21 +030093
94 public function ci_get_config()
Taufan Adityae1dc9ea2012-03-28 16:49:49 +070095 {
dchill427ecc5cd2012-10-12 16:25:51 -040096 return isset($this->ci_instance->config) ? $this->ci_instance->config->config : array();
Taufan Adityae1dc9ea2012-03-28 16:49:49 +070097 }
Andrey Andreevf243ce12012-06-09 23:34:21 +030098
Pascal Krietefe372e32011-04-21 00:59:45 -040099 // --------------------------------------------------------------------
Andrey Andreevf243ce12012-06-09 23:34:21 +0300100
101 public function ci_instance($obj = FALSE)
Pascal Krietefe372e32011-04-21 00:59:45 -0400102 {
103 if ( ! is_object($obj))
104 {
105 return $this->ci_instance;
106 }
Andrey Andreevf243ce12012-06-09 23:34:21 +0300107
Pascal Kriete69c97a72011-04-20 21:44:54 -0400108 $this->ci_instance = $obj;
109 }
Andrey Andreevf243ce12012-06-09 23:34:21 +0300110
Pascal Kriete69c97a72011-04-20 21:44:54 -0400111 // --------------------------------------------------------------------
Andrey Andreevf243ce12012-06-09 23:34:21 +0300112
113 public function ci_instance_var($name, $obj = FALSE)
Pascal Kriete69c97a72011-04-20 21:44:54 -0400114 {
Pascal Krietefe372e32011-04-21 00:59:45 -0400115 if ( ! is_object($obj))
116 {
117 return $this->ci_instance->$name;
118 }
Andrey Andreevf243ce12012-06-09 23:34:21 +0300119
Pascal Kriete69c97a72011-04-20 21:44:54 -0400120 $this->ci_instance->$name =& $obj;
121 }
Andrey Andreevf243ce12012-06-09 23:34:21 +0300122
Pascal Kriete69c97a72011-04-20 21:44:54 -0400123 // --------------------------------------------------------------------
Pascal Kriete69c97a72011-04-20 21:44:54 -0400124
125 /**
126 * Grab a core class
127 *
128 * Loads the correct core class without extensions
129 * and returns a reference to the class name in the
130 * globals array with the correct key. This way the
131 * test can modify the variable it assigns to and
132 * still maintain the global.
133 */
Andrey Andreevf243ce12012-06-09 23:34:21 +0300134 public function &ci_core_class($name)
Pascal Kriete69c97a72011-04-20 21:44:54 -0400135 {
136 $name = strtolower($name);
Andrey Andreevf243ce12012-06-09 23:34:21 +0300137
Pascal Krieteae7b3f92011-04-21 01:21:27 -0400138 if (isset($this->global_map[$name]))
Pascal Kriete69c97a72011-04-20 21:44:54 -0400139 {
140 $class_name = ucfirst($name);
Pascal Krieteae7b3f92011-04-21 01:21:27 -0400141 $global_name = $this->global_map[$name];
Pascal Kriete69c97a72011-04-20 21:44:54 -0400142 }
Pascal Krieteae7b3f92011-04-21 01:21:27 -0400143 elseif (in_array($name, $this->global_map))
Pascal Kriete69c97a72011-04-20 21:44:54 -0400144 {
Pascal Krieteae7b3f92011-04-21 01:21:27 -0400145 $class_name = ucfirst(array_search($name, $this->global_map));
Pascal Kriete69c97a72011-04-20 21:44:54 -0400146 $global_name = $name;
147 }
148 else
149 {
150 throw new Exception('Not a valid core class.');
151 }
Andrey Andreevf243ce12012-06-09 23:34:21 +0300152
Pascal Kriete69c97a72011-04-20 21:44:54 -0400153 if ( ! class_exists('CI_'.$class_name))
154 {
dchill427ecc5cd2012-10-12 16:25:51 -0400155 require_once SYSTEM_PATH.'core/'.$class_name.'.php';
Pascal Kriete69c97a72011-04-20 21:44:54 -0400156 }
Andrey Andreevf243ce12012-06-09 23:34:21 +0300157
Pascal Kriete69c97a72011-04-20 21:44:54 -0400158 $GLOBALS[strtoupper($global_name)] = 'CI_'.$class_name;
159 return $GLOBALS[strtoupper($global_name)];
160 }
Andrey Andreevf243ce12012-06-09 23:34:21 +0300161
Pascal Kriete69c97a72011-04-20 21:44:54 -0400162 // --------------------------------------------------------------------
Andrey Andreevf243ce12012-06-09 23:34:21 +0300163
Pascal Kriete69c97a72011-04-20 21:44:54 -0400164 // convenience function for global mocks
Andrey Andreevf243ce12012-06-09 23:34:21 +0300165 public function ci_set_core_class($name, $obj)
Pascal Kriete69c97a72011-04-20 21:44:54 -0400166 {
167 $orig =& $this->ci_core_class($name);
168 $orig = $obj;
169 }
Andrey Andreevf243ce12012-06-09 23:34:21 +0300170
dchill427ecc5cd2012-10-12 16:25:51 -0400171 /**
172 * Create VFS directory
173 *
174 * @param string Directory name
175 * @param object Optional root to create in
176 * @return object New directory object
177 */
178 public function ci_vfs_mkdir($name, $root = NULL)
179 {
180 // Check for root
181 if ( ! $root)
182 {
183 $root = $this->ci_vfs_root;
184 }
185
186 // Return new directory object
187 return vfsStream::newDirectory($name)->at($root);
188 }
189
190 // --------------------------------------------------------------------
191
192 /**
193 * Create VFS content
194 *
195 * @param string File name
196 * @param string File content
197 * @param object VFS directory object
198 * @param mixed Optional subdirectory path or array of subs
199 * @return void
200 */
201 public function ci_vfs_create($file, $content = '', $root = NULL, $path = NULL)
202 {
203 // Check for array
204 if (is_array($file))
205 {
206 foreach ($file as $name => $content)
207 {
208 $this->ci_vfs_create($name, $content, $root, $path);
209 }
210 return;
211 }
212
213 // Assert .php extension if none given
214 if (pathinfo($file, PATHINFO_EXTENSION) == '')
215 {
216 $file .= '.php';
217 }
218
219 // Build content
220 $tree = array($file => $content);
221
222 // Check for path
223 $subs = array();
224 if ($path)
225 {
226 // Explode if not array
227 $subs = is_array($path) ? $path : explode('/', trim($path, '/'));
228 }
229
230 // Check for root
231 if ( ! $root)
232 {
233 // Use base VFS root
234 $root = $this->ci_vfs_root;
235 }
236
237 // Handle subdirectories
238 while (($dir = array_shift($subs)))
239 {
240 // See if subdir exists under current root
241 $dir_root = $root->getChild($dir);
242 if ($dir_root)
243 {
244 // Yes - recurse into subdir
245 $root = $dir_root;
246 }
247 else
248 {
249 // No - put subdirectory back and quit
250 array_unshift($subs, $dir);
251 break;
252 }
253 }
254
255 // Create any remaining subdirectories
256 if ($subs)
257 {
258 foreach (array_reverse($subs) as $dir)
259 {
260 // Wrap content in subdirectory for creation
261 $tree = array($dir => $tree);
262 }
263 }
264
265 // Create tree
266 vfsStream::create($tree, $root);
267 }
268
269 // --------------------------------------------------------------------
270
271 /**
272 * Clone a real file into VFS
273 *
274 * @param string Path from base directory
275 * @return bool TRUE on success, otherwise FALSE
276 */
277 public function ci_vfs_clone($path)
278 {
dchill42e9435dc2012-10-14 15:44:39 -0400279 // Check for array
280 if (is_array($path))
281 {
282 foreach ($path as $file)
283 {
284 $this->ci_vfs_clone($file);
285 }
286 return;
287 }
288
dchill427ecc5cd2012-10-12 16:25:51 -0400289 // Get real file contents
290 $content = file_get_contents(PROJECT_BASE.$path);
291 if ($content === FALSE)
292 {
293 // Couldn't find file to clone
294 return FALSE;
295 }
296
297 $this->ci_vfs_create(basename($path), $content, NULL, dirname($path));
298 return TRUE;
299 }
300
301 // --------------------------------------------------------------------
302
303 /**
304 * Helper to get a VFS URL path
305 *
306 * @param string Path
307 * @param string Optional base path
308 * @return string Path URL
309 */
310 public function ci_vfs_path($path, $base = '')
311 {
312 // Check for base path
313 if ($base)
314 {
315 // Prepend to path
316 $path = rtrim($base, '/').'/'.ltrim($path, '/');
317
318 // Is it already in URL form?
319 if (strpos($path, '://') !== FALSE)
320 {
321 // Done - return path
322 return $path;
323 }
324 }
325
326 // Trim leading slash and return URL
327 return vfsStream::url(ltrim($path, '/'));
328 }
329
Pascal Kriete69c97a72011-04-20 21:44:54 -0400330 // --------------------------------------------------------------------
Pascal Krieteae7b3f92011-04-21 01:21:27 -0400331 // Internals
332 // --------------------------------------------------------------------
Andrey Andreevf243ce12012-06-09 23:34:21 +0300333
Pascal Krieteae7b3f92011-04-21 01:21:27 -0400334 /**
335 * Overwrite runBare
336 *
337 * PHPUnit instantiates the test classes before
338 * running them individually. So right before a test
339 * runs we set our instance. Normally this step would
340 * happen in setUp, but someone is bound to forget to
341 * call the parent method and debugging this is no fun.
342 */
343 public function runBare()
Pascal Krietefe372e32011-04-21 00:59:45 -0400344 {
Pascal Krieteae7b3f92011-04-21 01:21:27 -0400345 self::$ci_test_instance = $this;
346 parent::runBare();
Pascal Krietefe372e32011-04-21 00:59:45 -0400347 }
Taufan Adityae1dc9ea2012-03-28 16:49:49 +0700348
Pascal Krietefe372e32011-04-21 00:59:45 -0400349 // --------------------------------------------------------------------
Andrey Andreevf243ce12012-06-09 23:34:21 +0300350
351 public function helper($name)
Pascal Krieteae7b3f92011-04-21 01:21:27 -0400352 {
dchill427ecc5cd2012-10-12 16:25:51 -0400353 require_once(SYSTEM_PATH.'helpers/'.$name.'_helper.php');
354 }
355
356 // --------------------------------------------------------------------
357
358 public function lang($name)
359 {
360 require(SYSTEM_PATH.'language/english/'.$name.'_lang.php');
361 return $lang;
Pascal Krietefe372e32011-04-21 00:59:45 -0400362 }
Taufan Aditya8749bc72012-03-11 05:43:45 +0700363
364 // --------------------------------------------------------------------
Andrey Andreevf243ce12012-06-09 23:34:21 +0300365
Taufan Aditya8749bc72012-03-11 05:43:45 +0700366 /**
367 * This overload is useful to create a stub, that need to have a specific method.
368 */
Andrey Andreevf243ce12012-06-09 23:34:21 +0300369 public function __call($method, $args)
Taufan Aditya8749bc72012-03-11 05:43:45 +0700370 {
Andrey Andreevf243ce12012-06-09 23:34:21 +0300371 if ($this->{$method} instanceof Closure)
Taufan Aditya8749bc72012-03-11 05:43:45 +0700372 {
373 return call_user_func_array($this->{$method},$args);
Andrey Andreevf243ce12012-06-09 23:34:21 +0300374 }
375 else
Taufan Aditya8749bc72012-03-11 05:43:45 +0700376 {
377 return parent::__call($method, $args);
378 }
379 }
Pascal Kriete69c97a72011-04-20 21:44:54 -0400380
Andrey Andreevf243ce12012-06-09 23:34:21 +0300381}