Adding Logger Tests
This commit is contained in:
parent
7bebb03f95
commit
aee348fa02
9 changed files with 447 additions and 82 deletions
|
@ -115,7 +115,6 @@ class StreamLogger extends AbstractLogger
|
|||
|
||||
$this->checkStream();
|
||||
|
||||
$this->stream = fopen($this->url, 'a');
|
||||
$formattedLog = $this->formatLog($level, $message, $context);
|
||||
fwrite($this->stream, $formattedLog);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ namespace Friendica\Util\Logger;
|
|||
|
||||
use Friendica\Network\HTTPException\InternalServerErrorException;
|
||||
use Friendica\Util\Introspection;
|
||||
use Psr\Log\InvalidArgumentException;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
/**
|
||||
|
@ -117,7 +116,7 @@ class SyslogLogger extends AbstractLogger
|
|||
public function mapLevelToPriority($level)
|
||||
{
|
||||
if (!array_key_exists($level, $this->logLevels)) {
|
||||
throw new InvalidArgumentException('LogLevel \'' . $level . '\' isn\'t valid.');
|
||||
throw new \InvalidArgumentException(sprintf('The level "%s" is not valid.', $level));
|
||||
}
|
||||
|
||||
return $this->logLevels[$level];
|
||||
|
@ -146,7 +145,7 @@ class SyslogLogger extends AbstractLogger
|
|||
throw new InternalServerErrorException('Can\'t open syslog for ident "' . $this->channel . '" and facility "' . $this->logFacility . '""');
|
||||
}
|
||||
|
||||
syslog($priority, $message);
|
||||
$this->syslogWrapper($priority, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -172,4 +171,15 @@ class SyslogLogger extends AbstractLogger
|
|||
|
||||
return $logMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* A syslog wrapper to make syslog functionality testable
|
||||
*
|
||||
* @param int $level The syslog priority
|
||||
* @param string $entry The message to send to the syslog function
|
||||
*/
|
||||
protected function syslogWrapper($level, $entry)
|
||||
{
|
||||
syslog($level, $entry);
|
||||
}
|
||||
}
|
||||
|
|
143
tests/src/Util/Logger/AbstractLoggerTest.php
Normal file
143
tests/src/Util/Logger/AbstractLoggerTest.php
Normal file
|
@ -0,0 +1,143 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Test\src\Util\Logger;
|
||||
|
||||
use Friendica\Test\MockedTest;
|
||||
use Friendica\Util\Introspection;
|
||||
use Mockery\MockInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
abstract class AbstractLoggerTest extends MockedTest
|
||||
{
|
||||
use LoggerDataTrait;
|
||||
|
||||
const LOGLINE = '/.* \[.*\]: .* \{.*\"file\":\".*\".*,.*\"line\":\d*,.*\"function\":\".*\".*,.*\"uid\":\".*\".*}/';
|
||||
|
||||
const FILE = 'test';
|
||||
const LINE = 666;
|
||||
const FUNC = 'myfunction';
|
||||
|
||||
/**
|
||||
* @var Introspection|MockInterface
|
||||
*/
|
||||
protected $introspection;
|
||||
|
||||
/**
|
||||
* Returns the content of the current logger instance
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function getContent();
|
||||
|
||||
/**
|
||||
* Returns the current logger instance
|
||||
*
|
||||
* @param string $level the default loglevel
|
||||
*
|
||||
* @return LoggerInterface
|
||||
*/
|
||||
abstract protected function getInstance($level = LogLevel::DEBUG);
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->introspection = \Mockery::mock(Introspection::class);
|
||||
$this->introspection->shouldReceive('getRecord')->andReturn([
|
||||
'file' => self::FILE,
|
||||
'line' => self::LINE,
|
||||
'function' => self::FUNC
|
||||
]);
|
||||
}
|
||||
|
||||
public function assertLogline($string)
|
||||
{
|
||||
$this->assertRegExp(self::LOGLINE, $string);
|
||||
}
|
||||
|
||||
public function assertLoglineNums($assertNum, $string)
|
||||
{
|
||||
$this->assertEquals($assertNum, preg_match_all(self::LOGLINE, $string));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the logger works correctly
|
||||
*/
|
||||
public function testNormal()
|
||||
{
|
||||
$logger = $this->getInstance();
|
||||
$logger->emergency('working!');
|
||||
$logger->alert('working too!');
|
||||
$logger->debug('and now?');
|
||||
$logger->notice('message', ['an' => 'context']);
|
||||
|
||||
$text = $this->getContent();
|
||||
$this->assertLogline($text);
|
||||
$this->assertLoglineNums(4, $text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a log entry is correctly interpolated
|
||||
*/
|
||||
public function testPsrInterpolate()
|
||||
{
|
||||
$logger = $this->getInstance();
|
||||
|
||||
$logger->emergency('A {psr} test', ['psr' => 'working']);
|
||||
$logger->alert('An {array} test', ['array' => ['it', 'is', 'working']]);
|
||||
$text = $this->getContent();
|
||||
$this->assertContains('A working test', $text);
|
||||
$this->assertContains('An ["it","is","working"] test', $text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a log entry contains all necessary information
|
||||
*/
|
||||
public function testContainsInformation()
|
||||
{
|
||||
$logger = $this->getInstance();
|
||||
$logger->emergency('A test');
|
||||
|
||||
$text = $this->getContent();
|
||||
$this->assertContains('"file":"' . self::FILE . '"', $text);
|
||||
$this->assertContains('"line":' . self::LINE, $text);
|
||||
$this->assertContains('"function":"' . self::FUNC . '"', $text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the minimum level is working
|
||||
*/
|
||||
public function testMinimumLevel()
|
||||
{
|
||||
$logger = $this->getInstance(LogLevel::NOTICE);
|
||||
|
||||
$logger->emergency('working');
|
||||
$logger->alert('working');
|
||||
$logger->error('working');
|
||||
$logger->warning('working');
|
||||
$logger->notice('working');
|
||||
$logger->info('not working');
|
||||
$logger->debug('not working');
|
||||
|
||||
$text = $this->getContent();
|
||||
|
||||
$this->assertLoglineNums(5, $text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test with different logging data
|
||||
* @dataProvider dataTests
|
||||
*/
|
||||
public function testDifferentTypes($function, $message, array $context)
|
||||
{
|
||||
$logger = $this->getInstance();
|
||||
$logger->$function($message, $context);
|
||||
|
||||
$text = $this->getContent();
|
||||
|
||||
$this->assertLogline($text);
|
||||
|
||||
$this->assertContains(@json_encode($context), $text);
|
||||
}
|
||||
}
|
52
tests/src/Util/Logger/LoggerDataTrait.php
Normal file
52
tests/src/Util/Logger/LoggerDataTrait.php
Normal file
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Test\src\Util\Logger;
|
||||
|
||||
trait LoggerDataTrait
|
||||
{
|
||||
public function dataTests()
|
||||
{
|
||||
return [
|
||||
'emergency' => [
|
||||
'function' => 'emergency',
|
||||
'message' => 'test',
|
||||
'context' => ['a' => 'context'],
|
||||
],
|
||||
'alert' => [
|
||||
'function' => 'alert',
|
||||
'message' => 'test {test}',
|
||||
'context' => ['a' => 'context', 2 => 'so', 'test' => 'works'],
|
||||
],
|
||||
'critical' => [
|
||||
'function' => 'critical',
|
||||
'message' => 'test crit 2345',
|
||||
'context' => ['a' => 'context', 'wit' => ['more', 'array']],
|
||||
],
|
||||
'error' => [
|
||||
'function' => 'error',
|
||||
'message' => 2.554,
|
||||
'context' => [],
|
||||
],
|
||||
'warning' => [
|
||||
'function' => 'warning',
|
||||
'message' => 'test warn',
|
||||
'context' => ['a' => 'context'],
|
||||
],
|
||||
'notice' => [
|
||||
'function' => 'notice',
|
||||
'message' => 2346,
|
||||
'context' => ['a' => 'context'],
|
||||
],
|
||||
'info' => [
|
||||
'function' => 'info',
|
||||
'message' => null,
|
||||
'context' => ['a' => 'context'],
|
||||
],
|
||||
'debug' => [
|
||||
'function' => 'debug',
|
||||
'message' => true,
|
||||
'context' => ['a' => false],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
58
tests/src/Util/Logger/ProfilerLoggerTest.php
Normal file
58
tests/src/Util/Logger/ProfilerLoggerTest.php
Normal file
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Test\src\Util\Logger;
|
||||
|
||||
use Friendica\Test\MockedTest;
|
||||
use Friendica\Util\Logger\ProfilerLogger;
|
||||
use Friendica\Util\Profiler;
|
||||
use Mockery\MockInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
class ProfilerLoggerTest extends MockedTest
|
||||
{
|
||||
use LoggerDataTrait;
|
||||
|
||||
/**
|
||||
* @var LoggerInterface|MockInterface
|
||||
*/
|
||||
private $logger;
|
||||
/**
|
||||
* @var Profiler|MockInterface
|
||||
*/
|
||||
private $profiler;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->logger = \Mockery::mock(LoggerInterface::class);
|
||||
$this->profiler = \Mockery::mock(Profiler::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the profiler is profiling data
|
||||
* @dataProvider dataTests
|
||||
*/
|
||||
public function testProfiling($function, $message, array $context)
|
||||
{
|
||||
$logger = new ProfilerLogger($this->logger, $this->profiler);
|
||||
|
||||
$this->logger->shouldReceive($function)->with($message, $context)->once();
|
||||
$this->profiler->shouldReceive('saveTimestamp')->with(\Mockery::any(), 'file', \Mockery::any())->once();
|
||||
$logger->$function($message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the log() function
|
||||
*/
|
||||
public function testProfilingLog()
|
||||
{
|
||||
$logger = new ProfilerLogger($this->logger, $this->profiler);
|
||||
|
||||
$this->logger->shouldReceive('log')->with(LogLevel::WARNING, 'test', ['a' => 'context'])->once();
|
||||
$this->profiler->shouldReceive('saveTimestamp')->with(\Mockery::any(), 'file', \Mockery::any())->once();
|
||||
|
||||
$logger->log(LogLevel::WARNING, 'test', ['a' => 'context']);
|
||||
}
|
||||
}
|
|
@ -2,126 +2,89 @@
|
|||
|
||||
namespace Friendica\Test\src\Util\Logger;
|
||||
|
||||
use Friendica\Test\MockedTest;
|
||||
use Friendica\Test\Util\VFSTrait;
|
||||
use Friendica\Util\Introspection;
|
||||
use Friendica\Util\Logger\StreamLogger;
|
||||
use Mockery\MockInterface;
|
||||
use org\bovigo\vfs\vfsStream;
|
||||
use org\bovigo\vfs\vfsStreamFile;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
class StreamLoggerTest extends MockedTest
|
||||
class StreamLoggerTest extends AbstractLoggerTest
|
||||
{
|
||||
const LOGLINE = '/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} .* \[.*\]: .* \{.*\"file\":\".*\".*,.*\"line\":\d*,.*\"function\":\".*\".*,.*\"uid\":\".*\".*,.*\"process_id\":\d*.*\}/';
|
||||
|
||||
const FILE = 'test';
|
||||
const LINE = 666;
|
||||
const FUNC = 'myfunction';
|
||||
|
||||
use VFSTrait;
|
||||
|
||||
/**
|
||||
* @var Introspection|MockInterface
|
||||
* @var StreamLogger
|
||||
*/
|
||||
private $introspection;
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* @var vfsStreamFile
|
||||
*/
|
||||
private $logfile;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->setUpVfsDir();
|
||||
|
||||
$this->introspection = \Mockery::mock(Introspection::class);
|
||||
$this->introspection->shouldReceive('getRecord')->andReturn([
|
||||
'file' => self::FILE,
|
||||
'line' => self::LINE,
|
||||
'function' => self::FUNC
|
||||
]);
|
||||
}
|
||||
|
||||
public function assertLogline($string)
|
||||
{
|
||||
$this->assertRegExp(self::LOGLINE, $string);
|
||||
}
|
||||
|
||||
public function assertLoglineNums($assertNum, $string)
|
||||
{
|
||||
$this->assertEquals($assertNum, preg_match_all(self::LOGLINE, $string));
|
||||
}
|
||||
|
||||
public function testNormal()
|
||||
{
|
||||
$logfile = vfsStream::newFile('friendica.log')
|
||||
->at($this->root);
|
||||
|
||||
$logger = new StreamLogger('test', $logfile->url(), $this->introspection);
|
||||
$logger->emergency('working!');
|
||||
$logger->alert('working too!');
|
||||
$logger->debug('and now?');
|
||||
$logger->notice('message', ['an' => 'context']);
|
||||
|
||||
$text = $logfile->getContent();
|
||||
$this->assertLogline($text);
|
||||
$this->assertLoglineNums(4, $text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a log entry is correctly interpolated
|
||||
* {@@inheritdoc}
|
||||
*/
|
||||
public function testPsrInterpolate()
|
||||
protected function getInstance($level = LogLevel::DEBUG)
|
||||
{
|
||||
$logfile = vfsStream::newFile('friendica.log')
|
||||
$this->logfile = vfsStream::newFile('friendica.log')
|
||||
->at($this->root);
|
||||
|
||||
$logger = new StreamLogger('test', $logfile->url(), $this->introspection);
|
||||
$this->logger = new StreamLogger('test', $this->logfile->url(), $this->introspection, $level);
|
||||
|
||||
$logger->emergency('A {psr} test', ['psr' => 'working']);
|
||||
$logger->alert('An {array} test', ['array' => ['it', 'is', 'working']]);
|
||||
$text = $logfile->getContent();
|
||||
$this->assertContains('A working test', $text);
|
||||
$this->assertContains('An ["it","is","working"] test', $text);
|
||||
return $this->logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a log entry contains all necessary information
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function testContainsInformation()
|
||||
protected function getContent()
|
||||
{
|
||||
$logfile = vfsStream::newFile('friendica.log')
|
||||
->at($this->root);
|
||||
|
||||
$logger = new StreamLogger('test', $logfile->url(), $this->introspection);
|
||||
|
||||
$logger->emergency('A test');
|
||||
|
||||
$text = $logfile->getContent();
|
||||
$this->assertContains('"process_id":' . getmypid(), $text);
|
||||
$this->assertContains('"file":"' . self::FILE . '"', $text);
|
||||
$this->assertContains('"line":' . self::LINE, $text);
|
||||
$this->assertContains('"function":"' . self::FUNC . '"', $text);
|
||||
return $this->logfile->getContent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the minimum level is working
|
||||
* Test if a stream is working
|
||||
*/
|
||||
public function testMinimumLevel()
|
||||
public function testStream()
|
||||
{
|
||||
$logfile = vfsStream::newFile('friendica.log')
|
||||
->at($this->root);
|
||||
|
||||
$logger = new StreamLogger('test', $logfile->url(), $this->introspection, LogLevel::NOTICE);
|
||||
$filehandler = fopen($logfile->url(), 'ab');
|
||||
|
||||
$logger = new StreamLogger('test', $filehandler, $this->introspection);
|
||||
$logger->emergency('working');
|
||||
$logger->alert('working');
|
||||
$logger->error('working');
|
||||
$logger->warning('working');
|
||||
$logger->notice('working');
|
||||
$logger->info('not working');
|
||||
$logger->debug('not working');
|
||||
|
||||
$text = $logfile->getContent();
|
||||
|
||||
$this->assertLoglineNums(5, $text);
|
||||
$this->assertLogline($text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the close statement is working
|
||||
*/
|
||||
public function testClose()
|
||||
{
|
||||
$logfile = vfsStream::newFile('friendica.log')
|
||||
->at($this->root);
|
||||
|
||||
$logger = new StreamLogger('test', $logfile->url(), $this->introspection);
|
||||
$logger->emergency('working');
|
||||
$logger->close();
|
||||
// close doesn't affect
|
||||
$logger->emergency('working too');
|
||||
|
||||
$text = $logfile->getContent();
|
||||
|
||||
$this->assertLoglineNums(2, $text);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -187,4 +150,14 @@ class StreamLoggerTest extends MockedTest
|
|||
|
||||
$logger->log('NOPE', 'a test');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test when the file is null
|
||||
* @expectedException \InvalidArgumentException
|
||||
* @expectedExceptionMessage A stream must either be a resource or a string.
|
||||
*/
|
||||
public function testWrongFile()
|
||||
{
|
||||
$logger = new StreamLogger('test', null, $this->introspection);
|
||||
}
|
||||
}
|
||||
|
|
62
tests/src/Util/Logger/SyslogLoggerTest.php
Normal file
62
tests/src/Util/Logger/SyslogLoggerTest.php
Normal file
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Test\src\Util\Logger;
|
||||
|
||||
use Friendica\Util\Logger\SyslogLogger;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
class SyslogLoggerTest extends AbstractLoggerTest
|
||||
{
|
||||
/**
|
||||
* @var SyslogLoggerWrapper
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->introspection->shouldReceive('addClasses')->with([SyslogLogger::class]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getContent()
|
||||
{
|
||||
return $this->logger->getContent();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getInstance($level = LogLevel::DEBUG)
|
||||
{
|
||||
$this->logger = new SyslogLoggerWrapper('test', $this->introspection, $level);
|
||||
|
||||
return $this->logger;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test when the minimum level is not valid
|
||||
* @expectedException \InvalidArgumentException
|
||||
* @expectedExceptionMessageRegExp /The level ".*" is not valid./
|
||||
*/
|
||||
public function testWrongMinimumLevel()
|
||||
{
|
||||
$logger = new SyslogLoggerWrapper('test', $this->introspection, 'NOPE');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test when the minimum level is not valid
|
||||
* @expectedException \InvalidArgumentException
|
||||
* @expectedExceptionMessageRegExp /The level ".*" is not valid./
|
||||
*/
|
||||
public function testWrongLogLevel()
|
||||
{
|
||||
$logger = new SyslogLoggerWrapper('test', $this->introspection);
|
||||
|
||||
$logger->log('NOPE', 'a test');
|
||||
}
|
||||
}
|
37
tests/src/Util/Logger/SyslogLoggerWrapper.php
Normal file
37
tests/src/Util/Logger/SyslogLoggerWrapper.php
Normal file
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Test\src\Util\Logger;
|
||||
|
||||
use Friendica\Util\Introspection;
|
||||
use Friendica\Util\Logger\SyslogLogger;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
class SyslogLoggerWrapper extends SyslogLogger
|
||||
{
|
||||
private $content;
|
||||
|
||||
public function __construct($channel, Introspection $introspection, $level = LogLevel::NOTICE, $logOpts = LOG_PID, $logFacility = LOG_USER)
|
||||
{
|
||||
parent::__construct($channel, $introspection, $level, $logOpts, $logFacility);
|
||||
|
||||
$this->content = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the content from the wrapped Syslog
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getContent()
|
||||
{
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function syslogWrapper($level, $entry)
|
||||
{
|
||||
$this->content .= $entry . PHP_EOL;
|
||||
}
|
||||
}
|
31
tests/src/Util/Logger/VoidLoggerTest.php
Normal file
31
tests/src/Util/Logger/VoidLoggerTest.php
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Test\src\Util\Logger;
|
||||
|
||||
use Friendica\Test\MockedTest;
|
||||
use Friendica\Util\Logger\VoidLogger;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
class VoidLoggerTest extends MockedTest
|
||||
{
|
||||
use LoggerDataTrait;
|
||||
|
||||
/**
|
||||
* Test if the profiler is profiling data
|
||||
* @dataProvider dataTests
|
||||
*/
|
||||
public function testNormal($function, $message, array $context)
|
||||
{
|
||||
$logger = new VoidLogger();
|
||||
$logger->$function($message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the log() function
|
||||
*/
|
||||
public function testProfilingLog()
|
||||
{
|
||||
$logger = new VoidLogger();
|
||||
$logger->log(LogLevel::WARNING, 'test', ['a' => 'context']);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue