diff options
-rw-r--r-- | system/core/Loader.php | 12 | ||||
-rw-r--r-- | tests/codeigniter/core/Config_test.php | 52 | ||||
-rw-r--r-- | tests/codeigniter/core/Loader_test.php | 353 | ||||
-rw-r--r-- | tests/mocks/core/loader.php | 40 |
4 files changed, 395 insertions, 62 deletions
diff --git a/system/core/Loader.php b/system/core/Loader.php index 75e93608a..ed830e2dd 100644 --- a/system/core/Loader.php +++ b/system/core/Loader.php @@ -1140,13 +1140,16 @@ class CI_Loader { */ protected function _ci_autoloader() { - if (defined('ENVIRONMENT') && file_exists(APPPATH.'config/'.ENVIRONMENT.'/autoload.php')) + // Get autoloader file from config path + $CI =& get_instance(); + $path = reset($CI->config->_config_paths).'config/'; + if (defined('ENVIRONMENT') && file_exists($path.ENVIRONMENT.'/autoload.php')) { - include(APPPATH.'config/'.ENVIRONMENT.'/autoload.php'); + include($path.ENVIRONMENT.'/autoload.php'); } else { - include(APPPATH.'config/autoload.php'); + include($path.'autoload.php'); } if ( ! isset($autoload)) @@ -1166,7 +1169,6 @@ class CI_Loader { // Load any custom config file if (count($autoload['config']) > 0) { - $CI =& get_instance(); foreach ($autoload['config'] as $key => $val) { $CI->config->load($val); @@ -1275,4 +1277,4 @@ class CI_Loader { } /* End of file Loader.php */ -/* Location: ./system/core/Loader.php */
\ No newline at end of file +/* Location: ./system/core/Loader.php */ diff --git a/tests/codeigniter/core/Config_test.php b/tests/codeigniter/core/Config_test.php index 30cb90a28..7782a7898 100644 --- a/tests/codeigniter/core/Config_test.php +++ b/tests/codeigniter/core/Config_test.php @@ -90,4 +90,54 @@ class Config_test extends CI_TestCase { $this->assertEquals('http://example.com/system/', $this->config->system_url()); } -}
\ No newline at end of file + // -------------------------------------------------------------------- + + public function test_load() + { + // Create VFS tree of application config files + $file1 = 'test.php'; + $file2 = 'secttest'; + $key1 = 'testconfig'; + $val1 = 'my_value'; + $cfg1 = array( + $key1 => $val1 + ); + $cfg2 = array( + 'one' => 'prime', + 'two' => 2, + 'three' => true + ); + $tree = array( + 'application' => array( + 'config' => array( + $file1 => '<?php $config = '.var_export($cfg1, TRUE).';', + $file2.'.php' => '<?php $config = '.var_export($cfg2, TRUE).';' + ) + ) + ); + $root = vfsStream::setup('root', NULL, $tree); + + // Set config path with VFS URL + $this->config->_config_paths = array(vfsStream::url('application').'/'); + + // Test regular load + $this->assertTrue($this->config->load($file1)); + $this->assertEquals($val1, $this->config->item($key1)); + + // Test section load + $this->assertTrue($this->config->load($file2, TRUE)); + $this->assertEquals($cfg2, $this->config->item($file2)); + + // Test graceful fail + $this->assertFalse($this->config->load('not_config_file', FALSE, TRUE)); + + // Test regular fail + $file3 = 'absentia'; + $this->setExpectedException( + 'RuntimeException', + 'CI Error: The configuration file '.$file3.'.php does not exist.' + ); + $this->assertNull($this->config->load($file3)); + } + +} diff --git a/tests/codeigniter/core/Loader_test.php b/tests/codeigniter/core/Loader_test.php index fdea962b7..db79e6a8b 100644 --- a/tests/codeigniter/core/Loader_test.php +++ b/tests/codeigniter/core/Loader_test.php @@ -18,54 +18,123 @@ class Loader_test extends CI_TestCase { // -------------------------------------------------------------------- + /** + * @covers CI_Loader::library + */ public function test_library() { $this->_setup_config_mock(); + // Create libraries directory with test library + $lib = 'unit_test_lib'; + $class = 'CI_'.ucfirst($lib); + $content = '<?php class '.$class.' { } '; + $this->_create_content('libraries', $lib, $content, NULL, TRUE); + // Test loading as an array. - $this->assertNull($this->load->library(array('table'))); - $this->assertTrue(class_exists('CI_Table'), 'Table class exists'); - $this->assertAttributeInstanceOf('CI_Table', 'table', $this->ci_obj); + $this->assertNull($this->load->library(array($lib))); + $this->assertTrue(class_exists($class), $class.' does not exist'); + $this->assertAttributeInstanceOf($class, $lib, $this->ci_obj); // Test no lib given - $this->assertEquals(FALSE, $this->load->library()); + $this->assertFalse($this->load->library()); // Test a string given to params - $this->assertEquals(NULL, $this->load->library('table', ' ')); + $this->assertNull($this->load->library($lib, ' ')); } // -------------------------------------------------------------------- + /** + * @covers CI_Loader::library + */ + public function test_library_config() + { + $this->_setup_config_mock(); + + // Create libraries directory with test library + $lib = 'unit_test_config_lib'; + $class = 'CI_'.ucfirst($lib); + $content = '<?php class '.$class.' { public function __construct($params) { $this->config = $params; } } '; + $this->_create_content('libraries', $lib, $content, NULL, TRUE); + + // Create config file + $cfg = array( + 'foo' => 'bar', + 'bar' => 'baz', + 'baz' => false + ); + $this->_create_content('config', $lib, '<?php $config = '.var_export($cfg, TRUE).';'); + + // Test object name and config + $obj = 'testy'; + $this->assertNull($this->load->library($lib, NULL, $obj)); + $this->assertTrue(class_exists($class), $class.' does not exist'); + $this->assertAttributeInstanceOf($class, $obj, $this->ci_obj); + $this->assertEquals($cfg, $this->ci_obj->$obj->config); + } + + // -------------------------------------------------------------------- + + /** + * @covers CI_Loader::library + */ public function test_load_library_in_application_dir() { $this->_setup_config_mock(); - $content = '<?php class Super_test_library {} '; + // Create libraries directory in app path with test library + $lib = 'super_test_library'; + $class = ucfirst($lib); + $content = '<?php class '.$class.' {} '; + $this->_create_content('libraries', $lib, $content); - $model = vfsStream::newFile('Super_test_library.php')->withContent($content)->at($this->load->libs_dir); - $this->assertNull($this->load->library('super_test_library')); + // Load library + $this->assertNull($this->load->library($lib)); // Was the model class instantiated. - $this->assertTrue(class_exists('Super_test_library')); + $this->assertTrue(class_exists($class), $class.' does not exist'); + $this->assertAttributeInstanceOf($class, $lib, $this->ci_obj); } // -------------------------------------------------------------------- - private function _setup_config_mock() + /** + * @covers CI_Loader::driver + */ + public function test_driver() { - // Mock up a config object until we - // figure out how to test the library configs - $config = $this->getMock('CI_Config', NULL, array(), '', FALSE); - $config->expects($this->any()) - ->method('load') - ->will($this->returnValue(TRUE)); + $this->_setup_config_mock(); - // Add the mock to our stdClass - $this->ci_instance_var('config', $config); + // Create libraries directory with test driver + $driver = 'unit_test_driver'; + $dir = ucfirst($driver); + $class = 'CI_'.$dir; + $content = '<?php class '.$class.' { } '; + $this->_create_content('libraries', $driver, $content, $dir, TRUE); + + // Test loading as an array. + $this->assertNull($this->load->driver(array($driver))); + $this->assertTrue(class_exists($class), $class.' does not exist'); + $this->assertAttributeInstanceOf($class, $driver, $this->ci_obj); + + // Test loading as a library with a name + $obj = 'testdrive'; + $this->assertNull($this->load->library($driver, NULL, $obj)); + $this->assertAttributeInstanceOf($class, $obj, $this->ci_obj); + + // Test no driver given + $this->assertFalse($this->load->driver()); + + // Test a string given to params + $this->assertNull($this->load->driver($driver, ' ')); } // -------------------------------------------------------------------- + /** + * @covers CI_Loader::model + */ public function test_non_existent_model() { $this->setExpectedException( @@ -79,20 +148,23 @@ class Loader_test extends CI_TestCase { // -------------------------------------------------------------------- /** - * @coverts CI_Loader::model + * @covers CI_Loader::model */ public function test_models() { $this->ci_set_core_class('model', 'CI_Model'); - $content = '<?php class Unit_test_model extends CI_Model {} '; + // Create models directory with test model + $model = 'unit_test_model'; + $class = ucfirst($model); + $content = '<?php class '.$class.' extends CI_Model {} '; + $this->_create_content('models', $model, $content); - $model = vfsStream::newFile('unit_test_model.php')->withContent($content)->at($this->load->models_dir); - - $this->assertNull($this->load->model('unit_test_model')); + // Load model + $this->assertNull($this->load->model($model)); // Was the model class instantiated. - $this->assertTrue(class_exists('Unit_test_model')); + $this->assertTrue(class_exists($class)); // Test no model given $this->assertNull($this->load->model('')); @@ -109,26 +181,27 @@ class Loader_test extends CI_TestCase { // -------------------------------------------------------------------- /** - * @coverts CI_Loader::view + * @covers CI_Loader::view */ public function test_load_view() { $this->ci_set_core_class('output', 'CI_Output'); + // Create views directory with test view + $view = 'unit_test_view'; $content = 'This is my test page. <?php echo $hello; ?>'; - $view = vfsStream::newFile('unit_test_view.php')->withContent($content)->at($this->load->views_dir); + $this->_create_content('views', $view, $content); // Use the optional return parameter in this test, so the view is not // run through the output class. - $this->assertEquals('This is my test page. World!', - $this->load->view('unit_test_view', array('hello' => "World!"), TRUE)); - + $out = $this->load->view($view, array('hello' => "World!"), TRUE); + $this->assertEquals('This is my test page. World!', $out); } // -------------------------------------------------------------------- /** - * @coverts CI_Loader::view + * @covers CI_Loader::view */ public function test_non_existent_view() { @@ -142,16 +215,22 @@ class Loader_test extends CI_TestCase { // -------------------------------------------------------------------- + /** + * @covers CI_Loader::file + */ public function test_file() { + // Create views directory with test file + $dir = 'views'; + $file = 'ci_test_mock_file'; $content = 'Here is a test file, which we will load now.'; - $file = vfsStream::newFile('ci_test_mock_file.php')->withContent($content)->at($this->load->views_dir); + $this->_create_content($dir, $file, $content); // Just like load->view(), take the output class out of the mix here. - $load = $this->load->file(vfsStream::url('application').'/views/ci_test_mock_file.php', TRUE); - - $this->assertEquals($content, $load); + $out = $this->load->file($this->load->app_path.$dir.'/'.$file.'.php', TRUE); + $this->assertEquals($content, $out); + // Test non-existent file $this->setExpectedException( 'RuntimeException', 'CI Error: Unable to load the requested file: ci_test_file_not_exists' @@ -162,6 +241,9 @@ class Loader_test extends CI_TestCase { // -------------------------------------------------------------------- + /** + * @covers CI_Loader::vars + */ public function test_vars() { $this->assertNull($this->load->vars(array('foo' => 'bar'))); @@ -170,10 +252,22 @@ class Loader_test extends CI_TestCase { // -------------------------------------------------------------------- + /** + * @covers CI_Loader::helper + */ public function test_helper() { - $this->assertEquals(NULL, $this->load->helper('array')); + // Create helper directory in app path with test helper + $helper = 'test'; + $func = '_my_helper_test_func'; + $content = '<?php function '.$func.'() { return true; } '; + $this->_create_content('helpers', $helper.'_helper', $content); + // Load helper + $this->assertEquals(NULL, $this->load->helper($helper)); + $this->assertTrue(function_exists($func), $func.' does not exist'); + + // Test non-existent helper $this->setExpectedException( 'RuntimeException', 'CI Error: Unable to load the requested file: helpers/bad_helper.php' @@ -184,9 +278,31 @@ class Loader_test extends CI_TestCase { // -------------------------------------------------------------------- + /** + * @covers CI_Loader::helper + */ public function test_loading_multiple_helpers() { - $this->assertEquals(NULL, $this->load->helpers(array('file', 'array', 'string'))); + // Create helper directory in base path with test helpers + $helpers = array(); + $funcs = array(); + $files = array(); + for ($i = 1; $i <= 3; ++$i) { + $helper = 'test'.$i; + $helpers[] = $helper; + $func = '_my_helper_test_func'.$i; + $funcs[] = $func; + $files[$helper.'_helper'] = '<?php function '.$func.'() { return true; } '; + } + $this->_create_content('helpers', $files, NULL, NULL, TRUE); + + // Load helpers + $this->assertEquals(NULL, $this->load->helpers($helpers)); + + // Verify helper existence + foreach ($funcs as $func) { + $this->assertTrue(function_exists($func), $func.' does not exist'); + } } // -------------------------------------------------------------------- @@ -198,6 +314,52 @@ class Loader_test extends CI_TestCase { // -------------------------------------------------------------------- + /** + * @covers CI_Loader::add_package_path + * @covers CI_Loader::get_package_paths + * @covers CI_Loader::remove_package_path + */ + public function test_packages() + { + $this->_setup_config_mock(); + + // Create third-party directory in app path with model + $dir = 'third-party'; + $lib = 'unit_test_package'; + $class = 'CI_'.ucfirst($lib); + $content = '<?php class '.$class.' { } '; + $this->_create_content($dir, $lib, $content); + + // Test failed load without path + $this->setExpectedException( + 'RuntimeException', + 'CI Error: Unable to load the requested class: '.$lib + ); + $this->load->library($lib); + + // Clear exception and get paths + $this->setExpectedException(NULL); + $paths = $this->load->get_package_paths(TRUE); + + // Add path and verify + $path = $this->load->app_path.$dir; + $this->assertNull($this->load->add_package_path($path)); + $this->assertContains($path, $this->load->get_package_paths(TRUE)); + + // Test successful load + $this->assertNull($this->load->library($lib)); + $this->assertTrue(class_exists($class), $class.' does not exist'); + + // Remove path and verify restored paths + $this->assertNull($this->load->remove_package_path($path)); + $this->assertEquals($paths, $this->load->get_package_paths(TRUE)); + } + + // -------------------------------------------------------------------- + + /** + * @covers CI_Loader::config + */ public function test_load_config() { $this->_setup_config_mock(); @@ -206,16 +368,123 @@ class Loader_test extends CI_TestCase { // -------------------------------------------------------------------- - public function test_load_bad_config() + /** + * @covers CI_Loader::_ci_autoloader + */ + public function test_autoloader() { $this->_setup_config_mock(); - $this->setExpectedException( - 'RuntimeException', - 'CI Error: The configuration file foobar.php does not exist.' + // Create helper directory in app path with test helper + $helper = 'autohelp'; + $hlp_func = '_autohelp_test_func'; + $this->_create_content('helpers', $helper.'_helper', '<?php function '.$hlp_func.'() { return true; } '); + + // Create libraries directory in base path with test library + $lib = 'autolib'; + $lib_class = 'CI_'.ucfirst($lib); + $this->_create_content('libraries', $lib, '<?php class '.$lib_class.' { } ', NULL, TRUE); + + // Create libraries subdirectory with test driver + // Since libraries/ now exists, we have to look it up and + // add the subdir directly instead of using _create_content + $drv = 'autodrv'; + $subdir = ucfirst($drv); + $drv_class = 'CI_'.$subdir; + $tree = array( + $subdir => array($drv.'.php' => '<?php class '.$drv_class.' { } ') ); + vfsStream::create($tree, $this->load->base_root->getChild('libraries')); + + // Create package directory in app path with model + $dir = 'testdir'; + $path = $this->load->app_path.$dir.'/'; + $model = 'automod'; + $mod_class = ucfirst($model); + $this->_create_content($dir, $model, '<?php class '.$mod_class.' { } ', 'models'); + + // Create autoloader config + $cfg = array( + 'packages' => array($path), + 'helper' => array($helper), + 'libraries' => array($lib), + 'drivers' => array($drv), + 'model' => array($model), + 'config' => array() + ); + $this->_create_content('config', 'autoload', '<?php $autoload = '.var_export($cfg, TRUE).';'); + + // Run autoloader + $this->load->autoload(); - $this->load->config('foobar', FALSE); + // Verify path + $this->assertContains($path, $this->load->get_package_paths()); + + // Verify helper + $this->assertTrue(function_exists($hlp_func), $hlp_func.' does not exist'); + + // Verify library + $this->assertTrue(class_exists($lib_class), $lib_class.' does not exist'); + $this->assertAttributeInstanceOf($lib_class, $lib, $this->ci_obj); + + // Verify driver + $this->assertTrue(class_exists($drv_class), $drv_class.' does not exist'); + $this->assertAttributeInstanceOf($drv_class, $drv, $this->ci_obj); + + // Verify model + $this->assertTrue(class_exists($mod_class), $mod_class.' does not exist'); + $this->assertAttributeInstanceOf($mod_class, $model, $this->ci_obj); + } + + // -------------------------------------------------------------------- + + private function _setup_config_mock() + { + // Mock up a config object so config() has something to call + $config = $this->getMock('CI_Config', array('load'), array(), '', FALSE); + $config->expects($this->any()) + ->method('load') + ->will($this->returnValue(TRUE)); + + // Reinitialize config paths to use VFS + $config->_config_paths = array($this->load->app_path); + + // Add the mock to our stdClass + $this->ci_instance_var('config', $config); + } + + // -------------------------------------------------------------------- + + private function _create_content($dir, $file, $content, $sub = NULL, $base = FALSE) + { + // Create structure containing directory + $tree = array($dir => array()); + + // Check for subdirectory + if ($sub) { + // Add subdirectory to tree and get reference + $tree[$dir][$sub] = array(); + $leaf =& $tree[$dir][$sub]; + } + else { + // Get reference to main directory + $leaf =& $tree[$dir]; + } + + // Check for multiple files + if (is_array($file)) { + // Add multiple files to directory + foreach ($file as $name => $data) { + $leaf[$name.'.php'] = $data; + } + } + else { + // Add single file with content + $leaf[$file.'.php'] = $content; + } + + // Create structure under app or base path + vfsStream::create($tree, $base ? $this->load->base_root : $this->load->app_root); } -}
\ No newline at end of file +} diff --git a/tests/mocks/core/loader.php b/tests/mocks/core/loader.php index 53d88d55b..9eb78253b 100644 --- a/tests/mocks/core/loader.php +++ b/tests/mocks/core/loader.php @@ -5,27 +5,39 @@ class Mock_Core_Loader extends CI_Loader { /** * Since we use paths to load up models, views, etc, we need the ability to * mock up the file system so when core tests are run, we aren't mucking - * in the application directory. this will give finer grained control over - * these tests. So yeah, while this looks odd, I need to overwrite protected - * class vars in the loader. So here we go... + * in the application directory. This will give finer grained control over + * these tests. Also, by mocking the system directory, we eliminate dependency + * on any other classes so errors in libraries, helpers, etc. don't give false + * negatives for the actual loading process. So yeah, while this looks odd, + * I need to overwrite protected class vars in the loader. So here we go... * * @covers CI_Loader::__construct() */ public function __construct() { - vfsStreamWrapper::register(); - vfsStreamWrapper::setRoot(new vfsStreamDirectory('application')); + // Create VFS tree of loader locations + $this->root = vfsStream::setup(); + $this->app_root = vfsStream::newDirectory('application')->at($this->root); + $this->base_root = vfsStream::newDirectory('system')->at($this->root); - $this->models_dir = vfsStream::newDirectory('models')->at(vfsStreamWrapper::getRoot()); - $this->libs_dir = vfsStream::newDirectory('libraries')->at(vfsStreamWrapper::getRoot()); - $this->helpers_dir = vfsStream::newDirectory('helpers')->at(vfsStreamWrapper::getRoot()); - $this->views_dir = vfsStream::newDirectory('views')->at(vfsStreamWrapper::getRoot()); + // Get VFS app and base path URLs + $this->app_path = vfsStream::url('application').'/'; + $this->base_path = vfsStream::url('system').'/'; + // Set loader paths with VFS URLs $this->_ci_ob_level = ob_get_level(); - $this->_ci_library_paths = array(vfsStream::url('application').'/', BASEPATH); - $this->_ci_helper_paths = array(vfsStream::url('application').'/', BASEPATH); - $this->_ci_model_paths = array(vfsStream::url('application').'/'); - $this->_ci_view_paths = array(vfsStream::url('application').'/views/' => TRUE); + $this->_ci_library_paths = array($this->app_path, $this->base_path); + $this->_ci_helper_paths = array($this->app_path, $this->base_path); + $this->_ci_model_paths = array($this->app_path); + $this->_ci_view_paths = array($this->app_path.'views/' => TRUE); } -}
\ No newline at end of file + /** + * Give public access to _ci_autoloader for testing + */ + public function autoload() + { + $this->_ci_autoloader(); + } + +} |