Sfoglia il codice sorgente

Fix some issues, bump phpunit version

Jordi Boggiano 3 anni fa
parent
commit
400effdd45
45 ha cambiato i file con 602 aggiunte e 774 eliminazioni
  1. 1 1
      composer.json
  2. 1 1
      src/Monolog/Formatter/ElasticsearchFormatter.php
  3. 1 3
      src/Monolog/Formatter/FlowdockFormatter.php
  4. 0 4
      src/Monolog/Formatter/GelfMessageFormatter.php
  5. 2 2
      src/Monolog/Formatter/JsonFormatter.php
  6. 0 1
      src/Monolog/Formatter/LineFormatter.php
  7. 6 6
      src/Monolog/Formatter/LogglyFormatter.php
  8. 4 2
      src/Monolog/Formatter/LogmaticFormatter.php
  9. 1 1
      src/Monolog/Formatter/MongoDBFormatter.php
  10. 17 3
      src/Monolog/Formatter/NormalizerFormatter.php
  11. 4 8
      src/Monolog/Formatter/ScalarFormatter.php
  12. 1 1
      src/Monolog/Formatter/WildfireFormatter.php
  13. 7 9
      src/Monolog/Handler/ChromePHPHandler.php
  14. 1 1
      src/Monolog/Handler/DynamoDbHandler.php
  15. 1 1
      src/Monolog/Handler/FlowdockHandler.php
  16. 3 4
      src/Monolog/Handler/MailHandler.php
  17. 14 14
      src/Monolog/Handler/PHPConsoleHandler.php
  18. 6 6
      src/Monolog/Handler/Slack/SlackRecord.php
  19. 7 6
      src/Monolog/Handler/TestHandler.php
  20. 3 1
      src/Monolog/Logger.php
  21. 36 46
      tests/Monolog/Formatter/ChromePHPFormatterTest.php
  22. 6 7
      tests/Monolog/Formatter/ElasticaFormatterTest.php
  23. 10 11
      tests/Monolog/Formatter/ElasticsearchFormatterTest.php
  24. 3 3
      tests/Monolog/Formatter/FlowdockFormatterTest.php
  25. 2 4
      tests/Monolog/Formatter/FluentdFormatterTest.php
  26. 61 88
      tests/Monolog/Formatter/GelfMessageFormatterTest.php
  27. 34 44
      tests/Monolog/Formatter/JsonFormatterTest.php
  28. 94 132
      tests/Monolog/Formatter/LineFormatterTest.php
  29. 46 55
      tests/Monolog/Formatter/LogstashFormatterTest.php
  30. 43 55
      tests/Monolog/Formatter/MongoDBFormatterTest.php
  31. 51 58
      tests/Monolog/Formatter/NormalizerFormatterTest.php
  32. 26 31
      tests/Monolog/Formatter/ScalarFormatterTest.php
  33. 32 46
      tests/Monolog/Formatter/WildfireFormatterTest.php
  34. 5 10
      tests/Monolog/Handler/DeduplicationHandlerTest.php
  35. 4 28
      tests/Monolog/Handler/ElasticaHandlerTest.php
  36. 3 19
      tests/Monolog/Handler/ElasticsearchHandlerTest.php
  37. 3 5
      tests/Monolog/Handler/FingersCrossedHandlerTest.php
  38. 1 9
      tests/Monolog/Handler/FleepHookHandlerTest.php
  39. 6 3
      tests/Monolog/Handler/GelfHandlerTest.php
  40. 1 1
      tests/Monolog/Handler/MongoDBHandlerTest.php
  41. 2 2
      tests/Monolog/Handler/PsrHandlerTest.php
  42. 12 12
      tests/Monolog/Handler/SyslogUdpHandlerTest.php
  43. 5 5
      tests/Monolog/Handler/TestHandlerTest.php
  44. 33 13
      tests/Monolog/LoggerTest.php
  45. 3 12
      tests/Monolog/Processor/IntrospectionProcessorTest.php

+ 1 - 1
composer.json

@@ -25,7 +25,7 @@
         "php-amqplib/php-amqplib": "~2.4 || ^3",
         "php-console/php-console": "^3.1.3",
         "phpspec/prophecy": "^1.6.1",
-        "phpunit/phpunit": "^9",
+        "phpunit/phpunit": "^9.5.16",
         "predis/predis": "^1.1",
         "rollbar/rollbar": "^3",
         "ruflin/elastica": ">=0.90@dev",

+ 1 - 1
src/Monolog/Formatter/ElasticsearchFormatter.php

@@ -80,7 +80,7 @@ class ElasticsearchFormatter extends NormalizerFormatter
      * @param  mixed[] $record Log message
      * @return mixed[]
      */
-    protected function getDocument(LogRecord $record): array
+    protected function getDocument(array $record): array
     {
         $record['_index'] = $this->index;
         $record['_type'] = $this->type;

+ 1 - 3
src/Monolog/Formatter/FlowdockFormatter.php

@@ -60,7 +60,7 @@ class FlowdockFormatter implements FormatterInterface
             $this->getShortMessage($record['message'])
         );
 
-        $record['flowdock'] = [
+        return [
             'source' => $this->source,
             'from_address' => $this->sourceEmail,
             'subject' => $subject,
@@ -68,8 +68,6 @@ class FlowdockFormatter implements FormatterInterface
             'tags' => $tags,
             'project' => $this->source,
         ];
-
-        return $record;
     }
 
     /**

+ 0 - 4
src/Monolog/Formatter/GelfMessageFormatter.php

@@ -96,10 +96,6 @@ class GelfMessageFormatter extends NormalizerFormatter
             $extra = parent::normalize($record['extra']);
         }
 
-        if (!isset($record['datetime'], $record['message'], $record['level'])) {
-            throw new \InvalidArgumentException('The record should at least contain datetime, message and level keys, '.var_export($record, true).' given');
-        }
-
         $message = new Message();
         $message
             ->setTimestamp($record['datetime'])

+ 2 - 2
src/Monolog/Formatter/JsonFormatter.php

@@ -75,7 +75,7 @@ class JsonFormatter extends NormalizerFormatter
      */
     public function format(LogRecord $record): string
     {
-        $normalized = $this->normalize($record);
+        $normalized = parent::format($record);
 
         if (isset($normalized['context']) && $normalized['context'] === []) {
             if ($this->ignoreEmptyContextAndExtra) {
@@ -157,7 +157,7 @@ class JsonFormatter extends NormalizerFormatter
      *
      * @return mixed
      */
-    protected function normalize($data, int $depth = 0)
+    protected function normalize(mixed $data, int $depth = 0): mixed
     {
         if ($depth > $this->maxNormalizeDepth) {
             return 'Over '.$this->maxNormalizeDepth.' levels deep, aborting normalization';

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

@@ -82,7 +82,6 @@ class LineFormatter extends NormalizerFormatter
         $vars = parent::format($record);
 
         $output = $this->format;
-
         foreach ($vars['extra'] as $var => $val) {
             if (false !== strpos($output, '%extra.'.$var.'%')) {
                 $output = str_replace('%extra.'.$var.'%', $this->stringify($val), $output);

+ 6 - 6
src/Monolog/Formatter/LogglyFormatter.php

@@ -35,13 +35,13 @@ class LogglyFormatter extends JsonFormatter
      * @see https://www.loggly.com/docs/automated-parsing/#json
      * @see \Monolog\Formatter\JsonFormatter::format()
      */
-    public function format(LogRecord $record): string
+    protected function normalizeRecord(LogRecord $record): array
     {
-        if (isset($record["datetime"]) && ($record["datetime"] instanceof \DateTimeInterface)) {
-            $record["timestamp"] = $record["datetime"]->format("Y-m-d\TH:i:s.uO");
-            unset($record["datetime"]);
-        }
+        $recordData = parent::normalizeRecord($record);
 
-        return parent::format($record);
+        $recordData["timestamp"] = $record->datetime->format("Y-m-d\TH:i:s.uO");
+        unset($recordData["datetime"]);
+
+        return $recordData;
     }
 }

+ 4 - 2
src/Monolog/Formatter/LogmaticFormatter.php

@@ -52,8 +52,10 @@ class LogmaticFormatter extends JsonFormatter
      * @see http://doc.logmatic.io/docs/basics-to-send-data
      * @see \Monolog\Formatter\JsonFormatter::format()
      */
-    public function format(LogRecord $record): string
+    public function normalizeRecord(LogRecord $record): array
     {
+        $record = parent::normalizeRecord($record);
+
         if (!empty($this->hostname)) {
             $record["hostname"] = $this->hostname;
         }
@@ -63,6 +65,6 @@ class LogmaticFormatter extends JsonFormatter
 
         $record["@marker"] = static::MARKERS;
 
-        return parent::format($record);
+        return $record;
     }
 }

+ 1 - 1
src/Monolog/Formatter/MongoDBFormatter.php

@@ -50,7 +50,7 @@ class MongoDBFormatter implements FormatterInterface
     public function format(LogRecord $record): array
     {
         /** @var mixed[] $res */
-        $res = $this->formatArray($record);
+        $res = $this->formatArray($record->toArray());
 
         return $res;
     }

+ 17 - 3
src/Monolog/Formatter/NormalizerFormatter.php

@@ -53,9 +53,12 @@ class NormalizerFormatter implements FormatterInterface
      */
     public function format(LogRecord $record)
     {
-        $record = $record->toArray();
+        return $this->normalizeRecord($record);
+    }
 
-        return $this->normalize($record);
+    public function normalizeValue(mixed $data): mixed
+    {
+        return $this->normalize($data);
     }
 
     /**
@@ -126,11 +129,22 @@ class NormalizerFormatter implements FormatterInterface
         return $this;
     }
 
+    /**
+     * Provided as extension point
+     *
+     * Because normalize is called with sub-values of context data etc, normalizeRecord can be
+     * extended when data needs to be appended on the record array but not to other normalized data.
+     */
+    protected function normalizeRecord(LogRecord $record): array
+    {
+        return $this->normalize($record->toArray());
+    }
+
     /**
      * @param  mixed                $data
      * @return null|scalar|array<array|scalar|null>
      */
-    protected function normalize($data, int $depth = 0)
+    protected function normalize(mixed $data, int $depth = 0): mixed
     {
         if ($depth > $this->maxNormalizeDepth) {
             return 'Over ' . $this->maxNormalizeDepth . ' levels deep, aborting normalization';

+ 4 - 8
src/Monolog/Formatter/ScalarFormatter.php

@@ -14,7 +14,7 @@ namespace Monolog\Formatter;
 use Monolog\LogRecord;
 
 /**
- * Formats data into an associative array of scalar values.
+ * Formats data into an associative array of scalar (+ null) values.
  * Objects and arrays will be JSON encoded.
  *
  * @author Andrew Lawson <adlawson@gmail.com>
@@ -29,18 +29,14 @@ class ScalarFormatter extends NormalizerFormatter
     public function format(LogRecord $record): array
     {
         $result = [];
-        foreach ($record as $key => $value) {
-            $result[$key] = $this->normalizeValue($value);
+        foreach ($record->toArray() as $key => $value) {
+            $result[$key] = $this->toScalar($value);
         }
 
         return $result;
     }
 
-    /**
-     * @param  mixed                      $value
-     * @return scalar|null
-     */
-    protected function normalizeValue($value)
+    protected function toScalar(mixed $value): string|int|float|bool|null
     {
         $normalized = $this->normalize($value);
 

+ 1 - 1
src/Monolog/Formatter/WildfireFormatter.php

@@ -129,7 +129,7 @@ class WildfireFormatter extends NormalizerFormatter
      *
      * @return null|scalar|array<array|scalar|null>|object
      */
-    protected function normalize($data, int $depth = 0)
+    protected function normalize(mixed $data, int $depth = 0): mixed
     {
         if (is_object($data) && !$data instanceof \DateTimeInterface) {
             return $data;

+ 7 - 9
src/Monolog/Handler/ChromePHPHandler.php

@@ -16,6 +16,7 @@ use Monolog\Formatter\FormatterInterface;
 use Monolog\Logger;
 use Monolog\Utils;
 use Monolog\LogRecord;
+use Monolog\DateTimeImmutable;
 
 /**
  * Handler sending logs to the ChromePHP extension (http://www.chromephp.com/)
@@ -154,15 +155,12 @@ class ChromePHPHandler extends AbstractProcessingHandler
         if (strlen($data) > 3 * 1024) {
             self::$overflowed = true;
 
-            $record = [
-                'message' => 'Incomplete logs, chrome header size limit reached',
-                'context' => [],
-                'level' => Logger::WARNING,
-                'level_name' => Logger::getLevelName(Logger::WARNING),
-                'channel' => 'monolog',
-                'datetime' => new \DateTimeImmutable(),
-                'extra' => [],
-            ];
+            $record = new LogRecord(
+                message: 'Incomplete logs, chrome header size limit reached',
+                level: Logger::WARNING,
+                channel: 'monolog',
+                datetime: new DateTimeImmutable(true),
+            );
             self::$json['rows'][count(self::$json['rows']) - 1] = $this->getFormatter()->format($record);
             $json = Utils::jsonEncode(self::$json, null, true);
             $data = base64_encode(utf8_encode($json));

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

@@ -88,7 +88,7 @@ class DynamoDbHandler extends AbstractProcessingHandler
      * @param  mixed[] $record
      * @return mixed[]
      */
-    protected function filterEmptyFields(LogRecord $record): array
+    protected function filterEmptyFields(array $record): array
     {
         return array_filter($record, function ($value) {
             return !empty($value) || false === $value || 0 === $value;

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

@@ -114,7 +114,7 @@ class FlowdockHandler extends SocketHandler
      */
     private function buildContent(LogRecord $record): string
     {
-        return Utils::jsonEncode($record['formatted']['flowdock']);
+        return Utils::jsonEncode($record['formatted']);
     }
 
     /**

+ 3 - 4
src/Monolog/Handler/MailHandler.php

@@ -51,7 +51,7 @@ abstract class MailHandler extends AbstractProcessingHandler
      * @param string $content formatted email body to be sent
      * @param array  $records the array of log records that formed this content
      *
-     * @phpstan-param Record[] $records
+     * @phpstan-param non-empty-array<LogRecord> $records
      */
     abstract protected function send(string $content, array $records): void;
 
@@ -64,10 +64,9 @@ abstract class MailHandler extends AbstractProcessingHandler
     }
 
     /**
-     * @phpstan-param non-empty-array<Record> $records
-     * @phpstan-return Record
+     * @phpstan-param non-empty-array<LogRecord> $records
      */
-    protected function getHighestRecord(array $records): array
+    protected function getHighestRecord(array $records): LogRecord
     {
         $highestRecord = null;
         foreach ($records as $record) {

+ 14 - 14
src/Monolog/Handler/PHPConsoleHandler.php

@@ -196,10 +196,10 @@ class PHPConsoleHandler extends AbstractProcessingHandler
      */
     private function handleDebugRecord(LogRecord $record): void
     {
-        $tags = $this->getRecordTags($record);
+        [$tags, $filteredContext] = $this->getRecordTags($record);
         $message = $record['message'];
-        if ($record['context']) {
-            $message .= ' ' . Utils::jsonEncode($this->connector->getDumper()->dump(array_filter($record['context'])), null, true);
+        if ($filteredContext) {
+            $message .= ' ' . Utils::jsonEncode($this->connector->getDumper()->dump(array_filter($filteredContext)), null, true);
         }
         $this->connector->getDebugDispatcher()->dispatchDebug($message, $tags, $this->options['classesPartialsTraceIgnore']);
     }
@@ -217,7 +217,7 @@ class PHPConsoleHandler extends AbstractProcessingHandler
      */
     private function handleErrorRecord(LogRecord $record): void
     {
-        $context = $record['context'];
+        $context = $record->context;
 
         $this->connector->getErrorsDispatcher()->dispatchError(
             $context['code'] ?? null,
@@ -229,28 +229,28 @@ class PHPConsoleHandler extends AbstractProcessingHandler
     }
 
     /**
-     * @phpstan-param Record $record
-     * @return string
+     * @return array{string, mixed[]}
      */
-    private function getRecordTags(array &$record)
+    private function getRecordTags(LogRecord $record): array
     {
         $tags = null;
-        if (!empty($record['context'])) {
-            $context = & $record['context'];
+        $filteredContext = [];
+        if ($record->context !== []) {
+            $filteredContext = $record->context;
             foreach ($this->options['debugTagsKeysInContext'] as $key) {
-                if (!empty($context[$key])) {
-                    $tags = $context[$key];
+                if (!empty($filteredContext[$key])) {
+                    $tags = $filteredContext[$key];
                     if ($key === 0) {
-                        array_shift($context);
+                        array_shift($filteredContext);
                     } else {
-                        unset($context[$key]);
+                        unset($filteredContext[$key]);
                     }
                     break;
                 }
             }
         }
 
-        return $tags ?: strtolower($record['level_name']);
+        return [$tags ?: strtolower($record->levelName), $filteredContext];
     }
 
     /**

+ 6 - 6
src/Monolog/Handler/Slack/SlackRecord.php

@@ -128,7 +128,6 @@ class SlackRecord
     public function getSlackData(LogRecord $record): array
     {
         $dataArray = array();
-        $record = $this->removeExcludedFields($record);
 
         if ($this->username) {
             $dataArray['username'] = $this->username;
@@ -142,9 +141,11 @@ class SlackRecord
             /** @phpstan-ignore-next-line */
             $message = $this->formatter->format($record);
         } else {
-            $message = $record['message'];
+            $message = $record->message;
         }
 
+        $record = $this->removeExcludedFields($record);
+
         if ($this->useAttachment) {
             $attachment = array(
                 'fallback'    => $message,
@@ -226,8 +227,7 @@ class SlackRecord
      */
     public function stringify(array $fields): string
     {
-        /** @var Record $fields */
-        $normalized = $this->normalizerFormatter->format($fields);
+        $normalized = $this->normalizerFormatter->normalizeValue($fields);
 
         $hasSecondDimension = count(array_filter($normalized, 'is_array'));
         $hasNonNumericKeys = !count(array_filter(array_keys($normalized), 'is_numeric'));
@@ -347,8 +347,7 @@ class SlackRecord
      */
     private function generateAttachmentFields(array $data): array
     {
-        /** @var Record $data */
-        $normalized = $this->normalizerFormatter->format($data);
+        $normalized = $this->normalizerFormatter->normalizeValue($data);
 
         $fields = array();
         foreach ($normalized as $key => $value) {
@@ -367,6 +366,7 @@ class SlackRecord
      */
     private function removeExcludedFields(LogRecord $record): array
     {
+        $record = $record->toArray();
         foreach ($this->excludeFields as $field) {
             $keys = explode('.', $field);
             $node = &$record;

+ 7 - 6
src/Monolog/Handler/TestHandler.php

@@ -14,6 +14,7 @@ namespace Monolog\Handler;
 use Monolog\Logger;
 use Psr\Log\LogLevel;
 use Monolog\LogRecord;
+use Monolog\DateTimeImmutable;
 
 /**
  * Used for testing purposes.
@@ -125,16 +126,16 @@ class TestHandler extends AbstractProcessingHandler
     }
 
     /**
-     * @param string|LogRecord $record Either a message string or an array containing message and optionally context keys that will be checked against all records
+     * @param string|array $record Either a message string or an array containing message and optionally context keys that will be checked against all records
      * @param string|int   $level  Logging level value or name
      *
      * @phpstan-param array{message: string, context?: mixed[]}|string $record
      * @phpstan-param Level|LevelName|LogLevel::*                      $level
      */
-    public function hasRecord($record, $level): bool
+    public function hasRecord(string|array $record, $level): bool
     {
         if (is_string($record)) {
-            $record = array('message' => $record);
+            $record = ['message' => $record];
         }
 
         return $this->hasRecordThatPasses(function (LogRecord $rec) use ($record) {
@@ -168,8 +169,8 @@ class TestHandler extends AbstractProcessingHandler
      */
     public function hasRecordThatMatches(string $regex, $level): bool
     {
-        return $this->hasRecordThatPasses(function (array $rec) use ($regex): bool {
-            return preg_match($regex, $rec['message']) > 0;
+        return $this->hasRecordThatPasses(function (LogRecord $rec) use ($regex): bool {
+            return preg_match($regex, $rec->message) > 0;
         }, $level);
     }
 
@@ -202,7 +203,7 @@ class TestHandler extends AbstractProcessingHandler
      */
     protected function write(LogRecord $record): void
     {
-        $this->recordsByLevel[$record['level']][] = $record;
+        $this->recordsByLevel[$record->level][] = $record;
         $this->records[] = $record;
     }
 

+ 3 - 1
src/Monolog/Logger.php

@@ -301,6 +301,7 @@ class Logger implements LoggerInterface, ResettableInterface
             datetime: new DateTimeImmutable($this->microsecondTimestamps, $this->timezone),
             extra: [],
         );
+        $handled = false;
 
         foreach ($this->handlers as $handler) {
             if (false === $recordInitialized) {
@@ -323,6 +324,7 @@ class Logger implements LoggerInterface, ResettableInterface
 
             // once the record is initialized, send it to all handlers as long as the bubbling chain is not interrupted
             try {
+                $handled = true;
                 if (true === $handler->handle($record)) {
                     break;
                 }
@@ -333,7 +335,7 @@ class Logger implements LoggerInterface, ResettableInterface
             }
         }
 
-        return null !== $record;
+        return $handled;
     }
 
     /**

+ 36 - 46
tests/Monolog/Formatter/ChromePHPFormatterTest.php

@@ -12,8 +12,9 @@
 namespace Monolog\Formatter;
 
 use Monolog\Logger;
+use Monolog\Test\TestCase;
 
-class ChromePHPFormatterTest extends \PHPUnit\Framework\TestCase
+class ChromePHPFormatterTest extends TestCase
 {
     /**
      * @covers Monolog\Formatter\ChromePHPFormatter::format
@@ -21,15 +22,14 @@ class ChromePHPFormatterTest extends \PHPUnit\Framework\TestCase
     public function testDefaultFormat()
     {
         $formatter = new ChromePHPFormatter();
-        $record = [
-            'level' => Logger::ERROR,
-            'level_name' => 'ERROR',
-            'channel' => 'meh',
-            'context' => ['from' => 'logger'],
-            'datetime' => new \DateTimeImmutable("@0"),
-            'extra' => ['ip' => '127.0.0.1'],
-            'message' => 'log',
-        ];
+        $record = $this->getRecord(
+            Logger::ERROR,
+            'log',
+            channel: 'meh',
+            context: ['from' => 'logger'],
+            datetime: new \DateTimeImmutable("@0"),
+            extra: ['ip' => '127.0.0.1'],
+        );
 
         $message = $formatter->format($record);
 
@@ -54,15 +54,14 @@ class ChromePHPFormatterTest extends \PHPUnit\Framework\TestCase
     public function testFormatWithFileAndLine()
     {
         $formatter = new ChromePHPFormatter();
-        $record = [
-            'level' => Logger::CRITICAL,
-            'level_name' => 'CRITICAL',
-            'channel' => 'meh',
-            'context' => ['from' => 'logger'],
-            'datetime' => new \DateTimeImmutable("@0"),
-            'extra' => ['ip' => '127.0.0.1', 'file' => 'test', 'line' => 14],
-            'message' => 'log',
-        ];
+        $record = $this->getRecord(
+            Logger::CRITICAL,
+            'log',
+            channel: 'meh',
+            context: ['from' => 'logger'],
+            datetime: new \DateTimeImmutable("@0"),
+            extra: ['ip' => '127.0.0.1', 'file' => 'test', 'line' => 14],
+        );
 
         $message = $formatter->format($record);
 
@@ -87,15 +86,12 @@ class ChromePHPFormatterTest extends \PHPUnit\Framework\TestCase
     public function testFormatWithoutContext()
     {
         $formatter = new ChromePHPFormatter();
-        $record = [
-            'level' => Logger::DEBUG,
-            'level_name' => 'DEBUG',
-            'channel' => 'meh',
-            'context' => [],
-            'datetime' => new \DateTimeImmutable("@0"),
-            'extra' => [],
-            'message' => 'log',
-        ];
+        $record = $this->getRecord(
+            Logger::DEBUG,
+            'log',
+            channel: 'meh',
+            datetime: new \DateTimeImmutable("@0"),
+        );
 
         $message = $formatter->format($record);
 
@@ -117,24 +113,18 @@ class ChromePHPFormatterTest extends \PHPUnit\Framework\TestCase
     {
         $formatter = new ChromePHPFormatter();
         $records = [
-            [
-                'level' => Logger::INFO,
-                'level_name' => 'INFO',
-                'channel' => 'meh',
-                'context' => [],
-                'datetime' => new \DateTimeImmutable("@0"),
-                'extra' => [],
-                'message' => 'log',
-            ],
-            [
-                'level' => Logger::WARNING,
-                'level_name' => 'WARNING',
-                'channel' => 'foo',
-                'context' => [],
-                'datetime' => new \DateTimeImmutable("@0"),
-                'extra' => [],
-                'message' => 'log2',
-            ],
+            $this->getRecord(
+                Logger::INFO,
+                'log',
+                channel: 'meh',
+                datetime: new \DateTimeImmutable("@0"),
+            ),
+            $this->getRecord(
+                Logger::WARNING,
+                'log2',
+                channel: 'foo',
+                datetime: new \DateTimeImmutable("@0"),
+            ),
         ];
 
         $this->assertEquals(

+ 6 - 7
tests/Monolog/Formatter/ElasticaFormatterTest.php

@@ -13,8 +13,9 @@ namespace Monolog\Formatter;
 
 use Monolog\Logger;
 use Monolog\LogRecord;
+use Monolog\Test\TestCase;
 
-class ElasticaFormatterTest extends \PHPUnit\Framework\TestCase
+class ElasticaFormatterTest extends TestCase
 {
     public function setUp(): void
     {
@@ -31,18 +32,16 @@ class ElasticaFormatterTest extends \PHPUnit\Framework\TestCase
     public function testFormat()
     {
         // test log message
-        $msg = new LogRecord(
-            level: Logger::ERROR,
-            levelName: 'ERROR',
+        $msg = $this->getRecord(
+            Logger::ERROR,
+            'log',
             channel: 'meh',
             context: ['foo' => 7, 'bar', 'class' => new \stdClass],
             datetime: new \DateTimeImmutable("@0"),
-            message: 'log',
         );
 
         // expected values
-        $expected = (array) $msg;
-        unset($expected['formatted']);
+        $expected = $msg->toArray();
         $expected['datetime'] = '1970-01-01T00:00:00.000000+00:00';
         $expected['context'] = [
             'class' => ['stdClass' => []],

+ 10 - 11
tests/Monolog/Formatter/ElasticsearchFormatterTest.php

@@ -12,8 +12,9 @@
 namespace Monolog\Formatter;
 
 use Monolog\Logger;
+use Monolog\Test\TestCase;
 
-class ElasticsearchFormatterTest extends \PHPUnit\Framework\TestCase
+class ElasticsearchFormatterTest extends TestCase
 {
     /**
      * @covers Monolog\Formatter\ElasticsearchFormatter::__construct
@@ -23,18 +24,16 @@ class ElasticsearchFormatterTest extends \PHPUnit\Framework\TestCase
     public function testFormat()
     {
         // Test log message
-        $msg = [
-            'level' => Logger::ERROR,
-            'level_name' => 'ERROR',
-            'channel' => 'meh',
-            'context' => ['foo' => 7, 'bar', 'class' => new \stdClass],
-            'datetime' => new \DateTimeImmutable("@0"),
-            'extra' => [],
-            'message' => 'log',
-        ];
+        $msg = $this->getRecord(
+            Logger::ERROR,
+            'log',
+            channel: 'meh',
+            context: ['foo' => 7, 'bar', 'class' => new \stdClass],
+            datetime: new \DateTimeImmutable("@0"),
+        );
 
         // Expected values
-        $expected = $msg;
+        $expected = $msg->toArray();
         $expected['datetime'] = '1970-01-01T00:00:00+0000';
         $expected['context'] = [
             'class' => ['stdClass' => []],

+ 3 - 3
tests/Monolog/Formatter/FlowdockFormatterTest.php

@@ -34,7 +34,7 @@ class FlowdockFormatterTest extends TestCase
         ];
         $formatted = $formatter->format($record);
 
-        $this->assertEquals($expected, $formatted['flowdock']);
+        $this->assertEquals($expected, $formatted);
     }
 
     /**
@@ -49,7 +49,7 @@ class FlowdockFormatterTest extends TestCase
         ];
         $formatted = $formatter->formatBatch($records);
 
-        $this->assertArrayHasKey('flowdock', $formatted[0]);
-        $this->assertArrayHasKey('flowdock', $formatted[1]);
+        $this->assertArrayHasKey('from_address', $formatted[0]);
+        $this->assertArrayHasKey('from_address', $formatted[1]);
     }
 }

+ 2 - 4
tests/Monolog/Formatter/FluentdFormatterTest.php

@@ -35,8 +35,7 @@ class FluentdFormatterTest extends TestCase
      */
     public function testFormat()
     {
-        $record = $this->getRecord(Logger::WARNING);
-        $record['datetime'] = new \DateTimeImmutable("@0");
+        $record = $this->getRecord(Logger::WARNING, datetime: new \DateTimeImmutable("@0"));
 
         $formatter = new FluentdFormatter();
         $this->assertEquals(
@@ -50,8 +49,7 @@ class FluentdFormatterTest extends TestCase
      */
     public function testFormatWithTag()
     {
-        $record = $this->getRecord(Logger::ERROR);
-        $record['datetime'] = new \DateTimeImmutable("@0");
+        $record = $this->getRecord(Logger::ERROR, datetime: new \DateTimeImmutable("@0"));
 
         $formatter = new FluentdFormatter(true);
         $this->assertEquals(

+ 61 - 88
tests/Monolog/Formatter/GelfMessageFormatterTest.php

@@ -12,7 +12,7 @@
 namespace Monolog\Formatter;
 
 use Monolog\Logger;
-use PHPUnit\Framework\TestCase;
+use Monolog\Test\TestCase;
 
 class GelfMessageFormatterTest extends TestCase
 {
@@ -29,15 +29,12 @@ class GelfMessageFormatterTest extends TestCase
     public function testDefaultFormatter()
     {
         $formatter = new GelfMessageFormatter();
-        $record = [
-            'level' => Logger::ERROR,
-            'level_name' => 'ERROR',
-            'channel' => 'meh',
-            'context' => [],
-            'datetime' => new \DateTimeImmutable("@0"),
-            'extra' => [],
-            'message' => 'log',
-        ];
+        $record = $this->getRecord(
+            Logger::ERROR,
+            'log',
+            channel: 'meh',
+            datetime: new \DateTimeImmutable("@0"),
+        );
 
         $message = $formatter->format($record);
 
@@ -64,15 +61,14 @@ class GelfMessageFormatterTest extends TestCase
     public function testFormatWithFileAndLine()
     {
         $formatter = new GelfMessageFormatter();
-        $record = [
-            'level' => Logger::ERROR,
-            'level_name' => 'ERROR',
-            'channel' => 'meh',
-            'context' => ['from' => 'logger'],
-            'datetime' => new \DateTimeImmutable("@0"),
-            'extra' => ['file' => 'test', 'line' => 14],
-            'message' => 'log',
-        ];
+        $record = $this->getRecord(
+            Logger::ERROR,
+            'log',
+            channel: 'meh',
+            context: ['from' => 'logger'],
+            datetime: new \DateTimeImmutable("@0"),
+            extra: ['file' => 'test', 'line' => 14],
+        );
 
         $message = $formatter->format($record);
 
@@ -81,37 +77,20 @@ class GelfMessageFormatterTest extends TestCase
         $this->assertEquals(14, $message->getLine());
     }
 
-    /**
-     * @covers Monolog\Formatter\GelfMessageFormatter::format
-     */
-    public function testFormatInvalidFails()
-    {
-        $formatter = new GelfMessageFormatter();
-        $record = [
-            'level' => Logger::ERROR,
-            'level_name' => 'ERROR',
-        ];
-
-        $this->expectException(\InvalidArgumentException::class);
-
-        $formatter->format($record);
-    }
-
     /**
      * @covers Monolog\Formatter\GelfMessageFormatter::format
      */
     public function testFormatWithContext()
     {
         $formatter = new GelfMessageFormatter();
-        $record = [
-            'level' => Logger::ERROR,
-            'level_name' => 'ERROR',
-            'channel' => 'meh',
-            'context' => ['from' => 'logger'],
-            'datetime' => new \DateTimeImmutable("@0"),
-            'extra' => ['key' => 'pair'],
-            'message' => 'log',
-        ];
+        $record = $this->getRecord(
+            Logger::ERROR,
+            'log',
+            channel: 'meh',
+            context: ['from' => 'logger'],
+            datetime: new \DateTimeImmutable("@0"),
+            extra: ['key' => 'pair'],
+        );
 
         $message = $formatter->format($record);
 
@@ -140,19 +119,17 @@ class GelfMessageFormatterTest extends TestCase
     public function testFormatWithContextContainingException()
     {
         $formatter = new GelfMessageFormatter();
-        $record = [
-            'level' => Logger::ERROR,
-            'level_name' => 'ERROR',
-            'channel' => 'meh',
-            'context' => ['from' => 'logger', 'exception' => [
+        $record = $this->getRecord(
+            Logger::ERROR,
+            'log',
+            channel: 'meh',
+            context: ['from' => 'logger', 'exception' => [
                 'class' => '\Exception',
                 'file'  => '/some/file/in/dir.php:56',
                 'trace' => ['/some/file/1.php:23', '/some/file/2.php:3'],
             ]],
-            'datetime' => new \DateTimeImmutable("@0"),
-            'extra' => [],
-            'message' => 'log',
-        ];
+            datetime: new \DateTimeImmutable("@0"),
+        );
 
         $message = $formatter->format($record);
 
@@ -168,15 +145,14 @@ class GelfMessageFormatterTest extends TestCase
     public function testFormatWithExtra()
     {
         $formatter = new GelfMessageFormatter();
-        $record = [
-            'level' => Logger::ERROR,
-            'level_name' => 'ERROR',
-            'channel' => 'meh',
-            'context' => ['from' => 'logger'],
-            'datetime' => new \DateTimeImmutable("@0"),
-            'extra' => ['key' => 'pair'],
-            'message' => 'log',
-        ];
+        $record = $this->getRecord(
+            Logger::ERROR,
+            'log',
+            channel: 'meh',
+            context: ['from' => 'logger'],
+            datetime: new \DateTimeImmutable("@0"),
+            extra: ['key' => 'pair'],
+        );
 
         $message = $formatter->format($record);
 
@@ -202,15 +178,14 @@ class GelfMessageFormatterTest extends TestCase
     public function testFormatWithLargeData()
     {
         $formatter = new GelfMessageFormatter();
-        $record = [
-            'level' => Logger::ERROR,
-            'level_name' => 'ERROR',
-            'channel' => 'meh',
-            'context' => ['exception' => str_repeat(' ', 32767)],
-            'datetime' => new \DateTimeImmutable("@0"),
-            'extra' => ['key' => str_repeat(' ', 32767)],
-            'message' => 'log',
-        ];
+        $record = $this->getRecord(
+            Logger::ERROR,
+            'log',
+            channel: 'meh',
+            context: ['exception' => str_repeat(' ', 32767)],
+            datetime: new \DateTimeImmutable("@0"),
+            extra: ['key' => str_repeat(' ', 32767)],
+        );
         $message = $formatter->format($record);
         $messageArray = $message->toArray();
 
@@ -229,14 +204,13 @@ class GelfMessageFormatterTest extends TestCase
     public function testFormatWithUnlimitedLength()
     {
         $formatter = new GelfMessageFormatter('LONG_SYSTEM_NAME', null, 'ctxt_', PHP_INT_MAX);
-        $record = array(
-            'level' => Logger::ERROR,
-            'level_name' => 'ERROR',
-            'channel' => 'meh',
-            'context' => array('exception' => str_repeat(' ', 32767 * 2)),
-            'datetime' => new \DateTime("@0"),
-            'extra' => array('key' => str_repeat(' ', 32767 * 2)),
-            'message' => 'log',
+        $record = $this->getRecord(
+            Logger::ERROR,
+            'log',
+            channel: 'meh',
+            context: ['exception' => str_repeat(' ', 32767 * 2)],
+            datetime: new \DateTimeImmutable("@0"),
+            extra: ['key' => str_repeat(' ', 32767 * 2)],
         );
         $message = $formatter->format($record);
         $messageArray = $message->toArray();
@@ -256,15 +230,14 @@ class GelfMessageFormatterTest extends TestCase
     public function testFormatWithLargeCyrillicData()
     {
         $formatter = new GelfMessageFormatter();
-        $record = [
-            'level' => Logger::ERROR,
-            'level_name' => 'ERROR',
-            'channel' => 'meh',
-            'context' => ['exception' => str_repeat('а', 32767)],
-            'datetime' => new \DateTimeImmutable("@0"),
-            'extra' => ['key' => str_repeat('б', 32767)],
-            'message' => str_repeat('в', 32767),
-        ];
+        $record = $this->getRecord(
+            Logger::ERROR,
+            str_repeat('в', 32767),
+            channel: 'meh',
+            context: ['exception' => str_repeat('а', 32767)],
+            datetime: new \DateTimeImmutable("@0"),
+            extra: ['key' => str_repeat('б', 32767)],
+        );
         $message = $formatter->format($record);
         $messageArray = $message->toArray();
 

+ 34 - 44
tests/Monolog/Formatter/JsonFormatterTest.php

@@ -12,6 +12,7 @@
 namespace Monolog\Formatter;
 
 use Monolog\Logger;
+use Monolog\LogRecord;
 use Monolog\Test\TestCase;
 
 class JsonFormatterTest extends TestCase
@@ -38,8 +39,7 @@ class JsonFormatterTest extends TestCase
     {
         $formatter = new JsonFormatter();
         $record = $this->getRecord();
-        $record['context'] = $record['extra'] = new \stdClass;
-        $this->assertEquals(json_encode($record)."\n", $formatter->format($record));
+        $this->assertEquals(json_encode($record->toArray(), JSON_FORCE_OBJECT)."\n", $formatter->format($record));
 
         $formatter = new JsonFormatter(JsonFormatter::BATCH_MODE_JSON, false);
         $record = $this->getRecord();
@@ -54,8 +54,7 @@ class JsonFormatterTest extends TestCase
         $formatter = new JsonFormatter();
         $formatter->setJsonPrettyPrint(true);
         $record = $this->getRecord();
-        $record['context'] = $record['extra'] = new \stdClass;
-        $this->assertEquals(json_encode($record, JSON_PRETTY_PRINT)."\n", $formatter->format($record));
+        $this->assertEquals(json_encode($record->toArray(), JSON_PRETTY_PRINT | JSON_FORCE_OBJECT)."\n", $formatter->format($record));
 
         $formatter = new JsonFormatter(JsonFormatter::BATCH_MODE_JSON, false);
         $formatter->setJsonPrettyPrint(true);
@@ -99,14 +98,11 @@ class JsonFormatterTest extends TestCase
     public function testFormatBatchNewlines()
     {
         $formatter = new JsonFormatter(JsonFormatter::BATCH_MODE_NEWLINES);
-        $records = $expected = [
+        $records = [
             $this->getRecord(Logger::WARNING),
             $this->getRecord(Logger::DEBUG),
         ];
-        array_walk($expected, function (&$value, $key) {
-            $value['context'] = $value['extra'] = new \stdClass;
-            $value = json_encode($value);
-        });
+        $expected = array_map(fn (LogRecord $record) => json_encode($record->toArray(), JSON_FORCE_OBJECT), $records);
         $this->assertEquals(implode("\n", $expected), $formatter->formatBatch($records));
     }
 
@@ -165,7 +161,7 @@ class JsonFormatterTest extends TestCase
         $message = $this->formatRecordWithExceptionInContext($formatter, $throwable);
 
         $this->assertEquals(
-            '{"...":"Over 0 items (6 total), aborting normalization"}'."\n",
+            '{"...":"Over 0 items (7 total), aborting normalization"}'."\n",
             $message
         );
     }
@@ -180,7 +176,7 @@ class JsonFormatterTest extends TestCase
         $message = $this->formatRecordWithExceptionInContext($formatter, $throwable);
 
         $this->assertEquals(
-            '{"level_name":"CRITICAL","channel":"core","...":"Over 2 items (6 total), aborting normalization"}'."\n",
+            '{"message":"foobar","context":{"exception":{"class":"Error","message":"Foo","code":0,"file":"'.__FILE__.':'.(__LINE__ - 5).'"}},"...":"Over 2 items (7 total), aborting normalization"}'."\n",
             $message
         );
     }
@@ -188,8 +184,9 @@ class JsonFormatterTest extends TestCase
     public function testDefFormatWithResource()
     {
         $formatter = new JsonFormatter(JsonFormatter::BATCH_MODE_JSON, false);
-        $record = $this->getRecord();
-        $record['context'] = ['field_resource' => opendir(__DIR__)];
+        $record = $this->getRecord(
+            context: ['field_resource' => opendir(__DIR__)],
+        );
         $this->assertEquals('{"message":"test","context":{"field_resource":"[resource(stream)]"},"level":300,"level_name":"WARNING","channel":"test","datetime":"'.$record['datetime']->format('Y-m-d\TH:i:s.uP').'","extra":{}}', $formatter->format($record));
     }
 
@@ -202,7 +199,7 @@ class JsonFormatterTest extends TestCase
     private function assertContextContainsFormattedException($expected, $actual)
     {
         $this->assertEquals(
-            '{"level_name":"CRITICAL","channel":"core","context":{"exception":'.$expected.'},"datetime":null,"extra":{},"message":"foobar"}'."\n",
+            '{"message":"foobar","context":{"exception":'.$expected.'},"level":500,"level_name":"CRITICAL","channel":"core","datetime":"2022-02-22T00:00:00+00:00","extra":{}}'."\n",
             $actual
         );
     }
@@ -215,14 +212,13 @@ class JsonFormatterTest extends TestCase
      */
     private function formatRecordWithExceptionInContext(JsonFormatter $formatter, \Throwable $exception)
     {
-        $message = $formatter->format([
-            'level_name' => 'CRITICAL',
-            'channel' => 'core',
-            'context' => ['exception' => $exception],
-            'datetime' => null,
-            'extra' => [],
-            'message' => 'foobar',
-        ]);
+        $message = $formatter->format($this->getRecord(
+            Logger::CRITICAL,
+            'foobar',
+            channel: 'core',
+            context: ['exception' => $exception],
+            datetime: new \DateTimeImmutable('2022-02-22 00:00:00'),
+        ));
 
         return $message;
     }
@@ -265,13 +261,11 @@ class JsonFormatterTest extends TestCase
         $formatter = new NormalizerFormatter();
         $largeArray = range(1, 1000);
 
-        $res = $formatter->format(array(
-            'level_name' => 'CRITICAL',
-            'channel' => 'test',
-            'message' => 'bar',
-            'context' => array($largeArray),
-            'datetime' => new \DateTime,
-            'extra' => array(),
+        $res = $formatter->format($this->getRecord(
+            Logger::CRITICAL,
+            'bar',
+            channel: 'test',
+            context: array($largeArray),
         ));
 
         $this->assertCount(1000, $res['context'][0]);
@@ -283,13 +277,11 @@ class JsonFormatterTest extends TestCase
         $formatter = new NormalizerFormatter();
         $largeArray = range(1, 2000);
 
-        $res = $formatter->format(array(
-            'level_name' => 'CRITICAL',
-            'channel' => 'test',
-            'message' => 'bar',
-            'context' => array($largeArray),
-            'datetime' => new \DateTime,
-            'extra' => array(),
+        $res = $formatter->format($this->getRecord(
+            Logger::CRITICAL,
+            'bar',
+            channel: 'test',
+            context: array($largeArray),
         ));
 
         $this->assertCount(1001, $res['context'][0]);
@@ -300,17 +292,15 @@ class JsonFormatterTest extends TestCase
     {
         $formatter = new JsonFormatter(JsonFormatter::BATCH_MODE_JSON, true, true);
 
-        $record = $formatter->format(array(
-            'level' => 100,
-            'level_name' => 'DEBUG',
-            'channel' => 'test',
-            'message' => 'Testing',
-            'context' => array(),
-            'extra' => array(),
+        $record = $formatter->format($this->getRecord(
+            Logger::DEBUG,
+            'Testing',
+            channel: 'test',
+            datetime: new \DateTimeImmutable('2022-02-22 00:00:00'),
         ));
 
         $this->assertSame(
-            '{"level":100,"level_name":"DEBUG","channel":"test","message":"Testing"}'."\n",
+            '{"message":"Testing","level":100,"level_name":"DEBUG","channel":"test","datetime":"2022-02-22T00:00:00+00:00"}'."\n",
             $record
         );
     }

+ 94 - 132
tests/Monolog/Formatter/LineFormatterTest.php

@@ -11,111 +11,101 @@
 
 namespace Monolog\Formatter;
 
+use Monolog\Test\TestCase;
+use Monolog\Logger;
+
 /**
  * @covers Monolog\Formatter\LineFormatter
  */
-class LineFormatterTest extends \PHPUnit\Framework\TestCase
+class LineFormatterTest extends TestCase
 {
     public function testDefFormatWithString()
     {
         $formatter = new LineFormatter(null, 'Y-m-d');
-        $message = $formatter->format([
-            'level_name' => 'WARNING',
-            'channel' => 'log',
-            'context' => [],
-            'message' => 'foo',
-            'datetime' => new \DateTimeImmutable,
-            'extra' => [],
-        ]);
+        $message = $formatter->format($this->getRecord(
+            Logger::WARNING,
+            'foo',
+            channel: 'log',
+        ));
         $this->assertEquals('['.date('Y-m-d').'] log.WARNING: foo [] []'."\n", $message);
     }
 
     public function testDefFormatWithArrayContext()
     {
         $formatter = new LineFormatter(null, 'Y-m-d');
-        $message = $formatter->format([
-            'level_name' => 'ERROR',
-            'channel' => 'meh',
-            'message' => 'foo',
-            'datetime' => new \DateTimeImmutable,
-            'extra' => [],
-            'context' => [
+        $message = $formatter->format($this->getRecord(
+            Logger::ERROR,
+            'foo',
+            channel: 'meh',
+            context: [
                 'foo' => 'bar',
                 'baz' => 'qux',
                 'bool' => false,
                 'null' => null,
             ],
-        ]);
+        ));
         $this->assertEquals('['.date('Y-m-d').'] meh.ERROR: foo {"foo":"bar","baz":"qux","bool":false,"null":null} []'."\n", $message);
     }
 
     public function testDefFormatExtras()
     {
         $formatter = new LineFormatter(null, 'Y-m-d');
-        $message = $formatter->format([
-            'level_name' => 'ERROR',
-            'channel' => 'meh',
-            'context' => [],
-            'datetime' => new \DateTimeImmutable,
-            'extra' => ['ip' => '127.0.0.1'],
-            'message' => 'log',
-        ]);
+        $message = $formatter->format($this->getRecord(
+            Logger::ERROR,
+            'log',
+            channel: 'meh',
+            extra: ['ip' => '127.0.0.1'],
+        ));
         $this->assertEquals('['.date('Y-m-d').'] meh.ERROR: log [] {"ip":"127.0.0.1"}'."\n", $message);
     }
 
     public function testFormatExtras()
     {
         $formatter = new LineFormatter("[%datetime%] %channel%.%level_name%: %message% %context% %extra.file% %extra%\n", 'Y-m-d');
-        $message = $formatter->format([
-            'level_name' => 'ERROR',
-            'channel' => 'meh',
-            'context' => [],
-            'datetime' => new \DateTimeImmutable,
-            'extra' => ['ip' => '127.0.0.1', 'file' => 'test'],
-            'message' => 'log',
-        ]);
+        $message = $formatter->format($this->getRecord(
+            Logger::ERROR,
+            'log',
+            channel: 'meh',
+            extra: ['ip' => '127.0.0.1', 'file' => 'test'],
+        ));
         $this->assertEquals('['.date('Y-m-d').'] meh.ERROR: log [] test {"ip":"127.0.0.1"}'."\n", $message);
     }
 
     public function testContextAndExtraOptionallyNotShownIfEmpty()
     {
         $formatter = new LineFormatter(null, 'Y-m-d', false, true);
-        $message = $formatter->format([
-            'level_name' => 'ERROR',
-            'channel' => 'meh',
-            'context' => [],
-            'datetime' => new \DateTimeImmutable,
-            'extra' => [],
-            'message' => 'log',
-        ]);
+        $message = $formatter->format($this->getRecord(
+            Logger::ERROR,
+            'log',
+            channel: 'meh',
+        ));
         $this->assertEquals('['.date('Y-m-d').'] meh.ERROR: log  '."\n", $message);
     }
 
     public function testContextAndExtraReplacement()
     {
         $formatter = new LineFormatter('%context.foo% => %extra.foo%');
-        $message = $formatter->format([
-            'level_name' => 'ERROR',
-            'channel' => 'meh',
-            'context' => ['foo' => 'bar'],
-            'datetime' => new \DateTimeImmutable,
-            'extra' => ['foo' => 'xbar'],
-            'message' => 'log',
-        ]);
+        $message = $formatter->format($this->getRecord(
+            Logger::ERROR,
+            'log',
+            channel: 'meh',
+            context: ['foo' => 'bar'],
+            extra: ['foo' => 'xbar'],
+        ));
+
         $this->assertEquals('bar => xbar', $message);
     }
 
     public function testDefFormatWithObject()
     {
         $formatter = new LineFormatter(null, 'Y-m-d');
-        $message = $formatter->format([
-            'level_name' => 'ERROR',
-            'channel' => 'meh',
-            'context' => [],
-            'datetime' => new \DateTimeImmutable,
-            'extra' => ['foo' => new TestFoo, 'bar' => new TestBar, 'baz' => [], 'res' => fopen('php://memory', 'rb')],
-            'message' => 'foobar',
-        ]);
+        $message = $formatter->format($this->getRecord(
+            Logger::ERROR,
+            'foobar',
+            channel: 'meh',
+            context: [],
+            extra: ['foo' => new TestFoo, 'bar' => new TestBar, 'baz' => [], 'res' => fopen('php://memory', 'rb')],
+        ));
 
         $this->assertEquals('['.date('Y-m-d').'] meh.ERROR: foobar [] {"foo":{"Monolog\\\\Formatter\\\\TestFoo":{"foo":"fooValue"}},"bar":{"Monolog\\\\Formatter\\\\TestBar":"bar"},"baz":[],"res":"[resource(stream)]"}'."\n", $message);
     }
@@ -123,54 +113,48 @@ class LineFormatterTest extends \PHPUnit\Framework\TestCase
     public function testDefFormatWithException()
     {
         $formatter = new LineFormatter(null, 'Y-m-d');
-        $message = $formatter->format([
-            'level_name' => 'CRITICAL',
-            'channel' => 'core',
-            'context' => ['exception' => new \RuntimeException('Foo')],
-            'datetime' => new \DateTimeImmutable,
-            'extra' => [],
-            'message' => 'foobar',
-        ]);
+        $message = $formatter->format($this->getRecord(
+            Logger::CRITICAL,
+            'foobar',
+            channel: 'core',
+            context: ['exception' => new \RuntimeException('Foo')],
+        ));
 
         $path = str_replace('\\/', '/', json_encode(__FILE__));
 
-        $this->assertEquals('['.date('Y-m-d').'] core.CRITICAL: foobar {"exception":"[object] (RuntimeException(code: 0): Foo at '.substr($path, 1, -1).':'.(__LINE__ - 8).')"} []'."\n", $message);
+        $this->assertEquals('['.date('Y-m-d').'] core.CRITICAL: foobar {"exception":"[object] (RuntimeException(code: 0): Foo at '.substr($path, 1, -1).':'.(__LINE__ - 5).')"} []'."\n", $message);
     }
 
     public function testDefFormatWithExceptionAndStacktrace()
     {
         $formatter = new LineFormatter(null, 'Y-m-d');
         $formatter->includeStacktraces();
-        $message = $formatter->format([
-            'level_name' => 'CRITICAL',
-            'channel' => 'core',
-            'context' => ['exception' => new \RuntimeException('Foo')],
-            'datetime' => new \DateTimeImmutable,
-            'extra' => [],
-            'message' => 'foobar',
-        ]);
+        $message = $formatter->format($this->getRecord(
+            Logger::CRITICAL,
+            'foobar',
+            channel: 'core',
+            context: ['exception' => new \RuntimeException('Foo')],
+        ));
 
         $path = str_replace('\\/', '/', json_encode(__FILE__));
 
-        $this->assertMatchesRegularExpression('{^\['.date('Y-m-d').'] core\.CRITICAL: foobar \{"exception":"\[object] \(RuntimeException\(code: 0\): Foo at '.preg_quote(substr($path, 1, -1)).':'.(__LINE__ - 8).'\)\n\[stacktrace]\n#0}', $message);
+        $this->assertMatchesRegularExpression('{^\['.date('Y-m-d').'] core\.CRITICAL: foobar \{"exception":"\[object] \(RuntimeException\(code: 0\): Foo at '.preg_quote(substr($path, 1, -1)).':'.(__LINE__ - 5).'\)\n\[stacktrace]\n#0}', $message);
     }
 
     public function testDefFormatWithPreviousException()
     {
         $formatter = new LineFormatter(null, 'Y-m-d');
         $previous = new \LogicException('Wut?');
-        $message = $formatter->format([
-            'level_name' => 'CRITICAL',
-            'channel' => 'core',
-            'context' => ['exception' => new \RuntimeException('Foo', 0, $previous)],
-            'datetime' => new \DateTimeImmutable,
-            'extra' => [],
-            'message' => 'foobar',
-        ]);
+        $message = $formatter->format($this->getRecord(
+            Logger::CRITICAL,
+            'foobar',
+            channel: 'core',
+            context: ['exception' => new \RuntimeException('Foo', 0, $previous)],
+        ));
 
         $path = str_replace('\\/', '/', json_encode(__FILE__));
 
-        $this->assertEquals('['.date('Y-m-d').'] core.CRITICAL: foobar {"exception":"[object] (RuntimeException(code: 0): Foo at '.substr($path, 1, -1).':'.(__LINE__ - 8).')\n[previous exception] [object] (LogicException(code: 0): Wut? at '.substr($path, 1, -1).':'.(__LINE__ - 12).')"} []'."\n", $message);
+        $this->assertEquals('['.date('Y-m-d').'] core.CRITICAL: foobar {"exception":"[object] (RuntimeException(code: 0): Foo at '.substr($path, 1, -1).':'.(__LINE__ - 5).')\n[previous exception] [object] (LogicException(code: 0): Wut? at '.substr($path, 1, -1).':'.(__LINE__ - 10).')"} []'."\n", $message);
     }
 
     public function testDefFormatWithSoapFaultException()
@@ -180,53 +164,43 @@ class LineFormatterTest extends \PHPUnit\Framework\TestCase
         }
 
         $formatter = new LineFormatter(null, 'Y-m-d');
-        $message = $formatter->format([
-            'level_name' => 'CRITICAL',
-            'channel' => 'core',
-            'context' => ['exception' => new \SoapFault('foo', 'bar', 'hello', 'world')],
-            'datetime' => new \DateTimeImmutable,
-            'extra' => [],
-            'message' => 'foobar',
-        ]);
+        $message = $formatter->format($this->getRecord(
+            Logger::CRITICAL,
+            'foobar',
+            channel: 'core',
+            context: ['exception' => new \SoapFault('foo', 'bar', 'hello', 'world')],
+        ));
 
         $path = str_replace('\\/', '/', json_encode(__FILE__));
 
-        $this->assertEquals('['.date('Y-m-d').'] core.CRITICAL: foobar {"exception":"[object] (SoapFault(code: 0 faultcode: foo faultactor: hello detail: world): bar at '.substr($path, 1, -1).':'.(__LINE__ - 8).')"} []'."\n", $message);
+        $this->assertEquals('['.date('Y-m-d').'] core.CRITICAL: foobar {"exception":"[object] (SoapFault(code: 0 faultcode: foo faultactor: hello detail: world): bar at '.substr($path, 1, -1).':'.(__LINE__ - 5).')"} []'."\n", $message);
 
-        $message = $formatter->format([
-            'level_name' => 'CRITICAL',
-            'channel' => 'core',
-            'context' => ['exception' => new \SoapFault('foo', 'bar', 'hello', (object) ['bar' => (object) ['biz' => 'baz'], 'foo' => 'world'])],
-            'datetime' => new \DateTimeImmutable,
-            'extra' => [],
-            'message' => 'foobar',
-        ]);
+        $message = $formatter->format($this->getRecord(
+            Logger::CRITICAL,
+            'foobar',
+            channel: 'core',
+            context: ['exception' => new \SoapFault('foo', 'bar', 'hello', (object) ['bar' => (object) ['biz' => 'baz'], 'foo' => 'world'])],
+        ));
 
         $path = str_replace('\\/', '/', json_encode(__FILE__));
 
-        $this->assertEquals('['.date('Y-m-d').'] core.CRITICAL: foobar {"exception":"[object] (SoapFault(code: 0 faultcode: foo faultactor: hello detail: {\"bar\":{\"biz\":\"baz\"},\"foo\":\"world\"}): bar at '.substr($path, 1, -1).':'.(__LINE__ - 8).')"} []'."\n", $message);
+        $this->assertEquals('['.date('Y-m-d').'] core.CRITICAL: foobar {"exception":"[object] (SoapFault(code: 0 faultcode: foo faultactor: hello detail: {\"bar\":{\"biz\":\"baz\"},\"foo\":\"world\"}): bar at '.substr($path, 1, -1).':'.(__LINE__ - 5).')"} []'."\n", $message);
     }
 
     public function testBatchFormat()
     {
         $formatter = new LineFormatter(null, 'Y-m-d');
         $message = $formatter->formatBatch([
-            [
-                'level_name' => 'CRITICAL',
-                'channel' => 'test',
-                'message' => 'bar',
-                'context' => [],
-                'datetime' => new \DateTimeImmutable,
-                'extra' => [],
-            ],
-            [
-                'level_name' => 'WARNING',
-                'channel' => 'log',
-                'message' => 'foo',
-                'context' => [],
-                'datetime' => new \DateTimeImmutable,
-                'extra' => [],
-            ],
+            $this->getRecord(
+                Logger::CRITICAL,
+                'bar',
+                channel: 'test',
+            ),
+            $this->getRecord(
+                Logger::WARNING,
+                'foo',
+                channel: 'log',
+            ),
         ]);
         $this->assertEquals('['.date('Y-m-d').'] test.CRITICAL: bar [] []'."\n".'['.date('Y-m-d').'] log.WARNING: foo [] []'."\n", $message);
     }
@@ -234,13 +208,7 @@ class LineFormatterTest extends \PHPUnit\Framework\TestCase
     public function testFormatShouldStripInlineLineBreaks()
     {
         $formatter = new LineFormatter(null, 'Y-m-d');
-        $message = $formatter->format(
-            [
-                'message' => "foo\nbar",
-                'context' => [],
-                'extra' => [],
-            ]
-        );
+        $message = $formatter->format($this->getRecord(message: "foo\nbar"));
 
         $this->assertMatchesRegularExpression('/foo bar/', $message);
     }
@@ -248,13 +216,7 @@ class LineFormatterTest extends \PHPUnit\Framework\TestCase
     public function testFormatShouldNotStripInlineLineBreaksWhenFlagIsSet()
     {
         $formatter = new LineFormatter(null, 'Y-m-d', true);
-        $message = $formatter->format(
-            [
-                'message' => "foo\nbar",
-                'context' => [],
-                'extra' => [],
-            ]
-        );
+        $message = $formatter->format($this->getRecord(message: "foo\nbar"));
 
         $this->assertMatchesRegularExpression('/foo\nbar/', $message);
     }

+ 46 - 55
tests/Monolog/Formatter/LogstashFormatterTest.php

@@ -12,7 +12,7 @@
 namespace Monolog\Formatter;
 
 use Monolog\Logger;
-use PHPUnit\Framework\TestCase;
+use Monolog\Test\TestCase;
 
 class LogstashFormatterTest extends TestCase
 {
@@ -22,15 +22,12 @@ class LogstashFormatterTest extends TestCase
     public function testDefaultFormatterV1()
     {
         $formatter = new LogstashFormatter('test', 'hostname');
-        $record = [
-            'level' => Logger::ERROR,
-            'level_name' => 'ERROR',
-            'channel' => 'meh',
-            'context' => [],
-            'datetime' => new \DateTimeImmutable("@0"),
-            'extra' => [],
-            'message' => 'log',
-        ];
+        $record = $this->getRecord(
+            Logger::ERROR,
+            'log',
+            channel: 'meh',
+            datetime: new \DateTimeImmutable("@0"),
+        );
 
         $message = json_decode($formatter->format($record), true);
 
@@ -56,15 +53,14 @@ class LogstashFormatterTest extends TestCase
     public function testFormatWithFileAndLineV1()
     {
         $formatter = new LogstashFormatter('test');
-        $record = [
-            'level' => Logger::ERROR,
-            'level_name' => 'ERROR',
-            'channel' => 'meh',
-            'context' => ['from' => 'logger'],
-            'datetime' => new \DateTimeImmutable("@0"),
-            'extra' => ['file' => 'test', 'line' => 14],
-            'message' => 'log',
-        ];
+        $record = $this->getRecord(
+            Logger::ERROR,
+            'log',
+            channel: 'meh',
+            context: ['from' => 'logger'],
+            datetime: new \DateTimeImmutable("@0"),
+            extra: ['file' => 'test', 'line' => 14],
+        );
 
         $message = json_decode($formatter->format($record), true);
 
@@ -78,15 +74,14 @@ class LogstashFormatterTest extends TestCase
     public function testFormatWithContextV1()
     {
         $formatter = new LogstashFormatter('test');
-        $record = [
-            'level' => Logger::ERROR,
-            'level_name' => 'ERROR',
-            'channel' => 'meh',
-            'context' => ['from' => 'logger'],
-            'datetime' => new \DateTimeImmutable("@0"),
-            'extra' => ['key' => 'pair'],
-            'message' => 'log',
-        ];
+        $record = $this->getRecord(
+            Logger::ERROR,
+            'log',
+            channel: 'meh',
+            context: ['from' => 'logger'],
+            datetime: new \DateTimeImmutable("@0"),
+            extra: ['key' => 'pair'],
+        );
 
         $message = json_decode($formatter->format($record), true);
 
@@ -109,15 +104,14 @@ class LogstashFormatterTest extends TestCase
     public function testFormatWithExtraV1()
     {
         $formatter = new LogstashFormatter('test');
-        $record = [
-            'level' => Logger::ERROR,
-            'level_name' => 'ERROR',
-            'channel' => 'meh',
-            'context' => ['from' => 'logger'],
-            'datetime' => new \DateTimeImmutable("@0"),
-            'extra' => ['key' => 'pair'],
-            'message' => 'log',
-        ];
+        $record = $this->getRecord(
+            Logger::ERROR,
+            'log',
+            channel: 'meh',
+            context: ['from' => 'logger'],
+            datetime: new \DateTimeImmutable("@0"),
+            extra: ['key' => 'pair'],
+        );
 
         $message = json_decode($formatter->format($record), true);
 
@@ -137,15 +131,14 @@ class LogstashFormatterTest extends TestCase
     public function testFormatWithApplicationNameV1()
     {
         $formatter = new LogstashFormatter('app', 'test');
-        $record = [
-            'level' => Logger::ERROR,
-            'level_name' => 'ERROR',
-            'channel' => 'meh',
-            'context' => ['from' => 'logger'],
-            'datetime' => new \DateTimeImmutable("@0"),
-            'extra' => ['key' => 'pair'],
-            'message' => 'log',
-        ];
+        $record = $this->getRecord(
+            Logger::ERROR,
+            'log',
+            channel: 'meh',
+            context: ['from' => 'logger'],
+            datetime: new \DateTimeImmutable("@0"),
+            extra: ['key' => 'pair'],
+        );
 
         $message = json_decode($formatter->format($record), true);
 
@@ -156,17 +149,15 @@ class LogstashFormatterTest extends TestCase
     public function testFormatWithLatin9Data()
     {
         $formatter = new LogstashFormatter('test', 'hostname');
-        $record = [
-            'level' => Logger::ERROR,
-            'level_name' => 'ERROR',
-            'channel' => '¯\_(ツ)_/¯',
-            'context' => [],
-            'datetime' => new \DateTimeImmutable("@0"),
-            'extra' => [
+        $record = $this->getRecord(
+            Logger::ERROR,
+            'log',
+            channel: '¯\_(ツ)_/¯',
+            datetime: new \DateTimeImmutable("@0"),
+            extra: [
                 'user_agent' => "\xD6WN; FBCR/OrangeEspa\xF1a; Vers\xE3o/4.0; F\xE4rist",
             ],
-            'message' => 'log',
-        ];
+        );
 
         $message = json_decode($formatter->format($record), true);
 

+ 43 - 55
tests/Monolog/Formatter/MongoDBFormatterTest.php

@@ -15,11 +15,12 @@ use MongoDB\BSON\ObjectId;
 use MongoDB\BSON\Regex;
 use MongoDB\BSON\UTCDateTime;
 use Monolog\Logger;
+use Monolog\Test\TestCase;
 
 /**
  * @author Florian Plattner <me@florianplattner.de>
  */
-class MongoDBFormatterTest extends \PHPUnit\Framework\TestCase
+class MongoDBFormatterTest extends TestCase
 {
     public function setUp(): void
     {
@@ -59,15 +60,12 @@ class MongoDBFormatterTest extends \PHPUnit\Framework\TestCase
 
     public function testSimpleFormat()
     {
-        $record = [
-            'message' => 'some log message',
-            'context' => [],
-            'level' => Logger::WARNING,
-            'level_name' => Logger::getLevelName(Logger::WARNING),
-            'channel' => 'test',
-            'datetime' => new \DateTimeImmutable('2016-01-21T21:11:30.123456+00:00'),
-            'extra' => [],
-        ];
+        $record = $this->getRecord(
+            message: 'some log message',
+            level: Logger::WARNING,
+            channel: 'test',
+            datetime: new \DateTimeImmutable('2016-01-21T21:11:30.123456+00:00'),
+        );
 
         $formatter = new MongoDBFormatter();
         $formattedRecord = $formatter->format($record);
@@ -89,21 +87,19 @@ class MongoDBFormatterTest extends \PHPUnit\Framework\TestCase
         $someObject->foo = 'something';
         $someObject->bar = 'stuff';
 
-        $record = [
-            'message' => 'some log message',
-            'context' => [
+        $record = $this->getRecord(
+            message: 'some log message',
+            context: [
                 'stuff' => new \DateTimeImmutable('1969-01-21T21:11:30.213000+00:00'),
                 'some_object' => $someObject,
                 'context_string' => 'some string',
                 'context_int' => 123456,
                 'except' => new \Exception('exception message', 987),
             ],
-            'level' => Logger::WARNING,
-            'level_name' => Logger::getLevelName(Logger::WARNING),
-            'channel' => 'test',
-            'datetime' => new \DateTimeImmutable('2016-01-21T21:11:30.213000+00:00'),
-            'extra' => [],
-        ];
+            level: Logger::WARNING,
+            channel: 'test',
+            datetime: new \DateTimeImmutable('2016-01-21T21:11:30.213000+00:00'),
+        );
 
         $formatter = new MongoDBFormatter();
         $formattedRecord = $formatter->format($record);
@@ -133,9 +129,9 @@ class MongoDBFormatterTest extends \PHPUnit\Framework\TestCase
 
     public function testFormatDepthArray()
     {
-        $record = [
-            'message' => 'some log message',
-            'context' => [
+        $record = $this->getRecord(
+            message: 'some log message',
+            context: [
                 'nest2' => [
                     'property' => 'anything',
                     'nest3' => [
@@ -144,12 +140,10 @@ class MongoDBFormatterTest extends \PHPUnit\Framework\TestCase
                     ],
                 ],
             ],
-            'level' => Logger::WARNING,
-            'level_name' => Logger::getLevelName(Logger::WARNING),
-            'channel' => 'test',
-            'datetime' => new \DateTimeImmutable('2016-01-21T21:11:30.123456+00:00'),
-            'extra' => [],
-        ];
+            level: Logger::WARNING,
+            channel: 'test',
+            datetime: new \DateTimeImmutable('2016-01-21T21:11:30.123456+00:00'),
+        );
 
         $formatter = new MongoDBFormatter(2);
         $formattedResult = $formatter->format($record);
@@ -167,9 +161,9 @@ class MongoDBFormatterTest extends \PHPUnit\Framework\TestCase
 
     public function testFormatDepthArrayInfiniteNesting()
     {
-        $record = [
-            'message' => 'some log message',
-            'context' => [
+        $record = $this->getRecord(
+            message: 'some log message',
+            context: [
                 'nest2' => [
                     'property' => 'something',
                     'nest3' => [
@@ -180,12 +174,10 @@ class MongoDBFormatterTest extends \PHPUnit\Framework\TestCase
                     ],
                 ],
             ],
-            'level' => Logger::WARNING,
-            'level_name' => Logger::getLevelName(Logger::WARNING),
-            'channel' => 'test',
-            'datetime' => new \DateTimeImmutable('2016-01-21T21:11:30.123456+00:00'),
-            'extra' => [],
-        ];
+            level: Logger::WARNING,
+            channel: 'test',
+            datetime: new \DateTimeImmutable('2016-01-21T21:11:30.123456+00:00'),
+        );
 
         $formatter = new MongoDBFormatter(0);
         $formattedResult = $formatter->format($record);
@@ -214,17 +206,15 @@ class MongoDBFormatterTest extends \PHPUnit\Framework\TestCase
         $someObject->nest3->property = 'nothing';
         $someObject->nest3->nest4 = 'invisible';
 
-        $record = [
-            'message' => 'some log message',
-            'context' => [
+        $record = $this->getRecord(
+            message: 'some log message',
+            context: [
                 'nest2' => $someObject,
             ],
-            'level' => Logger::WARNING,
-            'level_name' => Logger::getLevelName(Logger::WARNING),
-            'channel' => 'test',
-            'datetime' => new \DateTimeImmutable('2016-01-21T21:11:30.123456+00:00'),
-            'extra' => [],
-        ];
+            level: Logger::WARNING,
+            channel: 'test',
+            datetime: new \DateTimeImmutable('2016-01-21T21:11:30.123456+00:00'),
+        );
 
         $formatter = new MongoDBFormatter(2, true);
         $formattedResult = $formatter->format($record);
@@ -243,17 +233,15 @@ class MongoDBFormatterTest extends \PHPUnit\Framework\TestCase
 
     public function testFormatDepthException()
     {
-        $record = [
-            'message' => 'some log message',
-            'context' => [
+        $record = $this->getRecord(
+            message: 'some log message',
+            context: [
                 'nest2' => new \Exception('exception message', 987),
             ],
-            'level' => Logger::WARNING,
-            'level_name' => Logger::getLevelName(Logger::WARNING),
-            'channel' => 'test',
-            'datetime' => new \DateTimeImmutable('2016-01-21T21:11:30.123456+00:00'),
-            'extra' => [],
-        ];
+            level: Logger::WARNING,
+            channel: 'test',
+            datetime: new \DateTimeImmutable('2016-01-21T21:11:30.123456+00:00'),
+        );
 
         $formatter = new MongoDBFormatter(2, false);
         $formattedRecord = $formatter->format($record);

+ 51 - 58
tests/Monolog/Formatter/NormalizerFormatterTest.php

@@ -11,7 +11,8 @@
 
 namespace Monolog\Formatter;
 
-use PHPUnit\Framework\TestCase;
+use Monolog\Test\TestCase;
+use Monolog\Logger;
 
 /**
  * @covers Monolog\Formatter\NormalizerFormatter
@@ -21,23 +22,23 @@ class NormalizerFormatterTest extends TestCase
     public function testFormat()
     {
         $formatter = new NormalizerFormatter('Y-m-d');
-        $formatted = $formatter->format([
-            'level_name' => 'ERROR',
-            'channel' => 'meh',
-            'message' => 'foo',
-            'datetime' => new \DateTimeImmutable,
-            'extra' => ['foo' => new TestFooNorm, 'bar' => new TestBarNorm, 'baz' => [], 'res' => fopen('php://memory', 'rb')],
-            'context' => [
+        $formatted = $formatter->format($this->getRecord(
+            Logger::ERROR,
+            'foo',
+            channel: 'meh',
+            extra: ['foo' => new TestFooNorm, 'bar' => new TestBarNorm, 'baz' => [], 'res' => fopen('php://memory', 'rb')],
+            context: [
                 'foo' => 'bar',
                 'baz' => 'qux',
                 'inf' => INF,
                 '-inf' => -INF,
                 'nan' => acos(4),
             ],
-        ]);
+        ));
 
         $this->assertEquals([
             'level_name' => 'ERROR',
+            'level' => Logger::ERROR,
             'channel' => 'meh',
             'message' => 'foo',
             'datetime' => date('Y-m-d'),
@@ -62,7 +63,7 @@ class NormalizerFormatterTest extends TestCase
         $formatter = new NormalizerFormatter('Y-m-d');
         $e = new \LogicException('bar');
         $e2 = new \RuntimeException('foo', 0, $e);
-        $formatted = $formatter->format([
+        $formatted = $formatter->normalizeValue([
             'exception' => $e2,
         ]);
 
@@ -88,7 +89,7 @@ class NormalizerFormatterTest extends TestCase
 
         $formatter = new NormalizerFormatter('Y-m-d');
         $e = new \SoapFault('foo', 'bar', 'hello', 'world');
-        $formatted = $formatter->format([
+        $formatted = $formatter->normalizeValue([
             'exception' => $e,
         ]);
 
@@ -108,7 +109,7 @@ class NormalizerFormatterTest extends TestCase
 
         $formatter = new NormalizerFormatter('Y-m-d');
         $e = new \SoapFault('foo', 'bar', 'hello', (object) ['bar' => (object) ['biz' => 'baz'], 'foo' => 'world']);
-        $formatted = $formatter->format([
+        $formatted = $formatter->normalizeValue([
             'exception' => $e,
         ]);
 
@@ -132,35 +133,22 @@ class NormalizerFormatterTest extends TestCase
         $formatter = new NormalizerFormatter('Y-m-d');
         $this->expectException('RuntimeException');
         $this->expectExceptionMessage('Could not convert to string');
-        $formatter->format([
+        $formatter->format($this->getRecord(context: [
             'myObject' => new TestToStringError(),
-        ]);
+        ]));
     }
 
     public function testBatchFormat()
     {
         $formatter = new NormalizerFormatter('Y-m-d');
         $formatted = $formatter->formatBatch([
-            [
-                'level_name' => 'CRITICAL',
-                'channel' => 'test',
-                'message' => 'bar',
-                'context' => [],
-                'datetime' => new \DateTimeImmutable,
-                'extra' => [],
-            ],
-            [
-                'level_name' => 'WARNING',
-                'channel' => 'log',
-                'message' => 'foo',
-                'context' => [],
-                'datetime' => new \DateTimeImmutable,
-                'extra' => [],
-            ],
+            $this->getRecord(Logger::CRITICAL, 'bar', channel: 'test'),
+            $this->getRecord(Logger::WARNING, 'foo', channel: 'log'),
         ]);
         $this->assertEquals([
             [
                 'level_name' => 'CRITICAL',
+                'level' => Logger::CRITICAL,
                 'channel' => 'test',
                 'message' => 'bar',
                 'context' => [],
@@ -169,6 +157,7 @@ class NormalizerFormatterTest extends TestCase
             ],
             [
                 'level_name' => 'WARNING',
+                'level' => Logger::WARNING,
                 'channel' => 'log',
                 'message' => 'foo',
                 'context' => [],
@@ -217,7 +206,7 @@ class NormalizerFormatterTest extends TestCase
         $x = ['foo' => 'bar'];
         $y = ['x' => &$x];
         $x['y'] = &$y;
-        $formatter->format($y);
+        $formatter->normalizeValue($y);
     }
 
     public function testToJsonIgnoresInvalidTypes()
@@ -251,13 +240,11 @@ class NormalizerFormatterTest extends TestCase
         $formatter = new NormalizerFormatter();
         $largeArray = range(1, 1000);
 
-        $res = $formatter->format(array(
-            'level_name' => 'CRITICAL',
-            'channel' => 'test',
-            'message' => 'bar',
-            'context' => array($largeArray),
-            'datetime' => new \DateTime,
-            'extra' => array(),
+        $res = $formatter->format($this->getRecord(
+            Logger::CRITICAL,
+            'bar',
+            channel: 'test',
+            context: [$largeArray],
         ));
 
         $this->assertCount(1000, $res['context'][0]);
@@ -269,13 +256,11 @@ class NormalizerFormatterTest extends TestCase
         $formatter = new NormalizerFormatter();
         $largeArray = range(1, 2000);
 
-        $res = $formatter->format(array(
-            'level_name' => 'CRITICAL',
-            'channel' => 'test',
-            'message' => 'bar',
-            'context' => array($largeArray),
-            'datetime' => new \DateTime,
-            'extra' => array(),
+        $res = $formatter->format($this->getRecord(
+            Logger::CRITICAL,
+            'bar',
+            channel: 'test',
+            context: [$largeArray],
         ));
 
         $this->assertCount(1001, $res['context'][0]);
@@ -328,12 +313,12 @@ class NormalizerFormatterTest extends TestCase
 
         $message = $this->formatRecordWithExceptionInContext($formatter, $throwable);
         $this->assertEquals(
-            ["..." => "Over 0 items (6 total), aborting normalization"],
+            ["..." => "Over 0 items (7 total), aborting normalization"],
             $message
         );
     }
 
-    public function testMaxNormalizeItemCountWith3ItemsMax()
+    public function testMaxNormalizeItemCountWith2ItemsMax()
     {
         $formatter = new NormalizerFormatter();
         $formatter->setMaxNormalizeDepth(9);
@@ -342,8 +327,18 @@ class NormalizerFormatterTest extends TestCase
 
         $message = $this->formatRecordWithExceptionInContext($formatter, $throwable);
 
+        unset($message['context']['exception']['trace']);
+        unset($message['context']['exception']['file']);
         $this->assertEquals(
-            ["level_name" => "CRITICAL", "channel" => "core", "..." => "Over 2 items (6 total), aborting normalization"],
+            [
+                "message" => "foobar",
+                "context" => ['exception' => [
+                    'class' => 'Error',
+                    'message' => 'Foo',
+                    'code' => 0,
+               ]],
+                "..." => "Over 2 items (7 total), aborting normalization"
+            ],
             $message
         );
     }
@@ -366,7 +361,7 @@ class NormalizerFormatterTest extends TestCase
         }
 
         $formatter = new NormalizerFormatter();
-        $record = ['context' => ['exception' => $e]];
+        $record = $this->getRecord(context: ['exception' => $e]);
         $result = $formatter->format($record);
 
         $this->assertSame(
@@ -383,14 +378,12 @@ class NormalizerFormatterTest extends TestCase
      */
     private function formatRecordWithExceptionInContext(NormalizerFormatter $formatter, \Throwable $exception)
     {
-        $message = $formatter->format([
-            'level_name' => 'CRITICAL',
-            'channel' => 'core',
-            'context' => ['exception' => $exception],
-            'datetime' => null,
-            'extra' => [],
-            'message' => 'foobar',
-        ]);
+        $message = $formatter->format($this->getRecord(
+            Logger::CRITICAL,
+            'foobar',
+            channel: 'core',
+            context: ['exception' => $exception],
+        ));
 
         return $message;
     }
@@ -404,7 +397,7 @@ class NormalizerFormatterTest extends TestCase
         }
 
         $formatter = new NormalizerFormatter();
-        $record = array('context' => array('exception' => $e));
+        $record = $this->getRecord(context: ['exception' => $e]);
         $result = $formatter->format($record);
 
         $this->assertSame(

+ 26 - 31
tests/Monolog/Formatter/ScalarFormatterTest.php

@@ -12,8 +12,9 @@
 namespace Monolog\Formatter;
 
 use Monolog\DateTimeImmutable;
+use Monolog\Test\TestCase;
 
-class ScalarFormatterTest extends \PHPUnit\Framework\TestCase
+class ScalarFormatterTest extends TestCase
 {
     private $formatter;
 
@@ -43,7 +44,7 @@ class ScalarFormatterTest extends \PHPUnit\Framework\TestCase
     public function testFormat()
     {
         $exception = new \Exception('foo');
-        $formatted = $this->formatter->format([
+        $formatted = $this->formatter->format($this->getRecord(context: [
             'foo' => 'string',
             'bar' => 1,
             'baz' => false,
@@ -51,56 +52,50 @@ class ScalarFormatterTest extends \PHPUnit\Framework\TestCase
             'bat' => ['foo' => 'bar'],
             'bap' => $dt = new DateTimeImmutable(true),
             'ban' => $exception,
-        ]);
+        ]));
 
-        $this->assertSame([
+        $this->assertSame($this->encodeJson([
             'foo' => 'string',
             'bar' => 1,
             'baz' => false,
-            'bam' => $this->encodeJson([1, 2, 3]),
-            'bat' => $this->encodeJson(['foo' => 'bar']),
+            'bam' => [1, 2, 3],
+            'bat' => ['foo' => 'bar'],
             'bap' => (string) $dt,
-            'ban' => $this->encodeJson([
+            'ban' => [
                 'class'   => get_class($exception),
                 'message' => $exception->getMessage(),
                 'code'    => $exception->getCode(),
                 'file'    => $exception->getFile() . ':' . $exception->getLine(),
                 'trace'   => $this->buildTrace($exception),
-            ]),
-        ], $formatted);
+            ],
+        ]), $formatted['context']);
     }
 
     public function testFormatWithErrorContext()
     {
         $context = ['file' => 'foo', 'line' => 1];
-        $formatted = $this->formatter->format([
-            'context' => $context,
-        ]);
+        $formatted = $this->formatter->format($this->getRecord(
+            context: $context,
+        ));
 
-        $this->assertSame([
-            'context' => $this->encodeJson($context),
-        ], $formatted);
+        $this->assertSame($this->encodeJson($context), $formatted['context']);
     }
 
     public function testFormatWithExceptionContext()
     {
         $exception = new \Exception('foo');
-        $formatted = $this->formatter->format([
-            'context' => [
-                'exception' => $exception,
-            ],
-        ]);
+        $formatted = $this->formatter->format($this->getRecord(context: [
+            'exception' => $exception,
+        ]));
 
-        $this->assertSame([
-            'context' => $this->encodeJson([
-                'exception' => [
-                    'class'   => get_class($exception),
-                    'message' => $exception->getMessage(),
-                    'code'    => $exception->getCode(),
-                    'file'    => $exception->getFile() . ':' . $exception->getLine(),
-                    'trace'   => $this->buildTrace($exception),
-                ],
-            ]),
-        ], $formatted);
+        $this->assertSame($this->encodeJson([
+            'exception' => [
+                'class'   => get_class($exception),
+                'message' => $exception->getMessage(),
+                'code'    => $exception->getCode(),
+                'file'    => $exception->getFile() . ':' . $exception->getLine(),
+                'trace'   => $this->buildTrace($exception),
+            ]
+        ]), $formatted['context']);
     }
 }

+ 32 - 46
tests/Monolog/Formatter/WildfireFormatterTest.php

@@ -12,8 +12,9 @@
 namespace Monolog\Formatter;
 
 use Monolog\Logger;
+use Monolog\Test\TestCase;
 
-class WildfireFormatterTest extends \PHPUnit\Framework\TestCase
+class WildfireFormatterTest extends TestCase
 {
     /**
      * @covers Monolog\Formatter\WildfireFormatter::format
@@ -21,15 +22,13 @@ class WildfireFormatterTest extends \PHPUnit\Framework\TestCase
     public function testDefaultFormat()
     {
         $wildfire = new WildfireFormatter();
-        $record = [
-            'level' => Logger::ERROR,
-            'level_name' => 'ERROR',
-            'channel' => 'meh',
-            'context' => ['from' => 'logger'],
-            'datetime' => new \DateTimeImmutable("@0"),
-            'extra' => ['ip' => '127.0.0.1'],
-            'message' => 'log',
-        ];
+        $record = $this->getRecord(
+            Logger::ERROR,
+            'log',
+            channel: 'meh',
+            context: ['from' => 'logger'],
+            extra: ['ip' => '127.0.0.1'],
+        );
 
         $message = $wildfire->format($record);
 
@@ -46,15 +45,13 @@ class WildfireFormatterTest extends \PHPUnit\Framework\TestCase
     public function testFormatWithFileAndLine()
     {
         $wildfire = new WildfireFormatter();
-        $record = [
-            'level' => Logger::ERROR,
-            'level_name' => 'ERROR',
-            'channel' => 'meh',
-            'context' => ['from' => 'logger'],
-            'datetime' => new \DateTimeImmutable("@0"),
-            'extra' => ['ip' => '127.0.0.1', 'file' => 'test', 'line' => 14],
-            'message' => 'log',
-        ];
+        $record = $this->getRecord(
+            Logger::ERROR,
+            'log',
+            channel: 'meh',
+            context: ['from' => 'logger'],
+            extra: ['ip' => '127.0.0.1', 'file' => 'test', 'line' => 14],
+        );
 
         $message = $wildfire->format($record);
 
@@ -71,15 +68,11 @@ class WildfireFormatterTest extends \PHPUnit\Framework\TestCase
     public function testFormatWithoutContext()
     {
         $wildfire = new WildfireFormatter();
-        $record = [
-            'level' => Logger::ERROR,
-            'level_name' => 'ERROR',
-            'channel' => 'meh',
-            'context' => [],
-            'datetime' => new \DateTimeImmutable("@0"),
-            'extra' => [],
-            'message' => 'log',
-        ];
+        $record = $this->getRecord(
+            Logger::ERROR,
+            'log',
+            channel: 'meh',
+        );
 
         $message = $wildfire->format($record);
 
@@ -97,15 +90,11 @@ class WildfireFormatterTest extends \PHPUnit\Framework\TestCase
         $this->expectException(\BadMethodCallException::class);
 
         $wildfire = new WildfireFormatter();
-        $record = [
-            'level' => Logger::ERROR,
-            'level_name' => 'ERROR',
-            'channel' => 'meh',
-            'context' => [],
-            'datetime' => new \DateTimeImmutable("@0"),
-            'extra' => [],
-            'message' => 'log',
-        ];
+        $record = $this->getRecord(
+            Logger::ERROR,
+            'log',
+            channel: 'meh',
+        );
 
         $wildfire->formatBatch([$record]);
     }
@@ -116,11 +105,11 @@ class WildfireFormatterTest extends \PHPUnit\Framework\TestCase
     public function testTableFormat()
     {
         $wildfire = new WildfireFormatter();
-        $record = [
-            'level' => Logger::ERROR,
-            'level_name' => 'ERROR',
-            'channel' => 'table-channel',
-            'context' => [
+        $record = $this->getRecord(
+            Logger::ERROR,
+            'table-message',
+            channel: 'table-channel',
+            context: [
                 'table' => [
                     ['col1', 'col2', 'col3'],
                     ['val1', 'val2', 'val3'],
@@ -128,10 +117,7 @@ class WildfireFormatterTest extends \PHPUnit\Framework\TestCase
                     ['bar1', 'bar2', 'bar3'],
                 ],
             ],
-            'datetime' => new \DateTimeImmutable("@0"),
-            'extra' => [],
-            'message' => 'table-message',
-        ];
+        );
 
         $message = $wildfire->format($record);
 

+ 5 - 10
tests/Monolog/Handler/DeduplicationHandlerTest.php

@@ -87,11 +87,9 @@ class DeduplicationHandlerTest extends TestCase
         $test = new TestHandler();
         $handler = new DeduplicationHandler($test, sys_get_temp_dir().'/monolog_dedup.log', 0);
 
-        $record = $this->getRecord(Logger::ERROR);
-        $record['datetime'] = $record['datetime']->modify('+62seconds');
+        $record = $this->getRecord(Logger::ERROR, datetime: new \DateTimeImmutable('+62seconds'));
         $handler->handle($record);
-        $record = $this->getRecord(Logger::CRITICAL);
-        $record['datetime'] = $record['datetime']->modify('+62seconds');
+        $record = $this->getRecord(Logger::CRITICAL, datetime: new \DateTimeImmutable('+62seconds'));
         $handler->handle($record);
 
         $handler->flush();
@@ -114,14 +112,11 @@ class DeduplicationHandlerTest extends TestCase
         $handler = new DeduplicationHandler($test, sys_get_temp_dir().'/monolog_dedup.log', 0);
 
         // handle two records from yesterday, and one recent
-        $record = $this->getRecord(Logger::ERROR);
-        $record['datetime'] = $record['datetime']->modify('-1day -10seconds');
+        $record = $this->getRecord(Logger::ERROR, datetime: new \DateTimeImmutable('-1day -10seconds'));
         $handler->handle($record);
-        $record2 = $this->getRecord(Logger::CRITICAL);
-        $record2['datetime'] = $record2['datetime']->modify('-1day -10seconds');
+        $record2 = $this->getRecord(Logger::CRITICAL, datetime: new \DateTimeImmutable('-1day -10seconds'));
         $handler->handle($record2);
-        $record3 = $this->getRecord(Logger::CRITICAL);
-        $record3['datetime'] = $record3['datetime']->modify('-30seconds');
+        $record3 = $this->getRecord(Logger::CRITICAL, datetime: new \DateTimeImmutable('-30seconds'));
         $handler->handle($record3);
 
         // log is written as none of them are duplicate

+ 4 - 28
tests/Monolog/Handler/ElasticaHandlerTest.php

@@ -58,15 +58,7 @@ class ElasticaHandlerTest extends TestCase
     public function testHandle()
     {
         // log message
-        $msg = new LogRecord(
-            level: Logger::ERROR,
-            levelName: 'ERROR',
-            channel: 'meh',
-            context: ['foo' => 7, 'bar', 'class' => new \stdClass],
-            datetime: new \DateTimeImmutable("@0"),
-            extra: [],
-            message: 'log',
-        );
+        $msg = $this->getRecord(Logger::ERROR, 'log', context: ['foo' => 7, 'bar', 'class' => new \stdClass], datetime: new \DateTimeImmutable("@0"));
 
         // format expected result
         $formatter = new ElasticaFormatter($this->options['index'], $this->options['type']);
@@ -166,17 +158,9 @@ class ElasticaHandlerTest extends TestCase
      */
     public function testHandleIntegration()
     {
-        $msg = new LogRecord(
-            level: Logger::ERROR,
-            levelName: 'ERROR',
-            channel: 'meh',
-            context: ['foo' => 7, 'bar', 'class' => new \stdClass],
-            datetime: new \DateTimeImmutable("@0"),
-            extra: [],
-            message: 'log',
-        );
+        $msg = $this->getRecord(Logger::ERROR, 'log', context: ['foo' => 7, 'bar', 'class' => new \stdClass], datetime: new \DateTimeImmutable("@0"));
 
-        $expected = (array) $msg;
+        $expected = $msg->toArray();
         $expected['datetime'] = $msg['datetime']->format(\DateTime::ISO8601);
         $expected['context'] = [
             'class' => '[object] (stdClass: {})',
@@ -220,15 +204,7 @@ class ElasticaHandlerTest extends TestCase
      */
     public function testHandleIntegrationNewESVersion()
     {
-        $msg = new LogRecord(
-            level: Logger::ERROR,
-            levelName: 'ERROR',
-            channel: 'meh',
-            context: ['foo' => 7, 'bar', 'class' => new \stdClass],
-            datetime: new \DateTimeImmutable("@0"),
-            extra: [],
-            message: 'log',
-        );
+        $msg = $this->getRecord(Logger::ERROR, 'log', context: ['foo' => 7, 'bar', 'class' => new \stdClass], datetime: new \DateTimeImmutable("@0"));
 
         $expected = (array) $msg;
         $expected['datetime'] = $msg['datetime']->format(\DateTime::ISO8601);

+ 3 - 19
tests/Monolog/Handler/ElasticsearchHandlerTest.php

@@ -56,15 +56,7 @@ class ElasticsearchHandlerTest extends TestCase
     public function testHandle()
     {
         // log message
-        $msg = [
-            'level' => Logger::ERROR,
-            'level_name' => 'ERROR',
-            'channel' => 'meh',
-            'context' => ['foo' => 7, 'bar', 'class' => new \stdClass],
-            'datetime' => new \DateTimeImmutable("@0"),
-            'extra' => [],
-            'message' => 'log',
-        ];
+        $msg = $this->getRecord(Logger::ERROR, 'log', context: ['foo' => 7, 'bar', 'class' => new \stdClass], datetime: new \DateTimeImmutable("@0"));
 
         // format expected result
         $formatter = new ElasticsearchFormatter($this->options['index'], $this->options['type']);
@@ -180,17 +172,9 @@ class ElasticsearchHandlerTest extends TestCase
      */
     public function testHandleIntegration()
     {
-        $msg = [
-            'level' => Logger::ERROR,
-            'level_name' => 'ERROR',
-            'channel' => 'meh',
-            'context' => ['foo' => 7, 'bar', 'class' => new \stdClass],
-            'datetime' => new \DateTimeImmutable("@0"),
-            'extra' => [],
-            'message' => 'log',
-        ];
+        $msg = $this->getRecord(Logger::ERROR, 'log', context: ['foo' => 7, 'bar', 'class' => new \stdClass], datetime: new \DateTimeImmutable("@0"));
 
-        $expected = $msg;
+        $expected = $msg->toArray();
         $expected['datetime'] = $msg['datetime']->format(\DateTime::ISO8601);
         $expected['context'] = [
             'class' => ["stdClass" => []],

+ 3 - 5
tests/Monolog/Handler/FingersCrossedHandlerTest.php

@@ -209,8 +209,7 @@ class FingersCrossedHandlerTest extends TestCase
         $handler = new FingersCrossedHandler($test, new ChannelLevelActivationStrategy(Logger::ERROR, ['othertest' => Logger::DEBUG]));
         $handler->handle($this->getRecord(Logger::WARNING));
         $this->assertFalse($test->hasWarningRecords());
-        $record = $this->getRecord(Logger::DEBUG);
-        $record['channel'] = 'othertest';
+        $record = $this->getRecord(Logger::DEBUG, channel: 'othertest');
         $handler->handle($record);
         $this->assertTrue($test->hasDebugRecords());
         $this->assertTrue($test->hasWarningRecords());
@@ -226,8 +225,7 @@ class FingersCrossedHandlerTest extends TestCase
         $handler = new FingersCrossedHandler($test, new ChannelLevelActivationStrategy('error', ['othertest' => 'debug']));
         $handler->handle($this->getRecord(Logger::WARNING));
         $this->assertFalse($test->hasWarningRecords());
-        $record = $this->getRecord(Logger::DEBUG);
-        $record['channel'] = 'othertest';
+        $record = $this->getRecord(Logger::DEBUG, channel: 'othertest');
         $handler->handle($record);
         $this->assertTrue($test->hasDebugRecords());
         $this->assertTrue($test->hasWarningRecords());
@@ -242,7 +240,7 @@ class FingersCrossedHandlerTest extends TestCase
         $test = new TestHandler();
         $handler = new FingersCrossedHandler($test, Logger::INFO);
         $handler->pushProcessor(function ($record) {
-            $record['extra']['foo'] = true;
+            $record->extra['foo'] = true;
 
             return $record;
         });

+ 1 - 9
tests/Monolog/Handler/FleepHookHandlerTest.php

@@ -56,15 +56,7 @@ class FleepHookHandlerTest extends TestCase
      */
     public function testHandlerUsesLineFormatterWhichIgnoresEmptyArrays()
     {
-        $record = [
-            'message' => 'msg',
-            'context' => [],
-            'level' => Logger::DEBUG,
-            'level_name' => Logger::getLevelName(Logger::DEBUG),
-            'channel' => 'channel',
-            'datetime' => new \DateTimeImmutable(),
-            'extra' => [],
-        ];
+        $record = $this->getRecord(Logger::DEBUG, 'msg');
 
         $expectedFormatter = new LineFormatter(null, null, true, true);
         $expected = $expectedFormatter->format($record);

+ 6 - 3
tests/Monolog/Handler/GelfHandlerTest.php

@@ -93,9 +93,12 @@ class GelfHandlerTest extends TestCase
 
     public function testInjectedGelfMessageFormatter()
     {
-        $record = $this->getRecord(Logger::WARNING, "A test warning message");
-        $record['extra']['blarg'] = 'yep';
-        $record['context']['from'] = 'logger';
+        $record = $this->getRecord(
+            Logger::WARNING,
+            "A test warning message",
+            extra: ['blarg' => 'yep'],
+            context: ['from' => 'logger'],
+        );
 
         $expectedMessage = new Message();
         $expectedMessage

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

@@ -43,7 +43,7 @@ class MongoDBHandlerTest extends TestCase
             ->will($this->returnValue($collection));
 
         $record = $this->getRecord();
-        $expected = $record;
+        $expected = $record->toArray();
         $expected['datetime'] = new \MongoDB\BSON\UTCDateTime((int) floor(((float) $record['datetime']->format('U.u')) * 1000));
 
         $collection->expects($this->once())

+ 2 - 2
tests/Monolog/Handler/PsrHandlerTest.php

@@ -46,7 +46,7 @@ class PsrHandlerTest extends TestCase
             ->with(strtolower($levelName), $message, $context);
 
         $handler = new PsrHandler($psrLogger);
-        $handler->handle(['level' => $level, 'level_name' => $levelName, 'message' => $message, 'context' => $context]);
+        $handler->handle($this->getRecord($level, $message, context: $context));
     }
 
     public function testFormatter()
@@ -63,6 +63,6 @@ class PsrHandlerTest extends TestCase
 
         $handler = new PsrHandler($psrLogger);
         $handler->setFormatter(new LineFormatter('dummy'));
-        $handler->handle(['level' => $level, 'level_name' => $levelName, 'message' => $message, 'context' => $context, 'extra' => [], 'date' => new \DateTimeImmutable()]);
+        $handler->handle($this->getRecord($level, $message, context: $context, datetime: new \DateTimeImmutable()));
     }
 }

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

@@ -38,12 +38,12 @@ class SyslogUdpHandlerTest extends TestCase
             ->onlyMethods(['write'])
             ->setConstructorArgs(['lol'])
             ->getMock();
-        $socket->expects($this->at(0))
+        $socket->expects($this->atLeast(2))
             ->method('write')
-            ->with("lol", "<".(LOG_AUTHPRIV + LOG_WARNING).">1 $time $host php $pid - - ");
-        $socket->expects($this->at(1))
-            ->method('write')
-            ->with("hej", "<".(LOG_AUTHPRIV + LOG_WARNING).">1 $time $host php $pid - - ");
+            ->withConsecutive(
+                [$this->equalTo("lol"), $this->equalTo("<".(LOG_AUTHPRIV + LOG_WARNING).">1 $time $host php $pid - - ")],
+                [$this->equalTo("hej"), $this->equalTo("<".(LOG_AUTHPRIV + LOG_WARNING).">1 $time $host php $pid - - ")],
+            );
 
         $handler->setSocket($socket);
 
@@ -64,7 +64,7 @@ class SyslogUdpHandlerTest extends TestCase
 
         $handler->setSocket($socket);
 
-        $handler->handle($this->getRecordWithMessage(null));
+        $handler->handle($this->getRecordWithMessage(''));
     }
 
     public function testRfc()
@@ -84,12 +84,12 @@ class SyslogUdpHandlerTest extends TestCase
             ->setConstructorArgs(array('lol', 999))
             ->onlyMethods(array('write'))
             ->getMock();
-        $socket->expects($this->at(0))
-            ->method('write')
-            ->with("lol", "<".(LOG_AUTHPRIV + LOG_WARNING).">$time $host php[$pid]: ");
-        $socket->expects($this->at(1))
+        $socket->expects($this->atLeast(2))
             ->method('write')
-            ->with("hej", "<".(LOG_AUTHPRIV + LOG_WARNING).">$time $host php[$pid]: ");
+            ->withConsecutive(
+                [$this->equalTo("lol"), $this->equalTo("<".(LOG_AUTHPRIV + LOG_WARNING).">$time $host php[$pid]: ")],
+                [$this->equalTo("hej"), $this->equalTo("<".(LOG_AUTHPRIV + LOG_WARNING).">$time $host php[$pid]: ")],
+            );
 
         $handler->setSocket($socket);
 
@@ -98,6 +98,6 @@ class SyslogUdpHandlerTest extends TestCase
 
     protected function getRecordWithMessage($msg)
     {
-        return ['message' => $msg, 'level' => \Monolog\Logger::WARNING, 'context' => null, 'extra' => [], 'channel' => 'lol', 'datetime' => new \DateTimeImmutable('2014-01-07 12:34:56')];
+        return $this->getRecord(message: $msg, level: \Monolog\Logger::WARNING, channel: 'lol', datetime: new \DateTimeImmutable('2014-01-07 12:34:56'));
     }
 }

+ 5 - 5
tests/Monolog/Handler/TestHandlerTest.php

@@ -27,8 +27,8 @@ class TestHandlerTest extends TestCase
         $handler = new TestHandler;
         $record = $this->getRecord($level, 'test'.$method);
         $this->assertFalse($handler->hasRecords($level));
-        $this->assertFalse($handler->hasRecord($record, $level));
-        $this->assertFalse($handler->{'has'.$method}($record), 'has'.$method);
+        $this->assertFalse($handler->hasRecord($record->message, $level));
+        $this->assertFalse($handler->{'has'.$method}($record->message), 'has'.$method);
         $this->assertFalse($handler->{'has'.$method.'ThatContains'}('test'), 'has'.$method.'ThatContains');
         $this->assertFalse($handler->{'has'.$method.'ThatPasses'}(function ($rec) {
             return true;
@@ -39,8 +39,8 @@ class TestHandlerTest extends TestCase
 
         $this->assertFalse($handler->{'has'.$method}('bar'), 'has'.$method);
         $this->assertTrue($handler->hasRecords($level));
-        $this->assertTrue($handler->hasRecord($record, $level));
-        $this->assertTrue($handler->{'has'.$method}($record), 'has'.$method);
+        $this->assertTrue($handler->hasRecord($record->message, $level));
+        $this->assertTrue($handler->{'has'.$method}($record->message), 'has'.$method);
         $this->assertTrue($handler->{'has'.$method}('test'.$method), 'has'.$method);
         $this->assertTrue($handler->{'has'.$method.'ThatContains'}('test'), 'has'.$method.'ThatContains');
         $this->assertTrue($handler->{'has'.$method.'ThatPasses'}(function ($rec) {
@@ -50,7 +50,7 @@ class TestHandlerTest extends TestCase
         $this->assertTrue($handler->{'has'.$method.'Records'}(), 'has'.$method.'Records');
 
         $records = $handler->getRecords();
-        unset($records[0]['formatted']);
+        $records[0]->formatted = null;
         $this->assertEquals([$record], $records);
     }
 

+ 33 - 13
tests/Monolog/LoggerTest.php

@@ -13,8 +13,9 @@ namespace Monolog;
 
 use Monolog\Processor\WebProcessor;
 use Monolog\Handler\TestHandler;
+use Monolog\Test\TestCase;
 
-class LoggerTest extends \PHPUnit\Framework\TestCase
+class LoggerTest extends TestCase
 {
     /**
      * @covers Monolog\Logger::getName
@@ -91,11 +92,11 @@ class LoggerTest extends \PHPUnit\Framework\TestCase
     {
         $logger = new Logger(__METHOD__);
 
-        $handler = $this->prophesize('Monolog\Handler\NullHandler');
-        $handler->handle(\Prophecy\Argument::any())->shouldBeCalled();
-        $handler->isHandling(['level' => 300])->willReturn(true);
+        $handler = $this->getMockBuilder('Monolog\Handler\HandlerInterface')->getMock();
+        $handler->expects($this->never())->method('isHandling');
+        $handler->expects($this->once())->method('handle');
 
-        $logger->pushHandler($handler->reveal());
+        $logger->pushHandler($handler);
 
         $this->assertTrue($logger->addRecord(Logger::WARNING, 'test'));
     }
@@ -103,15 +104,32 @@ class LoggerTest extends \PHPUnit\Framework\TestCase
     /**
      * @covers Monolog\Logger::addRecord
      */
-    public function testLogNotHandled()
+    public function testLogAlwaysHandledIfNoProcessorsArePresent()
     {
         $logger = new Logger(__METHOD__);
 
-        $handler = $this->prophesize('Monolog\Handler\NullHandler');
-        $handler->handle()->shouldNotBeCalled();
-        $handler->isHandling(['level' => 300])->willReturn(false);
+        $handler = $this->getMockBuilder('Monolog\Handler\HandlerInterface')->getMock();
+        $handler->expects($this->never())->method('isHandling');
+        $handler->expects($this->once())->method('handle');
+
+        $logger->pushHandler($handler);
 
-        $logger->pushHandler($handler->reveal());
+        $this->assertTrue($logger->addRecord(Logger::WARNING, 'test'));
+    }
+
+    /**
+     * @covers Monolog\Logger::addRecord
+     */
+    public function testLogNotHandledIfProcessorsArePresent()
+    {
+        $logger = new Logger(__METHOD__);
+
+        $handler = $this->getMockBuilder('Monolog\Handler\HandlerInterface')->getMock();
+        $handler->expects($this->once())->method('isHandling')->will($this->returnValue(false));
+        $handler->expects($this->never())->method('handle');
+
+        $logger->pushProcessor(fn (LogRecord $record) => $record);
+        $logger->pushHandler($handler);
 
         $this->assertFalse($logger->addRecord(Logger::WARNING, 'test'));
     }
@@ -273,9 +291,10 @@ class LoggerTest extends \PHPUnit\Framework\TestCase
     /**
      * @covers Monolog\Logger::addRecord
      */
-    public function testHandlersNotCalledBeforeFirstHandling()
+    public function testHandlersNotCalledBeforeFirstHandlingWhenProcessorsPresent()
     {
         $logger = new Logger(__METHOD__);
+        $logger->pushProcessor(fn($record) => $record);
 
         $handler1 = $this->createMock('Monolog\Handler\HandlerInterface');
         $handler1->expects($this->never())
@@ -315,7 +334,7 @@ class LoggerTest extends \PHPUnit\Framework\TestCase
     /**
      * @covers Monolog\Logger::addRecord
      */
-    public function testHandlersNotCalledBeforeFirstHandlingWithAssocArray()
+    public function testHandlersNotCalledBeforeFirstHandlingWhenProcessorsPresentWithAssocArray()
     {
         $handler1 = $this->createMock('Monolog\Handler\HandlerInterface');
         $handler1->expects($this->never())
@@ -347,6 +366,7 @@ class LoggerTest extends \PHPUnit\Framework\TestCase
         ;
 
         $logger = new Logger(__METHOD__, ['last' => $handler3, 'second' => $handler2, 'first' => $handler1]);
+        $logger->pushProcessor(fn($record) => $record);
 
         $logger->debug('test');
     }
@@ -627,7 +647,7 @@ class LoggerTest extends \PHPUnit\Framework\TestCase
         $that = $this;
         $logger->setExceptionHandler(function ($e, $record) use ($that) {
             $that->assertEquals($e->getMessage(), 'Some handler exception');
-            $that->assertTrue(is_array($record));
+            $that->assertInstanceOf(LogRecord::class, $record);
             $that->assertEquals($record['message'], 'test');
         });
         $handler = $this->getMockBuilder('Monolog\Handler\HandlerInterface')->getMock();

+ 3 - 12
tests/Monolog/Processor/IntrospectionProcessorTest.php

@@ -66,10 +66,7 @@ class IntrospectionProcessorTest extends TestCase
 
     public function testLevelTooLow()
     {
-        $input = [
-            'level' => Logger::DEBUG,
-            'extra' => [],
-        ];
+        $input = $this->getRecord(Logger::DEBUG);
 
         $expected = $input;
 
@@ -81,10 +78,7 @@ class IntrospectionProcessorTest extends TestCase
 
     public function testLevelEqual()
     {
-        $input = [
-            'level' => Logger::CRITICAL,
-            'extra' => [],
-        ];
+        $input = $this->getRecord(Logger::CRITICAL);
 
         $expected = $input;
         $expected['extra'] = [
@@ -103,10 +97,7 @@ class IntrospectionProcessorTest extends TestCase
 
     public function testLevelHigher()
     {
-        $input = [
-            'level' => Logger::EMERGENCY,
-            'extra' => [],
-        ];
+        $input = $this->getRecord(Logger::EMERGENCY);
 
         $expected = $input;
         $expected['extra'] = [