<?php  if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
 * CodeIgniter
 *
 * An open source application development framework for PHP 4.3.2 or newer
 *
 * @package		CodeIgniter
 * @author		ExpressionEngine Dev Team
 * @copyright	Copyright (c) 2006, EllisLab, Inc.
 * @license		http://codeigniter.com/user_guide/license.html
 * @link		http://codeigniter.com
 * @since		Version 1.3.1
 * @filesource
 */

// ------------------------------------------------------------------------

/**
 * Unit Testing Class
 *
 * Simple testing class
 *
 * @package		CodeIgniter
 * @subpackage	Libraries
 * @category	UnitTesting
 * @author		ExpressionEngine Dev Team
 * @link		http://codeigniter.com/user_guide/libraries/uri.html
 */
class CI_Unit_test {

	var $active			= TRUE;
	var $results 		= array();
	var $strict			= FALSE;
	var $_template 		= NULL;
	var $_template_rows	= NULL;

	function CI_Unit_test()
	{
		log_message('debug', "Unit Testing Class Initialized");
	}	

	// --------------------------------------------------------------------
	
	/**
	 * Run the tests
	 *
	 * Runs the supplied tests
	 *
	 * @access	public
	 * @param	mixed
	 * @param	mixed
	 * @param	string
	 * @return	string
	 */	
	function run($test, $expected = TRUE, $test_name = 'undefined')
	{
		if ($this->active == FALSE)
		{
			return FALSE;
		}
	
		if (in_array($expected, array('is_string', 'is_bool', 'is_true', 'is_false', 'is_int', 'is_numeric', 'is_float', 'is_double', 'is_array', 'is_null'), TRUE))
		{
			$expected = str_replace('is_float', 'is_double', $expected);
			$result = ($expected($test)) ? TRUE : FALSE;	
			$extype = str_replace(array('true', 'false'), 'bool', str_replace('is_', '', $expected));
		}
		else
		{
			if ($this->strict == TRUE)
				$result = ($test === $expected) ? TRUE : FALSE;	
			else
				$result = ($test == $expected) ? TRUE : FALSE;	
			
			$extype = gettype($expected);
		}
				
		$back = $this->_backtrace();
	
		$report[] = array (
							'test_name'			=> $test_name,
							'test_datatype'		=> gettype($test),
							'res_datatype'		=> $extype,
							'result'			=> ($result === TRUE) ? 'passed' : 'failed',
							'file'				=> $back['file'],
							'line'				=> $back['line']
						);

		$this->results[] = $report;		
				
		return($this->report($this->result($report)));
	}

	// --------------------------------------------------------------------
	
	/**
	 * Generate a report
	 *
	 * Displays a table with the test data
	 *
	 * @access	public
	 * @return	string
	 */
	function report($result = array())
	{
		if (count($result) == 0)
		{
			$result = $this->result();
		}

		$CI =& get_instance();
		$CI->load->language('unit_test');

		$this->_parse_template();

		$r = '';
		foreach ($result as $res)
		{
			$table = '';

			foreach ($res as $key => $val)
			{

				if ($key == $CI->lang->line('ut_result'))
				{
					if ($val == $CI->lang->line('ut_passed'))
					{
						$val = '<span style="color: #0C0;">'.$val.'</span>';
					}
					elseif ($val == $CI->lang->line('ut_failed'))
					{
						$val = '<span style="color: #C00;">'.$val.'</span>';
					}
				}

				$temp = $this->_template_rows;
				$temp = str_replace('{item}', $key, $temp);
				$temp = str_replace('{result}', $val, $temp);
				$table .= $temp;
			}

			$r .= str_replace('{rows}', $table, $this->_template);
		}

		return $r;
	}
	
	// --------------------------------------------------------------------
	
	/**
	 * Use strict comparison
	 *
	 * Causes the evaluation to use === rather then ==
	 *
	 * @access	public
	 * @param	bool
	 * @return	null
	 */
	function use_strict($state = TRUE)
	{
		$this->strict = ($state == FALSE) ? FALSE : TRUE;
	}
	
	// --------------------------------------------------------------------
	
	/**
	 * Make Unit testing active
	 *
	 * Enables/disables unit testing
	 *
	 * @access	public
	 * @param	bool
	 * @return	null
	 */
	function active($state = TRUE)
	{
		$this->active = ($state == FALSE) ? FALSE : TRUE;
	}
	
	// --------------------------------------------------------------------
	
	/**
	 * Result Array
	 *
	 * Returns the raw result data
	 *
	 * @access	public
	 * @return	array
	 */
	function result($results = array())
	{	
		$CI =& get_instance();
		$CI->load->language('unit_test');
		
		if (count($results) == 0)
		{
			$results = $this->results;
		}
		
		$retval = array();
		foreach ($results as $result)
		{
			$temp = array();
			foreach ($result as $key => $val)
			{
				if (is_array($val))
				{
					foreach ($val as $k => $v)
					{
						if (FALSE !== ($line = $CI->lang->line(strtolower('ut_'.$v))))
						{
							$v = $line;
						}				
						$temp[$CI->lang->line('ut_'.$k)] = $v;					
					}
				}
				else
				{
					if (FALSE !== ($line = $CI->lang->line(strtolower('ut_'.$val))))
					{
						$val = $line;
					}				
					$temp[$CI->lang->line('ut_'.$key)] = $val;
				}
			}
			
			$retval[] = $temp;
		}
	
		return $retval;
	}
	
	// --------------------------------------------------------------------
	
	/**
	 * Set the template
	 *
	 * This lets us set the template to be used to display results
	 *
	 * @access	public
	 * @param	string
	 * @return	void
	 */	
	function set_template($template)
	{
		$this->_template = $template;
	}
	
	// --------------------------------------------------------------------
	
	/**
	 * Generate a backtrace
	 *
	 * This lets us show file names and line numbers
	 *
	 * @access	private
	 * @return	array
	 */
	function _backtrace()
	{
		if (function_exists('debug_backtrace'))
		{
			$back = debug_backtrace();
			
			$file = (! isset($back['1']['file'])) ? '' : $back['1']['file'];
			$line = (! isset($back['1']['line'])) ? '' : $back['1']['line'];
						
			return array('file' => $file, 'line' => $line);
		}
		return array('file' => 'Unknown', 'line' => 'Unknown');
	}

	// --------------------------------------------------------------------
	
	/**
	 * Get Default Template
	 *
	 * @access	private
	 * @return	string
	 */
	function _default_template()
	{	
		$this->_template = "\n".'<table style="width:100%; font-size:small; margin:10px 0; border-collapse:collapse; border:1px solid #CCC;">';
		$this->_template .= '{rows}';
		$this->_template .= "\n".'</table>';
		
		$this->_template_rows = "\n\t".'<tr>';
		$this->_template_rows .= "\n\t\t".'<th style="text-align: left; border-bottom:1px solid #CCC;">{item}</th>';
		$this->_template_rows .= "\n\t\t".'<td style="border-bottom:1px solid #CCC;">{result}</td>';
		$this->_template_rows .= "\n\t".'</tr>';	
	}
	
	// --------------------------------------------------------------------

	/**
	 * Parse Template
	 *
	 * Harvests the data within the template {pseudo-variables}
	 *
	 * @access	private
	 * @return	void
	 */
 	function _parse_template()
 	{
 		if (! is_null($this->_template_rows))
 		{
 			return;
 		}
 		
 		if (is_null($this->_template))
 		{
 			$this->_default_template();
 			return;
 		}
 		
		if (! preg_match("/\{rows\}(.*?)\{\/rows\}/si", $this->_template, $match))
		{
 			$this->_default_template();
 			return;
		}

		$this->_template_rows = $match['1'];
		$this->_template = str_replace($match['0'], '{rows}', $this->_template); 	
 	}
 	
}
// END Unit_test Class

/**
 * Helper functions to test boolean true/false
 *
 *
 * @access	private
 * @return	bool
 */
function is_true($test)
{
	return (is_bool($test) AND $test === TRUE) ? TRUE : FALSE;
}
function is_false($test)
{
	return (is_bool($test) AND $test === FALSE) ? TRUE : FALSE;
}


/* End of file Unit_test.php */
/* Location: ./system/libraries/Unit_test.php */