summaryrefslogtreecommitdiffstats
path: root/tests/mocks
diff options
context:
space:
mode:
Diffstat (limited to 'tests/mocks')
-rw-r--r--tests/mocks/autoloader.php94
-rw-r--r--tests/mocks/ci_testcase.php194
-rw-r--r--tests/mocks/core/benchmark.php3
-rw-r--r--tests/mocks/core/common.php169
-rw-r--r--tests/mocks/core/input.php31
-rw-r--r--tests/mocks/core/loader.php31
-rw-r--r--tests/mocks/core/security.php30
-rw-r--r--tests/mocks/core/uri.php26
-rw-r--r--tests/mocks/core/utf8.php26
-rwxr-xr-xtests/mocks/database/ci_test.sqlitebin0 -> 19456 bytes
-rw-r--r--tests/mocks/database/config/mysql.php34
-rw-r--r--tests/mocks/database/config/pdo/mysql.php37
-rw-r--r--tests/mocks/database/config/pdo/pgsql.php37
-rw-r--r--tests/mocks/database/config/pdo/sqlite.php37
-rw-r--r--tests/mocks/database/config/pgsql.php34
-rw-r--r--tests/mocks/database/config/sqlite.php34
-rw-r--r--tests/mocks/database/db.php100
-rw-r--r--tests/mocks/database/db/driver.php39
-rw-r--r--tests/mocks/database/db/querybuilder.php3
-rw-r--r--tests/mocks/database/drivers/mysql.php17
-rw-r--r--tests/mocks/database/drivers/pdo.php16
-rw-r--r--tests/mocks/database/drivers/postgre.php17
-rw-r--r--tests/mocks/database/drivers/sqlite.php17
-rw-r--r--tests/mocks/database/schema/skeleton.php147
-rw-r--r--tests/mocks/libraries/encrypt.php16
-rw-r--r--tests/mocks/libraries/parser.php3
-rw-r--r--tests/mocks/libraries/table.php16
-rw-r--r--tests/mocks/libraries/typography.php3
-rw-r--r--tests/mocks/libraries/useragent.php3
29 files changed, 1214 insertions, 0 deletions
diff --git a/tests/mocks/autoloader.php b/tests/mocks/autoloader.php
new file mode 100644
index 000000000..be1c2220c
--- /dev/null
+++ b/tests/mocks/autoloader.php
@@ -0,0 +1,94 @@
+<?php
+
+// This autoloader provide convinient way to working with mock object
+// make the test looks natural. This autoloader support cascade file loading as well
+// within mocks directory.
+//
+// Prototype :
+//
+// $mock_table = new Mock_Libraries_Table(); // Will load ./mocks/libraries/table.php
+// $mock_database_driver = new Mock_Database_Driver(); // Will load ./mocks/database/driver.php
+// and so on...
+function autoload($class)
+{
+ $dir = realpath(dirname(__FILE__)).DIRECTORY_SEPARATOR;
+
+ $ci_core = array(
+ 'Benchmark', 'Config', 'Controller',
+ 'Exceptions', 'Hooks', 'Input',
+ 'Lang', 'Loader', 'Model',
+ 'Output', 'Router', 'Security',
+ 'URI', 'Utf8',
+ );
+
+ $ci_libraries = array(
+ 'Calendar', 'Cart', 'Driver_Library',
+ 'Email', 'Encrypt', 'Form_validation',
+ 'Ftp', 'Image_lib', 'Javascript',
+ 'Log', 'Migration', 'Pagination',
+ 'Parser', 'Profiler', 'Session',
+ 'Table', 'Trackback', 'Typography',
+ 'Unit_test', 'Upload', 'User_agent',
+ 'Xmlrpc', 'Zip',
+ );
+
+ if (strpos($class, 'Mock_') === 0)
+ {
+ $class = str_replace(array('Mock_', '_'), array('', DIRECTORY_SEPARATOR), $class);
+ $class = strtolower($class);
+ }
+ elseif (strpos($class, 'CI_') === 0)
+ {
+ $fragments = explode('_', $class, 2);
+ $subclass = next($fragments);
+
+ if (in_array($subclass, $ci_core))
+ {
+ $dir = BASEPATH.'core'.DIRECTORY_SEPARATOR;
+ $class = $subclass;
+ }
+ elseif (in_array($subclass, $ci_libraries))
+ {
+ $dir = BASEPATH.'libraries'.DIRECTORY_SEPARATOR;
+ $class = ($subclass === 'Driver_Library') ? 'Driver' : $subclass;
+ }
+ elseif (preg_match('/^CI_DB_(.+)_(driver|forge|result|utility)$/', $class, $m) && count($m) === 3)
+ {
+ $driver_path = BASEPATH.'database'.DIRECTORY_SEPARATOR.'drivers'.DIRECTORY_SEPARATOR;
+ $dir = $driver_path.$m[1].DIRECTORY_SEPARATOR;
+ $file = $dir.$m[1].'_'.$m[2].'.php';
+ }
+ elseif (strpos($class, 'CI_DB') === 0)
+ {
+ $dir = BASEPATH.'database'.DIRECTORY_SEPARATOR;
+ $file = $dir.str_replace(array('CI_DB','active_record'), array('DB', 'active_rec'), $subclass).'.php';
+ }
+ else
+ {
+ $class = strtolower($class);
+ }
+ }
+
+ $file = (isset($file)) ? $file : $dir.$class.'.php';
+
+ if ( ! file_exists($file))
+ {
+ $trace = debug_backtrace();
+
+ if ($trace[2]['function'] === 'class_exists' OR $trace[2]['function'] === 'file_exists')
+ {
+ // If the autoload call came from `class_exists` or `file_exists`,
+ // we skipped and return FALSE
+ return FALSE;
+ }
+ elseif (($autoloader = spl_autoload_functions()) && end($autoloader) !== __FUNCTION__)
+ {
+ // If there was other custom autoloader, passed away
+ return FALSE;
+ }
+
+ throw new InvalidArgumentException("Unable to load {$class}.");
+ }
+
+ include_once($file);
+} \ No newline at end of file
diff --git a/tests/mocks/ci_testcase.php b/tests/mocks/ci_testcase.php
new file mode 100644
index 000000000..eda9e1b60
--- /dev/null
+++ b/tests/mocks/ci_testcase.php
@@ -0,0 +1,194 @@
+<?php
+
+class CI_TestCase extends PHPUnit_Framework_TestCase {
+
+ protected $ci_config;
+ protected $ci_instance;
+ protected static $ci_test_instance;
+
+ private $global_map = array(
+ 'benchmark' => 'bm',
+ 'config' => 'cfg',
+ 'hooks' => 'ext',
+ 'utf8' => 'uni',
+ 'router' => 'rtr',
+ 'output' => 'out',
+ 'security' => 'sec',
+ 'input' => 'in',
+ 'lang' => 'lang',
+ 'loader' => 'load',
+ 'model' => 'model'
+ );
+
+ // --------------------------------------------------------------------
+
+ public function __construct()
+ {
+ parent::__construct();
+ $this->ci_config = array();
+ }
+
+ // --------------------------------------------------------------------
+
+ public function setUp()
+ {
+ if (method_exists($this, 'set_up'))
+ {
+ $this->set_up();
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ public function tearDown()
+ {
+ if (method_exists($this, 'tear_down'))
+ {
+ $this->tear_down();
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ public static function instance()
+ {
+ return self::$ci_test_instance;
+ }
+
+ // --------------------------------------------------------------------
+
+ public function ci_set_config($key, $val = '')
+ {
+ if (is_array($key))
+ {
+ $this->ci_config = $key;
+ }
+ else
+ {
+ $this->ci_config[$key] = $val;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ public function ci_get_config()
+ {
+ return $this->ci_config;
+ }
+
+ // --------------------------------------------------------------------
+
+ public function ci_instance($obj = FALSE)
+ {
+ if ( ! is_object($obj))
+ {
+ return $this->ci_instance;
+ }
+
+ $this->ci_instance = $obj;
+ }
+
+ // --------------------------------------------------------------------
+
+ public function ci_instance_var($name, $obj = FALSE)
+ {
+ if ( ! is_object($obj))
+ {
+ return $this->ci_instance->$name;
+ }
+
+ $this->ci_instance->$name =& $obj;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Grab a core class
+ *
+ * Loads the correct core class without extensions
+ * and returns a reference to the class name in the
+ * globals array with the correct key. This way the
+ * test can modify the variable it assigns to and
+ * still maintain the global.
+ */
+ public function &ci_core_class($name)
+ {
+ $name = strtolower($name);
+
+ if (isset($this->global_map[$name]))
+ {
+ $class_name = ucfirst($name);
+ $global_name = $this->global_map[$name];
+ }
+ elseif (in_array($name, $this->global_map))
+ {
+ $class_name = ucfirst(array_search($name, $this->global_map));
+ $global_name = $name;
+ }
+ else
+ {
+ throw new Exception('Not a valid core class.');
+ }
+
+ if ( ! class_exists('CI_'.$class_name))
+ {
+ require_once BASEPATH.'core/'.$class_name.'.php';
+ }
+
+ $GLOBALS[strtoupper($global_name)] = 'CI_'.$class_name;
+ return $GLOBALS[strtoupper($global_name)];
+ }
+
+ // --------------------------------------------------------------------
+
+ // convenience function for global mocks
+ public function ci_set_core_class($name, $obj)
+ {
+ $orig =& $this->ci_core_class($name);
+ $orig = $obj;
+ }
+
+ // --------------------------------------------------------------------
+ // Internals
+ // --------------------------------------------------------------------
+
+ /**
+ * Overwrite runBare
+ *
+ * PHPUnit instantiates the test classes before
+ * running them individually. So right before a test
+ * runs we set our instance. Normally this step would
+ * happen in setUp, but someone is bound to forget to
+ * call the parent method and debugging this is no fun.
+ */
+ public function runBare()
+ {
+ self::$ci_test_instance = $this;
+ parent::runBare();
+ }
+
+ // --------------------------------------------------------------------
+
+ public function helper($name)
+ {
+ require_once(BASEPATH.'helpers/'.$name.'_helper.php');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * This overload is useful to create a stub, that need to have a specific method.
+ */
+ public function __call($method, $args)
+ {
+ if ($this->{$method} instanceof Closure)
+ {
+ return call_user_func_array($this->{$method},$args);
+ }
+ else
+ {
+ return parent::__call($method, $args);
+ }
+ }
+
+} \ No newline at end of file
diff --git a/tests/mocks/core/benchmark.php b/tests/mocks/core/benchmark.php
new file mode 100644
index 000000000..d92be21db
--- /dev/null
+++ b/tests/mocks/core/benchmark.php
@@ -0,0 +1,3 @@
+<?php
+
+class Mock_Core_Benchmark extends CI_Benchmark {} \ No newline at end of file
diff --git a/tests/mocks/core/common.php b/tests/mocks/core/common.php
new file mode 100644
index 000000000..a655ee1db
--- /dev/null
+++ b/tests/mocks/core/common.php
@@ -0,0 +1,169 @@
+<?php
+
+// Set up the global CI functions in their most minimal core representation
+
+if ( ! function_exists('get_instance'))
+{
+ function &get_instance()
+ {
+ $test = CI_TestCase::instance();
+ $test = $test->ci_instance();
+ return $test;
+ }
+}
+
+// --------------------------------------------------------------------
+
+if ( ! function_exists('get_config'))
+{
+ function &get_config()
+ {
+ $test = CI_TestCase::instance();
+ $config = $test->ci_get_config();
+ return $config;
+ }
+}
+
+if ( ! function_exists('config_item'))
+{
+ function config_item($item)
+ {
+ $config =& get_config();
+
+ if ( ! isset($config[$item]))
+ {
+ return FALSE;
+ }
+
+ return $config[$item];
+ }
+}
+
+// --------------------------------------------------------------------
+
+if ( ! function_exists('load_class'))
+{
+ function load_class($class, $directory = 'libraries', $prefix = 'CI_')
+ {
+ if ($directory !== 'core' OR $prefix !== 'CI_')
+ {
+ throw new Exception('Not Implemented: Non-core load_class()');
+ }
+
+ $test = CI_TestCase::instance();
+
+ $obj =& $test->ci_core_class($class);
+
+ if (is_string($obj))
+ {
+ throw new Exception('Bad Isolation: Use ci_set_core_class to set '.$class);
+ }
+
+ return $obj;
+ }
+}
+
+// This is sort of meh. Should probably be mocked up with
+// controllable output, so that we can test some of our
+// security code. The function itself will be tested in the
+// bootstrap testsuite.
+// --------------------------------------------------------------------
+
+if ( ! function_exists('remove_invisible_characters'))
+{
+ function remove_invisible_characters($str, $url_encoded = TRUE)
+ {
+ $non_displayables = array();
+
+ // every control character except newline (dec 10)
+ // carriage return (dec 13), and horizontal tab (dec 09)
+
+ if ($url_encoded)
+ {
+ $non_displayables[] = '/%0[0-8bcef]/'; // url encoded 00-08, 11, 12, 14, 15
+ $non_displayables[] = '/%1[0-9a-f]/'; // url encoded 16-31
+ }
+
+ $non_displayables[] = '/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S'; // 00-08, 11, 12, 14-31, 127
+
+ do
+ {
+ $str = preg_replace($non_displayables, '', $str, -1, $count);
+ }
+ while ($count);
+
+ return $str;
+ }
+}
+
+
+// Clean up error messages
+// --------------------------------------------------------------------
+
+if ( ! function_exists('show_error'))
+{
+ function show_error($message, $status_code = 500, $heading = 'An Error Was Encountered')
+ {
+ throw new RuntimeException('CI Error: '.$message);
+ }
+}
+
+if ( ! function_exists('show_404'))
+{
+ function show_404($page = '', $log_error = TRUE)
+ {
+ throw new RuntimeException('CI Error: 404');
+ }
+}
+
+if ( ! function_exists('_exception_handler'))
+{
+ function _exception_handler($severity, $message, $filepath, $line)
+ {
+ throw new RuntimeException('CI Exception: '.$message.' | '.$filepath.' | '.$line);
+ }
+}
+
+
+// We assume a few things about our environment ...
+// --------------------------------------------------------------------
+
+if ( ! function_exists('is_php'))
+{
+ function is_php($version = '5.0.0')
+ {
+ return ! (version_compare(PHP_VERSION, $version) < 0);
+ }
+}
+
+if ( ! function_exists('is_really_writable'))
+{
+ function is_really_writable($file)
+ {
+ return is_writable($file);
+ }
+}
+
+if ( ! function_exists('is_loaded'))
+{
+ function is_loaded()
+ {
+ throw new Exception('Bad Isolation: mock up environment');
+ }
+}
+
+if ( ! function_exists('log_message'))
+{
+ function log_message($level = 'error', $message, $php_error = FALSE)
+ {
+ return TRUE;
+ }
+}
+
+if ( ! function_exists('set_status_header'))
+{
+ function set_status_header($code = 200, $text = '')
+ {
+ return TRUE;
+ }
+} \ No newline at end of file
diff --git a/tests/mocks/core/input.php b/tests/mocks/core/input.php
new file mode 100644
index 000000000..2a4aa4997
--- /dev/null
+++ b/tests/mocks/core/input.php
@@ -0,0 +1,31 @@
+<?php
+
+class Mock_Core_Input extends CI_Input {
+
+ /**
+ * Since we use GLOBAL to fetch Security and Utf8 classes,
+ * we need to use inversion of control to mock up
+ * the same process within CI_Input class constructor.
+ *
+ * @covers CI_Input::__construct()
+ */
+ public function __construct($security, $utf8)
+ {
+ $this->_allow_get_array = (config_item('allow_get_array') === TRUE);
+ $this->_enable_xss = (config_item('global_xss_filtering') === TRUE);
+ $this->_enable_csrf = (config_item('csrf_protection') === TRUE);
+
+ // Assign Security and Utf8 classes
+ $this->security = $security;
+ $this->uni = $utf8;
+
+ // Sanitize global arrays
+ $this->_sanitize_globals();
+ }
+
+ public function fetch_from_array($array, $index = '', $xss_clean = FALSE)
+ {
+ return parent::_fetch_from_array($array, $index, $xss_clean);
+ }
+
+} \ No newline at end of file
diff --git a/tests/mocks/core/loader.php b/tests/mocks/core/loader.php
new file mode 100644
index 000000000..53d88d55b
--- /dev/null
+++ b/tests/mocks/core/loader.php
@@ -0,0 +1,31 @@
+<?php
+
+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...
+ *
+ * @covers CI_Loader::__construct()
+ */
+ public function __construct()
+ {
+ vfsStreamWrapper::register();
+ vfsStreamWrapper::setRoot(new vfsStreamDirectory('application'));
+
+ $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());
+
+ $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);
+ }
+
+} \ No newline at end of file
diff --git a/tests/mocks/core/security.php b/tests/mocks/core/security.php
new file mode 100644
index 000000000..e19a8b20b
--- /dev/null
+++ b/tests/mocks/core/security.php
@@ -0,0 +1,30 @@
+<?php
+
+class Mock_Core_Security extends CI_Security {
+
+ public function csrf_set_cookie()
+ {
+ // We cannot set cookie in CLI mode, so for csrf test, who rely on $_COOKIE,
+ // we superseded set_cookie with directly set the cookie variable,
+ // @see : ./tests/codeigniter/core/Security_test.php, line 8
+ return $this;
+ }
+
+ // Overide inaccesible protected properties
+ public function __get($property)
+ {
+ return isset($this->{'_'.$property}) ? $this->{'_'.$property} : NULL;
+ }
+
+ // Overide inaccesible protected method
+ public function __call($method, $params)
+ {
+ if (is_callable(array($this, '_'.$method)))
+ {
+ return call_user_func_array(array($this, '_'.$method), $params);
+ }
+
+ throw new BadMethodCallException('Method '.$method.' was not found');
+ }
+
+} \ No newline at end of file
diff --git a/tests/mocks/core/uri.php b/tests/mocks/core/uri.php
new file mode 100644
index 000000000..94f75df64
--- /dev/null
+++ b/tests/mocks/core/uri.php
@@ -0,0 +1,26 @@
+<?php
+
+class Mock_Core_URI extends CI_URI {
+
+ public function __construct()
+ {
+ $test = CI_TestCase::instance();
+ $cls =& $test->ci_core_class('cfg');
+
+ // set predictable config values
+ $test->ci_set_config(array(
+ 'index_page' => 'index.php',
+ 'base_url' => 'http://example.com/',
+ 'subclass_prefix' => 'MY_'
+ ));
+
+ $this->config = new $cls;
+
+ }
+
+ protected function _is_cli_request()
+ {
+ return FALSE;
+ }
+
+} \ No newline at end of file
diff --git a/tests/mocks/core/utf8.php b/tests/mocks/core/utf8.php
new file mode 100644
index 000000000..068e74ac1
--- /dev/null
+++ b/tests/mocks/core/utf8.php
@@ -0,0 +1,26 @@
+<?php
+
+class Mock_Core_Utf8 extends CI_Utf8 {
+
+ /**
+ * We need to define several constants as
+ * the same process within CI_Utf8 class constructor.
+ *
+ * @covers CI_Utf8::__construct()
+ */
+ public function __construct()
+ {
+ defined('UTF8_ENABLED') OR define('UTF8_ENABLED', TRUE);
+
+ if (extension_loaded('mbstring'))
+ {
+ defined('MB_ENABLED') OR define('MB_ENABLED', TRUE);
+ mb_internal_encoding('UTF-8');
+ }
+ else
+ {
+ defined('MB_ENABLED') OR define('MB_ENABLED', FALSE);
+ }
+ }
+
+} \ No newline at end of file
diff --git a/tests/mocks/database/ci_test.sqlite b/tests/mocks/database/ci_test.sqlite
new file mode 100755
index 000000000..44dcef9ec
--- /dev/null
+++ b/tests/mocks/database/ci_test.sqlite
Binary files differ
diff --git a/tests/mocks/database/config/mysql.php b/tests/mocks/database/config/mysql.php
new file mode 100644
index 000000000..a590b9f53
--- /dev/null
+++ b/tests/mocks/database/config/mysql.php
@@ -0,0 +1,34 @@
+<?php
+
+return array(
+
+ // Typical Database configuration
+ 'mysql' => array(
+ 'dsn' => '',
+ 'hostname' => 'localhost',
+ 'username' => 'travis',
+ 'password' => '',
+ 'database' => 'ci_test',
+ 'dbdriver' => 'mysql'
+ ),
+
+ // Database configuration with failover
+ 'mysql_failover' => array(
+ 'dsn' => '',
+ 'hostname' => 'localhost',
+ 'username' => 'not_travis',
+ 'password' => 'wrong password',
+ 'database' => 'not_ci_test',
+ 'dbdriver' => 'mysql',
+ 'failover' => array(
+ array(
+ 'dsn' => '',
+ 'hostname' => 'localhost',
+ 'username' => 'travis',
+ 'password' => '',
+ 'database' => 'ci_test',
+ 'dbdriver' => 'mysql',
+ )
+ )
+ )
+); \ No newline at end of file
diff --git a/tests/mocks/database/config/pdo/mysql.php b/tests/mocks/database/config/pdo/mysql.php
new file mode 100644
index 000000000..96608f787
--- /dev/null
+++ b/tests/mocks/database/config/pdo/mysql.php
@@ -0,0 +1,37 @@
+<?php
+
+return array(
+
+ // Typical Database configuration
+ 'pdo/mysql' => array(
+ 'dsn' => 'mysql:host=localhost;dbname=ci_test',
+ 'hostname' => 'localhost',
+ 'username' => 'travis',
+ 'password' => '',
+ 'database' => 'ci_test',
+ 'dbdriver' => 'pdo',
+ 'subdriver' => 'mysql'
+ ),
+
+ // Database configuration with failover
+ 'pdo/mysql_failover' => array(
+ 'dsn' => '',
+ 'hostname' => 'localhost',
+ 'username' => 'not_travis',
+ 'password' => 'wrong password',
+ 'database' => 'not_ci_test',
+ 'dbdriver' => 'pdo',
+ 'subdriver' => 'mysql',
+ 'failover' => array(
+ array(
+ 'dsn' => 'mysql:host=localhost;dbname=ci_test',
+ 'hostname' => 'localhost',
+ 'username' => 'travis',
+ 'password' => '',
+ 'database' => 'ci_test',
+ 'dbdriver' => 'pdo',
+ 'subdriver' => 'mysql'
+ )
+ )
+ )
+); \ No newline at end of file
diff --git a/tests/mocks/database/config/pdo/pgsql.php b/tests/mocks/database/config/pdo/pgsql.php
new file mode 100644
index 000000000..e55e3ea77
--- /dev/null
+++ b/tests/mocks/database/config/pdo/pgsql.php
@@ -0,0 +1,37 @@
+<?php
+
+return array(
+
+ // Typical Database configuration
+ 'pdo/pgsql' => array(
+ 'dsn' => 'pgsql:host=localhost;port=5432;dbname=ci_test;',
+ 'hostname' => 'localhost',
+ 'username' => 'postgres',
+ 'password' => '',
+ 'database' => 'ci_test',
+ 'dbdriver' => 'pdo',
+ 'subdriver' => 'pgsql'
+ ),
+
+ // Database configuration with failover
+ 'pdo/pgsql_failover' => array(
+ 'dsn' => '',
+ 'hostname' => 'localhost',
+ 'username' => 'not_travis',
+ 'password' => 'wrong password',
+ 'database' => 'not_ci_test',
+ 'dbdriver' => 'pdo',
+ 'subdriver' => 'pgsql',
+ 'failover' => array(
+ array(
+ 'dsn' => 'pgsql:host=localhost;port=5432;dbname=ci_test;',
+ 'hostname' => 'localhost',
+ 'username' => 'postgres',
+ 'password' => '',
+ 'database' => 'ci_test',
+ 'dbdriver' => 'pdo',
+ 'subdriver' => 'pgsql'
+ )
+ )
+ )
+); \ No newline at end of file
diff --git a/tests/mocks/database/config/pdo/sqlite.php b/tests/mocks/database/config/pdo/sqlite.php
new file mode 100644
index 000000000..1bf56b3ac
--- /dev/null
+++ b/tests/mocks/database/config/pdo/sqlite.php
@@ -0,0 +1,37 @@
+<?php
+
+return array(
+
+ // Typical Database configuration
+ 'pdo/sqlite' => array(
+ 'dsn' => 'sqlite:/'.realpath(__DIR__.'/../..').'/ci_test.sqlite',
+ 'hostname' => 'localhost',
+ 'username' => 'sqlite',
+ 'password' => 'sqlite',
+ 'database' => 'sqlite',
+ 'dbdriver' => 'pdo',
+ 'subdriver' => 'sqlite'
+ ),
+
+ // Database configuration with failover
+ 'pdo/sqlite_failover' => array(
+ 'dsn' => 'sqlite:not_exists.sqlite',
+ 'hostname' => 'localhost',
+ 'username' => 'sqlite',
+ 'password' => 'sqlite',
+ 'database' => 'sqlite',
+ 'dbdriver' => 'pdo',
+ 'subdriver' => 'sqlite',
+ 'failover' => array(
+ array(
+ 'dsn' => 'sqlite:/'.realpath(__DIR__.'/../..').'/ci_test.sqlite',
+ 'hostname' => 'localhost',
+ 'username' => 'sqlite',
+ 'password' => 'sqlite',
+ 'database' => 'sqlite',
+ 'dbdriver' => 'pdo',
+ 'subdriver' => 'sqlite'
+ )
+ )
+ )
+); \ No newline at end of file
diff --git a/tests/mocks/database/config/pgsql.php b/tests/mocks/database/config/pgsql.php
new file mode 100644
index 000000000..1444b0066
--- /dev/null
+++ b/tests/mocks/database/config/pgsql.php
@@ -0,0 +1,34 @@
+<?php
+
+return array(
+
+ // Typical Database configuration
+ 'pgsql' => array(
+ 'dsn' => '',
+ 'hostname' => 'localhost',
+ 'username' => 'postgres',
+ 'password' => '',
+ 'database' => 'ci_test',
+ 'dbdriver' => 'postgre'
+ ),
+
+ // Database configuration with failover
+ 'pgsql_failover' => array(
+ 'dsn' => '',
+ 'hostname' => 'localhost',
+ 'username' => 'not_travis',
+ 'password' => 'wrong password',
+ 'database' => 'not_ci_test',
+ 'dbdriver' => 'postgre',
+ 'failover' => array(
+ array(
+ 'dsn' => '',
+ 'hostname' => 'localhost',
+ 'username' => 'postgres',
+ 'password' => '',
+ 'database' => 'ci_test',
+ 'dbdriver' => 'postgre',
+ )
+ )
+ )
+); \ No newline at end of file
diff --git a/tests/mocks/database/config/sqlite.php b/tests/mocks/database/config/sqlite.php
new file mode 100644
index 000000000..d37ee4871
--- /dev/null
+++ b/tests/mocks/database/config/sqlite.php
@@ -0,0 +1,34 @@
+<?php
+
+return array(
+
+ // Typical Database configuration
+ 'sqlite' => array(
+ 'dsn' => '',
+ 'hostname' => 'localhost',
+ 'username' => 'sqlite',
+ 'password' => 'sqlite',
+ 'database' => realpath(__DIR__.'/..').'/ci_test.sqlite',
+ 'dbdriver' => 'sqlite3'
+ ),
+
+ // Database configuration with failover
+ 'sqlite_failover' => array(
+ 'dsn' => '',
+ 'hostname' => 'localhost',
+ 'username' => 'sqlite',
+ 'password' => 'sqlite',
+ 'database' => '../not_exists.sqlite',
+ 'dbdriver' => 'sqlite3',
+ 'failover' => array(
+ array(
+ 'dsn' => '',
+ 'hostname' => 'localhost',
+ 'username' => 'sqlite',
+ 'password' => 'sqlite',
+ 'database' => realpath(__DIR__.'/..').'/ci_test.sqlite',
+ 'dbdriver' => 'sqlite3'
+ )
+ )
+ )
+); \ No newline at end of file
diff --git a/tests/mocks/database/db.php b/tests/mocks/database/db.php
new file mode 100644
index 000000000..75658530b
--- /dev/null
+++ b/tests/mocks/database/db.php
@@ -0,0 +1,100 @@
+<?php
+
+class Mock_Database_DB {
+
+ /**
+ * @var array DB configuration
+ */
+ private $config = array();
+
+ /**
+ * Prepare database configuration skeleton
+ *
+ * @param array DB configuration to set
+ * @return void
+ */
+ public function __construct($config = array())
+ {
+ $this->config = $config;
+ }
+
+ /**
+ * Build DSN connection string for DB driver instantiate process
+ *
+ * @param string Group name
+ * @return string DSN Connection string
+ */
+ public function set_dsn($group = 'default')
+ {
+ if ( ! isset($this->config[$group]))
+ {
+ throw new InvalidArgumentException('Group '.$group.' not exists');
+ }
+
+ $params = array(
+ 'dbprefix' => '',
+ 'pconnect' => FALSE,
+ 'db_debug' => FALSE,
+ 'cache_on' => FALSE,
+ 'cachedir' => '',
+ 'char_set' => 'utf8',
+ 'dbcollat' => 'utf8_general_ci',
+ 'swap_pre' => '',
+ 'autoinit' => TRUE,
+ 'stricton' => FALSE,
+ );
+
+ $config = array_merge($this->config[$group], $params);
+ $dsnstring = empty($config['dsn']) ? FALSE : $config['dsn'];
+ $subdriver = empty($config['subdriver']) ? FALSE: $config['subdriver'];
+ $failover = empty($config['failover']) ? FALSE : $config['failover'];
+
+ $dsn = $config['dbdriver'].'://'.$config['username'].':'.$config['password']
+ .'@'.$config['hostname'].'/'.$config['database'];
+
+ // Build the parameter
+ $other_params = array_slice($config, 6);
+ if ($dsnstring) $other_params['dsn'] = $dsnstring;
+ if ($subdriver) $other_params['subdriver'] = $subdriver;
+ if ($failover) $other_params['failover'] = $failover;
+
+ return $dsn.'?'.http_build_query($other_params);
+ }
+
+ /**
+ * Return a database config array
+ *
+ * @see ./config
+ * @param string Driver based configuration
+ * @return array
+ */
+ public static function config($driver)
+ {
+ $dir = realpath(dirname(__FILE__)).DIRECTORY_SEPARATOR;
+ return include($dir.'config'.DIRECTORY_SEPARATOR.$driver.'.php');
+ }
+
+ /**
+ * Main DB method wrapper
+ *
+ * @param string Group or DSN string
+ * @param bool
+ * @return object
+ */
+ public static function DB($group, $query_builder = FALSE)
+ {
+ include_once(BASEPATH.'database/DB.php');
+
+ try
+ {
+ $db = DB($group, $query_builder);
+ }
+ catch (Exception $e)
+ {
+ throw new InvalidArgumentException($e->getMessage());
+ }
+
+ return $db;
+ }
+
+} \ No newline at end of file
diff --git a/tests/mocks/database/db/driver.php b/tests/mocks/database/db/driver.php
new file mode 100644
index 000000000..65ac2c4cc
--- /dev/null
+++ b/tests/mocks/database/db/driver.php
@@ -0,0 +1,39 @@
+<?php
+
+class Mock_Database_DB_Driver extends CI_DB_driver {
+
+ /**
+ * @var object The actual Driver
+ */
+ protected $ci_db_driver;
+
+ /**
+ * Instantiate the database driver
+ *
+ * @param string DB Driver class name
+ * @param array DB configuration to set
+ * @return void
+ */
+ public function __construct($driver_class, $config = array())
+ {
+ if (is_string($driver_class))
+ {
+ $this->ci_db_driver = new $driver_class($config);
+ }
+ }
+
+ /**
+ * Overloading method, emulate the actual driver method (multiple inheritance workaround)
+ */
+ public function __call($method, $arguments)
+ {
+ if ( ! is_callable(array($this->ci_db_driver, $method)))
+ {
+ throw new BadMethodCallException($method. ' not exists or not implemented');
+ }
+
+ return call_user_func_array(array($this->ci_db_driver, $method), $arguments);
+ }
+}
+
+class CI_DB extends Mock_Database_DB_QueryBuilder {} \ No newline at end of file
diff --git a/tests/mocks/database/db/querybuilder.php b/tests/mocks/database/db/querybuilder.php
new file mode 100644
index 000000000..3f2252622
--- /dev/null
+++ b/tests/mocks/database/db/querybuilder.php
@@ -0,0 +1,3 @@
+<?php
+
+class Mock_Database_DB_QueryBuilder extends CI_DB_query_builder {} \ No newline at end of file
diff --git a/tests/mocks/database/drivers/mysql.php b/tests/mocks/database/drivers/mysql.php
new file mode 100644
index 000000000..e0c1fb06c
--- /dev/null
+++ b/tests/mocks/database/drivers/mysql.php
@@ -0,0 +1,17 @@
+<?php
+
+class Mock_Database_Drivers_Mysql extends Mock_Database_DB_Driver {
+
+ /**
+ * Instantiate the database driver
+ *
+ * @param string DB Driver class name
+ * @param array DB configuration to set
+ * @return void
+ */
+ public function __construct($config = array())
+ {
+ parent::__construct('CI_DB_mysql_driver', $config);
+ }
+
+} \ No newline at end of file
diff --git a/tests/mocks/database/drivers/pdo.php b/tests/mocks/database/drivers/pdo.php
new file mode 100644
index 000000000..17768eed7
--- /dev/null
+++ b/tests/mocks/database/drivers/pdo.php
@@ -0,0 +1,16 @@
+<?php
+
+class Mock_Database_Drivers_PDO extends Mock_Database_DB_Driver {
+
+ /**
+ * Instantiate the database driver
+ *
+ * @param string DB Driver class name
+ * @param array DB configuration to set
+ * @return void
+ */
+ public function __construct($config = array())
+ {
+ parent::__construct('CI_DB_pdo_driver', $config);
+ }
+} \ No newline at end of file
diff --git a/tests/mocks/database/drivers/postgre.php b/tests/mocks/database/drivers/postgre.php
new file mode 100644
index 000000000..5a45115fa
--- /dev/null
+++ b/tests/mocks/database/drivers/postgre.php
@@ -0,0 +1,17 @@
+<?php
+
+class Mock_Database_Drivers_Postgre extends Mock_Database_DB_Driver {
+
+ /**
+ * Instantiate the database driver
+ *
+ * @param string DB Driver class name
+ * @param array DB configuration to set
+ * @return void
+ */
+ public function __construct($config = array())
+ {
+ parent::__construct('CI_DB_postgre_driver', $config);
+ }
+
+} \ No newline at end of file
diff --git a/tests/mocks/database/drivers/sqlite.php b/tests/mocks/database/drivers/sqlite.php
new file mode 100644
index 000000000..512467520
--- /dev/null
+++ b/tests/mocks/database/drivers/sqlite.php
@@ -0,0 +1,17 @@
+<?php
+
+class Mock_Database_Drivers_Sqlite extends Mock_Database_DB_Driver {
+
+ /**
+ * Instantiate the database driver
+ *
+ * @param string DB Driver class name
+ * @param array DB configuration to set
+ * @return void
+ */
+ public function __construct($config = array())
+ {
+ parent::__construct('CI_DB_sqlite3_driver', $config);
+ }
+
+} \ No newline at end of file
diff --git a/tests/mocks/database/schema/skeleton.php b/tests/mocks/database/schema/skeleton.php
new file mode 100644
index 000000000..18e1ddd4d
--- /dev/null
+++ b/tests/mocks/database/schema/skeleton.php
@@ -0,0 +1,147 @@
+<?php
+
+class Mock_Database_Schema_Skeleton {
+
+ /**
+ * @var object Database Holder
+ */
+ public static $db;
+
+ /**
+ * @var object Forge Holder
+ */
+ public static $forge;
+
+ /**
+ * @var object Driver Holder
+ */
+ public static $driver;
+
+ /**
+ * Initialize both database and forge components
+ */
+ public static function init($driver)
+ {
+ if (empty(static::$db) && empty(static::$forge))
+ {
+ $config = Mock_Database_DB::config($driver);
+ $connection = new Mock_Database_DB($config);
+ $db = Mock_Database_DB::DB($connection->set_dsn($driver), TRUE);
+
+ CI_TestCase::instance()->ci_instance_var('db', $db);
+
+ $loader = new Mock_Core_Loader();
+ $loader->dbforge();
+ $forge = CI_TestCase::instance()->ci_instance_var('dbforge');
+
+ static::$db = $db;
+ static::$forge = $forge;
+ static::$driver = $driver;
+ }
+
+ return static::$db;
+ }
+
+ /**
+ * Create the dummy tables
+ *
+ * @return void
+ */
+ public static function create_tables()
+ {
+ // User Table
+ static::$forge->add_field(array(
+ 'id' => array(
+ 'type' => 'INTEGER',
+ 'constraint' => 3
+ ),
+ 'name' => array(
+ 'type' => 'VARCHAR',
+ 'constraint' => 40
+ ),
+ 'email' => array(
+ 'type' => 'VARCHAR',
+ 'constraint' => 100
+ ),
+ 'country' => array(
+ 'type' => 'VARCHAR',
+ 'constraint' => 40
+ )
+ ));
+ static::$forge->add_key('id', TRUE);
+ static::$forge->create_table('user', (strpos(static::$driver, 'pgsql') === FALSE));
+
+ // Job Table
+ static::$forge->add_field(array(
+ 'id' => array(
+ 'type' => 'INTEGER',
+ 'constraint' => 3
+ ),
+ 'name' => array(
+ 'type' => 'VARCHAR',
+ 'constraint' => 40
+ ),
+ 'description' => array(
+ 'type' => 'TEXT'
+ )
+ ));
+ static::$forge->add_key('id', TRUE);
+ static::$forge->create_table('job', (strpos(static::$driver, 'pgsql') === FALSE));
+
+ // Misc Table
+ static::$forge->add_field(array(
+ 'id' => array(
+ 'type' => 'INTEGER',
+ 'constraint' => 3
+ ),
+ 'key' => array(
+ 'type' => 'VARCHAR',
+ 'constraint' => 40
+ ),
+ 'value' => array(
+ 'type' => 'TEXT'
+ )
+ ));
+ static::$forge->add_key('id', TRUE);
+ static::$forge->create_table('misc', (strpos(static::$driver, 'pgsql') === FALSE));
+ }
+
+ /**
+ * Create the dummy datas
+ *
+ * @return void
+ */
+ public static function create_data()
+ {
+ // Job Data
+ $data = array(
+ 'user' => array(
+ array('id' => 1, 'name' => 'Derek Jones', 'email' => 'derek@world.com', 'country' => 'US'),
+ array('id' => 2, 'name' => 'Ahmadinejad', 'email' => 'ahmadinejad@world.com', 'country' => 'Iran'),
+ array('id' => 3, 'name' => 'Richard A Causey', 'email' => 'richard@world.com', 'country' => 'US'),
+ array('id' => 4, 'name' => 'Chris Martin', 'email' => 'chris@world.com', 'country' => 'UK')
+ ),
+ 'job' => array(
+ array('id' => 1, 'name' => 'Developer', 'description' => 'Awesome job, but sometimes makes you bored'),
+ array('id' => 2, 'name' => 'Politician', 'description' => 'This is not really a job'),
+ array('id' => 3, 'name' => 'Accountant', 'description' => 'Boring job, but you will get free snack at lunch'),
+ array('id' => 4, 'name' => 'Musician', 'description' => 'Only Coldplay can actually called Musician')
+ ),
+ 'misc' => array(
+ array('id' => 1, 'key' => '\\xxxfoo456', 'value' => 'Entry with \\xxx'),
+ array('id' => 2, 'key' => '\\%foo456', 'value' => 'Entry with \\%')
+ )
+ );
+
+ foreach ($data as $table => $dummy_data)
+ {
+ static::$db->truncate($table);
+
+ foreach ($dummy_data as $single_dummy_data)
+ {
+ static::$db->insert($table, $single_dummy_data);
+ }
+ }
+ }
+
+} \ No newline at end of file
diff --git a/tests/mocks/libraries/encrypt.php b/tests/mocks/libraries/encrypt.php
new file mode 100644
index 000000000..f1859398f
--- /dev/null
+++ b/tests/mocks/libraries/encrypt.php
@@ -0,0 +1,16 @@
+<?php
+
+class Mock_Libraries_Encrypt extends CI_Encrypt {
+
+ // Overide inaccesible protected method
+ public function __call($method, $params)
+ {
+ if (is_callable(array($this, '_'.$method)))
+ {
+ return call_user_func_array(array($this, '_'.$method), $params);
+ }
+
+ throw new BadMethodCallException('Method '.$method.' was not found');
+ }
+
+} \ No newline at end of file
diff --git a/tests/mocks/libraries/parser.php b/tests/mocks/libraries/parser.php
new file mode 100644
index 000000000..81dcfb37e
--- /dev/null
+++ b/tests/mocks/libraries/parser.php
@@ -0,0 +1,3 @@
+<?php
+
+class Mock_Libraries_Parser extends CI_Parser {} \ No newline at end of file
diff --git a/tests/mocks/libraries/table.php b/tests/mocks/libraries/table.php
new file mode 100644
index 000000000..87c278bce
--- /dev/null
+++ b/tests/mocks/libraries/table.php
@@ -0,0 +1,16 @@
+<?php
+
+class Mock_Libraries_Table extends CI_Table {
+
+ // Overide inaccesible protected method
+ public function __call($method, $params)
+ {
+ if (is_callable(array($this, '_'.$method)))
+ {
+ return call_user_func_array(array($this, '_'.$method), $params);
+ }
+
+ throw new BadMethodCallException('Method '.$method.' was not found');
+ }
+
+} \ No newline at end of file
diff --git a/tests/mocks/libraries/typography.php b/tests/mocks/libraries/typography.php
new file mode 100644
index 000000000..0f76c5745
--- /dev/null
+++ b/tests/mocks/libraries/typography.php
@@ -0,0 +1,3 @@
+<?php
+
+class Mock_Libraries_Typography extends CI_Typography {} \ No newline at end of file
diff --git a/tests/mocks/libraries/useragent.php b/tests/mocks/libraries/useragent.php
new file mode 100644
index 000000000..c957cde5b
--- /dev/null
+++ b/tests/mocks/libraries/useragent.php
@@ -0,0 +1,3 @@
+<?php
+
+class Mock_Libraries_UserAgent extends CI_User_agent {} \ No newline at end of file