瀏覽代碼

Merge pull request #2 from Seldaek/master

Update from fork
Tiago Brito 12 年之前
父節點
當前提交
5c71be127d

+ 4 - 1
.travis.yml

@@ -5,8 +5,11 @@ php:
   - 5.3
   - 5.4
   - 5.5
+  - hhvm
 
 before_script:
-  - composer install --dev --prefer-source
+  - if [ "`phpenv version-name`" != "hhvm" ]; then echo "extension = mongo.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; fi
+  - if [ "`phpenv version-name`" != "hhvm" ]; then echo "extension = amqp.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; fi
+  - composer install --prefer-source
 
 script: ./vendor/bin/phpunit

+ 1 - 0
README.mdown

@@ -235,6 +235,7 @@ Frameworks Integration
 - [CakePHP](http://cakephp.org/) is usable with Monolog via the [cakephp-monolog](https://github.com/jadb/cakephp-monolog) plugin.
 - [Slim](http://www.slimframework.com/) is usable with Monolog via the [Slim-Monolog](https://github.com/Flynsarmy/Slim-Monolog) log writer.
 - [XOOPS 2.6](http://xoops.org/) comes out of the box with Monolog.
+- [Aura.Web_Project](https://github.com/auraphp/Aura.Web_Project) comes out of the box with Monolog.
 
 Author
 ------

+ 2 - 2
composer.json

@@ -19,7 +19,7 @@
     "require-dev": {
         "phpunit/phpunit": "~3.7.0",
         "mlehner/gelf-php": "1.0.*",
-        "raven/raven": "0.5.*",
+        "raven/raven": "~0.5",
         "ruflin/elastica": "0.90.*",
         "doctrine/couchdb": "dev-master",
         "aws/aws-sdk-php": "~2.4.8"
@@ -34,7 +34,7 @@
         "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB"
     },
     "autoload": {
-        "psr-0": {"Monolog": "src/"}
+        "psr-4": {"Monolog\\": "src/Monolog"}
     },
     "extra": {
         "branch-alias": {

+ 1 - 1
doc/extending.md

@@ -65,7 +65,7 @@ You can now use this handler in your logger:
 ```php
 <?php
 
-$logger->pushHandler(new PDOHandler(new PDO('sqlite:logs.sqlite'));
+$logger->pushHandler(new PDOHandler(new PDO('sqlite:logs.sqlite')));
 
 // You can now use your logger
 $logger->addInfo('My logger is now ready');

+ 1 - 1
doc/usage.md

@@ -8,7 +8,7 @@ Monolog is available on Packagist ([monolog/monolog](http://packagist.org/packag
 and as such installable via [Composer](http://getcomposer.org/).
 
 ```bash
-php composer.phar require monolog/monolog '~1.4'
+php composer.phar require monolog/monolog '~1.7'
 ```
 
 If you do not use Composer, you can grab the code from GitHub, and use any

+ 31 - 22
src/Monolog/Formatter/LineFormatter.php

@@ -11,6 +11,8 @@
 
 namespace Monolog\Formatter;
 
+use Exception;
+
 /**
  * Formats incoming records into a one-line string
  *
@@ -24,14 +26,17 @@ class LineFormatter extends NormalizerFormatter
     const SIMPLE_FORMAT = "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n";
 
     protected $format;
+    protected $allowInlineLineBreaks;
 
     /**
-     * @param string $format     The format of the message
-     * @param string $dateFormat The format of the timestamp: one supported by DateTime::format
+     * @param string $format                The format of the message
+     * @param string $dateFormat            The format of the timestamp: one supported by DateTime::format
+     * @param bool   $allowInlineLineBreaks Whether to allow inline line breaks in log entries
      */
-    public function __construct($format = null, $dateFormat = null)
+    public function __construct($format = null, $dateFormat = null, $allowInlineLineBreaks = false)
     {
         $this->format = $format ?: static::SIMPLE_FORMAT;
+        $this->allowInlineLineBreaks = $allowInlineLineBreaks;
         parent::__construct($dateFormat);
     }
 
@@ -45,13 +50,13 @@ class LineFormatter extends NormalizerFormatter
         $output = $this->format;
         foreach ($vars['extra'] as $var => $val) {
             if (false !== strpos($output, '%extra.'.$var.'%')) {
-                $output = str_replace('%extra.'.$var.'%', $this->convertToString($val), $output);
+                $output = str_replace('%extra.'.$var.'%', $this->replaceNewlines($this->convertToString($val)), $output);
                 unset($vars['extra'][$var]);
             }
         }
         foreach ($vars as $var => $val) {
             if (false !== strpos($output, '%'.$var.'%')) {
-                $output = str_replace('%'.$var.'%', $this->convertToString($val), $output);
+                $output = str_replace('%'.$var.'%', $this->replaceNewlines($this->convertToString($val)), $output);
             }
         }
 
@@ -68,37 +73,41 @@ class LineFormatter extends NormalizerFormatter
         return $message;
     }
 
-    protected function normalize($data)
+    protected function normalizeException(Exception $e)
     {
-        if (is_bool($data) || is_null($data)) {
-            return var_export($data, true);
+        $previousText = '';
+        if ($previous = $e->getPrevious()) {
+            do {
+                $previousText .= ', '.get_class($previous).': '.$previous->getMessage().' at '.$previous->getFile().':'.$previous->getLine();
+            } while ($previous = $previous->getPrevious());
         }
 
-        if ($data instanceof \Exception) {
-            $previousText = '';
-            if ($previous = $data->getPrevious()) {
-                do {
-                    $previousText .= ', '.get_class($previous).': '.$previous->getMessage().' at '.$previous->getFile().':'.$previous->getLine();
-                } while ($previous = $previous->getPrevious());
-            }
-
-            return '[object] ('.get_class($data).': '.$data->getMessage().' at '.$data->getFile().':'.$data->getLine().$previousText.')';
-        }
-
-        return parent::normalize($data);
+        return '[object] ('.get_class($e).': '.$e->getMessage().' at '.$e->getFile().':'.$e->getLine().$previousText.')';
     }
 
     protected function convertToString($data)
     {
-        if (null === $data || is_scalar($data)) {
+        if (null === $data || is_bool($data)) {
+            return var_export($data, true);
+        }
+
+        if (is_scalar($data)) {
             return (string) $data;
         }
 
-        $data = $this->normalize($data);
         if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
             return $this->toJson($data, true);
         }
 
         return str_replace('\\/', '/', @json_encode($data));
     }
+
+    protected function replaceNewlines($str)
+    {
+        if ($this->allowInlineLineBreaks) {
+            return $str;
+        }
+
+        return preg_replace('{[\r\n]+}', ' ', $str);
+    }
 }

+ 0 - 1
src/Monolog/Formatter/NormalizerFormatter.php

@@ -101,7 +101,6 @@ class NormalizerFormatter implements FormatterInterface
         );
 
         $trace = $e->getTrace();
-        array_shift($trace);
         foreach ($trace as $frame) {
             if (isset($frame['file'])) {
                 $data['trace'][] = $frame['file'].':'.$frame['line'];

+ 0 - 2
src/Monolog/Formatter/ScalarFormatter.php

@@ -11,8 +11,6 @@
 
 namespace Monolog\Formatter;
 
-use Monolog\Formatter\NormalizerFormatter;
-
 /**
  * Formats data into an associative array of scalar values.
  * Objects and arrays will be JSON encoded.

+ 2 - 2
src/Monolog/Handler/AbstractHandler.php

@@ -141,8 +141,8 @@ abstract class AbstractHandler implements HandlerInterface
     /**
      * Sets the bubbling behavior.
      *
-     * @param Boolean $bubble true means that this handler allows bubbling.
-     *                        false means that bubbling is not permitted.
+     * @param  Boolean $bubble true means that this handler allows bubbling.
+     *                         false means that bubbling is not permitted.
      * @return self
      */
     public function setBubble($bubble)

+ 2 - 2
src/Monolog/Handler/CubeHandler.php

@@ -32,8 +32,8 @@ class CubeHandler extends AbstractProcessingHandler
      * Create a Cube handler
      *
      * @throws UnexpectedValueException when given url is not a valid url.
-     * A valid url must consists of three parts : protocol://host:port
-     * Only valid protocol used by Cube are http and udp
+     *                                  A valid url must consists of three parts : protocol://host:port
+     *                                  Only valid protocol used by Cube are http and udp
      */
     public function __construct($url, $level = Logger::DEBUG, $bubble = true)
     {

+ 1 - 1
src/Monolog/Handler/DynamoDbHandler.php

@@ -75,7 +75,7 @@ class DynamoDbHandler extends AbstractProcessingHandler
      */
     protected function filterEmptyFields(array $record)
     {
-        return array_filter($record, function($value) {
+        return array_filter($record, function ($value) {
             return !empty($value) || false === $value || 0 === $value;
         });
     }

+ 1 - 1
src/Monolog/Handler/HandlerInterface.php

@@ -47,7 +47,7 @@ interface HandlerInterface
      *
      * @param  array   $record The record to handle
      * @return Boolean true means that this handler handled the record, and that bubbling is not permitted.
-     *                 false means the record was either not processed or that this handler allows bubbling.
+     *                        false means the record was either not processed or that this handler allows bubbling.
      */
     public function handle(array $record);
 

+ 102 - 21
src/Monolog/Handler/HipChatHandler.php

@@ -27,6 +27,16 @@ use Monolog\Logger;
  */
 class HipChatHandler extends SocketHandler
 {
+    /**
+     * The maximum allowed length for the name used in the "from" field.
+     */
+    const MAXIMUM_NAME_LENGTH = 15;
+
+    /**
+     * The maximum allowed length for the message.
+     */
+    const MAXIMUM_MESSAGE_LENGTH = 9500;
+
     /**
      * @var string
      */
@@ -47,6 +57,11 @@ class HipChatHandler extends SocketHandler
      */
     private $notify;
 
+    /**
+     * @var string
+     */
+    private $format;
+
     /**
      * @param string  $token  HipChat API Token
      * @param string  $room   The room that should be alerted of the message (Id or Name)
@@ -55,9 +70,14 @@ class HipChatHandler extends SocketHandler
      * @param int     $level  The minimum logging level at which this handler will be triggered
      * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
      * @param Boolean $useSSL Whether to connect via SSL.
+     * @param string  $format The format of the messages (default to text, can be set to html if you have html in the messages)
      */
-    public function __construct($token, $room, $name = 'Monolog', $notify = false, $level = Logger::CRITICAL, $bubble = true, $useSSL = true)
+    public function __construct($token, $room, $name = 'Monolog', $notify = false, $level = Logger::CRITICAL, $bubble = true, $useSSL = true, $format = 'text')
     {
+        if (!$this->validateStringLength($name, static::MAXIMUM_NAME_LENGTH)) {
+            throw new \InvalidArgumentException('The supplied name is too long. HipChat\'s v1 API supports names up to 15 UTF-8 characters.');
+        }
+
         $connectionString = $useSSL ? 'ssl://api.hipchat.com:443' : 'api.hipchat.com:80';
         parent::__construct($connectionString, $level, $bubble);
 
@@ -65,6 +85,7 @@ class HipChatHandler extends SocketHandler
         $this->name = $name;
         $this->notify = $notify;
         $this->room = $room;
+        $this->format = $format;
     }
 
     /**
@@ -93,7 +114,7 @@ class HipChatHandler extends SocketHandler
             'room_id' => $this->room,
             'notify' => $this->notify,
             'message' => $record['formatted'],
-            'message_format' => 'text',
+            'message_format' => $this->format,
             'color' => $this->getAlertColor($record['level']),
         );
 
@@ -159,13 +180,19 @@ class HipChatHandler extends SocketHandler
             return true;
         }
 
-        $batchRecord = $this->combineRecords($records);
+        $batchRecords = $this->combineRecords($records);
 
-        if (!$this->isHandling($batchRecord)) {
-            return false;
+        $handled = false;
+        foreach ($batchRecords as $batchRecord) {
+            if ($this->isHandling($batchRecord)) {
+                $this->write($batchRecord);
+                $handled = true;
+            }
         }
 
-        $this->write($batchRecord);
+        if (!$handled) {
+            return false;
+        }
 
         return false === $this->bubble;
     }
@@ -180,6 +207,9 @@ class HipChatHandler extends SocketHandler
      */
     private function combineRecords($records)
     {
+        $batchRecord = null;
+        $batchRecords = array();
+        $batchedMessages = array();
         $messages = array();
         $formattedMessages = array();
         $level = 0;
@@ -187,12 +217,7 @@ class HipChatHandler extends SocketHandler
         $datetime = null;
 
         foreach ($records as $record) {
-
             $record = $this->processRecord($record);
-            $record['formatted'] = $this->getFormatter()->format($record);
-
-            $messages[] = $record['message'];
-            $formattedMessages[] = $record['formatted'];
 
             if ($record['level'] > $level) {
                 $level = $record['level'];
@@ -202,18 +227,74 @@ class HipChatHandler extends SocketHandler
             if (null === $datetime) {
                 $datetime = $record['datetime'];
             }
+
+            $messages[] = $record['message'];
+            $messgeStr = implode(PHP_EOL, $messages);
+            $formattedMessages[] = $this->getFormatter()->format($record);
+            $formattedMessageStr = implode('', $formattedMessages);
+
+            $batchRecord = array(
+                'message'   => $messgeStr,
+                'formatted' => $formattedMessageStr,
+                'context'   => array(),
+                'extra'     => array(),
+            );
+
+            if (!$this->validateStringLength($batchRecord['formatted'], static::MAXIMUM_MESSAGE_LENGTH)) {
+                // Pop the last message and implode the remainging messages
+                $lastMessage = array_pop($messages);
+                $lastFormattedMessage = array_pop($formattedMessages);
+                $batchRecord['message'] = implode(PHP_EOL, $messages);
+                $batchRecord['formatted'] = implode('', $formattedMessages);
+
+                $batchRecords[] = $batchRecord;
+                $messages = array($lastMessage);
+                $formattedMessages = array($lastFormattedMessage);
+
+                $batchRecord = null;
+            }
         }
 
-        $batchRecord = array(
-            'message' => implode(PHP_EOL, $messages),
-            'formatted' => implode('', $formattedMessages),
-            'level' => $level,
-            'level_name' => $levelName,
-            'datetime' => $datetime,
-            'context' => array(),
-            'extra' => array(),
-        );
+        if (null !== $batchRecord) {
+            $batchRecords[] = $batchRecord;
+        }
+
+        // Set the max level and datetime for all records
+        foreach ($batchRecords as &$batchRecord) {
+            $batchRecord = array_merge(
+                $batchRecord,
+                array(
+                    'level'      => $level,
+                    'level_name' => $levelName,
+                    'datetime'   => $datetime
+                )
+            );
+        }
+
+        return $batchRecords;
+    }
+
+    /**
+     * Validates the length of a string.
+     *
+     * If the `mb_strlen()` function is available, it will use that, as HipChat
+     * allows UTF-8 characters. Otherwise, it will fall back to `strlen()`.
+     *
+     * Note that this might cause false failures in the specific case of using
+     * a valid name with less than 16 characters, but 16 or more bytes, on a
+     * system where `mb_strlen()` is unavailable.
+     *
+     * @param string $str
+     * @param int $length
+     *
+     * @return bool
+     */
+    private function validateStringLength($str, $length)
+    {
+        if (function_exists('mb_strlen')) {
+            return (mb_strlen($str) <= $length);
+        }
 
-        return $batchRecord;
+        return (strlen($str) <= $length);
     }
 }

+ 13 - 13
src/Monolog/Handler/PushoverHandler.php

@@ -32,19 +32,19 @@ class PushoverHandler extends SocketHandler
     private $emergencyLevel;
 
     /**
-     * @param string       $token  Pushover api token
-     * @param string|array $users  Pushover user id or array of ids the message will be sent to
-     * @param string       $title  Title sent to the Pushover API
-     * @param integer      $level  The minimum logging level at which this handler will be triggered
-     * @param Boolean      $bubble Whether the messages that are handled can bubble up the stack or not
-     * @param Boolean      $useSSL Whether to connect via SSL. Required when pushing messages to users that are not
-     *                        the pushover.net app owner. OpenSSL is required for this option.
-     * @param integer $highPriorityLevel The minimum logging level at which this handler will start
-     *                                   sending "high priority" requests to the Pushover API
-     * @param integer $emergencyLevel The minimum logging level at which this handler will start
-     *                                sending "emergency" requests to the Pushover API
-     * @param integer $retry  The retry parameter specifies how often (in seconds) the Pushover servers will send the same notification to the user.
-     * @param integer $expire The expire parameter specifies how many seconds your notification will continue to be retried for (every retry seconds).
+     * @param string       $token             Pushover api token
+     * @param string|array $users             Pushover user id or array of ids the message will be sent to
+     * @param string       $title             Title sent to the Pushover API
+     * @param integer      $level             The minimum logging level at which this handler will be triggered
+     * @param Boolean      $bubble            Whether the messages that are handled can bubble up the stack or not
+     * @param Boolean      $useSSL            Whether to connect via SSL. Required when pushing messages to users that are not
+     *                                        the pushover.net app owner. OpenSSL is required for this option.
+     * @param integer      $highPriorityLevel The minimum logging level at which this handler will start
+     *                                        sending "high priority" requests to the Pushover API
+     * @param integer      $emergencyLevel    The minimum logging level at which this handler will start
+     *                                        sending "emergency" requests to the Pushover API
+     * @param integer      $retry             The retry parameter specifies how often (in seconds) the Pushover servers will send the same notification to the user.
+     * @param integer      $expire            The expire parameter specifies how many seconds your notification will continue to be retried for (every retry seconds).
      */
     public function __construct($token, $users, $title = null, $level = Logger::CRITICAL, $bubble = true, $useSSL = true, $highPriorityLevel = Logger::CRITICAL, $emergencyLevel = Logger::EMERGENCY, $retry = 30, $expire = 25200)
     {

+ 2 - 2
src/Monolog/Handler/RavenHandler.php

@@ -69,7 +69,7 @@ class RavenHandler extends AbstractProcessingHandler
         $level = $this->level;
 
         // filter records based on their level
-        $records = array_filter($records, function($record) use ($level) {
+        $records = array_filter($records, function ($record) use ($level) {
             return $record['level'] >= $level;
         });
 
@@ -78,7 +78,7 @@ class RavenHandler extends AbstractProcessingHandler
         }
 
         // the record with the highest severity is the "main" one
-        $record = array_reduce($records, function($highest, $record) {
+        $record = array_reduce($records, function ($highest, $record) {
             if ($record['level'] >= $highest['level']) {
                 return $record;
             }

+ 1 - 1
src/Monolog/Handler/RotatingFileHandler.php

@@ -105,7 +105,7 @@ class RotatingFileHandler extends StreamHandler
         }
 
         // Sorting the files by name to remove the older ones
-        usort($logFiles, function($a, $b) {
+        usort($logFiles, function ($a, $b) {
             return strcmp($b, $a);
         });
 

+ 9 - 6
src/Monolog/Logger.php

@@ -107,12 +107,15 @@ class Logger implements LoggerInterface
      */
     protected static $timezone;
 
+    /**
+     * @var string
+     */
     protected $name;
 
     /**
      * The handler stack
      *
-     * @var array of Monolog\Handler\HandlerInterface
+     * @var HandlerInterface[]
      */
     protected $handlers;
 
@@ -121,14 +124,14 @@ class Logger implements LoggerInterface
      *
      * To process records of a single handler instead, add the processor on that specific handler
      *
-     * @var array of callables
+     * @var callable[]
      */
     protected $processors;
 
     /**
-     * @param string $name       The logging channel
-     * @param array  $handlers   Optional stack of handlers, the first one in the array is called first, etc.
-     * @param array  $processors Optional array of processors
+     * @param string             $name       The logging channel
+     * @param HandlerInterface[] $handlers   Optional stack of handlers, the first one in the array is called first, etc.
+     * @param callable[]         $processors Optional array of processors
      */
     public function __construct($name, array $handlers = array(), array $processors = array())
     {
@@ -341,7 +344,7 @@ class Logger implements LoggerInterface
      */
     public function addEmergency($message, array $context = array())
     {
-      return $this->addRecord(static::EMERGENCY, $message, $context);
+        return $this->addRecord(static::EMERGENCY, $message, $context);
     }
 
     /**

+ 13 - 3
src/Monolog/Processor/IntrospectionProcessor.php

@@ -28,9 +28,12 @@ class IntrospectionProcessor
 {
     private $level;
 
-    public function __construct($level = Logger::DEBUG)
+    private $skipClassesPartials;
+
+    public function __construct($level = Logger::DEBUG, array $skipClassesPartials = array('Monolog\\'))
     {
         $this->level = $level;
+        $this->skipClassesPartials = $skipClassesPartials;
     }
 
     /**
@@ -52,8 +55,15 @@ class IntrospectionProcessor
         array_shift($trace);
 
         $i = 0;
-        while (isset($trace[$i]['class']) && false !== strpos($trace[$i]['class'], 'Monolog\\')) {
-            $i++;
+
+        while (isset($trace[$i]['class'])) {
+            foreach ($this->skipClassesPartials as $part) {
+                if (strpos($trace[$i]['class'], $part) !== false) {
+                    $i++;
+                    continue 2;
+                }
+            }
+            break;
         }
 
         // we should have the call source now

+ 1 - 1
src/Monolog/Registry.php

@@ -48,7 +48,7 @@ class Registry
      * Adds new logging channel to the registry
      *
      * @param  Logger                    $logger    Instance of the logging channel
-     * @param  string                    $name      Name of the logging channel ($logger->getName() by default)
+     * @param  string|null               $name      Name of the logging channel ($logger->getName() by default)
      * @param  boolean                   $overwrite Overwrite instance in the registry if the given name already exists?
      * @throws \InvalidArgumentException If $overwrite set to false and named Logger instance already exists
      */

+ 31 - 1
tests/Monolog/Formatter/LineFormatterTest.php

@@ -42,9 +42,11 @@ class LineFormatterTest extends \PHPUnit_Framework_TestCase
             'context' => array(
                 'foo' => 'bar',
                 'baz' => 'qux',
+                'bool' => false,
+                'null' => null,
             )
         ));
-        $this->assertEquals('['.date('Y-m-d').'] meh.ERROR: foo {"foo":"bar","baz":"qux"} []'."\n", $message);
+        $this->assertEquals('['.date('Y-m-d').'] meh.ERROR: foo {"foo":"bar","baz":"qux","bool":false,"null":null} []'."\n", $message);
     }
 
     public function testDefFormatExtras()
@@ -148,6 +150,34 @@ class LineFormatterTest extends \PHPUnit_Framework_TestCase
         ));
         $this->assertEquals('['.date('Y-m-d').'] test.CRITICAL: bar [] []'."\n".'['.date('Y-m-d').'] log.WARNING: foo [] []'."\n", $message);
     }
+
+    public function testFormatShouldStripInlineLineBreaks()
+    {
+        $formatter = new LineFormatter(null, 'Y-m-d');
+        $message = $formatter->format(
+            array(
+                'message' => "foo\nbar",
+                'context' => array(),
+                'extra' => array(),
+            )
+        );
+
+        $this->assertRegExp('/foo bar/', $message);
+    }
+
+    public function testFormatShouldNotStripInlineLineBreaksWhenFlagIsSet()
+    {
+        $formatter = new LineFormatter(null, 'Y-m-d', true);
+        $message = $formatter->format(
+            array(
+                'message' => "foo\nbar",
+                'context' => array(),
+                'extra' => array(),
+            )
+        );
+
+        $this->assertRegExp('/foo\nbar/', $message);
+    }
 }
 
 class TestFoo

+ 0 - 1
tests/Monolog/Formatter/ScalarFormatterTest.php

@@ -12,7 +12,6 @@ class ScalarFormatterTest extends \PHPUnit_Framework_TestCase
     {
         $data = array();
         $trace = $e->getTrace();
-        array_shift($trace);
         foreach ($trace as $frame) {
             if (isset($frame['file'])) {
                 $data[] = $frame['file'].':'.$frame['line'];

+ 0 - 38
tests/Monolog/Handler/AmqpExchangeMock.php

@@ -1,38 +0,0 @@
-<?php
-
-/*
- * This file is part of the Monolog package.
- *
- * (c) Jordi Boggiano <j.boggiano@seld.be>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Monolog\Handler;
-
-class AmqpExchangeMock extends \AMQPExchange
-{
-    protected $messages = array();
-
-    public function __construct()
-    {
-    }
-
-    public function publish($message, $routing_key, $params = 0, $attributes = array())
-    {
-        $this->messages[] = array($message, $routing_key, $params, $attributes);
-
-        return true;
-    }
-
-    public function getMessages()
-    {
-        return $this->messages;
-    }
-
-    public function setName($name)
-    {
-        return true;
-    }
-}

+ 13 - 7
tests/Monolog/Handler/AmqpHandlerTest.php

@@ -32,7 +32,19 @@ class AmqpHandlerTest extends TestCase
 
     public function testHandle()
     {
-        $exchange = $this->getExchange();
+        $messages = array();
+
+        $exchange = $this->getMock('AMQPExchange', array('publish', 'setName'), array(), '', false);
+        $exchange->expects($this->once())
+            ->method('setName')
+            ->with('log')
+        ;
+        $exchange->expects($this->any())
+            ->method('publish')
+            ->will($this->returnCallback(function ($message, $routing_key, $flags = 0, $attributes = array()) use (&$messages) {
+                $messages[] = array($message, $routing_key, $flags, $attributes);
+            }))
+        ;
 
         $handler = new AmqpHandler($exchange, 'log');
 
@@ -60,15 +72,9 @@ class AmqpHandlerTest extends TestCase
 
         $handler->handle($record);
 
-        $messages = $exchange->getMessages();
         $this->assertCount(1, $messages);
         $messages[0][0] = json_decode($messages[0][0], true);
         unset($messages[0][0]['datetime']);
         $this->assertEquals($expected, $messages[0]);
     }
-
-    protected function getExchange()
-    {
-        return new AmqpExchangeMock();
-    }
 }

+ 3 - 1
tests/Monolog/Handler/DynamoDbHandlerTest.php

@@ -21,7 +21,9 @@ class DynamoDbHandlerTest extends TestCase
             $this->markTestSkipped('aws/aws-sdk-php not installed');
         }
 
-        $this->client = $this->getMockBuilder('Aws\DynamoDb\DynamoDbClient')->disableOriginalConstructor()->getMock();
+        $this->client = $this->getMockBuilder('Aws\DynamoDb\DynamoDbClient')
+            ->setMethods(array('formatAttributes', '__call'))
+            ->disableOriginalConstructor()->getMock();
     }
 
     public function testConstruct()

+ 8 - 0
tests/Monolog/Handler/HipChatHandlerTest.php

@@ -156,4 +156,12 @@ class HipChatHandlerTest extends TestCase
 
         $this->handler->setFormatter($this->getIdentityFormatter());
     }
+
+    /**
+     * @expectedException InvalidArgumentException
+     */
+    public function testCreateWithTooLongName()
+    {
+        $hipChatHandler = new \Monolog\Handler\HipChatHandler('token', 'room', 'SixteenCharsHere');
+    }
 }

+ 1 - 1
tests/Monolog/Handler/MongoDBHandlerTest.php

@@ -26,7 +26,7 @@ class MongoDBHandlerTest extends TestCase
 
     public function testHandle()
     {
-        $mongo = $this->getMock('Mongo', array('selectCollection'));
+        $mongo = $this->getMock('Mongo', array('selectCollection'), array(), '', false);
         $collection = $this->getMock('stdClass', array('save'));
 
         $mongo->expects($this->once())

+ 3 - 3
tests/Monolog/Handler/SyslogUdpHandlerTest.php

@@ -16,16 +16,16 @@ class SyslogUdpHandlerTest extends \PHPUnit_Framework_TestCase
 
     public function testWeSplitIntoLines()
     {
-        $handler = new SyslogUdpHandler("127.0.0.1", 514, "local5");
+        $handler = new SyslogUdpHandler("127.0.0.1", 514, "authpriv");
         $handler->setFormatter(new \Monolog\Formatter\ChromePHPFormatter());
 
         $socket = $this->getMock('\Monolog\Handler\SyslogUdp\UdpSocket', array('write'), array('lol', 'lol'));
         $socket->expects($this->at(0))
             ->method('write')
-            ->with("lol", "<172>: ");
+            ->with("lol", "<".(LOG_AUTHPRIV + LOG_WARNING).">: ");
         $socket->expects($this->at(1))
             ->method('write')
-            ->with("hej", "<172>: ");
+            ->with("hej", "<".(LOG_AUTHPRIV + LOG_WARNING).">: ");
 
         $handler->setSocket($socket);
 

+ 3 - 1
tests/bootstrap.php

@@ -10,4 +10,6 @@
  */
 
 $loader = require __DIR__ . "/../vendor/autoload.php";
-$loader->add('Monolog\\', __DIR__);
+$loader->addPsr4('Monolog\\', __DIR__.'/Monolog');
+
+date_default_timezone_set('UTC');