From c6b98d3891ed795a1d8e080b90c840d05e666640 Mon Sep 17 00:00:00 2001 From: SVN Migration Date: Fri, 19 Mar 2004 00:48:40 +0000 Subject: [PATCH] This commit was manufactured by cvs2svn to create branch 'PHP_4_3'. --- ext/standard/tests/serialize/bug27469.phpt | 27 + pear/PEAR/ErrorStack.php | 889 ++++++++++++++++++ .../Error_Stack_TestCase_getErrorMessage.php | 142 +++ ...Stack_TestCase_getErrorMessageTemplate.php | 88 ++ .../Error_Stack_TestCase_getErrors.php | 135 +++ .../Error_Stack_TestCase_pushpop.php | 367 ++++++++ .../Error_Stack_TestCase_pushpopcallback.php | 320 +++++++ .../Error_Stack_TestCase_pushpopstatic.php | 327 +++++++ .../Error_Stack_TestCase_singleton.php | 93 ++ .../Error_Stack_TestCase_staticGetErrors.php | 225 +++++ .../PEAR_ErrorStack/HTML_TestListener.php | 64 ++ pear/tests/PEAR_ErrorStack/TestUnit.php | 55 ++ .../tests/PEAR_ErrorStack/base_regression.php | 550 +++++++++++ pear/tests/PEAR_ErrorStack/stylesheet.css | 65 ++ pear/tests/PEAR_ErrorStack/testsuite.php | 152 +++ 15 files changed, 3499 insertions(+) create mode 100644 ext/standard/tests/serialize/bug27469.phpt create mode 100644 pear/PEAR/ErrorStack.php create mode 100644 pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_getErrorMessage.php create mode 100644 pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_getErrorMessageTemplate.php create mode 100644 pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_getErrors.php create mode 100644 pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_pushpop.php create mode 100644 pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_pushpopcallback.php create mode 100644 pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_pushpopstatic.php create mode 100644 pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_singleton.php create mode 100644 pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_staticGetErrors.php create mode 100644 pear/tests/PEAR_ErrorStack/HTML_TestListener.php create mode 100644 pear/tests/PEAR_ErrorStack/TestUnit.php create mode 100644 pear/tests/PEAR_ErrorStack/base_regression.php create mode 100644 pear/tests/PEAR_ErrorStack/stylesheet.css create mode 100644 pear/tests/PEAR_ErrorStack/testsuite.php diff --git a/ext/standard/tests/serialize/bug27469.phpt b/ext/standard/tests/serialize/bug27469.phpt new file mode 100644 index 0000000000..e8d14106a8 --- /dev/null +++ b/ext/standard/tests/serialize/bug27469.phpt @@ -0,0 +1,27 @@ +--TEST-- +Bug #27469 (serialize() objects of incomplete class) +--FILE-- + +--EXPECT-- +object(__PHP_Incomplete_Class)#1 (1) { + ["__PHP_Incomplete_Class_Name"]=> + string(9) "TestClass" +} +O:9:"TestClass":0:{} +object(__PHP_Incomplete_Class)#1 (1) { + ["__PHP_Incomplete_Class_Name"]=> + string(9) "TestClass" +} +O:9:"TestClass":0:{} +object(__PHP_Incomplete_Class)#1 (1) { + ["__PHP_Incomplete_Class_Name"]=> + string(9) "TestClass" +} diff --git a/pear/PEAR/ErrorStack.php b/pear/PEAR/ErrorStack.php new file mode 100644 index 0000000000..0f8e6a11ec --- /dev/null +++ b/pear/PEAR/ErrorStack.php @@ -0,0 +1,889 @@ + | +// | | +// +----------------------------------------------------------------------+ +// +// $Id$ + +/** + * Error Stack Implementation + * + * This is an incredibly simple implementation of a very complex error handling + * facility. It contains the ability + * to track multiple errors from multiple packages simultaneously. In addition, + * it can track errors of many levels, save data along with the error, context + * information such as the exact file, line number, class and function that + * generated the error, and if necessary, it can raise a traditional PEAR_Error. + * It has built-in support for PEAR::Log, to log errors as they occur + * + * Since version 0.2alpha, it is also possible to selectively ignore errors, + * through the use of an error callback, see {@link pushCallback()} + * + * Since version 0.3alpha, it is possible to specify the exception class + * returned from {@link push()} + * @author Greg Beaver + * @version 0.6alpha + * @package PEAR_ErrorStack + * @category Debugging + * @license http://www.php.net/license/3_0.txt PHP License v3.0 + */ + +/** + * Singleton storage + * + * Format: + *
+ * array(
+ *  'package1' => PEAR_ErrorStack object,
+ *  'package2' => PEAR_ErrorStack object,
+ *  ...
+ * )
+ * 
+ * @access private + * @global array $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] + */ +$GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] = array(); + +/** + * Global error callback (default) + * + * This is only used + * @see PEAR_ErrorStack::setDefaultCallback() + * @access private + * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'] + */ +$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'] = false; + +/** + * Global Log object (default) + * + * This is only used + * @see PEAR_ErrorStack::setDefaultLogger() + * @access private + * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] + */ +$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = false; + +/**#@+ + * One of four possible return values from the error Callback + * @see PEAR_ErrorStack::_errorCallback() + */ +/** + * If this is returned, then the error will be both pushed onto the stack + * and logged. + */ +define('PEAR_ERRORSTACK_PUSHANDLOG', 1); +/** + * If this is returned, then the error will only be pushed onto the stack, + * and not logged. + */ +define("PEAR_ERRORSTACK_PUSH", 2); +/** + * If this is returned, then the error will only be logged, but not pushed + * onto the error stack. + */ +define("PEAR_ERRORSTACK_LOG", 3); +/** + * If this is returned, then the error is completely ignored. + */ +define("PEAR_ERRORSTACK_IGNORE", 4); +/**#@-*/ + +/** + * Error code for an attempt to instantiate a non-class as a PEAR_ErrorStack in + * the singleton method. + */ +define("PEAR_ERRORSTACK_ERR_NONCLASS", 1); + +/** + * Error code for an attempt to pass an object into {@link PEAR_ErrorStack::getMessage()} + * that has no __toString() method + */ +define('PEAR_ERRORSTACK_ERR_OBJTOSTRING', 2); +/** + * Error Stack Implementation + * + * Usage: + * + * // global error stack + * $global_stack = &PEAR_ErrorStack::singleton('MyPackage'); + * // local error stack + * $local_stack = new PEAR_ErrorStack('MyPackage'); + * + * @copyright 2004 Gregory Beaver + * @package PEAR_ErrorStack + * @license http://www.php.net/license/3_0.txt PHP License + */ +class PEAR_ErrorStack { + /** + * Errors are stored in the order that they are pushed on the stack. + * @since 0.4alpha Errors are no longer organized by error level. + * This renders pop() nearly unusable, and levels could be more easily + * handled in a callback anyway + * @var array + * @access private + */ + var $_errors = array(); + + /** + * Package name this error stack represents + * @var string + * @access protected + */ + var $_package; + + /** + * Determines whether a PEAR_Error is thrown upon every error addition + * @var boolean + * @access private + */ + var $_compat = false; + + /** + * If set to a valid callback, this will be used to generate the error + * message from the error code, otherwise the message passed in will be + * used + * @var false|string|array + * @access private + */ + var $_msgCallback = false; + + /** + * If set to a valid callback, this will be used to generate the error + * context for an error. For PHP-related errors, this will be a file + * and line number as retrieved from debug_backtrace(), but can be + * customized for other purposes. The error might actually be in a separate + * configuration file, or in a database query. + * @var false|string|array + * @access protected + */ + var $_contextCallback = false; + + /** + * If set to a valid callback, this will be called every time an error + * is pushed onto the stack. The return value will be used to determine + * whether to allow an error to be pushed or logged. + * + * The return value must be one an PEAR_ERRORSTACK_* constant + * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG + * @var false|string|array + * @access protected + */ + var $_errorCallback = array(); + + /** + * PEAR::Log object for logging errors + * @var false|Log + * @access protected + */ + var $_logger = false; + + /** + * Class name to use for a PHP 5 exception that will be returned + * @var string + * @access protected + */ + var $_exceptionClass = 'Exception'; + + /** + * Error messages - designed to be overridden + * @var array + * @abstract + */ + var $_errorMsgs = array(); + + /** + * Set up a new error stack + * + * @param string $package name of the package this error stack represents + * @param callback $msgCallback callback used for error message generation + * @param callback $contextCallback callback used for context generation, + * defaults to {@link getFileLine()} + * @param boolean $throwPEAR_Error + * @param string $exceptionClass exception class to instantiate if + * in PHP 5 + */ + function PEAR_ErrorStack($package, $msgCallback = false, $contextCallback = false, + $throwPEAR_Error = false, $exceptionClass = 'Exception') + { + $this->_package = $package; + $this->setMessageCallback($msgCallback); + $this->setContextCallback($contextCallback); + $this->_compat = $throwPEAR_Error; + $this->_exceptionClass = $exceptionClass; + } + + /** + * Return a single error stack for this package. + * + * Note that all parameters are ignored if the stack for package $package + * has already been instantiated + * @param string $package name of the package this error stack represents + * @param callback $msgCallback callback used for error message generation + * @param callback $contextCallback callback used for context generation, + * defaults to {@link getFileLine()} + * @param boolean $throwPEAR_Error + * @param string $exceptionClass exception class to instantiate if + * in PHP 5 + * @param string $stackClass class to instantiate + * @static + * @return PEAR_ErrorStack + */ + function &singleton($package, $msgCallback = false, $contextCallback = false, + $throwPEAR_Error = false, $exceptionClass = 'Exception', + $stackClass = 'PEAR_ErrorStack') + { + if (isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) { + return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]; + } + if (!class_exists($stackClass)) { + $trace = debug_backtrace(); + PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_NONCLASS, + 'exception', array('stackclass' => $stackClass), + 'stack class "%stackclass%" is not a valid class name (should be like PEAR_ErrorStack)', + false, $trace); + } + return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package] = + &new $stackClass($package, $msgCallback, $contextCallback, $throwPEAR_Error, + $exceptionClass); + } + + /** + * Internal error handler for PEAR_ErrorStack class + * + * Dies if the error is an exception (and would have died anyway) + * @access private + */ + function _handleError($err) + { + if ($err['level'] == 'exception') { + $message = $err['message']; + if (isset($_SERVER['REQUEST_URI'])) { + echo '
'; + } else { + echo "\n"; + } + var_dump($err['context']); + die($message); + } + } + + /** + * Set up a PEAR::Log object for all error stacks that don't have one + * @param Log $log + * @static + */ + function setDefaultLogger(&$log) + { + $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log; + } + + /** + * Set up a PEAR::Log object for this error stack + * @param Log $log + */ + function setLogger(&$log) + { + $this->_logger = &$log; + } + + /** + * Set an error code => error message mapping callback + * + * This method sets the callback that can be used to generate error + * messages for any instance + * @param string $package Package Name + * @param array|string Callback function/method + */ + function setMessageCallback($msgCallback) + { + if (!$msgCallback) { + $this->_msgCallback = array(&$this, 'getErrorMessage'); + } else { + if (is_callable($msgCallback)) { + $this->_msgCallback = $msgCallback; + } + } + } + + /** + * Get an error code => error message mapping callback + * + * This method returns the current callback that can be used to generate error + * messages + * @return array|string|false Callback function/method or false if none + */ + function getMessageCallback() + { + return $this->_msgCallback; + } + + /** + * Sets a default callback to be used by all error stacks + * + * This method sets the callback that can be used to generate error + * messages for a singleton + * @param array|string Callback function/method + * @static + */ + function setDefaultCallback($callback = false) + { + if (!is_callable($callback)) { + $callback = false; + } + $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'] = $callback; + } + + /** + * Set an error code => error message mapping callback + * + * This method sets the callback that can be used to generate error + * messages for any PEAR_ErrorStack instance + * @param string $package Package Name + * @param array|string Callback function/method + */ + function setContextCallback($contextCallback) + { + if (!$contextCallback) { + $this->_contextCallback = array(&$this, 'getFileLine'); + } else { + if (is_callable($contextCallback)) { + $this->_contextCallback = $contextCallback; + } + } + } + + /** + * Set an error Callback + * If set to a valid callback, this will be called every time an error + * is pushed onto the stack. The return value will be used to determine + * whether to allow an error to be pushed or logged. + * + * The return value must be one of the ERRORSTACK_* constants. + * + * This functionality can be used to emulate PEAR's pushErrorHandling, and + * the PEAR_ERROR_CALLBACK mode, without affecting the integrity of + * the error stack or logging + * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG + * @see popCallback() + * @param string|array $cb + */ + function pushCallback($cb) + { + array_push($this->_errorCallback, $cb); + } + + /** + * Remove a callback from the error callback stack + * @see pushCallback() + * @return array|string|false + */ + function popCallback() + { + if (!count($this->_errorCallback)) { + return false; + } + return array_pop($this->_errorCallback); + } + + /** + * Set an error Callback for every package error stack + * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG + * @see staticPopCallback(), pushCallback() + * @param string|array $cb + * @static + */ + function staticPushCallback($cb) + { + foreach($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $unused) { + $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->pushCallback($cb); + } + } + + /** + * Remove a callback from every error callback stack + * @see staticPushCallback() + * @return array|string|false + */ + function staticPopCallback() + { + foreach($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $unused) { + $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->popCallback(); + } + } + + /** + * Add an error to the stack + * + * If the message generator exists, it is called with 2 parameters. + * - the current Error Stack object + * - an array that is in the same format as an error. Available indices + * are 'code', 'package', 'time', 'params', 'level', and 'context' + * + * Next, if the error should contain context information, this is + * handled by the context grabbing method. + * Finally, the error is pushed onto the proper error stack + * @param int $code Package-specific error code + * @param string $level Error level. This is NOT spell-checked + * @param array $params associative array of error parameters + * @param string $msg Error message, or a portion of it if the message + * is to be generated + * @param array $repackage If this error re-packages an error pushed by + * another package, place the array returned from + * {@link pop()} in this parameter + * @param array $backtrace Protected parameter: use this to pass in the + * {@link debug_backtrace()} that should be used + * to find error context + * @return PEAR_Error|array|Exception + * if compatibility mode is on, a PEAR_Error is also + * thrown. If the class Exception exists, then one + * is returned to allow code like: + * + * throw ($stack->push(MY_ERROR_CODE, 'error', array('username' => 'grob'))); + * + * + * The errorData property of the exception class will be set to the array + * that would normally be returned. If a PEAR_Error is returned, the userinfo + * property is set to the array + * + * Otherwise, an array is returned in this format: + * + * array( + * 'code' => $code, + * 'params' => $params, + * 'package' => $this->_package, + * 'level' => $level, + * 'time' => time(), + * 'context' => $context, + * 'message' => $msg, + * //['repackage' => $err] repackaged error array + * ); + * + */ + function push($code, $level = 'error', $params = array(), $msg = false, + $repackage = false, $backtrace = false) + { + $context = false; + // grab error context + if ($this->_contextCallback) { + if (!$backtrace) { + $backtrace = debug_backtrace(); + } + $context = call_user_func($this->_contextCallback, $code, $params, $backtrace); + } + + // save error + $time = explode(' ', microtime()); + $time = $time[1] + $time[0]; + $err = array( + 'code' => $code, + 'params' => $params, + 'package' => $this->_package, + 'level' => $level, + 'time' => $time, + 'context' => $context, + 'message' => $msg, + ); + + // set up the error message, if necessary + if ($this->_msgCallback) { + $msg = call_user_func_array($this->_msgCallback, + array(&$this, $err)); + $err['message'] = $msg; + } + + + if ($repackage) { + $err['repackage'] = $repackage; + } + $push = $log = true; + $callback = $this->popCallback(); + if (is_callable($callback)) { + $this->pushCallback($callback); + switch(call_user_func($callback, $err)){ + case PEAR_ERRORSTACK_IGNORE: + return $err; + break; + case PEAR_ERRORSTACK_PUSH: + $log = false; + break; + case PEAR_ERRORSTACK_LOG: + $push = false; + break; + // anything else returned has the same effect as pushandlog + } + } elseif (is_callable($GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'])) { + switch(call_user_func($GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'], $err)){ + case PEAR_ERRORSTACK_IGNORE: + return $err; + break; + case PEAR_ERRORSTACK_PUSH: + $log = false; + break; + case PEAR_ERRORSTACK_LOG: + $push = false; + break; + // anything else returned has the same effect as pushandlog + } + } + if ($push) { + array_unshift($this->_errors, $err); + } + if ($log) { + if ($this->_logger || $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']) { + $this->_log($err); + } + } + if ($this->_compat && $push) { + return $this->raiseError($msg, $code, null, null, $err); + } + if (class_exists($this->_exceptionClass)) { + $exception = $this->_exceptionClass; + $ret = new $exception($msg, $code); + $ret->errorData = $err; + } + return $err; + } + + /** + * Static version of {@link push()} + * + * @param string $package Package name this error belongs to + * @param int $code Package-specific error code + * @param string $level Error level. This is NOT spell-checked + * @param array $params associative array of error parameters + * @param string $msg Error message, or a portion of it if the message + * is to be generated + * @param array $repackage If this error re-packages an error pushed by + * another package, place the array returned from + * {@link pop()} in this parameter + * @param array $backtrace Protected parameter: use this to pass in the + * {@link debug_backtrace()} that should be used + * to find error context + * @return PEAR_Error|null|Exception + * if compatibility mode is on, a PEAR_Error is also + * thrown. If the class Exception exists, then one + * is returned to allow code like: + * + * throw ($stack->push(MY_ERROR_CODE, 'error', array('username' => 'grob'))); + * + * @static + */ + function staticPush($package, $code, $level = 'error', $params = array(), + $msg = false, $repackage = false, $backtrace = false) + { + $s = &PEAR_ErrorStack::singleton($package); + if ($s->_contextCallback) { + if (!$backtrace) { + $backtrace = debug_backtrace(); + } + } + return $s->push($code, $level, $params, $msg, $repackage, $backtrace); + } + + /** + * Log an error using PEAR::Log + * @param array $err Error array + * @param array $levels Error level => Log constant map + * @access protected + */ + function _log($err, $levels = array( + 'exception' => PEAR_LOG_CRIT, + 'alert' => PEAR_LOG_ALERT, + 'critical' => PEAR_LOG_CRIT, + 'error' => PEAR_LOG_ERR, + 'warning' => PEAR_LOG_WARNING, + 'notice' => PEAR_LOG_NOTICE, + 'info' => PEAR_LOG_INFO, + 'debug' => PEAR_LOG_DEBUG)) + { + if (isset($levels[$err['level']])) { + $level = $levels[$err['level']]; + } else { + $level = PEAR_LOG_INFO; + } + if ($this->_logger) { + $this->_logger->log($err['message'], $level, $err); + } else { + $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']->log($err['message'], $level, $err); + } + } + + + /** + * Pop an error off of the error stack + * + * @return false|array + * @since 0.4alpha it is no longer possible to specify a specific error + * level to return - the last error pushed will be returned, instead + */ + function pop() + { + return @array_shift($this->_errors); + } + + /** + * Determine whether there are any errors on the stack + * @return boolean + */ + function hasErrors() + { + return count($this->_errors); + } + + /** + * Retrieve all errors since last purge + * + * @param boolean $purge set in order to empty the error stack + * @return array + */ + function getErrors($purge = false) + { + if (!$purge) { + return $this->_errors; + } + $ret = $this->_errors; + $this->_errors = array(); + return $ret; + } + + /** + * Determine whether there are any errors on any error stack + * @return boolean + * @static + */ + function staticHasErrors() + { + foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) { + if ($obj->hasErrors()) { + return true; + } + } + return false; + } + + /** + * Get a list of all errors since last purge, organized by package + * @param boolean $clearStack Set to purge the error stack of existing errors + * @param boolean $merge Set to return a flat array, not organized by package + * @param array $sortfunc Function used to sort a merged array - default + * sorts by time, and should be good for most cases + * @static + * @return array + */ + function staticGetErrors($purge = false, $merge = false, $sortfunc = array('PEAR_ErrorStack', '_sortErrors')) + { + $ret = array(); + if (!is_callable($sortfunc)) { + $sortfunc = array('PEAR_ErrorStack', '_sortErrors'); + } + foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) { + $test = $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->getErrors($purge); + if ($test) { + if ($merge) { + $ret = array_merge($ret, $test); + } else { + $ret[$package] = $test; + } + } + } + if ($merge) { + usort($ret, $sortfunc); + } + return $ret; + } + + /** + * Error sorting function, sorts by time + * @access private + */ + function _sortErrors($a, $b) + { + if ($a['time'] == $b['time']) { + return 0; + } + if ($a['time'] < $b['time']) { + return 1; + } + return -1; + } + + /** + * Standard file/line number/function/class context callback + * + * This function uses a backtrace generated from {@link debug_backtrace()} + * and so will not work at all in PHP < 4.3.0. The frame should + * reference the frame that contains the source of the error. + * @return array|false either array('file' => file, 'line' => line, + * 'function' => function name, 'class' => class name) or + * if this doesn't work, then false + * @param array Results of debug_backtrace() + * @param unused + * @param integer backtrace frame. + * @static + */ + function getFileLine($code, $params, $backtrace = null) + { + if ($backtrace === null) { + return false; + } + $frame = 0; + $functionframe = 1; + if (!isset($backtrace[1])) { + $functionframe = 0; + } else { + while (isset($backtrace[$functionframe]['function']) && + $backtrace[$functionframe]['function'] == 'eval' && + isset($backtrace[$functionframe + 1])) { + $functionframe++; + } + } + if (isset($backtrace[$frame])) { + if (!isset($backtrace[$frame]['file'])) { + $frame++; + } + $funcbacktrace = $backtrace[$functionframe]; + $filebacktrace = $backtrace[$frame]; + $ret = array('file' => $filebacktrace['file'], + 'line' => $filebacktrace['line']); + // rearrange for eval'd code or create function errors + if (strpos($filebacktrace['file'], '(') && + preg_match(';^(.*?)\((\d+)\) : (.*?)$;', $filebacktrace['file'], + $matches)) { + $ret['file'] = $matches[1]; + $ret['line'] = $matches[2] + 0; + } + if (isset($funcbacktrace['function']) && isset($backtrace[1])) { + if ($funcbacktrace['function'] != 'eval') { + if ($funcbacktrace['function'] == '__lambda_func') { + $ret['function'] = 'create_function() code'; + } else { + $ret['function'] = $funcbacktrace['function']; + } + } + } + if (isset($funcbacktrace['class']) && isset($backtrace[1])) { + $ret['class'] = $funcbacktrace['class']; + } + return $ret; + } + return false; + } + + /** + * Standard error message generation callback + * + * This method may also be called by a custom error message generator + * to fill in template values from the params array, simply + * set the third parameter to the error message template string to use + * + * The special variable %__msg% is reserved: use it only to specify + * where a message passed in by the user should be placed in the template, + * like so: + * + * Error message: %msg% - internal error + * + * If the message passed like so: + * + * + * $stack->push(ERROR_CODE, 'error', array(), 'server error 500'); + * + * + * The returned error message will be "Error message: server error 500 - + * internal error" + * @param PEAR_ErrorStack + * @param array + * @param string|false Pre-generated error message template + * @static + * @return string + */ + function getErrorMessage(&$stack, $err, $template = false) + { + if ($template) { + $mainmsg = $template; + } else { + $mainmsg = $stack->getErrorMessageTemplate($err['code']); + } + $mainmsg = str_replace('%__msg%', $err['message'], $mainmsg); + if (count($err['params'])) { + foreach ($err['params'] as $name => $val) { + if (is_array($val)) { + $val = implode(', ', $val); + } + if (is_object($val)) { + if (method_exists($val, '__toString')) { + $val = $val->__toString(); + } else { + PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_OBJTOSTRING, + 'warning', array('obj' => get_class($val)), + 'object %obj% passed into getErrorMessage, but has no __toString() method'); + $val = 'Object'; + } + } + $mainmsg = str_replace('%' . $name . '%', $val, $mainmsg); + } + } + return $mainmsg; + } + + /** + * Standard Error Message Template generator from code + * @return string + */ + function getErrorMessageTemplate($code) + { + if (!isset($this->_errorMsgs[$code])) { + return '%__msg%'; + } + return $this->_errorMsgs[$code]; + } + + /** + * Set the Error Message Template array + * + * The array format must be: + *
+     * array(error code => 'message template',...)
+     * 
+ * + * Error message parameters passed into {@link push()} will be used as input + * for the error message. If the template is 'message %foo% was %bar%', and the + * parameters are array('foo' => 'one', 'bar' => 'six'), the error message returned will + * be 'message one was six' + * @return string + */ + function setErrorMessageTemplate($template) + { + $this->_errorMsgs = $template; + } + + + /** + * emulate PEAR::raiseError() + * + * @return PEAR_Error + */ + function raiseError() + { + require_once 'PEAR.php'; + $args = func_get_args(); + return call_user_func_array(array('PEAR', 'raiseError'), $args); + } +} +$stack = &PEAR_ErrorStack::singleton('PEAR_ErrorStack'); +$stack->pushCallback(array('PEAR_ErrorStack', '_handleError')); +?> \ No newline at end of file diff --git a/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_getErrorMessage.php b/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_getErrorMessage.php new file mode 100644 index 0000000000..2f46b19bc9 --- /dev/null +++ b/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_getErrorMessage.php @@ -0,0 +1,142 @@ + portions from HTML_CSS + * @author Greg Beaver + * @package PEAR_ErrorStack + */ + +class testgemessage +{ + function __toString() + { + return '__toString() called'; + } +} +class testgemessage1 {} +/** + * @package PEAR_ErrorStack + */ + +class PEAR_ErrorStack_TestCase_getErrorMessage extends PHPUnit_TestCase +{ + + function PEAR_ErrorStack_TestCase_getErrorMessage($name) + { + $this->PHPUnit_TestCase($name); + } + + function setUp() + { + error_reporting(E_ALL); + $this->errorOccured = false; + set_error_handler(array(&$this, 'errorHandler')); + $this->stack = new PEAR_ErrorStack('test'); + $s = &PEAR_ErrorStack::singleton('PEAR_ErrorStack'); + $s->pushCallback(array('PEAR_ErrorStack', '_handleError')); + } + + function tearDown() + { + unset($this->stack); + unset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON']); + } + + + function _stripWhitespace($str) + { + return preg_replace('/\\s+/', '', $str); + } + + function _methodExists($name) + { + if (in_array(strtolower($name), get_class_methods($this->stack))) { + return true; + } + $this->assertTrue(false, 'method '. $name . ' not implemented in ' . get_class($this->stack)); + return false; + } + + function errorHandler($errno, $errstr, $errfile, $errline) { + //die("$errstr in $errfile at line $errline: $errstr"); + $this->errorOccured = true; + $this->assertTrue(false, "$errstr at line $errline, $errfile"); + } + + function returnsignore($err) + { + $this->wasCalled = true; + return PEAR_ERRORSTACK_IGNORE; + } + + function test_basic() + { + if (!$this->_methodExists('getErrorMessage')) { + return; + } + $msg = PEAR_ErrorStack::getErrorMessage($this->stack, + array('message' => 'boo', 'params' => array(), 'code' => 6)); + $this->assertEquals('boo', $msg); + } + + function test_basic_template() + { + if (!$this->_methodExists('getErrorMessage')) { + return; + } + $msg = PEAR_ErrorStack::getErrorMessage($this->stack, + array('message' => 'boo', 'params' => array()), 'far%__msg%'); + $this->assertEquals('farboo', $msg); + } + + function test_basic_params() + { + if (!$this->_methodExists('getErrorMessage')) { + return; + } + $msg = PEAR_ErrorStack::getErrorMessage($this->stack, array('message' => '', + 'params' => array('bar' => 'hello')), '%bar% foo'); + $this->assertEquals('hello foo', $msg, 'string'); + $msg = PEAR_ErrorStack::getErrorMessage($this->stack, array('message' => '', + 'params' => array('bar' => array('hello', 'there'))), '%bar% foo'); + $this->assertEquals('hello, there foo', $msg, 'array'); + $msg = PEAR_ErrorStack::getErrorMessage($this->stack, array('message' => '', + 'params' => array('bar' => new testgemessage)), '%bar% foo'); + $this->assertEquals('__toString() called foo', $msg, 'first object, __toString()'); + $msg = PEAR_ErrorStack::getErrorMessage($this->stack, array('message' => '', + 'params' => array('bar' => new testgemessage1)), '%bar% foo'); + $this->assertEquals('Object foo', $msg, 'second object, no __toString()'); + $errs = PEAR_ErrorStack::staticGetErrors(); + unset($errs['PEAR_ErrorStack'][0]['context']); + unset($errs['PEAR_ErrorStack'][0]['time']); + $this->assertEquals( + array('PEAR_ErrorStack' => + array( + array( + 'code' => PEAR_ERRORSTACK_ERR_OBJTOSTRING, + 'params' => array('obj' => 'testgemessage1'), + 'package' => 'PEAR_ErrorStack', + 'level' => 'warning', + 'message' => 'object testgemessage1 passed into getErrorMessage, but has no __toString() method', + ))), $errs, 'warning not raised'); + } + + function test_basic_params_with_template() + { + if (!$this->_methodExists('getErrorMessage')) { + return; + } + $this->stack->setErrorMessageTemplate(array(6 => '%bar% foo')); + $msg = PEAR_ErrorStack::getErrorMessage($this->stack, array('message' => '', + 'params' => array('bar' => 'hello'), 'code' => 6)); + $this->assertEquals('hello foo', $msg, 'string'); + $msg = PEAR_ErrorStack::getErrorMessage($this->stack, array('message' => '', + 'params' => array('bar' => 'hello'), 'code' => 7)); + $this->assertEquals('', $msg, 'string'); + } +} + +?> diff --git a/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_getErrorMessageTemplate.php b/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_getErrorMessageTemplate.php new file mode 100644 index 0000000000..36270d6e9f --- /dev/null +++ b/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_getErrorMessageTemplate.php @@ -0,0 +1,88 @@ + portions from HTML_CSS + * @author Greg Beaver + * @package PEAR_ErrorStack + */ + +/** + * @package PEAR_ErrorStack + */ + +class PEAR_ErrorStack_TestCase_getErrorMessageTemplate extends PHPUnit_TestCase +{ + + function PEAR_ErrorStack_TestCase_getErrorMessageTemplate($name) + { + $this->PHPUnit_TestCase($name); + } + + function setUp() + { + error_reporting(E_ALL); + $this->errorOccured = false; + set_error_handler(array(&$this, 'errorHandler')); + $this->stack = new PEAR_ErrorStack('test'); + $s = &PEAR_ErrorStack::singleton('PEAR_ErrorStack'); + $s->pushCallback(array('PEAR_ErrorStack', '_handleError')); + } + + function tearDown() + { + unset($this->stack); + unset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON']); + } + + + function _stripWhitespace($str) + { + return preg_replace('/\\s+/', '', $str); + } + + function _methodExists($name) + { + if (in_array(strtolower($name), get_class_methods($this->stack))) { + return true; + } + $this->assertTrue(false, 'method '. $name . ' not implemented in ' . get_class($this->stack)); + return false; + } + + function errorHandler($errno, $errstr, $errfile, $errline) { + //die("$errstr in $errfile at line $errline: $errstr"); + $this->errorOccured = true; + $this->assertTrue(false, "$errstr at line $errline, $errfile"); + } + + function returnsignore($err) + { + $this->wasCalled = true; + return PEAR_ERRORSTACK_IGNORE; + } + + function test_normal() + { + if (!$this->_methodExists('getErrorMessageTemplate')) { + return; + } + $this->assertEquals('%__msg%', $this->stack->getErrorMessageTemplate(23)); + } + + function test_normal_hascode() + { + if (!$this->_methodExists('getErrorMessageTemplate')) { + return; + } + if (!$this->_methodExists('setErrorMessageTemplate')) { + return; + } + $this->stack->setErrorMessageTemplate(array(23 => '%foo% has %__msg%')); + $this->assertEquals('%foo% has %__msg%', $this->stack->getErrorMessageTemplate(23)); + } +} + +?> diff --git a/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_getErrors.php b/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_getErrors.php new file mode 100644 index 0000000000..e2a986e679 --- /dev/null +++ b/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_getErrors.php @@ -0,0 +1,135 @@ + portions from HTML_CSS + * @author Greg Beaver + * @package PEAR_ErrorStack + */ + +/** + * @package PEAR_ErrorStack + */ + +class PEAR_ErrorStack_TestCase_getErrors extends PHPUnit_TestCase +{ + + function PEAR_ErrorStack_TestCase_getErrors($name) + { + $this->PHPUnit_TestCase($name); + } + + function setUp() + { + error_reporting(E_ALL); + $this->errorOccured = false; + set_error_handler(array(&$this, 'errorHandler')); + $this->stack = new PEAR_ErrorStack('test'); + $s = &PEAR_ErrorStack::singleton('PEAR_ErrorStack'); + $s->pushCallback(array('PEAR_ErrorStack', '_handleError')); + } + + function tearDown() + { + unset($this->stack); + unset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON']); + } + + + function _stripWhitespace($str) + { + return preg_replace('/\\s+/', '', $str); + } + + function _methodExists($name) + { + if (in_array(strtolower($name), get_class_methods($this->stack))) { + return true; + } + $this->assertTrue(false, 'method '. $name . ' not implemented in ' . get_class($this->stack)); + return false; + } + + function errorHandler($errno, $errstr, $errfile, $errline) { + //die("$errstr in $errfile at line $errline: $errstr"); + $this->errorOccured = true; + $this->assertTrue(false, "$errstr at line $errline, $errfile"); + } + + function returnsignore($err) + { + $this->wasCalled = true; + return PEAR_ERRORSTACK_IGNORE; + } + + function test_none() + { + if (!$this->_methodExists('getErrors')) { + return; + } + $this->assertEquals(array(), $this->stack->getErrors()); + $this->assertEquals(array(), $this->stack->getErrors(true)); + } + + function test_normal() + { + if (!$this->_methodExists('getErrors')) { + return; + } + $this->assertEquals(array(), $this->stack->getErrors()); + $this->stack->push(1); + $this->stack->push(2, 'warning'); + $this->stack->push(3, 'foo'); + $ret = $this->stack->getErrors(); + for ($i= 0; $i < 3; $i++) { + unset($ret[$i]['time']); + unset($ret[$i]['context']); + } + $this->assertEquals( + array( + array('code' => 3, + 'params' => array(), + 'package' => 'test', + 'level' => 'foo', + 'message' => ''), + array('code' => 2, + 'params' => array(), + 'package' => 'test', + 'level' => 'warning', + 'message' => ''), + array('code' => 1, + 'params' => array(), + 'package' => 'test', + 'level' => 'error', + 'message' => ''), + ), $ret, 'incorrect errors, non-purge'); + $ret = $this->stack->getErrors(true); + for ($i= 0; $i < 3; $i++) { + unset($ret[$i]['time']); + unset($ret[$i]['context']); + } + $this->assertEquals( + array( + array('code' => 3, + 'params' => array(), + 'package' => 'test', + 'level' => 'foo', + 'message' => ''), + array('code' => 2, + 'params' => array(), + 'package' => 'test', + 'level' => 'warning', + 'message' => ''), + array('code' => 1, + 'params' => array(), + 'package' => 'test', + 'level' => 'error', + 'message' => ''), + ), $ret, 'incorrect errors, purge'); + $this->assertEquals(array(), $this->stack->getErrors()); + } +} + +?> diff --git a/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_pushpop.php b/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_pushpop.php new file mode 100644 index 0000000000..ec7eb8399a --- /dev/null +++ b/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_pushpop.php @@ -0,0 +1,367 @@ + portions from HTML_CSS + * @author Greg Beaver + * @package PEAR_ErrorStack + */ + +/** + * @package PEAR_ErrorStack + */ + +class PEAR_ErrorStack_TestCase_pushpop extends PHPUnit_TestCase +{ + /** + * A PEAR_PackageFileManager object + * @var object + */ + var $packagexml; + + function PEAR_ErrorStack_TestCase_pushpop($name) + { + $this->PHPUnit_TestCase($name); + } + + function setUp() + { + error_reporting(E_ALL); + $this->errorOccured = false; + set_error_handler(array(&$this, 'errorHandler')); + $this->stack = new PEAR_ErrorStack('test'); + $s = &PEAR_ErrorStack::singleton('PEAR_ErrorStack'); + $s->pushCallback(array('PEAR_ErrorStack', '_handleError')); + } + + function tearDown() + { + unset($this->stack); + unset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON']); + } + + + function _stripWhitespace($str) + { + return preg_replace('/\\s+/', '', $str); + } + + function _methodExists($name) + { + if (in_array(strtolower($name), get_class_methods($this->stack))) { + return true; + } + $this->assertTrue(false, 'method '. $name . ' not implemented in ' . get_class($this->stack)); + return false; + } + + function errorHandler($errno, $errstr, $errfile, $errline) { + //die("$errstr in $errfile at line $errline: $errstr"); + $this->errorOccured = true; + $this->assertTrue(false, "$errstr at line $errline, $errfile"); + } + + function test_valid_basic() + { + if (!$this->_methodExists('push')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + $this->stack->push(1); + $err = $this->stack->pop(); + unset($err['context']); + unset($err['time']); + $this->assertEquals( + array( + 'code' => 1, + 'params' => array(), + 'package' => 'test', + 'message' => '', + 'level' => 'error', + ), + $err, 'popped something else' + ); + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function test_valid_params() + { + if (!$this->_methodExists('push')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + $z = $this->stack->push(2, 'exception', array('my' => 'param'), 'hello', + array('test'), array(array('file' => 'boof', 'line' => 34))); + $err = $this->stack->pop('exception'); + $this->assertEquals($z, $err, 'popped different error'); + unset($err['time']); + $this->assertEquals( + array( + 'code' => 2, + 'params' => array('my' => 'param'), + 'package' => 'test', + 'message' => 'hello', + 'level' => 'exception', + 'context' => + array( + 'file' => 'boof', + 'line' => 34, + ), + 'repackage' => array('test'), + ), + $err, 'popped something else' + ); + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function test_valid_paramscompat() + { + if (!$this->_methodExists('push')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + $this->stack = new PEAR_ErrorStack('test', false, null, true); + $z = $this->stack->push(2, 'exception', array('my' => 'param'), 'hello', + array('test'), array(array('file' => 'boof', 'line' => 34))); + $this->assertEquals('pear_error', strtolower(get_class($z)), 'not pear_error'); + $err = $this->stack->pop('exception'); + if (is_a($z, 'PEAR_Error')) { + $this->assertEquals($err, $z->getUserInfo(), 'userinfo wrong'); + } + unset($err['time']); + $this->assertEquals( + array( + 'code' => 2, + 'params' => array('my' => 'param'), + 'package' => 'test', + 'message' => 'hello', + 'level' => 'exception', + 'context' => + array( + 'file' => 'boof', + 'line' => 34, + ), + 'repackage' => array('test'), + ), + $err, 'popped something else' + ); + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function contextcallback($code, $params, $trace) + { + $this->assertEquals(4, $code, 'wrong context code'); + $this->assertEquals(array('hello' => 6), $params, 'wrong context params'); + $this->wasCalled = true; + return array('hi' => 'there', 'you' => 'fool'); + } + + function test_valid_contextconstructor() + { + if (!$this->_methodExists('push')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + $this->stack = new PEAR_ErrorStack('test', false, array(&$this, 'contextcallback')); + $this->wasCalled = false; + $this->stack->push(4, 'error', array('hello' => 6)); + $this->assertTrue($this->wasCalled, 'context callback was not called!'); + $err = $this->stack->pop(); + unset($err['time']); + $this->assertEquals( + array( + 'code' => 4, + 'params' => array('hello' => 6), + 'package' => 'test', + 'message' => '', + 'level' => 'error', + 'context' => array('hi' => 'there', 'you' => 'fool'), + ), + $err, 'popped something else' + ); + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function test_valid_contextsingleton() + { + if (!$this->_methodExists('push')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + if (!$this->_methodExists('singleton')) { + return; + } + $this->stack = &PEAR_ErrorStack::singleton('test', false, array(&$this, 'contextcallback')); + $this->wasCalled = false; + $this->stack->push(4, 'error', array('hello' => 6)); + $this->assertTrue($this->wasCalled, 'context callback was not called!'); + $err = $this->stack->pop(); + unset($err['time']); + $this->assertEquals( + array( + 'code' => 4, + 'params' => array('hello' => 6), + 'package' => 'test', + 'message' => '', + 'level' => 'error', + 'context' => array('hi' => 'there', 'you' => 'fool'), + ), + $err, 'popped something else' + ); + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function test_valid_context_setcontext() + { + if (!$this->_methodExists('push')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + if (!$this->_methodExists('setContextCallback')) { + return; + } + $this->stack->setContextCallback(array(&$this, 'contextcallback')); + $this->wasCalled = false; + $this->stack->push(4, 'error', array('hello' => 6)); + $this->assertTrue($this->wasCalled, 'context callback was not called!'); + $err = $this->stack->pop(); + unset($err['time']); + $this->assertEquals( + array( + 'code' => 4, + 'params' => array('hello' => 6), + 'package' => 'test', + 'message' => '', + 'level' => 'error', + 'context' => array('hi' => 'there', 'you' => 'fool'), + ), + $err, 'popped something else' + ); + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function messagecallback(&$stack, $err) + { + $this->assertEquals(4, $err['code'], 'wrong message code'); + $this->assertEquals(array('hello' => 6), $err['params'], 'wrong message params'); + $this->assertEquals('test1', $err['package'], 'wrong error stack'); + $this->wasCalled = true; + return 'my silly message'; + } + + function test_valid_msgcallbackconstructor() + { + if (!$this->_methodExists('push')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + $this->stack = new PEAR_ErrorStack('test1', array(&$this, 'messagecallback')); + $this->wasCalled = false; + $this->stack->push(4, 'error', array('hello' => 6)); + $this->assertTrue($this->wasCalled, 'message callback was not called!'); + $err = $this->stack->pop(); + unset($err['time']); + unset($err['context']); + $this->assertEquals( + array( + 'code' => 4, + 'params' => array('hello' => 6), + 'package' => 'test1', + 'message' => 'my silly message', + 'level' => 'error', + ), + $err, 'popped something else' + ); + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function test_valid_msgcallbacksingleton() + { + if (!$this->_methodExists('push')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + if (!$this->_methodExists('singleton')) { + return; + } + $this->stack = &PEAR_ErrorStack::singleton('test1', array(&$this, 'messagecallback')); + $this->wasCalled = false; + $this->stack->push(4, 'error', array('hello' => 6)); + $this->assertTrue($this->wasCalled, 'message callback was not called!'); + $err = $this->stack->pop(); + unset($err['time']); + unset($err['context']); + $this->assertEquals( + array( + 'code' => 4, + 'params' => array('hello' => 6), + 'package' => 'test1', + 'message' => 'my silly message', + 'level' => 'error', + ), + $err, 'popped something else' + ); + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function test_valid_msgcallback_setmsgcallback() + { + if (!$this->_methodExists('push')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + if (!$this->_methodExists('setContextCallback')) { + return; + } + $this->stack = new PEAR_ErrorStack('test1'); + $this->stack->setMessageCallback(array(&$this, 'messagecallback')); + $this->wasCalled = false; + $this->stack->push(4, 'error', array('hello' => 6)); + $this->assertTrue($this->wasCalled, 'message callback was not called!'); + $err = $this->stack->pop(); + unset($err['time']); + unset($err['context']); + $this->assertEquals( + array( + 'code' => 4, + 'params' => array('hello' => 6), + 'package' => 'test1', + 'message' => 'my silly message', + 'level' => 'error', + ), + $err, 'popped something else' + ); + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } +} + +?> diff --git a/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_pushpopcallback.php b/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_pushpopcallback.php new file mode 100644 index 0000000000..3838ae309d --- /dev/null +++ b/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_pushpopcallback.php @@ -0,0 +1,320 @@ + portions from HTML_CSS + * @author Greg Beaver + * @package PEAR_ErrorStack + */ + +/** + * @package PEAR_ErrorStack + */ + +class PEAR_ErrorStack_TestCase_pushpopcallback extends PHPUnit_TestCase +{ + /** + * A PEAR_PackageFileManager object + * @var object + */ + var $packagexml; + + function PEAR_ErrorStack_TestCase_pushpopcallback($name) + { + $this->PHPUnit_TestCase($name); + } + + function setUp() + { + error_reporting(E_ALL); + $this->errorOccured = false; + set_error_handler(array(&$this, 'errorHandler')); + $this->stack = new PEAR_ErrorStack('test'); + } + + function tearDown() + { + unset($this->stack); + unset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON']); + } + + + function _stripWhitespace($str) + { + return preg_replace('/\\s+/', '', $str); + } + + function _methodExists($name) + { + if (in_array(strtolower($name), get_class_methods($this->stack))) { + return true; + } + $this->assertTrue(false, 'method '. $name . ' not implemented in ' . get_class($this->stack)); + return false; + } + + function errorHandler($errno, $errstr, $errfile, $errline) { + //die("$errstr in $errfile at line $errline: $errstr"); + $this->errorOccured = true; + $this->assertTrue(false, "$errstr at line $errline, $errfile"); + } + + function returnsignore($err) + { + $this->wasCalled = true; + return PEAR_ERRORSTACK_IGNORE; + } + + function test_return_ignore() + { + if (!$this->_methodExists('push')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + if (!$this->_methodExists('pushCallback')) { + return; + } + if (!$this->_methodExists('popCallback')) { + return; + } + $this->stack->pushCallback(array(&$this, 'returnsignore')); + $this->wasCalled = false; + $this->stack->push(1); + $this->assertTrue($this->wasCalled, 'returnsignore not called'); + $err = $this->stack->pop(); + $this->assertFalse($err, 'error was not ignored!'); + $this->stack->popCallback(); + $this->wasCalled = false; + $this->stack->push(1); + $this->assertFalse($this->wasCalled, 'returnsignore called'); + $err = $this->stack->pop(); + unset($err['context']); + unset($err['time']); + $this->assertEquals( + array( + 'code' => 1, + 'params' => array(), + 'package' => 'test', + 'message' => '', + 'level' => 'error', + ), + $err, 'popped something else' + ); + + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function returnsnothing($err) + { + $this->wasCalled = true; + } + + function test_return_nothing() + { + if (!$this->_methodExists('push')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + if (!$this->_methodExists('pushCallback')) { + return; + } + if (!$this->_methodExists('popCallback')) { + return; + } + $this->stack->pushCallback(array(&$this, 'returnsnothing')); + $this->wasCalled = false; + $this->stack->push(1); + $this->assertTrue($this->wasCalled, 'returnsnothing not called'); + $err = $this->stack->pop(); + unset($err['context']); + unset($err['time']); + $this->assertEquals( + array( + 'code' => 1, + 'params' => array(), + 'package' => 'test', + 'message' => '', + 'level' => 'error', + ), + $err, 'popped something else' + ); + $this->stack->popCallback(); + $this->wasCalled = false; + $this->stack->push(1); + $this->assertFalse($this->wasCalled, 'returnsnothing called'); + $err = $this->stack->pop(); + unset($err['context']); + unset($err['time']); + $this->assertEquals( + array( + 'code' => 1, + 'params' => array(), + 'package' => 'test', + 'message' => '', + 'level' => 'error', + ), + $err, 'popped something else' + ); + + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function returnspush($err) + { + $this->wasCalled = true; + return PEAR_ERRORSTACK_PUSH; + } + + function test_return_push() + { + if (!$this->_methodExists('push')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + if (!$this->_methodExists('pushCallback')) { + return; + } + if (!$this->_methodExists('popCallback')) { + return; + } + if (!$this->_methodExists('setLogger')) { + return; + } + $this->stack->pushCallback(array(&$this, 'returnspush')); + $log = new BurfLog; + $log->setTestCase($this); + $log->curMethod(__FUNCTION__); + $this->stack->setLogger($log); + $this->wasCalled = false; + $this->stack->push(1); + $this->assertTrue($this->wasCalled, 'returnspush not called'); + $err = $this->stack->pop(); + unset($err['context']); + unset($err['time']); + $this->assertEquals( + array( + 'code' => 1, + 'params' => array(), + 'package' => 'test', + 'message' => '', + 'level' => 'error', + ), + $err, 'popped something else 1' + ); + $this->stack->popCallback(); + $log->pushExpect('', PEAR_LOG_ERR, array( + 'code' => 1, + 'params' => array(), + 'package' => 'test', + 'message' => '', + 'level' => 'error', + )); + $this->wasCalled = false; + $this->wasLogged = false; + $this->stack->push(1); + $this->assertFalse($this->wasCalled, 'returnspush called'); + $this->assertTrue($this->wasLogged, 'was not logged!'); + $err = $this->stack->pop(); + unset($err['context']); + unset($err['time']); + $this->assertEquals( + array( + 'code' => 1, + 'params' => array(), + 'package' => 'test', + 'message' => '', + 'level' => 'error', + ), + $err, 'popped something else 2' + ); + + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function returnslog($err) + { + $this->wasCalled = true; + return PEAR_ERRORSTACK_LOG; + } + + function test_return_log() + { + if (!$this->_methodExists('push')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + if (!$this->_methodExists('pushCallback')) { + return; + } + if (!$this->_methodExists('popCallback')) { + return; + } + if (!$this->_methodExists('setLogger')) { + return; + } + $this->stack->pushCallback(array(&$this, 'returnslog')); + $log = new BurfLog; + $log->setTestCase($this); + $log->curMethod(__FUNCTION__); + $this->stack->setLogger($log); + $this->wasCalled = false; + $this->wasLogged = false; + $log->pushExpect('', PEAR_LOG_ERR, array( + 'code' => 1, + 'params' => array(), + 'package' => 'test', + 'message' => '', + 'level' => 'error', + )); + $this->stack->push(1); + $this->assertTrue($this->wasCalled, 'returnslog not called'); + $this->assertTrue($this->wasLogged, 'was not logged!'); + $err = $this->stack->pop(); + $this->assertFalse($err, 'an error was pushed!'); + $this->stack->popCallback(); + $log->clearExpect(); + $log->pushExpect('', PEAR_LOG_ERR, array( + 'code' => 1, + 'params' => array(), + 'package' => 'test', + 'message' => '', + 'level' => 'error', + )); + $this->wasCalled = false; + $this->wasLogged = false; + $this->stack->push(1); + $this->assertFalse($this->wasCalled, 'returnspush called'); + $this->assertTrue($this->wasLogged, 'was not logged!'); + $err = $this->stack->pop(); + unset($err['context']); + unset($err['time']); + $this->assertEquals( + array( + 'code' => 1, + 'params' => array(), + 'package' => 'test', + 'message' => '', + 'level' => 'error', + ), + $err, 'popped something else 2' + ); + + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } +} + +?> diff --git a/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_pushpopstatic.php b/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_pushpopstatic.php new file mode 100644 index 0000000000..1af66d7bef --- /dev/null +++ b/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_pushpopstatic.php @@ -0,0 +1,327 @@ + portions from HTML_CSS + * @author Greg Beaver + * @package PEAR_ErrorStack + */ + +/** + * @package PEAR_ErrorStack + */ + +class PEAR_ErrorStack_TestCase_pushpopstatic extends PHPUnit_TestCase +{ + /** + * A PEAR_PackageFileManager object + * @var object + */ + var $packagexml; + + function PEAR_ErrorStack_TestCase_pushpopstatic($name) + { + $this->PHPUnit_TestCase($name); + } + + function setUp() + { + error_reporting(E_ALL); + $this->errorOccured = false; + set_error_handler(array(&$this, 'errorHandler')); + $this->stack = new PEAR_ErrorStack(''); + $s = &PEAR_ErrorStack::singleton('PEAR_ErrorStack'); + $s->pushCallback(array('PEAR_ErrorStack', '_handleError')); + } + + function tearDown() + { + unset($this->stack); + unset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON']); + } + + + function _stripWhitespace($str) + { + return preg_replace('/\\s+/', '', $str); + } + + function _methodExists($name) + { + if (in_array(strtolower($name), get_class_methods($this->stack))) { + return true; + } + $this->assertTrue(false, 'method '. $name . ' not implemented in ' . get_class($this->stack)); + return false; + } + + function errorHandler($errno, $errstr, $errfile, $errline) { + //die("$errstr in $errfile at line $errline: $errstr"); + $this->errorOccured = true; + $this->assertTrue(false, "$errstr at line $errline, $errfile"); + } + + function test_valid_basic() + { + if (!$this->_methodExists('staticPush')) { + return; + } + if (!$this->_methodExists('singleton')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + $this->stack = &PEAR_ErrorStack::singleton('test'); + PEAR_ErrorStack::staticPush('test', 1); + $err = $this->stack->pop(); + unset($err['context']); + unset($err['time']); + $this->assertEquals( + array( + 'code' => 1, + 'params' => array(), + 'package' => 'test', + 'message' => '', + 'level' => 'error', + ), + $err, 'popped something else' + ); + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function test_valid_params() + { + if (!$this->_methodExists('staticPush')) { + return; + } + if (!$this->_methodExists('singleton')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + $this->stack = &PEAR_ErrorStack::singleton('test'); + $z = PEAR_ErrorStack::staticPush('test', 2, 'exception', array('my' => 'param'), 'hello', + array('test'), array(array('file' => 'boof', 'line' => 34))); + $err = $this->stack->pop('exception'); + $this->assertEquals($z, $err, 'popped different error'); + unset($err['time']); + $this->assertEquals( + array( + 'code' => 2, + 'params' => array('my' => 'param'), + 'package' => 'test', + 'message' => 'hello', + 'level' => 'exception', + 'context' => + array( + 'file' => 'boof', + 'line' => 34, + ), + 'repackage' => array('test'), + ), + $err, 'popped something else' + ); + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function test_valid_paramscompat() + { + if (!$this->_methodExists('staticPush')) { + return; + } + if (!$this->_methodExists('singleton')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + $this->stack = &PEAR_ErrorStack::singleton('test', false, null, 'PEAR_ErrorStack', true); + $z = PEAR_ErrorStack::staticPush('test', 2, 'exception', array('my' => 'param'), 'hello', + array('test'), array(array('file' => 'boof', 'line' => 34))); + $this->assertEquals('pear_error', strtolower(get_class($z)), 'not pear_error'); + $err = $this->stack->pop('exception'); + if (is_a($z, 'PEAR_Error')) { + $this->assertEquals($err, $z->getUserInfo(), 'userinfo wrong'); + } + unset($err['time']); + $this->assertEquals( + array( + 'code' => 2, + 'params' => array('my' => 'param'), + 'package' => 'test', + 'message' => 'hello', + 'level' => 'exception', + 'context' => + array( + 'file' => 'boof', + 'line' => 34, + ), + 'repackage' => array('test'), + ), + $err, 'popped something else' + ); + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function contextcallback($code, $params, $trace) + { + $this->assertEquals(4, $code, 'wrong context code'); + $this->assertEquals(array('hello' => 6), $params, 'wrong context params'); + $this->wasCalled = true; + return array('hi' => 'there', 'you' => 'fool'); + } + + function test_valid_contextsingleton() + { + if (!$this->_methodExists('staticPush')) { + return; + } + if (!$this->_methodExists('singleton')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + $this->stack = &PEAR_ErrorStack::singleton('test', false, array(&$this, 'contextcallback')); + $this->wasCalled = false; + PEAR_ErrorStack::staticPush('test', 4, 'error', array('hello' => 6)); + $this->assertTrue($this->wasCalled, 'context callback was not called!'); + $err = $this->stack->pop(); + unset($err['time']); + $this->assertEquals( + array( + 'code' => 4, + 'params' => array('hello' => 6), + 'package' => 'test', + 'message' => '', + 'level' => 'error', + 'context' => array('hi' => 'there', 'you' => 'fool'), + ), + $err, 'popped something else' + ); + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function test_valid_context_setcontext() + { + if (!$this->_methodExists('staticPush')) { + return; + } + if (!$this->_methodExists('singleton')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + if (!$this->_methodExists('setContextCallback')) { + return; + } + $this->stack = &PEAR_ErrorStack::singleton('test'); + $this->stack->setContextCallback(array(&$this, 'contextcallback')); + $this->wasCalled = false; + PEAR_ErrorStack::staticPush('test', 4, 'error', array('hello' => 6)); + $this->assertTrue($this->wasCalled, 'context callback was not called!'); + $err = $this->stack->pop(); + unset($err['time']); + $this->assertEquals( + array( + 'code' => 4, + 'params' => array('hello' => 6), + 'package' => 'test', + 'message' => '', + 'level' => 'error', + 'context' => array('hi' => 'there', 'you' => 'fool'), + ), + $err, 'popped something else' + ); + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function messagecallback(&$stack, $err) + { + $this->assertEquals(4, $err['code'], 'wrong message code'); + $this->assertEquals(array('hello' => 6), $err['params'], 'wrong message params'); + $this->assertEquals('test1', $err['package'], 'wrong error stack'); + $this->wasCalled = true; + return 'my silly message'; + } + + function test_valid_msgcallbacksingleton() + { + if (!$this->_methodExists('staticPush')) { + return; + } + if (!$this->_methodExists('singleton')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + $this->stack = &PEAR_ErrorStack::singleton('test1', array(&$this, 'messagecallback')); + $this->wasCalled = false; + PEAR_ErrorStack::staticPush('test1', 4, 'error', array('hello' => 6)); + $this->assertTrue($this->wasCalled, 'message callback was not called!'); + $err = $this->stack->pop(); + unset($err['time']); + unset($err['context']); + $this->assertEquals( + array( + 'code' => 4, + 'params' => array('hello' => 6), + 'package' => 'test1', + 'message' => 'my silly message', + 'level' => 'error', + ), + $err, 'popped something else' + ); + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function test_valid_msgcallback_setmsgcallback() + { + if (!$this->_methodExists('staticPush')) { + return; + } + if (!$this->_methodExists('singleton')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + if (!$this->_methodExists('setContextCallback')) { + return; + } + $this->stack = &PEAR_ErrorStack::singleton('test1'); + $this->stack->setMessageCallback(array(&$this, 'messagecallback')); + $this->wasCalled = false; + PEAR_ErrorStack::staticPush('test1', 4, 'error', array('hello' => 6)); + $this->assertTrue($this->wasCalled, 'message callback was not called!'); + $err = $this->stack->pop(); + unset($err['time']); + unset($err['context']); + $this->assertEquals( + array( + 'code' => 4, + 'params' => array('hello' => 6), + 'package' => 'test1', + 'message' => 'my silly message', + 'level' => 'error', + ), + $err, 'popped something else' + ); + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } +} + +?> diff --git a/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_singleton.php b/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_singleton.php new file mode 100644 index 0000000000..0a052f17f1 --- /dev/null +++ b/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_singleton.php @@ -0,0 +1,93 @@ + portions from HTML_CSS + * @author Greg Beaver + * @package PEAR_ErrorStack + */ + +/** + * @package PEAR_ErrorStack + */ + +class PEAR_ErrorStack_TestCase_singleton extends PHPUnit_TestCase +{ + /** + * A PEAR_PackageFileManager object + * @var object + */ + var $packagexml; + + function PEAR_ErrorStack_TestCase_singleton($name) + { + $this->PHPUnit_TestCase($name); + } + + function setUp() + { + error_reporting(E_ALL); + $this->errorOccured = false; + set_error_handler(array(&$this, 'errorHandler')); + $this->stack = new PEAR_ErrorStack(''); + $s = &PEAR_ErrorStack::singleton('PEAR_ErrorStack'); + $s->pushCallback(array('PEAR_ErrorStack', '_handleError')); + } + + function tearDown() + { + } + + + function _stripWhitespace($str) + { + return preg_replace('/\\s+/', '', $str); + } + + function _methodExists($name) + { + if (in_array(strtolower($name), get_class_methods($this->stack))) { + return true; + } + $this->assertTrue(false, 'method '. $name . ' not implemented in ' . get_class($this->stack)); + return false; + } + + function errorHandler($errno, $errstr, $errfile, $errline) { + //die("$errstr in $errfile at line $errline: $errstr"); + $this->errorOccured = true; + $this->assertTrue(false, "$errstr at line $errline, $errfile"); + } + + function test_valid_singleton() + { + if (!$this->_methodExists('singleton')) { + return; + } + $one = &PEAR_ErrorStack::singleton('first'); + $two = &PEAR_ErrorStack::singleton('first'); + $two->testme = 2; + $this->assertEquals(2, $two->testme, 'duh test'); + $one->testme = 4; + $this->assertEquals(4, $one->testme, 'duh test 2'); + $this->assertEquals(4, $two->testme, 'same object test'); + } + + function test_invalid_singleton() + { + if (!$this->_methodExists('singleton')) { + return; + } + $one = &PEAR_ErrorStack::singleton('first'); + $two = &PEAR_ErrorStack::singleton('second'); + $two->testme = 2; + $this->assertEquals(2, $two->testme, 'duh test'); + $one->testme = 4; + $this->assertEquals(4, $one->testme, 'duh test 2'); + $this->assertEquals(2, $two->testme, 'not same object test'); + } +} + +?> diff --git a/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_staticGetErrors.php b/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_staticGetErrors.php new file mode 100644 index 0000000000..d96480d442 --- /dev/null +++ b/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_staticGetErrors.php @@ -0,0 +1,225 @@ + portions from HTML_CSS + * @author Greg Beaver + * @package PEAR_ErrorStack + */ + +/** + * @package PEAR_ErrorStack + */ + +class PEAR_ErrorStack_TestCase_staticGetErrors extends PHPUnit_TestCase +{ + + function PEAR_ErrorStack_TestCase_staticGetErrors($name) + { + $this->PHPUnit_TestCase($name); + } + + function setUp() + { + error_reporting(E_ALL); + $this->errorOccured = false; + set_error_handler(array(&$this, 'errorHandler')); + $this->stack = &PEAR_ErrorStack::singleton('test'); + $s = &PEAR_ErrorStack::singleton('PEAR_ErrorStack'); + $s->pushCallback(array('PEAR_ErrorStack', '_handleError')); + } + + function tearDown() + { + unset($this->stack); + unset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON']); + } + + + function _stripWhitespace($str) + { + return preg_replace('/\\s+/', '', $str); + } + + function _methodExists($name) + { + if (in_array(strtolower($name), get_class_methods($this->stack))) { + return true; + } + $this->assertTrue(false, 'method '. $name . ' not implemented in ' . get_class($this->stack)); + return false; + } + + function errorHandler($errno, $errstr, $errfile, $errline) { + //die("$errstr in $errfile at line $errline: $errstr"); + $this->errorOccured = true; + $this->assertTrue(false, "$errstr at line $errline, $errfile"); + } + + function returnsignore($err) + { + $this->wasCalled = true; + return PEAR_ERRORSTACK_IGNORE; + } + + function test_none() + { + if (!$this->_methodExists('staticGetErrors')) { + return; + } + $this->assertEquals(array(), PEAR_ErrorStack::staticGetErrors()); + $this->assertEquals(array(), PEAR_ErrorStack::staticGetErrors(true)); + } + + function test_normal() + { + if (!$this->_methodExists('staticGetErrors')) { + return; + } + $this->assertEquals(array(), PEAR_ErrorStack::staticGetErrors()); + $this->stack->push(1); + $this->stack->push(2, 'warning'); + $this->stack->push(3, 'foo'); + $ret = PEAR_ErrorStack::staticGetErrors(); + for ($i= 0; $i < 3; $i++) { + unset($ret['test'][$i]['time']); + unset($ret['test'][$i]['context']); + } + $this->assertEquals( + array( 'test' => array( + array('code' => 3, + 'params' => array(), + 'package' => 'test', + 'level' => 'foo', + 'message' => ''), + array('code' => 2, + 'params' => array(), + 'package' => 'test', + 'level' => 'warning', + 'message' => ''), + array('code' => 1, + 'params' => array(), + 'package' => 'test', + 'level' => 'error', + 'message' => ''), + )), $ret, 'incorrect errors, non-purge'); + $ret = PEAR_ErrorStack::staticGetErrors(true); + for ($i= 0; $i < 3; $i++) { + unset($ret['test'][$i]['time']); + unset($ret['test'][$i]['context']); + } + $this->assertEquals( + array( 'test' => array( + array('code' => 3, + 'params' => array(), + 'package' => 'test', + 'level' => 'foo', + 'message' => ''), + array('code' => 2, + 'params' => array(), + 'package' => 'test', + 'level' => 'warning', + 'message' => ''), + array('code' => 1, + 'params' => array(), + 'package' => 'test', + 'level' => 'error', + 'message' => ''), + )), $ret, 'incorrect errors, purge'); + $this->assertEquals(array(), PEAR_ErrorStack::staticGetErrors()); + } + + function test_merge() + { + if (!$this->_methodExists('staticGetErrors')) { + return; + } + $this->assertEquals(array(), PEAR_ErrorStack::staticGetErrors()); + $this->stack->push(1); + for($i=0;$i<10000;$i++); + $this->stack->push(2, 'warning'); + for($i=0;$i<10000;$i++); + PEAR_ErrorStack::staticPush('fronk', 3, 'foo'); + $ret = PEAR_ErrorStack::staticGetErrors(true, true); + for ($i= 0; $i < 3; $i++) { + unset($ret[$i]['time']); + unset($ret[$i]['context']); + } + $this->assertEquals( + array( + array('code' => 3, + 'params' => array(), + 'package' => 'fronk', + 'level' => 'foo', + 'message' => ''), + array('code' => 2, + 'params' => array(), + 'package' => 'test', + 'level' => 'warning', + 'message' => ''), + array('code' => 1, + 'params' => array(), + 'package' => 'test', + 'level' => 'error', + 'message' => ''), + ), $ret, 'incorrect errors, non-purge'); + $test = PEAR_ErrorStack::staticGetErrors(); + $this->assertEquals(array(), $test, 'normal array'); + } + + function _sortErrorsRev($a, $b) + { + $this->wasCalled = true; + if ($a['time'] == $b['time']) { + return 0; + } + if ($a['time'] < $b['time']) { + return -1; + } + return 1; + } + + function test_merge_sortfunc() + { + if (!$this->_methodExists('staticGetErrors')) { + return; + } + $this->assertEquals(array(), PEAR_ErrorStack::staticGetErrors()); + $this->stack->push(1); + for($i=0;$i<10000;$i++); + $this->stack->push(2, 'warning'); + for($i=0;$i<10000;$i++); + PEAR_ErrorStack::staticPush('fronk', 3, 'foo'); + $this->wasCalled = false; + $ret = PEAR_ErrorStack::staticGetErrors(true, true, array(&$this, '_sortErrorsRev')); + $this->assertTrue($this->wasCalled, '_sortErrorsRev not called!'); + for ($i= 0; $i < 3; $i++) { + unset($ret[$i]['time']); + unset($ret[$i]['context']); + } + $this->assertEquals( + array( + array('code' => 1, + 'params' => array(), + 'package' => 'test', + 'level' => 'error', + 'message' => ''), + array('code' => 2, + 'params' => array(), + 'package' => 'test', + 'level' => 'warning', + 'message' => ''), + array('code' => 3, + 'params' => array(), + 'package' => 'fronk', + 'level' => 'foo', + 'message' => ''), + ), $ret, 'incorrect errors, non-purge'); + $test = PEAR_ErrorStack::staticGetErrors(); + $this->assertEquals(array(), $test, 'normal array'); + } +} + +?> diff --git a/pear/tests/PEAR_ErrorStack/HTML_TestListener.php b/pear/tests/PEAR_ErrorStack/HTML_TestListener.php new file mode 100644 index 0000000000..a6b3ca6588 --- /dev/null +++ b/pear/tests/PEAR_ErrorStack/HTML_TestListener.php @@ -0,0 +1,64 @@ + + * @package HTML_CSS + */ + +class HTML_TestListener extends PHPUnit_TestListener { + + function HTML_TestListener() { + +$report = << +ClassFunctionSuccessMeta-result +EOS; + echo $report; + } + + function addError(&$test, &$t) { + $this->_errors += 1; + } + + function addFailure(&$test, &$t) { + $this->_fails += 1; + } + + function endTest(&$test) { + /* Report both the test result and, for this special situation + where some tests are expected to fail, a "meta" test result + which indicates whether the test result matches the + expected result. + */ + $expect_failure = preg_match('/fail/i', $test->getName()); + $test_passed = ($this->_fails == 0 && $this->_errors == 0); + + if ($this->_errors > 0) { + $outcome = "ERROR"; + } else if ($this->_fails > 0) { + $outcome = "FAIL"; + } else { + $outcome = "OK"; + } + if ($this->_errors > 0) { + $meta_outcome = 'unknown'; + } else { + $meta_outcome = ($expect_failure xor $test_passed) + ? 'as expected' + : 'UNEXPECTED'; + } + printf("$outcome$meta_outcome"); + } + + function startTest(&$test) { + $this->_fails = 0; + $this->_errors = 0; + printf("%s %s ", get_class($test), $test->getName()); + } + + +} +?> \ No newline at end of file diff --git a/pear/tests/PEAR_ErrorStack/TestUnit.php b/pear/tests/PEAR_ErrorStack/TestUnit.php new file mode 100644 index 0000000000..1fe703f664 --- /dev/null +++ b/pear/tests/PEAR_ErrorStack/TestUnit.php @@ -0,0 +1,55 @@ + + * @package HTML_CSS + */ + +require_once 'PHPUnit.php'; + +class TestUnit extends PHPUnit { + + function &run(&$suite, $listener) { + $result = new TestResult(); + $result->addListener($listener); + $suite->run($result); + + return $result; + } +} + +class TestResult extends PHPUnit_TestResult { + + /* report result of test run */ + function report() { + echo ""; + + $nRun = $this->runCount(); + $nErrors = $this->errorCount(); + $nFailures = $this->failureCount(); + echo "

Summary

"; + + printf("

%s test%s run.
", $nRun, ($nRun > 1) ? 's' : ''); + printf("%s error%s.
\n", $nErrors, ($nErrors > 1) ? 's' : ''); + printf("%s failure%s.
\n", $nFailures, ($nFailures > 1) ? 's' : ''); + if ($nFailures > 0) { + echo "

Failure Details

"; + print("
    \n"); + $failures = $this->failures(); + while (list($i, $failure) = each($failures)) { + $failedTest = $failure->failedTest(); + printf("
  1. %s\n", $failedTest->getName() ); + print("
      "); + printf("
    • %s\n", $failure->thrownException() ); + print("
    "); + } + print("
\n"); + } + } + +} +?> diff --git a/pear/tests/PEAR_ErrorStack/base_regression.php b/pear/tests/PEAR_ErrorStack/base_regression.php new file mode 100644 index 0000000000..16e9eeb302 --- /dev/null +++ b/pear/tests/PEAR_ErrorStack/base_regression.php @@ -0,0 +1,550 @@ + + */ +require_once 'PEAR/ErrorStack.php'; +$result = array( +'passed' => array(), +'failed' => array() +); +$stack = &PEAR_ErrorStack::singleton('test'); +$testNumber = 1; +// test basic global file/line +$stack->push(3); +$testline = __LINE__ - 1; + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'function' => 'include_once', + 'line' => $testline)); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test basic in-function file/line #2 +function testfunc() { global $stack, $testline; +$stack->push(3); +$testline = __LINE__ - 1; +} +testfunc(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'testfunc')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test basic in-static method file/line #3 +class stclass { +function stfunc() { global $stack, $testline; +$stack->push(3); +$testline = __LINE__ - 1; +} +} +stclass::stfunc(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'stfunc', + 'class' => 'stclass')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test basic in-method file/line #4 +class normalclass { +function normalfunc() { global $stack, $testline; +$stack->push(3); +$testline = __LINE__ - 1; +} +} +$z = new normalclass; +$z->normalfunc(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'normalfunc', + 'class' => 'normalclass')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test global eval file/line #5 +eval('$stack->push(3);'); +$testline = __LINE__ - 1; + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'function' => 'include_once', + 'line' => $testline)); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test in-function eval file/line #6 +function test2() { + global $testline, $stack; +eval('$stack->push(3);'); +$testline = __LINE__ - 1; +} +test2(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'test2')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test in-static method eval file/line #7 +class test3 { +function test3() { + global $testline, $stack; +eval('$stack->push(3);'); +$testline = __LINE__ - 1; +} +} +test3::test3(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'test3', + 'class' => 'test3')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test in-method eval file/line #8 +class test4 { +function test4() { + global $testline, $stack; +eval('$stack->push(3);'); +$testline = __LINE__ - 1; +} +} +$z = new test4; +$z->test4(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'test4', + 'class' => 'test4')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test global create_function file/line #9 +$a = create_function('', '$GLOBALS["stack"]->push(3);'); +$testline = __LINE__ - 1; +$a(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'create_function() code')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test in-function create_function file/line #10 +function test7() { global $a; +$a(); +} +test7(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'create_function() code')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test in-static method create_function file/line #11 +class test8 { +function test8() { global $a; +$a(); +} +} +test8::test8(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'create_function() code')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test in-method create_function file/line #12 +class test9 { +function test9() { global $a; +$a(); +} +} +$z = new test9; +$z->test9(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'create_function() code')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$result['number'] = $testNumber; + +$testNumber++; +// test static basic global file/line #13 +PEAR_ErrorStack::staticPush('test', 3); +$testline = __LINE__ - 1; + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'function' => 'include_once', + 'line' => $testline)); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test static basic in-function file/line #14 +function testfunc2() { global $stack, $testline; +PEAR_ErrorStack::staticPush('test', 3); +$testline = __LINE__ - 1; +} +testfunc2(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'testfunc2')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test static basic in-static method file/line #15 +class stclass2 { +function stfunc() { global $stack, $testline; +PEAR_ErrorStack::staticPush('test', 3); +$testline = __LINE__ - 1; +} +} +stclass2::stfunc(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'stfunc', + 'class' => 'stclass2')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test static basic in-method file/line #16 +class normalclass2 { +function normalfunc() { global $stack, $testline; +PEAR_ErrorStack::staticPush('test', 3); +$testline = __LINE__ - 1; +} +} +$z = new normalclass2; +$z->normalfunc(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'normalfunc', + 'class' => 'normalclass2')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test static global eval file/line #17 +eval('PEAR_ErrorStack::staticPush(\'test\', 3);'); +$testline = __LINE__ - 1; + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'function' => 'include_once', + 'line' => $testline)); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test static in-function eval file/line #18 +function test22() { + global $testline, $stack; +eval('PEAR_ErrorStack::staticPush("test", 3);'); +$testline = __LINE__ - 1; +} +test22(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'test22')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test static in-static method eval file/line #19 +class test32 { +function test3() { + global $testline, $stack; +eval('PEAR_ErrorStack::staticPush(\'test\',3);'); +$testline = __LINE__ - 1; +} +} +test32::test3(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'test3', + 'class' => 'test32')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test static in-method eval file/line #20 +class test42 { +function test4() { + global $testline, $stack; +eval('PEAR_ErrorStack::staticPush(\'test\',3);'); +$testline = __LINE__ - 1; +} +} +$z = new test42; +$z->test4(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'test4', + 'class' => 'test42')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test static global create_function file/line #21 +$a = create_function('', 'PEAR_ErrorStack::staticPush("test",3);'); +$testline = __LINE__ - 1; +$a(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'create_function() code')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test static in-function create_function file/line #22 +function test72() { global $a; +$a(); +} +test72(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'create_function() code')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test static in-static method create_function file/line #23 +class test82 { +function test8() { global $a; +$a(); +} +} +test82::test8(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'create_function() code')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test static in-method create_function file/line #24 +class test92 { +function test9() { global $a; +$a(); +} +} +$z = new test92; +$z->test9(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'create_function() code')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$result['number'] = $testNumber; + +return $result; +/** + * Utility function + */ +function isIncludeable($path) +{ + if (file_exists(realpath($path)) && is_readable(realpath($path))) { + return true; + } + foreach (explode(PATH_SEPARATOR, get_include_path()) as $prepend) { + $test = realpath($prepend . DIRECTORY_SEPARATOR . $path); + if (file_exists($test) && is_readable($test)) { + return true; + } + } +} +/** + * Mock PHPUnit object + */ +class Mock_PHPUnit { + var $name; + function getName() + { + return 'base regression test ' . $this->name; + } +} +?> \ No newline at end of file diff --git a/pear/tests/PEAR_ErrorStack/stylesheet.css b/pear/tests/PEAR_ErrorStack/stylesheet.css new file mode 100644 index 0000000000..47b9f92b2a --- /dev/null +++ b/pear/tests/PEAR_ErrorStack/stylesheet.css @@ -0,0 +1,65 @@ +/* $Id$ */ + +body { + font:normal 68% verdana,arial,helvetica; + color:#000000; +} +table tr td, table tr th { + font-size: 68%; +} +table.details tr th{ + font-weight: bold; + text-align:left; + background:#a6caf0; +} +table.details tr{ + background:#eeeee0; +} + +p { + line-height:1.5em; + margin-top:0.5em; margin-bottom:1.0em; +} +h1 { + margin: 0px 0px 5px; font: 165% verdana,arial,helvetica +} +h2 { + margin-top: 1em; margin-bottom: 0.5em; font: bold 125% verdana,arial,helvetica +} +h3 { + margin-bottom: 0.5em; font: bold 115% verdana,arial,helvetica +} +h4 { + margin-bottom: 0.5em; font: bold 100% verdana,arial,helvetica +} +h5 { + margin-bottom: 0.5em; font: bold 100% verdana,arial,helvetica +} +h6 { + margin-bottom: 0.5em; font: bold 100% verdana,arial,helvetica +} +.Error { + font-weight:bold; color:red; +} +.Failure, .Unexpected { + background:#ff0000; font-weight:bold; color:black; +} +.Unknown { + background:#ffff00; font-weight:bold; color:black; +} +.Pass, .Expected { + background:#00ff00; font-weight:bold; color:black; +} +.Properties { + text-align:right; +} + +CODE.expected { + color: green; background: none; font-weight: normal; +} +CODE.actual { + color: red; background: none; font-weight: normal; +} +.typeinfo { + color: gray; +} diff --git a/pear/tests/PEAR_ErrorStack/testsuite.php b/pear/tests/PEAR_ErrorStack/testsuite.php new file mode 100644 index 0000000000..1899142746 --- /dev/null +++ b/pear/tests/PEAR_ErrorStack/testsuite.php @@ -0,0 +1,152 @@ + + * @package HTML_CSS + */ + +require_once 'TestUnit.php'; +require_once 'HTML_TestListener.php'; +require_once 'PEAR/ErrorStack.php'; + +$title = 'PhpUnit test run, PEAR_ErrorStack package'; +?> + + +<?php echo $title; ?> + + + +

+

+ This page runs all the phpUnit self-tests, and produces nice HTML output. +

+

+ Unlike typical test run, expect many test cases to + fail. Exactly those with pass in their name + should succeed. +

+

+ For each test we display both the test result -- ok, FAIL, or + ERROR -- and also a meta-result -- + as expected, UNEXPECTED, or unknown -- that indicates whether the + expected test result occurred. Although many test results will + be 'FAIL' here, all meta-results should be 'as expected', except + for a few 'unknown' meta-results (because of errors) when running + in PHP3. +

+ +

Tests

+ testcase = &$testcase; + } + + function curMethod($method) + { + $this->method = $method; + } + + function pushExpect($message, $priority, $errarray) + { + unset($errarray['time']); + unset($errarray['context']); + array_push($this->expect, array($message, $priority, $errarray)); + } + + function clearExpect() + { + $this->expect = array(); + } + + function log($message, $priority, $errarray) + { + $this->testcase->wasLogged = true; + if (!is_a($this->testcase, 'PHPUnit_TestCase')) { + trigger_error('ERROR: burflog never set up', E_USER_ERROR); + return; + } + if (!isset($this->method)) { + $this->testcase->assertFalse(true, 'ERROR: burflog never set up'); + return; + } + if (!count($this->expect)) { + $this->testcase->assertFalse(true, "method $this->method: logged, but no log expected"); + $this->testcase->assertFalse(true, "method $this->method: log message = $message"); + $this->testcase->assertFalse(true, "method $this->method: log priority = $priority"); + return; + } + unset($errarray['time']); + unset($errarray['context']); + $expect = array_pop($this->expect); + $this->testcase->assertEquals($expect[0], $message, "method $this->method: wrong message"); + $this->testcase->assertEquals($expect[1], $priority, "method $this->method: wrong priority"); + $this->testcase->assertEquals($expect[2], $errarray, "method $this->method: wrong errarray"); + } +} + + $suite = new PHPUnit_TestSuite(); + + foreach ($testcases as $testcase) { + include_once $testcase . '.php'; + $suite->addTestSuite($testcase); + } + + $listener = new HTML_TestListener(); + $finalresult = TestUnit::run($suite, $listener); + $results = include_once dirname(__FILE__) . '/base_regression.php'; + $num = $results['number']; + $failed = $results['failed']; + $passed = $results['passed']; + for ($i = 1; $i <= $num; $i++) { + $bla = new Mock_PHPUnit; + $bla->name = $i; + $listener->startTest($bla); + if (isset($failed[$i])) { + $listener->addFailure($bla, $failed[$i]); + $finalresult->addFailure($bla, $a = 'context had additional ' . serialize($failed[$i])); + } + $listener->endTest($bla); + } + + $finalresult->removeListener($listener); + // hack in the base regression test count + $finalresult->_runTests += count($results['failed']) + count($results['passed']); + $finalresult->report(); + + ?> + + -- 2.40.0