blob: 980e912c59bb27fae6a49c2cc7791de5e20a74de [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);
41
Eric Barnes68286a42011-04-21 22:00:33 -040042 if (method_exists($this, 'set_up'))
43 {
44 $this->set_up();
45 }
46 }
Andrey Andreevf243ce12012-06-09 23:34:21 +030047
Eric Barnes68286a42011-04-21 22:00:33 -040048 // --------------------------------------------------------------------
Andrey Andreevf243ce12012-06-09 23:34:21 +030049
50 public function tearDown()
Eric Barnes68286a42011-04-21 22:00:33 -040051 {
52 if (method_exists($this, 'tear_down'))
53 {
54 $this->tear_down();
55 }
56 }
Taufan Adityae1dc9ea2012-03-28 16:49:49 +070057
58 // --------------------------------------------------------------------
Andrey Andreevf243ce12012-06-09 23:34:21 +030059
Taufan Adityae1dc9ea2012-03-28 16:49:49 +070060 public static function instance()
61 {
62 return self::$ci_test_instance;
63 }
Andrey Andreevf243ce12012-06-09 23:34:21 +030064
Eric Barnes68286a42011-04-21 22:00:33 -040065 // --------------------------------------------------------------------
Andrey Andreevf243ce12012-06-09 23:34:21 +030066
dchill427ecc5cd2012-10-12 16:25:51 -040067 public function ci_set_config($key = '', $val = '')
Pascal Kriete69c97a72011-04-20 21:44:54 -040068 {
dchill427ecc5cd2012-10-12 16:25:51 -040069 // Add test config
70 if ( ! isset($this->ci_instance->config))
71 {
72 $this->ci_instance->config = new CI_TestConfig();
73 }
74
75 // Empty key means just do setup above
76 if ($key === '')
77 {
78 return;
79 }
80
Pascal Krieteae7b3f92011-04-21 01:21:27 -040081 if (is_array($key))
82 {
dchill427ecc5cd2012-10-12 16:25:51 -040083 $this->ci_instance->config->config = $key;
Pascal Krieteae7b3f92011-04-21 01:21:27 -040084 }
85 else
86 {
dchill427ecc5cd2012-10-12 16:25:51 -040087 $this->ci_instance->config->config[$key] = $val;
Pascal Krieteae7b3f92011-04-21 01:21:27 -040088 }
Pascal Krietefe372e32011-04-21 00:59:45 -040089 }
Taufan Adityae1dc9ea2012-03-28 16:49:49 +070090
91 // --------------------------------------------------------------------
Andrey Andreevf243ce12012-06-09 23:34:21 +030092
93 public function ci_get_config()
Taufan Adityae1dc9ea2012-03-28 16:49:49 +070094 {
dchill427ecc5cd2012-10-12 16:25:51 -040095 return isset($this->ci_instance->config) ? $this->ci_instance->config->config : array();
Taufan Adityae1dc9ea2012-03-28 16:49:49 +070096 }
Andrey Andreevf243ce12012-06-09 23:34:21 +030097
Pascal Krietefe372e32011-04-21 00:59:45 -040098 // --------------------------------------------------------------------
Andrey Andreevf243ce12012-06-09 23:34:21 +030099
100 public function ci_instance($obj = FALSE)
Pascal Krietefe372e32011-04-21 00:59:45 -0400101 {
102 if ( ! is_object($obj))
103 {
104 return $this->ci_instance;
105 }
Andrey Andreevf243ce12012-06-09 23:34:21 +0300106
Pascal Kriete69c97a72011-04-20 21:44:54 -0400107 $this->ci_instance = $obj;
108 }
Andrey Andreevf243ce12012-06-09 23:34:21 +0300109
Pascal Kriete69c97a72011-04-20 21:44:54 -0400110 // --------------------------------------------------------------------
Andrey Andreevf243ce12012-06-09 23:34:21 +0300111
112 public function ci_instance_var($name, $obj = FALSE)
Pascal Kriete69c97a72011-04-20 21:44:54 -0400113 {
Pascal Krietefe372e32011-04-21 00:59:45 -0400114 if ( ! is_object($obj))
115 {
116 return $this->ci_instance->$name;
117 }
Andrey Andreevf243ce12012-06-09 23:34:21 +0300118
Pascal Kriete69c97a72011-04-20 21:44:54 -0400119 $this->ci_instance->$name =& $obj;
120 }
Andrey Andreevf243ce12012-06-09 23:34:21 +0300121
Pascal Kriete69c97a72011-04-20 21:44:54 -0400122 // --------------------------------------------------------------------
Pascal Kriete69c97a72011-04-20 21:44:54 -0400123
124 /**
125 * Grab a core class
126 *
127 * Loads the correct core class without extensions
128 * and returns a reference to the class name in the
129 * globals array with the correct key. This way the
130 * test can modify the variable it assigns to and
131 * still maintain the global.
132 */
Andrey Andreevf243ce12012-06-09 23:34:21 +0300133 public function &ci_core_class($name)
Pascal Kriete69c97a72011-04-20 21:44:54 -0400134 {
135 $name = strtolower($name);
Andrey Andreevf243ce12012-06-09 23:34:21 +0300136
Pascal Krieteae7b3f92011-04-21 01:21:27 -0400137 if (isset($this->global_map[$name]))
Pascal Kriete69c97a72011-04-20 21:44:54 -0400138 {
139 $class_name = ucfirst($name);
Pascal Krieteae7b3f92011-04-21 01:21:27 -0400140 $global_name = $this->global_map[$name];
Pascal Kriete69c97a72011-04-20 21:44:54 -0400141 }
Pascal Krieteae7b3f92011-04-21 01:21:27 -0400142 elseif (in_array($name, $this->global_map))
Pascal Kriete69c97a72011-04-20 21:44:54 -0400143 {
Pascal Krieteae7b3f92011-04-21 01:21:27 -0400144 $class_name = ucfirst(array_search($name, $this->global_map));
Pascal Kriete69c97a72011-04-20 21:44:54 -0400145 $global_name = $name;
146 }
147 else
148 {
149 throw new Exception('Not a valid core class.');
150 }
Andrey Andreevf243ce12012-06-09 23:34:21 +0300151
Pascal Kriete69c97a72011-04-20 21:44:54 -0400152 if ( ! class_exists('CI_'.$class_name))
153 {
dchill427ecc5cd2012-10-12 16:25:51 -0400154 require_once SYSTEM_PATH.'core/'.$class_name.'.php';
Pascal Kriete69c97a72011-04-20 21:44:54 -0400155 }
Andrey Andreevf243ce12012-06-09 23:34:21 +0300156
Pascal Kriete69c97a72011-04-20 21:44:54 -0400157 $GLOBALS[strtoupper($global_name)] = 'CI_'.$class_name;
158 return $GLOBALS[strtoupper($global_name)];
159 }
Andrey Andreevf243ce12012-06-09 23:34:21 +0300160
Pascal Kriete69c97a72011-04-20 21:44:54 -0400161 // --------------------------------------------------------------------
Andrey Andreevf243ce12012-06-09 23:34:21 +0300162
Pascal Kriete69c97a72011-04-20 21:44:54 -0400163 // convenience function for global mocks
Andrey Andreevf243ce12012-06-09 23:34:21 +0300164 public function ci_set_core_class($name, $obj)
Pascal Kriete69c97a72011-04-20 21:44:54 -0400165 {
166 $orig =& $this->ci_core_class($name);
167 $orig = $obj;
168 }
Andrey Andreevf243ce12012-06-09 23:34:21 +0300169
dchill427ecc5cd2012-10-12 16:25:51 -0400170 /**
171 * Create VFS directory
172 *
173 * @param string Directory name
174 * @param object Optional root to create in
175 * @return object New directory object
176 */
177 public function ci_vfs_mkdir($name, $root = NULL)
178 {
179 // Check for root
180 if ( ! $root)
181 {
182 $root = $this->ci_vfs_root;
183 }
184
185 // Return new directory object
186 return vfsStream::newDirectory($name)->at($root);
187 }
188
189 // --------------------------------------------------------------------
190
191 /**
192 * Create VFS content
193 *
194 * @param string File name
195 * @param string File content
196 * @param object VFS directory object
197 * @param mixed Optional subdirectory path or array of subs
198 * @return void
199 */
200 public function ci_vfs_create($file, $content = '', $root = NULL, $path = NULL)
201 {
202 // Check for array
203 if (is_array($file))
204 {
205 foreach ($file as $name => $content)
206 {
207 $this->ci_vfs_create($name, $content, $root, $path);
208 }
209 return;
210 }
211
212 // Assert .php extension if none given
213 if (pathinfo($file, PATHINFO_EXTENSION) == '')
214 {
215 $file .= '.php';
216 }
217
218 // Build content
219 $tree = array($file => $content);
220
221 // Check for path
222 $subs = array();
223 if ($path)
224 {
225 // Explode if not array
226 $subs = is_array($path) ? $path : explode('/', trim($path, '/'));
227 }
228
229 // Check for root
230 if ( ! $root)
231 {
232 // Use base VFS root
233 $root = $this->ci_vfs_root;
234 }
235
236 // Handle subdirectories
237 while (($dir = array_shift($subs)))
238 {
239 // See if subdir exists under current root
240 $dir_root = $root->getChild($dir);
241 if ($dir_root)
242 {
243 // Yes - recurse into subdir
244 $root = $dir_root;
245 }
246 else
247 {
248 // No - put subdirectory back and quit
249 array_unshift($subs, $dir);
250 break;
251 }
252 }
253
254 // Create any remaining subdirectories
255 if ($subs)
256 {
257 foreach (array_reverse($subs) as $dir)
258 {
259 // Wrap content in subdirectory for creation
260 $tree = array($dir => $tree);
261 }
262 }
263
264 // Create tree
265 vfsStream::create($tree, $root);
266 }
267
268 // --------------------------------------------------------------------
269
270 /**
271 * Clone a real file into VFS
272 *
273 * @param string Path from base directory
274 * @return bool TRUE on success, otherwise FALSE
275 */
276 public function ci_vfs_clone($path)
277 {
278 // Get real file contents
279 $content = file_get_contents(PROJECT_BASE.$path);
280 if ($content === FALSE)
281 {
282 // Couldn't find file to clone
283 return FALSE;
284 }
285
286 $this->ci_vfs_create(basename($path), $content, NULL, dirname($path));
287 return TRUE;
288 }
289
290 // --------------------------------------------------------------------
291
292 /**
293 * Helper to get a VFS URL path
294 *
295 * @param string Path
296 * @param string Optional base path
297 * @return string Path URL
298 */
299 public function ci_vfs_path($path, $base = '')
300 {
301 // Check for base path
302 if ($base)
303 {
304 // Prepend to path
305 $path = rtrim($base, '/').'/'.ltrim($path, '/');
306
307 // Is it already in URL form?
308 if (strpos($path, '://') !== FALSE)
309 {
310 // Done - return path
311 return $path;
312 }
313 }
314
315 // Trim leading slash and return URL
316 return vfsStream::url(ltrim($path, '/'));
317 }
318
Pascal Kriete69c97a72011-04-20 21:44:54 -0400319 // --------------------------------------------------------------------
Pascal Krieteae7b3f92011-04-21 01:21:27 -0400320 // Internals
321 // --------------------------------------------------------------------
Andrey Andreevf243ce12012-06-09 23:34:21 +0300322
Pascal Krieteae7b3f92011-04-21 01:21:27 -0400323 /**
324 * Overwrite runBare
325 *
326 * PHPUnit instantiates the test classes before
327 * running them individually. So right before a test
328 * runs we set our instance. Normally this step would
329 * happen in setUp, but someone is bound to forget to
330 * call the parent method and debugging this is no fun.
331 */
332 public function runBare()
Pascal Krietefe372e32011-04-21 00:59:45 -0400333 {
Pascal Krieteae7b3f92011-04-21 01:21:27 -0400334 self::$ci_test_instance = $this;
335 parent::runBare();
Pascal Krietefe372e32011-04-21 00:59:45 -0400336 }
Taufan Adityae1dc9ea2012-03-28 16:49:49 +0700337
Pascal Krietefe372e32011-04-21 00:59:45 -0400338 // --------------------------------------------------------------------
Andrey Andreevf243ce12012-06-09 23:34:21 +0300339
340 public function helper($name)
Pascal Krieteae7b3f92011-04-21 01:21:27 -0400341 {
dchill427ecc5cd2012-10-12 16:25:51 -0400342 require_once(SYSTEM_PATH.'helpers/'.$name.'_helper.php');
343 }
344
345 // --------------------------------------------------------------------
346
347 public function lang($name)
348 {
349 require(SYSTEM_PATH.'language/english/'.$name.'_lang.php');
350 return $lang;
Pascal Krietefe372e32011-04-21 00:59:45 -0400351 }
Taufan Aditya8749bc72012-03-11 05:43:45 +0700352
353 // --------------------------------------------------------------------
Andrey Andreevf243ce12012-06-09 23:34:21 +0300354
Taufan Aditya8749bc72012-03-11 05:43:45 +0700355 /**
356 * This overload is useful to create a stub, that need to have a specific method.
357 */
Andrey Andreevf243ce12012-06-09 23:34:21 +0300358 public function __call($method, $args)
Taufan Aditya8749bc72012-03-11 05:43:45 +0700359 {
Andrey Andreevf243ce12012-06-09 23:34:21 +0300360 if ($this->{$method} instanceof Closure)
Taufan Aditya8749bc72012-03-11 05:43:45 +0700361 {
362 return call_user_func_array($this->{$method},$args);
Andrey Andreevf243ce12012-06-09 23:34:21 +0300363 }
364 else
Taufan Aditya8749bc72012-03-11 05:43:45 +0700365 {
366 return parent::__call($method, $args);
367 }
368 }
Pascal Kriete69c97a72011-04-20 21:44:54 -0400369
Andrey Andreevf243ce12012-06-09 23:34:21 +0300370}