From 2b1ce3826eb480adda6bdf37afb4ef66d6865f84 Mon Sep 17 00:00:00 2001 From: Chuck Hagenbuch Date: Thu, 6 Nov 2008 21:26:43 -0500 Subject: [PATCH] move Horde_Log to git --- framework/Log/lib/Horde/Log.php | 46 +++++ framework/Log/lib/Horde/Log/Exception.php | 30 ++++ framework/Log/lib/Horde/Log/Filter/Interface.php | 35 ++++ framework/Log/lib/Horde/Log/Filter/Level.php | 53 ++++++ framework/Log/lib/Horde/Log/Filter/Message.php | 57 ++++++ .../Log/lib/Horde/Log/Formatter/Interface.php | 31 ++++ framework/Log/lib/Horde/Log/Formatter/Simple.php | 71 ++++++++ framework/Log/lib/Horde/Log/Formatter/Xml.php | 59 +++++++ framework/Log/lib/Horde/Log/Handler/Base.php | 95 ++++++++++ framework/Log/lib/Horde/Log/Handler/Db.php | 76 ++++++++ framework/Log/lib/Horde/Log/Handler/Firebug.php | 122 +++++++++++++ framework/Log/lib/Horde/Log/Handler/Null.php | 35 ++++ framework/Log/lib/Horde/Log/Handler/Stream.php | 84 +++++++++ framework/Log/lib/Horde/Log/Logger.php | 191 +++++++++++++++++++++ framework/Log/package.xml | 94 ++++++++++ framework/Log/test/Horde/Log/AllTests.php | 70 ++++++++ .../Log/test/Horde/Log/Filter/ChainingTest.php | 79 +++++++++ framework/Log/test/Horde/Log/Filter/LevelTest.php | 55 ++++++ .../Log/test/Horde/Log/Filter/MessageTest.php | 45 +++++ .../Log/test/Horde/Log/Formatter/SimpleTest.php | 48 ++++++ framework/Log/test/Horde/Log/Formatter/XmlTest.php | 55 ++++++ framework/Log/test/Horde/Log/Handler/DbTest.php | 84 +++++++++ .../Log/test/Horde/Log/Handler/FirebugTest.php | 61 +++++++ framework/Log/test/Horde/Log/Handler/NullTest.php | 32 ++++ .../Log/test/Horde/Log/Handler/StreamTest.php | 125 ++++++++++++++ framework/Log/test/Horde/Log/LogTest.php | 147 ++++++++++++++++ 26 files changed, 1880 insertions(+) create mode 100644 framework/Log/lib/Horde/Log.php create mode 100644 framework/Log/lib/Horde/Log/Exception.php create mode 100644 framework/Log/lib/Horde/Log/Filter/Interface.php create mode 100644 framework/Log/lib/Horde/Log/Filter/Level.php create mode 100644 framework/Log/lib/Horde/Log/Filter/Message.php create mode 100644 framework/Log/lib/Horde/Log/Formatter/Interface.php create mode 100644 framework/Log/lib/Horde/Log/Formatter/Simple.php create mode 100644 framework/Log/lib/Horde/Log/Formatter/Xml.php create mode 100644 framework/Log/lib/Horde/Log/Handler/Base.php create mode 100644 framework/Log/lib/Horde/Log/Handler/Db.php create mode 100644 framework/Log/lib/Horde/Log/Handler/Firebug.php create mode 100644 framework/Log/lib/Horde/Log/Handler/Null.php create mode 100644 framework/Log/lib/Horde/Log/Handler/Stream.php create mode 100644 framework/Log/lib/Horde/Log/Logger.php create mode 100644 framework/Log/package.xml create mode 100644 framework/Log/test/Horde/Log/AllTests.php create mode 100644 framework/Log/test/Horde/Log/Filter/ChainingTest.php create mode 100644 framework/Log/test/Horde/Log/Filter/LevelTest.php create mode 100644 framework/Log/test/Horde/Log/Filter/MessageTest.php create mode 100644 framework/Log/test/Horde/Log/Formatter/SimpleTest.php create mode 100644 framework/Log/test/Horde/Log/Formatter/XmlTest.php create mode 100644 framework/Log/test/Horde/Log/Handler/DbTest.php create mode 100644 framework/Log/test/Horde/Log/Handler/FirebugTest.php create mode 100644 framework/Log/test/Horde/Log/Handler/NullTest.php create mode 100644 framework/Log/test/Horde/Log/Handler/StreamTest.php create mode 100644 framework/Log/test/Horde/Log/LogTest.php diff --git a/framework/Log/lib/Horde/Log.php b/framework/Log/lib/Horde/Log.php new file mode 100644 index 000000000..08d065c2f --- /dev/null +++ b/framework/Log/lib/Horde/Log.php @@ -0,0 +1,46 @@ + + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ + +/** + * @category Horde + * @package Horde_Log + */ +class Horde_Log { + + /** Emergency: system is unusable */ + const EMERG = 0; + + /** Alert: action must be taken immediately */ + const ALERT = 1; + + /** Critical: critical conditions */ + const CRIT = 2; + + /** Error: error conditions */ + const ERR = 3; + + /** Warning: warning conditions */ + const WARN = 4; + + /** Notice: normal but significant condition */ + const NOTICE = 5; + + /** Informational: informational messages */ + const INFO = 6; + + /** Debug: debug-level messages */ + const DEBUG = 7; + +} diff --git a/framework/Log/lib/Horde/Log/Exception.php b/framework/Log/lib/Horde/Log/Exception.php new file mode 100644 index 000000000..6f006d22a --- /dev/null +++ b/framework/Log/lib/Horde/Log/Exception.php @@ -0,0 +1,30 @@ + + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ + +/** + * @package Horde_Log + * @author Mike Naberezny + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ +class Horde_Log_Exception extends Exception +{ + /** + */ + public function __construct($msg, $code = 0) + { + parent::__construct($msg, $code); + } + +} diff --git a/framework/Log/lib/Horde/Log/Filter/Interface.php b/framework/Log/lib/Horde/Log/Filter/Interface.php new file mode 100644 index 000000000..48120cb9b --- /dev/null +++ b/framework/Log/lib/Horde/Log/Filter/Interface.php @@ -0,0 +1,35 @@ + + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ + +/** + * @category Horde + * @package Horde_Log + * @subpackage Filters + * @author Mike Naberezny + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ +interface Horde_Log_Filter_Interface +{ + /** + * Returns TRUE to accept the message, FALSE to block it. + * + * @param array $event Log event + * @return boolean accepted? + */ + public function accept($event); + +} diff --git a/framework/Log/lib/Horde/Log/Filter/Level.php b/framework/Log/lib/Horde/Log/Filter/Level.php new file mode 100644 index 000000000..8585b563a --- /dev/null +++ b/framework/Log/lib/Horde/Log/Filter/Level.php @@ -0,0 +1,53 @@ + + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ + +/** + * @package Horde_Log + * @author Mike Naberezny + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ +class Horde_Log_Filter_Level implements Horde_Log_Filter_Interface +{ + /** + * @var integer + */ + protected $_level; + + /** + * Filter out any log messages greater than $level. + * + * @param integer $level Maximum log level to pass through the filter + */ + public function __construct($level) + { + if (! is_integer($level)) { + throw new Horde_Log_Exception('Level must be an integer'); + } + + $this->_level = $level; + } + + /** + * Returns TRUE to accept the message, FALSE to block it. + * + * @param array $event Log event + * @return boolean accepted? + */ + public function accept($event) + { + return $event['level'] <= $this->_level; + } + +} diff --git a/framework/Log/lib/Horde/Log/Filter/Message.php b/framework/Log/lib/Horde/Log/Filter/Message.php new file mode 100644 index 000000000..74b6d0b05 --- /dev/null +++ b/framework/Log/lib/Horde/Log/Filter/Message.php @@ -0,0 +1,57 @@ + + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ + +/** + * @category Horde + * @package Horde_Log + * @subpackage Filters + * @author Mike Naberezny + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ +class Horde_Log_Filter_Message implements Horde_Log_Filter_Interface +{ + /** + * @var string + */ + protected $_regexp; + + /** + * Filter out any log messages not matching $regexp. + * + * @param string $regexp Regular expression to test the log message + * @throws Horde_Log_Exception Invalid regular expression + */ + public function __construct($regexp) + { + if (@preg_match($regexp, '') === false) { + throw new Horde_Log_Exception("Invalid regular expression '$regexp'"); + } + $this->_regexp = $regexp; + } + + /** + * Returns TRUE to accept the message, FALSE to block it. + * + * @param array $event Log event + * @return boolean accepted? + */ + public function accept($event) + { + return preg_match($this->_regexp, $event['message']) > 0; + } + +} diff --git a/framework/Log/lib/Horde/Log/Formatter/Interface.php b/framework/Log/lib/Horde/Log/Formatter/Interface.php new file mode 100644 index 000000000..0975abcb7 --- /dev/null +++ b/framework/Log/lib/Horde/Log/Formatter/Interface.php @@ -0,0 +1,31 @@ + + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ + +/** + * @package Horde_Log + * @author Mike Naberezny + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ +interface Horde_Log_Formatter_Interface +{ + /** + * Formats an event to be written by the handler. + * + * @param array $event Log event + * @return string formatted line + */ + public function format($event); + +} diff --git a/framework/Log/lib/Horde/Log/Formatter/Simple.php b/framework/Log/lib/Horde/Log/Formatter/Simple.php new file mode 100644 index 000000000..939f6a5f1 --- /dev/null +++ b/framework/Log/lib/Horde/Log/Formatter/Simple.php @@ -0,0 +1,71 @@ + + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ + +/** + * @category Horde + * @package Horde_Log + * @subpackage Formatters + * @author Mike Naberezny + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ +class Horde_Log_Formatter_Simple +{ + /** + * Format string + * + * @var string + */ + protected $_format; + + /** + * Constructor + */ + public function __construct($options = null) + { + if (is_array($options) && isset($options['format'])) { + $format = $options['format']; + } else { + $format = $options; + } + + if (is_null($format)) { + $format = '%timestamp% %levelName%: %message%' . PHP_EOL; + } + + if (!is_string($format)) { + throw new Horde_Log_Exception('Format must be a string'); + } + + $this->_format = $format; + } + + /** + * Formats an event to be written by the handler. + * + * @param array $event Log event + * @return string formatted line + */ + public function format($event) + { + $output = $this->_format; + foreach ($event as $name => $value) { + $output = str_replace("%$name%", $value, $output); + } + return $output; + } + +} diff --git a/framework/Log/lib/Horde/Log/Formatter/Xml.php b/framework/Log/lib/Horde/Log/Formatter/Xml.php new file mode 100644 index 000000000..9b3511942 --- /dev/null +++ b/framework/Log/lib/Horde/Log/Formatter/Xml.php @@ -0,0 +1,59 @@ + + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ + +/** + * @category Horde + * @package Horde_Log + * @subpackage Formatters + * @author Mike Naberezny + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ +class Horde_Log_Formatter_Xml +{ + protected $_options = array('elementEntry' => 'log', + 'elementTimestamp' => 'timestamp', + 'elementMessage' => 'message', + 'elementLevel' => 'level', + 'lineEnding' => PHP_EOL); + + public function __construct($options = array()) + { + $this->_options = array_merge($this->_options, $options); + } + + /** + * Formats an event to be written by the handler. + * + * @param array $event Log event + * @return string XML string + */ + public function format($event) + { + $dom = new DOMDocument(); + + $elt = $dom->appendChild(new DOMElement($this->_options['elementEntry'])); + $elt->appendChild(new DOMElement($this->_options['elementTimestamp'], date('c'))); + $elt->appendChild(new DOMElement($this->_options['elementMessage'], $event['message'])); + $elt->appendChild(new DOMElement($this->_options['elementLevel'], $event['level'])); + + $xml = $dom->saveXML(); + $xml = preg_replace('/<\?xml version="1.0"( encoding="[^\"]*")?\?>\n/u', '', $xml); + + return $xml . $this->_options['lineEnding']; + } + +} diff --git a/framework/Log/lib/Horde/Log/Handler/Base.php b/framework/Log/lib/Horde/Log/Handler/Base.php new file mode 100644 index 000000000..8279b0320 --- /dev/null +++ b/framework/Log/lib/Horde/Log/Handler/Base.php @@ -0,0 +1,95 @@ + + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ + +/** + * @category Horde + * @package Horde_Log + * @subpackage Handlers + * @author Mike Naberezny + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ +abstract class Horde_Log_Handler_Base +{ + /** + * @var array of key/value pair options + */ + protected $_options = array(); + + /** + * @var array of Horde_Log_Filter_Interface + */ + protected $_filters = array(); + + /** + * Add a filter specific to this handler. + * + * @param Horde_Log_Filter_Interface $filter + * @return void + */ + public function addFilter($filter) + { + if (is_integer($filter)) { + $filter = new Horde_Log_Filter_Level($filter); + } + + $this->_filters[] = $filter; + } + + /** + * Log a message to this handler. + * + * @param array $event Log event + * @return void + */ + public function log($event) + { + // if any local filter rejects the message, don't log it. + foreach ($this->_filters as $filter) { + if (!$filter->accept($event)) { + return; + } + } + + $this->write($event); + } + + /** + * Sets an option specific to the implementation of the log handler. + * + * @param $optionKey Key name for the option to be changed. Keys are handler-specific + * @param $optionValue New value to assign to the option + * @return bool True + */ + public function setOption($optionKey, $optionValue) + { + if (!isset($this->_options[$optionKey])) { + throw new Horde_Log_Exception("Unknown option \"$optionKey\"."); + } + $this->_options[$optionKey] = $optionValue; + + return true; + } + + /** + * Buffer a message to be stored in the storage + * implemented by this handler. + * + * @param array $event Log event + */ + abstract public function write($event); + +} diff --git a/framework/Log/lib/Horde/Log/Handler/Db.php b/framework/Log/lib/Horde/Log/Handler/Db.php new file mode 100644 index 000000000..6c545331d --- /dev/null +++ b/framework/Log/lib/Horde/Log/Handler/Db.php @@ -0,0 +1,76 @@ + + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ + +/** + * @category Horde + * @package Horde_Log + * @subpackage Handlers + * @author Mike Naberezny + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ +class Horde_Log_Handler_Db extends Horde_Log_Handler_Base +{ + /** + * Database adapter instance + * @var Horde_Db_Adapter + */ + private $_db; + + /** + * Name of the log table in the database + * @var string + */ + private $_table; + + /** + * Options to be set by setOption(). Sets the field names in the database table. + * + * @var array + */ + protected $_options = array('fieldMessage' => 'message', + 'fieldLevel' => 'level'); + + /** + * Class constructor + * + * @param Horde_Db_Adapter $db Database adapter instance + * @param string $table Log table in database + */ + public function __construct($db, $table) + { + $this->_db = $db; + $this->_table = $table; + } + + /** + * Write a message to the log. + * + * @param array $event Log event + * @return bool Always True + */ + public function write($event) + { + $fields = array( + $this->_options['fieldMessage'] => $event['message'], + $this->_options['fieldLevel'] => $event['level'], + ); + + $this->_db->insert($this->_table, $fields); + return true; + } + +} diff --git a/framework/Log/lib/Horde/Log/Handler/Firebug.php b/framework/Log/lib/Horde/Log/Handler/Firebug.php new file mode 100644 index 000000000..f209eb869 --- /dev/null +++ b/framework/Log/lib/Horde/Log/Handler/Firebug.php @@ -0,0 +1,122 @@ + + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ + +/** + * @category Horde + * @package Horde_Log + * @subpackage Handlers + * @author Mike Naberezny + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ +class Horde_Log_Handler_Firebug extends Horde_Log_Handler_Base +{ + /** + * Formats the log message before writing. + * @var Horde_Log_Formatter_Interface + */ + protected $_formatter; + + /** + * Options to be set by setOption(). Sets the field names in the database table. + * + * @var array + */ + protected $_options = array('buffering' => false); + + /** + * Array of buffered output. + * @var string + */ + protected $_buffer = array(); + + /** + * Mapping of log priorities to Firebug methods. + * @var array + * @access private + */ + protected static $_methods = array( + Horde_Log::EMERG => 'error', + Horde_Log::ALERT => 'error', + Horde_Log::CRIT => 'error', + Horde_Log::ERR => 'error', + Horde_Log::WARN => 'warn', + Horde_Log::NOTICE => 'info', + Horde_Log::INFO => 'info', + Horde_Log::DEBUG => 'debug', + ); + + /** + * Class Constructor + */ + public function __construct() + { + $this->_formatter = new Horde_Log_Formatter_Simple(); + } + + /** + * Write a message to the firebug console. This function really just writes + * the message to the buffer. If buffering is enabled, the + * message won't be output until the buffer is flushed. If + * buffering is not enabled, the buffer will be flushed + * immediately. + * + * @param array $event Log event + * @return bool Always True + */ + public function write($event) + { + $this->_buffer[] = $event; + + if (empty($this->_options['buffering'])) { + $this->flush(); + } + + return true; + } + + /** + */ + public function flush() + { + if (!count($this->_buffer)) { + return true; + } + + $output = array(); + foreach ($this->_buffer as $event) { + $line = trim($this->_formatter->format($event)); + + // normalize line breaks + $line = str_replace("\r\n", "\n", $line); + + // escape line breaks + $line = str_replace("\n", "\\n\\\n", $line); + + // escape quotes + $line = str_replace('"', '\\"', $line); + + // firebug call + $method = isset(self::$_methods[$event['level']]) ? self::$_methods[$event['level']] : 'log'; + $output[] = 'console.' . $method . '("' . $line . '");'; + } + + echo '\n"; + + $this->_buffer = array(); + } + +} diff --git a/framework/Log/lib/Horde/Log/Handler/Null.php b/framework/Log/lib/Horde/Log/Handler/Null.php new file mode 100644 index 000000000..0e0bbc5f0 --- /dev/null +++ b/framework/Log/lib/Horde/Log/Handler/Null.php @@ -0,0 +1,35 @@ + + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ + +/** + * @category Horde + * @package Horde_Log + * @subpackage Handlers + * @author Mike Naberezny + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ +class Horde_Log_Handler_Null extends Horde_Log_Handler_Base +{ + /** + * Write a message to the log buffer + */ + public function write($event) + { + return true; + } + +} \ No newline at end of file diff --git a/framework/Log/lib/Horde/Log/Handler/Stream.php b/framework/Log/lib/Horde/Log/Handler/Stream.php new file mode 100644 index 000000000..bea99a8fb --- /dev/null +++ b/framework/Log/lib/Horde/Log/Handler/Stream.php @@ -0,0 +1,84 @@ + + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ + +/** + * @category Horde + * @package Horde_Log + * @subpackage Handlers + * @author Mike Naberezny + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ +class Horde_Log_Handler_Stream extends Horde_Log_Handler_Base +{ + /** + * Formats the log message before writing. + * @var Horde_Log_Formatter_Interface + */ + protected $_formatter; + + /** + * Holds the PHP stream to log to. + * @var null|stream + */ + protected $_stream = null; + + /** + * Class Constructor + * + * @param mixed $streamOrUrl Stream or URL to open as a stream + * @param string $mode Mode, only applicable if a URL is given + */ + public function __construct($streamOrUrl, $mode = 'a+') + { + $this->_formatter = new Horde_Log_Formatter_Simple(); + + if (is_resource($streamOrUrl)) { + if (get_resource_type($streamOrUrl) != 'stream') { + throw new Horde_Log_Exception('Resource is not a stream'); + } + + if ($mode != 'a+') { + throw new Horde_Log_Exception('Mode cannot be changed on existing streams'); + } + + $this->_stream = $streamOrUrl; + } else { + if (! $this->_stream = @fopen($streamOrUrl, $mode, false)) { + $msg = "\"$streamOrUrl\" cannot be opened with mode \"$mode\""; + throw new Horde_Log_Exception($msg); + } + } + } + + /** + * Write a message to the log. + * + * @param array $event Log event + * @return bool Always True + */ + public function write($event) + { + $line = $this->_formatter->format($event); + + if (! @fwrite($this->_stream, $line)) { + throw new Horde_Log_Exception("Unable to write to stream"); + } + + return true; + } + +} diff --git a/framework/Log/lib/Horde/Log/Logger.php b/framework/Log/lib/Horde/Log/Logger.php new file mode 100644 index 000000000..5a0617a66 --- /dev/null +++ b/framework/Log/lib/Horde/Log/Logger.php @@ -0,0 +1,191 @@ + + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ + +/** + * @category Horde + * @package Horde_Log + * @author Mike Naberezny + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + * + * @method void LOGLEVEL() LOGLEVEL($event) Log an event at LOGLEVEL, where LOGLEVEL has been added with addLevel() or already exists + * @method void emerg() emerg($event) Log an event at the EMERG log level + * @method void alert() alert($event) Log an event at the ALERT log level + * @method void crit() crit($event) Log an event at the CRIT log level + * @method void err() err($event) Log an event at the ERR log level + * @method void warn() warn($event) Log an event at the WARN log level + * @method void notice() notice($event) Log an event at the NOTICE log level + * @method void info() info($event) Log an event at the INFO log level + * @method void debug() debug($event) Log an event at the DEBUG log level + */ +class Horde_Log_Logger +{ + /** + * @var array of log levels where the keys are the + * level priorities and the values are the level names + */ + private $_levels = array(); + + /** + * @var array of Horde_Log_Handler_Abstract objects + */ + private $_handlers = array(); + + /** + * @var array of Horde_Log_Filter_Interface objects + */ + private $_filters = array(); + + /** + * Class constructor. Create a new logger + * + * @param Horde_Log_Handler_Abstract|null $handler default handler + */ + public function __construct($handler = null) + { + $r = new ReflectionClass('Horde_Log'); + $this->_levels = array_flip($r->getConstants()); + + if ($handler !== null) { + $this->addHandler($handler); + } + } + + /** + * Undefined method handler allows a shortcut: + * $log->levelName('message') + * instead of + * $log->log('message', Horde_Log_LEVELNAME) + * + * @param string $method log level name + * @param string $params message to log + * @return void + */ + public function __call($method, $params) + { + $level = strtoupper($method); + if (($level = array_search($level, $this->_levels)) !== false) { + $this->log(array_shift($params), $level); + } else { + throw new Horde_Log_Exception('Bad log level'); + } + } + + /** + * Log a message at a level + * + * @param mixed $event Message to log, either an array or a string + * @param integer $level Log level of message, required if $message is a string + * @return void + */ + public function log($event, $level = null) + { + if (empty($this->_handlers)) { + throw new Horde_Log_Exception('No handlers were added'); + } + + // Create an event array from the given arguments. + if (is_array($event)) { + // If we are passed an array, it must contain 'message' + // and 'level' indices. + if (!isset($event['message'])) { + throw new Horde_Log_Exception('Event array did not contain a message'); + } + if (!isset($event['level'])) { + if ($level === null) { + throw new Horde_Log_Exception('Event array did not contain a log level'); + } else { + $event['level'] = $level; + } + } + } else { + // Create an event array from the message and level + // arguments. + $event = array('message' => $event, 'level' => $level); + } + + if (!isset($this->_levels[$event['level']])) { + throw new Horde_Log_Exception('Bad log level'); + } + + // Fill in the level name and timestamp for filters, formatters, handlers + $event['levelName'] = $this->_levels[$event['level']]; + + if (!isset($event['timestamp'])) { + $event['timestamp'] = date('c'); + } + + // If any global filter rejects the event, don't log it. + foreach ($this->_filters as $filter) { + if (!$filter->accept($event)) { + return; + } + } + + foreach ($this->_handlers as $handler) { + $handler->log($event); + } + } + + /** + * Add a custom log level + * + * @param string $name Name of level + * @param integer $level Numeric level + * @return void + */ + public function addLevel($name, $level) + { + // Log level names must be uppercase for predictability. + $name = strtoupper($name); + + if (isset($this->_levels[$level]) + || array_search($name, $this->_levels)) { + throw new Horde_Log_Exception('Existing log levels cannot be overwritten'); + } + + $this->_levels[$level] = $name; + } + + /** + * Add a filter that will be applied before all log handlers. + * Before a message will be received by any of the handlers, it + * must be accepted by all filters added with this method. + * + * @param Horde_Log_Filter_Interface $filter + * @return void + */ + public function addFilter($filter) + { + if (is_integer($filter)) { + $filter = new Horde_Log_Filter_Level($filter); + } + + $this->_filters[] = $filter; + } + + /** + * Add a handler. A handler is responsible for taking a log + * message and writing it out to storage. + * + * @param Horde_Log_Handler_Abstract $handler + * @return void + */ + public function addHandler($handler) + { + $this->_handlers[] = $handler; + } + +} diff --git a/framework/Log/package.xml b/framework/Log/package.xml new file mode 100644 index 000000000..85e5aa4eb --- /dev/null +++ b/framework/Log/package.xml @@ -0,0 +1,94 @@ + + + Log + pear.horde.org + Horde Logging library + Horde Logging package with configurable handlers, filters, and formatting. + + + Chuck Hagenbuch + chuck + chuck@horde.org + yes + + + Mike Naberezny + mnaberez + mike@maintainable.com + yes + + 2007-10-21 + + + 0.1.0 + 0.1.0 + + + beta + beta + + BSD + Initial Horde_Log release + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5.2 + + + 1.5.0 + + + + + + + + + + + + + + + + + + + + + + diff --git a/framework/Log/test/Horde/Log/AllTests.php b/framework/Log/test/Horde/Log/AllTests.php new file mode 100644 index 000000000..b19ccffef --- /dev/null +++ b/framework/Log/test/Horde/Log/AllTests.php @@ -0,0 +1,70 @@ + + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ + +if (!defined('PHPUnit_MAIN_METHOD')) { + define('PHPUnit_MAIN_METHOD', 'Horde_Log_AllTests::main'); +} + +require_once 'PHPUnit/Framework/TestSuite.php'; +require_once 'PHPUnit/TextUI/TestRunner.php'; + +/** + * @category Horde + * @package Horde_Log + * @subpackage UnitTests + * @author Mike Naberezny + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ +class Horde_Log_AllTests +{ + + public static function main() + { + PHPUnit_TextUI_TestRunner::run(self::suite()); + } + + public static function suite() + { + set_include_path(dirname(__FILE__) . '/../../../lib' . PATH_SEPARATOR . get_include_path()); + if (!spl_autoload_functions()) { + spl_autoload_register(create_function('$class', '$filename = str_replace(array(\'::\', \'_\'), \'/\', $class); include "$filename.php";')); + } + + $suite = new PHPUnit_Framework_TestSuite('Horde_Log'); + + $basedir = dirname(__FILE__); + $baseregexp = preg_quote($basedir . DIRECTORY_SEPARATOR, '/'); + + foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($basedir)) as $file) { + if ($file->isFile() && preg_match('/Test.php$/', $file->getFilename())) { + $pathname = $file->getPathname(); + require $pathname; + + $class = 'Horde_Log_' . str_replace(DIRECTORY_SEPARATOR, '_', + preg_replace("/^$baseregexp(.*)\.php/", '\\1', $pathname)); + $suite->addTestSuite($class); + } + } + + return $suite; + } + +} + +if (PHPUnit_MAIN_METHOD == 'Horde_Log_AllTests::main') { + Horde_Log_AllTests::main(); +} diff --git a/framework/Log/test/Horde/Log/Filter/ChainingTest.php b/framework/Log/test/Horde/Log/Filter/ChainingTest.php new file mode 100644 index 000000000..4927fde6d --- /dev/null +++ b/framework/Log/test/Horde/Log/Filter/ChainingTest.php @@ -0,0 +1,79 @@ + + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ + +/** + * @category Horde + * @package Horde_Log + * @subpackage UnitTests + * @author Mike Naberezny + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ +class Horde_Log_Filter_ChainingTest extends PHPUnit_Framework_TestCase +{ + public function setUp() + { + date_default_timezone_set('America/New_York'); + + $this->log = fopen('php://memory', 'w'); + $this->logger = new Horde_Log_Logger(); + $this->logger->addHandler(new Horde_Log_Handler_Stream($this->log)); + } + + public function tearDown() + { + fclose($this->log); + } + + public function testFilterAllHandlers() + { + // filter out anything above a WARNing for all handlers + $this->logger->addFilter(Horde_Log::WARN); + + $this->logger->info($ignored = 'info-message-ignored'); + $this->logger->warn($logged = 'warn-message-logged'); + + rewind($this->log); + $logdata = stream_get_contents($this->log); + + $this->assertNotContains($ignored, $logdata); + $this->assertContains($logged, $logdata); + } + + + public function testFilterOnSpecificHandler() + { + $log2 = fopen('php://memory', 'w'); + $handler2 = new Horde_Log_Handler_Stream($log2); + $handler2->addFilter(Horde_Log::ERR); + + $this->logger->addHandler($handler2); + + $this->logger->warn($warn = 'warn-message'); + $this->logger->err($err = 'err-message'); + + rewind($this->log); + $logdata = stream_get_contents($this->log); + $this->assertContains($warn, $logdata); + $this->assertContains($err, $logdata); + + rewind($log2); + $logdata = stream_get_contents($log2); + $this->assertContains($err, $logdata); + $this->assertNotContains($warn, $logdata); + } + +} diff --git a/framework/Log/test/Horde/Log/Filter/LevelTest.php b/framework/Log/test/Horde/Log/Filter/LevelTest.php new file mode 100644 index 000000000..76bca92fb --- /dev/null +++ b/framework/Log/test/Horde/Log/Filter/LevelTest.php @@ -0,0 +1,55 @@ + + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ + +/** + * @category Horde + * @package Horde_Log + * @subpackage UnitTests + * @author Mike Naberezny + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ +class Horde_Log_Filter_LevelTest extends PHPUnit_Framework_TestCase +{ + + public function setUp() + { + // accept at or below level 2 + $this->filter = new Horde_Log_Filter_Level(2); + } + + public function testLevelFilterAccept() + { + $this->assertTrue($this->filter->accept(array('message' => '', 'level' => 2))); + $this->assertTrue($this->filter->accept(array('message' => '', 'level' => 1))); + } + + public function testLevelFilterReject() + { + $this->assertFalse($this->filter->accept(array('message' => '', 'level' => 3))); + } + + public function testConstructorThrowsOnInvalidLevel() + { + try { + new Horde_Log_Filter_Level('foo'); + $this->fail(); + } catch (Exception $e) { + $this->assertType('Horde_Log_Exception', $e); + $this->assertRegExp('/must be an integer/i', $e->getMessage()); + } + } +} diff --git a/framework/Log/test/Horde/Log/Filter/MessageTest.php b/framework/Log/test/Horde/Log/Filter/MessageTest.php new file mode 100644 index 000000000..c2aa1d29c --- /dev/null +++ b/framework/Log/test/Horde/Log/Filter/MessageTest.php @@ -0,0 +1,45 @@ + + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ + +/** + * @category Horde + * @package Horde_Log + * @subpackage UnitTests + * @author Mike Naberezny + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ +class Horde_Log_Filter_MessageTest extends PHPUnit_Framework_TestCase +{ + + public function testMessageFilterRecognizesInvalidRegularExpression() + { + try { + $filter = new Horde_Log_Filter_Message('invalid regexp'); + $this->fail(); + } catch (Horde_Log_Exception $e) { + $this->assertRegexp('/invalid reg/i', $e->getMessage()); + } + } + + public function testMessageFilter() + { + $filter = new Horde_Log_Filter_Message('/accept/'); + $this->assertTrue($filter->accept(array('message' => 'foo accept bar', 'level' => 0))); + $this->assertFalse($filter->accept(array('message' => 'foo reject bar', 'level' => 0))); + } + +} diff --git a/framework/Log/test/Horde/Log/Formatter/SimpleTest.php b/framework/Log/test/Horde/Log/Formatter/SimpleTest.php new file mode 100644 index 000000000..3926cf448 --- /dev/null +++ b/framework/Log/test/Horde/Log/Formatter/SimpleTest.php @@ -0,0 +1,48 @@ + + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ + +/** + * @category Horde + * @package Horde_Log + * @subpackage UnitTests + * @author Mike Naberezny + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ +class Horde_Log_Formatter_SimpleTest extends PHPUnit_Framework_TestCase +{ + public function testConstructorThrowsOnBadFormatString() + { + try { + new Horde_Log_Formatter_Simple(1); + $this->fail(); + } catch (Exception $e) { + $this->assertType('Horde_Log_Exception', $e); + $this->assertRegExp('/must be a string/i', $e->getMessage()); + } + } + + public function testDefaultFormat() + { + $f = new Horde_Log_Formatter_Simple(); + $line = $f->format(array('message' => $message = 'message', + 'level' => $level = Horde_Log::ALERT, + 'levelName' => $levelName = 'ALERT')); + + $this->assertContains($message, $line); + $this->assertContains($levelName, $line); + } +} diff --git a/framework/Log/test/Horde/Log/Formatter/XmlTest.php b/framework/Log/test/Horde/Log/Formatter/XmlTest.php new file mode 100644 index 000000000..266b38353 --- /dev/null +++ b/framework/Log/test/Horde/Log/Formatter/XmlTest.php @@ -0,0 +1,55 @@ + + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ + +/** + * @category Horde + * @package Horde_Log + * @author Mike Naberezny + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ +class Horde_Log_Formatter_XmlTest extends PHPUnit_Framework_TestCase +{ + public function setUp() + { + date_default_timezone_set('America/New_York'); + } + + public function testDefaultFormat() + { + $f = new Horde_Log_Formatter_Xml(); + $line = $f->format(array('message' => $message = 'message', 'level' => $level = 1)); + + $this->assertContains($message, $line); + $this->assertContains((string)$level, $line); + } + + public function testXmlDeclarationIsStripped() + { + $f = new Horde_Log_Formatter_Xml(); + $line = $f->format(array('message' => $message = 'message', 'level' => $level = 1)); + + $this->assertNotContains('<\?xml version=', $line); + } + + public function testXmlValidates() + { + $f = new Horde_Log_Formatter_Xml(); + $line = $f->format(array('message' => $message = 'message', 'level' => $level = 1)); + + $sxml = @simplexml_load_string($line); + $this->assertType('SimpleXMLElement', $sxml, 'Formatted XML is invalid'); + } +} diff --git a/framework/Log/test/Horde/Log/Handler/DbTest.php b/framework/Log/test/Horde/Log/Handler/DbTest.php new file mode 100644 index 000000000..282a004ae --- /dev/null +++ b/framework/Log/test/Horde/Log/Handler/DbTest.php @@ -0,0 +1,84 @@ + + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ + +/** + * @category Horde + * @package Horde_Log + * @subpackage UnitTests + * @author Mike Naberezny + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ +class Horde_Log_Handler_DbTest extends PHPUnit_Framework_TestCase +{ + public function setUp() + { + $this->tableName = 'db-table-name'; + + $this->db = new Horde_Log_Handler_DbTest_MockDbAdapter(); + $this->handler = new Horde_Log_Handler_Db($this->db, $this->tableName); + } + + public function testWriteWithDefaults() + { + // log to the mock db adapter + $message = 'message-to-log'; + $level = 2; + $this->handler->write(array('message' => $message, 'level' => $level)); + + // insert should be called once... + $this->assertContains('insert', array_keys($this->db->calls)); + $this->assertEquals(1, count($this->db->calls['insert'])); + + // ...with the correct table and binds for the database + $binds = array('message' => $message, + 'level' => $level); + $this->assertEquals(array($this->tableName, $binds), + $this->db->calls['insert'][0]); + } + + public function testWriteUsesOptionalCustomColumns() + { + $this->handler->setOption('fieldMessage', $messageField = 'new-message-field'); + $this->handler->setOption('fieldLevel', $levelField = 'new-level-field'); + + // log to the mock db adapter + $message = 'message-to-log'; + $level = 2; + $this->handler->write(array('message' => $message, 'level' => $level)); + + // insert should be called once... + $this->assertContains('insert', array_keys($this->db->calls)); + $this->assertEquals(1, count($this->db->calls['insert'])); + + // ...with the correct table and binds for the database + $binds = array($messageField => $message, + $levelField => $level); + $this->assertEquals(array($this->tableName, $binds), + $this->db->calls['insert'][0]); + } +} + + +class Horde_Log_Handler_DbTest_MockDbAdapter +{ + public $calls = array(); + + public function __call($method, $params) + { + $this->calls[$method][] = $params; + } +} \ No newline at end of file diff --git a/framework/Log/test/Horde/Log/Handler/FirebugTest.php b/framework/Log/test/Horde/Log/Handler/FirebugTest.php new file mode 100644 index 000000000..7824ee33f --- /dev/null +++ b/framework/Log/test/Horde/Log/Handler/FirebugTest.php @@ -0,0 +1,61 @@ + + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ + +/** + * @category Horde + * @package Horde_Log + * @subpackage UnitTests + * @author Mike Naberezny + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ +class Horde_Log_Handler_FirebugTest extends PHPUnit_Framework_TestCase +{ + public function setUp() + { + date_default_timezone_set('America/New_York'); + } + + public function testSettingBadOptionThrows() + { + try { + $handler = new Horde_Log_Handler_Stream('php://memory'); + $handler->setOption('foo', 42); + $this->fail(); + } catch (Exception $e) { + $this->assertType('Horde_Log_Exception', $e); + $this->assertRegExp('/unknown option/i', $e->getMessage()); + } + } + + public function testWrite() + { + ob_start(); + + $handler = new Horde_Log_Handler_Firebug(); + $handler->write(array('message' => $message = 'message-to-log', + 'level' => $level = Horde_Log::ALERT, + 'levelName' => $levelName = 'ALERT', + 'timestamp' => date('c'))); + + $contents = ob_get_clean(); + + $date = '\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}-\d{2}:\d{2}'; + + $this->assertRegExp("/console.error\(\"$date $levelName: $message\"\);/", $contents); + } + +} diff --git a/framework/Log/test/Horde/Log/Handler/NullTest.php b/framework/Log/test/Horde/Log/Handler/NullTest.php new file mode 100644 index 000000000..2fb78183b --- /dev/null +++ b/framework/Log/test/Horde/Log/Handler/NullTest.php @@ -0,0 +1,32 @@ + + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ + +/** + * @category Horde + * @package Horde_Log + * @subpackage UnitTests + * @author Mike Naberezny + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ +class Horde_Log_Handler_NullTest extends PHPUnit_Framework_TestCase +{ + public function testWrite() + { + $handler = new Horde_Log_Handler_Null(); + $this->assertTrue($handler->write(array('message' => 'foo', 'level' => 42))); + } +} diff --git a/framework/Log/test/Horde/Log/Handler/StreamTest.php b/framework/Log/test/Horde/Log/Handler/StreamTest.php new file mode 100644 index 000000000..eeb56eaaa --- /dev/null +++ b/framework/Log/test/Horde/Log/Handler/StreamTest.php @@ -0,0 +1,125 @@ + + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ + +/** + * @category Horde + * @package Horde_Log + * @subpackage UnitTests + * @author Mike Naberezny + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ +class Horde_Log_Handler_StreamTest extends PHPUnit_Framework_TestCase +{ + public function setUp() + { + date_default_timezone_set('America/New_York'); + } + + public function testConstructorThrowsWhenResourceIsNotStream() + { + $resource = xml_parser_create(); + try { + new Horde_Log_Handler_Stream($resource); + $this->fail(); + } catch (Exception $e) { + $this->assertType('Horde_Log_Exception', $e); + $this->assertRegExp('/not a stream/i', $e->getMessage()); + } + xml_parser_free($resource); + } + + public function testConstructorWithValidStream() + { + $stream = fopen('php://memory', 'a'); + new Horde_Log_Handler_Stream($stream); + } + + public function testConstructorWithValidUrl() + { + new Horde_Log_Handler_Stream('php://memory'); + } + + public function testConstructorThrowsWhenModeSpecifiedForExistingStream() + { + $stream = fopen('php://memory', 'a'); + try { + new Horde_Log_Handler_Stream($stream, 'w'); + $this->fail(); + } catch (Exception $e) { + $this->assertType('Horde_Log_Exception', $e); + $this->assertRegExp('/existing stream/i', $e->getMessage()); + } + } + + public function testConstructorThrowsWhenStreamCannotBeOpened() + { + try { + new Horde_Log_Handler_Stream(''); + $this->fail(); + } catch (Exception $e) { + $this->assertType('Horde_Log_Exception', $e); + $this->assertRegExp('/cannot be opened/i', $e->getMessage()); + } + } + + public function testSettingBadOptionThrows() + { + try { + $handler = new Horde_Log_Handler_Stream('php://memory'); + $handler->setOption('foo', 42); + $this->fail(); + } catch (Exception $e) { + $this->assertType('Horde_Log_Exception', $e); + $this->assertRegExp('/unknown option/i', $e->getMessage()); + } + } + + public function testWrite() + { + $stream = fopen('php://memory', 'a'); + + $handler = new Horde_Log_Handler_Stream($stream); + $handler->write(array('message' => $message = 'message-to-log', + 'level' => $level = Horde_Log::ALERT, + 'levelName' => $levelName = 'ALERT', + 'timestamp' => date('c'))); + + rewind($stream); + $contents = stream_get_contents($stream); + fclose($stream); + + $date = '\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}-\d{2}:\d{2}'; + + $this->assertRegExp("/$date $levelName: $message/", $contents); + } + + public function testWriteThrowsWhenStreamWriteFails() + { + $stream = fopen('php://memory', 'a'); + $handler = new Horde_Log_Handler_Stream($stream); + fclose($stream); + + try { + $handler->write(array('message' => 'foo', 'level' => 1)); + $this->fail(); + } catch (Exception $e) { + $this->assertType('Horde_Log_Exception', $e); + $this->assertRegExp('/unable to write/i', $e->getMessage()); + } + } + +} diff --git a/framework/Log/test/Horde/Log/LogTest.php b/framework/Log/test/Horde/Log/LogTest.php new file mode 100644 index 000000000..26a38d91e --- /dev/null +++ b/framework/Log/test/Horde/Log/LogTest.php @@ -0,0 +1,147 @@ + + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ + +/** + * @category Horde + * @package Horde_Log + * @subpackage UnitTests + * @author Mike Naberezny + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php BSD + */ +class Horde_Log_LogTest extends PHPUnit_Framework_TestCase +{ + public function setUp() + { + date_default_timezone_set('America/New_York'); + + $this->log = fopen('php://memory', 'a'); + $this->handler = new Horde_Log_Handler_Stream($this->log); + } + + // Handlers + + public function testHandlerCanBeAddedWithConstructor() + { + $logger = new Horde_Log_Logger($this->handler); + $logger->log($message = 'message-to-long', Horde_Log::INFO); + + rewind($this->log); + $this->assertContains($message, stream_get_contents($this->log)); + } + + public function testaddHandler() + { + $logger = new Horde_Log_Logger(); + $logger->addHandler($this->handler); + $logger->log($message = 'message-to-log', Horde_Log::INFO); + + rewind($this->log); + $this->assertContains($message, stream_get_contents($this->log)); + } + + public function testaddHandlerAddsMultipleHandlers() + { + $logger = new Horde_Log_Logger(); + + // create handlers for two separate streams of temporary memory + $log1 = fopen('php://memory', 'a'); + $handler1 = new Horde_Log_Handler_Stream($log1); + $log2 = fopen('php://memory', 'a'); + $handler2 = new Horde_Log_Handler_Stream($log2); + + // add the handlers + $logger->addHandler($handler1); + $logger->addHandler($handler2); + + // log to both handlers + $logger->log($message = 'message-sent-to-both-logs', Horde_Log::INFO); + + // verify both handlers were called by the logger + rewind($log1); + $this->assertContains($message, stream_get_contents($log1)); + rewind($log2); + $this->assertContains($message, stream_get_contents($log2)); + + // prove the two memory streams are different + // and both handlers were indeed called + fwrite($log1, 'foo'); + $this->assertNotEquals(ftell($log1), ftell($log2)); + } + + public function testLoggerThrowsWhenNoHandlers() + { + $logger = new Horde_Log_Logger(); + try { + $logger->log('message', Horde_Log::INFO); + $this->fail(); + } catch (Horde_Log_Exception $e) { + $this->assertRegexp('/no handler/i', $e->getMessage()); + } + } + + // Levels + + public function testLogThrowsOnBadLogLevel() + { + $logger = new Horde_Log_Logger($this->handler); + try { + $logger->log('foo', 42); + $this->fail(); + } catch (Exception $e) { + $this->assertType('Horde_Log_Exception', $e); + $this->assertRegExp('/bad log level/i', $e->getMessage()); + } + } + + public function testLogThrough__callThrowsOnBadLogLevel() + { + $logger = new Horde_Log_Logger($this->handler); + try { + $logger->nonexistantLevel(''); + $this->fail(); + } catch (Exception $e) { + $this->assertType('Horde_Log_Exception', $e); + $this->assertRegExp('/bad log level/i', $e->getMessage()); + } + } + + public function testAddingLevelThrowsWhenOverridingBuiltinLogLevel() + { + try { + $logger = new Horde_Log_Logger($this->handler); + $logger->addLevel('BOB', 0); + $this->fail(); + } catch (Exception $e) { + $this->assertType('Horde_Log_Exception', $e); + $this->assertRegExp('/existing log level/i', $e->getMessage()); + } + + } + + public function testAddLogLevel() + { + $logger = new Horde_Log_Logger($this->handler); + $logger->addLevel($levelName = 'EIGHT', $level = 8); + + $logger->eight($message = 'eight message'); + + rewind($this->log); + $logdata = stream_get_contents($this->log); + $this->assertContains($levelName, $logdata); + $this->assertContains($message, $logdata); + } +} -- 2.11.0