Dustin Wilson
1 year ago
8 changed files with 294 additions and 36 deletions
@ -0,0 +1,151 @@ |
|||||
|
<?php |
||||
|
/** |
||||
|
* @license MIT |
||||
|
* Copyright 2022 Dustin Wilson, et al. |
||||
|
* See LICENSE and AUTHORS files for details |
||||
|
*/ |
||||
|
|
||||
|
declare(strict_types=1); |
||||
|
namespace MensBeam\Logger\Test; |
||||
|
use MensBeam\Logger; |
||||
|
use MensBeam\Logger\{ |
||||
|
Handler, |
||||
|
InvalidArgumentException, |
||||
|
Level, |
||||
|
RangeException, |
||||
|
StreamHandler |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
/** @covers \MensBeam\Logger\Handler */ |
||||
|
class TestHandler extends ErrorHandlingTestCase { |
||||
|
public function testConstructor(): void { |
||||
|
// Test Level enums and integers, duplicated |
||||
|
$h = new StreamHandler(levels: [ |
||||
|
Level::Notice, |
||||
|
6, |
||||
|
Level::Debug, |
||||
|
Level::Info, |
||||
|
Level::Critical, |
||||
|
0, |
||||
|
Level::Emergency, |
||||
|
Level::Error, |
||||
|
Level::Alert, |
||||
|
3, |
||||
|
Level::Warning |
||||
|
]); |
||||
|
$this->assertSame([ 0, 1, 2, 3, 4, 5, 6, 7 ], $h->getLevels()); |
||||
|
} |
||||
|
|
||||
|
public function testOptions(): void { |
||||
|
$h = new StreamHandler(options: [ |
||||
|
'bubbles' => false, |
||||
|
'datetimeFormat' => 'Y-m-d\TH:i:sP' |
||||
|
]); |
||||
|
$this->assertFalse($h->getOption('bubbles')); |
||||
|
$this->assertSame('Y-m-d\TH:i:sP', $h->getOption('datetimeFormat')); |
||||
|
$h->setOption('bubbles', true); |
||||
|
$h->setOption('datetimeFormat', 'Y-m-d'); |
||||
|
$this->assertTrue($h->getOption('bubbles')); |
||||
|
$this->assertSame('Y-m-d', $h->getOption('datetimeFormat')); |
||||
|
} |
||||
|
|
||||
|
/** @dataProvider provideFatalErrorTests */ |
||||
|
public function testFatalErrors(string $throwableClassName, int $code, string $message, \Closure $closure): void { |
||||
|
$this->expectException($throwableClassName); |
||||
|
$this->expectExceptionMessage($message); |
||||
|
if ($throwableClassName === Error::class) { |
||||
|
$this->expectExceptionCode($code); |
||||
|
} |
||||
|
|
||||
|
$closure(new StreamHandler()); |
||||
|
} |
||||
|
|
||||
|
/** @dataProvider provideNonFatalErrorTests */ |
||||
|
public function testNonFatalErrors(int $code, string $message, \Closure $closure): void { |
||||
|
$closure(new StreamHandler()); |
||||
|
$this->assertEquals($code, $this->lastError?->getCode()); |
||||
|
$this->assertSame($message, $this->lastError?->getMessage()); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
public function testInvocation(): void { |
||||
|
$s = fopen('php://memory', 'r+'); |
||||
|
// Test setting the datetimeFormat and messageTransform options, showing |
||||
|
// a very simple example of using sprintf for interpolation. |
||||
|
$l = new Logger('ook', new StreamHandler(stream: $s, options: [ |
||||
|
'datetimeFormat' => 'Y-m-d', |
||||
|
'messageTransform' => function (string $message, array $context): string { |
||||
|
return vsprintf($message, $context); |
||||
|
} |
||||
|
])); |
||||
|
$l->error('Ook! %s', [ 'Eek!' ]); |
||||
|
rewind($s); |
||||
|
$o = stream_get_contents($s); |
||||
|
$this->assertEquals(1, preg_match('/^' . (new \DateTimeImmutable())->format('Y-m-d') . ' ook ERROR Ook! Eek!\n/', $o)); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
public static function provideFatalErrorTests(): iterable { |
||||
|
$iterable = [ |
||||
|
[ |
||||
|
InvalidArgumentException::class, |
||||
|
0, |
||||
|
'Argument #1 ($levels) must not be empty', |
||||
|
function (Handler $h): void { |
||||
|
$h->setLevels(); |
||||
|
} |
||||
|
], |
||||
|
[ |
||||
|
InvalidArgumentException::class, |
||||
|
0, |
||||
|
'Value #5 of argument #2 ($levels) must be of type int|MensBeam\Logger\Level, string given', |
||||
|
function (Handler $h): void { |
||||
|
new StreamHandler(levels: [ 0, 1, 2, 3, '4', 5, 6, 7 ]); |
||||
|
} |
||||
|
], |
||||
|
[ |
||||
|
RangeException::class, |
||||
|
0, |
||||
|
'Value #2 of argument #1 ($levels) cannot be 42; it is not in the range 0 - 7', |
||||
|
function (Handler $h): void { |
||||
|
$h->setLevels(0, 42); |
||||
|
} |
||||
|
] |
||||
|
]; |
||||
|
|
||||
|
foreach ($iterable as $i) { |
||||
|
yield $i; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public static function provideNonFatalErrorTests(): iterable { |
||||
|
$iterable = [ |
||||
|
[ |
||||
|
\E_USER_WARNING, |
||||
|
'Undefined option in ' . StreamHandler::class . ': ook', |
||||
|
function (Handler $h): void { |
||||
|
$h = new StreamHandler(options: [ 'ook' => 'eek' ]); |
||||
|
} |
||||
|
], |
||||
|
[ |
||||
|
\E_USER_WARNING, |
||||
|
'Undefined option in ' . StreamHandler::class . ': ook', |
||||
|
function (Handler $h): void { |
||||
|
$ook = $h->getOption('ook'); |
||||
|
} |
||||
|
], |
||||
|
[ |
||||
|
\E_USER_WARNING, |
||||
|
'Undefined option in ' . StreamHandler::class . ': ook', |
||||
|
function (Handler $h): void { |
||||
|
$ook = $h->setOption('ook', 'eek'); |
||||
|
} |
||||
|
] |
||||
|
]; |
||||
|
|
||||
|
foreach ($iterable as $i) { |
||||
|
yield $i; |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,37 @@ |
|||||
|
<?php |
||||
|
/** |
||||
|
* @license MIT |
||||
|
* Copyright 2022 Dustin Wilson, et al. |
||||
|
* See LICENSE and AUTHORS files for details |
||||
|
*/ |
||||
|
|
||||
|
declare(strict_types=1); |
||||
|
namespace MensBeam\Logger\Test; |
||||
|
use MensBeam\Logger; |
||||
|
use MensBeam\Logger\Level, |
||||
|
Psr\Log\LogLevel; |
||||
|
|
||||
|
|
||||
|
/** @covers \MensBeam\Logger\Level */ |
||||
|
class TestLevel extends \PHPUnit\Framework\TestCase { |
||||
|
/** @dataProvider provideConversionsTests */ |
||||
|
public function testConversions(string $PSR3Level, Level $level): void { |
||||
|
$this->assertSame($level, Level::fromPSR3($PSR3Level)); |
||||
|
$this->assertSame($PSR3Level, $level->toPSR3()); |
||||
|
} |
||||
|
|
||||
|
public static function provideConversionsTests(): iterable { |
||||
|
foreach ([ |
||||
|
[ LogLevel::EMERGENCY, Level::Emergency ], |
||||
|
[ LogLevel::ALERT, Level::Alert ], |
||||
|
[ LogLevel::CRITICAL, Level::Critical ], |
||||
|
[ LogLevel::ERROR, Level::Error ], |
||||
|
[ LogLevel::WARNING, Level::Warning ], |
||||
|
[ LogLevel::NOTICE, Level::Notice ], |
||||
|
[ LogLevel::INFO, Level::Info ], |
||||
|
[ LogLevel::DEBUG, Level::Debug ] |
||||
|
] as $l) { |
||||
|
yield $l; |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,11 @@ |
|||||
|
<?php |
||||
|
/** |
||||
|
* @license MIT |
||||
|
* Copyright 2022 Dustin Wilson, et al. |
||||
|
* See LICENSE and AUTHORS files for details |
||||
|
*/ |
||||
|
|
||||
|
declare(strict_types=1); |
||||
|
namespace MensBeam\Logger\Test; |
||||
|
|
||||
|
class Error extends \Error {} |
@ -0,0 +1,31 @@ |
|||||
|
<?php |
||||
|
/** |
||||
|
* @license MIT |
||||
|
* Copyright 2022 Dustin Wilson, et al. |
||||
|
* See LICENSE and AUTHORS files for details |
||||
|
*/ |
||||
|
|
||||
|
declare(strict_types=1); |
||||
|
namespace MensBeam\Logger\Test; |
||||
|
|
||||
|
|
||||
|
class ErrorHandlingTestCase extends \PHPUnit\Framework\TestCase { |
||||
|
protected ?Error $lastError = null; |
||||
|
|
||||
|
|
||||
|
public function setUp(): void { |
||||
|
set_error_handler([ $this, 'handleError' ]); |
||||
|
} |
||||
|
|
||||
|
public function tearDown(): void { |
||||
|
restore_error_handler(); |
||||
|
} |
||||
|
|
||||
|
public function handleError(int $code, string $message, string $file, int $line): void { |
||||
|
$e = new Error($message, $code); |
||||
|
$this->lastError = $e; |
||||
|
if (in_array($code, [ \E_ERROR, \E_PARSE, \E_CORE_ERROR, \E_COMPILE_ERROR, \E_USER_ERROR, \E_RECOVERABLE_ERROR ])) { |
||||
|
throw $e; |
||||
|
} |
||||
|
} |
||||
|
} |
Loading…
Reference in new issue