logger 추가
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog;
|
||||
|
||||
use Monolog\Handler\TestHandler;
|
||||
|
||||
class ErrorHandlerTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testHandleError()
|
||||
{
|
||||
$logger = new Logger('test', array($handler = new TestHandler));
|
||||
$errHandler = new ErrorHandler($logger);
|
||||
|
||||
$errHandler->registerErrorHandler(array(E_USER_NOTICE => Logger::EMERGENCY), false);
|
||||
trigger_error('Foo', E_USER_ERROR);
|
||||
$this->assertCount(1, $handler->getRecords());
|
||||
$this->assertTrue($handler->hasErrorRecords());
|
||||
trigger_error('Foo', E_USER_NOTICE);
|
||||
$this->assertCount(2, $handler->getRecords());
|
||||
$this->assertTrue($handler->hasEmergencyRecords());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Formatter;
|
||||
|
||||
use Monolog\Logger;
|
||||
|
||||
class ChromePHPFormatterTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @covers Monolog\Formatter\ChromePHPFormatter::format
|
||||
*/
|
||||
public function testDefaultFormat()
|
||||
{
|
||||
$formatter = new ChromePHPFormatter();
|
||||
$record = array(
|
||||
'level' => Logger::ERROR,
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => 'meh',
|
||||
'context' => array('from' => 'logger'),
|
||||
'datetime' => new \DateTime("@0"),
|
||||
'extra' => array('ip' => '127.0.0.1'),
|
||||
'message' => 'log',
|
||||
);
|
||||
|
||||
$message = $formatter->format($record);
|
||||
|
||||
$this->assertEquals(
|
||||
array(
|
||||
'meh',
|
||||
array(
|
||||
'message' => 'log',
|
||||
'context' => array('from' => 'logger'),
|
||||
'extra' => array('ip' => '127.0.0.1'),
|
||||
),
|
||||
'unknown',
|
||||
'error',
|
||||
),
|
||||
$message
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Formatter\ChromePHPFormatter::format
|
||||
*/
|
||||
public function testFormatWithFileAndLine()
|
||||
{
|
||||
$formatter = new ChromePHPFormatter();
|
||||
$record = array(
|
||||
'level' => Logger::CRITICAL,
|
||||
'level_name' => 'CRITICAL',
|
||||
'channel' => 'meh',
|
||||
'context' => array('from' => 'logger'),
|
||||
'datetime' => new \DateTime("@0"),
|
||||
'extra' => array('ip' => '127.0.0.1', 'file' => 'test', 'line' => 14),
|
||||
'message' => 'log',
|
||||
);
|
||||
|
||||
$message = $formatter->format($record);
|
||||
|
||||
$this->assertEquals(
|
||||
array(
|
||||
'meh',
|
||||
array(
|
||||
'message' => 'log',
|
||||
'context' => array('from' => 'logger'),
|
||||
'extra' => array('ip' => '127.0.0.1'),
|
||||
),
|
||||
'test : 14',
|
||||
'error',
|
||||
),
|
||||
$message
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Formatter\ChromePHPFormatter::format
|
||||
*/
|
||||
public function testFormatWithoutContext()
|
||||
{
|
||||
$formatter = new ChromePHPFormatter();
|
||||
$record = array(
|
||||
'level' => Logger::DEBUG,
|
||||
'level_name' => 'DEBUG',
|
||||
'channel' => 'meh',
|
||||
'context' => array(),
|
||||
'datetime' => new \DateTime("@0"),
|
||||
'extra' => array(),
|
||||
'message' => 'log',
|
||||
);
|
||||
|
||||
$message = $formatter->format($record);
|
||||
|
||||
$this->assertEquals(
|
||||
array(
|
||||
'meh',
|
||||
'log',
|
||||
'unknown',
|
||||
'log',
|
||||
),
|
||||
$message
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Formatter\ChromePHPFormatter::formatBatch
|
||||
*/
|
||||
public function testBatchFormatThrowException()
|
||||
{
|
||||
$formatter = new ChromePHPFormatter();
|
||||
$records = array(
|
||||
array(
|
||||
'level' => Logger::INFO,
|
||||
'level_name' => 'INFO',
|
||||
'channel' => 'meh',
|
||||
'context' => array(),
|
||||
'datetime' => new \DateTime("@0"),
|
||||
'extra' => array(),
|
||||
'message' => 'log',
|
||||
),
|
||||
array(
|
||||
'level' => Logger::WARNING,
|
||||
'level_name' => 'WARNING',
|
||||
'channel' => 'foo',
|
||||
'context' => array(),
|
||||
'datetime' => new \DateTime("@0"),
|
||||
'extra' => array(),
|
||||
'message' => 'log2',
|
||||
),
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
array(
|
||||
array(
|
||||
'meh',
|
||||
'log',
|
||||
'unknown',
|
||||
'info',
|
||||
),
|
||||
array(
|
||||
'foo',
|
||||
'log2',
|
||||
'unknown',
|
||||
'warn',
|
||||
),
|
||||
),
|
||||
$formatter->formatBatch($records)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Formatter;
|
||||
|
||||
use Monolog\Logger;
|
||||
|
||||
class ElasticaFormatterTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
if (!class_exists("Elastica\Document")) {
|
||||
$this->markTestSkipped("ruflin/elastica not installed");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Formatter\ElasticaFormatter::__construct
|
||||
* @covers Monolog\Formatter\ElasticaFormatter::format
|
||||
* @covers Monolog\Formatter\ElasticaFormatter::getDocument
|
||||
*/
|
||||
public function testFormat()
|
||||
{
|
||||
// test log message
|
||||
$msg = array(
|
||||
'level' => Logger::ERROR,
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => 'meh',
|
||||
'context' => array('foo' => 7, 'bar', 'class' => new \stdClass),
|
||||
'datetime' => new \DateTime("@0"),
|
||||
'extra' => array(),
|
||||
'message' => 'log',
|
||||
);
|
||||
|
||||
// expected values
|
||||
$expected = $msg;
|
||||
$expected['datetime'] = '1970-01-01T00:00:00.000000+00:00';
|
||||
$expected['context'] = array(
|
||||
'class' => '[object] (stdClass: {})',
|
||||
'foo' => 7,
|
||||
0 => 'bar',
|
||||
);
|
||||
|
||||
// format log message
|
||||
$formatter = new ElasticaFormatter('my_index', 'doc_type');
|
||||
$doc = $formatter->format($msg);
|
||||
$this->assertInstanceOf('Elastica\Document', $doc);
|
||||
|
||||
// Document parameters
|
||||
$params = $doc->getParams();
|
||||
$this->assertEquals('my_index', $params['_index']);
|
||||
$this->assertEquals('doc_type', $params['_type']);
|
||||
|
||||
// Document data values
|
||||
$data = $doc->getData();
|
||||
foreach (array_keys($expected) as $key) {
|
||||
$this->assertEquals($expected[$key], $data[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Formatter\ElasticaFormatter::getIndex
|
||||
* @covers Monolog\Formatter\ElasticaFormatter::getType
|
||||
*/
|
||||
public function testGetters()
|
||||
{
|
||||
$formatter = new ElasticaFormatter('my_index', 'doc_type');
|
||||
$this->assertEquals('my_index', $formatter->getIndex());
|
||||
$this->assertEquals('doc_type', $formatter->getType());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Formatter;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Monolog\TestCase;
|
||||
|
||||
class FlowdockFormatterTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers Monolog\Formatter\FlowdockFormatter::format
|
||||
*/
|
||||
public function testFormat()
|
||||
{
|
||||
$formatter = new FlowdockFormatter('test_source', 'source@test.com');
|
||||
$record = $this->getRecord();
|
||||
|
||||
$expected = array(
|
||||
'source' => 'test_source',
|
||||
'from_address' => 'source@test.com',
|
||||
'subject' => 'in test_source: WARNING - test',
|
||||
'content' => 'test',
|
||||
'tags' => array('#logs', '#warning', '#test'),
|
||||
'project' => 'test_source',
|
||||
);
|
||||
$formatted = $formatter->format($record);
|
||||
|
||||
$this->assertEquals($expected, $formatted['flowdock']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ covers Monolog\Formatter\FlowdockFormatter::formatBatch
|
||||
*/
|
||||
public function testFormatBatch()
|
||||
{
|
||||
$formatter = new FlowdockFormatter('test_source', 'source@test.com');
|
||||
$records = array(
|
||||
$this->getRecord(Logger::WARNING),
|
||||
$this->getRecord(Logger::DEBUG),
|
||||
);
|
||||
$formatted = $formatter->formatBatch($records);
|
||||
|
||||
$this->assertArrayHasKey('flowdock', $formatted[0]);
|
||||
$this->assertArrayHasKey('flowdock', $formatted[1]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Formatter;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Monolog\TestCase;
|
||||
|
||||
class FluentdFormatterTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers Monolog\Formatter\FluentdFormatter::__construct
|
||||
* @covers Monolog\Formatter\FluentdFormatter::isUsingLevelsInTag
|
||||
*/
|
||||
public function testConstruct()
|
||||
{
|
||||
$formatter = new FluentdFormatter();
|
||||
$this->assertEquals(false, $formatter->isUsingLevelsInTag());
|
||||
$formatter = new FluentdFormatter(false);
|
||||
$this->assertEquals(false, $formatter->isUsingLevelsInTag());
|
||||
$formatter = new FluentdFormatter(true);
|
||||
$this->assertEquals(true, $formatter->isUsingLevelsInTag());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Formatter\FluentdFormatter::format
|
||||
*/
|
||||
public function testFormat()
|
||||
{
|
||||
$record = $this->getRecord(Logger::WARNING);
|
||||
$record['datetime'] = new \DateTime("@0");
|
||||
|
||||
$formatter = new FluentdFormatter();
|
||||
$this->assertEquals(
|
||||
'["test",0,{"message":"test","extra":[],"level":300,"level_name":"WARNING"}]',
|
||||
$formatter->format($record)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Formatter\FluentdFormatter::format
|
||||
*/
|
||||
public function testFormatWithTag()
|
||||
{
|
||||
$record = $this->getRecord(Logger::ERROR);
|
||||
$record['datetime'] = new \DateTime("@0");
|
||||
|
||||
$formatter = new FluentdFormatter(true);
|
||||
$this->assertEquals(
|
||||
'["test.error",0,{"message":"test","extra":[]}]',
|
||||
$formatter->format($record)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,258 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Formatter;
|
||||
|
||||
use Monolog\Logger;
|
||||
|
||||
class GelfMessageFormatterTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
if (!class_exists('\Gelf\Message')) {
|
||||
$this->markTestSkipped("graylog2/gelf-php or mlehner/gelf-php is not installed");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Formatter\GelfMessageFormatter::format
|
||||
*/
|
||||
public function testDefaultFormatter()
|
||||
{
|
||||
$formatter = new GelfMessageFormatter();
|
||||
$record = array(
|
||||
'level' => Logger::ERROR,
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => 'meh',
|
||||
'context' => array(),
|
||||
'datetime' => new \DateTime("@0"),
|
||||
'extra' => array(),
|
||||
'message' => 'log',
|
||||
);
|
||||
|
||||
$message = $formatter->format($record);
|
||||
|
||||
$this->assertInstanceOf('Gelf\Message', $message);
|
||||
$this->assertEquals(0, $message->getTimestamp());
|
||||
$this->assertEquals('log', $message->getShortMessage());
|
||||
$this->assertEquals('meh', $message->getFacility());
|
||||
$this->assertEquals(null, $message->getLine());
|
||||
$this->assertEquals(null, $message->getFile());
|
||||
$this->assertEquals($this->isLegacy() ? 3 : 'error', $message->getLevel());
|
||||
$this->assertNotEmpty($message->getHost());
|
||||
|
||||
$formatter = new GelfMessageFormatter('mysystem');
|
||||
|
||||
$message = $formatter->format($record);
|
||||
|
||||
$this->assertInstanceOf('Gelf\Message', $message);
|
||||
$this->assertEquals('mysystem', $message->getHost());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Formatter\GelfMessageFormatter::format
|
||||
*/
|
||||
public function testFormatWithFileAndLine()
|
||||
{
|
||||
$formatter = new GelfMessageFormatter();
|
||||
$record = array(
|
||||
'level' => Logger::ERROR,
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => 'meh',
|
||||
'context' => array('from' => 'logger'),
|
||||
'datetime' => new \DateTime("@0"),
|
||||
'extra' => array('file' => 'test', 'line' => 14),
|
||||
'message' => 'log',
|
||||
);
|
||||
|
||||
$message = $formatter->format($record);
|
||||
|
||||
$this->assertInstanceOf('Gelf\Message', $message);
|
||||
$this->assertEquals('test', $message->getFile());
|
||||
$this->assertEquals(14, $message->getLine());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Formatter\GelfMessageFormatter::format
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testFormatInvalidFails()
|
||||
{
|
||||
$formatter = new GelfMessageFormatter();
|
||||
$record = array(
|
||||
'level' => Logger::ERROR,
|
||||
'level_name' => 'ERROR',
|
||||
);
|
||||
|
||||
$formatter->format($record);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Formatter\GelfMessageFormatter::format
|
||||
*/
|
||||
public function testFormatWithContext()
|
||||
{
|
||||
$formatter = new GelfMessageFormatter();
|
||||
$record = array(
|
||||
'level' => Logger::ERROR,
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => 'meh',
|
||||
'context' => array('from' => 'logger'),
|
||||
'datetime' => new \DateTime("@0"),
|
||||
'extra' => array('key' => 'pair'),
|
||||
'message' => 'log',
|
||||
);
|
||||
|
||||
$message = $formatter->format($record);
|
||||
|
||||
$this->assertInstanceOf('Gelf\Message', $message);
|
||||
|
||||
$message_array = $message->toArray();
|
||||
|
||||
$this->assertArrayHasKey('_ctxt_from', $message_array);
|
||||
$this->assertEquals('logger', $message_array['_ctxt_from']);
|
||||
|
||||
// Test with extraPrefix
|
||||
$formatter = new GelfMessageFormatter(null, null, 'CTX');
|
||||
$message = $formatter->format($record);
|
||||
|
||||
$this->assertInstanceOf('Gelf\Message', $message);
|
||||
|
||||
$message_array = $message->toArray();
|
||||
|
||||
$this->assertArrayHasKey('_CTXfrom', $message_array);
|
||||
$this->assertEquals('logger', $message_array['_CTXfrom']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Formatter\GelfMessageFormatter::format
|
||||
*/
|
||||
public function testFormatWithContextContainingException()
|
||||
{
|
||||
$formatter = new GelfMessageFormatter();
|
||||
$record = array(
|
||||
'level' => Logger::ERROR,
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => 'meh',
|
||||
'context' => array('from' => 'logger', 'exception' => array(
|
||||
'class' => '\Exception',
|
||||
'file' => '/some/file/in/dir.php:56',
|
||||
'trace' => array('/some/file/1.php:23', '/some/file/2.php:3'),
|
||||
)),
|
||||
'datetime' => new \DateTime("@0"),
|
||||
'extra' => array(),
|
||||
'message' => 'log',
|
||||
);
|
||||
|
||||
$message = $formatter->format($record);
|
||||
|
||||
$this->assertInstanceOf('Gelf\Message', $message);
|
||||
|
||||
$this->assertEquals("/some/file/in/dir.php", $message->getFile());
|
||||
$this->assertEquals("56", $message->getLine());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Formatter\GelfMessageFormatter::format
|
||||
*/
|
||||
public function testFormatWithExtra()
|
||||
{
|
||||
$formatter = new GelfMessageFormatter();
|
||||
$record = array(
|
||||
'level' => Logger::ERROR,
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => 'meh',
|
||||
'context' => array('from' => 'logger'),
|
||||
'datetime' => new \DateTime("@0"),
|
||||
'extra' => array('key' => 'pair'),
|
||||
'message' => 'log',
|
||||
);
|
||||
|
||||
$message = $formatter->format($record);
|
||||
|
||||
$this->assertInstanceOf('Gelf\Message', $message);
|
||||
|
||||
$message_array = $message->toArray();
|
||||
|
||||
$this->assertArrayHasKey('_key', $message_array);
|
||||
$this->assertEquals('pair', $message_array['_key']);
|
||||
|
||||
// Test with extraPrefix
|
||||
$formatter = new GelfMessageFormatter(null, 'EXT');
|
||||
$message = $formatter->format($record);
|
||||
|
||||
$this->assertInstanceOf('Gelf\Message', $message);
|
||||
|
||||
$message_array = $message->toArray();
|
||||
|
||||
$this->assertArrayHasKey('_EXTkey', $message_array);
|
||||
$this->assertEquals('pair', $message_array['_EXTkey']);
|
||||
}
|
||||
|
||||
public function testFormatWithLargeData()
|
||||
{
|
||||
$formatter = new GelfMessageFormatter();
|
||||
$record = array(
|
||||
'level' => Logger::ERROR,
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => 'meh',
|
||||
'context' => array('exception' => str_repeat(' ', 32767)),
|
||||
'datetime' => new \DateTime("@0"),
|
||||
'extra' => array('key' => str_repeat(' ', 32767)),
|
||||
'message' => 'log'
|
||||
);
|
||||
$message = $formatter->format($record);
|
||||
$messageArray = $message->toArray();
|
||||
|
||||
// 200 for padding + metadata
|
||||
$length = 200;
|
||||
|
||||
foreach ($messageArray as $key => $value) {
|
||||
if (!in_array($key, array('level', 'timestamp'))) {
|
||||
$length += strlen($value);
|
||||
}
|
||||
}
|
||||
|
||||
$this->assertLessThanOrEqual(65792, $length, 'The message length is no longer than the maximum allowed length');
|
||||
}
|
||||
|
||||
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'
|
||||
);
|
||||
$message = $formatter->format($record);
|
||||
$messageArray = $message->toArray();
|
||||
|
||||
// 200 for padding + metadata
|
||||
$length = 200;
|
||||
|
||||
foreach ($messageArray as $key => $value) {
|
||||
if (!in_array($key, array('level', 'timestamp'))) {
|
||||
$length += strlen($value);
|
||||
}
|
||||
}
|
||||
|
||||
$this->assertGreaterThanOrEqual(131289, $length, 'The message should not be truncated');
|
||||
}
|
||||
|
||||
private function isLegacy()
|
||||
{
|
||||
return interface_exists('\Gelf\IMessagePublisher');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Formatter;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Monolog\TestCase;
|
||||
|
||||
class JsonFormatterTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers Monolog\Formatter\JsonFormatter::__construct
|
||||
* @covers Monolog\Formatter\JsonFormatter::getBatchMode
|
||||
* @covers Monolog\Formatter\JsonFormatter::isAppendingNewlines
|
||||
*/
|
||||
public function testConstruct()
|
||||
{
|
||||
$formatter = new JsonFormatter();
|
||||
$this->assertEquals(JsonFormatter::BATCH_MODE_JSON, $formatter->getBatchMode());
|
||||
$this->assertEquals(true, $formatter->isAppendingNewlines());
|
||||
$formatter = new JsonFormatter(JsonFormatter::BATCH_MODE_NEWLINES, false);
|
||||
$this->assertEquals(JsonFormatter::BATCH_MODE_NEWLINES, $formatter->getBatchMode());
|
||||
$this->assertEquals(false, $formatter->isAppendingNewlines());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Formatter\JsonFormatter::format
|
||||
*/
|
||||
public function testFormat()
|
||||
{
|
||||
$formatter = new JsonFormatter();
|
||||
$record = $this->getRecord();
|
||||
$this->assertEquals(json_encode($record)."\n", $formatter->format($record));
|
||||
|
||||
$formatter = new JsonFormatter(JsonFormatter::BATCH_MODE_JSON, false);
|
||||
$record = $this->getRecord();
|
||||
$this->assertEquals(json_encode($record), $formatter->format($record));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Formatter\JsonFormatter::formatBatch
|
||||
* @covers Monolog\Formatter\JsonFormatter::formatBatchJson
|
||||
*/
|
||||
public function testFormatBatch()
|
||||
{
|
||||
$formatter = new JsonFormatter();
|
||||
$records = array(
|
||||
$this->getRecord(Logger::WARNING),
|
||||
$this->getRecord(Logger::DEBUG),
|
||||
);
|
||||
$this->assertEquals(json_encode($records), $formatter->formatBatch($records));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Formatter\JsonFormatter::formatBatch
|
||||
* @covers Monolog\Formatter\JsonFormatter::formatBatchNewlines
|
||||
*/
|
||||
public function testFormatBatchNewlines()
|
||||
{
|
||||
$formatter = new JsonFormatter(JsonFormatter::BATCH_MODE_NEWLINES);
|
||||
$records = $expected = array(
|
||||
$this->getRecord(Logger::WARNING),
|
||||
$this->getRecord(Logger::DEBUG),
|
||||
);
|
||||
array_walk($expected, function (&$value, $key) {
|
||||
$value = json_encode($value);
|
||||
});
|
||||
$this->assertEquals(implode("\n", $expected), $formatter->formatBatch($records));
|
||||
}
|
||||
|
||||
public function testDefFormatWithException()
|
||||
{
|
||||
$formatter = new JsonFormatter();
|
||||
$exception = new \RuntimeException('Foo');
|
||||
$formattedException = $this->formatException($exception);
|
||||
|
||||
$message = $this->formatRecordWithExceptionInContext($formatter, $exception);
|
||||
|
||||
$this->assertContextContainsFormattedException($formattedException, $message);
|
||||
}
|
||||
|
||||
public function testDefFormatWithPreviousException()
|
||||
{
|
||||
$formatter = new JsonFormatter();
|
||||
$exception = new \RuntimeException('Foo', 0, new \LogicException('Wut?'));
|
||||
$formattedPrevException = $this->formatException($exception->getPrevious());
|
||||
$formattedException = $this->formatException($exception, $formattedPrevException);
|
||||
|
||||
$message = $this->formatRecordWithExceptionInContext($formatter, $exception);
|
||||
|
||||
$this->assertContextContainsFormattedException($formattedException, $message);
|
||||
}
|
||||
|
||||
public function testDefFormatWithThrowable()
|
||||
{
|
||||
if (!class_exists('Error') || !is_subclass_of('Error', 'Throwable')) {
|
||||
$this->markTestSkipped('Requires PHP >=7');
|
||||
}
|
||||
|
||||
$formatter = new JsonFormatter();
|
||||
$throwable = new \Error('Foo');
|
||||
$formattedThrowable = $this->formatException($throwable);
|
||||
|
||||
$message = $this->formatRecordWithExceptionInContext($formatter, $throwable);
|
||||
|
||||
$this->assertContextContainsFormattedException($formattedThrowable, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $expected
|
||||
* @param string $actual
|
||||
*
|
||||
* @internal param string $exception
|
||||
*/
|
||||
private function assertContextContainsFormattedException($expected, $actual)
|
||||
{
|
||||
$this->assertEquals(
|
||||
'{"level_name":"CRITICAL","channel":"core","context":{"exception":'.$expected.'},"datetime":null,"extra":[],"message":"foobar"}'."\n",
|
||||
$actual
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param JsonFormatter $formatter
|
||||
* @param \Exception|\Throwable $exception
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function formatRecordWithExceptionInContext(JsonFormatter $formatter, $exception)
|
||||
{
|
||||
$message = $formatter->format(array(
|
||||
'level_name' => 'CRITICAL',
|
||||
'channel' => 'core',
|
||||
'context' => array('exception' => $exception),
|
||||
'datetime' => null,
|
||||
'extra' => array(),
|
||||
'message' => 'foobar',
|
||||
));
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Exception|\Throwable $exception
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function formatExceptionFilePathWithLine($exception)
|
||||
{
|
||||
$options = 0;
|
||||
if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
|
||||
$options = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE;
|
||||
}
|
||||
$path = substr(json_encode($exception->getFile(), $options), 1, -1);
|
||||
return $path . ':' . $exception->getLine();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Exception|\Throwable $exception
|
||||
*
|
||||
* @param null|string $previous
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function formatException($exception, $previous = null)
|
||||
{
|
||||
$formattedException =
|
||||
'{"class":"' . get_class($exception) .
|
||||
'","message":"' . $exception->getMessage() .
|
||||
'","code":' . $exception->getCode() .
|
||||
',"file":"' . $this->formatExceptionFilePathWithLine($exception) .
|
||||
($previous ? '","previous":' . $previous : '"') .
|
||||
'}';
|
||||
return $formattedException;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Formatter;
|
||||
|
||||
/**
|
||||
* @covers Monolog\Formatter\LineFormatter
|
||||
*/
|
||||
class LineFormatterTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testDefFormatWithString()
|
||||
{
|
||||
$formatter = new LineFormatter(null, 'Y-m-d');
|
||||
$message = $formatter->format(array(
|
||||
'level_name' => 'WARNING',
|
||||
'channel' => 'log',
|
||||
'context' => array(),
|
||||
'message' => 'foo',
|
||||
'datetime' => new \DateTime,
|
||||
'extra' => array(),
|
||||
));
|
||||
$this->assertEquals('['.date('Y-m-d').'] log.WARNING: foo [] []'."\n", $message);
|
||||
}
|
||||
|
||||
public function testDefFormatWithArrayContext()
|
||||
{
|
||||
$formatter = new LineFormatter(null, 'Y-m-d');
|
||||
$message = $formatter->format(array(
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => 'meh',
|
||||
'message' => 'foo',
|
||||
'datetime' => new \DateTime,
|
||||
'extra' => array(),
|
||||
'context' => array(
|
||||
'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(array(
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => 'meh',
|
||||
'context' => array(),
|
||||
'datetime' => new \DateTime,
|
||||
'extra' => array('ip' => '127.0.0.1'),
|
||||
'message' => 'log',
|
||||
));
|
||||
$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(array(
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => 'meh',
|
||||
'context' => array(),
|
||||
'datetime' => new \DateTime,
|
||||
'extra' => array('ip' => '127.0.0.1', 'file' => 'test'),
|
||||
'message' => 'log',
|
||||
));
|
||||
$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(array(
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => 'meh',
|
||||
'context' => array(),
|
||||
'datetime' => new \DateTime,
|
||||
'extra' => array(),
|
||||
'message' => 'log',
|
||||
));
|
||||
$this->assertEquals('['.date('Y-m-d').'] meh.ERROR: log '."\n", $message);
|
||||
}
|
||||
|
||||
public function testContextAndExtraReplacement()
|
||||
{
|
||||
$formatter = new LineFormatter('%context.foo% => %extra.foo%');
|
||||
$message = $formatter->format(array(
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => 'meh',
|
||||
'context' => array('foo' => 'bar'),
|
||||
'datetime' => new \DateTime,
|
||||
'extra' => array('foo' => 'xbar'),
|
||||
'message' => 'log',
|
||||
));
|
||||
$this->assertEquals('bar => xbar', $message);
|
||||
}
|
||||
|
||||
public function testDefFormatWithObject()
|
||||
{
|
||||
$formatter = new LineFormatter(null, 'Y-m-d');
|
||||
$message = $formatter->format(array(
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => 'meh',
|
||||
'context' => array(),
|
||||
'datetime' => new \DateTime,
|
||||
'extra' => array('foo' => new TestFoo, 'bar' => new TestBar, 'baz' => array(), 'res' => fopen('php://memory', 'rb')),
|
||||
'message' => 'foobar',
|
||||
));
|
||||
|
||||
$this->assertEquals('['.date('Y-m-d').'] meh.ERROR: foobar [] {"foo":"[object] (Monolog\\\\Formatter\\\\TestFoo: {\\"foo\\":\\"foo\\"})","bar":"[object] (Monolog\\\\Formatter\\\\TestBar: bar)","baz":[],"res":"[resource] (stream)"}'."\n", $message);
|
||||
}
|
||||
|
||||
public function testDefFormatWithException()
|
||||
{
|
||||
$formatter = new LineFormatter(null, 'Y-m-d');
|
||||
$message = $formatter->format(array(
|
||||
'level_name' => 'CRITICAL',
|
||||
'channel' => 'core',
|
||||
'context' => array('exception' => new \RuntimeException('Foo')),
|
||||
'datetime' => new \DateTime,
|
||||
'extra' => array(),
|
||||
'message' => 'foobar',
|
||||
));
|
||||
|
||||
$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);
|
||||
}
|
||||
|
||||
public function testDefFormatWithPreviousException()
|
||||
{
|
||||
$formatter = new LineFormatter(null, 'Y-m-d');
|
||||
$previous = new \LogicException('Wut?');
|
||||
$message = $formatter->format(array(
|
||||
'level_name' => 'CRITICAL',
|
||||
'channel' => 'core',
|
||||
'context' => array('exception' => new \RuntimeException('Foo', 0, $previous)),
|
||||
'datetime' => new \DateTime,
|
||||
'extra' => array(),
|
||||
'message' => 'foobar',
|
||||
));
|
||||
|
||||
$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).', LogicException(code: 0): Wut? at '.substr($path, 1, -1).':'.(__LINE__ - 12).')"} []'."\n", $message);
|
||||
}
|
||||
|
||||
public function testBatchFormat()
|
||||
{
|
||||
$formatter = new LineFormatter(null, 'Y-m-d');
|
||||
$message = $formatter->formatBatch(array(
|
||||
array(
|
||||
'level_name' => 'CRITICAL',
|
||||
'channel' => 'test',
|
||||
'message' => 'bar',
|
||||
'context' => array(),
|
||||
'datetime' => new \DateTime,
|
||||
'extra' => array(),
|
||||
),
|
||||
array(
|
||||
'level_name' => 'WARNING',
|
||||
'channel' => 'log',
|
||||
'message' => 'foo',
|
||||
'context' => array(),
|
||||
'datetime' => new \DateTime,
|
||||
'extra' => array(),
|
||||
),
|
||||
));
|
||||
$this->assertEquals('['.date('Y-m-d').'] test.CRITICAL: bar [] []'."\n".'['.date('Y-m-d').'] log.WARNING: foo [] []'."\n", $message);
|
||||
}
|
||||
|
||||
public function testFormatShouldStripInlineLineBreaks()
|
||||
{
|
||||
$formatter = new LineFormatter(null, 'Y-m-d');
|
||||
$message = $formatter->format(
|
||||
array(
|
||||
'message' => "foo\nbar",
|
||||
'context' => array(),
|
||||
'extra' => array(),
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertRegExp('/foo bar/', $message);
|
||||
}
|
||||
|
||||
public function testFormatShouldNotStripInlineLineBreaksWhenFlagIsSet()
|
||||
{
|
||||
$formatter = new LineFormatter(null, 'Y-m-d', true);
|
||||
$message = $formatter->format(
|
||||
array(
|
||||
'message' => "foo\nbar",
|
||||
'context' => array(),
|
||||
'extra' => array(),
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertRegExp('/foo\nbar/', $message);
|
||||
}
|
||||
}
|
||||
|
||||
class TestFoo
|
||||
{
|
||||
public $foo = 'foo';
|
||||
}
|
||||
|
||||
class TestBar
|
||||
{
|
||||
public function __toString()
|
||||
{
|
||||
return 'bar';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Formatter;
|
||||
|
||||
use Monolog\TestCase;
|
||||
|
||||
class LogglyFormatterTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers Monolog\Formatter\LogglyFormatter::__construct
|
||||
*/
|
||||
public function testConstruct()
|
||||
{
|
||||
$formatter = new LogglyFormatter();
|
||||
$this->assertEquals(LogglyFormatter::BATCH_MODE_NEWLINES, $formatter->getBatchMode());
|
||||
$formatter = new LogglyFormatter(LogglyFormatter::BATCH_MODE_JSON);
|
||||
$this->assertEquals(LogglyFormatter::BATCH_MODE_JSON, $formatter->getBatchMode());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Formatter\LogglyFormatter::format
|
||||
*/
|
||||
public function testFormat()
|
||||
{
|
||||
$formatter = new LogglyFormatter();
|
||||
$record = $this->getRecord();
|
||||
$formatted_decoded = json_decode($formatter->format($record), true);
|
||||
$this->assertArrayHasKey("timestamp", $formatted_decoded);
|
||||
$this->assertEquals(new \DateTime($formatted_decoded["timestamp"]), $record["datetime"]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,333 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Formatter;
|
||||
|
||||
use Monolog\Logger;
|
||||
|
||||
class LogstashFormatterTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function tearDown()
|
||||
{
|
||||
\PHPUnit_Framework_Error_Warning::$enabled = true;
|
||||
|
||||
return parent::tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Formatter\LogstashFormatter::format
|
||||
*/
|
||||
public function testDefaultFormatter()
|
||||
{
|
||||
$formatter = new LogstashFormatter('test', 'hostname');
|
||||
$record = array(
|
||||
'level' => Logger::ERROR,
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => 'meh',
|
||||
'context' => array(),
|
||||
'datetime' => new \DateTime("@0"),
|
||||
'extra' => array(),
|
||||
'message' => 'log',
|
||||
);
|
||||
|
||||
$message = json_decode($formatter->format($record), true);
|
||||
|
||||
$this->assertEquals("1970-01-01T00:00:00.000000+00:00", $message['@timestamp']);
|
||||
$this->assertEquals('log', $message['@message']);
|
||||
$this->assertEquals('meh', $message['@fields']['channel']);
|
||||
$this->assertContains('meh', $message['@tags']);
|
||||
$this->assertEquals(Logger::ERROR, $message['@fields']['level']);
|
||||
$this->assertEquals('test', $message['@type']);
|
||||
$this->assertEquals('hostname', $message['@source']);
|
||||
|
||||
$formatter = new LogstashFormatter('mysystem');
|
||||
|
||||
$message = json_decode($formatter->format($record), true);
|
||||
|
||||
$this->assertEquals('mysystem', $message['@type']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Formatter\LogstashFormatter::format
|
||||
*/
|
||||
public function testFormatWithFileAndLine()
|
||||
{
|
||||
$formatter = new LogstashFormatter('test');
|
||||
$record = array(
|
||||
'level' => Logger::ERROR,
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => 'meh',
|
||||
'context' => array('from' => 'logger'),
|
||||
'datetime' => new \DateTime("@0"),
|
||||
'extra' => array('file' => 'test', 'line' => 14),
|
||||
'message' => 'log',
|
||||
);
|
||||
|
||||
$message = json_decode($formatter->format($record), true);
|
||||
|
||||
$this->assertEquals('test', $message['@fields']['file']);
|
||||
$this->assertEquals(14, $message['@fields']['line']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Formatter\LogstashFormatter::format
|
||||
*/
|
||||
public function testFormatWithContext()
|
||||
{
|
||||
$formatter = new LogstashFormatter('test');
|
||||
$record = array(
|
||||
'level' => Logger::ERROR,
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => 'meh',
|
||||
'context' => array('from' => 'logger'),
|
||||
'datetime' => new \DateTime("@0"),
|
||||
'extra' => array('key' => 'pair'),
|
||||
'message' => 'log',
|
||||
);
|
||||
|
||||
$message = json_decode($formatter->format($record), true);
|
||||
|
||||
$message_array = $message['@fields'];
|
||||
|
||||
$this->assertArrayHasKey('ctxt_from', $message_array);
|
||||
$this->assertEquals('logger', $message_array['ctxt_from']);
|
||||
|
||||
// Test with extraPrefix
|
||||
$formatter = new LogstashFormatter('test', null, null, 'CTX');
|
||||
$message = json_decode($formatter->format($record), true);
|
||||
|
||||
$message_array = $message['@fields'];
|
||||
|
||||
$this->assertArrayHasKey('CTXfrom', $message_array);
|
||||
$this->assertEquals('logger', $message_array['CTXfrom']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Formatter\LogstashFormatter::format
|
||||
*/
|
||||
public function testFormatWithExtra()
|
||||
{
|
||||
$formatter = new LogstashFormatter('test');
|
||||
$record = array(
|
||||
'level' => Logger::ERROR,
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => 'meh',
|
||||
'context' => array('from' => 'logger'),
|
||||
'datetime' => new \DateTime("@0"),
|
||||
'extra' => array('key' => 'pair'),
|
||||
'message' => 'log',
|
||||
);
|
||||
|
||||
$message = json_decode($formatter->format($record), true);
|
||||
|
||||
$message_array = $message['@fields'];
|
||||
|
||||
$this->assertArrayHasKey('key', $message_array);
|
||||
$this->assertEquals('pair', $message_array['key']);
|
||||
|
||||
// Test with extraPrefix
|
||||
$formatter = new LogstashFormatter('test', null, 'EXT');
|
||||
$message = json_decode($formatter->format($record), true);
|
||||
|
||||
$message_array = $message['@fields'];
|
||||
|
||||
$this->assertArrayHasKey('EXTkey', $message_array);
|
||||
$this->assertEquals('pair', $message_array['EXTkey']);
|
||||
}
|
||||
|
||||
public function testFormatWithApplicationName()
|
||||
{
|
||||
$formatter = new LogstashFormatter('app', 'test');
|
||||
$record = array(
|
||||
'level' => Logger::ERROR,
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => 'meh',
|
||||
'context' => array('from' => 'logger'),
|
||||
'datetime' => new \DateTime("@0"),
|
||||
'extra' => array('key' => 'pair'),
|
||||
'message' => 'log',
|
||||
);
|
||||
|
||||
$message = json_decode($formatter->format($record), true);
|
||||
|
||||
$this->assertArrayHasKey('@type', $message);
|
||||
$this->assertEquals('app', $message['@type']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Formatter\LogstashFormatter::format
|
||||
*/
|
||||
public function testDefaultFormatterV1()
|
||||
{
|
||||
$formatter = new LogstashFormatter('test', 'hostname', null, 'ctxt_', LogstashFormatter::V1);
|
||||
$record = array(
|
||||
'level' => Logger::ERROR,
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => 'meh',
|
||||
'context' => array(),
|
||||
'datetime' => new \DateTime("@0"),
|
||||
'extra' => array(),
|
||||
'message' => 'log',
|
||||
);
|
||||
|
||||
$message = json_decode($formatter->format($record), true);
|
||||
|
||||
$this->assertEquals("1970-01-01T00:00:00.000000+00:00", $message['@timestamp']);
|
||||
$this->assertEquals("1", $message['@version']);
|
||||
$this->assertEquals('log', $message['message']);
|
||||
$this->assertEquals('meh', $message['channel']);
|
||||
$this->assertEquals('ERROR', $message['level']);
|
||||
$this->assertEquals('test', $message['type']);
|
||||
$this->assertEquals('hostname', $message['host']);
|
||||
|
||||
$formatter = new LogstashFormatter('mysystem', null, null, 'ctxt_', LogstashFormatter::V1);
|
||||
|
||||
$message = json_decode($formatter->format($record), true);
|
||||
|
||||
$this->assertEquals('mysystem', $message['type']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Formatter\LogstashFormatter::format
|
||||
*/
|
||||
public function testFormatWithFileAndLineV1()
|
||||
{
|
||||
$formatter = new LogstashFormatter('test', null, null, 'ctxt_', LogstashFormatter::V1);
|
||||
$record = array(
|
||||
'level' => Logger::ERROR,
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => 'meh',
|
||||
'context' => array('from' => 'logger'),
|
||||
'datetime' => new \DateTime("@0"),
|
||||
'extra' => array('file' => 'test', 'line' => 14),
|
||||
'message' => 'log',
|
||||
);
|
||||
|
||||
$message = json_decode($formatter->format($record), true);
|
||||
|
||||
$this->assertEquals('test', $message['file']);
|
||||
$this->assertEquals(14, $message['line']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Formatter\LogstashFormatter::format
|
||||
*/
|
||||
public function testFormatWithContextV1()
|
||||
{
|
||||
$formatter = new LogstashFormatter('test', null, null, 'ctxt_', LogstashFormatter::V1);
|
||||
$record = array(
|
||||
'level' => Logger::ERROR,
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => 'meh',
|
||||
'context' => array('from' => 'logger'),
|
||||
'datetime' => new \DateTime("@0"),
|
||||
'extra' => array('key' => 'pair'),
|
||||
'message' => 'log',
|
||||
);
|
||||
|
||||
$message = json_decode($formatter->format($record), true);
|
||||
|
||||
$this->assertArrayHasKey('ctxt_from', $message);
|
||||
$this->assertEquals('logger', $message['ctxt_from']);
|
||||
|
||||
// Test with extraPrefix
|
||||
$formatter = new LogstashFormatter('test', null, null, 'CTX', LogstashFormatter::V1);
|
||||
$message = json_decode($formatter->format($record), true);
|
||||
|
||||
$this->assertArrayHasKey('CTXfrom', $message);
|
||||
$this->assertEquals('logger', $message['CTXfrom']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Formatter\LogstashFormatter::format
|
||||
*/
|
||||
public function testFormatWithExtraV1()
|
||||
{
|
||||
$formatter = new LogstashFormatter('test', null, null, 'ctxt_', LogstashFormatter::V1);
|
||||
$record = array(
|
||||
'level' => Logger::ERROR,
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => 'meh',
|
||||
'context' => array('from' => 'logger'),
|
||||
'datetime' => new \DateTime("@0"),
|
||||
'extra' => array('key' => 'pair'),
|
||||
'message' => 'log',
|
||||
);
|
||||
|
||||
$message = json_decode($formatter->format($record), true);
|
||||
|
||||
$this->assertArrayHasKey('key', $message);
|
||||
$this->assertEquals('pair', $message['key']);
|
||||
|
||||
// Test with extraPrefix
|
||||
$formatter = new LogstashFormatter('test', null, 'EXT', 'ctxt_', LogstashFormatter::V1);
|
||||
$message = json_decode($formatter->format($record), true);
|
||||
|
||||
$this->assertArrayHasKey('EXTkey', $message);
|
||||
$this->assertEquals('pair', $message['EXTkey']);
|
||||
}
|
||||
|
||||
public function testFormatWithApplicationNameV1()
|
||||
{
|
||||
$formatter = new LogstashFormatter('app', 'test', null, 'ctxt_', LogstashFormatter::V1);
|
||||
$record = array(
|
||||
'level' => Logger::ERROR,
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => 'meh',
|
||||
'context' => array('from' => 'logger'),
|
||||
'datetime' => new \DateTime("@0"),
|
||||
'extra' => array('key' => 'pair'),
|
||||
'message' => 'log',
|
||||
);
|
||||
|
||||
$message = json_decode($formatter->format($record), true);
|
||||
|
||||
$this->assertArrayHasKey('type', $message);
|
||||
$this->assertEquals('app', $message['type']);
|
||||
}
|
||||
|
||||
public function testFormatWithLatin9Data()
|
||||
{
|
||||
if (version_compare(PHP_VERSION, '5.5.0', '<')) {
|
||||
// Ignore the warning that will be emitted by PHP <5.5.0
|
||||
\PHPUnit_Framework_Error_Warning::$enabled = false;
|
||||
}
|
||||
$formatter = new LogstashFormatter('test', 'hostname');
|
||||
$record = array(
|
||||
'level' => Logger::ERROR,
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => '¯\_(ツ)_/¯',
|
||||
'context' => array(),
|
||||
'datetime' => new \DateTime("@0"),
|
||||
'extra' => array(
|
||||
'user_agent' => "\xD6WN; FBCR/OrangeEspa\xF1a; Vers\xE3o/4.0; F\xE4rist",
|
||||
),
|
||||
'message' => 'log',
|
||||
);
|
||||
|
||||
$message = json_decode($formatter->format($record), true);
|
||||
|
||||
$this->assertEquals("1970-01-01T00:00:00.000000+00:00", $message['@timestamp']);
|
||||
$this->assertEquals('log', $message['@message']);
|
||||
$this->assertEquals('¯\_(ツ)_/¯', $message['@fields']['channel']);
|
||||
$this->assertContains('¯\_(ツ)_/¯', $message['@tags']);
|
||||
$this->assertEquals(Logger::ERROR, $message['@fields']['level']);
|
||||
$this->assertEquals('test', $message['@type']);
|
||||
$this->assertEquals('hostname', $message['@source']);
|
||||
if (version_compare(PHP_VERSION, '5.5.0', '>=')) {
|
||||
$this->assertEquals('ÖWN; FBCR/OrangeEspaña; Versão/4.0; Färist', $message['@fields']['user_agent']);
|
||||
} else {
|
||||
// PHP <5.5 does not return false for an element encoding failure,
|
||||
// instead it emits a warning (possibly) and nulls the value.
|
||||
$this->assertEquals(null, $message['@fields']['user_agent']);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,262 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Formatter;
|
||||
|
||||
use Monolog\Logger;
|
||||
|
||||
/**
|
||||
* @author Florian Plattner <me@florianplattner.de>
|
||||
*/
|
||||
class MongoDBFormatterTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
if (!class_exists('MongoDate')) {
|
||||
$this->markTestSkipped('mongo extension not installed');
|
||||
}
|
||||
}
|
||||
|
||||
public function constructArgumentProvider()
|
||||
{
|
||||
return array(
|
||||
array(1, true, 1, true),
|
||||
array(0, false, 0, false),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $traceDepth
|
||||
* @param $traceAsString
|
||||
* @param $expectedTraceDepth
|
||||
* @param $expectedTraceAsString
|
||||
*
|
||||
* @dataProvider constructArgumentProvider
|
||||
*/
|
||||
public function testConstruct($traceDepth, $traceAsString, $expectedTraceDepth, $expectedTraceAsString)
|
||||
{
|
||||
$formatter = new MongoDBFormatter($traceDepth, $traceAsString);
|
||||
|
||||
$reflTrace = new \ReflectionProperty($formatter, 'exceptionTraceAsString');
|
||||
$reflTrace->setAccessible(true);
|
||||
$this->assertEquals($expectedTraceAsString, $reflTrace->getValue($formatter));
|
||||
|
||||
$reflDepth = new\ReflectionProperty($formatter, 'maxNestingLevel');
|
||||
$reflDepth->setAccessible(true);
|
||||
$this->assertEquals($expectedTraceDepth, $reflDepth->getValue($formatter));
|
||||
}
|
||||
|
||||
public function testSimpleFormat()
|
||||
{
|
||||
$record = array(
|
||||
'message' => 'some log message',
|
||||
'context' => array(),
|
||||
'level' => Logger::WARNING,
|
||||
'level_name' => Logger::getLevelName(Logger::WARNING),
|
||||
'channel' => 'test',
|
||||
'datetime' => new \DateTime('2014-02-01 00:00:00'),
|
||||
'extra' => array(),
|
||||
);
|
||||
|
||||
$formatter = new MongoDBFormatter();
|
||||
$formattedRecord = $formatter->format($record);
|
||||
|
||||
$this->assertCount(7, $formattedRecord);
|
||||
$this->assertEquals('some log message', $formattedRecord['message']);
|
||||
$this->assertEquals(array(), $formattedRecord['context']);
|
||||
$this->assertEquals(Logger::WARNING, $formattedRecord['level']);
|
||||
$this->assertEquals(Logger::getLevelName(Logger::WARNING), $formattedRecord['level_name']);
|
||||
$this->assertEquals('test', $formattedRecord['channel']);
|
||||
$this->assertInstanceOf('\MongoDate', $formattedRecord['datetime']);
|
||||
$this->assertEquals('0.00000000 1391212800', $formattedRecord['datetime']->__toString());
|
||||
$this->assertEquals(array(), $formattedRecord['extra']);
|
||||
}
|
||||
|
||||
public function testRecursiveFormat()
|
||||
{
|
||||
$someObject = new \stdClass();
|
||||
$someObject->foo = 'something';
|
||||
$someObject->bar = 'stuff';
|
||||
|
||||
$record = array(
|
||||
'message' => 'some log message',
|
||||
'context' => array(
|
||||
'stuff' => new \DateTime('2014-02-01 02:31:33'),
|
||||
'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 \DateTime('2014-02-01 00:00:00'),
|
||||
'extra' => array(),
|
||||
);
|
||||
|
||||
$formatter = new MongoDBFormatter();
|
||||
$formattedRecord = $formatter->format($record);
|
||||
|
||||
$this->assertCount(5, $formattedRecord['context']);
|
||||
$this->assertInstanceOf('\MongoDate', $formattedRecord['context']['stuff']);
|
||||
$this->assertEquals('0.00000000 1391221893', $formattedRecord['context']['stuff']->__toString());
|
||||
$this->assertEquals(
|
||||
array(
|
||||
'foo' => 'something',
|
||||
'bar' => 'stuff',
|
||||
'class' => 'stdClass',
|
||||
),
|
||||
$formattedRecord['context']['some_object']
|
||||
);
|
||||
$this->assertEquals('some string', $formattedRecord['context']['context_string']);
|
||||
$this->assertEquals(123456, $formattedRecord['context']['context_int']);
|
||||
|
||||
$this->assertCount(5, $formattedRecord['context']['except']);
|
||||
$this->assertEquals('exception message', $formattedRecord['context']['except']['message']);
|
||||
$this->assertEquals(987, $formattedRecord['context']['except']['code']);
|
||||
$this->assertInternalType('string', $formattedRecord['context']['except']['file']);
|
||||
$this->assertInternalType('integer', $formattedRecord['context']['except']['code']);
|
||||
$this->assertInternalType('string', $formattedRecord['context']['except']['trace']);
|
||||
$this->assertEquals('Exception', $formattedRecord['context']['except']['class']);
|
||||
}
|
||||
|
||||
public function testFormatDepthArray()
|
||||
{
|
||||
$record = array(
|
||||
'message' => 'some log message',
|
||||
'context' => array(
|
||||
'nest2' => array(
|
||||
'property' => 'anything',
|
||||
'nest3' => array(
|
||||
'nest4' => 'value',
|
||||
'property' => 'nothing',
|
||||
),
|
||||
),
|
||||
),
|
||||
'level' => Logger::WARNING,
|
||||
'level_name' => Logger::getLevelName(Logger::WARNING),
|
||||
'channel' => 'test',
|
||||
'datetime' => new \DateTime('2014-02-01 00:00:00'),
|
||||
'extra' => array(),
|
||||
);
|
||||
|
||||
$formatter = new MongoDBFormatter(2);
|
||||
$formattedResult = $formatter->format($record);
|
||||
|
||||
$this->assertEquals(
|
||||
array(
|
||||
'nest2' => array(
|
||||
'property' => 'anything',
|
||||
'nest3' => '[...]',
|
||||
),
|
||||
),
|
||||
$formattedResult['context']
|
||||
);
|
||||
}
|
||||
|
||||
public function testFormatDepthArrayInfiniteNesting()
|
||||
{
|
||||
$record = array(
|
||||
'message' => 'some log message',
|
||||
'context' => array(
|
||||
'nest2' => array(
|
||||
'property' => 'something',
|
||||
'nest3' => array(
|
||||
'property' => 'anything',
|
||||
'nest4' => array(
|
||||
'property' => 'nothing',
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
'level' => Logger::WARNING,
|
||||
'level_name' => Logger::getLevelName(Logger::WARNING),
|
||||
'channel' => 'test',
|
||||
'datetime' => new \DateTime('2014-02-01 00:00:00'),
|
||||
'extra' => array(),
|
||||
);
|
||||
|
||||
$formatter = new MongoDBFormatter(0);
|
||||
$formattedResult = $formatter->format($record);
|
||||
|
||||
$this->assertEquals(
|
||||
array(
|
||||
'nest2' => array(
|
||||
'property' => 'something',
|
||||
'nest3' => array(
|
||||
'property' => 'anything',
|
||||
'nest4' => array(
|
||||
'property' => 'nothing',
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
$formattedResult['context']
|
||||
);
|
||||
}
|
||||
|
||||
public function testFormatDepthObjects()
|
||||
{
|
||||
$someObject = new \stdClass();
|
||||
$someObject->property = 'anything';
|
||||
$someObject->nest3 = new \stdClass();
|
||||
$someObject->nest3->property = 'nothing';
|
||||
$someObject->nest3->nest4 = 'invisible';
|
||||
|
||||
$record = array(
|
||||
'message' => 'some log message',
|
||||
'context' => array(
|
||||
'nest2' => $someObject,
|
||||
),
|
||||
'level' => Logger::WARNING,
|
||||
'level_name' => Logger::getLevelName(Logger::WARNING),
|
||||
'channel' => 'test',
|
||||
'datetime' => new \DateTime('2014-02-01 00:00:00'),
|
||||
'extra' => array(),
|
||||
);
|
||||
|
||||
$formatter = new MongoDBFormatter(2, true);
|
||||
$formattedResult = $formatter->format($record);
|
||||
|
||||
$this->assertEquals(
|
||||
array(
|
||||
'nest2' => array(
|
||||
'property' => 'anything',
|
||||
'nest3' => '[...]',
|
||||
'class' => 'stdClass',
|
||||
),
|
||||
),
|
||||
$formattedResult['context']
|
||||
);
|
||||
}
|
||||
|
||||
public function testFormatDepthException()
|
||||
{
|
||||
$record = array(
|
||||
'message' => 'some log message',
|
||||
'context' => array(
|
||||
'nest2' => new \Exception('exception message', 987),
|
||||
),
|
||||
'level' => Logger::WARNING,
|
||||
'level_name' => Logger::getLevelName(Logger::WARNING),
|
||||
'channel' => 'test',
|
||||
'datetime' => new \DateTime('2014-02-01 00:00:00'),
|
||||
'extra' => array(),
|
||||
);
|
||||
|
||||
$formatter = new MongoDBFormatter(2, false);
|
||||
$formattedRecord = $formatter->format($record);
|
||||
|
||||
$this->assertEquals('exception message', $formattedRecord['context']['nest2']['message']);
|
||||
$this->assertEquals(987, $formattedRecord['context']['nest2']['code']);
|
||||
$this->assertEquals('[...]', $formattedRecord['context']['nest2']['trace']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,423 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Formatter;
|
||||
|
||||
/**
|
||||
* @covers Monolog\Formatter\NormalizerFormatter
|
||||
*/
|
||||
class NormalizerFormatterTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function tearDown()
|
||||
{
|
||||
\PHPUnit_Framework_Error_Warning::$enabled = true;
|
||||
|
||||
return parent::tearDown();
|
||||
}
|
||||
|
||||
public function testFormat()
|
||||
{
|
||||
$formatter = new NormalizerFormatter('Y-m-d');
|
||||
$formatted = $formatter->format(array(
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => 'meh',
|
||||
'message' => 'foo',
|
||||
'datetime' => new \DateTime,
|
||||
'extra' => array('foo' => new TestFooNorm, 'bar' => new TestBarNorm, 'baz' => array(), 'res' => fopen('php://memory', 'rb')),
|
||||
'context' => array(
|
||||
'foo' => 'bar',
|
||||
'baz' => 'qux',
|
||||
'inf' => INF,
|
||||
'-inf' => -INF,
|
||||
'nan' => acos(4),
|
||||
),
|
||||
));
|
||||
|
||||
$this->assertEquals(array(
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => 'meh',
|
||||
'message' => 'foo',
|
||||
'datetime' => date('Y-m-d'),
|
||||
'extra' => array(
|
||||
'foo' => '[object] (Monolog\\Formatter\\TestFooNorm: {"foo":"foo"})',
|
||||
'bar' => '[object] (Monolog\\Formatter\\TestBarNorm: bar)',
|
||||
'baz' => array(),
|
||||
'res' => '[resource] (stream)',
|
||||
),
|
||||
'context' => array(
|
||||
'foo' => 'bar',
|
||||
'baz' => 'qux',
|
||||
'inf' => 'INF',
|
||||
'-inf' => '-INF',
|
||||
'nan' => 'NaN',
|
||||
),
|
||||
), $formatted);
|
||||
}
|
||||
|
||||
public function testFormatExceptions()
|
||||
{
|
||||
$formatter = new NormalizerFormatter('Y-m-d');
|
||||
$e = new \LogicException('bar');
|
||||
$e2 = new \RuntimeException('foo', 0, $e);
|
||||
$formatted = $formatter->format(array(
|
||||
'exception' => $e2,
|
||||
));
|
||||
|
||||
$this->assertGreaterThan(5, count($formatted['exception']['trace']));
|
||||
$this->assertTrue(isset($formatted['exception']['previous']));
|
||||
unset($formatted['exception']['trace'], $formatted['exception']['previous']);
|
||||
|
||||
$this->assertEquals(array(
|
||||
'exception' => array(
|
||||
'class' => get_class($e2),
|
||||
'message' => $e2->getMessage(),
|
||||
'code' => $e2->getCode(),
|
||||
'file' => $e2->getFile().':'.$e2->getLine(),
|
||||
),
|
||||
), $formatted);
|
||||
}
|
||||
|
||||
public function testFormatSoapFaultException()
|
||||
{
|
||||
if (!class_exists('SoapFault')) {
|
||||
$this->markTestSkipped('Requires the soap extension');
|
||||
}
|
||||
|
||||
$formatter = new NormalizerFormatter('Y-m-d');
|
||||
$e = new \SoapFault('foo', 'bar', 'hello', 'world');
|
||||
$formatted = $formatter->format(array(
|
||||
'exception' => $e,
|
||||
));
|
||||
|
||||
unset($formatted['exception']['trace']);
|
||||
|
||||
$this->assertEquals(array(
|
||||
'exception' => array(
|
||||
'class' => 'SoapFault',
|
||||
'message' => 'bar',
|
||||
'code' => 0,
|
||||
'file' => $e->getFile().':'.$e->getLine(),
|
||||
'faultcode' => 'foo',
|
||||
'faultactor' => 'hello',
|
||||
'detail' => 'world',
|
||||
),
|
||||
), $formatted);
|
||||
}
|
||||
|
||||
public function testFormatToStringExceptionHandle()
|
||||
{
|
||||
$formatter = new NormalizerFormatter('Y-m-d');
|
||||
$this->setExpectedException('RuntimeException', 'Could not convert to string');
|
||||
$formatter->format(array(
|
||||
'myObject' => new TestToStringError(),
|
||||
));
|
||||
}
|
||||
|
||||
public function testBatchFormat()
|
||||
{
|
||||
$formatter = new NormalizerFormatter('Y-m-d');
|
||||
$formatted = $formatter->formatBatch(array(
|
||||
array(
|
||||
'level_name' => 'CRITICAL',
|
||||
'channel' => 'test',
|
||||
'message' => 'bar',
|
||||
'context' => array(),
|
||||
'datetime' => new \DateTime,
|
||||
'extra' => array(),
|
||||
),
|
||||
array(
|
||||
'level_name' => 'WARNING',
|
||||
'channel' => 'log',
|
||||
'message' => 'foo',
|
||||
'context' => array(),
|
||||
'datetime' => new \DateTime,
|
||||
'extra' => array(),
|
||||
),
|
||||
));
|
||||
$this->assertEquals(array(
|
||||
array(
|
||||
'level_name' => 'CRITICAL',
|
||||
'channel' => 'test',
|
||||
'message' => 'bar',
|
||||
'context' => array(),
|
||||
'datetime' => date('Y-m-d'),
|
||||
'extra' => array(),
|
||||
),
|
||||
array(
|
||||
'level_name' => 'WARNING',
|
||||
'channel' => 'log',
|
||||
'message' => 'foo',
|
||||
'context' => array(),
|
||||
'datetime' => date('Y-m-d'),
|
||||
'extra' => array(),
|
||||
),
|
||||
), $formatted);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test issue #137
|
||||
*/
|
||||
public function testIgnoresRecursiveObjectReferences()
|
||||
{
|
||||
// set up the recursion
|
||||
$foo = new \stdClass();
|
||||
$bar = new \stdClass();
|
||||
|
||||
$foo->bar = $bar;
|
||||
$bar->foo = $foo;
|
||||
|
||||
// set an error handler to assert that the error is not raised anymore
|
||||
$that = $this;
|
||||
set_error_handler(function ($level, $message, $file, $line, $context) use ($that) {
|
||||
if (error_reporting() & $level) {
|
||||
restore_error_handler();
|
||||
$that->fail("$message should not be raised");
|
||||
}
|
||||
});
|
||||
|
||||
$formatter = new NormalizerFormatter();
|
||||
$reflMethod = new \ReflectionMethod($formatter, 'toJson');
|
||||
$reflMethod->setAccessible(true);
|
||||
$res = $reflMethod->invoke($formatter, array($foo, $bar), true);
|
||||
|
||||
restore_error_handler();
|
||||
|
||||
$this->assertEquals(@json_encode(array($foo, $bar)), $res);
|
||||
}
|
||||
|
||||
public function testIgnoresInvalidTypes()
|
||||
{
|
||||
// set up the recursion
|
||||
$resource = fopen(__FILE__, 'r');
|
||||
|
||||
// set an error handler to assert that the error is not raised anymore
|
||||
$that = $this;
|
||||
set_error_handler(function ($level, $message, $file, $line, $context) use ($that) {
|
||||
if (error_reporting() & $level) {
|
||||
restore_error_handler();
|
||||
$that->fail("$message should not be raised");
|
||||
}
|
||||
});
|
||||
|
||||
$formatter = new NormalizerFormatter();
|
||||
$reflMethod = new \ReflectionMethod($formatter, 'toJson');
|
||||
$reflMethod->setAccessible(true);
|
||||
$res = $reflMethod->invoke($formatter, array($resource), true);
|
||||
|
||||
restore_error_handler();
|
||||
|
||||
$this->assertEquals(@json_encode(array($resource)), $res);
|
||||
}
|
||||
|
||||
public function testNormalizeHandleLargeArrays()
|
||||
{
|
||||
$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(),
|
||||
));
|
||||
|
||||
$this->assertCount(1000, $res['context'][0]);
|
||||
$this->assertEquals('Over 1000 items (2000 total), aborting normalization', $res['context'][0]['...']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException RuntimeException
|
||||
*/
|
||||
public function testThrowsOnInvalidEncoding()
|
||||
{
|
||||
if (version_compare(PHP_VERSION, '5.5.0', '<')) {
|
||||
// Ignore the warning that will be emitted by PHP <5.5.0
|
||||
\PHPUnit_Framework_Error_Warning::$enabled = false;
|
||||
}
|
||||
$formatter = new NormalizerFormatter();
|
||||
$reflMethod = new \ReflectionMethod($formatter, 'toJson');
|
||||
$reflMethod->setAccessible(true);
|
||||
|
||||
// send an invalid unicode sequence as a object that can't be cleaned
|
||||
$record = new \stdClass;
|
||||
$record->message = "\xB1\x31";
|
||||
$res = $reflMethod->invoke($formatter, $record);
|
||||
if (PHP_VERSION_ID < 50500 && $res === '{"message":null}') {
|
||||
throw new \RuntimeException('PHP 5.3/5.4 throw a warning and null the value instead of returning false entirely');
|
||||
}
|
||||
}
|
||||
|
||||
public function testConvertsInvalidEncodingAsLatin9()
|
||||
{
|
||||
if (version_compare(PHP_VERSION, '5.5.0', '<')) {
|
||||
// Ignore the warning that will be emitted by PHP <5.5.0
|
||||
\PHPUnit_Framework_Error_Warning::$enabled = false;
|
||||
}
|
||||
$formatter = new NormalizerFormatter();
|
||||
$reflMethod = new \ReflectionMethod($formatter, 'toJson');
|
||||
$reflMethod->setAccessible(true);
|
||||
|
||||
$res = $reflMethod->invoke($formatter, array('message' => "\xA4\xA6\xA8\xB4\xB8\xBC\xBD\xBE"));
|
||||
|
||||
if (version_compare(PHP_VERSION, '5.5.0', '>=')) {
|
||||
$this->assertSame('{"message":"€ŠšŽžŒœŸ"}', $res);
|
||||
} else {
|
||||
// PHP <5.5 does not return false for an element encoding failure,
|
||||
// instead it emits a warning (possibly) and nulls the value.
|
||||
$this->assertSame('{"message":null}', $res);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $in Input
|
||||
* @param mixed $expect Expected output
|
||||
* @covers Monolog\Formatter\NormalizerFormatter::detectAndCleanUtf8
|
||||
* @dataProvider providesDetectAndCleanUtf8
|
||||
*/
|
||||
public function testDetectAndCleanUtf8($in, $expect)
|
||||
{
|
||||
$formatter = new NormalizerFormatter();
|
||||
$formatter->detectAndCleanUtf8($in);
|
||||
$this->assertSame($expect, $in);
|
||||
}
|
||||
|
||||
public function providesDetectAndCleanUtf8()
|
||||
{
|
||||
$obj = new \stdClass;
|
||||
|
||||
return array(
|
||||
'null' => array(null, null),
|
||||
'int' => array(123, 123),
|
||||
'float' => array(123.45, 123.45),
|
||||
'bool false' => array(false, false),
|
||||
'bool true' => array(true, true),
|
||||
'ascii string' => array('abcdef', 'abcdef'),
|
||||
'latin9 string' => array("\xB1\x31\xA4\xA6\xA8\xB4\xB8\xBC\xBD\xBE\xFF", '±1€ŠšŽžŒœŸÿ'),
|
||||
'unicode string' => array('¤¦¨´¸¼½¾€ŠšŽžŒœŸ', '¤¦¨´¸¼½¾€ŠšŽžŒœŸ'),
|
||||
'empty array' => array(array(), array()),
|
||||
'array' => array(array('abcdef'), array('abcdef')),
|
||||
'object' => array($obj, $obj),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $code
|
||||
* @param string $msg
|
||||
* @dataProvider providesHandleJsonErrorFailure
|
||||
*/
|
||||
public function testHandleJsonErrorFailure($code, $msg)
|
||||
{
|
||||
$formatter = new NormalizerFormatter();
|
||||
$reflMethod = new \ReflectionMethod($formatter, 'handleJsonError');
|
||||
$reflMethod->setAccessible(true);
|
||||
|
||||
$this->setExpectedException('RuntimeException', $msg);
|
||||
$reflMethod->invoke($formatter, $code, 'faked');
|
||||
}
|
||||
|
||||
public function providesHandleJsonErrorFailure()
|
||||
{
|
||||
return array(
|
||||
'depth' => array(JSON_ERROR_DEPTH, 'Maximum stack depth exceeded'),
|
||||
'state' => array(JSON_ERROR_STATE_MISMATCH, 'Underflow or the modes mismatch'),
|
||||
'ctrl' => array(JSON_ERROR_CTRL_CHAR, 'Unexpected control character found'),
|
||||
'default' => array(-1, 'Unknown error'),
|
||||
);
|
||||
}
|
||||
|
||||
public function testExceptionTraceWithArgs()
|
||||
{
|
||||
if (defined('HHVM_VERSION')) {
|
||||
$this->markTestSkipped('Not supported in HHVM since it detects errors differently');
|
||||
}
|
||||
|
||||
// This happens i.e. in React promises or Guzzle streams where stream wrappers are registered
|
||||
// and no file or line are included in the trace because it's treated as internal function
|
||||
set_error_handler(function ($errno, $errstr, $errfile, $errline) {
|
||||
throw new \ErrorException($errstr, 0, $errno, $errfile, $errline);
|
||||
});
|
||||
|
||||
try {
|
||||
// This will contain $resource and $wrappedResource as arguments in the trace item
|
||||
$resource = fopen('php://memory', 'rw+');
|
||||
fwrite($resource, 'test_resource');
|
||||
$wrappedResource = new TestFooNorm;
|
||||
$wrappedResource->foo = $resource;
|
||||
// Just do something stupid with a resource/wrapped resource as argument
|
||||
array_keys($wrappedResource);
|
||||
} catch (\Exception $e) {
|
||||
restore_error_handler();
|
||||
}
|
||||
|
||||
$formatter = new NormalizerFormatter();
|
||||
$record = array('context' => array('exception' => $e));
|
||||
$result = $formatter->format($record);
|
||||
|
||||
$this->assertRegExp(
|
||||
'%"resource":"\[resource\] \(stream\)"%',
|
||||
$result['context']['exception']['trace'][0]
|
||||
);
|
||||
|
||||
if (version_compare(PHP_VERSION, '5.5.0', '>=')) {
|
||||
$pattern = '%"wrappedResource":"\[object\] \(Monolog\\\\\\\\Formatter\\\\\\\\TestFooNorm: \)"%';
|
||||
} else {
|
||||
$pattern = '%\\\\"foo\\\\":null%';
|
||||
}
|
||||
|
||||
// Tests that the wrapped resource is ignored while encoding, only works for PHP <= 5.4
|
||||
$this->assertRegExp(
|
||||
$pattern,
|
||||
$result['context']['exception']['trace'][0]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class TestFooNorm
|
||||
{
|
||||
public $foo = 'foo';
|
||||
}
|
||||
|
||||
class TestBarNorm
|
||||
{
|
||||
public function __toString()
|
||||
{
|
||||
return 'bar';
|
||||
}
|
||||
}
|
||||
|
||||
class TestStreamFoo
|
||||
{
|
||||
public $foo;
|
||||
public $resource;
|
||||
|
||||
public function __construct($resource)
|
||||
{
|
||||
$this->resource = $resource;
|
||||
$this->foo = 'BAR';
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
fseek($this->resource, 0);
|
||||
|
||||
return $this->foo . ' - ' . (string) stream_get_contents($this->resource);
|
||||
}
|
||||
}
|
||||
|
||||
class TestToStringError
|
||||
{
|
||||
public function __toString()
|
||||
{
|
||||
throw new \RuntimeException('Could not convert to string');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Formatter;
|
||||
|
||||
class ScalarFormatterTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $formatter;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->formatter = new ScalarFormatter();
|
||||
}
|
||||
|
||||
public function buildTrace(\Exception $e)
|
||||
{
|
||||
$data = array();
|
||||
$trace = $e->getTrace();
|
||||
foreach ($trace as $frame) {
|
||||
if (isset($frame['file'])) {
|
||||
$data[] = $frame['file'].':'.$frame['line'];
|
||||
} else {
|
||||
$data[] = json_encode($frame);
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function encodeJson($data)
|
||||
{
|
||||
if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
|
||||
return json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
|
||||
return json_encode($data);
|
||||
}
|
||||
|
||||
public function testFormat()
|
||||
{
|
||||
$exception = new \Exception('foo');
|
||||
$formatted = $this->formatter->format(array(
|
||||
'foo' => 'string',
|
||||
'bar' => 1,
|
||||
'baz' => false,
|
||||
'bam' => array(1, 2, 3),
|
||||
'bat' => array('foo' => 'bar'),
|
||||
'bap' => \DateTime::createFromFormat(\DateTime::ISO8601, '1970-01-01T00:00:00+0000'),
|
||||
'ban' => $exception,
|
||||
));
|
||||
|
||||
$this->assertSame(array(
|
||||
'foo' => 'string',
|
||||
'bar' => 1,
|
||||
'baz' => false,
|
||||
'bam' => $this->encodeJson(array(1, 2, 3)),
|
||||
'bat' => $this->encodeJson(array('foo' => 'bar')),
|
||||
'bap' => '1970-01-01 00:00:00',
|
||||
'ban' => $this->encodeJson(array(
|
||||
'class' => get_class($exception),
|
||||
'message' => $exception->getMessage(),
|
||||
'code' => $exception->getCode(),
|
||||
'file' => $exception->getFile() . ':' . $exception->getLine(),
|
||||
'trace' => $this->buildTrace($exception),
|
||||
)),
|
||||
), $formatted);
|
||||
}
|
||||
|
||||
public function testFormatWithErrorContext()
|
||||
{
|
||||
$context = array('file' => 'foo', 'line' => 1);
|
||||
$formatted = $this->formatter->format(array(
|
||||
'context' => $context,
|
||||
));
|
||||
|
||||
$this->assertSame(array(
|
||||
'context' => $this->encodeJson($context),
|
||||
), $formatted);
|
||||
}
|
||||
|
||||
public function testFormatWithExceptionContext()
|
||||
{
|
||||
$exception = new \Exception('foo');
|
||||
$formatted = $this->formatter->format(array(
|
||||
'context' => array(
|
||||
'exception' => $exception,
|
||||
),
|
||||
));
|
||||
|
||||
$this->assertSame(array(
|
||||
'context' => $this->encodeJson(array(
|
||||
'exception' => array(
|
||||
'class' => get_class($exception),
|
||||
'message' => $exception->getMessage(),
|
||||
'code' => $exception->getCode(),
|
||||
'file' => $exception->getFile() . ':' . $exception->getLine(),
|
||||
'trace' => $this->buildTrace($exception),
|
||||
),
|
||||
)),
|
||||
), $formatted);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Formatter;
|
||||
|
||||
use Monolog\Logger;
|
||||
|
||||
class WildfireFormatterTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @covers Monolog\Formatter\WildfireFormatter::format
|
||||
*/
|
||||
public function testDefaultFormat()
|
||||
{
|
||||
$wildfire = new WildfireFormatter();
|
||||
$record = array(
|
||||
'level' => Logger::ERROR,
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => 'meh',
|
||||
'context' => array('from' => 'logger'),
|
||||
'datetime' => new \DateTime("@0"),
|
||||
'extra' => array('ip' => '127.0.0.1'),
|
||||
'message' => 'log',
|
||||
);
|
||||
|
||||
$message = $wildfire->format($record);
|
||||
|
||||
$this->assertEquals(
|
||||
'125|[{"Type":"ERROR","File":"","Line":"","Label":"meh"},'
|
||||
.'{"message":"log","context":{"from":"logger"},"extra":{"ip":"127.0.0.1"}}]|',
|
||||
$message
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Formatter\WildfireFormatter::format
|
||||
*/
|
||||
public function testFormatWithFileAndLine()
|
||||
{
|
||||
$wildfire = new WildfireFormatter();
|
||||
$record = array(
|
||||
'level' => Logger::ERROR,
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => 'meh',
|
||||
'context' => array('from' => 'logger'),
|
||||
'datetime' => new \DateTime("@0"),
|
||||
'extra' => array('ip' => '127.0.0.1', 'file' => 'test', 'line' => 14),
|
||||
'message' => 'log',
|
||||
);
|
||||
|
||||
$message = $wildfire->format($record);
|
||||
|
||||
$this->assertEquals(
|
||||
'129|[{"Type":"ERROR","File":"test","Line":14,"Label":"meh"},'
|
||||
.'{"message":"log","context":{"from":"logger"},"extra":{"ip":"127.0.0.1"}}]|',
|
||||
$message
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Formatter\WildfireFormatter::format
|
||||
*/
|
||||
public function testFormatWithoutContext()
|
||||
{
|
||||
$wildfire = new WildfireFormatter();
|
||||
$record = array(
|
||||
'level' => Logger::ERROR,
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => 'meh',
|
||||
'context' => array(),
|
||||
'datetime' => new \DateTime("@0"),
|
||||
'extra' => array(),
|
||||
'message' => 'log',
|
||||
);
|
||||
|
||||
$message = $wildfire->format($record);
|
||||
|
||||
$this->assertEquals(
|
||||
'58|[{"Type":"ERROR","File":"","Line":"","Label":"meh"},"log"]|',
|
||||
$message
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Formatter\WildfireFormatter::formatBatch
|
||||
* @expectedException BadMethodCallException
|
||||
*/
|
||||
public function testBatchFormatThrowException()
|
||||
{
|
||||
$wildfire = new WildfireFormatter();
|
||||
$record = array(
|
||||
'level' => Logger::ERROR,
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => 'meh',
|
||||
'context' => array(),
|
||||
'datetime' => new \DateTime("@0"),
|
||||
'extra' => array(),
|
||||
'message' => 'log',
|
||||
);
|
||||
|
||||
$wildfire->formatBatch(array($record));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Formatter\WildfireFormatter::format
|
||||
*/
|
||||
public function testTableFormat()
|
||||
{
|
||||
$wildfire = new WildfireFormatter();
|
||||
$record = array(
|
||||
'level' => Logger::ERROR,
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => 'table-channel',
|
||||
'context' => array(
|
||||
WildfireFormatter::TABLE => array(
|
||||
array('col1', 'col2', 'col3'),
|
||||
array('val1', 'val2', 'val3'),
|
||||
array('foo1', 'foo2', 'foo3'),
|
||||
array('bar1', 'bar2', 'bar3'),
|
||||
),
|
||||
),
|
||||
'datetime' => new \DateTime("@0"),
|
||||
'extra' => array(),
|
||||
'message' => 'table-message',
|
||||
);
|
||||
|
||||
$message = $wildfire->format($record);
|
||||
|
||||
$this->assertEquals(
|
||||
'171|[{"Type":"TABLE","File":"","Line":"","Label":"table-channel: table-message"},[["col1","col2","col3"],["val1","val2","val3"],["foo1","foo2","foo3"],["bar1","bar2","bar3"]]]|',
|
||||
$message
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
use Monolog\Formatter\LineFormatter;
|
||||
use Monolog\Processor\WebProcessor;
|
||||
|
||||
class AbstractHandlerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers Monolog\Handler\AbstractHandler::__construct
|
||||
* @covers Monolog\Handler\AbstractHandler::getLevel
|
||||
* @covers Monolog\Handler\AbstractHandler::setLevel
|
||||
* @covers Monolog\Handler\AbstractHandler::getBubble
|
||||
* @covers Monolog\Handler\AbstractHandler::setBubble
|
||||
* @covers Monolog\Handler\AbstractHandler::getFormatter
|
||||
* @covers Monolog\Handler\AbstractHandler::setFormatter
|
||||
*/
|
||||
public function testConstructAndGetSet()
|
||||
{
|
||||
$handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractHandler', array(Logger::WARNING, false));
|
||||
$this->assertEquals(Logger::WARNING, $handler->getLevel());
|
||||
$this->assertEquals(false, $handler->getBubble());
|
||||
|
||||
$handler->setLevel(Logger::ERROR);
|
||||
$handler->setBubble(true);
|
||||
$handler->setFormatter($formatter = new LineFormatter);
|
||||
$this->assertEquals(Logger::ERROR, $handler->getLevel());
|
||||
$this->assertEquals(true, $handler->getBubble());
|
||||
$this->assertSame($formatter, $handler->getFormatter());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\AbstractHandler::handleBatch
|
||||
*/
|
||||
public function testHandleBatch()
|
||||
{
|
||||
$handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractHandler');
|
||||
$handler->expects($this->exactly(2))
|
||||
->method('handle');
|
||||
$handler->handleBatch(array($this->getRecord(), $this->getRecord()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\AbstractHandler::isHandling
|
||||
*/
|
||||
public function testIsHandling()
|
||||
{
|
||||
$handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractHandler', array(Logger::WARNING, false));
|
||||
$this->assertTrue($handler->isHandling($this->getRecord()));
|
||||
$this->assertFalse($handler->isHandling($this->getRecord(Logger::DEBUG)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\AbstractHandler::__construct
|
||||
*/
|
||||
public function testHandlesPsrStyleLevels()
|
||||
{
|
||||
$handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractHandler', array('warning', false));
|
||||
$this->assertFalse($handler->isHandling($this->getRecord(Logger::DEBUG)));
|
||||
$handler->setLevel('debug');
|
||||
$this->assertTrue($handler->isHandling($this->getRecord(Logger::DEBUG)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\AbstractHandler::getFormatter
|
||||
* @covers Monolog\Handler\AbstractHandler::getDefaultFormatter
|
||||
*/
|
||||
public function testGetFormatterInitializesDefault()
|
||||
{
|
||||
$handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractHandler');
|
||||
$this->assertInstanceOf('Monolog\Formatter\LineFormatter', $handler->getFormatter());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\AbstractHandler::pushProcessor
|
||||
* @covers Monolog\Handler\AbstractHandler::popProcessor
|
||||
* @expectedException LogicException
|
||||
*/
|
||||
public function testPushPopProcessor()
|
||||
{
|
||||
$logger = $this->getMockForAbstractClass('Monolog\Handler\AbstractHandler');
|
||||
$processor1 = new WebProcessor;
|
||||
$processor2 = new WebProcessor;
|
||||
|
||||
$logger->pushProcessor($processor1);
|
||||
$logger->pushProcessor($processor2);
|
||||
|
||||
$this->assertEquals($processor2, $logger->popProcessor());
|
||||
$this->assertEquals($processor1, $logger->popProcessor());
|
||||
$logger->popProcessor();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\AbstractHandler::pushProcessor
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testPushProcessorWithNonCallable()
|
||||
{
|
||||
$handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractHandler');
|
||||
|
||||
$handler->pushProcessor(new \stdClass());
|
||||
}
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
use Monolog\Processor\WebProcessor;
|
||||
|
||||
class AbstractProcessingHandlerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers Monolog\Handler\AbstractProcessingHandler::handle
|
||||
*/
|
||||
public function testHandleLowerLevelMessage()
|
||||
{
|
||||
$handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractProcessingHandler', array(Logger::WARNING, true));
|
||||
$this->assertFalse($handler->handle($this->getRecord(Logger::DEBUG)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\AbstractProcessingHandler::handle
|
||||
*/
|
||||
public function testHandleBubbling()
|
||||
{
|
||||
$handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractProcessingHandler', array(Logger::DEBUG, true));
|
||||
$this->assertFalse($handler->handle($this->getRecord()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\AbstractProcessingHandler::handle
|
||||
*/
|
||||
public function testHandleNotBubbling()
|
||||
{
|
||||
$handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractProcessingHandler', array(Logger::DEBUG, false));
|
||||
$this->assertTrue($handler->handle($this->getRecord()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\AbstractProcessingHandler::handle
|
||||
*/
|
||||
public function testHandleIsFalseWhenNotHandled()
|
||||
{
|
||||
$handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractProcessingHandler', array(Logger::WARNING, false));
|
||||
$this->assertTrue($handler->handle($this->getRecord()));
|
||||
$this->assertFalse($handler->handle($this->getRecord(Logger::DEBUG)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\AbstractProcessingHandler::processRecord
|
||||
*/
|
||||
public function testProcessRecord()
|
||||
{
|
||||
$handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractProcessingHandler');
|
||||
$handler->pushProcessor(new WebProcessor(array(
|
||||
'REQUEST_URI' => '',
|
||||
'REQUEST_METHOD' => '',
|
||||
'REMOTE_ADDR' => '',
|
||||
'SERVER_NAME' => '',
|
||||
'UNIQUE_ID' => '',
|
||||
)));
|
||||
$handledRecord = null;
|
||||
$handler->expects($this->once())
|
||||
->method('write')
|
||||
->will($this->returnCallback(function ($record) use (&$handledRecord) {
|
||||
$handledRecord = $record;
|
||||
}))
|
||||
;
|
||||
$handler->handle($this->getRecord());
|
||||
$this->assertEquals(6, count($handledRecord['extra']));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
use PhpAmqpLib\Message\AMQPMessage;
|
||||
use PhpAmqpLib\Connection\AMQPConnection;
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\RotatingFileHandler
|
||||
*/
|
||||
class AmqpHandlerTest extends TestCase
|
||||
{
|
||||
public function testHandleAmqpExt()
|
||||
{
|
||||
if (!class_exists('AMQPConnection') || !class_exists('AMQPExchange')) {
|
||||
$this->markTestSkipped("amqp-php not installed");
|
||||
}
|
||||
|
||||
if (!class_exists('AMQPChannel')) {
|
||||
$this->markTestSkipped("Please update AMQP to version >= 1.0");
|
||||
}
|
||||
|
||||
$messages = array();
|
||||
|
||||
$exchange = $this->getMock('AMQPExchange', array('publish', 'setName'), array(), '', false);
|
||||
$exchange->expects($this->once())
|
||||
->method('setName')
|
||||
->with('log')
|
||||
;
|
||||
$exchange->expects($this->any())
|
||||
->method('publish')
|
||||
->will($this->returnCallback(function ($message, $routing_key, $flags = 0, $attributes = array()) use (&$messages) {
|
||||
$messages[] = array($message, $routing_key, $flags, $attributes);
|
||||
}))
|
||||
;
|
||||
|
||||
$handler = new AmqpHandler($exchange, 'log');
|
||||
|
||||
$record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34));
|
||||
|
||||
$expected = array(
|
||||
array(
|
||||
'message' => 'test',
|
||||
'context' => array(
|
||||
'data' => array(),
|
||||
'foo' => 34,
|
||||
),
|
||||
'level' => 300,
|
||||
'level_name' => 'WARNING',
|
||||
'channel' => 'test',
|
||||
'extra' => array(),
|
||||
),
|
||||
'warn.test',
|
||||
0,
|
||||
array(
|
||||
'delivery_mode' => 2,
|
||||
'content_type' => 'application/json',
|
||||
),
|
||||
);
|
||||
|
||||
$handler->handle($record);
|
||||
|
||||
$this->assertCount(1, $messages);
|
||||
$messages[0][0] = json_decode($messages[0][0], true);
|
||||
unset($messages[0][0]['datetime']);
|
||||
$this->assertEquals($expected, $messages[0]);
|
||||
}
|
||||
|
||||
public function testHandlePhpAmqpLib()
|
||||
{
|
||||
if (!class_exists('PhpAmqpLib\Connection\AMQPConnection')) {
|
||||
$this->markTestSkipped("php-amqplib not installed");
|
||||
}
|
||||
|
||||
$messages = array();
|
||||
|
||||
$exchange = $this->getMock('PhpAmqpLib\Channel\AMQPChannel', array('basic_publish', '__destruct'), array(), '', false);
|
||||
|
||||
$exchange->expects($this->any())
|
||||
->method('basic_publish')
|
||||
->will($this->returnCallback(function (AMQPMessage $msg, $exchange = "", $routing_key = "", $mandatory = false, $immediate = false, $ticket = null) use (&$messages) {
|
||||
$messages[] = array($msg, $exchange, $routing_key, $mandatory, $immediate, $ticket);
|
||||
}))
|
||||
;
|
||||
|
||||
$handler = new AmqpHandler($exchange, 'log');
|
||||
|
||||
$record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34));
|
||||
|
||||
$expected = array(
|
||||
array(
|
||||
'message' => 'test',
|
||||
'context' => array(
|
||||
'data' => array(),
|
||||
'foo' => 34,
|
||||
),
|
||||
'level' => 300,
|
||||
'level_name' => 'WARNING',
|
||||
'channel' => 'test',
|
||||
'extra' => array(),
|
||||
),
|
||||
'log',
|
||||
'warn.test',
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
array(
|
||||
'delivery_mode' => 2,
|
||||
'content_type' => 'application/json',
|
||||
),
|
||||
);
|
||||
|
||||
$handler->handle($record);
|
||||
|
||||
$this->assertCount(1, $messages);
|
||||
|
||||
/* @var $msg AMQPMessage */
|
||||
$msg = $messages[0][0];
|
||||
$messages[0][0] = json_decode($msg->body, true);
|
||||
$messages[0][] = $msg->get_properties();
|
||||
unset($messages[0][0]['datetime']);
|
||||
|
||||
$this->assertEquals($expected, $messages[0]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\BrowserConsoleHandlerTest
|
||||
*/
|
||||
class BrowserConsoleHandlerTest extends TestCase
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
BrowserConsoleHandler::reset();
|
||||
}
|
||||
|
||||
protected function generateScript()
|
||||
{
|
||||
$reflMethod = new \ReflectionMethod('Monolog\Handler\BrowserConsoleHandler', 'generateScript');
|
||||
$reflMethod->setAccessible(true);
|
||||
|
||||
return $reflMethod->invoke(null);
|
||||
}
|
||||
|
||||
public function testStyling()
|
||||
{
|
||||
$handler = new BrowserConsoleHandler();
|
||||
$handler->setFormatter($this->getIdentityFormatter());
|
||||
|
||||
$handler->handle($this->getRecord(Logger::DEBUG, 'foo[[bar]]{color: red}'));
|
||||
|
||||
$expected = <<<EOF
|
||||
(function (c) {if (c && c.groupCollapsed) {
|
||||
c.log("%cfoo%cbar%c", "font-weight: normal", "color: red", "font-weight: normal");
|
||||
}})(console);
|
||||
EOF;
|
||||
|
||||
$this->assertEquals($expected, $this->generateScript());
|
||||
}
|
||||
|
||||
public function testEscaping()
|
||||
{
|
||||
$handler = new BrowserConsoleHandler();
|
||||
$handler->setFormatter($this->getIdentityFormatter());
|
||||
|
||||
$handler->handle($this->getRecord(Logger::DEBUG, "[foo] [[\"bar\n[baz]\"]]{color: red}"));
|
||||
|
||||
$expected = <<<EOF
|
||||
(function (c) {if (c && c.groupCollapsed) {
|
||||
c.log("%c[foo] %c\"bar\\n[baz]\"%c", "font-weight: normal", "color: red", "font-weight: normal");
|
||||
}})(console);
|
||||
EOF;
|
||||
|
||||
$this->assertEquals($expected, $this->generateScript());
|
||||
}
|
||||
|
||||
public function testAutolabel()
|
||||
{
|
||||
$handler = new BrowserConsoleHandler();
|
||||
$handler->setFormatter($this->getIdentityFormatter());
|
||||
|
||||
$handler->handle($this->getRecord(Logger::DEBUG, '[[foo]]{macro: autolabel}'));
|
||||
$handler->handle($this->getRecord(Logger::DEBUG, '[[bar]]{macro: autolabel}'));
|
||||
$handler->handle($this->getRecord(Logger::DEBUG, '[[foo]]{macro: autolabel}'));
|
||||
|
||||
$expected = <<<EOF
|
||||
(function (c) {if (c && c.groupCollapsed) {
|
||||
c.log("%c%cfoo%c", "font-weight: normal", "background-color: blue; color: white; border-radius: 3px; padding: 0 2px 0 2px", "font-weight: normal");
|
||||
c.log("%c%cbar%c", "font-weight: normal", "background-color: green; color: white; border-radius: 3px; padding: 0 2px 0 2px", "font-weight: normal");
|
||||
c.log("%c%cfoo%c", "font-weight: normal", "background-color: blue; color: white; border-radius: 3px; padding: 0 2px 0 2px", "font-weight: normal");
|
||||
}})(console);
|
||||
EOF;
|
||||
|
||||
$this->assertEquals($expected, $this->generateScript());
|
||||
}
|
||||
|
||||
public function testContext()
|
||||
{
|
||||
$handler = new BrowserConsoleHandler();
|
||||
$handler->setFormatter($this->getIdentityFormatter());
|
||||
|
||||
$handler->handle($this->getRecord(Logger::DEBUG, 'test', array('foo' => 'bar')));
|
||||
|
||||
$expected = <<<EOF
|
||||
(function (c) {if (c && c.groupCollapsed) {
|
||||
c.groupCollapsed("%ctest", "font-weight: normal");
|
||||
c.log("%c%s", "font-weight: bold", "Context");
|
||||
c.log("%s: %o", "foo", "bar");
|
||||
c.groupEnd();
|
||||
}})(console);
|
||||
EOF;
|
||||
|
||||
$this->assertEquals($expected, $this->generateScript());
|
||||
}
|
||||
|
||||
public function testConcurrentHandlers()
|
||||
{
|
||||
$handler1 = new BrowserConsoleHandler();
|
||||
$handler1->setFormatter($this->getIdentityFormatter());
|
||||
|
||||
$handler2 = new BrowserConsoleHandler();
|
||||
$handler2->setFormatter($this->getIdentityFormatter());
|
||||
|
||||
$handler1->handle($this->getRecord(Logger::DEBUG, 'test1'));
|
||||
$handler2->handle($this->getRecord(Logger::DEBUG, 'test2'));
|
||||
$handler1->handle($this->getRecord(Logger::DEBUG, 'test3'));
|
||||
$handler2->handle($this->getRecord(Logger::DEBUG, 'test4'));
|
||||
|
||||
$expected = <<<EOF
|
||||
(function (c) {if (c && c.groupCollapsed) {
|
||||
c.log("%ctest1", "font-weight: normal");
|
||||
c.log("%ctest2", "font-weight: normal");
|
||||
c.log("%ctest3", "font-weight: normal");
|
||||
c.log("%ctest4", "font-weight: normal");
|
||||
}})(console);
|
||||
EOF;
|
||||
|
||||
$this->assertEquals($expected, $this->generateScript());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
|
||||
class BufferHandlerTest extends TestCase
|
||||
{
|
||||
private $shutdownCheckHandler;
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\BufferHandler::__construct
|
||||
* @covers Monolog\Handler\BufferHandler::handle
|
||||
* @covers Monolog\Handler\BufferHandler::close
|
||||
*/
|
||||
public function testHandleBuffers()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
$handler = new BufferHandler($test);
|
||||
$handler->handle($this->getRecord(Logger::DEBUG));
|
||||
$handler->handle($this->getRecord(Logger::INFO));
|
||||
$this->assertFalse($test->hasDebugRecords());
|
||||
$this->assertFalse($test->hasInfoRecords());
|
||||
$handler->close();
|
||||
$this->assertTrue($test->hasInfoRecords());
|
||||
$this->assertTrue(count($test->getRecords()) === 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\BufferHandler::close
|
||||
* @covers Monolog\Handler\BufferHandler::flush
|
||||
*/
|
||||
public function testPropagatesRecordsAtEndOfRequest()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
$handler = new BufferHandler($test);
|
||||
$handler->handle($this->getRecord(Logger::WARNING));
|
||||
$handler->handle($this->getRecord(Logger::DEBUG));
|
||||
$this->shutdownCheckHandler = $test;
|
||||
register_shutdown_function(array($this, 'checkPropagation'));
|
||||
}
|
||||
|
||||
public function checkPropagation()
|
||||
{
|
||||
if (!$this->shutdownCheckHandler->hasWarningRecords() || !$this->shutdownCheckHandler->hasDebugRecords()) {
|
||||
echo '!!! BufferHandlerTest::testPropagatesRecordsAtEndOfRequest failed to verify that the messages have been propagated' . PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\BufferHandler::handle
|
||||
*/
|
||||
public function testHandleBufferLimit()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
$handler = new BufferHandler($test, 2);
|
||||
$handler->handle($this->getRecord(Logger::DEBUG));
|
||||
$handler->handle($this->getRecord(Logger::DEBUG));
|
||||
$handler->handle($this->getRecord(Logger::INFO));
|
||||
$handler->handle($this->getRecord(Logger::WARNING));
|
||||
$handler->close();
|
||||
$this->assertTrue($test->hasWarningRecords());
|
||||
$this->assertTrue($test->hasInfoRecords());
|
||||
$this->assertFalse($test->hasDebugRecords());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\BufferHandler::handle
|
||||
*/
|
||||
public function testHandleBufferLimitWithFlushOnOverflow()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
$handler = new BufferHandler($test, 3, Logger::DEBUG, true, true);
|
||||
|
||||
// send two records
|
||||
$handler->handle($this->getRecord(Logger::DEBUG));
|
||||
$handler->handle($this->getRecord(Logger::DEBUG));
|
||||
$handler->handle($this->getRecord(Logger::DEBUG));
|
||||
$this->assertFalse($test->hasDebugRecords());
|
||||
$this->assertCount(0, $test->getRecords());
|
||||
|
||||
// overflow
|
||||
$handler->handle($this->getRecord(Logger::INFO));
|
||||
$this->assertTrue($test->hasDebugRecords());
|
||||
$this->assertCount(3, $test->getRecords());
|
||||
|
||||
// should buffer again
|
||||
$handler->handle($this->getRecord(Logger::WARNING));
|
||||
$this->assertCount(3, $test->getRecords());
|
||||
|
||||
$handler->close();
|
||||
$this->assertCount(5, $test->getRecords());
|
||||
$this->assertTrue($test->hasWarningRecords());
|
||||
$this->assertTrue($test->hasInfoRecords());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\BufferHandler::handle
|
||||
*/
|
||||
public function testHandleLevel()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
$handler = new BufferHandler($test, 0, Logger::INFO);
|
||||
$handler->handle($this->getRecord(Logger::DEBUG));
|
||||
$handler->handle($this->getRecord(Logger::INFO));
|
||||
$handler->handle($this->getRecord(Logger::WARNING));
|
||||
$handler->handle($this->getRecord(Logger::DEBUG));
|
||||
$handler->close();
|
||||
$this->assertTrue($test->hasWarningRecords());
|
||||
$this->assertTrue($test->hasInfoRecords());
|
||||
$this->assertFalse($test->hasDebugRecords());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\BufferHandler::flush
|
||||
*/
|
||||
public function testFlush()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
$handler = new BufferHandler($test, 0);
|
||||
$handler->handle($this->getRecord(Logger::DEBUG));
|
||||
$handler->handle($this->getRecord(Logger::INFO));
|
||||
$handler->flush();
|
||||
$this->assertTrue($test->hasInfoRecords());
|
||||
$this->assertTrue($test->hasDebugRecords());
|
||||
$this->assertFalse($test->hasWarningRecords());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\BufferHandler::handle
|
||||
*/
|
||||
public function testHandleUsesProcessors()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
$handler = new BufferHandler($test);
|
||||
$handler->pushProcessor(function ($record) {
|
||||
$record['extra']['foo'] = true;
|
||||
|
||||
return $record;
|
||||
});
|
||||
$handler->handle($this->getRecord(Logger::WARNING));
|
||||
$handler->flush();
|
||||
$this->assertTrue($test->hasWarningRecords());
|
||||
$records = $test->getRecords();
|
||||
$this->assertTrue($records[0]['extra']['foo']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\ChromePHPHandler
|
||||
*/
|
||||
class ChromePHPHandlerTest extends TestCase
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
TestChromePHPHandler::reset();
|
||||
$_SERVER['HTTP_USER_AGENT'] = 'Monolog Test; Chrome/1.0';
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider agentsProvider
|
||||
*/
|
||||
public function testHeaders($agent)
|
||||
{
|
||||
$_SERVER['HTTP_USER_AGENT'] = $agent;
|
||||
|
||||
$handler = new TestChromePHPHandler();
|
||||
$handler->setFormatter($this->getIdentityFormatter());
|
||||
$handler->handle($this->getRecord(Logger::DEBUG));
|
||||
$handler->handle($this->getRecord(Logger::WARNING));
|
||||
|
||||
$expected = array(
|
||||
'X-ChromeLogger-Data' => base64_encode(utf8_encode(json_encode(array(
|
||||
'version' => ChromePHPHandler::VERSION,
|
||||
'columns' => array('label', 'log', 'backtrace', 'type'),
|
||||
'rows' => array(
|
||||
'test',
|
||||
'test',
|
||||
),
|
||||
'request_uri' => '',
|
||||
)))),
|
||||
);
|
||||
|
||||
$this->assertEquals($expected, $handler->getHeaders());
|
||||
}
|
||||
|
||||
public static function agentsProvider()
|
||||
{
|
||||
return array(
|
||||
array('Monolog Test; Chrome/1.0'),
|
||||
array('Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0'),
|
||||
array('Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/56.0.2924.76 Chrome/56.0.2924.76 Safari/537.36'),
|
||||
array('Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome Safari/537.36'),
|
||||
);
|
||||
}
|
||||
|
||||
public function testHeadersOverflow()
|
||||
{
|
||||
$handler = new TestChromePHPHandler();
|
||||
$handler->handle($this->getRecord(Logger::DEBUG));
|
||||
$handler->handle($this->getRecord(Logger::WARNING, str_repeat('a', 150 * 1024)));
|
||||
|
||||
// overflow chrome headers limit
|
||||
$handler->handle($this->getRecord(Logger::WARNING, str_repeat('a', 100 * 1024)));
|
||||
|
||||
$expected = array(
|
||||
'X-ChromeLogger-Data' => base64_encode(utf8_encode(json_encode(array(
|
||||
'version' => ChromePHPHandler::VERSION,
|
||||
'columns' => array('label', 'log', 'backtrace', 'type'),
|
||||
'rows' => array(
|
||||
array(
|
||||
'test',
|
||||
'test',
|
||||
'unknown',
|
||||
'log',
|
||||
),
|
||||
array(
|
||||
'test',
|
||||
str_repeat('a', 150 * 1024),
|
||||
'unknown',
|
||||
'warn',
|
||||
),
|
||||
array(
|
||||
'monolog',
|
||||
'Incomplete logs, chrome header size limit reached',
|
||||
'unknown',
|
||||
'warn',
|
||||
),
|
||||
),
|
||||
'request_uri' => '',
|
||||
)))),
|
||||
);
|
||||
|
||||
$this->assertEquals($expected, $handler->getHeaders());
|
||||
}
|
||||
|
||||
public function testConcurrentHandlers()
|
||||
{
|
||||
$handler = new TestChromePHPHandler();
|
||||
$handler->setFormatter($this->getIdentityFormatter());
|
||||
$handler->handle($this->getRecord(Logger::DEBUG));
|
||||
$handler->handle($this->getRecord(Logger::WARNING));
|
||||
|
||||
$handler2 = new TestChromePHPHandler();
|
||||
$handler2->setFormatter($this->getIdentityFormatter());
|
||||
$handler2->handle($this->getRecord(Logger::DEBUG));
|
||||
$handler2->handle($this->getRecord(Logger::WARNING));
|
||||
|
||||
$expected = array(
|
||||
'X-ChromeLogger-Data' => base64_encode(utf8_encode(json_encode(array(
|
||||
'version' => ChromePHPHandler::VERSION,
|
||||
'columns' => array('label', 'log', 'backtrace', 'type'),
|
||||
'rows' => array(
|
||||
'test',
|
||||
'test',
|
||||
'test',
|
||||
'test',
|
||||
),
|
||||
'request_uri' => '',
|
||||
)))),
|
||||
);
|
||||
|
||||
$this->assertEquals($expected, $handler2->getHeaders());
|
||||
}
|
||||
}
|
||||
|
||||
class TestChromePHPHandler extends ChromePHPHandler
|
||||
{
|
||||
protected $headers = array();
|
||||
|
||||
public static function reset()
|
||||
{
|
||||
self::$initialized = false;
|
||||
self::$overflowed = false;
|
||||
self::$sendHeaders = true;
|
||||
self::$json['rows'] = array();
|
||||
}
|
||||
|
||||
protected function sendHeader($header, $content)
|
||||
{
|
||||
$this->headers[$header] = $content;
|
||||
}
|
||||
|
||||
public function getHeaders()
|
||||
{
|
||||
return $this->headers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
|
||||
class CouchDBHandlerTest extends TestCase
|
||||
{
|
||||
public function testHandle()
|
||||
{
|
||||
$record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34));
|
||||
|
||||
$handler = new CouchDBHandler();
|
||||
|
||||
try {
|
||||
$handler->handle($record);
|
||||
} catch (\RuntimeException $e) {
|
||||
$this->markTestSkipped('Could not connect to couchdb server on http://localhost:5984');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
|
||||
class DeduplicationHandlerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers Monolog\Handler\DeduplicationHandler::flush
|
||||
*/
|
||||
public function testFlushPassthruIfAllRecordsUnderTrigger()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
@unlink(sys_get_temp_dir().'/monolog_dedup.log');
|
||||
$handler = new DeduplicationHandler($test, sys_get_temp_dir().'/monolog_dedup.log', 0);
|
||||
|
||||
$handler->handle($this->getRecord(Logger::DEBUG));
|
||||
$handler->handle($this->getRecord(Logger::INFO));
|
||||
|
||||
$handler->flush();
|
||||
|
||||
$this->assertTrue($test->hasInfoRecords());
|
||||
$this->assertTrue($test->hasDebugRecords());
|
||||
$this->assertFalse($test->hasWarningRecords());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\DeduplicationHandler::flush
|
||||
* @covers Monolog\Handler\DeduplicationHandler::appendRecord
|
||||
*/
|
||||
public function testFlushPassthruIfEmptyLog()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
@unlink(sys_get_temp_dir().'/monolog_dedup.log');
|
||||
$handler = new DeduplicationHandler($test, sys_get_temp_dir().'/monolog_dedup.log', 0);
|
||||
|
||||
$handler->handle($this->getRecord(Logger::ERROR, 'Foo:bar'));
|
||||
$handler->handle($this->getRecord(Logger::CRITICAL, "Foo\nbar"));
|
||||
|
||||
$handler->flush();
|
||||
|
||||
$this->assertTrue($test->hasErrorRecords());
|
||||
$this->assertTrue($test->hasCriticalRecords());
|
||||
$this->assertFalse($test->hasWarningRecords());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\DeduplicationHandler::flush
|
||||
* @covers Monolog\Handler\DeduplicationHandler::appendRecord
|
||||
* @covers Monolog\Handler\DeduplicationHandler::isDuplicate
|
||||
* @depends testFlushPassthruIfEmptyLog
|
||||
*/
|
||||
public function testFlushSkipsIfLogExists()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
$handler = new DeduplicationHandler($test, sys_get_temp_dir().'/monolog_dedup.log', 0);
|
||||
|
||||
$handler->handle($this->getRecord(Logger::ERROR, 'Foo:bar'));
|
||||
$handler->handle($this->getRecord(Logger::CRITICAL, "Foo\nbar"));
|
||||
|
||||
$handler->flush();
|
||||
|
||||
$this->assertFalse($test->hasErrorRecords());
|
||||
$this->assertFalse($test->hasCriticalRecords());
|
||||
$this->assertFalse($test->hasWarningRecords());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\DeduplicationHandler::flush
|
||||
* @covers Monolog\Handler\DeduplicationHandler::appendRecord
|
||||
* @covers Monolog\Handler\DeduplicationHandler::isDuplicate
|
||||
* @depends testFlushPassthruIfEmptyLog
|
||||
*/
|
||||
public function testFlushPassthruIfLogTooOld()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
$handler = new DeduplicationHandler($test, sys_get_temp_dir().'/monolog_dedup.log', 0);
|
||||
|
||||
$record = $this->getRecord(Logger::ERROR);
|
||||
$record['datetime']->modify('+62seconds');
|
||||
$handler->handle($record);
|
||||
$record = $this->getRecord(Logger::CRITICAL);
|
||||
$record['datetime']->modify('+62seconds');
|
||||
$handler->handle($record);
|
||||
|
||||
$handler->flush();
|
||||
|
||||
$this->assertTrue($test->hasErrorRecords());
|
||||
$this->assertTrue($test->hasCriticalRecords());
|
||||
$this->assertFalse($test->hasWarningRecords());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\DeduplicationHandler::flush
|
||||
* @covers Monolog\Handler\DeduplicationHandler::appendRecord
|
||||
* @covers Monolog\Handler\DeduplicationHandler::isDuplicate
|
||||
* @covers Monolog\Handler\DeduplicationHandler::collectLogs
|
||||
*/
|
||||
public function testGcOldLogs()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
@unlink(sys_get_temp_dir().'/monolog_dedup.log');
|
||||
$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']->modify('-1day -10seconds');
|
||||
$handler->handle($record);
|
||||
$record2 = $this->getRecord(Logger::CRITICAL);
|
||||
$record2['datetime']->modify('-1day -10seconds');
|
||||
$handler->handle($record2);
|
||||
$record3 = $this->getRecord(Logger::CRITICAL);
|
||||
$record3['datetime']->modify('-30seconds');
|
||||
$handler->handle($record3);
|
||||
|
||||
// log is written as none of them are duplicate
|
||||
$handler->flush();
|
||||
$this->assertSame(
|
||||
$record['datetime']->getTimestamp() . ":ERROR:test\n" .
|
||||
$record2['datetime']->getTimestamp() . ":CRITICAL:test\n" .
|
||||
$record3['datetime']->getTimestamp() . ":CRITICAL:test\n",
|
||||
file_get_contents(sys_get_temp_dir() . '/monolog_dedup.log')
|
||||
);
|
||||
$this->assertTrue($test->hasErrorRecords());
|
||||
$this->assertTrue($test->hasCriticalRecords());
|
||||
$this->assertFalse($test->hasWarningRecords());
|
||||
|
||||
// clear test handler
|
||||
$test->clear();
|
||||
$this->assertFalse($test->hasErrorRecords());
|
||||
$this->assertFalse($test->hasCriticalRecords());
|
||||
|
||||
// log new records, duplicate log gets GC'd at the end of this flush call
|
||||
$handler->handle($record = $this->getRecord(Logger::ERROR));
|
||||
$handler->handle($record2 = $this->getRecord(Logger::CRITICAL));
|
||||
$handler->flush();
|
||||
|
||||
// log should now contain the new errors and the previous one that was recent enough
|
||||
$this->assertSame(
|
||||
$record3['datetime']->getTimestamp() . ":CRITICAL:test\n" .
|
||||
$record['datetime']->getTimestamp() . ":ERROR:test\n" .
|
||||
$record2['datetime']->getTimestamp() . ":CRITICAL:test\n",
|
||||
file_get_contents(sys_get_temp_dir() . '/monolog_dedup.log')
|
||||
);
|
||||
$this->assertTrue($test->hasErrorRecords());
|
||||
$this->assertTrue($test->hasCriticalRecords());
|
||||
$this->assertFalse($test->hasWarningRecords());
|
||||
}
|
||||
|
||||
public static function tearDownAfterClass()
|
||||
{
|
||||
@unlink(sys_get_temp_dir().'/monolog_dedup.log');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
|
||||
class DoctrineCouchDBHandlerTest extends TestCase
|
||||
{
|
||||
protected function setup()
|
||||
{
|
||||
if (!class_exists('Doctrine\CouchDB\CouchDBClient')) {
|
||||
$this->markTestSkipped('The "doctrine/couchdb" package is not installed');
|
||||
}
|
||||
}
|
||||
|
||||
public function testHandle()
|
||||
{
|
||||
$client = $this->getMockBuilder('Doctrine\\CouchDB\\CouchDBClient')
|
||||
->setMethods(array('postDocument'))
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34));
|
||||
|
||||
$expected = array(
|
||||
'message' => 'test',
|
||||
'context' => array('data' => '[object] (stdClass: {})', 'foo' => 34),
|
||||
'level' => Logger::WARNING,
|
||||
'level_name' => 'WARNING',
|
||||
'channel' => 'test',
|
||||
'datetime' => $record['datetime']->format('Y-m-d H:i:s'),
|
||||
'extra' => array(),
|
||||
);
|
||||
|
||||
$client->expects($this->once())
|
||||
->method('postDocument')
|
||||
->with($expected);
|
||||
|
||||
$handler = new DoctrineCouchDBHandler($client);
|
||||
$handler->handle($record);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
|
||||
class DynamoDbHandlerTest extends TestCase
|
||||
{
|
||||
private $client;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
if (!class_exists('Aws\DynamoDb\DynamoDbClient')) {
|
||||
$this->markTestSkipped('aws/aws-sdk-php not installed');
|
||||
}
|
||||
|
||||
$this->client = $this->getMockBuilder('Aws\DynamoDb\DynamoDbClient')
|
||||
->setMethods(array('formatAttributes', '__call'))
|
||||
->disableOriginalConstructor()->getMock();
|
||||
}
|
||||
|
||||
public function testConstruct()
|
||||
{
|
||||
$this->assertInstanceOf('Monolog\Handler\DynamoDbHandler', new DynamoDbHandler($this->client, 'foo'));
|
||||
}
|
||||
|
||||
public function testInterface()
|
||||
{
|
||||
$this->assertInstanceOf('Monolog\Handler\HandlerInterface', new DynamoDbHandler($this->client, 'foo'));
|
||||
}
|
||||
|
||||
public function testGetFormatter()
|
||||
{
|
||||
$handler = new DynamoDbHandler($this->client, 'foo');
|
||||
$this->assertInstanceOf('Monolog\Formatter\ScalarFormatter', $handler->getFormatter());
|
||||
}
|
||||
|
||||
public function testHandle()
|
||||
{
|
||||
$record = $this->getRecord();
|
||||
$formatter = $this->getMock('Monolog\Formatter\FormatterInterface');
|
||||
$formatted = array('foo' => 1, 'bar' => 2);
|
||||
$handler = new DynamoDbHandler($this->client, 'foo');
|
||||
$handler->setFormatter($formatter);
|
||||
|
||||
$isV3 = defined('Aws\Sdk::VERSION') && version_compare(\Aws\Sdk::VERSION, '3.0', '>=');
|
||||
if ($isV3) {
|
||||
$expFormatted = array('foo' => array('N' => 1), 'bar' => array('N' => 2));
|
||||
} else {
|
||||
$expFormatted = $formatted;
|
||||
}
|
||||
|
||||
$formatter
|
||||
->expects($this->once())
|
||||
->method('format')
|
||||
->with($record)
|
||||
->will($this->returnValue($formatted));
|
||||
$this->client
|
||||
->expects($isV3 ? $this->never() : $this->once())
|
||||
->method('formatAttributes')
|
||||
->with($this->isType('array'))
|
||||
->will($this->returnValue($formatted));
|
||||
$this->client
|
||||
->expects($this->once())
|
||||
->method('__call')
|
||||
->with('putItem', array(array(
|
||||
'TableName' => 'foo',
|
||||
'Item' => $expFormatted,
|
||||
)));
|
||||
|
||||
$handler->handle($record);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\Formatter\ElasticaFormatter;
|
||||
use Monolog\Formatter\NormalizerFormatter;
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
use Elastica\Client;
|
||||
use Elastica\Request;
|
||||
use Elastica\Response;
|
||||
|
||||
class ElasticSearchHandlerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var Client mock
|
||||
*/
|
||||
protected $client;
|
||||
|
||||
/**
|
||||
* @var array Default handler options
|
||||
*/
|
||||
protected $options = array(
|
||||
'index' => 'my_index',
|
||||
'type' => 'doc_type',
|
||||
);
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
// Elastica lib required
|
||||
if (!class_exists("Elastica\Client")) {
|
||||
$this->markTestSkipped("ruflin/elastica not installed");
|
||||
}
|
||||
|
||||
// base mock Elastica Client object
|
||||
$this->client = $this->getMockBuilder('Elastica\Client')
|
||||
->setMethods(array('addDocuments'))
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\ElasticSearchHandler::write
|
||||
* @covers Monolog\Handler\ElasticSearchHandler::handleBatch
|
||||
* @covers Monolog\Handler\ElasticSearchHandler::bulkSend
|
||||
* @covers Monolog\Handler\ElasticSearchHandler::getDefaultFormatter
|
||||
*/
|
||||
public function testHandle()
|
||||
{
|
||||
// log message
|
||||
$msg = array(
|
||||
'level' => Logger::ERROR,
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => 'meh',
|
||||
'context' => array('foo' => 7, 'bar', 'class' => new \stdClass),
|
||||
'datetime' => new \DateTime("@0"),
|
||||
'extra' => array(),
|
||||
'message' => 'log',
|
||||
);
|
||||
|
||||
// format expected result
|
||||
$formatter = new ElasticaFormatter($this->options['index'], $this->options['type']);
|
||||
$expected = array($formatter->format($msg));
|
||||
|
||||
// setup ES client mock
|
||||
$this->client->expects($this->any())
|
||||
->method('addDocuments')
|
||||
->with($expected);
|
||||
|
||||
// perform tests
|
||||
$handler = new ElasticSearchHandler($this->client, $this->options);
|
||||
$handler->handle($msg);
|
||||
$handler->handleBatch(array($msg));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\ElasticSearchHandler::setFormatter
|
||||
*/
|
||||
public function testSetFormatter()
|
||||
{
|
||||
$handler = new ElasticSearchHandler($this->client);
|
||||
$formatter = new ElasticaFormatter('index_new', 'type_new');
|
||||
$handler->setFormatter($formatter);
|
||||
$this->assertInstanceOf('Monolog\Formatter\ElasticaFormatter', $handler->getFormatter());
|
||||
$this->assertEquals('index_new', $handler->getFormatter()->getIndex());
|
||||
$this->assertEquals('type_new', $handler->getFormatter()->getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\ElasticSearchHandler::setFormatter
|
||||
* @expectedException InvalidArgumentException
|
||||
* @expectedExceptionMessage ElasticSearchHandler is only compatible with ElasticaFormatter
|
||||
*/
|
||||
public function testSetFormatterInvalid()
|
||||
{
|
||||
$handler = new ElasticSearchHandler($this->client);
|
||||
$formatter = new NormalizerFormatter();
|
||||
$handler->setFormatter($formatter);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\ElasticSearchHandler::__construct
|
||||
* @covers Monolog\Handler\ElasticSearchHandler::getOptions
|
||||
*/
|
||||
public function testOptions()
|
||||
{
|
||||
$expected = array(
|
||||
'index' => $this->options['index'],
|
||||
'type' => $this->options['type'],
|
||||
'ignore_error' => false,
|
||||
);
|
||||
$handler = new ElasticSearchHandler($this->client, $this->options);
|
||||
$this->assertEquals($expected, $handler->getOptions());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\ElasticSearchHandler::bulkSend
|
||||
* @dataProvider providerTestConnectionErrors
|
||||
*/
|
||||
public function testConnectionErrors($ignore, $expectedError)
|
||||
{
|
||||
$clientOpts = array('host' => '127.0.0.1', 'port' => 1);
|
||||
$client = new Client($clientOpts);
|
||||
$handlerOpts = array('ignore_error' => $ignore);
|
||||
$handler = new ElasticSearchHandler($client, $handlerOpts);
|
||||
|
||||
if ($expectedError) {
|
||||
$this->setExpectedException($expectedError[0], $expectedError[1]);
|
||||
$handler->handle($this->getRecord());
|
||||
} else {
|
||||
$this->assertFalse($handler->handle($this->getRecord()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function providerTestConnectionErrors()
|
||||
{
|
||||
return array(
|
||||
array(false, array('RuntimeException', 'Error sending messages to Elasticsearch')),
|
||||
array(true, false),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Integration test using localhost Elastic Search server
|
||||
*
|
||||
* @covers Monolog\Handler\ElasticSearchHandler::__construct
|
||||
* @covers Monolog\Handler\ElasticSearchHandler::handleBatch
|
||||
* @covers Monolog\Handler\ElasticSearchHandler::bulkSend
|
||||
* @covers Monolog\Handler\ElasticSearchHandler::getDefaultFormatter
|
||||
*/
|
||||
public function testHandleIntegration()
|
||||
{
|
||||
$msg = array(
|
||||
'level' => Logger::ERROR,
|
||||
'level_name' => 'ERROR',
|
||||
'channel' => 'meh',
|
||||
'context' => array('foo' => 7, 'bar', 'class' => new \stdClass),
|
||||
'datetime' => new \DateTime("@0"),
|
||||
'extra' => array(),
|
||||
'message' => 'log',
|
||||
);
|
||||
|
||||
$expected = $msg;
|
||||
$expected['datetime'] = $msg['datetime']->format(\DateTime::ISO8601);
|
||||
$expected['context'] = array(
|
||||
'class' => '[object] (stdClass: {})',
|
||||
'foo' => 7,
|
||||
0 => 'bar',
|
||||
);
|
||||
|
||||
$client = new Client();
|
||||
$handler = new ElasticSearchHandler($client, $this->options);
|
||||
try {
|
||||
$handler->handleBatch(array($msg));
|
||||
} catch (\RuntimeException $e) {
|
||||
$this->markTestSkipped("Cannot connect to Elastic Search server on localhost");
|
||||
}
|
||||
|
||||
// check document id from ES server response
|
||||
$documentId = $this->getCreatedDocId($client->getLastResponse());
|
||||
$this->assertNotEmpty($documentId, 'No elastic document id received');
|
||||
|
||||
// retrieve document source from ES and validate
|
||||
$document = $this->getDocSourceFromElastic(
|
||||
$client,
|
||||
$this->options['index'],
|
||||
$this->options['type'],
|
||||
$documentId
|
||||
);
|
||||
$this->assertEquals($expected, $document);
|
||||
|
||||
// remove test index from ES
|
||||
$client->request("/{$this->options['index']}", Request::DELETE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return last created document id from ES response
|
||||
* @param Response $response Elastica Response object
|
||||
* @return string|null
|
||||
*/
|
||||
protected function getCreatedDocId(Response $response)
|
||||
{
|
||||
$data = $response->getData();
|
||||
if (!empty($data['items'][0]['create']['_id'])) {
|
||||
return $data['items'][0]['create']['_id'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve document by id from Elasticsearch
|
||||
* @param Client $client Elastica client
|
||||
* @param string $index
|
||||
* @param string $type
|
||||
* @param string $documentId
|
||||
* @return array
|
||||
*/
|
||||
protected function getDocSourceFromElastic(Client $client, $index, $type, $documentId)
|
||||
{
|
||||
$resp = $client->request("/{$index}/{$type}/{$documentId}", Request::GET);
|
||||
$data = $resp->getData();
|
||||
if (!empty($data['_source'])) {
|
||||
return $data['_source'];
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
use Monolog\Formatter\LineFormatter;
|
||||
|
||||
function error_log()
|
||||
{
|
||||
$GLOBALS['error_log'][] = func_get_args();
|
||||
}
|
||||
|
||||
class ErrorLogHandlerTest extends TestCase
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
$GLOBALS['error_log'] = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\ErrorLogHandler::__construct
|
||||
* @expectedException InvalidArgumentException
|
||||
* @expectedExceptionMessage The given message type "42" is not supported
|
||||
*/
|
||||
public function testShouldNotAcceptAnInvalidTypeOnContructor()
|
||||
{
|
||||
new ErrorLogHandler(42);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\ErrorLogHandler::write
|
||||
*/
|
||||
public function testShouldLogMessagesUsingErrorLogFuncion()
|
||||
{
|
||||
$type = ErrorLogHandler::OPERATING_SYSTEM;
|
||||
$handler = new ErrorLogHandler($type);
|
||||
$handler->setFormatter(new LineFormatter('%channel%.%level_name%: %message% %context% %extra%', null, true));
|
||||
$handler->handle($this->getRecord(Logger::ERROR, "Foo\nBar\r\n\r\nBaz"));
|
||||
|
||||
$this->assertSame("test.ERROR: Foo\nBar\r\n\r\nBaz [] []", $GLOBALS['error_log'][0][0]);
|
||||
$this->assertSame($GLOBALS['error_log'][0][1], $type);
|
||||
|
||||
$handler = new ErrorLogHandler($type, Logger::DEBUG, true, true);
|
||||
$handler->setFormatter(new LineFormatter(null, null, true));
|
||||
$handler->handle($this->getRecord(Logger::ERROR, "Foo\nBar\r\n\r\nBaz"));
|
||||
|
||||
$this->assertStringMatchesFormat('[%s] test.ERROR: Foo', $GLOBALS['error_log'][1][0]);
|
||||
$this->assertSame($GLOBALS['error_log'][1][1], $type);
|
||||
|
||||
$this->assertStringMatchesFormat('Bar', $GLOBALS['error_log'][2][0]);
|
||||
$this->assertSame($GLOBALS['error_log'][2][1], $type);
|
||||
|
||||
$this->assertStringMatchesFormat('Baz [] []', $GLOBALS['error_log'][3][0]);
|
||||
$this->assertSame($GLOBALS['error_log'][3][1], $type);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Monolog\TestCase;
|
||||
|
||||
class FilterHandlerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers Monolog\Handler\FilterHandler::isHandling
|
||||
*/
|
||||
public function testIsHandling()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
$handler = new FilterHandler($test, Logger::INFO, Logger::NOTICE);
|
||||
$this->assertFalse($handler->isHandling($this->getRecord(Logger::DEBUG)));
|
||||
$this->assertTrue($handler->isHandling($this->getRecord(Logger::INFO)));
|
||||
$this->assertTrue($handler->isHandling($this->getRecord(Logger::NOTICE)));
|
||||
$this->assertFalse($handler->isHandling($this->getRecord(Logger::WARNING)));
|
||||
$this->assertFalse($handler->isHandling($this->getRecord(Logger::ERROR)));
|
||||
$this->assertFalse($handler->isHandling($this->getRecord(Logger::CRITICAL)));
|
||||
$this->assertFalse($handler->isHandling($this->getRecord(Logger::ALERT)));
|
||||
$this->assertFalse($handler->isHandling($this->getRecord(Logger::EMERGENCY)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\FilterHandler::handle
|
||||
* @covers Monolog\Handler\FilterHandler::setAcceptedLevels
|
||||
* @covers Monolog\Handler\FilterHandler::isHandling
|
||||
*/
|
||||
public function testHandleProcessOnlyNeededLevels()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
$handler = new FilterHandler($test, Logger::INFO, Logger::NOTICE);
|
||||
|
||||
$handler->handle($this->getRecord(Logger::DEBUG));
|
||||
$this->assertFalse($test->hasDebugRecords());
|
||||
|
||||
$handler->handle($this->getRecord(Logger::INFO));
|
||||
$this->assertTrue($test->hasInfoRecords());
|
||||
$handler->handle($this->getRecord(Logger::NOTICE));
|
||||
$this->assertTrue($test->hasNoticeRecords());
|
||||
|
||||
$handler->handle($this->getRecord(Logger::WARNING));
|
||||
$this->assertFalse($test->hasWarningRecords());
|
||||
$handler->handle($this->getRecord(Logger::ERROR));
|
||||
$this->assertFalse($test->hasErrorRecords());
|
||||
$handler->handle($this->getRecord(Logger::CRITICAL));
|
||||
$this->assertFalse($test->hasCriticalRecords());
|
||||
$handler->handle($this->getRecord(Logger::ALERT));
|
||||
$this->assertFalse($test->hasAlertRecords());
|
||||
$handler->handle($this->getRecord(Logger::EMERGENCY));
|
||||
$this->assertFalse($test->hasEmergencyRecords());
|
||||
|
||||
$test = new TestHandler();
|
||||
$handler = new FilterHandler($test, array(Logger::INFO, Logger::ERROR));
|
||||
|
||||
$handler->handle($this->getRecord(Logger::DEBUG));
|
||||
$this->assertFalse($test->hasDebugRecords());
|
||||
$handler->handle($this->getRecord(Logger::INFO));
|
||||
$this->assertTrue($test->hasInfoRecords());
|
||||
$handler->handle($this->getRecord(Logger::NOTICE));
|
||||
$this->assertFalse($test->hasNoticeRecords());
|
||||
$handler->handle($this->getRecord(Logger::ERROR));
|
||||
$this->assertTrue($test->hasErrorRecords());
|
||||
$handler->handle($this->getRecord(Logger::CRITICAL));
|
||||
$this->assertFalse($test->hasCriticalRecords());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\FilterHandler::setAcceptedLevels
|
||||
* @covers Monolog\Handler\FilterHandler::getAcceptedLevels
|
||||
*/
|
||||
public function testAcceptedLevelApi()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
$handler = new FilterHandler($test);
|
||||
|
||||
$levels = array(Logger::INFO, Logger::ERROR);
|
||||
$handler->setAcceptedLevels($levels);
|
||||
$this->assertSame($levels, $handler->getAcceptedLevels());
|
||||
|
||||
$handler->setAcceptedLevels(array('info', 'error'));
|
||||
$this->assertSame($levels, $handler->getAcceptedLevels());
|
||||
|
||||
$levels = array(Logger::CRITICAL, Logger::ALERT, Logger::EMERGENCY);
|
||||
$handler->setAcceptedLevels(Logger::CRITICAL, Logger::EMERGENCY);
|
||||
$this->assertSame($levels, $handler->getAcceptedLevels());
|
||||
|
||||
$handler->setAcceptedLevels('critical', 'emergency');
|
||||
$this->assertSame($levels, $handler->getAcceptedLevels());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\FilterHandler::handle
|
||||
*/
|
||||
public function testHandleUsesProcessors()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
$handler = new FilterHandler($test, Logger::DEBUG, Logger::EMERGENCY);
|
||||
$handler->pushProcessor(
|
||||
function ($record) {
|
||||
$record['extra']['foo'] = true;
|
||||
|
||||
return $record;
|
||||
}
|
||||
);
|
||||
$handler->handle($this->getRecord(Logger::WARNING));
|
||||
$this->assertTrue($test->hasWarningRecords());
|
||||
$records = $test->getRecords();
|
||||
$this->assertTrue($records[0]['extra']['foo']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\FilterHandler::handle
|
||||
*/
|
||||
public function testHandleRespectsBubble()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
|
||||
$handler = new FilterHandler($test, Logger::INFO, Logger::NOTICE, false);
|
||||
$this->assertTrue($handler->handle($this->getRecord(Logger::INFO)));
|
||||
$this->assertFalse($handler->handle($this->getRecord(Logger::WARNING)));
|
||||
|
||||
$handler = new FilterHandler($test, Logger::INFO, Logger::NOTICE, true);
|
||||
$this->assertFalse($handler->handle($this->getRecord(Logger::INFO)));
|
||||
$this->assertFalse($handler->handle($this->getRecord(Logger::WARNING)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\FilterHandler::handle
|
||||
*/
|
||||
public function testHandleWithCallback()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
$handler = new FilterHandler(
|
||||
function ($record, $handler) use ($test) {
|
||||
return $test;
|
||||
}, Logger::INFO, Logger::NOTICE, false
|
||||
);
|
||||
$handler->handle($this->getRecord(Logger::DEBUG));
|
||||
$handler->handle($this->getRecord(Logger::INFO));
|
||||
$this->assertFalse($test->hasDebugRecords());
|
||||
$this->assertTrue($test->hasInfoRecords());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\FilterHandler::handle
|
||||
* @expectedException \RuntimeException
|
||||
*/
|
||||
public function testHandleWithBadCallbackThrowsException()
|
||||
{
|
||||
$handler = new FilterHandler(
|
||||
function ($record, $handler) {
|
||||
return 'foo';
|
||||
}
|
||||
);
|
||||
$handler->handle($this->getRecord(Logger::WARNING));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,279 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy;
|
||||
use Monolog\Handler\FingersCrossed\ChannelLevelActivationStrategy;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
class FingersCrossedHandlerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers Monolog\Handler\FingersCrossedHandler::__construct
|
||||
* @covers Monolog\Handler\FingersCrossedHandler::handle
|
||||
* @covers Monolog\Handler\FingersCrossedHandler::activate
|
||||
*/
|
||||
public function testHandleBuffers()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
$handler = new FingersCrossedHandler($test);
|
||||
$handler->handle($this->getRecord(Logger::DEBUG));
|
||||
$handler->handle($this->getRecord(Logger::INFO));
|
||||
$this->assertFalse($test->hasDebugRecords());
|
||||
$this->assertFalse($test->hasInfoRecords());
|
||||
$handler->handle($this->getRecord(Logger::WARNING));
|
||||
$handler->close();
|
||||
$this->assertTrue($test->hasInfoRecords());
|
||||
$this->assertTrue(count($test->getRecords()) === 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\FingersCrossedHandler::handle
|
||||
* @covers Monolog\Handler\FingersCrossedHandler::activate
|
||||
*/
|
||||
public function testHandleStopsBufferingAfterTrigger()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
$handler = new FingersCrossedHandler($test);
|
||||
$handler->handle($this->getRecord(Logger::WARNING));
|
||||
$handler->handle($this->getRecord(Logger::DEBUG));
|
||||
$handler->close();
|
||||
$this->assertTrue($test->hasWarningRecords());
|
||||
$this->assertTrue($test->hasDebugRecords());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\FingersCrossedHandler::handle
|
||||
* @covers Monolog\Handler\FingersCrossedHandler::activate
|
||||
* @covers Monolog\Handler\FingersCrossedHandler::reset
|
||||
*/
|
||||
public function testHandleRestartBufferingAfterReset()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
$handler = new FingersCrossedHandler($test);
|
||||
$handler->handle($this->getRecord(Logger::WARNING));
|
||||
$handler->handle($this->getRecord(Logger::DEBUG));
|
||||
$handler->reset();
|
||||
$handler->handle($this->getRecord(Logger::INFO));
|
||||
$handler->close();
|
||||
$this->assertTrue($test->hasWarningRecords());
|
||||
$this->assertTrue($test->hasDebugRecords());
|
||||
$this->assertFalse($test->hasInfoRecords());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\FingersCrossedHandler::handle
|
||||
* @covers Monolog\Handler\FingersCrossedHandler::activate
|
||||
*/
|
||||
public function testHandleRestartBufferingAfterBeingTriggeredWhenStopBufferingIsDisabled()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
$handler = new FingersCrossedHandler($test, Logger::WARNING, 0, false, false);
|
||||
$handler->handle($this->getRecord(Logger::DEBUG));
|
||||
$handler->handle($this->getRecord(Logger::WARNING));
|
||||
$handler->handle($this->getRecord(Logger::INFO));
|
||||
$handler->close();
|
||||
$this->assertTrue($test->hasWarningRecords());
|
||||
$this->assertTrue($test->hasDebugRecords());
|
||||
$this->assertFalse($test->hasInfoRecords());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\FingersCrossedHandler::handle
|
||||
* @covers Monolog\Handler\FingersCrossedHandler::activate
|
||||
*/
|
||||
public function testHandleBufferLimit()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
$handler = new FingersCrossedHandler($test, Logger::WARNING, 2);
|
||||
$handler->handle($this->getRecord(Logger::DEBUG));
|
||||
$handler->handle($this->getRecord(Logger::DEBUG));
|
||||
$handler->handle($this->getRecord(Logger::INFO));
|
||||
$handler->handle($this->getRecord(Logger::WARNING));
|
||||
$this->assertTrue($test->hasWarningRecords());
|
||||
$this->assertTrue($test->hasInfoRecords());
|
||||
$this->assertFalse($test->hasDebugRecords());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\FingersCrossedHandler::handle
|
||||
* @covers Monolog\Handler\FingersCrossedHandler::activate
|
||||
*/
|
||||
public function testHandleWithCallback()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
$handler = new FingersCrossedHandler(function ($record, $handler) use ($test) {
|
||||
return $test;
|
||||
});
|
||||
$handler->handle($this->getRecord(Logger::DEBUG));
|
||||
$handler->handle($this->getRecord(Logger::INFO));
|
||||
$this->assertFalse($test->hasDebugRecords());
|
||||
$this->assertFalse($test->hasInfoRecords());
|
||||
$handler->handle($this->getRecord(Logger::WARNING));
|
||||
$this->assertTrue($test->hasInfoRecords());
|
||||
$this->assertTrue(count($test->getRecords()) === 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\FingersCrossedHandler::handle
|
||||
* @covers Monolog\Handler\FingersCrossedHandler::activate
|
||||
* @expectedException RuntimeException
|
||||
*/
|
||||
public function testHandleWithBadCallbackThrowsException()
|
||||
{
|
||||
$handler = new FingersCrossedHandler(function ($record, $handler) {
|
||||
return 'foo';
|
||||
});
|
||||
$handler->handle($this->getRecord(Logger::WARNING));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\FingersCrossedHandler::isHandling
|
||||
*/
|
||||
public function testIsHandlingAlways()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
$handler = new FingersCrossedHandler($test, Logger::ERROR);
|
||||
$this->assertTrue($handler->isHandling($this->getRecord(Logger::DEBUG)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\FingersCrossedHandler::__construct
|
||||
* @covers Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy::__construct
|
||||
* @covers Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy::isHandlerActivated
|
||||
*/
|
||||
public function testErrorLevelActivationStrategy()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
$handler = new FingersCrossedHandler($test, new ErrorLevelActivationStrategy(Logger::WARNING));
|
||||
$handler->handle($this->getRecord(Logger::DEBUG));
|
||||
$this->assertFalse($test->hasDebugRecords());
|
||||
$handler->handle($this->getRecord(Logger::WARNING));
|
||||
$this->assertTrue($test->hasDebugRecords());
|
||||
$this->assertTrue($test->hasWarningRecords());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\FingersCrossedHandler::__construct
|
||||
* @covers Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy::__construct
|
||||
* @covers Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy::isHandlerActivated
|
||||
*/
|
||||
public function testErrorLevelActivationStrategyWithPsrLevel()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
$handler = new FingersCrossedHandler($test, new ErrorLevelActivationStrategy('warning'));
|
||||
$handler->handle($this->getRecord(Logger::DEBUG));
|
||||
$this->assertFalse($test->hasDebugRecords());
|
||||
$handler->handle($this->getRecord(Logger::WARNING));
|
||||
$this->assertTrue($test->hasDebugRecords());
|
||||
$this->assertTrue($test->hasWarningRecords());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\FingersCrossedHandler::__construct
|
||||
* @covers Monolog\Handler\FingersCrossedHandler::activate
|
||||
*/
|
||||
public function testOverrideActivationStrategy()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
$handler = new FingersCrossedHandler($test, new ErrorLevelActivationStrategy('warning'));
|
||||
$handler->handle($this->getRecord(Logger::DEBUG));
|
||||
$this->assertFalse($test->hasDebugRecords());
|
||||
$handler->activate();
|
||||
$this->assertTrue($test->hasDebugRecords());
|
||||
$handler->handle($this->getRecord(Logger::INFO));
|
||||
$this->assertTrue($test->hasInfoRecords());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\FingersCrossed\ChannelLevelActivationStrategy::__construct
|
||||
* @covers Monolog\Handler\FingersCrossed\ChannelLevelActivationStrategy::isHandlerActivated
|
||||
*/
|
||||
public function testChannelLevelActivationStrategy()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
$handler = new FingersCrossedHandler($test, new ChannelLevelActivationStrategy(Logger::ERROR, array('othertest' => Logger::DEBUG)));
|
||||
$handler->handle($this->getRecord(Logger::WARNING));
|
||||
$this->assertFalse($test->hasWarningRecords());
|
||||
$record = $this->getRecord(Logger::DEBUG);
|
||||
$record['channel'] = 'othertest';
|
||||
$handler->handle($record);
|
||||
$this->assertTrue($test->hasDebugRecords());
|
||||
$this->assertTrue($test->hasWarningRecords());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\FingersCrossed\ChannelLevelActivationStrategy::__construct
|
||||
* @covers Monolog\Handler\FingersCrossed\ChannelLevelActivationStrategy::isHandlerActivated
|
||||
*/
|
||||
public function testChannelLevelActivationStrategyWithPsrLevels()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
$handler = new FingersCrossedHandler($test, new ChannelLevelActivationStrategy('error', array('othertest' => 'debug')));
|
||||
$handler->handle($this->getRecord(Logger::WARNING));
|
||||
$this->assertFalse($test->hasWarningRecords());
|
||||
$record = $this->getRecord(Logger::DEBUG);
|
||||
$record['channel'] = 'othertest';
|
||||
$handler->handle($record);
|
||||
$this->assertTrue($test->hasDebugRecords());
|
||||
$this->assertTrue($test->hasWarningRecords());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\FingersCrossedHandler::handle
|
||||
* @covers Monolog\Handler\FingersCrossedHandler::activate
|
||||
*/
|
||||
public function testHandleUsesProcessors()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
$handler = new FingersCrossedHandler($test, Logger::INFO);
|
||||
$handler->pushProcessor(function ($record) {
|
||||
$record['extra']['foo'] = true;
|
||||
|
||||
return $record;
|
||||
});
|
||||
$handler->handle($this->getRecord(Logger::WARNING));
|
||||
$this->assertTrue($test->hasWarningRecords());
|
||||
$records = $test->getRecords();
|
||||
$this->assertTrue($records[0]['extra']['foo']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\FingersCrossedHandler::close
|
||||
*/
|
||||
public function testPassthruOnClose()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
$handler = new FingersCrossedHandler($test, new ErrorLevelActivationStrategy(Logger::WARNING), 0, true, true, Logger::INFO);
|
||||
$handler->handle($this->getRecord(Logger::DEBUG));
|
||||
$handler->handle($this->getRecord(Logger::INFO));
|
||||
$handler->close();
|
||||
$this->assertFalse($test->hasDebugRecords());
|
||||
$this->assertTrue($test->hasInfoRecords());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\FingersCrossedHandler::close
|
||||
*/
|
||||
public function testPsrLevelPassthruOnClose()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
$handler = new FingersCrossedHandler($test, new ErrorLevelActivationStrategy(Logger::WARNING), 0, true, true, LogLevel::INFO);
|
||||
$handler->handle($this->getRecord(Logger::DEBUG));
|
||||
$handler->handle($this->getRecord(Logger::INFO));
|
||||
$handler->close();
|
||||
$this->assertFalse($test->hasDebugRecords());
|
||||
$this->assertTrue($test->hasInfoRecords());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\FirePHPHandler
|
||||
*/
|
||||
class FirePHPHandlerTest extends TestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
TestFirePHPHandler::reset();
|
||||
$_SERVER['HTTP_USER_AGENT'] = 'Monolog Test; FirePHP/1.0';
|
||||
}
|
||||
|
||||
public function testHeaders()
|
||||
{
|
||||
$handler = new TestFirePHPHandler;
|
||||
$handler->setFormatter($this->getIdentityFormatter());
|
||||
$handler->handle($this->getRecord(Logger::DEBUG));
|
||||
$handler->handle($this->getRecord(Logger::WARNING));
|
||||
|
||||
$expected = array(
|
||||
'X-Wf-Protocol-1' => 'http://meta.wildfirehq.org/Protocol/JsonStream/0.2',
|
||||
'X-Wf-1-Structure-1' => 'http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1',
|
||||
'X-Wf-1-Plugin-1' => 'http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.3',
|
||||
'X-Wf-1-1-1-1' => 'test',
|
||||
'X-Wf-1-1-1-2' => 'test',
|
||||
);
|
||||
|
||||
$this->assertEquals($expected, $handler->getHeaders());
|
||||
}
|
||||
|
||||
public function testConcurrentHandlers()
|
||||
{
|
||||
$handler = new TestFirePHPHandler;
|
||||
$handler->setFormatter($this->getIdentityFormatter());
|
||||
$handler->handle($this->getRecord(Logger::DEBUG));
|
||||
$handler->handle($this->getRecord(Logger::WARNING));
|
||||
|
||||
$handler2 = new TestFirePHPHandler;
|
||||
$handler2->setFormatter($this->getIdentityFormatter());
|
||||
$handler2->handle($this->getRecord(Logger::DEBUG));
|
||||
$handler2->handle($this->getRecord(Logger::WARNING));
|
||||
|
||||
$expected = array(
|
||||
'X-Wf-Protocol-1' => 'http://meta.wildfirehq.org/Protocol/JsonStream/0.2',
|
||||
'X-Wf-1-Structure-1' => 'http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1',
|
||||
'X-Wf-1-Plugin-1' => 'http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.3',
|
||||
'X-Wf-1-1-1-1' => 'test',
|
||||
'X-Wf-1-1-1-2' => 'test',
|
||||
);
|
||||
|
||||
$expected2 = array(
|
||||
'X-Wf-1-1-1-3' => 'test',
|
||||
'X-Wf-1-1-1-4' => 'test',
|
||||
);
|
||||
|
||||
$this->assertEquals($expected, $handler->getHeaders());
|
||||
$this->assertEquals($expected2, $handler2->getHeaders());
|
||||
}
|
||||
}
|
||||
|
||||
class TestFirePHPHandler extends FirePHPHandler
|
||||
{
|
||||
protected $headers = array();
|
||||
|
||||
public static function reset()
|
||||
{
|
||||
self::$initialized = false;
|
||||
self::$sendHeaders = true;
|
||||
self::$messageIndex = 1;
|
||||
}
|
||||
|
||||
protected function sendHeader($header, $content)
|
||||
{
|
||||
$this->headers[$header] = $content;
|
||||
}
|
||||
|
||||
public function getHeaders()
|
||||
{
|
||||
return $this->headers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\Formatter\LineFormatter;
|
||||
use Monolog\Logger;
|
||||
use Monolog\TestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Monolog\Handler\FleepHookHandler
|
||||
*/
|
||||
class FleepHookHandlerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Default token to use in tests
|
||||
*/
|
||||
const TOKEN = '123abc';
|
||||
|
||||
/**
|
||||
* @var FleepHookHandler
|
||||
*/
|
||||
private $handler;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
if (!extension_loaded('openssl')) {
|
||||
$this->markTestSkipped('This test requires openssl extension to run');
|
||||
}
|
||||
|
||||
// Create instances of the handler and logger for convenience
|
||||
$this->handler = new FleepHookHandler(self::TOKEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::__construct
|
||||
*/
|
||||
public function testConstructorSetsExpectedDefaults()
|
||||
{
|
||||
$this->assertEquals(Logger::DEBUG, $this->handler->getLevel());
|
||||
$this->assertEquals(true, $this->handler->getBubble());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getDefaultFormatter
|
||||
*/
|
||||
public function testHandlerUsesLineFormatterWhichIgnoresEmptyArrays()
|
||||
{
|
||||
$record = array(
|
||||
'message' => 'msg',
|
||||
'context' => array(),
|
||||
'level' => Logger::DEBUG,
|
||||
'level_name' => Logger::getLevelName(Logger::DEBUG),
|
||||
'channel' => 'channel',
|
||||
'datetime' => new \DateTime(),
|
||||
'extra' => array(),
|
||||
);
|
||||
|
||||
$expectedFormatter = new LineFormatter(null, null, true, true);
|
||||
$expected = $expectedFormatter->format($record);
|
||||
|
||||
$handlerFormatter = $this->handler->getFormatter();
|
||||
$actual = $handlerFormatter->format($record);
|
||||
|
||||
$this->assertEquals($expected, $actual, 'Empty context and extra arrays should not be rendered');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::__construct
|
||||
*/
|
||||
public function testConnectionStringisConstructedCorrectly()
|
||||
{
|
||||
$this->assertEquals('ssl://' . FleepHookHandler::FLEEP_HOST . ':443', $this->handler->getConnectionString());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\Formatter\FlowdockFormatter;
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
|
||||
/**
|
||||
* @author Dominik Liebler <liebler.dominik@gmail.com>
|
||||
* @see https://www.hipchat.com/docs/api
|
||||
*/
|
||||
class FlowdockHandlerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var resource
|
||||
*/
|
||||
private $res;
|
||||
|
||||
/**
|
||||
* @var FlowdockHandler
|
||||
*/
|
||||
private $handler;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
if (!extension_loaded('openssl')) {
|
||||
$this->markTestSkipped('This test requires openssl to run');
|
||||
}
|
||||
}
|
||||
|
||||
public function testWriteHeader()
|
||||
{
|
||||
$this->createHandler();
|
||||
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
|
||||
fseek($this->res, 0);
|
||||
$content = fread($this->res, 1024);
|
||||
|
||||
$this->assertRegexp('/POST \/v1\/messages\/team_inbox\/.* HTTP\/1.1\\r\\nHost: api.flowdock.com\\r\\nContent-Type: application\/json\\r\\nContent-Length: \d{2,4}\\r\\n\\r\\n/', $content);
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testWriteHeader
|
||||
*/
|
||||
public function testWriteContent($content)
|
||||
{
|
||||
$this->assertRegexp('/"source":"test_source"/', $content);
|
||||
$this->assertRegexp('/"from_address":"source@test\.com"/', $content);
|
||||
}
|
||||
|
||||
private function createHandler($token = 'myToken')
|
||||
{
|
||||
$constructorArgs = array($token, Logger::DEBUG);
|
||||
$this->res = fopen('php://memory', 'a');
|
||||
$this->handler = $this->getMock(
|
||||
'\Monolog\Handler\FlowdockHandler',
|
||||
array('fsockopen', 'streamSetTimeout', 'closeSocket'),
|
||||
$constructorArgs
|
||||
);
|
||||
|
||||
$reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString');
|
||||
$reflectionProperty->setAccessible(true);
|
||||
$reflectionProperty->setValue($this->handler, 'localhost:1234');
|
||||
|
||||
$this->handler->expects($this->any())
|
||||
->method('fsockopen')
|
||||
->will($this->returnValue($this->res));
|
||||
$this->handler->expects($this->any())
|
||||
->method('streamSetTimeout')
|
||||
->will($this->returnValue(true));
|
||||
$this->handler->expects($this->any())
|
||||
->method('closeSocket')
|
||||
->will($this->returnValue(true));
|
||||
|
||||
$this->handler->setFormatter(new FlowdockFormatter('test_source', 'source@test.com'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Gelf\Message;
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
use Monolog\Formatter\GelfMessageFormatter;
|
||||
|
||||
class GelfHandlerLegacyTest extends TestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
if (!class_exists('Gelf\MessagePublisher') || !class_exists('Gelf\Message')) {
|
||||
$this->markTestSkipped("mlehner/gelf-php not installed");
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/GelfMockMessagePublisher.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\GelfHandler::__construct
|
||||
*/
|
||||
public function testConstruct()
|
||||
{
|
||||
$handler = new GelfHandler($this->getMessagePublisher());
|
||||
$this->assertInstanceOf('Monolog\Handler\GelfHandler', $handler);
|
||||
}
|
||||
|
||||
protected function getHandler($messagePublisher)
|
||||
{
|
||||
$handler = new GelfHandler($messagePublisher);
|
||||
|
||||
return $handler;
|
||||
}
|
||||
|
||||
protected function getMessagePublisher()
|
||||
{
|
||||
return new GelfMockMessagePublisher('localhost');
|
||||
}
|
||||
|
||||
public function testDebug()
|
||||
{
|
||||
$messagePublisher = $this->getMessagePublisher();
|
||||
$handler = $this->getHandler($messagePublisher);
|
||||
|
||||
$record = $this->getRecord(Logger::DEBUG, "A test debug message");
|
||||
$handler->handle($record);
|
||||
|
||||
$this->assertEquals(7, $messagePublisher->lastMessage->getLevel());
|
||||
$this->assertEquals('test', $messagePublisher->lastMessage->getFacility());
|
||||
$this->assertEquals($record['message'], $messagePublisher->lastMessage->getShortMessage());
|
||||
$this->assertEquals(null, $messagePublisher->lastMessage->getFullMessage());
|
||||
}
|
||||
|
||||
public function testWarning()
|
||||
{
|
||||
$messagePublisher = $this->getMessagePublisher();
|
||||
$handler = $this->getHandler($messagePublisher);
|
||||
|
||||
$record = $this->getRecord(Logger::WARNING, "A test warning message");
|
||||
$handler->handle($record);
|
||||
|
||||
$this->assertEquals(4, $messagePublisher->lastMessage->getLevel());
|
||||
$this->assertEquals('test', $messagePublisher->lastMessage->getFacility());
|
||||
$this->assertEquals($record['message'], $messagePublisher->lastMessage->getShortMessage());
|
||||
$this->assertEquals(null, $messagePublisher->lastMessage->getFullMessage());
|
||||
}
|
||||
|
||||
public function testInjectedGelfMessageFormatter()
|
||||
{
|
||||
$messagePublisher = $this->getMessagePublisher();
|
||||
$handler = $this->getHandler($messagePublisher);
|
||||
|
||||
$handler->setFormatter(new GelfMessageFormatter('mysystem', 'EXT', 'CTX'));
|
||||
|
||||
$record = $this->getRecord(Logger::WARNING, "A test warning message");
|
||||
$record['extra']['blarg'] = 'yep';
|
||||
$record['context']['from'] = 'logger';
|
||||
$handler->handle($record);
|
||||
|
||||
$this->assertEquals('mysystem', $messagePublisher->lastMessage->getHost());
|
||||
$this->assertArrayHasKey('_EXTblarg', $messagePublisher->lastMessage->toArray());
|
||||
$this->assertArrayHasKey('_CTXfrom', $messagePublisher->lastMessage->toArray());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Gelf\Message;
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
use Monolog\Formatter\GelfMessageFormatter;
|
||||
|
||||
class GelfHandlerTest extends TestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
if (!class_exists('Gelf\Publisher') || !class_exists('Gelf\Message')) {
|
||||
$this->markTestSkipped("graylog2/gelf-php not installed");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\GelfHandler::__construct
|
||||
*/
|
||||
public function testConstruct()
|
||||
{
|
||||
$handler = new GelfHandler($this->getMessagePublisher());
|
||||
$this->assertInstanceOf('Monolog\Handler\GelfHandler', $handler);
|
||||
}
|
||||
|
||||
protected function getHandler($messagePublisher)
|
||||
{
|
||||
$handler = new GelfHandler($messagePublisher);
|
||||
|
||||
return $handler;
|
||||
}
|
||||
|
||||
protected function getMessagePublisher()
|
||||
{
|
||||
return $this->getMock('Gelf\Publisher', array('publish'), array(), '', false);
|
||||
}
|
||||
|
||||
public function testDebug()
|
||||
{
|
||||
$record = $this->getRecord(Logger::DEBUG, "A test debug message");
|
||||
$expectedMessage = new Message();
|
||||
$expectedMessage
|
||||
->setLevel(7)
|
||||
->setFacility("test")
|
||||
->setShortMessage($record['message'])
|
||||
->setTimestamp($record['datetime'])
|
||||
;
|
||||
|
||||
$messagePublisher = $this->getMessagePublisher();
|
||||
$messagePublisher->expects($this->once())
|
||||
->method('publish')
|
||||
->with($expectedMessage);
|
||||
|
||||
$handler = $this->getHandler($messagePublisher);
|
||||
|
||||
$handler->handle($record);
|
||||
}
|
||||
|
||||
public function testWarning()
|
||||
{
|
||||
$record = $this->getRecord(Logger::WARNING, "A test warning message");
|
||||
$expectedMessage = new Message();
|
||||
$expectedMessage
|
||||
->setLevel(4)
|
||||
->setFacility("test")
|
||||
->setShortMessage($record['message'])
|
||||
->setTimestamp($record['datetime'])
|
||||
;
|
||||
|
||||
$messagePublisher = $this->getMessagePublisher();
|
||||
$messagePublisher->expects($this->once())
|
||||
->method('publish')
|
||||
->with($expectedMessage);
|
||||
|
||||
$handler = $this->getHandler($messagePublisher);
|
||||
|
||||
$handler->handle($record);
|
||||
}
|
||||
|
||||
public function testInjectedGelfMessageFormatter()
|
||||
{
|
||||
$record = $this->getRecord(Logger::WARNING, "A test warning message");
|
||||
$record['extra']['blarg'] = 'yep';
|
||||
$record['context']['from'] = 'logger';
|
||||
|
||||
$expectedMessage = new Message();
|
||||
$expectedMessage
|
||||
->setLevel(4)
|
||||
->setFacility("test")
|
||||
->setHost("mysystem")
|
||||
->setShortMessage($record['message'])
|
||||
->setTimestamp($record['datetime'])
|
||||
->setAdditional("EXTblarg", 'yep')
|
||||
->setAdditional("CTXfrom", 'logger')
|
||||
;
|
||||
|
||||
$messagePublisher = $this->getMessagePublisher();
|
||||
$messagePublisher->expects($this->once())
|
||||
->method('publish')
|
||||
->with($expectedMessage);
|
||||
|
||||
$handler = $this->getHandler($messagePublisher);
|
||||
$handler->setFormatter(new GelfMessageFormatter('mysystem', 'EXT', 'CTX'));
|
||||
$handler->handle($record);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Gelf\MessagePublisher;
|
||||
use Gelf\Message;
|
||||
|
||||
class GelfMockMessagePublisher extends MessagePublisher
|
||||
{
|
||||
public function publish(Message $message)
|
||||
{
|
||||
$this->lastMessage = $message;
|
||||
}
|
||||
|
||||
public $lastMessage = null;
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
|
||||
class GroupHandlerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers Monolog\Handler\GroupHandler::__construct
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testConstructorOnlyTakesHandler()
|
||||
{
|
||||
new GroupHandler(array(new TestHandler(), "foo"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\GroupHandler::__construct
|
||||
* @covers Monolog\Handler\GroupHandler::handle
|
||||
*/
|
||||
public function testHandle()
|
||||
{
|
||||
$testHandlers = array(new TestHandler(), new TestHandler());
|
||||
$handler = new GroupHandler($testHandlers);
|
||||
$handler->handle($this->getRecord(Logger::DEBUG));
|
||||
$handler->handle($this->getRecord(Logger::INFO));
|
||||
foreach ($testHandlers as $test) {
|
||||
$this->assertTrue($test->hasDebugRecords());
|
||||
$this->assertTrue($test->hasInfoRecords());
|
||||
$this->assertTrue(count($test->getRecords()) === 2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\GroupHandler::handleBatch
|
||||
*/
|
||||
public function testHandleBatch()
|
||||
{
|
||||
$testHandlers = array(new TestHandler(), new TestHandler());
|
||||
$handler = new GroupHandler($testHandlers);
|
||||
$handler->handleBatch(array($this->getRecord(Logger::DEBUG), $this->getRecord(Logger::INFO)));
|
||||
foreach ($testHandlers as $test) {
|
||||
$this->assertTrue($test->hasDebugRecords());
|
||||
$this->assertTrue($test->hasInfoRecords());
|
||||
$this->assertTrue(count($test->getRecords()) === 2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\GroupHandler::isHandling
|
||||
*/
|
||||
public function testIsHandling()
|
||||
{
|
||||
$testHandlers = array(new TestHandler(Logger::ERROR), new TestHandler(Logger::WARNING));
|
||||
$handler = new GroupHandler($testHandlers);
|
||||
$this->assertTrue($handler->isHandling($this->getRecord(Logger::ERROR)));
|
||||
$this->assertTrue($handler->isHandling($this->getRecord(Logger::WARNING)));
|
||||
$this->assertFalse($handler->isHandling($this->getRecord(Logger::DEBUG)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\GroupHandler::handle
|
||||
*/
|
||||
public function testHandleUsesProcessors()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
$handler = new GroupHandler(array($test));
|
||||
$handler->pushProcessor(function ($record) {
|
||||
$record['extra']['foo'] = true;
|
||||
|
||||
return $record;
|
||||
});
|
||||
$handler->handle($this->getRecord(Logger::WARNING));
|
||||
$this->assertTrue($test->hasWarningRecords());
|
||||
$records = $test->getRecords();
|
||||
$this->assertTrue($records[0]['extra']['foo']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\GroupHandler::handle
|
||||
*/
|
||||
public function testHandleBatchUsesProcessors()
|
||||
{
|
||||
$testHandlers = array(new TestHandler(), new TestHandler());
|
||||
$handler = new GroupHandler($testHandlers);
|
||||
$handler->pushProcessor(function ($record) {
|
||||
$record['extra']['foo'] = true;
|
||||
|
||||
return $record;
|
||||
});
|
||||
$handler->handleBatch(array($this->getRecord(Logger::DEBUG), $this->getRecord(Logger::INFO)));
|
||||
foreach ($testHandlers as $test) {
|
||||
$this->assertTrue($test->hasDebugRecords());
|
||||
$this->assertTrue($test->hasInfoRecords());
|
||||
$this->assertTrue(count($test->getRecords()) === 2);
|
||||
$records = $test->getRecords();
|
||||
$this->assertTrue($records[0]['extra']['foo']);
|
||||
$this->assertTrue($records[1]['extra']['foo']);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
|
||||
/**
|
||||
* @author Alexey Karapetov <alexey@karapetov.com>
|
||||
*/
|
||||
class HandlerWrapperTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var HandlerWrapper
|
||||
*/
|
||||
private $wrapper;
|
||||
|
||||
private $handler;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->handler = $this->getMock('Monolog\\Handler\\HandlerInterface');
|
||||
$this->wrapper = new HandlerWrapper($this->handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function trueFalseDataProvider()
|
||||
{
|
||||
return array(
|
||||
array(true),
|
||||
array(false),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $result
|
||||
* @dataProvider trueFalseDataProvider
|
||||
*/
|
||||
public function testIsHandling($result)
|
||||
{
|
||||
$record = $this->getRecord();
|
||||
$this->handler->expects($this->once())
|
||||
->method('isHandling')
|
||||
->with($record)
|
||||
->willReturn($result);
|
||||
|
||||
$this->assertEquals($result, $this->wrapper->isHandling($record));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $result
|
||||
* @dataProvider trueFalseDataProvider
|
||||
*/
|
||||
public function testHandle($result)
|
||||
{
|
||||
$record = $this->getRecord();
|
||||
$this->handler->expects($this->once())
|
||||
->method('handle')
|
||||
->with($record)
|
||||
->willReturn($result);
|
||||
|
||||
$this->assertEquals($result, $this->wrapper->handle($record));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $result
|
||||
* @dataProvider trueFalseDataProvider
|
||||
*/
|
||||
public function testHandleBatch($result)
|
||||
{
|
||||
$records = $this->getMultipleRecords();
|
||||
$this->handler->expects($this->once())
|
||||
->method('handleBatch')
|
||||
->with($records)
|
||||
->willReturn($result);
|
||||
|
||||
$this->assertEquals($result, $this->wrapper->handleBatch($records));
|
||||
}
|
||||
|
||||
public function testPushProcessor()
|
||||
{
|
||||
$processor = function () {};
|
||||
$this->handler->expects($this->once())
|
||||
->method('pushProcessor')
|
||||
->with($processor);
|
||||
|
||||
$this->assertEquals($this->wrapper, $this->wrapper->pushProcessor($processor));
|
||||
}
|
||||
|
||||
public function testPopProcessor()
|
||||
{
|
||||
$processor = function () {};
|
||||
$this->handler->expects($this->once())
|
||||
->method('popProcessor')
|
||||
->willReturn($processor);
|
||||
|
||||
$this->assertEquals($processor, $this->wrapper->popProcessor());
|
||||
}
|
||||
|
||||
public function testSetFormatter()
|
||||
{
|
||||
$formatter = $this->getMock('Monolog\\Formatter\\FormatterInterface');
|
||||
$this->handler->expects($this->once())
|
||||
->method('setFormatter')
|
||||
->with($formatter);
|
||||
|
||||
$this->assertEquals($this->wrapper, $this->wrapper->setFormatter($formatter));
|
||||
}
|
||||
|
||||
public function testGetFormatter()
|
||||
{
|
||||
$formatter = $this->getMock('Monolog\\Formatter\\FormatterInterface');
|
||||
$this->handler->expects($this->once())
|
||||
->method('getFormatter')
|
||||
->willReturn($formatter);
|
||||
|
||||
$this->assertEquals($formatter, $this->wrapper->getFormatter());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,279 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
|
||||
/**
|
||||
* @author Rafael Dohms <rafael@doh.ms>
|
||||
* @see https://www.hipchat.com/docs/api
|
||||
*/
|
||||
class HipChatHandlerTest extends TestCase
|
||||
{
|
||||
private $res;
|
||||
/** @var HipChatHandler */
|
||||
private $handler;
|
||||
|
||||
public function testWriteHeader()
|
||||
{
|
||||
$this->createHandler();
|
||||
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
|
||||
fseek($this->res, 0);
|
||||
$content = fread($this->res, 1024);
|
||||
|
||||
$this->assertRegexp('/POST \/v1\/rooms\/message\?format=json&auth_token=.* HTTP\/1.1\\r\\nHost: api.hipchat.com\\r\\nContent-Type: application\/x-www-form-urlencoded\\r\\nContent-Length: \d{2,4}\\r\\n\\r\\n/', $content);
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
public function testWriteCustomHostHeader()
|
||||
{
|
||||
$this->createHandler('myToken', 'room1', 'Monolog', true, 'hipchat.foo.bar');
|
||||
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
|
||||
fseek($this->res, 0);
|
||||
$content = fread($this->res, 1024);
|
||||
|
||||
$this->assertRegexp('/POST \/v1\/rooms\/message\?format=json&auth_token=.* HTTP\/1.1\\r\\nHost: hipchat.foo.bar\\r\\nContent-Type: application\/x-www-form-urlencoded\\r\\nContent-Length: \d{2,4}\\r\\n\\r\\n/', $content);
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
public function testWriteV2()
|
||||
{
|
||||
$this->createHandler('myToken', 'room1', 'Monolog', false, 'hipchat.foo.bar', 'v2');
|
||||
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
|
||||
fseek($this->res, 0);
|
||||
$content = fread($this->res, 1024);
|
||||
|
||||
$this->assertRegexp('/POST \/v2\/room\/room1\/notification\?auth_token=.* HTTP\/1.1\\r\\nHost: hipchat.foo.bar\\r\\nContent-Type: application\/x-www-form-urlencoded\\r\\nContent-Length: \d{2,4}\\r\\n\\r\\n/', $content);
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
public function testWriteV2Notify()
|
||||
{
|
||||
$this->createHandler('myToken', 'room1', 'Monolog', true, 'hipchat.foo.bar', 'v2');
|
||||
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
|
||||
fseek($this->res, 0);
|
||||
$content = fread($this->res, 1024);
|
||||
|
||||
$this->assertRegexp('/POST \/v2\/room\/room1\/notification\?auth_token=.* HTTP\/1.1\\r\\nHost: hipchat.foo.bar\\r\\nContent-Type: application\/x-www-form-urlencoded\\r\\nContent-Length: \d{2,4}\\r\\n\\r\\n/', $content);
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
public function testRoomSpaces()
|
||||
{
|
||||
$this->createHandler('myToken', 'room name', 'Monolog', false, 'hipchat.foo.bar', 'v2');
|
||||
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
|
||||
fseek($this->res, 0);
|
||||
$content = fread($this->res, 1024);
|
||||
|
||||
$this->assertRegexp('/POST \/v2\/room\/room%20name\/notification\?auth_token=.* HTTP\/1.1\\r\\nHost: hipchat.foo.bar\\r\\nContent-Type: application\/x-www-form-urlencoded\\r\\nContent-Length: \d{2,4}\\r\\n\\r\\n/', $content);
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testWriteHeader
|
||||
*/
|
||||
public function testWriteContent($content)
|
||||
{
|
||||
$this->assertRegexp('/notify=0&message=test1&message_format=text&color=red&room_id=room1&from=Monolog$/', $content);
|
||||
}
|
||||
|
||||
public function testWriteContentV1WithoutName()
|
||||
{
|
||||
$this->createHandler('myToken', 'room1', null, false, 'hipchat.foo.bar', 'v1');
|
||||
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
|
||||
fseek($this->res, 0);
|
||||
$content = fread($this->res, 1024);
|
||||
|
||||
$this->assertRegexp('/notify=0&message=test1&message_format=text&color=red&room_id=room1&from=$/', $content);
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testWriteCustomHostHeader
|
||||
*/
|
||||
public function testWriteContentNotify($content)
|
||||
{
|
||||
$this->assertRegexp('/notify=1&message=test1&message_format=text&color=red&room_id=room1&from=Monolog$/', $content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testWriteV2
|
||||
*/
|
||||
public function testWriteContentV2($content)
|
||||
{
|
||||
$this->assertRegexp('/notify=false&message=test1&message_format=text&color=red&from=Monolog$/', $content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testWriteV2Notify
|
||||
*/
|
||||
public function testWriteContentV2Notify($content)
|
||||
{
|
||||
$this->assertRegexp('/notify=true&message=test1&message_format=text&color=red&from=Monolog$/', $content);
|
||||
}
|
||||
|
||||
public function testWriteContentV2WithoutName()
|
||||
{
|
||||
$this->createHandler('myToken', 'room1', null, false, 'hipchat.foo.bar', 'v2');
|
||||
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
|
||||
fseek($this->res, 0);
|
||||
$content = fread($this->res, 1024);
|
||||
|
||||
$this->assertRegexp('/notify=false&message=test1&message_format=text&color=red$/', $content);
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
public function testWriteWithComplexMessage()
|
||||
{
|
||||
$this->createHandler();
|
||||
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'Backup of database "example" finished in 16 minutes.'));
|
||||
fseek($this->res, 0);
|
||||
$content = fread($this->res, 1024);
|
||||
|
||||
$this->assertRegexp('/message=Backup\+of\+database\+%22example%22\+finished\+in\+16\+minutes\./', $content);
|
||||
}
|
||||
|
||||
public function testWriteTruncatesLongMessage()
|
||||
{
|
||||
$this->createHandler();
|
||||
$this->handler->handle($this->getRecord(Logger::CRITICAL, str_repeat('abcde', 2000)));
|
||||
fseek($this->res, 0);
|
||||
$content = fread($this->res, 12000);
|
||||
|
||||
$this->assertRegexp('/message='.str_repeat('abcde', 1900).'\+%5Btruncated%5D/', $content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideLevelColors
|
||||
*/
|
||||
public function testWriteWithErrorLevelsAndColors($level, $expectedColor)
|
||||
{
|
||||
$this->createHandler();
|
||||
$this->handler->handle($this->getRecord($level, 'Backup of database "example" finished in 16 minutes.'));
|
||||
fseek($this->res, 0);
|
||||
$content = fread($this->res, 1024);
|
||||
|
||||
$this->assertRegexp('/color='.$expectedColor.'/', $content);
|
||||
}
|
||||
|
||||
public function provideLevelColors()
|
||||
{
|
||||
return array(
|
||||
array(Logger::DEBUG, 'gray'),
|
||||
array(Logger::INFO, 'green'),
|
||||
array(Logger::WARNING, 'yellow'),
|
||||
array(Logger::ERROR, 'red'),
|
||||
array(Logger::CRITICAL, 'red'),
|
||||
array(Logger::ALERT, 'red'),
|
||||
array(Logger::EMERGENCY,'red'),
|
||||
array(Logger::NOTICE, 'green'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideBatchRecords
|
||||
*/
|
||||
public function testHandleBatch($records, $expectedColor)
|
||||
{
|
||||
$this->createHandler();
|
||||
|
||||
$this->handler->handleBatch($records);
|
||||
|
||||
fseek($this->res, 0);
|
||||
$content = fread($this->res, 1024);
|
||||
|
||||
$this->assertRegexp('/color='.$expectedColor.'/', $content);
|
||||
}
|
||||
|
||||
public function provideBatchRecords()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
array(
|
||||
array('level' => Logger::WARNING, 'message' => 'Oh bugger!', 'level_name' => 'warning', 'datetime' => new \DateTime()),
|
||||
array('level' => Logger::NOTICE, 'message' => 'Something noticeable happened.', 'level_name' => 'notice', 'datetime' => new \DateTime()),
|
||||
array('level' => Logger::CRITICAL, 'message' => 'Everything is broken!', 'level_name' => 'critical', 'datetime' => new \DateTime()),
|
||||
),
|
||||
'red',
|
||||
),
|
||||
array(
|
||||
array(
|
||||
array('level' => Logger::WARNING, 'message' => 'Oh bugger!', 'level_name' => 'warning', 'datetime' => new \DateTime()),
|
||||
array('level' => Logger::NOTICE, 'message' => 'Something noticeable happened.', 'level_name' => 'notice', 'datetime' => new \DateTime()),
|
||||
),
|
||||
'yellow',
|
||||
),
|
||||
array(
|
||||
array(
|
||||
array('level' => Logger::DEBUG, 'message' => 'Just debugging.', 'level_name' => 'debug', 'datetime' => new \DateTime()),
|
||||
array('level' => Logger::NOTICE, 'message' => 'Something noticeable happened.', 'level_name' => 'notice', 'datetime' => new \DateTime()),
|
||||
),
|
||||
'green',
|
||||
),
|
||||
array(
|
||||
array(
|
||||
array('level' => Logger::DEBUG, 'message' => 'Just debugging.', 'level_name' => 'debug', 'datetime' => new \DateTime()),
|
||||
),
|
||||
'gray',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
private function createHandler($token = 'myToken', $room = 'room1', $name = 'Monolog', $notify = false, $host = 'api.hipchat.com', $version = 'v1')
|
||||
{
|
||||
$constructorArgs = array($token, $room, $name, $notify, Logger::DEBUG, true, true, 'text', $host, $version);
|
||||
$this->res = fopen('php://memory', 'a');
|
||||
$this->handler = $this->getMock(
|
||||
'\Monolog\Handler\HipChatHandler',
|
||||
array('fsockopen', 'streamSetTimeout', 'closeSocket'),
|
||||
$constructorArgs
|
||||
);
|
||||
|
||||
$reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString');
|
||||
$reflectionProperty->setAccessible(true);
|
||||
$reflectionProperty->setValue($this->handler, 'localhost:1234');
|
||||
|
||||
$this->handler->expects($this->any())
|
||||
->method('fsockopen')
|
||||
->will($this->returnValue($this->res));
|
||||
$this->handler->expects($this->any())
|
||||
->method('streamSetTimeout')
|
||||
->will($this->returnValue(true));
|
||||
$this->handler->expects($this->any())
|
||||
->method('closeSocket')
|
||||
->will($this->returnValue(true));
|
||||
|
||||
$this->handler->setFormatter($this->getIdentityFormatter());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testCreateWithTooLongName()
|
||||
{
|
||||
$hipChatHandler = new HipChatHandler('token', 'room', 'SixteenCharsHere');
|
||||
}
|
||||
|
||||
public function testCreateWithTooLongNameV2()
|
||||
{
|
||||
// creating a handler with too long of a name but using the v2 api doesn't matter.
|
||||
$hipChatHandler = new HipChatHandler('token', 'room', 'SixteenCharsHere', false, Logger::CRITICAL, true, true, 'test', 'api.hipchat.com', 'v2');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
|
||||
/**
|
||||
* @author Robert Kaufmann III <rok3@rok3.me>
|
||||
*/
|
||||
class LogEntriesHandlerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var resource
|
||||
*/
|
||||
private $res;
|
||||
|
||||
/**
|
||||
* @var LogEntriesHandler
|
||||
*/
|
||||
private $handler;
|
||||
|
||||
public function testWriteContent()
|
||||
{
|
||||
$this->createHandler();
|
||||
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'Critical write test'));
|
||||
|
||||
fseek($this->res, 0);
|
||||
$content = fread($this->res, 1024);
|
||||
|
||||
$this->assertRegexp('/testToken \[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\] test.CRITICAL: Critical write test/', $content);
|
||||
}
|
||||
|
||||
public function testWriteBatchContent()
|
||||
{
|
||||
$records = array(
|
||||
$this->getRecord(),
|
||||
$this->getRecord(),
|
||||
$this->getRecord(),
|
||||
);
|
||||
$this->createHandler();
|
||||
$this->handler->handleBatch($records);
|
||||
|
||||
fseek($this->res, 0);
|
||||
$content = fread($this->res, 1024);
|
||||
|
||||
$this->assertRegexp('/(testToken \[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\] .* \[\] \[\]\n){3}/', $content);
|
||||
}
|
||||
|
||||
private function createHandler()
|
||||
{
|
||||
$useSSL = extension_loaded('openssl');
|
||||
$args = array('testToken', $useSSL, Logger::DEBUG, true);
|
||||
$this->res = fopen('php://memory', 'a');
|
||||
$this->handler = $this->getMock(
|
||||
'\Monolog\Handler\LogEntriesHandler',
|
||||
array('fsockopen', 'streamSetTimeout', 'closeSocket'),
|
||||
$args
|
||||
);
|
||||
|
||||
$reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString');
|
||||
$reflectionProperty->setAccessible(true);
|
||||
$reflectionProperty->setValue($this->handler, 'localhost:1234');
|
||||
|
||||
$this->handler->expects($this->any())
|
||||
->method('fsockopen')
|
||||
->will($this->returnValue($this->res));
|
||||
$this->handler->expects($this->any())
|
||||
->method('streamSetTimeout')
|
||||
->will($this->returnValue(true));
|
||||
$this->handler->expects($this->any())
|
||||
->method('closeSocket')
|
||||
->will($this->returnValue(true));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Monolog\TestCase;
|
||||
|
||||
class MailHandlerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers Monolog\Handler\MailHandler::handleBatch
|
||||
*/
|
||||
public function testHandleBatch()
|
||||
{
|
||||
$formatter = $this->getMock('Monolog\\Formatter\\FormatterInterface');
|
||||
$formatter->expects($this->once())
|
||||
->method('formatBatch'); // Each record is formatted
|
||||
|
||||
$handler = $this->getMockForAbstractClass('Monolog\\Handler\\MailHandler');
|
||||
$handler->expects($this->once())
|
||||
->method('send');
|
||||
$handler->expects($this->never())
|
||||
->method('write'); // write is for individual records
|
||||
|
||||
$handler->setFormatter($formatter);
|
||||
|
||||
$handler->handleBatch($this->getMultipleRecords());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\MailHandler::handleBatch
|
||||
*/
|
||||
public function testHandleBatchNotSendsMailIfMessagesAreBelowLevel()
|
||||
{
|
||||
$records = array(
|
||||
$this->getRecord(Logger::DEBUG, 'debug message 1'),
|
||||
$this->getRecord(Logger::DEBUG, 'debug message 2'),
|
||||
$this->getRecord(Logger::INFO, 'information'),
|
||||
);
|
||||
|
||||
$handler = $this->getMockForAbstractClass('Monolog\\Handler\\MailHandler');
|
||||
$handler->expects($this->never())
|
||||
->method('send');
|
||||
$handler->setLevel(Logger::ERROR);
|
||||
|
||||
$handler->handleBatch($records);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\MailHandler::write
|
||||
*/
|
||||
public function testHandle()
|
||||
{
|
||||
$handler = $this->getMockForAbstractClass('Monolog\\Handler\\MailHandler');
|
||||
|
||||
$record = $this->getRecord();
|
||||
$records = array($record);
|
||||
$records[0]['formatted'] = '['.$record['datetime']->format('Y-m-d H:i:s').'] test.WARNING: test [] []'."\n";
|
||||
|
||||
$handler->expects($this->once())
|
||||
->method('send')
|
||||
->with($records[0]['formatted'], $records);
|
||||
|
||||
$handler->handle($record);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Raven_Client;
|
||||
|
||||
class MockRavenClient extends Raven_Client
|
||||
{
|
||||
public function capture($data, $stack, $vars = null)
|
||||
{
|
||||
$data = array_merge($this->get_user_data(), $data);
|
||||
$this->lastData = $data;
|
||||
$this->lastStack = $stack;
|
||||
}
|
||||
|
||||
public $lastData;
|
||||
public $lastStack;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
|
||||
class MongoDBHandlerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testConstructorShouldThrowExceptionForInvalidMongo()
|
||||
{
|
||||
new MongoDBHandler(new \stdClass(), 'DB', 'Collection');
|
||||
}
|
||||
|
||||
public function testHandle()
|
||||
{
|
||||
$mongo = $this->getMock('Mongo', array('selectCollection'), array(), '', false);
|
||||
$collection = $this->getMock('stdClass', array('save'));
|
||||
|
||||
$mongo->expects($this->once())
|
||||
->method('selectCollection')
|
||||
->with('DB', 'Collection')
|
||||
->will($this->returnValue($collection));
|
||||
|
||||
$record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34));
|
||||
|
||||
$expected = array(
|
||||
'message' => 'test',
|
||||
'context' => array('data' => '[object] (stdClass: {})', 'foo' => 34),
|
||||
'level' => Logger::WARNING,
|
||||
'level_name' => 'WARNING',
|
||||
'channel' => 'test',
|
||||
'datetime' => $record['datetime']->format('Y-m-d H:i:s'),
|
||||
'extra' => array(),
|
||||
);
|
||||
|
||||
$collection->expects($this->once())
|
||||
->method('save')
|
||||
->with($expected);
|
||||
|
||||
$handler = new MongoDBHandler($mongo, 'DB', 'Collection');
|
||||
$handler->handle($record);
|
||||
}
|
||||
}
|
||||
|
||||
if (!class_exists('Mongo')) {
|
||||
class Mongo
|
||||
{
|
||||
public function selectCollection()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
use InvalidArgumentException;
|
||||
|
||||
function mail($to, $subject, $message, $additional_headers = null, $additional_parameters = null)
|
||||
{
|
||||
$GLOBALS['mail'][] = func_get_args();
|
||||
}
|
||||
|
||||
class NativeMailerHandlerTest extends TestCase
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
$GLOBALS['mail'] = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testConstructorHeaderInjection()
|
||||
{
|
||||
$mailer = new NativeMailerHandler('spammer@example.org', 'dear victim', "receiver@example.org\r\nFrom: faked@attacker.org");
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testSetterHeaderInjection()
|
||||
{
|
||||
$mailer = new NativeMailerHandler('spammer@example.org', 'dear victim', 'receiver@example.org');
|
||||
$mailer->addHeader("Content-Type: text/html\r\nFrom: faked@attacker.org");
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testSetterArrayHeaderInjection()
|
||||
{
|
||||
$mailer = new NativeMailerHandler('spammer@example.org', 'dear victim', 'receiver@example.org');
|
||||
$mailer->addHeader(array("Content-Type: text/html\r\nFrom: faked@attacker.org"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testSetterContentTypeInjection()
|
||||
{
|
||||
$mailer = new NativeMailerHandler('spammer@example.org', 'dear victim', 'receiver@example.org');
|
||||
$mailer->setContentType("text/html\r\nFrom: faked@attacker.org");
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testSetterEncodingInjection()
|
||||
{
|
||||
$mailer = new NativeMailerHandler('spammer@example.org', 'dear victim', 'receiver@example.org');
|
||||
$mailer->setEncoding("utf-8\r\nFrom: faked@attacker.org");
|
||||
}
|
||||
|
||||
public function testSend()
|
||||
{
|
||||
$to = 'spammer@example.org';
|
||||
$subject = 'dear victim';
|
||||
$from = 'receiver@example.org';
|
||||
|
||||
$mailer = new NativeMailerHandler($to, $subject, $from);
|
||||
$mailer->handleBatch(array());
|
||||
|
||||
// batch is empty, nothing sent
|
||||
$this->assertEmpty($GLOBALS['mail']);
|
||||
|
||||
// non-empty batch
|
||||
$mailer->handle($this->getRecord(Logger::ERROR, "Foo\nBar\r\n\r\nBaz"));
|
||||
$this->assertNotEmpty($GLOBALS['mail']);
|
||||
$this->assertInternalType('array', $GLOBALS['mail']);
|
||||
$this->assertArrayHasKey('0', $GLOBALS['mail']);
|
||||
$params = $GLOBALS['mail'][0];
|
||||
$this->assertCount(5, $params);
|
||||
$this->assertSame($to, $params[0]);
|
||||
$this->assertSame($subject, $params[1]);
|
||||
$this->assertStringEndsWith(" test.ERROR: Foo Bar Baz [] []\n", $params[2]);
|
||||
$this->assertSame("From: $from\r\nContent-type: text/plain; charset=utf-8\r\n", $params[3]);
|
||||
$this->assertSame('', $params[4]);
|
||||
}
|
||||
|
||||
public function testMessageSubjectFormatting()
|
||||
{
|
||||
$mailer = new NativeMailerHandler('to@example.org', 'Alert: %level_name% %message%', 'from@example.org');
|
||||
$mailer->handle($this->getRecord(Logger::ERROR, "Foo\nBar\r\n\r\nBaz"));
|
||||
$this->assertNotEmpty($GLOBALS['mail']);
|
||||
$this->assertInternalType('array', $GLOBALS['mail']);
|
||||
$this->assertArrayHasKey('0', $GLOBALS['mail']);
|
||||
$params = $GLOBALS['mail'][0];
|
||||
$this->assertCount(5, $params);
|
||||
$this->assertSame('Alert: ERROR Foo Bar Baz', $params[1]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\Formatter\LineFormatter;
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
|
||||
class NewRelicHandlerTest extends TestCase
|
||||
{
|
||||
public static $appname;
|
||||
public static $customParameters;
|
||||
public static $transactionName;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
self::$appname = null;
|
||||
self::$customParameters = array();
|
||||
self::$transactionName = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Monolog\Handler\MissingExtensionException
|
||||
*/
|
||||
public function testThehandlerThrowsAnExceptionIfTheNRExtensionIsNotLoaded()
|
||||
{
|
||||
$handler = new StubNewRelicHandlerWithoutExtension();
|
||||
$handler->handle($this->getRecord(Logger::ERROR));
|
||||
}
|
||||
|
||||
public function testThehandlerCanHandleTheRecord()
|
||||
{
|
||||
$handler = new StubNewRelicHandler();
|
||||
$handler->handle($this->getRecord(Logger::ERROR));
|
||||
}
|
||||
|
||||
public function testThehandlerCanAddContextParamsToTheNewRelicTrace()
|
||||
{
|
||||
$handler = new StubNewRelicHandler();
|
||||
$handler->handle($this->getRecord(Logger::ERROR, 'log message', array('a' => 'b')));
|
||||
$this->assertEquals(array('context_a' => 'b'), self::$customParameters);
|
||||
}
|
||||
|
||||
public function testThehandlerCanAddExplodedContextParamsToTheNewRelicTrace()
|
||||
{
|
||||
$handler = new StubNewRelicHandler(Logger::ERROR, true, self::$appname, true);
|
||||
$handler->handle($this->getRecord(
|
||||
Logger::ERROR,
|
||||
'log message',
|
||||
array('a' => array('key1' => 'value1', 'key2' => 'value2'))
|
||||
));
|
||||
$this->assertEquals(
|
||||
array('context_a_key1' => 'value1', 'context_a_key2' => 'value2'),
|
||||
self::$customParameters
|
||||
);
|
||||
}
|
||||
|
||||
public function testThehandlerCanAddExtraParamsToTheNewRelicTrace()
|
||||
{
|
||||
$record = $this->getRecord(Logger::ERROR, 'log message');
|
||||
$record['extra'] = array('c' => 'd');
|
||||
|
||||
$handler = new StubNewRelicHandler();
|
||||
$handler->handle($record);
|
||||
|
||||
$this->assertEquals(array('extra_c' => 'd'), self::$customParameters);
|
||||
}
|
||||
|
||||
public function testThehandlerCanAddExplodedExtraParamsToTheNewRelicTrace()
|
||||
{
|
||||
$record = $this->getRecord(Logger::ERROR, 'log message');
|
||||
$record['extra'] = array('c' => array('key1' => 'value1', 'key2' => 'value2'));
|
||||
|
||||
$handler = new StubNewRelicHandler(Logger::ERROR, true, self::$appname, true);
|
||||
$handler->handle($record);
|
||||
|
||||
$this->assertEquals(
|
||||
array('extra_c_key1' => 'value1', 'extra_c_key2' => 'value2'),
|
||||
self::$customParameters
|
||||
);
|
||||
}
|
||||
|
||||
public function testThehandlerCanAddExtraContextAndParamsToTheNewRelicTrace()
|
||||
{
|
||||
$record = $this->getRecord(Logger::ERROR, 'log message', array('a' => 'b'));
|
||||
$record['extra'] = array('c' => 'd');
|
||||
|
||||
$handler = new StubNewRelicHandler();
|
||||
$handler->handle($record);
|
||||
|
||||
$expected = array(
|
||||
'context_a' => 'b',
|
||||
'extra_c' => 'd',
|
||||
);
|
||||
|
||||
$this->assertEquals($expected, self::$customParameters);
|
||||
}
|
||||
|
||||
public function testThehandlerCanHandleTheRecordsFormattedUsingTheLineFormatter()
|
||||
{
|
||||
$handler = new StubNewRelicHandler();
|
||||
$handler->setFormatter(new LineFormatter());
|
||||
$handler->handle($this->getRecord(Logger::ERROR));
|
||||
}
|
||||
|
||||
public function testTheAppNameIsNullByDefault()
|
||||
{
|
||||
$handler = new StubNewRelicHandler();
|
||||
$handler->handle($this->getRecord(Logger::ERROR, 'log message'));
|
||||
|
||||
$this->assertEquals(null, self::$appname);
|
||||
}
|
||||
|
||||
public function testTheAppNameCanBeInjectedFromtheConstructor()
|
||||
{
|
||||
$handler = new StubNewRelicHandler(Logger::DEBUG, false, 'myAppName');
|
||||
$handler->handle($this->getRecord(Logger::ERROR, 'log message'));
|
||||
|
||||
$this->assertEquals('myAppName', self::$appname);
|
||||
}
|
||||
|
||||
public function testTheAppNameCanBeOverriddenFromEachLog()
|
||||
{
|
||||
$handler = new StubNewRelicHandler(Logger::DEBUG, false, 'myAppName');
|
||||
$handler->handle($this->getRecord(Logger::ERROR, 'log message', array('appname' => 'logAppName')));
|
||||
|
||||
$this->assertEquals('logAppName', self::$appname);
|
||||
}
|
||||
|
||||
public function testTheTransactionNameIsNullByDefault()
|
||||
{
|
||||
$handler = new StubNewRelicHandler();
|
||||
$handler->handle($this->getRecord(Logger::ERROR, 'log message'));
|
||||
|
||||
$this->assertEquals(null, self::$transactionName);
|
||||
}
|
||||
|
||||
public function testTheTransactionNameCanBeInjectedFromTheConstructor()
|
||||
{
|
||||
$handler = new StubNewRelicHandler(Logger::DEBUG, false, null, false, 'myTransaction');
|
||||
$handler->handle($this->getRecord(Logger::ERROR, 'log message'));
|
||||
|
||||
$this->assertEquals('myTransaction', self::$transactionName);
|
||||
}
|
||||
|
||||
public function testTheTransactionNameCanBeOverriddenFromEachLog()
|
||||
{
|
||||
$handler = new StubNewRelicHandler(Logger::DEBUG, false, null, false, 'myTransaction');
|
||||
$handler->handle($this->getRecord(Logger::ERROR, 'log message', array('transaction_name' => 'logTransactName')));
|
||||
|
||||
$this->assertEquals('logTransactName', self::$transactionName);
|
||||
}
|
||||
}
|
||||
|
||||
class StubNewRelicHandlerWithoutExtension extends NewRelicHandler
|
||||
{
|
||||
protected function isNewRelicEnabled()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class StubNewRelicHandler extends NewRelicHandler
|
||||
{
|
||||
protected function isNewRelicEnabled()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function newrelic_notice_error()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
function newrelic_set_appname($appname)
|
||||
{
|
||||
return NewRelicHandlerTest::$appname = $appname;
|
||||
}
|
||||
|
||||
function newrelic_name_transaction($transactionName)
|
||||
{
|
||||
return NewRelicHandlerTest::$transactionName = $transactionName;
|
||||
}
|
||||
|
||||
function newrelic_add_custom_parameter($key, $value)
|
||||
{
|
||||
NewRelicHandlerTest::$customParameters[$key] = $value;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\NullHandler::handle
|
||||
*/
|
||||
class NullHandlerTest extends TestCase
|
||||
{
|
||||
public function testHandle()
|
||||
{
|
||||
$handler = new NullHandler();
|
||||
$this->assertTrue($handler->handle($this->getRecord()));
|
||||
}
|
||||
|
||||
public function testHandleLowerLevelRecord()
|
||||
{
|
||||
$handler = new NullHandler(Logger::WARNING);
|
||||
$this->assertFalse($handler->handle($this->getRecord(Logger::DEBUG)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,273 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Exception;
|
||||
use Monolog\ErrorHandler;
|
||||
use Monolog\Logger;
|
||||
use Monolog\TestCase;
|
||||
use PhpConsole\Connector;
|
||||
use PhpConsole\Dispatcher\Debug as DebugDispatcher;
|
||||
use PhpConsole\Dispatcher\Errors as ErrorDispatcher;
|
||||
use PhpConsole\Handler;
|
||||
use PHPUnit_Framework_MockObject_MockObject;
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\PHPConsoleHandler
|
||||
* @author Sergey Barbushin https://www.linkedin.com/in/barbushin
|
||||
*/
|
||||
class PHPConsoleHandlerTest extends TestCase
|
||||
{
|
||||
/** @var Connector|PHPUnit_Framework_MockObject_MockObject */
|
||||
protected $connector;
|
||||
/** @var DebugDispatcher|PHPUnit_Framework_MockObject_MockObject */
|
||||
protected $debugDispatcher;
|
||||
/** @var ErrorDispatcher|PHPUnit_Framework_MockObject_MockObject */
|
||||
protected $errorDispatcher;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
if (!class_exists('PhpConsole\Connector')) {
|
||||
$this->markTestSkipped('PHP Console library not found. See https://github.com/barbushin/php-console#installation');
|
||||
}
|
||||
$this->connector = $this->initConnectorMock();
|
||||
|
||||
$this->debugDispatcher = $this->initDebugDispatcherMock($this->connector);
|
||||
$this->connector->setDebugDispatcher($this->debugDispatcher);
|
||||
|
||||
$this->errorDispatcher = $this->initErrorDispatcherMock($this->connector);
|
||||
$this->connector->setErrorsDispatcher($this->errorDispatcher);
|
||||
}
|
||||
|
||||
protected function initDebugDispatcherMock(Connector $connector)
|
||||
{
|
||||
return $this->getMockBuilder('PhpConsole\Dispatcher\Debug')
|
||||
->disableOriginalConstructor()
|
||||
->setMethods(array('dispatchDebug'))
|
||||
->setConstructorArgs(array($connector, $connector->getDumper()))
|
||||
->getMock();
|
||||
}
|
||||
|
||||
protected function initErrorDispatcherMock(Connector $connector)
|
||||
{
|
||||
return $this->getMockBuilder('PhpConsole\Dispatcher\Errors')
|
||||
->disableOriginalConstructor()
|
||||
->setMethods(array('dispatchError', 'dispatchException'))
|
||||
->setConstructorArgs(array($connector, $connector->getDumper()))
|
||||
->getMock();
|
||||
}
|
||||
|
||||
protected function initConnectorMock()
|
||||
{
|
||||
$connector = $this->getMockBuilder('PhpConsole\Connector')
|
||||
->disableOriginalConstructor()
|
||||
->setMethods(array(
|
||||
'sendMessage',
|
||||
'onShutDown',
|
||||
'isActiveClient',
|
||||
'setSourcesBasePath',
|
||||
'setServerEncoding',
|
||||
'setPassword',
|
||||
'enableSslOnlyMode',
|
||||
'setAllowedIpMasks',
|
||||
'setHeadersLimit',
|
||||
'startEvalRequestsListener',
|
||||
))
|
||||
->getMock();
|
||||
|
||||
$connector->expects($this->any())
|
||||
->method('isActiveClient')
|
||||
->will($this->returnValue(true));
|
||||
|
||||
return $connector;
|
||||
}
|
||||
|
||||
protected function getHandlerDefaultOption($name)
|
||||
{
|
||||
$handler = new PHPConsoleHandler(array(), $this->connector);
|
||||
$options = $handler->getOptions();
|
||||
|
||||
return $options[$name];
|
||||
}
|
||||
|
||||
protected function initLogger($handlerOptions = array(), $level = Logger::DEBUG)
|
||||
{
|
||||
return new Logger('test', array(
|
||||
new PHPConsoleHandler($handlerOptions, $this->connector, $level),
|
||||
));
|
||||
}
|
||||
|
||||
public function testInitWithDefaultConnector()
|
||||
{
|
||||
$handler = new PHPConsoleHandler();
|
||||
$this->assertEquals(spl_object_hash(Connector::getInstance()), spl_object_hash($handler->getConnector()));
|
||||
}
|
||||
|
||||
public function testInitWithCustomConnector()
|
||||
{
|
||||
$handler = new PHPConsoleHandler(array(), $this->connector);
|
||||
$this->assertEquals(spl_object_hash($this->connector), spl_object_hash($handler->getConnector()));
|
||||
}
|
||||
|
||||
public function testDebug()
|
||||
{
|
||||
$this->debugDispatcher->expects($this->once())->method('dispatchDebug')->with($this->equalTo('test'));
|
||||
$this->initLogger()->addDebug('test');
|
||||
}
|
||||
|
||||
public function testDebugContextInMessage()
|
||||
{
|
||||
$message = 'test';
|
||||
$tag = 'tag';
|
||||
$context = array($tag, 'custom' => mt_rand());
|
||||
$expectedMessage = $message . ' ' . json_encode(array_slice($context, 1));
|
||||
$this->debugDispatcher->expects($this->once())->method('dispatchDebug')->with(
|
||||
$this->equalTo($expectedMessage),
|
||||
$this->equalTo($tag)
|
||||
);
|
||||
$this->initLogger()->addDebug($message, $context);
|
||||
}
|
||||
|
||||
public function testDebugTags($tagsContextKeys = null)
|
||||
{
|
||||
$expectedTags = mt_rand();
|
||||
$logger = $this->initLogger($tagsContextKeys ? array('debugTagsKeysInContext' => $tagsContextKeys) : array());
|
||||
if (!$tagsContextKeys) {
|
||||
$tagsContextKeys = $this->getHandlerDefaultOption('debugTagsKeysInContext');
|
||||
}
|
||||
foreach ($tagsContextKeys as $key) {
|
||||
$debugDispatcher = $this->initDebugDispatcherMock($this->connector);
|
||||
$debugDispatcher->expects($this->once())->method('dispatchDebug')->with(
|
||||
$this->anything(),
|
||||
$this->equalTo($expectedTags)
|
||||
);
|
||||
$this->connector->setDebugDispatcher($debugDispatcher);
|
||||
$logger->addDebug('test', array($key => $expectedTags));
|
||||
}
|
||||
}
|
||||
|
||||
public function testError($classesPartialsTraceIgnore = null)
|
||||
{
|
||||
$code = E_USER_NOTICE;
|
||||
$message = 'message';
|
||||
$file = __FILE__;
|
||||
$line = __LINE__;
|
||||
$this->errorDispatcher->expects($this->once())->method('dispatchError')->with(
|
||||
$this->equalTo($code),
|
||||
$this->equalTo($message),
|
||||
$this->equalTo($file),
|
||||
$this->equalTo($line),
|
||||
$classesPartialsTraceIgnore ?: $this->equalTo($this->getHandlerDefaultOption('classesPartialsTraceIgnore'))
|
||||
);
|
||||
$errorHandler = ErrorHandler::register($this->initLogger($classesPartialsTraceIgnore ? array('classesPartialsTraceIgnore' => $classesPartialsTraceIgnore) : array()), false);
|
||||
$errorHandler->registerErrorHandler(array(), false, E_USER_WARNING);
|
||||
$errorHandler->handleError($code, $message, $file, $line);
|
||||
}
|
||||
|
||||
public function testException()
|
||||
{
|
||||
$e = new Exception();
|
||||
$this->errorDispatcher->expects($this->once())->method('dispatchException')->with(
|
||||
$this->equalTo($e)
|
||||
);
|
||||
$handler = $this->initLogger();
|
||||
$handler->log(
|
||||
\Psr\Log\LogLevel::ERROR,
|
||||
sprintf('Uncaught Exception %s: "%s" at %s line %s', get_class($e), $e->getMessage(), $e->getFile(), $e->getLine()),
|
||||
array('exception' => $e)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Exception
|
||||
*/
|
||||
public function testWrongOptionsThrowsException()
|
||||
{
|
||||
new PHPConsoleHandler(array('xxx' => 1));
|
||||
}
|
||||
|
||||
public function testOptionEnabled()
|
||||
{
|
||||
$this->debugDispatcher->expects($this->never())->method('dispatchDebug');
|
||||
$this->initLogger(array('enabled' => false))->addDebug('test');
|
||||
}
|
||||
|
||||
public function testOptionClassesPartialsTraceIgnore()
|
||||
{
|
||||
$this->testError(array('Class', 'Namespace\\'));
|
||||
}
|
||||
|
||||
public function testOptionDebugTagsKeysInContext()
|
||||
{
|
||||
$this->testDebugTags(array('key1', 'key2'));
|
||||
}
|
||||
|
||||
public function testOptionUseOwnErrorsAndExceptionsHandler()
|
||||
{
|
||||
$this->initLogger(array('useOwnErrorsHandler' => true, 'useOwnExceptionsHandler' => true));
|
||||
$this->assertEquals(array(Handler::getInstance(), 'handleError'), set_error_handler(function () {
|
||||
}));
|
||||
$this->assertEquals(array(Handler::getInstance(), 'handleException'), set_exception_handler(function () {
|
||||
}));
|
||||
}
|
||||
|
||||
public static function provideConnectorMethodsOptionsSets()
|
||||
{
|
||||
return array(
|
||||
array('sourcesBasePath', 'setSourcesBasePath', __DIR__),
|
||||
array('serverEncoding', 'setServerEncoding', 'cp1251'),
|
||||
array('password', 'setPassword', '******'),
|
||||
array('enableSslOnlyMode', 'enableSslOnlyMode', true, false),
|
||||
array('ipMasks', 'setAllowedIpMasks', array('127.0.0.*')),
|
||||
array('headersLimit', 'setHeadersLimit', 2500),
|
||||
array('enableEvalListener', 'startEvalRequestsListener', true, false),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideConnectorMethodsOptionsSets
|
||||
*/
|
||||
public function testOptionCallsConnectorMethod($option, $method, $value, $isArgument = true)
|
||||
{
|
||||
$expectCall = $this->connector->expects($this->once())->method($method);
|
||||
if ($isArgument) {
|
||||
$expectCall->with($value);
|
||||
}
|
||||
new PHPConsoleHandler(array($option => $value), $this->connector);
|
||||
}
|
||||
|
||||
public function testOptionDetectDumpTraceAndSource()
|
||||
{
|
||||
new PHPConsoleHandler(array('detectDumpTraceAndSource' => true), $this->connector);
|
||||
$this->assertTrue($this->connector->getDebugDispatcher()->detectTraceAndSource);
|
||||
}
|
||||
|
||||
public static function provideDumperOptionsValues()
|
||||
{
|
||||
return array(
|
||||
array('dumperLevelLimit', 'levelLimit', 1001),
|
||||
array('dumperItemsCountLimit', 'itemsCountLimit', 1002),
|
||||
array('dumperItemSizeLimit', 'itemSizeLimit', 1003),
|
||||
array('dumperDumpSizeLimit', 'dumpSizeLimit', 1004),
|
||||
array('dumperDetectCallbacks', 'detectCallbacks', true),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideDumperOptionsValues
|
||||
*/
|
||||
public function testDumperOptions($option, $dumperProperty, $value)
|
||||
{
|
||||
new PHPConsoleHandler(array($option => $value), $this->connector);
|
||||
$this->assertEquals($value, $this->connector->getDumper()->$dumperProperty);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\PsrHandler::handle
|
||||
*/
|
||||
class PsrHandlerTest extends TestCase
|
||||
{
|
||||
public function logLevelProvider()
|
||||
{
|
||||
$levels = array();
|
||||
$monologLogger = new Logger('');
|
||||
|
||||
foreach ($monologLogger->getLevels() as $levelName => $level) {
|
||||
$levels[] = array($levelName, $level);
|
||||
}
|
||||
|
||||
return $levels;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider logLevelProvider
|
||||
*/
|
||||
public function testHandlesAllLevels($levelName, $level)
|
||||
{
|
||||
$message = 'Hello, world! ' . $level;
|
||||
$context = array('foo' => 'bar', 'level' => $level);
|
||||
|
||||
$psrLogger = $this->getMock('Psr\Log\NullLogger');
|
||||
$psrLogger->expects($this->once())
|
||||
->method('log')
|
||||
->with(strtolower($levelName), $message, $context);
|
||||
|
||||
$handler = new PsrHandler($psrLogger);
|
||||
$handler->handle(array('level' => $level, 'level_name' => $levelName, 'message' => $message, 'context' => $context));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
|
||||
/**
|
||||
* Almost all examples (expected header, titles, messages) taken from
|
||||
* https://www.pushover.net/api
|
||||
* @author Sebastian Göttschkes <sebastian.goettschkes@googlemail.com>
|
||||
* @see https://www.pushover.net/api
|
||||
*/
|
||||
class PushoverHandlerTest extends TestCase
|
||||
{
|
||||
private $res;
|
||||
private $handler;
|
||||
|
||||
public function testWriteHeader()
|
||||
{
|
||||
$this->createHandler();
|
||||
$this->handler->setHighPriorityLevel(Logger::EMERGENCY); // skip priority notifications
|
||||
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
|
||||
fseek($this->res, 0);
|
||||
$content = fread($this->res, 1024);
|
||||
|
||||
$this->assertRegexp('/POST \/1\/messages.json HTTP\/1.1\\r\\nHost: api.pushover.net\\r\\nContent-Type: application\/x-www-form-urlencoded\\r\\nContent-Length: \d{2,4}\\r\\n\\r\\n/', $content);
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testWriteHeader
|
||||
*/
|
||||
public function testWriteContent($content)
|
||||
{
|
||||
$this->assertRegexp('/token=myToken&user=myUser&message=test1&title=Monolog×tamp=\d{10}$/', $content);
|
||||
}
|
||||
|
||||
public function testWriteWithComplexTitle()
|
||||
{
|
||||
$this->createHandler('myToken', 'myUser', 'Backup finished - SQL1');
|
||||
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
|
||||
fseek($this->res, 0);
|
||||
$content = fread($this->res, 1024);
|
||||
|
||||
$this->assertRegexp('/title=Backup\+finished\+-\+SQL1/', $content);
|
||||
}
|
||||
|
||||
public function testWriteWithComplexMessage()
|
||||
{
|
||||
$this->createHandler();
|
||||
$this->handler->setHighPriorityLevel(Logger::EMERGENCY); // skip priority notifications
|
||||
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'Backup of database "example" finished in 16 minutes.'));
|
||||
fseek($this->res, 0);
|
||||
$content = fread($this->res, 1024);
|
||||
|
||||
$this->assertRegexp('/message=Backup\+of\+database\+%22example%22\+finished\+in\+16\+minutes\./', $content);
|
||||
}
|
||||
|
||||
public function testWriteWithTooLongMessage()
|
||||
{
|
||||
$message = str_pad('test', 520, 'a');
|
||||
$this->createHandler();
|
||||
$this->handler->setHighPriorityLevel(Logger::EMERGENCY); // skip priority notifications
|
||||
$this->handler->handle($this->getRecord(Logger::CRITICAL, $message));
|
||||
fseek($this->res, 0);
|
||||
$content = fread($this->res, 1024);
|
||||
|
||||
$expectedMessage = substr($message, 0, 505);
|
||||
|
||||
$this->assertRegexp('/message=' . $expectedMessage . '&title/', $content);
|
||||
}
|
||||
|
||||
public function testWriteWithHighPriority()
|
||||
{
|
||||
$this->createHandler();
|
||||
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
|
||||
fseek($this->res, 0);
|
||||
$content = fread($this->res, 1024);
|
||||
|
||||
$this->assertRegexp('/token=myToken&user=myUser&message=test1&title=Monolog×tamp=\d{10}&priority=1$/', $content);
|
||||
}
|
||||
|
||||
public function testWriteWithEmergencyPriority()
|
||||
{
|
||||
$this->createHandler();
|
||||
$this->handler->handle($this->getRecord(Logger::EMERGENCY, 'test1'));
|
||||
fseek($this->res, 0);
|
||||
$content = fread($this->res, 1024);
|
||||
|
||||
$this->assertRegexp('/token=myToken&user=myUser&message=test1&title=Monolog×tamp=\d{10}&priority=2&retry=30&expire=25200$/', $content);
|
||||
}
|
||||
|
||||
public function testWriteToMultipleUsers()
|
||||
{
|
||||
$this->createHandler('myToken', array('userA', 'userB'));
|
||||
$this->handler->handle($this->getRecord(Logger::EMERGENCY, 'test1'));
|
||||
fseek($this->res, 0);
|
||||
$content = fread($this->res, 1024);
|
||||
|
||||
$this->assertRegexp('/token=myToken&user=userA&message=test1&title=Monolog×tamp=\d{10}&priority=2&retry=30&expire=25200POST/', $content);
|
||||
$this->assertRegexp('/token=myToken&user=userB&message=test1&title=Monolog×tamp=\d{10}&priority=2&retry=30&expire=25200$/', $content);
|
||||
}
|
||||
|
||||
private function createHandler($token = 'myToken', $user = 'myUser', $title = 'Monolog')
|
||||
{
|
||||
$constructorArgs = array($token, $user, $title);
|
||||
$this->res = fopen('php://memory', 'a');
|
||||
$this->handler = $this->getMock(
|
||||
'\Monolog\Handler\PushoverHandler',
|
||||
array('fsockopen', 'streamSetTimeout', 'closeSocket'),
|
||||
$constructorArgs
|
||||
);
|
||||
|
||||
$reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString');
|
||||
$reflectionProperty->setAccessible(true);
|
||||
$reflectionProperty->setValue($this->handler, 'localhost:1234');
|
||||
|
||||
$this->handler->expects($this->any())
|
||||
->method('fsockopen')
|
||||
->will($this->returnValue($this->res));
|
||||
$this->handler->expects($this->any())
|
||||
->method('streamSetTimeout')
|
||||
->will($this->returnValue(true));
|
||||
$this->handler->expects($this->any())
|
||||
->method('closeSocket')
|
||||
->will($this->returnValue(true));
|
||||
|
||||
$this->handler->setFormatter($this->getIdentityFormatter());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,255 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
use Monolog\Formatter\LineFormatter;
|
||||
|
||||
class RavenHandlerTest extends TestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
if (!class_exists('Raven_Client')) {
|
||||
$this->markTestSkipped('raven/raven not installed');
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/MockRavenClient.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\RavenHandler::__construct
|
||||
*/
|
||||
public function testConstruct()
|
||||
{
|
||||
$handler = new RavenHandler($this->getRavenClient());
|
||||
$this->assertInstanceOf('Monolog\Handler\RavenHandler', $handler);
|
||||
}
|
||||
|
||||
protected function getHandler($ravenClient)
|
||||
{
|
||||
$handler = new RavenHandler($ravenClient);
|
||||
|
||||
return $handler;
|
||||
}
|
||||
|
||||
protected function getRavenClient()
|
||||
{
|
||||
$dsn = 'http://43f6017361224d098402974103bfc53d:a6a0538fc2934ba2bed32e08741b2cd3@marca.python.live.cheggnet.com:9000/1';
|
||||
|
||||
return new MockRavenClient($dsn);
|
||||
}
|
||||
|
||||
public function testDebug()
|
||||
{
|
||||
$ravenClient = $this->getRavenClient();
|
||||
$handler = $this->getHandler($ravenClient);
|
||||
|
||||
$record = $this->getRecord(Logger::DEBUG, 'A test debug message');
|
||||
$handler->handle($record);
|
||||
|
||||
$this->assertEquals($ravenClient::DEBUG, $ravenClient->lastData['level']);
|
||||
$this->assertContains($record['message'], $ravenClient->lastData['message']);
|
||||
}
|
||||
|
||||
public function testWarning()
|
||||
{
|
||||
$ravenClient = $this->getRavenClient();
|
||||
$handler = $this->getHandler($ravenClient);
|
||||
|
||||
$record = $this->getRecord(Logger::WARNING, 'A test warning message');
|
||||
$handler->handle($record);
|
||||
|
||||
$this->assertEquals($ravenClient::WARNING, $ravenClient->lastData['level']);
|
||||
$this->assertContains($record['message'], $ravenClient->lastData['message']);
|
||||
}
|
||||
|
||||
public function testTag()
|
||||
{
|
||||
$ravenClient = $this->getRavenClient();
|
||||
$handler = $this->getHandler($ravenClient);
|
||||
|
||||
$tags = array(1, 2, 'foo');
|
||||
$record = $this->getRecord(Logger::INFO, 'test', array('tags' => $tags));
|
||||
$handler->handle($record);
|
||||
|
||||
$this->assertEquals($tags, $ravenClient->lastData['tags']);
|
||||
}
|
||||
|
||||
public function testExtraParameters()
|
||||
{
|
||||
$ravenClient = $this->getRavenClient();
|
||||
$handler = $this->getHandler($ravenClient);
|
||||
|
||||
$checksum = '098f6bcd4621d373cade4e832627b4f6';
|
||||
$release = '05a671c66aefea124cc08b76ea6d30bb';
|
||||
$eventId = '31423';
|
||||
$record = $this->getRecord(Logger::INFO, 'test', array('checksum' => $checksum, 'release' => $release, 'event_id' => $eventId));
|
||||
$handler->handle($record);
|
||||
|
||||
$this->assertEquals($checksum, $ravenClient->lastData['checksum']);
|
||||
$this->assertEquals($release, $ravenClient->lastData['release']);
|
||||
$this->assertEquals($eventId, $ravenClient->lastData['event_id']);
|
||||
}
|
||||
|
||||
public function testFingerprint()
|
||||
{
|
||||
$ravenClient = $this->getRavenClient();
|
||||
$handler = $this->getHandler($ravenClient);
|
||||
|
||||
$fingerprint = array('{{ default }}', 'other value');
|
||||
$record = $this->getRecord(Logger::INFO, 'test', array('fingerprint' => $fingerprint));
|
||||
$handler->handle($record);
|
||||
|
||||
$this->assertEquals($fingerprint, $ravenClient->lastData['fingerprint']);
|
||||
}
|
||||
|
||||
public function testUserContext()
|
||||
{
|
||||
$ravenClient = $this->getRavenClient();
|
||||
$handler = $this->getHandler($ravenClient);
|
||||
|
||||
$recordWithNoContext = $this->getRecord(Logger::INFO, 'test with default user context');
|
||||
// set user context 'externally'
|
||||
|
||||
$user = array(
|
||||
'id' => '123',
|
||||
'email' => 'test@test.com',
|
||||
);
|
||||
|
||||
$recordWithContext = $this->getRecord(Logger::INFO, 'test', array('user' => $user));
|
||||
|
||||
$ravenClient->user_context(array('id' => 'test_user_id'));
|
||||
// handle context
|
||||
$handler->handle($recordWithContext);
|
||||
$this->assertEquals($user, $ravenClient->lastData['user']);
|
||||
|
||||
// check to see if its reset
|
||||
$handler->handle($recordWithNoContext);
|
||||
$this->assertInternalType('array', $ravenClient->context->user);
|
||||
$this->assertSame('test_user_id', $ravenClient->context->user['id']);
|
||||
|
||||
// handle with null context
|
||||
$ravenClient->user_context(null);
|
||||
$handler->handle($recordWithContext);
|
||||
$this->assertEquals($user, $ravenClient->lastData['user']);
|
||||
|
||||
// check to see if its reset
|
||||
$handler->handle($recordWithNoContext);
|
||||
$this->assertNull($ravenClient->context->user);
|
||||
}
|
||||
|
||||
public function testException()
|
||||
{
|
||||
$ravenClient = $this->getRavenClient();
|
||||
$handler = $this->getHandler($ravenClient);
|
||||
|
||||
try {
|
||||
$this->methodThatThrowsAnException();
|
||||
} catch (\Exception $e) {
|
||||
$record = $this->getRecord(Logger::ERROR, $e->getMessage(), array('exception' => $e));
|
||||
$handler->handle($record);
|
||||
}
|
||||
|
||||
$this->assertEquals($record['message'], $ravenClient->lastData['message']);
|
||||
}
|
||||
|
||||
public function testHandleBatch()
|
||||
{
|
||||
$records = $this->getMultipleRecords();
|
||||
$records[] = $this->getRecord(Logger::WARNING, 'warning');
|
||||
$records[] = $this->getRecord(Logger::WARNING, 'warning');
|
||||
|
||||
$logFormatter = $this->getMock('Monolog\\Formatter\\FormatterInterface');
|
||||
$logFormatter->expects($this->once())->method('formatBatch');
|
||||
|
||||
$formatter = $this->getMock('Monolog\\Formatter\\FormatterInterface');
|
||||
$formatter->expects($this->once())->method('format')->with($this->callback(function ($record) {
|
||||
return $record['level'] == 400;
|
||||
}));
|
||||
|
||||
$handler = $this->getHandler($this->getRavenClient());
|
||||
$handler->setBatchFormatter($logFormatter);
|
||||
$handler->setFormatter($formatter);
|
||||
$handler->handleBatch($records);
|
||||
}
|
||||
|
||||
public function testHandleBatchDoNothingIfRecordsAreBelowLevel()
|
||||
{
|
||||
$records = array(
|
||||
$this->getRecord(Logger::DEBUG, 'debug message 1'),
|
||||
$this->getRecord(Logger::DEBUG, 'debug message 2'),
|
||||
$this->getRecord(Logger::INFO, 'information'),
|
||||
);
|
||||
|
||||
$handler = $this->getMock('Monolog\Handler\RavenHandler', null, array($this->getRavenClient()));
|
||||
$handler->expects($this->never())->method('handle');
|
||||
$handler->setLevel(Logger::ERROR);
|
||||
$handler->handleBatch($records);
|
||||
}
|
||||
|
||||
public function testHandleBatchPicksProperMessage()
|
||||
{
|
||||
$records = array(
|
||||
$this->getRecord(Logger::DEBUG, 'debug message 1'),
|
||||
$this->getRecord(Logger::DEBUG, 'debug message 2'),
|
||||
$this->getRecord(Logger::INFO, 'information 1'),
|
||||
$this->getRecord(Logger::ERROR, 'error 1'),
|
||||
$this->getRecord(Logger::WARNING, 'warning'),
|
||||
$this->getRecord(Logger::ERROR, 'error 2'),
|
||||
$this->getRecord(Logger::INFO, 'information 2'),
|
||||
);
|
||||
|
||||
$logFormatter = $this->getMock('Monolog\\Formatter\\FormatterInterface');
|
||||
$logFormatter->expects($this->once())->method('formatBatch');
|
||||
|
||||
$formatter = $this->getMock('Monolog\\Formatter\\FormatterInterface');
|
||||
$formatter->expects($this->once())->method('format')->with($this->callback(function ($record) use ($records) {
|
||||
return $record['message'] == 'error 1';
|
||||
}));
|
||||
|
||||
$handler = $this->getHandler($this->getRavenClient());
|
||||
$handler->setBatchFormatter($logFormatter);
|
||||
$handler->setFormatter($formatter);
|
||||
$handler->handleBatch($records);
|
||||
}
|
||||
|
||||
public function testGetSetBatchFormatter()
|
||||
{
|
||||
$ravenClient = $this->getRavenClient();
|
||||
$handler = $this->getHandler($ravenClient);
|
||||
|
||||
$handler->setBatchFormatter($formatter = new LineFormatter());
|
||||
$this->assertSame($formatter, $handler->getBatchFormatter());
|
||||
}
|
||||
|
||||
public function testRelease()
|
||||
{
|
||||
$ravenClient = $this->getRavenClient();
|
||||
$handler = $this->getHandler($ravenClient);
|
||||
$release = 'v42.42.42';
|
||||
$handler->setRelease($release);
|
||||
$record = $this->getRecord(Logger::INFO, 'test');
|
||||
$handler->handle($record);
|
||||
$this->assertEquals($release, $ravenClient->lastData['release']);
|
||||
|
||||
$localRelease = 'v41.41.41';
|
||||
$record = $this->getRecord(Logger::INFO, 'test', array('release' => $localRelease));
|
||||
$handler->handle($record);
|
||||
$this->assertEquals($localRelease, $ravenClient->lastData['release']);
|
||||
}
|
||||
|
||||
private function methodThatThrowsAnException()
|
||||
{
|
||||
throw new \Exception('This is an exception');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
use Monolog\Formatter\LineFormatter;
|
||||
|
||||
class RedisHandlerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testConstructorShouldThrowExceptionForInvalidRedis()
|
||||
{
|
||||
new RedisHandler(new \stdClass(), 'key');
|
||||
}
|
||||
|
||||
public function testConstructorShouldWorkWithPredis()
|
||||
{
|
||||
$redis = $this->getMock('Predis\Client');
|
||||
$this->assertInstanceof('Monolog\Handler\RedisHandler', new RedisHandler($redis, 'key'));
|
||||
}
|
||||
|
||||
public function testConstructorShouldWorkWithRedis()
|
||||
{
|
||||
$redis = $this->getMock('Redis');
|
||||
$this->assertInstanceof('Monolog\Handler\RedisHandler', new RedisHandler($redis, 'key'));
|
||||
}
|
||||
|
||||
public function testPredisHandle()
|
||||
{
|
||||
$redis = $this->getMock('Predis\Client', array('rpush'));
|
||||
|
||||
// Predis\Client uses rpush
|
||||
$redis->expects($this->once())
|
||||
->method('rpush')
|
||||
->with('key', 'test');
|
||||
|
||||
$record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34));
|
||||
|
||||
$handler = new RedisHandler($redis, 'key');
|
||||
$handler->setFormatter(new LineFormatter("%message%"));
|
||||
$handler->handle($record);
|
||||
}
|
||||
|
||||
public function testRedisHandle()
|
||||
{
|
||||
$redis = $this->getMock('Redis', array('rpush'));
|
||||
|
||||
// Redis uses rPush
|
||||
$redis->expects($this->once())
|
||||
->method('rPush')
|
||||
->with('key', 'test');
|
||||
|
||||
$record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34));
|
||||
|
||||
$handler = new RedisHandler($redis, 'key');
|
||||
$handler->setFormatter(new LineFormatter("%message%"));
|
||||
$handler->handle($record);
|
||||
}
|
||||
|
||||
public function testRedisHandleCapped()
|
||||
{
|
||||
$redis = $this->getMock('Redis', array('multi', 'rpush', 'ltrim', 'exec'));
|
||||
|
||||
// Redis uses multi
|
||||
$redis->expects($this->once())
|
||||
->method('multi')
|
||||
->will($this->returnSelf());
|
||||
|
||||
$redis->expects($this->once())
|
||||
->method('rpush')
|
||||
->will($this->returnSelf());
|
||||
|
||||
$redis->expects($this->once())
|
||||
->method('ltrim')
|
||||
->will($this->returnSelf());
|
||||
|
||||
$redis->expects($this->once())
|
||||
->method('exec')
|
||||
->will($this->returnSelf());
|
||||
|
||||
$record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34));
|
||||
|
||||
$handler = new RedisHandler($redis, 'key', Logger::DEBUG, true, 10);
|
||||
$handler->setFormatter(new LineFormatter("%message%"));
|
||||
$handler->handle($record);
|
||||
}
|
||||
|
||||
public function testPredisHandleCapped()
|
||||
{
|
||||
$redis = $this->getMock('Predis\Client', array('transaction'));
|
||||
|
||||
$redisTransaction = $this->getMock('Predis\Client', array('rpush', 'ltrim'));
|
||||
|
||||
$redisTransaction->expects($this->once())
|
||||
->method('rpush')
|
||||
->will($this->returnSelf());
|
||||
|
||||
$redisTransaction->expects($this->once())
|
||||
->method('ltrim')
|
||||
->will($this->returnSelf());
|
||||
|
||||
// Redis uses multi
|
||||
$redis->expects($this->once())
|
||||
->method('transaction')
|
||||
->will($this->returnCallback(function ($cb) use ($redisTransaction) {
|
||||
$cb($redisTransaction);
|
||||
}));
|
||||
|
||||
$record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34));
|
||||
|
||||
$handler = new RedisHandler($redis, 'key', Logger::DEBUG, true, 10);
|
||||
$handler->setFormatter(new LineFormatter("%message%"));
|
||||
$handler->handle($record);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Exception;
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
use PHPUnit_Framework_MockObject_MockObject as MockObject;
|
||||
|
||||
/**
|
||||
* @author Erik Johansson <erik.pm.johansson@gmail.com>
|
||||
* @see https://rollbar.com/docs/notifier/rollbar-php/
|
||||
*
|
||||
* @coversDefaultClass Monolog\Handler\RollbarHandler
|
||||
*/
|
||||
class RollbarHandlerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var MockObject
|
||||
*/
|
||||
private $rollbarNotifier;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $reportedExceptionArguments = null;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->setupRollbarNotifierMock();
|
||||
}
|
||||
|
||||
/**
|
||||
* When reporting exceptions to Rollbar the
|
||||
* level has to be set in the payload data
|
||||
*/
|
||||
public function testExceptionLogLevel()
|
||||
{
|
||||
$handler = $this->createHandler();
|
||||
|
||||
$handler->handle($this->createExceptionRecord(Logger::DEBUG));
|
||||
|
||||
$this->assertEquals('debug', $this->reportedExceptionArguments['payload']['level']);
|
||||
}
|
||||
|
||||
private function setupRollbarNotifierMock()
|
||||
{
|
||||
$this->rollbarNotifier = $this->getMockBuilder('RollbarNotifier')
|
||||
->setMethods(array('report_message', 'report_exception', 'flush'))
|
||||
->getMock();
|
||||
|
||||
$that = $this;
|
||||
|
||||
$this->rollbarNotifier
|
||||
->expects($this->any())
|
||||
->method('report_exception')
|
||||
->willReturnCallback(function ($exception, $context, $payload) use ($that) {
|
||||
$that->reportedExceptionArguments = compact('exception', 'context', 'payload');
|
||||
});
|
||||
}
|
||||
|
||||
private function createHandler()
|
||||
{
|
||||
return new RollbarHandler($this->rollbarNotifier, Logger::DEBUG);
|
||||
}
|
||||
|
||||
private function createExceptionRecord($level = Logger::DEBUG, $message = 'test', $exception = null)
|
||||
{
|
||||
return $this->getRecord($level, $message, array(
|
||||
'exception' => $exception ?: new Exception()
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
use PHPUnit_Framework_Error_Deprecated;
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\RotatingFileHandler
|
||||
*/
|
||||
class RotatingFileHandlerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* This var should be private but then the anonymous function
|
||||
* in the `setUp` method won't be able to set it. `$this` cant't
|
||||
* be used in the anonymous function in `setUp` because PHP 5.3
|
||||
* does not support it.
|
||||
*/
|
||||
public $lastError;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$dir = __DIR__.'/Fixtures';
|
||||
chmod($dir, 0777);
|
||||
if (!is_writable($dir)) {
|
||||
$this->markTestSkipped($dir.' must be writable to test the RotatingFileHandler.');
|
||||
}
|
||||
$this->lastError = null;
|
||||
$self = $this;
|
||||
// workaround with &$self used for PHP 5.3
|
||||
set_error_handler(function($code, $message) use (&$self) {
|
||||
$self->lastError = array(
|
||||
'code' => $code,
|
||||
'message' => $message,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
private function assertErrorWasTriggered($code, $message)
|
||||
{
|
||||
if (empty($this->lastError)) {
|
||||
$this->fail(
|
||||
sprintf(
|
||||
'Failed asserting that error with code `%d` and message `%s` was triggered',
|
||||
$code,
|
||||
$message
|
||||
)
|
||||
);
|
||||
}
|
||||
$this->assertEquals($code, $this->lastError['code'], sprintf('Expected an error with code %d to be triggered, got `%s` instead', $code, $this->lastError['code']));
|
||||
$this->assertEquals($message, $this->lastError['message'], sprintf('Expected an error with message `%d` to be triggered, got `%s` instead', $message, $this->lastError['message']));
|
||||
}
|
||||
|
||||
public function testRotationCreatesNewFile()
|
||||
{
|
||||
touch(__DIR__.'/Fixtures/foo-'.date('Y-m-d', time() - 86400).'.rot');
|
||||
|
||||
$handler = new RotatingFileHandler(__DIR__.'/Fixtures/foo.rot');
|
||||
$handler->setFormatter($this->getIdentityFormatter());
|
||||
$handler->handle($this->getRecord());
|
||||
|
||||
$log = __DIR__.'/Fixtures/foo-'.date('Y-m-d').'.rot';
|
||||
$this->assertTrue(file_exists($log));
|
||||
$this->assertEquals('test', file_get_contents($log));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider rotationTests
|
||||
*/
|
||||
public function testRotation($createFile, $dateFormat, $timeCallback)
|
||||
{
|
||||
touch($old1 = __DIR__.'/Fixtures/foo-'.date($dateFormat, $timeCallback(-1)).'.rot');
|
||||
touch($old2 = __DIR__.'/Fixtures/foo-'.date($dateFormat, $timeCallback(-2)).'.rot');
|
||||
touch($old3 = __DIR__.'/Fixtures/foo-'.date($dateFormat, $timeCallback(-3)).'.rot');
|
||||
touch($old4 = __DIR__.'/Fixtures/foo-'.date($dateFormat, $timeCallback(-4)).'.rot');
|
||||
|
||||
$log = __DIR__.'/Fixtures/foo-'.date($dateFormat).'.rot';
|
||||
|
||||
if ($createFile) {
|
||||
touch($log);
|
||||
}
|
||||
|
||||
$handler = new RotatingFileHandler(__DIR__.'/Fixtures/foo.rot', 2);
|
||||
$handler->setFormatter($this->getIdentityFormatter());
|
||||
$handler->setFilenameFormat('{filename}-{date}', $dateFormat);
|
||||
$handler->handle($this->getRecord());
|
||||
|
||||
$handler->close();
|
||||
|
||||
$this->assertTrue(file_exists($log));
|
||||
$this->assertTrue(file_exists($old1));
|
||||
$this->assertEquals($createFile, file_exists($old2));
|
||||
$this->assertEquals($createFile, file_exists($old3));
|
||||
$this->assertEquals($createFile, file_exists($old4));
|
||||
$this->assertEquals('test', file_get_contents($log));
|
||||
}
|
||||
|
||||
public function rotationTests()
|
||||
{
|
||||
$now = time();
|
||||
$dayCallback = function($ago) use ($now) {
|
||||
return $now + 86400 * $ago;
|
||||
};
|
||||
$monthCallback = function($ago) {
|
||||
return gmmktime(0, 0, 0, date('n') + $ago, 1, date('Y'));
|
||||
};
|
||||
$yearCallback = function($ago) {
|
||||
return gmmktime(0, 0, 0, 1, 1, date('Y') + $ago);
|
||||
};
|
||||
|
||||
return array(
|
||||
'Rotation is triggered when the file of the current day is not present'
|
||||
=> array(true, RotatingFileHandler::FILE_PER_DAY, $dayCallback),
|
||||
'Rotation is not triggered when the file of the current day is already present'
|
||||
=> array(false, RotatingFileHandler::FILE_PER_DAY, $dayCallback),
|
||||
|
||||
'Rotation is triggered when the file of the current month is not present'
|
||||
=> array(true, RotatingFileHandler::FILE_PER_MONTH, $monthCallback),
|
||||
'Rotation is not triggered when the file of the current month is already present'
|
||||
=> array(false, RotatingFileHandler::FILE_PER_MONTH, $monthCallback),
|
||||
|
||||
'Rotation is triggered when the file of the current year is not present'
|
||||
=> array(true, RotatingFileHandler::FILE_PER_YEAR, $yearCallback),
|
||||
'Rotation is not triggered when the file of the current year is already present'
|
||||
=> array(false, RotatingFileHandler::FILE_PER_YEAR, $yearCallback),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dateFormatProvider
|
||||
*/
|
||||
public function testAllowOnlyFixedDefinedDateFormats($dateFormat, $valid)
|
||||
{
|
||||
$handler = new RotatingFileHandler(__DIR__.'/Fixtures/foo.rot', 2);
|
||||
$handler->setFilenameFormat('{filename}-{date}', $dateFormat);
|
||||
if (!$valid) {
|
||||
$this->assertErrorWasTriggered(
|
||||
E_USER_DEPRECATED,
|
||||
'Invalid date format - format must be one of RotatingFileHandler::FILE_PER_DAY ("Y-m-d"), '.
|
||||
'RotatingFileHandler::FILE_PER_MONTH ("Y-m") or RotatingFileHandler::FILE_PER_YEAR ("Y"), '.
|
||||
'or you can set one of the date formats using slashes, underscores and/or dots instead of dashes.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function dateFormatProvider()
|
||||
{
|
||||
return array(
|
||||
array(RotatingFileHandler::FILE_PER_DAY, true),
|
||||
array(RotatingFileHandler::FILE_PER_MONTH, true),
|
||||
array(RotatingFileHandler::FILE_PER_YEAR, true),
|
||||
array('m-d-Y', false),
|
||||
array('Y-m-d-h-i', false)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider filenameFormatProvider
|
||||
*/
|
||||
public function testDisallowFilenameFormatsWithoutDate($filenameFormat, $valid)
|
||||
{
|
||||
$handler = new RotatingFileHandler(__DIR__.'/Fixtures/foo.rot', 2);
|
||||
$handler->setFilenameFormat($filenameFormat, RotatingFileHandler::FILE_PER_DAY);
|
||||
if (!$valid) {
|
||||
$this->assertErrorWasTriggered(
|
||||
E_USER_DEPRECATED,
|
||||
'Invalid filename format - format should contain at least `{date}`, because otherwise rotating is impossible.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function filenameFormatProvider()
|
||||
{
|
||||
return array(
|
||||
array('{filename}', false),
|
||||
array('{filename}-{date}', true),
|
||||
array('{date}', true),
|
||||
array('foobar-{date}', true),
|
||||
array('foo-{date}-bar', true),
|
||||
array('{date}-foobar', true),
|
||||
array('foobar', false),
|
||||
);
|
||||
}
|
||||
|
||||
public function testReuseCurrentFile()
|
||||
{
|
||||
$log = __DIR__.'/Fixtures/foo-'.date('Y-m-d').'.rot';
|
||||
file_put_contents($log, "foo");
|
||||
$handler = new RotatingFileHandler(__DIR__.'/Fixtures/foo.rot');
|
||||
$handler->setFormatter($this->getIdentityFormatter());
|
||||
$handler->handle($this->getRecord());
|
||||
$this->assertEquals('footest', file_get_contents($log));
|
||||
}
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
foreach (glob(__DIR__.'/Fixtures/*.rot') as $file) {
|
||||
unlink($file);
|
||||
}
|
||||
restore_error_handler();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\SamplingHandler::handle
|
||||
*/
|
||||
class SamplingHandlerTest extends TestCase
|
||||
{
|
||||
public function testHandle()
|
||||
{
|
||||
$testHandler = new TestHandler();
|
||||
$handler = new SamplingHandler($testHandler, 2);
|
||||
for ($i = 0; $i < 10000; $i++) {
|
||||
$handler->handle($this->getRecord());
|
||||
}
|
||||
$count = count($testHandler->getRecords());
|
||||
// $count should be half of 10k, so between 4k and 6k
|
||||
$this->assertLessThan(6000, $count);
|
||||
$this->assertGreaterThan(4000, $count);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,387 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler\Slack;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Monolog\TestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass Monolog\Handler\Slack\SlackRecord
|
||||
*/
|
||||
class SlackRecordTest extends TestCase
|
||||
{
|
||||
private $jsonPrettyPrintFlag;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->jsonPrettyPrintFlag = defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : 128;
|
||||
}
|
||||
|
||||
public function dataGetAttachmentColor()
|
||||
{
|
||||
return array(
|
||||
array(Logger::DEBUG, SlackRecord::COLOR_DEFAULT),
|
||||
array(Logger::INFO, SlackRecord::COLOR_GOOD),
|
||||
array(Logger::NOTICE, SlackRecord::COLOR_GOOD),
|
||||
array(Logger::WARNING, SlackRecord::COLOR_WARNING),
|
||||
array(Logger::ERROR, SlackRecord::COLOR_DANGER),
|
||||
array(Logger::CRITICAL, SlackRecord::COLOR_DANGER),
|
||||
array(Logger::ALERT, SlackRecord::COLOR_DANGER),
|
||||
array(Logger::EMERGENCY, SlackRecord::COLOR_DANGER),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataGetAttachmentColor
|
||||
* @param int $logLevel
|
||||
* @param string $expectedColour RGB hex color or name of Slack color
|
||||
* @covers ::getAttachmentColor
|
||||
*/
|
||||
public function testGetAttachmentColor($logLevel, $expectedColour)
|
||||
{
|
||||
$slackRecord = new SlackRecord();
|
||||
$this->assertSame(
|
||||
$expectedColour,
|
||||
$slackRecord->getAttachmentColor($logLevel)
|
||||
);
|
||||
}
|
||||
|
||||
public function testAddsChannel()
|
||||
{
|
||||
$channel = '#test';
|
||||
$record = new SlackRecord($channel);
|
||||
$data = $record->getSlackData($this->getRecord());
|
||||
|
||||
$this->assertArrayHasKey('channel', $data);
|
||||
$this->assertSame($channel, $data['channel']);
|
||||
}
|
||||
|
||||
public function testNoUsernameByDefault()
|
||||
{
|
||||
$record = new SlackRecord();
|
||||
$data = $record->getSlackData($this->getRecord());
|
||||
|
||||
$this->assertArrayNotHasKey('username', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function dataStringify()
|
||||
{
|
||||
$jsonPrettyPrintFlag = defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : 128;
|
||||
|
||||
$multipleDimensions = array(array(1, 2));
|
||||
$numericKeys = array('library' => 'monolog');
|
||||
$singleDimension = array(1, 'Hello', 'Jordi');
|
||||
|
||||
return array(
|
||||
array(array(), '[]'),
|
||||
array($multipleDimensions, json_encode($multipleDimensions, $jsonPrettyPrintFlag)),
|
||||
array($numericKeys, json_encode($numericKeys, $jsonPrettyPrintFlag)),
|
||||
array($singleDimension, json_encode($singleDimension))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataStringify
|
||||
*/
|
||||
public function testStringify($fields, $expectedResult)
|
||||
{
|
||||
$slackRecord = new SlackRecord(
|
||||
'#test',
|
||||
'test',
|
||||
true,
|
||||
null,
|
||||
true,
|
||||
true
|
||||
);
|
||||
|
||||
$this->assertSame($expectedResult, $slackRecord->stringify($fields));
|
||||
}
|
||||
|
||||
public function testAddsCustomUsername()
|
||||
{
|
||||
$username = 'Monolog bot';
|
||||
$record = new SlackRecord(null, $username);
|
||||
$data = $record->getSlackData($this->getRecord());
|
||||
|
||||
$this->assertArrayHasKey('username', $data);
|
||||
$this->assertSame($username, $data['username']);
|
||||
}
|
||||
|
||||
public function testNoIcon()
|
||||
{
|
||||
$record = new SlackRecord();
|
||||
$data = $record->getSlackData($this->getRecord());
|
||||
|
||||
$this->assertArrayNotHasKey('icon_emoji', $data);
|
||||
}
|
||||
|
||||
public function testAddsIcon()
|
||||
{
|
||||
$record = $this->getRecord();
|
||||
$slackRecord = new SlackRecord(null, null, false, 'ghost');
|
||||
$data = $slackRecord->getSlackData($record);
|
||||
|
||||
$slackRecord2 = new SlackRecord(null, null, false, 'http://github.com/Seldaek/monolog');
|
||||
$data2 = $slackRecord2->getSlackData($record);
|
||||
|
||||
$this->assertArrayHasKey('icon_emoji', $data);
|
||||
$this->assertSame(':ghost:', $data['icon_emoji']);
|
||||
$this->assertArrayHasKey('icon_url', $data2);
|
||||
$this->assertSame('http://github.com/Seldaek/monolog', $data2['icon_url']);
|
||||
}
|
||||
|
||||
public function testAttachmentsNotPresentIfNoAttachment()
|
||||
{
|
||||
$record = new SlackRecord(null, null, false);
|
||||
$data = $record->getSlackData($this->getRecord());
|
||||
|
||||
$this->assertArrayNotHasKey('attachments', $data);
|
||||
}
|
||||
|
||||
public function testAddsOneAttachment()
|
||||
{
|
||||
$record = new SlackRecord();
|
||||
$data = $record->getSlackData($this->getRecord());
|
||||
|
||||
$this->assertArrayHasKey('attachments', $data);
|
||||
$this->assertArrayHasKey(0, $data['attachments']);
|
||||
$this->assertInternalType('array', $data['attachments'][0]);
|
||||
}
|
||||
|
||||
public function testTextEqualsMessageIfNoAttachment()
|
||||
{
|
||||
$message = 'Test message';
|
||||
$record = new SlackRecord(null, null, false);
|
||||
$data = $record->getSlackData($this->getRecord(Logger::WARNING, $message));
|
||||
|
||||
$this->assertArrayHasKey('text', $data);
|
||||
$this->assertSame($message, $data['text']);
|
||||
}
|
||||
|
||||
public function testTextEqualsFormatterOutput()
|
||||
{
|
||||
$formatter = $this->getMock('Monolog\\Formatter\\FormatterInterface');
|
||||
$formatter
|
||||
->expects($this->any())
|
||||
->method('format')
|
||||
->will($this->returnCallback(function ($record) { return $record['message'] . 'test'; }));
|
||||
|
||||
$formatter2 = $this->getMock('Monolog\\Formatter\\FormatterInterface');
|
||||
$formatter2
|
||||
->expects($this->any())
|
||||
->method('format')
|
||||
->will($this->returnCallback(function ($record) { return $record['message'] . 'test1'; }));
|
||||
|
||||
$message = 'Test message';
|
||||
$record = new SlackRecord(null, null, false, null, false, false, array(), $formatter);
|
||||
$data = $record->getSlackData($this->getRecord(Logger::WARNING, $message));
|
||||
|
||||
$this->assertArrayHasKey('text', $data);
|
||||
$this->assertSame($message . 'test', $data['text']);
|
||||
|
||||
$record->setFormatter($formatter2);
|
||||
$data = $record->getSlackData($this->getRecord(Logger::WARNING, $message));
|
||||
|
||||
$this->assertArrayHasKey('text', $data);
|
||||
$this->assertSame($message . 'test1', $data['text']);
|
||||
}
|
||||
|
||||
public function testAddsFallbackAndTextToAttachment()
|
||||
{
|
||||
$message = 'Test message';
|
||||
$record = new SlackRecord(null);
|
||||
$data = $record->getSlackData($this->getRecord(Logger::WARNING, $message));
|
||||
|
||||
$this->assertSame($message, $data['attachments'][0]['text']);
|
||||
$this->assertSame($message, $data['attachments'][0]['fallback']);
|
||||
}
|
||||
|
||||
public function testMapsLevelToColorAttachmentColor()
|
||||
{
|
||||
$record = new SlackRecord(null);
|
||||
$errorLoggerRecord = $this->getRecord(Logger::ERROR);
|
||||
$emergencyLoggerRecord = $this->getRecord(Logger::EMERGENCY);
|
||||
$warningLoggerRecord = $this->getRecord(Logger::WARNING);
|
||||
$infoLoggerRecord = $this->getRecord(Logger::INFO);
|
||||
$debugLoggerRecord = $this->getRecord(Logger::DEBUG);
|
||||
|
||||
$data = $record->getSlackData($errorLoggerRecord);
|
||||
$this->assertSame(SlackRecord::COLOR_DANGER, $data['attachments'][0]['color']);
|
||||
|
||||
$data = $record->getSlackData($emergencyLoggerRecord);
|
||||
$this->assertSame(SlackRecord::COLOR_DANGER, $data['attachments'][0]['color']);
|
||||
|
||||
$data = $record->getSlackData($warningLoggerRecord);
|
||||
$this->assertSame(SlackRecord::COLOR_WARNING, $data['attachments'][0]['color']);
|
||||
|
||||
$data = $record->getSlackData($infoLoggerRecord);
|
||||
$this->assertSame(SlackRecord::COLOR_GOOD, $data['attachments'][0]['color']);
|
||||
|
||||
$data = $record->getSlackData($debugLoggerRecord);
|
||||
$this->assertSame(SlackRecord::COLOR_DEFAULT, $data['attachments'][0]['color']);
|
||||
}
|
||||
|
||||
public function testAddsShortAttachmentWithoutContextAndExtra()
|
||||
{
|
||||
$level = Logger::ERROR;
|
||||
$levelName = Logger::getLevelName($level);
|
||||
$record = new SlackRecord(null, null, true, null, true);
|
||||
$data = $record->getSlackData($this->getRecord($level, 'test', array('test' => 1)));
|
||||
|
||||
$attachment = $data['attachments'][0];
|
||||
$this->assertArrayHasKey('title', $attachment);
|
||||
$this->assertArrayHasKey('fields', $attachment);
|
||||
$this->assertSame($levelName, $attachment['title']);
|
||||
$this->assertSame(array(), $attachment['fields']);
|
||||
}
|
||||
|
||||
public function testAddsShortAttachmentWithContextAndExtra()
|
||||
{
|
||||
$level = Logger::ERROR;
|
||||
$levelName = Logger::getLevelName($level);
|
||||
$context = array('test' => 1);
|
||||
$extra = array('tags' => array('web'));
|
||||
$record = new SlackRecord(null, null, true, null, true, true);
|
||||
$loggerRecord = $this->getRecord($level, 'test', $context);
|
||||
$loggerRecord['extra'] = $extra;
|
||||
$data = $record->getSlackData($loggerRecord);
|
||||
|
||||
$attachment = $data['attachments'][0];
|
||||
$this->assertArrayHasKey('title', $attachment);
|
||||
$this->assertArrayHasKey('fields', $attachment);
|
||||
$this->assertCount(2, $attachment['fields']);
|
||||
$this->assertSame($levelName, $attachment['title']);
|
||||
$this->assertSame(
|
||||
array(
|
||||
array(
|
||||
'title' => 'Extra',
|
||||
'value' => sprintf('```%s```', json_encode($extra, $this->jsonPrettyPrintFlag)),
|
||||
'short' => false
|
||||
),
|
||||
array(
|
||||
'title' => 'Context',
|
||||
'value' => sprintf('```%s```', json_encode($context, $this->jsonPrettyPrintFlag)),
|
||||
'short' => false
|
||||
)
|
||||
),
|
||||
$attachment['fields']
|
||||
);
|
||||
}
|
||||
|
||||
public function testAddsLongAttachmentWithoutContextAndExtra()
|
||||
{
|
||||
$level = Logger::ERROR;
|
||||
$levelName = Logger::getLevelName($level);
|
||||
$record = new SlackRecord(null, null, true, null);
|
||||
$data = $record->getSlackData($this->getRecord($level, 'test', array('test' => 1)));
|
||||
|
||||
$attachment = $data['attachments'][0];
|
||||
$this->assertArrayHasKey('title', $attachment);
|
||||
$this->assertArrayHasKey('fields', $attachment);
|
||||
$this->assertCount(1, $attachment['fields']);
|
||||
$this->assertSame('Message', $attachment['title']);
|
||||
$this->assertSame(
|
||||
array(array(
|
||||
'title' => 'Level',
|
||||
'value' => $levelName,
|
||||
'short' => false
|
||||
)),
|
||||
$attachment['fields']
|
||||
);
|
||||
}
|
||||
|
||||
public function testAddsLongAttachmentWithContextAndExtra()
|
||||
{
|
||||
$level = Logger::ERROR;
|
||||
$levelName = Logger::getLevelName($level);
|
||||
$context = array('test' => 1);
|
||||
$extra = array('tags' => array('web'));
|
||||
$record = new SlackRecord(null, null, true, null, false, true);
|
||||
$loggerRecord = $this->getRecord($level, 'test', $context);
|
||||
$loggerRecord['extra'] = $extra;
|
||||
$data = $record->getSlackData($loggerRecord);
|
||||
|
||||
$expectedFields = array(
|
||||
array(
|
||||
'title' => 'Level',
|
||||
'value' => $levelName,
|
||||
'short' => false,
|
||||
),
|
||||
array(
|
||||
'title' => 'tags',
|
||||
'value' => sprintf('```%s```', json_encode($extra['tags'])),
|
||||
'short' => false
|
||||
),
|
||||
array(
|
||||
'title' => 'test',
|
||||
'value' => $context['test'],
|
||||
'short' => false
|
||||
)
|
||||
);
|
||||
|
||||
$attachment = $data['attachments'][0];
|
||||
$this->assertArrayHasKey('title', $attachment);
|
||||
$this->assertArrayHasKey('fields', $attachment);
|
||||
$this->assertCount(3, $attachment['fields']);
|
||||
$this->assertSame('Message', $attachment['title']);
|
||||
$this->assertSame(
|
||||
$expectedFields,
|
||||
$attachment['fields']
|
||||
);
|
||||
}
|
||||
|
||||
public function testAddsTimestampToAttachment()
|
||||
{
|
||||
$record = $this->getRecord();
|
||||
$slackRecord = new SlackRecord();
|
||||
$data = $slackRecord->getSlackData($this->getRecord());
|
||||
|
||||
$attachment = $data['attachments'][0];
|
||||
$this->assertArrayHasKey('ts', $attachment);
|
||||
$this->assertSame($record['datetime']->getTimestamp(), $attachment['ts']);
|
||||
}
|
||||
|
||||
public function testExcludeExtraAndContextFields()
|
||||
{
|
||||
$record = $this->getRecord(
|
||||
Logger::WARNING,
|
||||
'test',
|
||||
array('info' => array('library' => 'monolog', 'author' => 'Jordi'))
|
||||
);
|
||||
$record['extra'] = array('tags' => array('web', 'cli'));
|
||||
|
||||
$slackRecord = new SlackRecord(null, null, true, null, false, true, array('context.info.library', 'extra.tags.1'));
|
||||
$data = $slackRecord->getSlackData($record);
|
||||
$attachment = $data['attachments'][0];
|
||||
|
||||
$expected = array(
|
||||
array(
|
||||
'title' => 'info',
|
||||
'value' => sprintf('```%s```', json_encode(array('author' => 'Jordi'), $this->jsonPrettyPrintFlag)),
|
||||
'short' => false
|
||||
),
|
||||
array(
|
||||
'title' => 'tags',
|
||||
'value' => sprintf('```%s```', json_encode(array('web'))),
|
||||
'short' => false
|
||||
),
|
||||
);
|
||||
|
||||
foreach ($expected as $field) {
|
||||
$this->assertNotFalse(array_search($field, $attachment['fields']));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
use Monolog\Formatter\LineFormatter;
|
||||
use Monolog\Handler\Slack\SlackRecord;
|
||||
|
||||
/**
|
||||
* @author Greg Kedzierski <greg@gregkedzierski.com>
|
||||
* @see https://api.slack.com/
|
||||
*/
|
||||
class SlackHandlerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var resource
|
||||
*/
|
||||
private $res;
|
||||
|
||||
/**
|
||||
* @var SlackHandler
|
||||
*/
|
||||
private $handler;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
if (!extension_loaded('openssl')) {
|
||||
$this->markTestSkipped('This test requires openssl to run');
|
||||
}
|
||||
}
|
||||
|
||||
public function testWriteHeader()
|
||||
{
|
||||
$this->createHandler();
|
||||
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
|
||||
fseek($this->res, 0);
|
||||
$content = fread($this->res, 1024);
|
||||
|
||||
$this->assertRegexp('/POST \/api\/chat.postMessage HTTP\/1.1\\r\\nHost: slack.com\\r\\nContent-Type: application\/x-www-form-urlencoded\\r\\nContent-Length: \d{2,4}\\r\\n\\r\\n/', $content);
|
||||
}
|
||||
|
||||
public function testWriteContent()
|
||||
{
|
||||
$this->createHandler();
|
||||
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
|
||||
fseek($this->res, 0);
|
||||
$content = fread($this->res, 1024);
|
||||
|
||||
$this->assertRegExp('/username=Monolog/', $content);
|
||||
$this->assertRegExp('/channel=channel1/', $content);
|
||||
$this->assertRegExp('/token=myToken/', $content);
|
||||
$this->assertRegExp('/attachments/', $content);
|
||||
}
|
||||
|
||||
public function testWriteContentUsesFormatterIfProvided()
|
||||
{
|
||||
$this->createHandler('myToken', 'channel1', 'Monolog', false);
|
||||
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
|
||||
fseek($this->res, 0);
|
||||
$content = fread($this->res, 1024);
|
||||
|
||||
$this->createHandler('myToken', 'channel1', 'Monolog', false);
|
||||
$this->handler->setFormatter(new LineFormatter('foo--%message%'));
|
||||
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test2'));
|
||||
fseek($this->res, 0);
|
||||
$content2 = fread($this->res, 1024);
|
||||
|
||||
$this->assertRegexp('/text=test1/', $content);
|
||||
$this->assertRegexp('/text=foo--test2/', $content2);
|
||||
}
|
||||
|
||||
public function testWriteContentWithEmoji()
|
||||
{
|
||||
$this->createHandler('myToken', 'channel1', 'Monolog', true, 'alien');
|
||||
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
|
||||
fseek($this->res, 0);
|
||||
$content = fread($this->res, 1024);
|
||||
|
||||
$this->assertRegexp('/icon_emoji=%3Aalien%3A/', $content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideLevelColors
|
||||
*/
|
||||
public function testWriteContentWithColors($level, $expectedColor)
|
||||
{
|
||||
$this->createHandler();
|
||||
$this->handler->handle($this->getRecord($level, 'test1'));
|
||||
fseek($this->res, 0);
|
||||
$content = fread($this->res, 1024);
|
||||
|
||||
$this->assertRegexp('/%22color%22%3A%22'.$expectedColor.'/', $content);
|
||||
}
|
||||
|
||||
public function testWriteContentWithPlainTextMessage()
|
||||
{
|
||||
$this->createHandler('myToken', 'channel1', 'Monolog', false);
|
||||
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
|
||||
fseek($this->res, 0);
|
||||
$content = fread($this->res, 1024);
|
||||
|
||||
$this->assertRegexp('/text=test1/', $content);
|
||||
}
|
||||
|
||||
public function provideLevelColors()
|
||||
{
|
||||
return array(
|
||||
array(Logger::DEBUG, urlencode(SlackRecord::COLOR_DEFAULT)),
|
||||
array(Logger::INFO, SlackRecord::COLOR_GOOD),
|
||||
array(Logger::NOTICE, SlackRecord::COLOR_GOOD),
|
||||
array(Logger::WARNING, SlackRecord::COLOR_WARNING),
|
||||
array(Logger::ERROR, SlackRecord::COLOR_DANGER),
|
||||
array(Logger::CRITICAL, SlackRecord::COLOR_DANGER),
|
||||
array(Logger::ALERT, SlackRecord::COLOR_DANGER),
|
||||
array(Logger::EMERGENCY,SlackRecord::COLOR_DANGER),
|
||||
);
|
||||
}
|
||||
|
||||
private function createHandler($token = 'myToken', $channel = 'channel1', $username = 'Monolog', $useAttachment = true, $iconEmoji = null, $useShortAttachment = false, $includeExtra = false)
|
||||
{
|
||||
$constructorArgs = array($token, $channel, $username, $useAttachment, $iconEmoji, Logger::DEBUG, true, $useShortAttachment, $includeExtra);
|
||||
$this->res = fopen('php://memory', 'a');
|
||||
$this->handler = $this->getMock(
|
||||
'\Monolog\Handler\SlackHandler',
|
||||
array('fsockopen', 'streamSetTimeout', 'closeSocket'),
|
||||
$constructorArgs
|
||||
);
|
||||
|
||||
$reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString');
|
||||
$reflectionProperty->setAccessible(true);
|
||||
$reflectionProperty->setValue($this->handler, 'localhost:1234');
|
||||
|
||||
$this->handler->expects($this->any())
|
||||
->method('fsockopen')
|
||||
->will($this->returnValue($this->res));
|
||||
$this->handler->expects($this->any())
|
||||
->method('streamSetTimeout')
|
||||
->will($this->returnValue(true));
|
||||
$this->handler->expects($this->any())
|
||||
->method('closeSocket')
|
||||
->will($this->returnValue(true));
|
||||
|
||||
$this->handler->setFormatter($this->getIdentityFormatter());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
use Monolog\Formatter\LineFormatter;
|
||||
use Monolog\Handler\Slack\SlackRecord;
|
||||
|
||||
/**
|
||||
* @author Haralan Dobrev <hkdobrev@gmail.com>
|
||||
* @see https://api.slack.com/incoming-webhooks
|
||||
* @coversDefaultClass Monolog\Handler\SlackWebhookHandler
|
||||
*/
|
||||
class SlackWebhookHandlerTest extends TestCase
|
||||
{
|
||||
const WEBHOOK_URL = 'https://hooks.slack.com/services/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E';
|
||||
|
||||
/**
|
||||
* @covers ::__construct
|
||||
* @covers ::getSlackRecord
|
||||
*/
|
||||
public function testConstructorMinimal()
|
||||
{
|
||||
$handler = new SlackWebhookHandler(self::WEBHOOK_URL);
|
||||
$record = $this->getRecord();
|
||||
$slackRecord = $handler->getSlackRecord();
|
||||
$this->assertInstanceOf('Monolog\Handler\Slack\SlackRecord', $slackRecord);
|
||||
$this->assertEquals(array(
|
||||
'attachments' => array(
|
||||
array(
|
||||
'fallback' => 'test',
|
||||
'text' => 'test',
|
||||
'color' => SlackRecord::COLOR_WARNING,
|
||||
'fields' => array(
|
||||
array(
|
||||
'title' => 'Level',
|
||||
'value' => 'WARNING',
|
||||
'short' => false,
|
||||
),
|
||||
),
|
||||
'title' => 'Message',
|
||||
'mrkdwn_in' => array('fields'),
|
||||
'ts' => $record['datetime']->getTimestamp(),
|
||||
),
|
||||
),
|
||||
), $slackRecord->getSlackData($record));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::__construct
|
||||
* @covers ::getSlackRecord
|
||||
*/
|
||||
public function testConstructorFull()
|
||||
{
|
||||
$handler = new SlackWebhookHandler(
|
||||
self::WEBHOOK_URL,
|
||||
'test-channel',
|
||||
'test-username',
|
||||
false,
|
||||
':ghost:',
|
||||
false,
|
||||
false,
|
||||
Logger::DEBUG,
|
||||
false
|
||||
);
|
||||
|
||||
$slackRecord = $handler->getSlackRecord();
|
||||
$this->assertInstanceOf('Monolog\Handler\Slack\SlackRecord', $slackRecord);
|
||||
$this->assertEquals(array(
|
||||
'username' => 'test-username',
|
||||
'text' => 'test',
|
||||
'channel' => 'test-channel',
|
||||
'icon_emoji' => ':ghost:',
|
||||
), $slackRecord->getSlackData($this->getRecord()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getFormatter
|
||||
*/
|
||||
public function testGetFormatter()
|
||||
{
|
||||
$handler = new SlackWebhookHandler(self::WEBHOOK_URL);
|
||||
$formatter = $handler->getFormatter();
|
||||
$this->assertInstanceOf('Monolog\Formatter\FormatterInterface', $formatter);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::setFormatter
|
||||
*/
|
||||
public function testSetFormatter()
|
||||
{
|
||||
$handler = new SlackWebhookHandler(self::WEBHOOK_URL);
|
||||
$formatter = new LineFormatter();
|
||||
$handler->setFormatter($formatter);
|
||||
$this->assertSame($formatter, $handler->getFormatter());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
|
||||
/**
|
||||
* @author Haralan Dobrev <hkdobrev@gmail.com>
|
||||
* @see https://slack.com/apps/A0F81R8ET-slackbot
|
||||
* @coversDefaultClass Monolog\Handler\SlackbotHandler
|
||||
*/
|
||||
class SlackbotHandlerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers ::__construct
|
||||
*/
|
||||
public function testConstructorMinimal()
|
||||
{
|
||||
$handler = new SlackbotHandler('test-team', 'test-token', 'test-channel');
|
||||
$this->assertInstanceOf('Monolog\Handler\AbstractProcessingHandler', $handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::__construct
|
||||
*/
|
||||
public function testConstructorFull()
|
||||
{
|
||||
$handler = new SlackbotHandler(
|
||||
'test-team',
|
||||
'test-token',
|
||||
'test-channel',
|
||||
Logger::DEBUG,
|
||||
false
|
||||
);
|
||||
$this->assertInstanceOf('Monolog\Handler\AbstractProcessingHandler', $handler);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,309 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
|
||||
/**
|
||||
* @author Pablo de Leon Belloc <pablolb@gmail.com>
|
||||
*/
|
||||
class SocketHandlerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var Monolog\Handler\SocketHandler
|
||||
*/
|
||||
private $handler;
|
||||
|
||||
/**
|
||||
* @var resource
|
||||
*/
|
||||
private $res;
|
||||
|
||||
/**
|
||||
* @expectedException UnexpectedValueException
|
||||
*/
|
||||
public function testInvalidHostname()
|
||||
{
|
||||
$this->createHandler('garbage://here');
|
||||
$this->writeRecord('data');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testBadConnectionTimeout()
|
||||
{
|
||||
$this->createHandler('localhost:1234');
|
||||
$this->handler->setConnectionTimeout(-1);
|
||||
}
|
||||
|
||||
public function testSetConnectionTimeout()
|
||||
{
|
||||
$this->createHandler('localhost:1234');
|
||||
$this->handler->setConnectionTimeout(10.1);
|
||||
$this->assertEquals(10.1, $this->handler->getConnectionTimeout());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testBadTimeout()
|
||||
{
|
||||
$this->createHandler('localhost:1234');
|
||||
$this->handler->setTimeout(-1);
|
||||
}
|
||||
|
||||
public function testSetTimeout()
|
||||
{
|
||||
$this->createHandler('localhost:1234');
|
||||
$this->handler->setTimeout(10.25);
|
||||
$this->assertEquals(10.25, $this->handler->getTimeout());
|
||||
}
|
||||
|
||||
public function testSetWritingTimeout()
|
||||
{
|
||||
$this->createHandler('localhost:1234');
|
||||
$this->handler->setWritingTimeout(10.25);
|
||||
$this->assertEquals(10.25, $this->handler->getWritingTimeout());
|
||||
}
|
||||
|
||||
public function testSetConnectionString()
|
||||
{
|
||||
$this->createHandler('tcp://localhost:9090');
|
||||
$this->assertEquals('tcp://localhost:9090', $this->handler->getConnectionString());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException UnexpectedValueException
|
||||
*/
|
||||
public function testExceptionIsThrownOnFsockopenError()
|
||||
{
|
||||
$this->setMockHandler(array('fsockopen'));
|
||||
$this->handler->expects($this->once())
|
||||
->method('fsockopen')
|
||||
->will($this->returnValue(false));
|
||||
$this->writeRecord('Hello world');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException UnexpectedValueException
|
||||
*/
|
||||
public function testExceptionIsThrownOnPfsockopenError()
|
||||
{
|
||||
$this->setMockHandler(array('pfsockopen'));
|
||||
$this->handler->expects($this->once())
|
||||
->method('pfsockopen')
|
||||
->will($this->returnValue(false));
|
||||
$this->handler->setPersistent(true);
|
||||
$this->writeRecord('Hello world');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException UnexpectedValueException
|
||||
*/
|
||||
public function testExceptionIsThrownIfCannotSetTimeout()
|
||||
{
|
||||
$this->setMockHandler(array('streamSetTimeout'));
|
||||
$this->handler->expects($this->once())
|
||||
->method('streamSetTimeout')
|
||||
->will($this->returnValue(false));
|
||||
$this->writeRecord('Hello world');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException RuntimeException
|
||||
*/
|
||||
public function testWriteFailsOnIfFwriteReturnsFalse()
|
||||
{
|
||||
$this->setMockHandler(array('fwrite'));
|
||||
|
||||
$callback = function ($arg) {
|
||||
$map = array(
|
||||
'Hello world' => 6,
|
||||
'world' => false,
|
||||
);
|
||||
|
||||
return $map[$arg];
|
||||
};
|
||||
|
||||
$this->handler->expects($this->exactly(2))
|
||||
->method('fwrite')
|
||||
->will($this->returnCallback($callback));
|
||||
|
||||
$this->writeRecord('Hello world');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException RuntimeException
|
||||
*/
|
||||
public function testWriteFailsIfStreamTimesOut()
|
||||
{
|
||||
$this->setMockHandler(array('fwrite', 'streamGetMetadata'));
|
||||
|
||||
$callback = function ($arg) {
|
||||
$map = array(
|
||||
'Hello world' => 6,
|
||||
'world' => 5,
|
||||
);
|
||||
|
||||
return $map[$arg];
|
||||
};
|
||||
|
||||
$this->handler->expects($this->exactly(1))
|
||||
->method('fwrite')
|
||||
->will($this->returnCallback($callback));
|
||||
$this->handler->expects($this->exactly(1))
|
||||
->method('streamGetMetadata')
|
||||
->will($this->returnValue(array('timed_out' => true)));
|
||||
|
||||
$this->writeRecord('Hello world');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException RuntimeException
|
||||
*/
|
||||
public function testWriteFailsOnIncompleteWrite()
|
||||
{
|
||||
$this->setMockHandler(array('fwrite', 'streamGetMetadata'));
|
||||
|
||||
$res = $this->res;
|
||||
$callback = function ($string) use ($res) {
|
||||
fclose($res);
|
||||
|
||||
return strlen('Hello');
|
||||
};
|
||||
|
||||
$this->handler->expects($this->exactly(1))
|
||||
->method('fwrite')
|
||||
->will($this->returnCallback($callback));
|
||||
$this->handler->expects($this->exactly(1))
|
||||
->method('streamGetMetadata')
|
||||
->will($this->returnValue(array('timed_out' => false)));
|
||||
|
||||
$this->writeRecord('Hello world');
|
||||
}
|
||||
|
||||
public function testWriteWithMemoryFile()
|
||||
{
|
||||
$this->setMockHandler();
|
||||
$this->writeRecord('test1');
|
||||
$this->writeRecord('test2');
|
||||
$this->writeRecord('test3');
|
||||
fseek($this->res, 0);
|
||||
$this->assertEquals('test1test2test3', fread($this->res, 1024));
|
||||
}
|
||||
|
||||
public function testWriteWithMock()
|
||||
{
|
||||
$this->setMockHandler(array('fwrite'));
|
||||
|
||||
$callback = function ($arg) {
|
||||
$map = array(
|
||||
'Hello world' => 6,
|
||||
'world' => 5,
|
||||
);
|
||||
|
||||
return $map[$arg];
|
||||
};
|
||||
|
||||
$this->handler->expects($this->exactly(2))
|
||||
->method('fwrite')
|
||||
->will($this->returnCallback($callback));
|
||||
|
||||
$this->writeRecord('Hello world');
|
||||
}
|
||||
|
||||
public function testClose()
|
||||
{
|
||||
$this->setMockHandler();
|
||||
$this->writeRecord('Hello world');
|
||||
$this->assertInternalType('resource', $this->res);
|
||||
$this->handler->close();
|
||||
$this->assertFalse(is_resource($this->res), "Expected resource to be closed after closing handler");
|
||||
}
|
||||
|
||||
public function testCloseDoesNotClosePersistentSocket()
|
||||
{
|
||||
$this->setMockHandler();
|
||||
$this->handler->setPersistent(true);
|
||||
$this->writeRecord('Hello world');
|
||||
$this->assertTrue(is_resource($this->res));
|
||||
$this->handler->close();
|
||||
$this->assertTrue(is_resource($this->res));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \RuntimeException
|
||||
*/
|
||||
public function testAvoidInfiniteLoopWhenNoDataIsWrittenForAWritingTimeoutSeconds()
|
||||
{
|
||||
$this->setMockHandler(array('fwrite', 'streamGetMetadata'));
|
||||
|
||||
$this->handler->expects($this->any())
|
||||
->method('fwrite')
|
||||
->will($this->returnValue(0));
|
||||
|
||||
$this->handler->expects($this->any())
|
||||
->method('streamGetMetadata')
|
||||
->will($this->returnValue(array('timed_out' => false)));
|
||||
|
||||
$this->handler->setWritingTimeout(1);
|
||||
|
||||
$this->writeRecord('Hello world');
|
||||
}
|
||||
|
||||
private function createHandler($connectionString)
|
||||
{
|
||||
$this->handler = new SocketHandler($connectionString);
|
||||
$this->handler->setFormatter($this->getIdentityFormatter());
|
||||
}
|
||||
|
||||
private function writeRecord($string)
|
||||
{
|
||||
$this->handler->handle($this->getRecord(Logger::WARNING, $string));
|
||||
}
|
||||
|
||||
private function setMockHandler(array $methods = array())
|
||||
{
|
||||
$this->res = fopen('php://memory', 'a');
|
||||
|
||||
$defaultMethods = array('fsockopen', 'pfsockopen', 'streamSetTimeout');
|
||||
$newMethods = array_diff($methods, $defaultMethods);
|
||||
|
||||
$finalMethods = array_merge($defaultMethods, $newMethods);
|
||||
|
||||
$this->handler = $this->getMock(
|
||||
'\Monolog\Handler\SocketHandler', $finalMethods, array('localhost:1234')
|
||||
);
|
||||
|
||||
if (!in_array('fsockopen', $methods)) {
|
||||
$this->handler->expects($this->any())
|
||||
->method('fsockopen')
|
||||
->will($this->returnValue($this->res));
|
||||
}
|
||||
|
||||
if (!in_array('pfsockopen', $methods)) {
|
||||
$this->handler->expects($this->any())
|
||||
->method('pfsockopen')
|
||||
->will($this->returnValue($this->res));
|
||||
}
|
||||
|
||||
if (!in_array('streamSetTimeout', $methods)) {
|
||||
$this->handler->expects($this->any())
|
||||
->method('streamSetTimeout')
|
||||
->will($this->returnValue(true));
|
||||
}
|
||||
|
||||
$this->handler->setFormatter($this->getIdentityFormatter());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
|
||||
class StreamHandlerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers Monolog\Handler\StreamHandler::__construct
|
||||
* @covers Monolog\Handler\StreamHandler::write
|
||||
*/
|
||||
public function testWrite()
|
||||
{
|
||||
$handle = fopen('php://memory', 'a+');
|
||||
$handler = new StreamHandler($handle);
|
||||
$handler->setFormatter($this->getIdentityFormatter());
|
||||
$handler->handle($this->getRecord(Logger::WARNING, 'test'));
|
||||
$handler->handle($this->getRecord(Logger::WARNING, 'test2'));
|
||||
$handler->handle($this->getRecord(Logger::WARNING, 'test3'));
|
||||
fseek($handle, 0);
|
||||
$this->assertEquals('testtest2test3', fread($handle, 100));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\StreamHandler::close
|
||||
*/
|
||||
public function testCloseKeepsExternalHandlersOpen()
|
||||
{
|
||||
$handle = fopen('php://memory', 'a+');
|
||||
$handler = new StreamHandler($handle);
|
||||
$this->assertTrue(is_resource($handle));
|
||||
$handler->close();
|
||||
$this->assertTrue(is_resource($handle));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\StreamHandler::close
|
||||
*/
|
||||
public function testClose()
|
||||
{
|
||||
$handler = new StreamHandler('php://memory');
|
||||
$handler->handle($this->getRecord(Logger::WARNING, 'test'));
|
||||
$streamProp = new \ReflectionProperty('Monolog\Handler\StreamHandler', 'stream');
|
||||
$streamProp->setAccessible(true);
|
||||
$handle = $streamProp->getValue($handler);
|
||||
|
||||
$this->assertTrue(is_resource($handle));
|
||||
$handler->close();
|
||||
$this->assertFalse(is_resource($handle));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\StreamHandler::write
|
||||
*/
|
||||
public function testWriteCreatesTheStreamResource()
|
||||
{
|
||||
$handler = new StreamHandler('php://memory');
|
||||
$handler->handle($this->getRecord());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\StreamHandler::__construct
|
||||
* @covers Monolog\Handler\StreamHandler::write
|
||||
*/
|
||||
public function testWriteLocking()
|
||||
{
|
||||
$temp = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'monolog_locked_log';
|
||||
$handler = new StreamHandler($temp, Logger::DEBUG, true, null, true);
|
||||
$handler->handle($this->getRecord());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException LogicException
|
||||
* @covers Monolog\Handler\StreamHandler::__construct
|
||||
* @covers Monolog\Handler\StreamHandler::write
|
||||
*/
|
||||
public function testWriteMissingResource()
|
||||
{
|
||||
$handler = new StreamHandler(null);
|
||||
$handler->handle($this->getRecord());
|
||||
}
|
||||
|
||||
public function invalidArgumentProvider()
|
||||
{
|
||||
return array(
|
||||
array(1),
|
||||
array(array()),
|
||||
array(array('bogus://url')),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider invalidArgumentProvider
|
||||
* @expectedException InvalidArgumentException
|
||||
* @covers Monolog\Handler\StreamHandler::__construct
|
||||
*/
|
||||
public function testWriteInvalidArgument($invalidArgument)
|
||||
{
|
||||
$handler = new StreamHandler($invalidArgument);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException UnexpectedValueException
|
||||
* @covers Monolog\Handler\StreamHandler::__construct
|
||||
* @covers Monolog\Handler\StreamHandler::write
|
||||
*/
|
||||
public function testWriteInvalidResource()
|
||||
{
|
||||
$handler = new StreamHandler('bogus://url');
|
||||
$handler->handle($this->getRecord());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException UnexpectedValueException
|
||||
* @covers Monolog\Handler\StreamHandler::__construct
|
||||
* @covers Monolog\Handler\StreamHandler::write
|
||||
*/
|
||||
public function testWriteNonExistingResource()
|
||||
{
|
||||
$handler = new StreamHandler('ftp://foo/bar/baz/'.rand(0, 10000));
|
||||
$handler->handle($this->getRecord());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\StreamHandler::__construct
|
||||
* @covers Monolog\Handler\StreamHandler::write
|
||||
*/
|
||||
public function testWriteNonExistingPath()
|
||||
{
|
||||
$handler = new StreamHandler(sys_get_temp_dir().'/bar/'.rand(0, 10000).DIRECTORY_SEPARATOR.rand(0, 10000));
|
||||
$handler->handle($this->getRecord());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\StreamHandler::__construct
|
||||
* @covers Monolog\Handler\StreamHandler::write
|
||||
*/
|
||||
public function testWriteNonExistingFileResource()
|
||||
{
|
||||
$handler = new StreamHandler('file://'.sys_get_temp_dir().'/bar/'.rand(0, 10000).DIRECTORY_SEPARATOR.rand(0, 10000));
|
||||
$handler->handle($this->getRecord());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Exception
|
||||
* @expectedExceptionMessageRegExp /There is no existing directory at/
|
||||
* @covers Monolog\Handler\StreamHandler::__construct
|
||||
* @covers Monolog\Handler\StreamHandler::write
|
||||
*/
|
||||
public function testWriteNonExistingAndNotCreatablePath()
|
||||
{
|
||||
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
|
||||
$this->markTestSkipped('Permissions checks can not run on windows');
|
||||
}
|
||||
$handler = new StreamHandler('/foo/bar/'.rand(0, 10000).DIRECTORY_SEPARATOR.rand(0, 10000));
|
||||
$handler->handle($this->getRecord());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Exception
|
||||
* @expectedExceptionMessageRegExp /There is no existing directory at/
|
||||
* @covers Monolog\Handler\StreamHandler::__construct
|
||||
* @covers Monolog\Handler\StreamHandler::write
|
||||
*/
|
||||
public function testWriteNonExistingAndNotCreatableFileResource()
|
||||
{
|
||||
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
|
||||
$this->markTestSkipped('Permissions checks can not run on windows');
|
||||
}
|
||||
$handler = new StreamHandler('file:///foo/bar/'.rand(0, 10000).DIRECTORY_SEPARATOR.rand(0, 10000));
|
||||
$handler->handle($this->getRecord());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Monolog\TestCase;
|
||||
|
||||
class SwiftMailerHandlerTest extends TestCase
|
||||
{
|
||||
/** @var \Swift_Mailer|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $mailer;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->mailer = $this
|
||||
->getMockBuilder('Swift_Mailer')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
}
|
||||
|
||||
public function testMessageCreationIsLazyWhenUsingCallback()
|
||||
{
|
||||
$this->mailer->expects($this->never())
|
||||
->method('send');
|
||||
|
||||
$callback = function () {
|
||||
throw new \RuntimeException('Swift_Message creation callback should not have been called in this test');
|
||||
};
|
||||
$handler = new SwiftMailerHandler($this->mailer, $callback);
|
||||
|
||||
$records = array(
|
||||
$this->getRecord(Logger::DEBUG),
|
||||
$this->getRecord(Logger::INFO),
|
||||
);
|
||||
$handler->handleBatch($records);
|
||||
}
|
||||
|
||||
public function testMessageCanBeCustomizedGivenLoggedData()
|
||||
{
|
||||
// Wire Mailer to expect a specific Swift_Message with a customized Subject
|
||||
$expectedMessage = new \Swift_Message();
|
||||
$this->mailer->expects($this->once())
|
||||
->method('send')
|
||||
->with($this->callback(function ($value) use ($expectedMessage) {
|
||||
return $value instanceof \Swift_Message
|
||||
&& $value->getSubject() === 'Emergency'
|
||||
&& $value === $expectedMessage;
|
||||
}));
|
||||
|
||||
// Callback dynamically changes subject based on number of logged records
|
||||
$callback = function ($content, array $records) use ($expectedMessage) {
|
||||
$subject = count($records) > 0 ? 'Emergency' : 'Normal';
|
||||
$expectedMessage->setSubject($subject);
|
||||
|
||||
return $expectedMessage;
|
||||
};
|
||||
$handler = new SwiftMailerHandler($this->mailer, $callback);
|
||||
|
||||
// Logging 1 record makes this an Emergency
|
||||
$records = array(
|
||||
$this->getRecord(Logger::EMERGENCY),
|
||||
);
|
||||
$handler->handleBatch($records);
|
||||
}
|
||||
|
||||
public function testMessageSubjectFormatting()
|
||||
{
|
||||
// Wire Mailer to expect a specific Swift_Message with a customized Subject
|
||||
$messageTemplate = new \Swift_Message();
|
||||
$messageTemplate->setSubject('Alert: %level_name% %message%');
|
||||
$receivedMessage = null;
|
||||
|
||||
$this->mailer->expects($this->once())
|
||||
->method('send')
|
||||
->with($this->callback(function ($value) use (&$receivedMessage) {
|
||||
$receivedMessage = $value;
|
||||
return true;
|
||||
}));
|
||||
|
||||
$handler = new SwiftMailerHandler($this->mailer, $messageTemplate);
|
||||
|
||||
$records = array(
|
||||
$this->getRecord(Logger::EMERGENCY),
|
||||
);
|
||||
$handler->handleBatch($records);
|
||||
|
||||
$this->assertEquals('Alert: EMERGENCY test', $receivedMessage->getSubject());
|
||||
}
|
||||
|
||||
public function testMessageHaveUniqueId()
|
||||
{
|
||||
$messageTemplate = new \Swift_Message();
|
||||
$handler = new SwiftMailerHandler($this->mailer, $messageTemplate);
|
||||
|
||||
$method = new \ReflectionMethod('Monolog\Handler\SwiftMailerHandler', 'buildMessage');
|
||||
$method->setAccessible(true);
|
||||
$method->invokeArgs($handler, array($messageTemplate, array()));
|
||||
|
||||
$builtMessage1 = $method->invoke($handler, $messageTemplate, array());
|
||||
$builtMessage2 = $method->invoke($handler, $messageTemplate, array());
|
||||
|
||||
$this->assertFalse($builtMessage1->getId() === $builtMessage2->getId(), 'Two different messages have the same id');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\Logger;
|
||||
|
||||
class SyslogHandlerTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @covers Monolog\Handler\SyslogHandler::__construct
|
||||
*/
|
||||
public function testConstruct()
|
||||
{
|
||||
$handler = new SyslogHandler('test');
|
||||
$this->assertInstanceOf('Monolog\Handler\SyslogHandler', $handler);
|
||||
|
||||
$handler = new SyslogHandler('test', LOG_USER);
|
||||
$this->assertInstanceOf('Monolog\Handler\SyslogHandler', $handler);
|
||||
|
||||
$handler = new SyslogHandler('test', 'user');
|
||||
$this->assertInstanceOf('Monolog\Handler\SyslogHandler', $handler);
|
||||
|
||||
$handler = new SyslogHandler('test', LOG_USER, Logger::DEBUG, true, LOG_PERROR);
|
||||
$this->assertInstanceOf('Monolog\Handler\SyslogHandler', $handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\SyslogHandler::__construct
|
||||
*/
|
||||
public function testConstructInvalidFacility()
|
||||
{
|
||||
$this->setExpectedException('UnexpectedValueException');
|
||||
$handler = new SyslogHandler('test', 'unknown');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
|
||||
/**
|
||||
* @requires extension sockets
|
||||
*/
|
||||
class SyslogUdpHandlerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @expectedException UnexpectedValueException
|
||||
*/
|
||||
public function testWeValidateFacilities()
|
||||
{
|
||||
$handler = new SyslogUdpHandler("ip", null, "invalidFacility");
|
||||
}
|
||||
|
||||
public function testWeSplitIntoLines()
|
||||
{
|
||||
$time = '2014-01-07T12:34';
|
||||
$pid = getmypid();
|
||||
$host = gethostname();
|
||||
|
||||
$handler = $this->getMockBuilder('\Monolog\Handler\SyslogUdpHandler')
|
||||
->setConstructorArgs(array("127.0.0.1", 514, "authpriv"))
|
||||
->setMethods(array('getDateTime'))
|
||||
->getMock();
|
||||
|
||||
$handler->method('getDateTime')
|
||||
->willReturn($time);
|
||||
|
||||
$handler->setFormatter(new \Monolog\Formatter\ChromePHPFormatter());
|
||||
|
||||
$socket = $this->getMock('\Monolog\Handler\SyslogUdp\UdpSocket', array('write'), array('lol', 'lol'));
|
||||
$socket->expects($this->at(0))
|
||||
->method('write')
|
||||
->with("lol", "<".(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 - - ");
|
||||
|
||||
$handler->setSocket($socket);
|
||||
|
||||
$handler->handle($this->getRecordWithMessage("hej\nlol"));
|
||||
}
|
||||
|
||||
public function testSplitWorksOnEmptyMsg()
|
||||
{
|
||||
$handler = new SyslogUdpHandler("127.0.0.1", 514, "authpriv");
|
||||
$handler->setFormatter($this->getIdentityFormatter());
|
||||
|
||||
$socket = $this->getMock('\Monolog\Handler\SyslogUdp\UdpSocket', array('write'), array('lol', 'lol'));
|
||||
$socket->expects($this->never())
|
||||
->method('write');
|
||||
|
||||
$handler->setSocket($socket);
|
||||
|
||||
$handler->handle($this->getRecordWithMessage(null));
|
||||
}
|
||||
|
||||
protected function getRecordWithMessage($msg)
|
||||
{
|
||||
return array('message' => $msg, 'level' => \Monolog\Logger::WARNING, 'context' => null, 'extra' => array(), 'channel' => 'lol');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\TestHandler
|
||||
*/
|
||||
class TestHandlerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider methodProvider
|
||||
*/
|
||||
public function testHandler($method, $level)
|
||||
{
|
||||
$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->{'has'.$method.'ThatContains'}('test'), 'has'.$method.'ThatContains');
|
||||
$this->assertFalse($handler->{'has'.$method.'ThatPasses'}(function ($rec) {
|
||||
return true;
|
||||
}), 'has'.$method.'ThatPasses');
|
||||
$this->assertFalse($handler->{'has'.$method.'ThatMatches'}('/test\w+/'));
|
||||
$this->assertFalse($handler->{'has'.$method.'Records'}(), 'has'.$method.'Records');
|
||||
$handler->handle($record);
|
||||
|
||||
$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->{'has'.$method}('test'.$method), 'has'.$method);
|
||||
$this->assertTrue($handler->{'has'.$method.'ThatContains'}('test'), 'has'.$method.'ThatContains');
|
||||
$this->assertTrue($handler->{'has'.$method.'ThatPasses'}(function ($rec) {
|
||||
return true;
|
||||
}), 'has'.$method.'ThatPasses');
|
||||
$this->assertTrue($handler->{'has'.$method.'ThatMatches'}('/test\w+/'));
|
||||
$this->assertTrue($handler->{'has'.$method.'Records'}(), 'has'.$method.'Records');
|
||||
|
||||
$records = $handler->getRecords();
|
||||
unset($records[0]['formatted']);
|
||||
$this->assertEquals(array($record), $records);
|
||||
}
|
||||
|
||||
public function methodProvider()
|
||||
{
|
||||
return array(
|
||||
array('Emergency', Logger::EMERGENCY),
|
||||
array('Alert' , Logger::ALERT),
|
||||
array('Critical' , Logger::CRITICAL),
|
||||
array('Error' , Logger::ERROR),
|
||||
array('Warning' , Logger::WARNING),
|
||||
array('Info' , Logger::INFO),
|
||||
array('Notice' , Logger::NOTICE),
|
||||
array('Debug' , Logger::DEBUG),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Handler\SyslogUdp\UdpSocket;
|
||||
|
||||
/**
|
||||
* @requires extension sockets
|
||||
*/
|
||||
class UdpSocketTest extends TestCase
|
||||
{
|
||||
public function testWeDoNotTruncateShortMessages()
|
||||
{
|
||||
$socket = $this->getMock('\Monolog\Handler\SyslogUdp\UdpSocket', array('send'), array('lol', 'lol'));
|
||||
|
||||
$socket->expects($this->at(0))
|
||||
->method('send')
|
||||
->with("HEADER: The quick brown fox jumps over the lazy dog");
|
||||
|
||||
$socket->write("The quick brown fox jumps over the lazy dog", "HEADER: ");
|
||||
}
|
||||
|
||||
public function testLongMessagesAreTruncated()
|
||||
{
|
||||
$socket = $this->getMock('\Monolog\Handler\SyslogUdp\UdpSocket', array('send'), array('lol', 'lol'));
|
||||
|
||||
$truncatedString = str_repeat("derp", 16254).'d';
|
||||
|
||||
$socket->expects($this->exactly(1))
|
||||
->method('send')
|
||||
->with("HEADER" . $truncatedString);
|
||||
|
||||
$longString = str_repeat("derp", 20000);
|
||||
|
||||
$socket->write($longString, "HEADER");
|
||||
}
|
||||
|
||||
public function testDoubleCloseDoesNotError()
|
||||
{
|
||||
$socket = new UdpSocket('127.0.0.1', 514);
|
||||
$socket->close();
|
||||
$socket->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException LogicException
|
||||
*/
|
||||
public function testWriteAfterCloseErrors()
|
||||
{
|
||||
$socket = new UdpSocket('127.0.0.1', 514);
|
||||
$socket->close();
|
||||
$socket->write('foo', "HEADER");
|
||||
}
|
||||
}
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Logger;
|
||||
|
||||
class WhatFailureGroupHandlerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers Monolog\Handler\WhatFailureGroupHandler::__construct
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testConstructorOnlyTakesHandler()
|
||||
{
|
||||
new WhatFailureGroupHandler(array(new TestHandler(), "foo"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\WhatFailureGroupHandler::__construct
|
||||
* @covers Monolog\Handler\WhatFailureGroupHandler::handle
|
||||
*/
|
||||
public function testHandle()
|
||||
{
|
||||
$testHandlers = array(new TestHandler(), new TestHandler());
|
||||
$handler = new WhatFailureGroupHandler($testHandlers);
|
||||
$handler->handle($this->getRecord(Logger::DEBUG));
|
||||
$handler->handle($this->getRecord(Logger::INFO));
|
||||
foreach ($testHandlers as $test) {
|
||||
$this->assertTrue($test->hasDebugRecords());
|
||||
$this->assertTrue($test->hasInfoRecords());
|
||||
$this->assertTrue(count($test->getRecords()) === 2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\WhatFailureGroupHandler::handleBatch
|
||||
*/
|
||||
public function testHandleBatch()
|
||||
{
|
||||
$testHandlers = array(new TestHandler(), new TestHandler());
|
||||
$handler = new WhatFailureGroupHandler($testHandlers);
|
||||
$handler->handleBatch(array($this->getRecord(Logger::DEBUG), $this->getRecord(Logger::INFO)));
|
||||
foreach ($testHandlers as $test) {
|
||||
$this->assertTrue($test->hasDebugRecords());
|
||||
$this->assertTrue($test->hasInfoRecords());
|
||||
$this->assertTrue(count($test->getRecords()) === 2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\WhatFailureGroupHandler::isHandling
|
||||
*/
|
||||
public function testIsHandling()
|
||||
{
|
||||
$testHandlers = array(new TestHandler(Logger::ERROR), new TestHandler(Logger::WARNING));
|
||||
$handler = new WhatFailureGroupHandler($testHandlers);
|
||||
$this->assertTrue($handler->isHandling($this->getRecord(Logger::ERROR)));
|
||||
$this->assertTrue($handler->isHandling($this->getRecord(Logger::WARNING)));
|
||||
$this->assertFalse($handler->isHandling($this->getRecord(Logger::DEBUG)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\WhatFailureGroupHandler::handle
|
||||
*/
|
||||
public function testHandleUsesProcessors()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
$handler = new WhatFailureGroupHandler(array($test));
|
||||
$handler->pushProcessor(function ($record) {
|
||||
$record['extra']['foo'] = true;
|
||||
|
||||
return $record;
|
||||
});
|
||||
$handler->handle($this->getRecord(Logger::WARNING));
|
||||
$this->assertTrue($test->hasWarningRecords());
|
||||
$records = $test->getRecords();
|
||||
$this->assertTrue($records[0]['extra']['foo']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\WhatFailureGroupHandler::handle
|
||||
*/
|
||||
public function testHandleException()
|
||||
{
|
||||
$test = new TestHandler();
|
||||
$exception = new ExceptionTestHandler();
|
||||
$handler = new WhatFailureGroupHandler(array($exception, $test, $exception));
|
||||
$handler->pushProcessor(function ($record) {
|
||||
$record['extra']['foo'] = true;
|
||||
|
||||
return $record;
|
||||
});
|
||||
$handler->handle($this->getRecord(Logger::WARNING));
|
||||
$this->assertTrue($test->hasWarningRecords());
|
||||
$records = $test->getRecords();
|
||||
$this->assertTrue($records[0]['extra']['foo']);
|
||||
}
|
||||
}
|
||||
|
||||
class ExceptionTestHandler extends TestHandler
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function handle(array $record)
|
||||
{
|
||||
parent::handle($record);
|
||||
|
||||
throw new \Exception("ExceptionTestHandler::handle");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\TestCase;
|
||||
|
||||
class ZendMonitorHandlerTest extends TestCase
|
||||
{
|
||||
protected $zendMonitorHandler;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
if (!function_exists('zend_monitor_custom_event')) {
|
||||
$this->markTestSkipped('ZendServer is not installed');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\ZendMonitorHandler::write
|
||||
*/
|
||||
public function testWrite()
|
||||
{
|
||||
$record = $this->getRecord();
|
||||
$formatterResult = array(
|
||||
'message' => $record['message'],
|
||||
);
|
||||
|
||||
$zendMonitor = $this->getMockBuilder('Monolog\Handler\ZendMonitorHandler')
|
||||
->setMethods(array('writeZendMonitorCustomEvent', 'getDefaultFormatter'))
|
||||
->getMock();
|
||||
|
||||
$formatterMock = $this->getMockBuilder('Monolog\Formatter\NormalizerFormatter')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$formatterMock->expects($this->once())
|
||||
->method('format')
|
||||
->will($this->returnValue($formatterResult));
|
||||
|
||||
$zendMonitor->expects($this->once())
|
||||
->method('getDefaultFormatter')
|
||||
->will($this->returnValue($formatterMock));
|
||||
|
||||
$levelMap = $zendMonitor->getLevelMap();
|
||||
|
||||
$zendMonitor->expects($this->once())
|
||||
->method('writeZendMonitorCustomEvent')
|
||||
->with($levelMap[$record['level']], $record['message'], $formatterResult);
|
||||
|
||||
$zendMonitor->handle($record);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Handler\ZendMonitorHandler::getDefaultFormatter
|
||||
*/
|
||||
public function testGetDefaultFormatterReturnsNormalizerFormatter()
|
||||
{
|
||||
$zendMonitor = new ZendMonitorHandler();
|
||||
$this->assertInstanceOf('Monolog\Formatter\NormalizerFormatter', $zendMonitor->getDefaultFormatter());
|
||||
}
|
||||
}
|
||||
+548
@@ -0,0 +1,548 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog;
|
||||
|
||||
use Monolog\Processor\WebProcessor;
|
||||
use Monolog\Handler\TestHandler;
|
||||
|
||||
class LoggerTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @covers Monolog\Logger::getName
|
||||
*/
|
||||
public function testGetName()
|
||||
{
|
||||
$logger = new Logger('foo');
|
||||
$this->assertEquals('foo', $logger->getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Logger::getLevelName
|
||||
*/
|
||||
public function testGetLevelName()
|
||||
{
|
||||
$this->assertEquals('ERROR', Logger::getLevelName(Logger::ERROR));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Logger::withName
|
||||
*/
|
||||
public function testWithName()
|
||||
{
|
||||
$first = new Logger('first', array($handler = new TestHandler()));
|
||||
$second = $first->withName('second');
|
||||
|
||||
$this->assertSame('first', $first->getName());
|
||||
$this->assertSame('second', $second->getName());
|
||||
$this->assertSame($handler, $second->popHandler());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Logger::toMonologLevel
|
||||
*/
|
||||
public function testConvertPSR3ToMonologLevel()
|
||||
{
|
||||
$this->assertEquals(Logger::toMonologLevel('debug'), 100);
|
||||
$this->assertEquals(Logger::toMonologLevel('info'), 200);
|
||||
$this->assertEquals(Logger::toMonologLevel('notice'), 250);
|
||||
$this->assertEquals(Logger::toMonologLevel('warning'), 300);
|
||||
$this->assertEquals(Logger::toMonologLevel('error'), 400);
|
||||
$this->assertEquals(Logger::toMonologLevel('critical'), 500);
|
||||
$this->assertEquals(Logger::toMonologLevel('alert'), 550);
|
||||
$this->assertEquals(Logger::toMonologLevel('emergency'), 600);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Logger::getLevelName
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testGetLevelNameThrows()
|
||||
{
|
||||
Logger::getLevelName(5);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Logger::__construct
|
||||
*/
|
||||
public function testChannel()
|
||||
{
|
||||
$logger = new Logger('foo');
|
||||
$handler = new TestHandler;
|
||||
$logger->pushHandler($handler);
|
||||
$logger->addWarning('test');
|
||||
list($record) = $handler->getRecords();
|
||||
$this->assertEquals('foo', $record['channel']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Logger::addRecord
|
||||
*/
|
||||
public function testLog()
|
||||
{
|
||||
$logger = new Logger(__METHOD__);
|
||||
|
||||
$handler = $this->getMock('Monolog\Handler\NullHandler', array('handle'));
|
||||
$handler->expects($this->once())
|
||||
->method('handle');
|
||||
$logger->pushHandler($handler);
|
||||
|
||||
$this->assertTrue($logger->addWarning('test'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Logger::addRecord
|
||||
*/
|
||||
public function testLogNotHandled()
|
||||
{
|
||||
$logger = new Logger(__METHOD__);
|
||||
|
||||
$handler = $this->getMock('Monolog\Handler\NullHandler', array('handle'), array(Logger::ERROR));
|
||||
$handler->expects($this->never())
|
||||
->method('handle');
|
||||
$logger->pushHandler($handler);
|
||||
|
||||
$this->assertFalse($logger->addWarning('test'));
|
||||
}
|
||||
|
||||
public function testHandlersInCtor()
|
||||
{
|
||||
$handler1 = new TestHandler;
|
||||
$handler2 = new TestHandler;
|
||||
$logger = new Logger(__METHOD__, array($handler1, $handler2));
|
||||
|
||||
$this->assertEquals($handler1, $logger->popHandler());
|
||||
$this->assertEquals($handler2, $logger->popHandler());
|
||||
}
|
||||
|
||||
public function testProcessorsInCtor()
|
||||
{
|
||||
$processor1 = new WebProcessor;
|
||||
$processor2 = new WebProcessor;
|
||||
$logger = new Logger(__METHOD__, array(), array($processor1, $processor2));
|
||||
|
||||
$this->assertEquals($processor1, $logger->popProcessor());
|
||||
$this->assertEquals($processor2, $logger->popProcessor());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Logger::pushHandler
|
||||
* @covers Monolog\Logger::popHandler
|
||||
* @expectedException LogicException
|
||||
*/
|
||||
public function testPushPopHandler()
|
||||
{
|
||||
$logger = new Logger(__METHOD__);
|
||||
$handler1 = new TestHandler;
|
||||
$handler2 = new TestHandler;
|
||||
|
||||
$logger->pushHandler($handler1);
|
||||
$logger->pushHandler($handler2);
|
||||
|
||||
$this->assertEquals($handler2, $logger->popHandler());
|
||||
$this->assertEquals($handler1, $logger->popHandler());
|
||||
$logger->popHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Logger::setHandlers
|
||||
*/
|
||||
public function testSetHandlers()
|
||||
{
|
||||
$logger = new Logger(__METHOD__);
|
||||
$handler1 = new TestHandler;
|
||||
$handler2 = new TestHandler;
|
||||
|
||||
$logger->pushHandler($handler1);
|
||||
$logger->setHandlers(array($handler2));
|
||||
|
||||
// handler1 has been removed
|
||||
$this->assertEquals(array($handler2), $logger->getHandlers());
|
||||
|
||||
$logger->setHandlers(array(
|
||||
"AMapKey" => $handler1,
|
||||
"Woop" => $handler2,
|
||||
));
|
||||
|
||||
// Keys have been scrubbed
|
||||
$this->assertEquals(array($handler1, $handler2), $logger->getHandlers());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Logger::pushProcessor
|
||||
* @covers Monolog\Logger::popProcessor
|
||||
* @expectedException LogicException
|
||||
*/
|
||||
public function testPushPopProcessor()
|
||||
{
|
||||
$logger = new Logger(__METHOD__);
|
||||
$processor1 = new WebProcessor;
|
||||
$processor2 = new WebProcessor;
|
||||
|
||||
$logger->pushProcessor($processor1);
|
||||
$logger->pushProcessor($processor2);
|
||||
|
||||
$this->assertEquals($processor2, $logger->popProcessor());
|
||||
$this->assertEquals($processor1, $logger->popProcessor());
|
||||
$logger->popProcessor();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Logger::pushProcessor
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testPushProcessorWithNonCallable()
|
||||
{
|
||||
$logger = new Logger(__METHOD__);
|
||||
|
||||
$logger->pushProcessor(new \stdClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Logger::addRecord
|
||||
*/
|
||||
public function testProcessorsAreExecuted()
|
||||
{
|
||||
$logger = new Logger(__METHOD__);
|
||||
$handler = new TestHandler;
|
||||
$logger->pushHandler($handler);
|
||||
$logger->pushProcessor(function ($record) {
|
||||
$record['extra']['win'] = true;
|
||||
|
||||
return $record;
|
||||
});
|
||||
$logger->addError('test');
|
||||
list($record) = $handler->getRecords();
|
||||
$this->assertTrue($record['extra']['win']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Logger::addRecord
|
||||
*/
|
||||
public function testProcessorsAreCalledOnlyOnce()
|
||||
{
|
||||
$logger = new Logger(__METHOD__);
|
||||
$handler = $this->getMock('Monolog\Handler\HandlerInterface');
|
||||
$handler->expects($this->any())
|
||||
->method('isHandling')
|
||||
->will($this->returnValue(true))
|
||||
;
|
||||
$handler->expects($this->any())
|
||||
->method('handle')
|
||||
->will($this->returnValue(true))
|
||||
;
|
||||
$logger->pushHandler($handler);
|
||||
|
||||
$processor = $this->getMockBuilder('Monolog\Processor\WebProcessor')
|
||||
->disableOriginalConstructor()
|
||||
->setMethods(array('__invoke'))
|
||||
->getMock()
|
||||
;
|
||||
$processor->expects($this->once())
|
||||
->method('__invoke')
|
||||
->will($this->returnArgument(0))
|
||||
;
|
||||
$logger->pushProcessor($processor);
|
||||
|
||||
$logger->addError('test');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Logger::addRecord
|
||||
*/
|
||||
public function testProcessorsNotCalledWhenNotHandled()
|
||||
{
|
||||
$logger = new Logger(__METHOD__);
|
||||
$handler = $this->getMock('Monolog\Handler\HandlerInterface');
|
||||
$handler->expects($this->once())
|
||||
->method('isHandling')
|
||||
->will($this->returnValue(false))
|
||||
;
|
||||
$logger->pushHandler($handler);
|
||||
$that = $this;
|
||||
$logger->pushProcessor(function ($record) use ($that) {
|
||||
$that->fail('The processor should not be called');
|
||||
});
|
||||
$logger->addAlert('test');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Logger::addRecord
|
||||
*/
|
||||
public function testHandlersNotCalledBeforeFirstHandling()
|
||||
{
|
||||
$logger = new Logger(__METHOD__);
|
||||
|
||||
$handler1 = $this->getMock('Monolog\Handler\HandlerInterface');
|
||||
$handler1->expects($this->never())
|
||||
->method('isHandling')
|
||||
->will($this->returnValue(false))
|
||||
;
|
||||
$handler1->expects($this->once())
|
||||
->method('handle')
|
||||
->will($this->returnValue(false))
|
||||
;
|
||||
$logger->pushHandler($handler1);
|
||||
|
||||
$handler2 = $this->getMock('Monolog\Handler\HandlerInterface');
|
||||
$handler2->expects($this->once())
|
||||
->method('isHandling')
|
||||
->will($this->returnValue(true))
|
||||
;
|
||||
$handler2->expects($this->once())
|
||||
->method('handle')
|
||||
->will($this->returnValue(false))
|
||||
;
|
||||
$logger->pushHandler($handler2);
|
||||
|
||||
$handler3 = $this->getMock('Monolog\Handler\HandlerInterface');
|
||||
$handler3->expects($this->once())
|
||||
->method('isHandling')
|
||||
->will($this->returnValue(false))
|
||||
;
|
||||
$handler3->expects($this->never())
|
||||
->method('handle')
|
||||
;
|
||||
$logger->pushHandler($handler3);
|
||||
|
||||
$logger->debug('test');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Logger::addRecord
|
||||
*/
|
||||
public function testHandlersNotCalledBeforeFirstHandlingWithAssocArray()
|
||||
{
|
||||
$handler1 = $this->getMock('Monolog\Handler\HandlerInterface');
|
||||
$handler1->expects($this->never())
|
||||
->method('isHandling')
|
||||
->will($this->returnValue(false))
|
||||
;
|
||||
$handler1->expects($this->once())
|
||||
->method('handle')
|
||||
->will($this->returnValue(false))
|
||||
;
|
||||
|
||||
$handler2 = $this->getMock('Monolog\Handler\HandlerInterface');
|
||||
$handler2->expects($this->once())
|
||||
->method('isHandling')
|
||||
->will($this->returnValue(true))
|
||||
;
|
||||
$handler2->expects($this->once())
|
||||
->method('handle')
|
||||
->will($this->returnValue(false))
|
||||
;
|
||||
|
||||
$handler3 = $this->getMock('Monolog\Handler\HandlerInterface');
|
||||
$handler3->expects($this->once())
|
||||
->method('isHandling')
|
||||
->will($this->returnValue(false))
|
||||
;
|
||||
$handler3->expects($this->never())
|
||||
->method('handle')
|
||||
;
|
||||
|
||||
$logger = new Logger(__METHOD__, array('last' => $handler3, 'second' => $handler2, 'first' => $handler1));
|
||||
|
||||
$logger->debug('test');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Logger::addRecord
|
||||
*/
|
||||
public function testBubblingWhenTheHandlerReturnsFalse()
|
||||
{
|
||||
$logger = new Logger(__METHOD__);
|
||||
|
||||
$handler1 = $this->getMock('Monolog\Handler\HandlerInterface');
|
||||
$handler1->expects($this->any())
|
||||
->method('isHandling')
|
||||
->will($this->returnValue(true))
|
||||
;
|
||||
$handler1->expects($this->once())
|
||||
->method('handle')
|
||||
->will($this->returnValue(false))
|
||||
;
|
||||
$logger->pushHandler($handler1);
|
||||
|
||||
$handler2 = $this->getMock('Monolog\Handler\HandlerInterface');
|
||||
$handler2->expects($this->any())
|
||||
->method('isHandling')
|
||||
->will($this->returnValue(true))
|
||||
;
|
||||
$handler2->expects($this->once())
|
||||
->method('handle')
|
||||
->will($this->returnValue(false))
|
||||
;
|
||||
$logger->pushHandler($handler2);
|
||||
|
||||
$logger->debug('test');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Logger::addRecord
|
||||
*/
|
||||
public function testNotBubblingWhenTheHandlerReturnsTrue()
|
||||
{
|
||||
$logger = new Logger(__METHOD__);
|
||||
|
||||
$handler1 = $this->getMock('Monolog\Handler\HandlerInterface');
|
||||
$handler1->expects($this->any())
|
||||
->method('isHandling')
|
||||
->will($this->returnValue(true))
|
||||
;
|
||||
$handler1->expects($this->never())
|
||||
->method('handle')
|
||||
;
|
||||
$logger->pushHandler($handler1);
|
||||
|
||||
$handler2 = $this->getMock('Monolog\Handler\HandlerInterface');
|
||||
$handler2->expects($this->any())
|
||||
->method('isHandling')
|
||||
->will($this->returnValue(true))
|
||||
;
|
||||
$handler2->expects($this->once())
|
||||
->method('handle')
|
||||
->will($this->returnValue(true))
|
||||
;
|
||||
$logger->pushHandler($handler2);
|
||||
|
||||
$logger->debug('test');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Logger::isHandling
|
||||
*/
|
||||
public function testIsHandling()
|
||||
{
|
||||
$logger = new Logger(__METHOD__);
|
||||
|
||||
$handler1 = $this->getMock('Monolog\Handler\HandlerInterface');
|
||||
$handler1->expects($this->any())
|
||||
->method('isHandling')
|
||||
->will($this->returnValue(false))
|
||||
;
|
||||
|
||||
$logger->pushHandler($handler1);
|
||||
$this->assertFalse($logger->isHandling(Logger::DEBUG));
|
||||
|
||||
$handler2 = $this->getMock('Monolog\Handler\HandlerInterface');
|
||||
$handler2->expects($this->any())
|
||||
->method('isHandling')
|
||||
->will($this->returnValue(true))
|
||||
;
|
||||
|
||||
$logger->pushHandler($handler2);
|
||||
$this->assertTrue($logger->isHandling(Logger::DEBUG));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider logMethodProvider
|
||||
* @covers Monolog\Logger::addDebug
|
||||
* @covers Monolog\Logger::addInfo
|
||||
* @covers Monolog\Logger::addNotice
|
||||
* @covers Monolog\Logger::addWarning
|
||||
* @covers Monolog\Logger::addError
|
||||
* @covers Monolog\Logger::addCritical
|
||||
* @covers Monolog\Logger::addAlert
|
||||
* @covers Monolog\Logger::addEmergency
|
||||
* @covers Monolog\Logger::debug
|
||||
* @covers Monolog\Logger::info
|
||||
* @covers Monolog\Logger::notice
|
||||
* @covers Monolog\Logger::warn
|
||||
* @covers Monolog\Logger::err
|
||||
* @covers Monolog\Logger::crit
|
||||
* @covers Monolog\Logger::alert
|
||||
* @covers Monolog\Logger::emerg
|
||||
*/
|
||||
public function testLogMethods($method, $expectedLevel)
|
||||
{
|
||||
$logger = new Logger('foo');
|
||||
$handler = new TestHandler;
|
||||
$logger->pushHandler($handler);
|
||||
$logger->{$method}('test');
|
||||
list($record) = $handler->getRecords();
|
||||
$this->assertEquals($expectedLevel, $record['level']);
|
||||
}
|
||||
|
||||
public function logMethodProvider()
|
||||
{
|
||||
return array(
|
||||
// monolog methods
|
||||
array('addDebug', Logger::DEBUG),
|
||||
array('addInfo', Logger::INFO),
|
||||
array('addNotice', Logger::NOTICE),
|
||||
array('addWarning', Logger::WARNING),
|
||||
array('addError', Logger::ERROR),
|
||||
array('addCritical', Logger::CRITICAL),
|
||||
array('addAlert', Logger::ALERT),
|
||||
array('addEmergency', Logger::EMERGENCY),
|
||||
|
||||
// ZF/Sf2 compat methods
|
||||
array('debug', Logger::DEBUG),
|
||||
array('info', Logger::INFO),
|
||||
array('notice', Logger::NOTICE),
|
||||
array('warn', Logger::WARNING),
|
||||
array('err', Logger::ERROR),
|
||||
array('crit', Logger::CRITICAL),
|
||||
array('alert', Logger::ALERT),
|
||||
array('emerg', Logger::EMERGENCY),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider setTimezoneProvider
|
||||
* @covers Monolog\Logger::setTimezone
|
||||
*/
|
||||
public function testSetTimezone($tz)
|
||||
{
|
||||
Logger::setTimezone($tz);
|
||||
$logger = new Logger('foo');
|
||||
$handler = new TestHandler;
|
||||
$logger->pushHandler($handler);
|
||||
$logger->info('test');
|
||||
list($record) = $handler->getRecords();
|
||||
$this->assertEquals($tz, $record['datetime']->getTimezone());
|
||||
}
|
||||
|
||||
public function setTimezoneProvider()
|
||||
{
|
||||
return array_map(
|
||||
function ($tz) { return array(new \DateTimeZone($tz)); },
|
||||
\DateTimeZone::listIdentifiers()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider useMicrosecondTimestampsProvider
|
||||
* @covers Monolog\Logger::useMicrosecondTimestamps
|
||||
* @covers Monolog\Logger::addRecord
|
||||
*/
|
||||
public function testUseMicrosecondTimestamps($micro, $assert)
|
||||
{
|
||||
$logger = new Logger('foo');
|
||||
$logger->useMicrosecondTimestamps($micro);
|
||||
$handler = new TestHandler;
|
||||
$logger->pushHandler($handler);
|
||||
$logger->info('test');
|
||||
list($record) = $handler->getRecords();
|
||||
$this->{$assert}('000000', $record['datetime']->format('u'));
|
||||
}
|
||||
|
||||
public function useMicrosecondTimestampsProvider()
|
||||
{
|
||||
return array(
|
||||
// this has a very small chance of a false negative (1/10^6)
|
||||
'with microseconds' => array(true, 'assertNotSame'),
|
||||
'without microseconds' => array(false, PHP_VERSION_ID >= 70100 ? 'assertNotSame' : 'assertSame'),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Processor;
|
||||
|
||||
use Monolog\TestCase;
|
||||
|
||||
class GitProcessorTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers Monolog\Processor\GitProcessor::__invoke
|
||||
*/
|
||||
public function testProcessor()
|
||||
{
|
||||
$processor = new GitProcessor();
|
||||
$record = $processor($this->getRecord());
|
||||
|
||||
$this->assertArrayHasKey('git', $record['extra']);
|
||||
$this->assertTrue(!is_array($record['extra']['git']['branch']));
|
||||
}
|
||||
}
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Acme;
|
||||
|
||||
class Tester
|
||||
{
|
||||
public function test($handler, $record)
|
||||
{
|
||||
$handler->handle($record);
|
||||
}
|
||||
}
|
||||
|
||||
function tester($handler, $record)
|
||||
{
|
||||
$handler->handle($record);
|
||||
}
|
||||
|
||||
namespace Monolog\Processor;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Monolog\TestCase;
|
||||
use Monolog\Handler\TestHandler;
|
||||
|
||||
class IntrospectionProcessorTest extends TestCase
|
||||
{
|
||||
public function getHandler()
|
||||
{
|
||||
$processor = new IntrospectionProcessor();
|
||||
$handler = new TestHandler();
|
||||
$handler->pushProcessor($processor);
|
||||
|
||||
return $handler;
|
||||
}
|
||||
|
||||
public function testProcessorFromClass()
|
||||
{
|
||||
$handler = $this->getHandler();
|
||||
$tester = new \Acme\Tester;
|
||||
$tester->test($handler, $this->getRecord());
|
||||
list($record) = $handler->getRecords();
|
||||
$this->assertEquals(__FILE__, $record['extra']['file']);
|
||||
$this->assertEquals(18, $record['extra']['line']);
|
||||
$this->assertEquals('Acme\Tester', $record['extra']['class']);
|
||||
$this->assertEquals('test', $record['extra']['function']);
|
||||
}
|
||||
|
||||
public function testProcessorFromFunc()
|
||||
{
|
||||
$handler = $this->getHandler();
|
||||
\Acme\tester($handler, $this->getRecord());
|
||||
list($record) = $handler->getRecords();
|
||||
$this->assertEquals(__FILE__, $record['extra']['file']);
|
||||
$this->assertEquals(24, $record['extra']['line']);
|
||||
$this->assertEquals(null, $record['extra']['class']);
|
||||
$this->assertEquals('Acme\tester', $record['extra']['function']);
|
||||
}
|
||||
|
||||
public function testLevelTooLow()
|
||||
{
|
||||
$input = array(
|
||||
'level' => Logger::DEBUG,
|
||||
'extra' => array(),
|
||||
);
|
||||
|
||||
$expected = $input;
|
||||
|
||||
$processor = new IntrospectionProcessor(Logger::CRITICAL);
|
||||
$actual = $processor($input);
|
||||
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
public function testLevelEqual()
|
||||
{
|
||||
$input = array(
|
||||
'level' => Logger::CRITICAL,
|
||||
'extra' => array(),
|
||||
);
|
||||
|
||||
$expected = $input;
|
||||
$expected['extra'] = array(
|
||||
'file' => null,
|
||||
'line' => null,
|
||||
'class' => 'ReflectionMethod',
|
||||
'function' => 'invokeArgs',
|
||||
);
|
||||
|
||||
$processor = new IntrospectionProcessor(Logger::CRITICAL);
|
||||
$actual = $processor($input);
|
||||
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
public function testLevelHigher()
|
||||
{
|
||||
$input = array(
|
||||
'level' => Logger::EMERGENCY,
|
||||
'extra' => array(),
|
||||
);
|
||||
|
||||
$expected = $input;
|
||||
$expected['extra'] = array(
|
||||
'file' => null,
|
||||
'line' => null,
|
||||
'class' => 'ReflectionMethod',
|
||||
'function' => 'invokeArgs',
|
||||
);
|
||||
|
||||
$processor = new IntrospectionProcessor(Logger::CRITICAL);
|
||||
$actual = $processor($input);
|
||||
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Processor;
|
||||
|
||||
use Monolog\TestCase;
|
||||
|
||||
class MemoryPeakUsageProcessorTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers Monolog\Processor\MemoryPeakUsageProcessor::__invoke
|
||||
* @covers Monolog\Processor\MemoryProcessor::formatBytes
|
||||
*/
|
||||
public function testProcessor()
|
||||
{
|
||||
$processor = new MemoryPeakUsageProcessor();
|
||||
$record = $processor($this->getRecord());
|
||||
$this->assertArrayHasKey('memory_peak_usage', $record['extra']);
|
||||
$this->assertRegExp('#[0-9.]+ (M|K)?B$#', $record['extra']['memory_peak_usage']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Processor\MemoryPeakUsageProcessor::__invoke
|
||||
* @covers Monolog\Processor\MemoryProcessor::formatBytes
|
||||
*/
|
||||
public function testProcessorWithoutFormatting()
|
||||
{
|
||||
$processor = new MemoryPeakUsageProcessor(true, false);
|
||||
$record = $processor($this->getRecord());
|
||||
$this->assertArrayHasKey('memory_peak_usage', $record['extra']);
|
||||
$this->assertInternalType('int', $record['extra']['memory_peak_usage']);
|
||||
$this->assertGreaterThan(0, $record['extra']['memory_peak_usage']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Processor;
|
||||
|
||||
use Monolog\TestCase;
|
||||
|
||||
class MemoryUsageProcessorTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers Monolog\Processor\MemoryUsageProcessor::__invoke
|
||||
* @covers Monolog\Processor\MemoryProcessor::formatBytes
|
||||
*/
|
||||
public function testProcessor()
|
||||
{
|
||||
$processor = new MemoryUsageProcessor();
|
||||
$record = $processor($this->getRecord());
|
||||
$this->assertArrayHasKey('memory_usage', $record['extra']);
|
||||
$this->assertRegExp('#[0-9.]+ (M|K)?B$#', $record['extra']['memory_usage']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Processor\MemoryUsageProcessor::__invoke
|
||||
* @covers Monolog\Processor\MemoryProcessor::formatBytes
|
||||
*/
|
||||
public function testProcessorWithoutFormatting()
|
||||
{
|
||||
$processor = new MemoryUsageProcessor(true, false);
|
||||
$record = $processor($this->getRecord());
|
||||
$this->assertArrayHasKey('memory_usage', $record['extra']);
|
||||
$this->assertInternalType('int', $record['extra']['memory_usage']);
|
||||
$this->assertGreaterThan(0, $record['extra']['memory_usage']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jonathan A. Schweder <jonathanschweder@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Processor;
|
||||
|
||||
use Monolog\TestCase;
|
||||
|
||||
class MercurialProcessorTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers Monolog\Processor\MercurialProcessor::__invoke
|
||||
*/
|
||||
public function testProcessor()
|
||||
{
|
||||
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
|
||||
exec("where hg 2>NUL", $output, $result);
|
||||
} else {
|
||||
exec("which hg 2>/dev/null >/dev/null", $output, $result);
|
||||
}
|
||||
if ($result != 0) {
|
||||
$this->markTestSkipped('hg is missing');
|
||||
return;
|
||||
}
|
||||
|
||||
`hg init`;
|
||||
$processor = new MercurialProcessor();
|
||||
$record = $processor($this->getRecord());
|
||||
|
||||
$this->assertArrayHasKey('hg', $record['extra']);
|
||||
$this->assertTrue(!is_array($record['extra']['hg']['branch']));
|
||||
$this->assertTrue(!is_array($record['extra']['hg']['revision']));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Processor;
|
||||
|
||||
use Monolog\TestCase;
|
||||
|
||||
class ProcessIdProcessorTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers Monolog\Processor\ProcessIdProcessor::__invoke
|
||||
*/
|
||||
public function testProcessor()
|
||||
{
|
||||
$processor = new ProcessIdProcessor();
|
||||
$record = $processor($this->getRecord());
|
||||
$this->assertArrayHasKey('process_id', $record['extra']);
|
||||
$this->assertInternalType('int', $record['extra']['process_id']);
|
||||
$this->assertGreaterThan(0, $record['extra']['process_id']);
|
||||
$this->assertEquals(getmypid(), $record['extra']['process_id']);
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Processor;
|
||||
|
||||
class PsrLogMessageProcessorTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider getPairs
|
||||
*/
|
||||
public function testReplacement($val, $expected)
|
||||
{
|
||||
$proc = new PsrLogMessageProcessor;
|
||||
|
||||
$message = $proc(array(
|
||||
'message' => '{foo}',
|
||||
'context' => array('foo' => $val),
|
||||
));
|
||||
$this->assertEquals($expected, $message['message']);
|
||||
}
|
||||
|
||||
public function getPairs()
|
||||
{
|
||||
return array(
|
||||
array('foo', 'foo'),
|
||||
array('3', '3'),
|
||||
array(3, '3'),
|
||||
array(null, ''),
|
||||
array(true, '1'),
|
||||
array(false, ''),
|
||||
array(new \stdClass, '[object stdClass]'),
|
||||
array(array(), '[array]'),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Processor;
|
||||
|
||||
use Monolog\TestCase;
|
||||
|
||||
class TagProcessorTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers Monolog\Processor\TagProcessor::__invoke
|
||||
*/
|
||||
public function testProcessor()
|
||||
{
|
||||
$tags = array(1, 2, 3);
|
||||
$processor = new TagProcessor($tags);
|
||||
$record = $processor($this->getRecord());
|
||||
|
||||
$this->assertEquals($tags, $record['extra']['tags']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Processor\TagProcessor::__invoke
|
||||
*/
|
||||
public function testProcessorTagModification()
|
||||
{
|
||||
$tags = array(1, 2, 3);
|
||||
$processor = new TagProcessor($tags);
|
||||
|
||||
$record = $processor($this->getRecord());
|
||||
$this->assertEquals($tags, $record['extra']['tags']);
|
||||
|
||||
$processor->setTags(array('a', 'b'));
|
||||
$record = $processor($this->getRecord());
|
||||
$this->assertEquals(array('a', 'b'), $record['extra']['tags']);
|
||||
|
||||
$processor->addTags(array('a', 'c', 'foo' => 'bar'));
|
||||
$record = $processor($this->getRecord());
|
||||
$this->assertEquals(array('a', 'b', 'a', 'c', 'foo' => 'bar'), $record['extra']['tags']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Processor;
|
||||
|
||||
use Monolog\TestCase;
|
||||
|
||||
class UidProcessorTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers Monolog\Processor\UidProcessor::__invoke
|
||||
*/
|
||||
public function testProcessor()
|
||||
{
|
||||
$processor = new UidProcessor();
|
||||
$record = $processor($this->getRecord());
|
||||
$this->assertArrayHasKey('uid', $record['extra']);
|
||||
}
|
||||
|
||||
public function testGetUid()
|
||||
{
|
||||
$processor = new UidProcessor(10);
|
||||
$this->assertEquals(10, strlen($processor->getUid()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog\Processor;
|
||||
|
||||
use Monolog\TestCase;
|
||||
|
||||
class WebProcessorTest extends TestCase
|
||||
{
|
||||
public function testProcessor()
|
||||
{
|
||||
$server = array(
|
||||
'REQUEST_URI' => 'A',
|
||||
'REMOTE_ADDR' => 'B',
|
||||
'REQUEST_METHOD' => 'C',
|
||||
'HTTP_REFERER' => 'D',
|
||||
'SERVER_NAME' => 'F',
|
||||
'UNIQUE_ID' => 'G',
|
||||
);
|
||||
|
||||
$processor = new WebProcessor($server);
|
||||
$record = $processor($this->getRecord());
|
||||
$this->assertEquals($server['REQUEST_URI'], $record['extra']['url']);
|
||||
$this->assertEquals($server['REMOTE_ADDR'], $record['extra']['ip']);
|
||||
$this->assertEquals($server['REQUEST_METHOD'], $record['extra']['http_method']);
|
||||
$this->assertEquals($server['HTTP_REFERER'], $record['extra']['referrer']);
|
||||
$this->assertEquals($server['SERVER_NAME'], $record['extra']['server']);
|
||||
$this->assertEquals($server['UNIQUE_ID'], $record['extra']['unique_id']);
|
||||
}
|
||||
|
||||
public function testProcessorDoNothingIfNoRequestUri()
|
||||
{
|
||||
$server = array(
|
||||
'REMOTE_ADDR' => 'B',
|
||||
'REQUEST_METHOD' => 'C',
|
||||
);
|
||||
$processor = new WebProcessor($server);
|
||||
$record = $processor($this->getRecord());
|
||||
$this->assertEmpty($record['extra']);
|
||||
}
|
||||
|
||||
public function testProcessorReturnNullIfNoHttpReferer()
|
||||
{
|
||||
$server = array(
|
||||
'REQUEST_URI' => 'A',
|
||||
'REMOTE_ADDR' => 'B',
|
||||
'REQUEST_METHOD' => 'C',
|
||||
'SERVER_NAME' => 'F',
|
||||
);
|
||||
$processor = new WebProcessor($server);
|
||||
$record = $processor($this->getRecord());
|
||||
$this->assertNull($record['extra']['referrer']);
|
||||
}
|
||||
|
||||
public function testProcessorDoesNotAddUniqueIdIfNotPresent()
|
||||
{
|
||||
$server = array(
|
||||
'REQUEST_URI' => 'A',
|
||||
'REMOTE_ADDR' => 'B',
|
||||
'REQUEST_METHOD' => 'C',
|
||||
'SERVER_NAME' => 'F',
|
||||
);
|
||||
$processor = new WebProcessor($server);
|
||||
$record = $processor($this->getRecord());
|
||||
$this->assertFalse(isset($record['extra']['unique_id']));
|
||||
}
|
||||
|
||||
public function testProcessorAddsOnlyRequestedExtraFields()
|
||||
{
|
||||
$server = array(
|
||||
'REQUEST_URI' => 'A',
|
||||
'REMOTE_ADDR' => 'B',
|
||||
'REQUEST_METHOD' => 'C',
|
||||
'SERVER_NAME' => 'F',
|
||||
);
|
||||
|
||||
$processor = new WebProcessor($server, array('url', 'http_method'));
|
||||
$record = $processor($this->getRecord());
|
||||
|
||||
$this->assertSame(array('url' => 'A', 'http_method' => 'C'), $record['extra']);
|
||||
}
|
||||
|
||||
public function testProcessorConfiguringOfExtraFields()
|
||||
{
|
||||
$server = array(
|
||||
'REQUEST_URI' => 'A',
|
||||
'REMOTE_ADDR' => 'B',
|
||||
'REQUEST_METHOD' => 'C',
|
||||
'SERVER_NAME' => 'F',
|
||||
);
|
||||
|
||||
$processor = new WebProcessor($server, array('url' => 'REMOTE_ADDR'));
|
||||
$record = $processor($this->getRecord());
|
||||
|
||||
$this->assertSame(array('url' => 'B'), $record['extra']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException UnexpectedValueException
|
||||
*/
|
||||
public function testInvalidData()
|
||||
{
|
||||
new WebProcessor(new \stdClass);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog;
|
||||
|
||||
use Monolog\Handler\TestHandler;
|
||||
use Monolog\Formatter\LineFormatter;
|
||||
use Monolog\Processor\PsrLogMessageProcessor;
|
||||
use Psr\Log\Test\LoggerInterfaceTest;
|
||||
|
||||
class PsrLogCompatTest extends LoggerInterfaceTest
|
||||
{
|
||||
private $handler;
|
||||
|
||||
public function getLogger()
|
||||
{
|
||||
$logger = new Logger('foo');
|
||||
$logger->pushHandler($handler = new TestHandler);
|
||||
$logger->pushProcessor(new PsrLogMessageProcessor);
|
||||
$handler->setFormatter(new LineFormatter('%level_name% %message%'));
|
||||
|
||||
$this->handler = $handler;
|
||||
|
||||
return $logger;
|
||||
}
|
||||
|
||||
public function getLogs()
|
||||
{
|
||||
$convert = function ($record) {
|
||||
$lower = function ($match) {
|
||||
return strtolower($match[0]);
|
||||
};
|
||||
|
||||
return preg_replace_callback('{^[A-Z]+}', $lower, $record['formatted']);
|
||||
};
|
||||
|
||||
return array_map($convert, $this->handler->getRecords());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog;
|
||||
|
||||
class RegistryTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
Registry::clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider hasLoggerProvider
|
||||
* @covers Monolog\Registry::hasLogger
|
||||
*/
|
||||
public function testHasLogger(array $loggersToAdd, array $loggersToCheck, array $expectedResult)
|
||||
{
|
||||
foreach ($loggersToAdd as $loggerToAdd) {
|
||||
Registry::addLogger($loggerToAdd);
|
||||
}
|
||||
foreach ($loggersToCheck as $index => $loggerToCheck) {
|
||||
$this->assertSame($expectedResult[$index], Registry::hasLogger($loggerToCheck));
|
||||
}
|
||||
}
|
||||
|
||||
public function hasLoggerProvider()
|
||||
{
|
||||
$logger1 = new Logger('test1');
|
||||
$logger2 = new Logger('test2');
|
||||
$logger3 = new Logger('test3');
|
||||
|
||||
return array(
|
||||
// only instances
|
||||
array(
|
||||
array($logger1),
|
||||
array($logger1, $logger2),
|
||||
array(true, false),
|
||||
),
|
||||
// only names
|
||||
array(
|
||||
array($logger1),
|
||||
array('test1', 'test2'),
|
||||
array(true, false),
|
||||
),
|
||||
// mixed case
|
||||
array(
|
||||
array($logger1, $logger2),
|
||||
array('test1', $logger2, 'test3', $logger3),
|
||||
array(true, true, false, false),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Registry::clear
|
||||
*/
|
||||
public function testClearClears()
|
||||
{
|
||||
Registry::addLogger(new Logger('test1'), 'log');
|
||||
Registry::clear();
|
||||
|
||||
$this->setExpectedException('\InvalidArgumentException');
|
||||
Registry::getInstance('log');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider removedLoggerProvider
|
||||
* @covers Monolog\Registry::addLogger
|
||||
* @covers Monolog\Registry::removeLogger
|
||||
*/
|
||||
public function testRemovesLogger($loggerToAdd, $remove)
|
||||
{
|
||||
Registry::addLogger($loggerToAdd);
|
||||
Registry::removeLogger($remove);
|
||||
|
||||
$this->setExpectedException('\InvalidArgumentException');
|
||||
Registry::getInstance($loggerToAdd->getName());
|
||||
}
|
||||
|
||||
public function removedLoggerProvider()
|
||||
{
|
||||
$logger1 = new Logger('test1');
|
||||
|
||||
return array(
|
||||
array($logger1, $logger1),
|
||||
array($logger1, 'test1'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Registry::addLogger
|
||||
* @covers Monolog\Registry::getInstance
|
||||
* @covers Monolog\Registry::__callStatic
|
||||
*/
|
||||
public function testGetsSameLogger()
|
||||
{
|
||||
$logger1 = new Logger('test1');
|
||||
$logger2 = new Logger('test2');
|
||||
|
||||
Registry::addLogger($logger1, 'test1');
|
||||
Registry::addLogger($logger2);
|
||||
|
||||
$this->assertSame($logger1, Registry::getInstance('test1'));
|
||||
$this->assertSame($logger2, Registry::test2());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
* @covers Monolog\Registry::getInstance
|
||||
*/
|
||||
public function testFailsOnNonExistantLogger()
|
||||
{
|
||||
Registry::getInstance('test1');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Monolog\Registry::addLogger
|
||||
*/
|
||||
public function testReplacesLogger()
|
||||
{
|
||||
$log1 = new Logger('test1');
|
||||
$log2 = new Logger('test2');
|
||||
|
||||
Registry::addLogger($log1, 'log');
|
||||
|
||||
Registry::addLogger($log2, 'log', true);
|
||||
|
||||
$this->assertSame($log2, Registry::getInstance('log'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
* @covers Monolog\Registry::addLogger
|
||||
*/
|
||||
public function testFailsOnUnspecifiedReplacement()
|
||||
{
|
||||
$log1 = new Logger('test1');
|
||||
$log2 = new Logger('test2');
|
||||
|
||||
Registry::addLogger($log1, 'log');
|
||||
|
||||
Registry::addLogger($log2, 'log');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Monolog package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Monolog;
|
||||
|
||||
class TestCase extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @return array Record
|
||||
*/
|
||||
protected function getRecord($level = Logger::WARNING, $message = 'test', $context = array())
|
||||
{
|
||||
return array(
|
||||
'message' => $message,
|
||||
'context' => $context,
|
||||
'level' => $level,
|
||||
'level_name' => Logger::getLevelName($level),
|
||||
'channel' => 'test',
|
||||
'datetime' => \DateTime::createFromFormat('U.u', sprintf('%.6F', microtime(true))),
|
||||
'extra' => array(),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function getMultipleRecords()
|
||||
{
|
||||
return array(
|
||||
$this->getRecord(Logger::DEBUG, 'debug message 1'),
|
||||
$this->getRecord(Logger::DEBUG, 'debug message 2'),
|
||||
$this->getRecord(Logger::INFO, 'information'),
|
||||
$this->getRecord(Logger::WARNING, 'warning'),
|
||||
$this->getRecord(Logger::ERROR, 'error'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Monolog\Formatter\FormatterInterface
|
||||
*/
|
||||
protected function getIdentityFormatter()
|
||||
{
|
||||
$formatter = $this->getMock('Monolog\\Formatter\\FormatterInterface');
|
||||
$formatter->expects($this->any())
|
||||
->method('format')
|
||||
->will($this->returnCallback(function ($record) { return $record['message']; }));
|
||||
|
||||
return $formatter;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user