Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,15 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
# There is no code, we don't have to test old PHP versions
php-versions:
- 7.4
- 8.0
- 8.1
dependency-levels:
- 'highest'
experimental:
- false
include:
- php-versions: 7.4
- php-versions: 8.0
dependency-levels: 'lowest'
experimental: false
fail-fast: false
Expand All @@ -30,7 +28,7 @@ jobs:
php-version: ${{ matrix.php-versions }}

- name: Validating PHP syntax
run: find ./tests/ -type f -name '*.php' -print0 | xargs -0 -L 1 -P 4 -- php -l
run: find ./{src,tests}/ -type f -name '*.php' -print0 | xargs -0 -L 1 -P 4 -- php -l

- name: Validate composer.json and composer.lock
run: composer validate
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [1.1.0] - YYYY-MM-DD
### Added
- Import classes from [`psr/log`][] `v1.1.4`, for compatibility with `v2.0.0` and `v3.0.0`.

## [1.0.0] - 2022-09-07
### Changed
- Compatible with PHP 7.4 and 8.x. Dropped support for lower versions as Test class is marked @requires PHP 7.4
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ If the project supports older versions of PHP:
The version of `fig/log-test` that is installed after composer dependencies resolution varies with the version of `psr/log`.

| psr/log | fig/log-test | |
|---------------|---------------|-------------------------------------------------|
| `^1.1.14` | `1.0.*` | Empty package, classes a provided by `psr/log`. |
| `^2.0\|^3.0` | `^1.1` | Imports test classes removed from `psr/log`. |
|---------------|--------------|-------------------------------------------------|
| `^1.1.14` | `1.0.*` | Empty package, classes a provided by `psr/log`. |
| `^2.0\|^3.0` | `^1.1` | Imports test classes removed from `psr/log`. |

[`psr/log`]: https://packagist.org/packages/psr/log
[PSR-3]: https://www.php-fig.org/psr/psr-3/
9 changes: 7 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,18 @@
}
],
"require": {
"php": "^7.4 | ^8.0",
"psr/log": "^1.1.1"
"php": "^8.0",
"psr/log": "^2.0 | ^3.0"
},
"require-dev": {
"phpunit/phpunit": "^8.0 | ^9.0",
"squizlabs/php_codesniffer": "^3.6"
},
"autoload": {
"psr-4": {
"Psr\\Log\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"Fig\\Log\\Tests\\": "tests"
Expand Down
18 changes: 18 additions & 0 deletions src/Test/DummyTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace Psr\Log\Test;

/**
* This class is internal and does not follow the BC promise.
*
* Do NOT use this class in any way.
*
* @internal
*/
class DummyTest
{
public function __toString()
{
return 'DummyTest';
}
}
135 changes: 135 additions & 0 deletions src/Test/LoggerInterfaceTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
<?php

namespace Psr\Log\Test;

use Psr\Log\InvalidArgumentException;
use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
use PHPUnit\Framework\TestCase;

/**
* Provides a base test class for ensuring compliance with the LoggerInterface.
*
* Implementors can extend the class and implement abstract methods to run this
* as part of their test suite.
*/
abstract class LoggerInterfaceTest extends TestCase
{
/**
* Return an instance of the logger to be tested.
*
* @return LoggerInterface
*/
abstract public function getLogger();

/**
* This must return the log messages in order.
*
* The simple formatting of the messages is: "<LOG LEVEL> <MESSAGE>".
*
* Example ->error('Foo') would yield "error Foo".
*
* @return string[]
*/
abstract public function getLogs();

public function testImplements()
{
$this->assertInstanceOf(LoggerInterface::class, $this->getLogger());
}

/**
* @dataProvider provideLevelsAndMessages
*/
public function testLogsAtAllLevels($level, $message)
{
$logger = $this->getLogger();
$logger->{$level}($message, ['user' => 'Bob']);
$logger->log($level, $message, ['user' => 'Bob']);

$expected = [
$level . ' message of level ' . $level . ' with context: Bob',
$level . ' message of level ' . $level . ' with context: Bob',
];
$this->assertEquals($expected, $this->getLogs());
}

public function provideLevelsAndMessages()
{
return [
LogLevel::EMERGENCY => [LogLevel::EMERGENCY, 'message of level emergency with context: {user}'],
LogLevel::ALERT => [LogLevel::ALERT, 'message of level alert with context: {user}'],
LogLevel::CRITICAL => [LogLevel::CRITICAL, 'message of level critical with context: {user}'],
LogLevel::ERROR => [LogLevel::ERROR, 'message of level error with context: {user}'],
LogLevel::WARNING => [LogLevel::WARNING, 'message of level warning with context: {user}'],
LogLevel::NOTICE => [LogLevel::NOTICE, 'message of level notice with context: {user}'],
LogLevel::INFO => [LogLevel::INFO, 'message of level info with context: {user}'],
LogLevel::DEBUG => [LogLevel::DEBUG, 'message of level debug with context: {user}'],
];
}

public function testThrowsOnInvalidLevel()
{
$this->expectException(InvalidArgumentException::class);
$logger = $this->getLogger();
$logger->log('invalid level', 'Foo');
}

public function testContextReplacement()
{
$logger = $this->getLogger();
$logger->info('{Message {nothing} {user} {foo.bar} a}', ['user' => 'Bob', 'foo.bar' => 'Bar']);

$expected = ['info {Message {nothing} Bob Bar a}'];
$this->assertEquals($expected, $this->getLogs());
}

public function testObjectCastToString()
{
$dummy = $this->createPartialMock(DummyTest::class, ['__toString']);
$dummy->expects($this->once())
->method('__toString')
->will($this->returnValue('DUMMY'));

$this->getLogger()->warning($dummy);

$expected = ['warning DUMMY'];
$this->assertEquals($expected, $this->getLogs());
}

public function testContextCanContainAnything()
{
$closed = fopen('php://memory', 'r');
fclose($closed);

$context = [
'bool' => true,
'null' => null,
'string' => 'Foo',
'int' => 0,
'float' => 0.5,
'nested' => ['with object' => new DummyTest()],
'object' => new \DateTime(),
'resource' => fopen('php://memory', 'r'),
'closed' => $closed,
];

$this->getLogger()->warning('Crazy context data', $context);

$expected = ['warning Crazy context data'];
$this->assertEquals($expected, $this->getLogs());
}

public function testContextExceptionKeyCanBeExceptionOrOtherValues()
{
$logger = $this->getLogger();
$logger->warning('Random message', ['exception' => 'oops']);
$logger->critical('Uncaught Exception!', ['exception' => new \LogicException('Fail')]);

$expected = [
'warning Random message',
'critical Uncaught Exception!'
];
$this->assertEquals($expected, $this->getLogs());
}
}
Loading