summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSVN Migration <svn@php.net>2004-03-19 00:48:40 +0000
committerSVN Migration <svn@php.net>2004-03-19 00:48:40 +0000
commitc6b98d3891ed795a1d8e080b90c840d05e666640 (patch)
treeea5abd07e7e77ae9b58dd856109db7061ad16f1e
parent8621923a5e9b377c534bf1e4a0ee57483e54d15e (diff)
downloadphp-git-c6b98d3891ed795a1d8e080b90c840d05e666640.tar.gz
This commit was manufactured by cvs2svn to create branch 'PHP_4_3'.
-rw-r--r--ext/standard/tests/serialize/bug27469.phpt27
-rw-r--r--pear/PEAR/ErrorStack.php889
-rw-r--r--pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_getErrorMessage.php142
-rw-r--r--pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_getErrorMessageTemplate.php88
-rw-r--r--pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_getErrors.php135
-rw-r--r--pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_pushpop.php367
-rw-r--r--pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_pushpopcallback.php320
-rw-r--r--pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_pushpopstatic.php327
-rw-r--r--pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_singleton.php93
-rw-r--r--pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_staticGetErrors.php225
-rw-r--r--pear/tests/PEAR_ErrorStack/HTML_TestListener.php64
-rw-r--r--pear/tests/PEAR_ErrorStack/TestUnit.php55
-rw-r--r--pear/tests/PEAR_ErrorStack/base_regression.php550
-rw-r--r--pear/tests/PEAR_ErrorStack/stylesheet.css65
-rw-r--r--pear/tests/PEAR_ErrorStack/testsuite.php152
15 files changed, 3499 insertions, 0 deletions
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--
+<?php
+$str = 'O:9:"TestClass":0:{}';
+$obj = unserialize($str);
+var_dump($obj);
+echo serialize($obj)."\n";
+var_dump($obj);
+echo serialize($obj)."\n";
+var_dump($obj);
+?>
+--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 @@
+<?php
+//
+// +----------------------------------------------------------------------+
+// | PHP Version 5 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2004 The PHP Group |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 3.0 of the PHP license, |
+// | that is bundled with this package in the file LICENSE, and is |
+// | available through the world-wide-web at the following url: |
+// | http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +----------------------------------------------------------------------+
+// | Author: Gregory Beaver <cellog@php.net> |
+// | |
+// +----------------------------------------------------------------------+
+//
+// $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 <cellog@php.net>
+ * @version 0.6alpha
+ * @package PEAR_ErrorStack
+ * @category Debugging
+ * @license http://www.php.net/license/3_0.txt PHP License v3.0
+ */
+
+/**
+ * Singleton storage
+ *
+ * Format:
+ * <pre>
+ * array(
+ * 'package1' => PEAR_ErrorStack object,
+ * 'package2' => PEAR_ErrorStack object,
+ * ...
+ * )
+ * </pre>
+ * @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:
+ * <code>
+ * // global error stack
+ * $global_stack = &PEAR_ErrorStack::singleton('MyPackage');
+ * // local error stack
+ * $local_stack = new PEAR_ErrorStack('MyPackage');
+ * </code>
+ * @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 '<br />';
+ } 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:
+ * <code>
+ * throw ($stack->push(MY_ERROR_CODE, 'error', array('username' => 'grob')));
+ * </code>
+ *
+ * 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:
+ * <code>
+ * array(
+ * 'code' => $code,
+ * 'params' => $params,
+ * 'package' => $this->_package,
+ * 'level' => $level,
+ * 'time' => time(),
+ * 'context' => $context,
+ * 'message' => $msg,
+ * //['repackage' => $err] repackaged error array
+ * );
+ * </code>
+ */
+ 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:
+ * <code>
+ * throw ($stack->push(MY_ERROR_CODE, 'error', array('username' => 'grob')));
+ * </code>
+ * @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:
+ *
+ * <code>
+ * $stack->push(ERROR_CODE, 'error', array(), 'server error 500');
+ * </code>
+ *
+ * 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:
+ * <pre>
+ * array(error code => 'message template',...)
+ * </pre>
+ *
+ * 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 @@
+<?php
+
+/**
+ * API Unit tests for PEAR_ErrorStack package.
+ *
+ * @version $Id$
+ * @author Laurent Laville <pear@laurent-laville.org> 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 @@
+<?php
+
+/**
+ * API Unit tests for PEAR_ErrorStack package.
+ *
+ * @version $Id$
+ * @author Laurent Laville <pear@laurent-laville.org> 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 @@
+<?php
+
+/**
+ * API Unit tests for PEAR_ErrorStack package.
+ *
+ * @version $Id$
+ * @author Laurent Laville <pear@laurent-laville.org> 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 @@
+<?php
+
+/**
+ * API Unit tests for PEAR_ErrorStack package.
+ *
+ * @version $Id$
+ * @author Laurent Laville <pear@laurent-laville.org> 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 @@
+<?php
+
+/**
+ * API Unit tests for PEAR_ErrorStack package.
+ *
+ * @version $Id$
+ * @author Laurent Laville <pear@laurent-laville.org> 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 @@
+<?php
+
+/**
+ * API Unit tests for PEAR_ErrorStack package.
+ *
+ * @version $Id$
+ * @author Laurent Laville <pear@laurent-laville.org> 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 @@
+<?php
+
+/**
+ * API Unit tests for PEAR_ErrorStack package.
+ *
+ * @version $Id$
+ * @author Laurent Laville <pear@laurent-laville.org> 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 @@
+<?php
+
+/**
+ * API Unit tests for PEAR_ErrorStack package.
+ *
+ * @version $Id$
+ * @author Laurent Laville <pear@laurent-laville.org> 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 @@
+<?php
+
+/**
+ * Provides a nice HTML output for PHPUnit suite tests.
+ *
+ * @version $Id$
+ * @author Laurent Laville <pear@laurent-laville.org>
+ * @package HTML_CSS
+ */
+
+class HTML_TestListener extends PHPUnit_TestListener {
+
+ function HTML_TestListener() {
+
+$report = <<<EOS
+<table cellspacing="1" cellpadding="1" border="0" width="90%" align="center" class="details">
+<tr><th>Class</th><th>Function</th><th>Success</th><th>Meta-result</th></tr>
+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 = "<span class=\"Error\">ERROR</span>";
+ } else if ($this->_fails > 0) {
+ $outcome = "<span class=\"Failure\">FAIL</span>";
+ } else {
+ $outcome = "<span class=\"Pass\">OK</span>";
+ }
+ if ($this->_errors > 0) {
+ $meta_outcome = '<span class="Unknown">unknown</span>';
+ } else {
+ $meta_outcome = ($expect_failure xor $test_passed)
+ ? '<span class="Expected">as expected</span>'
+ : '<span class="Unexpected">UNEXPECTED</span>';
+ }
+ printf("<td>$outcome</td><td>$meta_outcome</td></tr>");
+ }
+
+ function startTest(&$test) {
+ $this->_fails = 0;
+ $this->_errors = 0;
+ printf("<tr><td>%s </td><td>%s </td>", 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 @@
+<?php
+
+/**
+ * TestUnit runs a TestSuite and returns a TestResult object.
+ * And more than PHPUnit attach a listener to TestResult.
+ *
+ * @version $Id$
+ * @author Laurent Laville <pear@laurent-laville.org>
+ * @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 "</TABLE>";
+
+ $nRun = $this->runCount();
+ $nErrors = $this->errorCount();
+ $nFailures = $this->failureCount();
+ echo "<h2>Summary</h2>";
+
+ printf("<p>%s test%s run.<br>", $nRun, ($nRun > 1) ? 's' : '');
+ printf("%s error%s.<br>\n", $nErrors, ($nErrors > 1) ? 's' : '');
+ printf("%s failure%s.<br>\n", $nFailures, ($nFailures > 1) ? 's' : '');
+ if ($nFailures > 0) {
+ echo "<h2>Failure Details</h2>";
+ print("<ol>\n");
+ $failures = $this->failures();
+ while (list($i, $failure) = each($failures)) {
+ $failedTest = $failure->failedTest();
+ printf("<li>%s\n", $failedTest->getName() );
+ print("<ul>");
+ printf("<li>%s\n", $failure->thrownException() );
+ print("</ul>");
+ }
+ print("</ol>\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 @@
+<?php
+// $Revision$
+/**
+ * Basic regression test for PEAR_ErrorStack::getFileLine()
+ *
+ * phpUnit can't test global code properly because of its design, so I designed
+ * this instead
+ * @package PEAR_ErrorStack
+ * @subpackage tests
+ * @author Greg Beaver <cellog@php.net>
+ */
+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 @@
+<?php
+
+/**
+ * HTML output for PHPUnit suite tests.
+ *
+ * Copied for PEAR_PackageFileManager from HTML_CSS
+ * @version $Id$
+ * @author Laurent Laville <pear@laurent-laville.org>
+ * @package HTML_CSS
+ */
+
+require_once 'TestUnit.php';
+require_once 'HTML_TestListener.php';
+require_once 'PEAR/ErrorStack.php';
+
+$title = 'PhpUnit test run, PEAR_ErrorStack package';
+?>
+<html>
+<head>
+<title><?php echo $title; ?></title>
+<link rel="stylesheet" href="stylesheet.css" type="text/css" />
+</head>
+<body>
+<h1><?php echo $title; ?></h1>
+ <p>
+ This page runs all the phpUnit self-tests, and produces nice HTML output.
+ </p>
+ <p>
+ Unlike typical test run, <strong>expect many test cases to
+ fail</strong>. Exactly those with <code>pass</code> in their name
+ should succeed.
+ </p>
+ <p>
+ For each test we display both the test result -- <span
+ class="Pass">ok</span>, <span class="Failure">FAIL</span>, or
+ <span class="Error">ERROR</span> -- and also a meta-result --
+ <span class="Expected">as expected</span>, <span
+ class="Unexpected">UNEXPECTED</span>, or <span
+ class="Unknown">unknown</span> -- 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.
+ </p>
+
+<h2>Tests</h2>
+ <?php
+ $testcases = array(
+ 'PEAR_ErrorStack_TestCase_singleton',
+ 'PEAR_ErrorStack_TestCase_pushpop',
+ 'PEAR_ErrorStack_TestCase_pushpopstatic',
+ 'PEAR_ErrorStack_TestCase_pushpopcallback',
+ 'PEAR_ErrorStack_TestCase_getErrorMessage',
+ 'PEAR_ErrorStack_TestCase_getErrorMessageTemplate',
+ 'PEAR_ErrorStack_TestCase_getErrors',
+ 'PEAR_ErrorStack_TestCase_staticGetErrors',
+ );
+define('PEAR_LOG_EMERG', 0); /** System is unusable */
+define('PEAR_LOG_ALERT', 1); /** Immediate action required */
+define('PEAR_LOG_CRIT', 2); /** Critical conditions */
+define('PEAR_LOG_ERR', 3); /** Error conditions */
+define('PEAR_LOG_WARNING', 4); /** Warning conditions */
+define('PEAR_LOG_NOTICE', 5); /** Normal but significant */
+define('PEAR_LOG_INFO', 6); /** Informational */
+define('PEAR_LOG_DEBUG', 7); /** Debug-level messages */
+/**
+* Mock Log object
+*/
+class BurfLog {
+ var $testcase;
+ var $method;
+ var $expect = array();
+ function setTestCase(&$testcase)
+ {
+ $this->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();
+
+ ?>
+</body>
+</html>