115 changed files with 12850 additions and 0 deletions
@ -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","context":[],"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","context":[],"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,219 @@ |
|||||
|
<?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; |
||||
|
} |
||||
|
|
||||
|
public function testNormalizeHandleLargeArraysWithExactly1000Items() |
||||
|
{ |
||||
|
$formatter = new NormalizerFormatter(); |
||||
|
$largeArray = range(1, 1000); |
||||
|
|
||||
|
$res = $formatter->format(array( |
||||
|
'level_name' => 'CRITICAL', |
||||
|
'channel' => 'test', |
||||
|
'message' => 'bar', |
||||
|
'context' => array($largeArray), |
||||
|
'datetime' => new \DateTime, |
||||
|
'extra' => array(), |
||||
|
)); |
||||
|
|
||||
|
$this->assertCount(1000, $res['context'][0]); |
||||
|
$this->assertArrayNotHasKey('...', $res['context'][0]); |
||||
|
} |
||||
|
|
||||
|
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(1001, $res['context'][0]); |
||||
|
$this->assertEquals('Over 1000 items (2000 total), aborting normalization', $res['context'][0]['...']); |
||||
|
} |
||||
|
} |
||||
@ -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,481 @@ |
|||||
|
<?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 testCanNormalizeReferences() |
||||
|
{ |
||||
|
$formatter = new NormalizerFormatter(); |
||||
|
$x = array('foo' => 'bar'); |
||||
|
$y = array('x' => &$x); |
||||
|
$x['y'] = &$y; |
||||
|
$formatter->format($y); |
||||
|
} |
||||
|
|
||||
|
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 testNormalizeHandleLargeArraysWithExactly1000Items() |
||||
|
{ |
||||
|
$formatter = new NormalizerFormatter(); |
||||
|
$largeArray = range(1, 1000); |
||||
|
|
||||
|
$res = $formatter->format(array( |
||||
|
'level_name' => 'CRITICAL', |
||||
|
'channel' => 'test', |
||||
|
'message' => 'bar', |
||||
|
'context' => array($largeArray), |
||||
|
'datetime' => new \DateTime, |
||||
|
'extra' => array(), |
||||
|
)); |
||||
|
|
||||
|
$this->assertCount(1000, $res['context'][0]); |
||||
|
$this->assertArrayNotHasKey('...', $res['context'][0]); |
||||
|
} |
||||
|
|
||||
|
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(1001, $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] |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
public function testExceptionTraceDoesNotLeakCallUserFuncArgs() |
||||
|
{ |
||||
|
try { |
||||
|
$arg = new TestInfoLeak; |
||||
|
call_user_func(array($this, 'throwHelper'), $arg, $dt = new \DateTime()); |
||||
|
} catch (\Exception $e) { |
||||
|
} |
||||
|
|
||||
|
$formatter = new NormalizerFormatter(); |
||||
|
$record = array('context' => array('exception' => $e)); |
||||
|
$result = $formatter->format($record); |
||||
|
|
||||
|
$this->assertSame( |
||||
|
'{"function":"throwHelper","class":"Monolog\\\\Formatter\\\\NormalizerFormatterTest","type":"->","args":["[object] (Monolog\\\\Formatter\\\\TestInfoLeak)","'.$dt->format('Y-m-d H:i:s').'"]}', |
||||
|
$result['context']['exception']['trace'][0] |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
private function throwHelper($arg) |
||||
|
{ |
||||
|
throw new \RuntimeException('Thrown'); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
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'); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
class TestInfoLeak |
||||
|
{ |
||||
|
public function __toString() |
||||
|
{ |
||||
|
return 'Sensitive information'; |
||||
|
} |
||||
|
} |
||||
@ -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()); |
||||
|
} |
||||
|
} |
||||
@ -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::resetStatic(); |
||||
|
} |
||||
|
|
||||
|
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::resetStatic(); |
||||
|
$_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 resetStatic() |
||||
|
{ |
||||
|
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 testHandleResetBufferingAfterReset() |
||||
|
{ |
||||
|
$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 testHandleResetBufferingAfterBeingTriggeredWhenStopBufferingIsDisabled() |
||||
|
{ |
||||
|
$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::resetStatic(); |
||||
|
$_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 resetStatic() |
||||
|
{ |
||||
|
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,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; |
||||
|
|
||||
|
/** |
||||
|
* @author Robert Kaufmann III <rok3@rok3.me> |
||||
|
* @author Gabriel Machado <gabriel.ms1@hotmail.com> |
||||
|
*/ |
||||
|
class InsightOpsHandlerTest extends TestCase |
||||
|
{ |
||||
|
/** |
||||
|
* @var resource |
||||
|
*/ |
||||
|
private $resource; |
||||
|
|
||||
|
/** |
||||
|
* @var LogEntriesHandler |
||||
|
*/ |
||||
|
private $handler; |
||||
|
|
||||
|
public function testWriteContent() |
||||
|
{ |
||||
|
$this->createHandler(); |
||||
|
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'Critical write test')); |
||||
|
|
||||
|
fseek($this->resource, 0); |
||||
|
$content = fread($this->resource, 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() |
||||
|
{ |
||||
|
$this->createHandler(); |
||||
|
$this->handler->handleBatch($this->getMultipleRecords()); |
||||
|
|
||||
|
fseek($this->resource, 0); |
||||
|
$content = fread($this->resource, 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', 'us', $useSSL, Logger::DEBUG, true); |
||||
|
$this->resource = fopen('php://memory', 'a'); |
||||
|
$this->handler = $this->getMock( |
||||
|
'\Monolog\Handler\InsightOpsHandler', |
||||
|
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->resource)); |
||||
|
$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,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,245 @@ |
|||||
|
<?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), |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @dataProvider rotationWhenSimilarFilesExistTests |
||||
|
*/ |
||||
|
public function testRotationWhenSimilarFileNamesExist($dateFormat) |
||||
|
{ |
||||
|
touch($old1 = __DIR__.'/Fixtures/foo-foo-'.date($dateFormat).'.rot'); |
||||
|
touch($old2 = __DIR__.'/Fixtures/foo-bar-'.date($dateFormat).'.rot'); |
||||
|
|
||||
|
$log = __DIR__.'/Fixtures/foo-'.date($dateFormat).'.rot'; |
||||
|
|
||||
|
$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)); |
||||
|
} |
||||
|
|
||||
|
public function rotationWhenSimilarFilesExistTests() |
||||
|
{ |
||||
|
|
||||
|
return array( |
||||
|
'Rotation is triggered when the file of the current day is not present but similar exists' |
||||
|
=> array(RotatingFileHandler::FILE_PER_DAY), |
||||
|
|
||||
|
'Rotation is triggered when the file of the current month is not present but similar exists' |
||||
|
=> array(RotatingFileHandler::FILE_PER_MONTH), |
||||
|
|
||||
|
'Rotation is triggered when the file of the current year is not present but similar exists' |
||||
|
=> array(RotatingFileHandler::FILE_PER_YEAR), |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
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,395 @@ |
|||||
|
<?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 testContextHasException() |
||||
|
{ |
||||
|
$record = $this->getRecord(Logger::CRITICAL, 'This is a critical message.', array('exception' => new \Exception())); |
||||
|
$slackRecord = new SlackRecord(null, null, true, null, false, true); |
||||
|
$data = $slackRecord->getSlackData($record); |
||||
|
$this->assertInternalType('string', $data['attachments'][0]['fields'][1]['value']); |
||||
|
} |
||||
|
|
||||
|
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,335 @@ |
|||||
|
<?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 testSetChunkSize() |
||||
|
{ |
||||
|
$this->createHandler('localhost:1234'); |
||||
|
$this->handler->setChunkSize(1025); |
||||
|
$this->assertEquals(1025, $this->handler->getChunkSize()); |
||||
|
} |
||||
|
|
||||
|
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 UnexpectedValueException |
||||
|
*/ |
||||
|
public function testExceptionIsThrownIfCannotSetChunkSize() |
||||
|
{ |
||||
|
$this->setMockHandler(array('streamSetChunkSize')); |
||||
|
$this->handler->setChunkSize(8192); |
||||
|
$this->handler->expects($this->once()) |
||||
|
->method('streamSetChunkSize') |
||||
|
->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)); |
||||
|
} |
||||
|
|
||||
|
if (!in_array('streamSetChunkSize', $methods)) { |
||||
|
$this->handler->expects($this->any()) |
||||
|
->method('streamSetChunkSize') |
||||
|
->will($this->returnValue(8192)); |
||||
|
} |
||||
|
|
||||
|
$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,116 @@ |
|||||
|
<?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 testHandlerAssertEmptyContext() { |
||||
|
$handler = new TestHandler; |
||||
|
$record = $this->getRecord(Logger::WARNING, 'test', array()); |
||||
|
$this->assertFalse($handler->hasWarning(array( |
||||
|
'message' => 'test', |
||||
|
'context' => array(), |
||||
|
))); |
||||
|
|
||||
|
$handler->handle($record); |
||||
|
|
||||
|
$this->assertTrue($handler->hasWarning(array( |
||||
|
'message' => 'test', |
||||
|
'context' => array(), |
||||
|
))); |
||||
|
$this->assertFalse($handler->hasWarning(array( |
||||
|
'message' => 'test', |
||||
|
'context' => array( |
||||
|
'foo' => 'bar' |
||||
|
), |
||||
|
))); |
||||
|
} |
||||
|
|
||||
|
public function testHandlerAssertNonEmptyContext() { |
||||
|
$handler = new TestHandler; |
||||
|
$record = $this->getRecord(Logger::WARNING, 'test', array('foo' => 'bar')); |
||||
|
$this->assertFalse($handler->hasWarning(array( |
||||
|
'message' => 'test', |
||||
|
'context' => array( |
||||
|
'foo' => 'bar' |
||||
|
), |
||||
|
))); |
||||
|
|
||||
|
$handler->handle($record); |
||||
|
|
||||
|
$this->assertTrue($handler->hasWarning(array( |
||||
|
'message' => 'test', |
||||
|
'context' => array( |
||||
|
'foo' => 'bar' |
||||
|
), |
||||
|
))); |
||||
|
$this->assertFalse($handler->hasWarning(array( |
||||
|
'message' => 'test', |
||||
|
'context' => array(), |
||||
|
))); |
||||
|
} |
||||
|
|
||||
|
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"); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,144 @@ |
|||||
|
<?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::handleBatch |
||||
|
*/ |
||||
|
public function testHandleBatchUsesProcessors() |
||||
|
{ |
||||
|
$testHandlers = array(new TestHandler(), new TestHandler()); |
||||
|
$handler = new WhatFailureGroupHandler($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']); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @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()); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,690 @@ |
|||||
|
<?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'), |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @covers Monolog\Logger::setExceptionHandler |
||||
|
*/ |
||||
|
public function testSetExceptionHandler() |
||||
|
{ |
||||
|
$logger = new Logger(__METHOD__); |
||||
|
$this->assertNull($logger->getExceptionHandler()); |
||||
|
$callback = function ($ex) { |
||||
|
}; |
||||
|
$logger->setExceptionHandler($callback); |
||||
|
$this->assertEquals($callback, $logger->getExceptionHandler()); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @covers Monolog\Logger::setExceptionHandler |
||||
|
* @expectedException InvalidArgumentException |
||||
|
*/ |
||||
|
public function testBadExceptionHandlerType() |
||||
|
{ |
||||
|
$logger = new Logger(__METHOD__); |
||||
|
$logger->setExceptionHandler(false); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @covers Monolog\Logger::handleException |
||||
|
* @expectedException Exception |
||||
|
*/ |
||||
|
public function testDefaultHandleException() |
||||
|
{ |
||||
|
$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->throwException(new \Exception('Some handler exception'))) |
||||
|
; |
||||
|
$logger->pushHandler($handler); |
||||
|
$logger->info('test'); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @covers Monolog\Logger::handleException |
||||
|
* @covers Monolog\Logger::addRecord |
||||
|
*/ |
||||
|
public function testCustomHandleException() |
||||
|
{ |
||||
|
$logger = new Logger(__METHOD__); |
||||
|
$that = $this; |
||||
|
$logger->setExceptionHandler(function ($e, $record) use ($that) { |
||||
|
$that->assertEquals($e->getMessage(), 'Some handler exception'); |
||||
|
$that->assertTrue(is_array($record)); |
||||
|
$that->assertEquals($record['message'], 'test'); |
||||
|
}); |
||||
|
$handler = $this->getMock('Monolog\Handler\HandlerInterface'); |
||||
|
$handler->expects($this->any()) |
||||
|
->method('isHandling') |
||||
|
->will($this->returnValue(true)) |
||||
|
; |
||||
|
$handler->expects($this->any()) |
||||
|
->method('handle') |
||||
|
->will($this->throwException(new \Exception('Some handler exception'))) |
||||
|
; |
||||
|
$logger->pushHandler($handler); |
||||
|
$logger->info('test'); |
||||
|
} |
||||
|
|
||||
|
public function testReset() |
||||
|
{ |
||||
|
$logger = new Logger('app'); |
||||
|
|
||||
|
$testHandler = new Handler\TestHandler(); |
||||
|
$bufferHandler = new Handler\BufferHandler($testHandler); |
||||
|
$groupHandler = new Handler\GroupHandler(array($bufferHandler)); |
||||
|
$fingersCrossedHandler = new Handler\FingersCrossedHandler($groupHandler); |
||||
|
|
||||
|
$logger->pushHandler($fingersCrossedHandler); |
||||
|
|
||||
|
$processorUid1 = new Processor\UidProcessor(10); |
||||
|
$uid1 = $processorUid1->getUid(); |
||||
|
$groupHandler->pushProcessor($processorUid1); |
||||
|
|
||||
|
$processorUid2 = new Processor\UidProcessor(5); |
||||
|
$uid2 = $processorUid2->getUid(); |
||||
|
$logger->pushProcessor($processorUid2); |
||||
|
|
||||
|
$getProperty = function ($object, $property) { |
||||
|
$reflectionProperty = new \ReflectionProperty(get_class($object), $property); |
||||
|
$reflectionProperty->setAccessible(true); |
||||
|
|
||||
|
return $reflectionProperty->getValue($object); |
||||
|
}; |
||||
|
$that = $this; |
||||
|
$assertBufferOfBufferHandlerEmpty = function () use ($getProperty, $bufferHandler, $that) { |
||||
|
$that->assertEmpty($getProperty($bufferHandler, 'buffer')); |
||||
|
}; |
||||
|
$assertBuffersEmpty = function() use ($assertBufferOfBufferHandlerEmpty, $getProperty, $fingersCrossedHandler, $that) { |
||||
|
$assertBufferOfBufferHandlerEmpty(); |
||||
|
$that->assertEmpty($getProperty($fingersCrossedHandler, 'buffer')); |
||||
|
}; |
||||
|
|
||||
|
$logger->debug('debug'); |
||||
|
$logger->reset(); |
||||
|
$assertBuffersEmpty(); |
||||
|
$this->assertFalse($testHandler->hasDebugRecords()); |
||||
|
$this->assertFalse($testHandler->hasErrorRecords()); |
||||
|
$this->assertNotSame($uid1, $uid1 = $processorUid1->getUid()); |
||||
|
$this->assertNotSame($uid2, $uid2 = $processorUid2->getUid()); |
||||
|
|
||||
|
$logger->debug('debug'); |
||||
|
$logger->error('error'); |
||||
|
$logger->reset(); |
||||
|
$assertBuffersEmpty(); |
||||
|
$this->assertTrue($testHandler->hasDebugRecords()); |
||||
|
$this->assertTrue($testHandler->hasErrorRecords()); |
||||
|
$this->assertNotSame($uid1, $uid1 = $processorUid1->getUid()); |
||||
|
$this->assertNotSame($uid2, $uid2 = $processorUid2->getUid()); |
||||
|
|
||||
|
$logger->info('info'); |
||||
|
$this->assertNotEmpty($getProperty($fingersCrossedHandler, 'buffer')); |
||||
|
$assertBufferOfBufferHandlerEmpty(); |
||||
|
$this->assertFalse($testHandler->hasInfoRecords()); |
||||
|
|
||||
|
$logger->reset(); |
||||
|
$assertBuffersEmpty(); |
||||
|
$this->assertFalse($testHandler->hasInfoRecords()); |
||||
|
$this->assertNotSame($uid1, $uid1 = $processorUid1->getUid()); |
||||
|
$this->assertNotSame($uid2, $uid2 = $processorUid2->getUid()); |
||||
|
|
||||
|
$logger->notice('notice'); |
||||
|
$logger->emergency('emergency'); |
||||
|
$logger->reset(); |
||||
|
$assertBuffersEmpty(); |
||||
|
$this->assertFalse($testHandler->hasInfoRecords()); |
||||
|
$this->assertTrue($testHandler->hasNoticeRecords()); |
||||
|
$this->assertTrue($testHandler->hasEmergencyRecords()); |
||||
|
$this->assertNotSame($uid1, $processorUid1->getUid()); |
||||
|
$this->assertNotSame($uid2, $processorUid2->getUid()); |
||||
|
} |
||||
|
} |
||||
@ -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'])); |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
@ -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']); |
||||
|
} |
||||
|
} |
||||
@ -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,287 @@ |
|||||
|
<?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\StreamHandler; |
||||
|
use Monolog\Handler\TestHandler; |
||||
|
use Psr\Log\LogLevel; |
||||
|
|
||||
|
/** |
||||
|
* @author Robert Gust-Bardon <robert@gust-bardon.org> |
||||
|
* @covers Monolog\SignalHandler |
||||
|
*/ |
||||
|
class SignalHandlerTest extends TestCase |
||||
|
{ |
||||
|
|
||||
|
private $asyncSignalHandling; |
||||
|
private $blockedSignals; |
||||
|
private $signalHandlers; |
||||
|
|
||||
|
protected function setUp() |
||||
|
{ |
||||
|
$this->signalHandlers = array(); |
||||
|
if (extension_loaded('pcntl')) { |
||||
|
if (function_exists('pcntl_async_signals')) { |
||||
|
$this->asyncSignalHandling = pcntl_async_signals(); |
||||
|
} |
||||
|
if (function_exists('pcntl_sigprocmask')) { |
||||
|
pcntl_sigprocmask(SIG_BLOCK, array(), $this->blockedSignals); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected function tearDown() |
||||
|
{ |
||||
|
if ($this->asyncSignalHandling !== null) { |
||||
|
pcntl_async_signals($this->asyncSignalHandling); |
||||
|
} |
||||
|
if ($this->blockedSignals !== null) { |
||||
|
pcntl_sigprocmask(SIG_SETMASK, $this->blockedSignals); |
||||
|
} |
||||
|
if ($this->signalHandlers) { |
||||
|
pcntl_signal_dispatch(); |
||||
|
foreach ($this->signalHandlers as $signo => $handler) { |
||||
|
pcntl_signal($signo, $handler); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private function setSignalHandler($signo, $handler = SIG_DFL) { |
||||
|
if (function_exists('pcntl_signal_get_handler')) { |
||||
|
$this->signalHandlers[$signo] = pcntl_signal_get_handler($signo); |
||||
|
} else { |
||||
|
$this->signalHandlers[$signo] = SIG_DFL; |
||||
|
} |
||||
|
$this->assertTrue(pcntl_signal($signo, $handler)); |
||||
|
} |
||||
|
|
||||
|
public function testHandleSignal() |
||||
|
{ |
||||
|
$logger = new Logger('test', array($handler = new TestHandler)); |
||||
|
$errHandler = new SignalHandler($logger); |
||||
|
$signo = 2; // SIGINT. |
||||
|
$siginfo = array('signo' => $signo, 'errno' => 0, 'code' => 0); |
||||
|
$errHandler->handleSignal($signo, $siginfo); |
||||
|
$this->assertCount(1, $handler->getRecords()); |
||||
|
$this->assertTrue($handler->hasCriticalRecords()); |
||||
|
$records = $handler->getRecords(); |
||||
|
$this->assertSame($siginfo, $records[0]['context']); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @depends testHandleSignal |
||||
|
* @requires extension pcntl |
||||
|
* @requires extension posix |
||||
|
* @requires function pcntl_signal |
||||
|
* @requires function pcntl_signal_dispatch |
||||
|
* @requires function posix_getpid |
||||
|
* @requires function posix_kill |
||||
|
*/ |
||||
|
public function testRegisterSignalHandler() |
||||
|
{ |
||||
|
// SIGCONT and SIGURG should be ignored by default. |
||||
|
if (!defined('SIGCONT') || !defined('SIGURG')) { |
||||
|
$this->markTestSkipped('This test requires the SIGCONT and SIGURG pcntl constants.'); |
||||
|
} |
||||
|
|
||||
|
$this->setSignalHandler(SIGCONT, SIG_IGN); |
||||
|
$this->setSignalHandler(SIGURG, SIG_IGN); |
||||
|
|
||||
|
$logger = new Logger('test', array($handler = new TestHandler)); |
||||
|
$errHandler = new SignalHandler($logger); |
||||
|
$pid = posix_getpid(); |
||||
|
|
||||
|
$this->assertTrue(posix_kill($pid, SIGURG)); |
||||
|
$this->assertTrue(pcntl_signal_dispatch()); |
||||
|
$this->assertCount(0, $handler->getRecords()); |
||||
|
|
||||
|
$errHandler->registerSignalHandler(SIGURG, LogLevel::INFO, false, false, false); |
||||
|
|
||||
|
$this->assertTrue(posix_kill($pid, SIGCONT)); |
||||
|
$this->assertTrue(pcntl_signal_dispatch()); |
||||
|
$this->assertCount(0, $handler->getRecords()); |
||||
|
|
||||
|
$this->assertTrue(posix_kill($pid, SIGURG)); |
||||
|
$this->assertTrue(pcntl_signal_dispatch()); |
||||
|
$this->assertCount(1, $handler->getRecords()); |
||||
|
$this->assertTrue($handler->hasInfoThatContains('SIGURG')); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @dataProvider defaultPreviousProvider |
||||
|
* @depends testRegisterSignalHandler |
||||
|
* @requires function pcntl_fork |
||||
|
* @requires function pcntl_sigprocmask |
||||
|
* @requires function pcntl_waitpid |
||||
|
*/ |
||||
|
public function testRegisterDefaultPreviousSignalHandler($signo, $callPrevious, $expected) |
||||
|
{ |
||||
|
$this->setSignalHandler($signo, SIG_DFL); |
||||
|
|
||||
|
$path = tempnam(sys_get_temp_dir(), 'monolog-'); |
||||
|
$this->assertNotFalse($path); |
||||
|
|
||||
|
$pid = pcntl_fork(); |
||||
|
if ($pid === 0) { // Child. |
||||
|
$streamHandler = new StreamHandler($path); |
||||
|
$streamHandler->setFormatter($this->getIdentityFormatter()); |
||||
|
$logger = new Logger('test', array($streamHandler)); |
||||
|
$errHandler = new SignalHandler($logger); |
||||
|
$errHandler->registerSignalHandler($signo, LogLevel::INFO, $callPrevious, false, false); |
||||
|
pcntl_sigprocmask(SIG_SETMASK, array(SIGCONT)); |
||||
|
posix_kill(posix_getpid(), $signo); |
||||
|
pcntl_signal_dispatch(); |
||||
|
// If $callPrevious is true, SIGINT should terminate by this line. |
||||
|
pcntl_sigprocmask(SIG_BLOCK, array(), $oldset); |
||||
|
file_put_contents($path, implode(' ', $oldset), FILE_APPEND); |
||||
|
posix_kill(posix_getpid(), $signo); |
||||
|
pcntl_signal_dispatch(); |
||||
|
exit(); |
||||
|
} |
||||
|
|
||||
|
$this->assertNotSame(-1, $pid); |
||||
|
$this->assertNotSame(-1, pcntl_waitpid($pid, $status)); |
||||
|
$this->assertNotSame(-1, $status); |
||||
|
$this->assertSame($expected, file_get_contents($path)); |
||||
|
} |
||||
|
|
||||
|
public function defaultPreviousProvider() |
||||
|
{ |
||||
|
if (!defined('SIGCONT') || !defined('SIGINT') || !defined('SIGURG')) { |
||||
|
return array(); |
||||
|
} |
||||
|
|
||||
|
return array( |
||||
|
array(SIGINT, false, 'Program received signal SIGINT'.SIGCONT.'Program received signal SIGINT'), |
||||
|
array(SIGINT, true, 'Program received signal SIGINT'), |
||||
|
array(SIGURG, false, 'Program received signal SIGURG'.SIGCONT.'Program received signal SIGURG'), |
||||
|
array(SIGURG, true, 'Program received signal SIGURG'.SIGCONT.'Program received signal SIGURG'), |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @dataProvider callablePreviousProvider |
||||
|
* @depends testRegisterSignalHandler |
||||
|
* @requires function pcntl_signal_get_handler |
||||
|
*/ |
||||
|
public function testRegisterCallablePreviousSignalHandler($callPrevious) |
||||
|
{ |
||||
|
$this->setSignalHandler(SIGURG, SIG_IGN); |
||||
|
|
||||
|
$logger = new Logger('test', array($handler = new TestHandler)); |
||||
|
$errHandler = new SignalHandler($logger); |
||||
|
$previousCalled = 0; |
||||
|
pcntl_signal(SIGURG, function ($signo, array $siginfo = null) use (&$previousCalled) { |
||||
|
++$previousCalled; |
||||
|
}); |
||||
|
$errHandler->registerSignalHandler(SIGURG, LogLevel::INFO, $callPrevious, false, false); |
||||
|
$this->assertTrue(posix_kill(posix_getpid(), SIGURG)); |
||||
|
$this->assertTrue(pcntl_signal_dispatch()); |
||||
|
$this->assertCount(1, $handler->getRecords()); |
||||
|
$this->assertTrue($handler->hasInfoThatContains('SIGURG')); |
||||
|
$this->assertSame($callPrevious ? 1 : 0, $previousCalled); |
||||
|
} |
||||
|
|
||||
|
public function callablePreviousProvider() |
||||
|
{ |
||||
|
return array( |
||||
|
array(false), |
||||
|
array(true), |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @dataProvider restartSyscallsProvider |
||||
|
* @depends testRegisterDefaultPreviousSignalHandler |
||||
|
* @requires function pcntl_fork |
||||
|
* @requires function pcntl_waitpid |
||||
|
*/ |
||||
|
public function testRegisterSyscallRestartingSignalHandler($restartSyscalls) |
||||
|
{ |
||||
|
$this->setSignalHandler(SIGURG, SIG_IGN); |
||||
|
|
||||
|
$parentPid = posix_getpid(); |
||||
|
$microtime = microtime(true); |
||||
|
|
||||
|
$pid = pcntl_fork(); |
||||
|
if ($pid === 0) { // Child. |
||||
|
usleep(100000); |
||||
|
posix_kill($parentPid, SIGURG); |
||||
|
usleep(100000); |
||||
|
exit(); |
||||
|
} |
||||
|
|
||||
|
$this->assertNotSame(-1, $pid); |
||||
|
$logger = new Logger('test', array($handler = new TestHandler)); |
||||
|
$errHandler = new SignalHandler($logger); |
||||
|
$errHandler->registerSignalHandler(SIGURG, LogLevel::INFO, false, $restartSyscalls, false); |
||||
|
if ($restartSyscalls) { |
||||
|
// pcntl_wait is expected to be restarted after the signal handler. |
||||
|
$this->assertNotSame(-1, pcntl_waitpid($pid, $status)); |
||||
|
} else { |
||||
|
// pcntl_wait is expected to be interrupted when the signal handler is invoked. |
||||
|
$this->assertSame(-1, pcntl_waitpid($pid, $status)); |
||||
|
} |
||||
|
$this->assertSame($restartSyscalls, microtime(true) - $microtime > 0.15); |
||||
|
$this->assertTrue(pcntl_signal_dispatch()); |
||||
|
$this->assertCount(1, $handler->getRecords()); |
||||
|
if ($restartSyscalls) { |
||||
|
// The child has already exited. |
||||
|
$this->assertSame(-1, pcntl_waitpid($pid, $status)); |
||||
|
} else { |
||||
|
// The child has not exited yet. |
||||
|
$this->assertNotSame(-1, pcntl_waitpid($pid, $status)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public function restartSyscallsProvider() |
||||
|
{ |
||||
|
return array( |
||||
|
array(false), |
||||
|
array(true), |
||||
|
array(false), |
||||
|
array(true), |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @dataProvider asyncProvider |
||||
|
* @depends testRegisterDefaultPreviousSignalHandler |
||||
|
* @requires function pcntl_async_signals |
||||
|
*/ |
||||
|
public function testRegisterAsyncSignalHandler($initialAsync, $desiredAsync, $expectedBefore, $expectedAfter) |
||||
|
{ |
||||
|
$this->setSignalHandler(SIGURG, SIG_IGN); |
||||
|
pcntl_async_signals($initialAsync); |
||||
|
|
||||
|
$logger = new Logger('test', array($handler = new TestHandler)); |
||||
|
$errHandler = new SignalHandler($logger); |
||||
|
$errHandler->registerSignalHandler(SIGURG, LogLevel::INFO, false, false, $desiredAsync); |
||||
|
$this->assertTrue(posix_kill(posix_getpid(), SIGURG)); |
||||
|
$this->assertCount($expectedBefore, $handler->getRecords()); |
||||
|
$this->assertTrue(pcntl_signal_dispatch()); |
||||
|
$this->assertCount($expectedAfter, $handler->getRecords()); |
||||
|
} |
||||
|
|
||||
|
public function asyncProvider() |
||||
|
{ |
||||
|
return array( |
||||
|
array(false, false, 0, 1), |
||||
|
array(false, null, 0, 1), |
||||
|
array(false, true, 1, 1), |
||||
|
array(true, false, 0, 1), |
||||
|
array(true, null, 1, 1), |
||||
|
array(true, true, 1, 1), |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
# Changelog |
||||
|
|
||||
|
All notable changes to this project will be documented in this file, in reverse chronological order by release. |
||||
|
|
||||
|
## 1.0.1 - 2016-08-06 |
||||
|
|
||||
|
### Fixed |
||||
|
|
||||
|
- Make spacing consistent in phpdoc annotations php-fig/cache#9 - chalasr |
||||
|
- Fix grammar in phpdoc annotations php-fig/cache#10 - chalasr |
||||
|
- Be more specific in docblocks that `getItems()` and `deleteItems()` take an array of strings (`string[]`) compared to just `array` php-fig/cache#8 - GrahamCampbell |
||||
|
- For `expiresAt()` and `expiresAfter()` in CacheItemInterface fix docblock to specify null as a valid parameters as well as an implementation of DateTimeInterface php-fig/cache#7 - GrahamCampbell |
||||
|
|
||||
|
## 1.0.0 - 2015-12-11 |
||||
|
|
||||
|
Initial stable release; reflects accepted PSR-6 specification |
||||
@ -0,0 +1,19 @@ |
|||||
|
Copyright (c) 2015 PHP Framework Interoperability Group |
||||
|
|
||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
|
of this software and associated documentation files (the "Software"), to deal |
||||
|
in the Software without restriction, including without limitation the rights |
||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
|
copies of the Software, and to permit persons to whom the Software is |
||||
|
furnished to do so, subject to the following conditions: |
||||
|
|
||||
|
The above copyright notice and this permission notice shall be included in |
||||
|
all copies or substantial portions of the Software. |
||||
|
|
||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||
|
THE SOFTWARE. |
||||
@ -0,0 +1,9 @@ |
|||||
|
PSR Cache |
||||
|
========= |
||||
|
|
||||
|
This repository holds all interfaces defined by |
||||
|
[PSR-6](http://www.php-fig.org/psr/psr-6/). |
||||
|
|
||||
|
Note that this is not a Cache implementation of its own. It is merely an |
||||
|
interface that describes a Cache implementation. See the specification for more |
||||
|
details. |
||||
@ -0,0 +1,25 @@ |
|||||
|
{ |
||||
|
"name": "psr/cache", |
||||
|
"description": "Common interface for caching libraries", |
||||
|
"keywords": ["psr", "psr-6", "cache"], |
||||
|
"license": "MIT", |
||||
|
"authors": [ |
||||
|
{ |
||||
|
"name": "PHP-FIG", |
||||
|
"homepage": "http://www.php-fig.org/" |
||||
|
} |
||||
|
], |
||||
|
"require": { |
||||
|
"php": ">=5.3.0" |
||||
|
}, |
||||
|
"autoload": { |
||||
|
"psr-4": { |
||||
|
"Psr\\Cache\\": "src/" |
||||
|
} |
||||
|
}, |
||||
|
"extra": { |
||||
|
"branch-alias": { |
||||
|
"dev-master": "1.0.x-dev" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace Psr\Cache; |
||||
|
|
||||
|
/** |
||||
|
* Exception interface for all exceptions thrown by an Implementing Library. |
||||
|
*/ |
||||
|
interface CacheException |
||||
|
{ |
||||
|
} |
||||
@ -0,0 +1,105 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace Psr\Cache; |
||||
|
|
||||
|
/** |
||||
|
* CacheItemInterface defines an interface for interacting with objects inside a cache. |
||||
|
* |
||||
|
* Each Item object MUST be associated with a specific key, which can be set |
||||
|
* according to the implementing system and is typically passed by the |
||||
|
* Cache\CacheItemPoolInterface object. |
||||
|
* |
||||
|
* The Cache\CacheItemInterface object encapsulates the storage and retrieval of |
||||
|
* cache items. Each Cache\CacheItemInterface is generated by a |
||||
|
* Cache\CacheItemPoolInterface object, which is responsible for any required |
||||
|
* setup as well as associating the object with a unique Key. |
||||
|
* Cache\CacheItemInterface objects MUST be able to store and retrieve any type |
||||
|
* of PHP value defined in the Data section of the specification. |
||||
|
* |
||||
|
* Calling Libraries MUST NOT instantiate Item objects themselves. They may only |
||||
|
* be requested from a Pool object via the getItem() method. Calling Libraries |
||||
|
* SHOULD NOT assume that an Item created by one Implementing Library is |
||||
|
* compatible with a Pool from another Implementing Library. |
||||
|
*/ |
||||
|
interface CacheItemInterface |
||||
|
{ |
||||
|
/** |
||||
|
* Returns the key for the current cache item. |
||||
|
* |
||||
|
* The key is loaded by the Implementing Library, but should be available to |
||||
|
* the higher level callers when needed. |
||||
|
* |
||||
|
* @return string |
||||
|
* The key string for this cache item. |
||||
|
*/ |
||||
|
public function getKey(); |
||||
|
|
||||
|
/** |
||||
|
* Retrieves the value of the item from the cache associated with this object's key. |
||||
|
* |
||||
|
* The value returned must be identical to the value originally stored by set(). |
||||
|
* |
||||
|
* If isHit() returns false, this method MUST return null. Note that null |
||||
|
* is a legitimate cached value, so the isHit() method SHOULD be used to |
||||
|
* differentiate between "null value was found" and "no value was found." |
||||
|
* |
||||
|
* @return mixed |
||||
|
* The value corresponding to this cache item's key, or null if not found. |
||||
|
*/ |
||||
|
public function get(); |
||||
|
|
||||
|
/** |
||||
|
* Confirms if the cache item lookup resulted in a cache hit. |
||||
|
* |
||||
|
* Note: This method MUST NOT have a race condition between calling isHit() |
||||
|
* and calling get(). |
||||
|
* |
||||
|
* @return bool |
||||
|
* True if the request resulted in a cache hit. False otherwise. |
||||
|
*/ |
||||
|
public function isHit(); |
||||
|
|
||||
|
/** |
||||
|
* Sets the value represented by this cache item. |
||||
|
* |
||||
|
* The $value argument may be any item that can be serialized by PHP, |
||||
|
* although the method of serialization is left up to the Implementing |
||||
|
* Library. |
||||
|
* |
||||
|
* @param mixed $value |
||||
|
* The serializable value to be stored. |
||||
|
* |
||||
|
* @return static |
||||
|
* The invoked object. |
||||
|
*/ |
||||
|
public function set($value); |
||||
|
|
||||
|
/** |
||||
|
* Sets the expiration time for this cache item. |
||||
|
* |
||||
|
* @param \DateTimeInterface|null $expiration |
||||
|
* The point in time after which the item MUST be considered expired. |
||||
|
* If null is passed explicitly, a default value MAY be used. If none is set, |
||||
|
* the value should be stored permanently or for as long as the |
||||
|
* implementation allows. |
||||
|
* |
||||
|
* @return static |
||||
|
* The called object. |
||||
|
*/ |
||||
|
public function expiresAt($expiration); |
||||
|
|
||||
|
/** |
||||
|
* Sets the expiration time for this cache item. |
||||
|
* |
||||
|
* @param int|\DateInterval|null $time |
||||
|
* The period of time from the present after which the item MUST be considered |
||||
|
* expired. An integer parameter is understood to be the time in seconds until |
||||
|
* expiration. If null is passed explicitly, a default value MAY be used. |
||||
|
* If none is set, the value should be stored permanently or for as long as the |
||||
|
* implementation allows. |
||||
|
* |
||||
|
* @return static |
||||
|
* The called object. |
||||
|
*/ |
||||
|
public function expiresAfter($time); |
||||
|
} |
||||
@ -0,0 +1,138 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace Psr\Cache; |
||||
|
|
||||
|
/** |
||||
|
* CacheItemPoolInterface generates CacheItemInterface objects. |
||||
|
* |
||||
|
* The primary purpose of Cache\CacheItemPoolInterface is to accept a key from |
||||
|
* the Calling Library and return the associated Cache\CacheItemInterface object. |
||||
|
* It is also the primary point of interaction with the entire cache collection. |
||||
|
* All configuration and initialization of the Pool is left up to an |
||||
|
* Implementing Library. |
||||
|
*/ |
||||
|
interface CacheItemPoolInterface |
||||
|
{ |
||||
|
/** |
||||
|
* Returns a Cache Item representing the specified key. |
||||
|
* |
||||
|
* This method must always return a CacheItemInterface object, even in case of |
||||
|
* a cache miss. It MUST NOT return null. |
||||
|
* |
||||
|
* @param string $key |
||||
|
* The key for which to return the corresponding Cache Item. |
||||
|
* |
||||
|
* @throws InvalidArgumentException |
||||
|
* If the $key string is not a legal value a \Psr\Cache\InvalidArgumentException |
||||
|
* MUST be thrown. |
||||
|
* |
||||
|
* @return CacheItemInterface |
||||
|
* The corresponding Cache Item. |
||||
|
*/ |
||||
|
public function getItem($key); |
||||
|
|
||||
|
/** |
||||
|
* Returns a traversable set of cache items. |
||||
|
* |
||||
|
* @param string[] $keys |
||||
|
* An indexed array of keys of items to retrieve. |
||||
|
* |
||||
|
* @throws InvalidArgumentException |
||||
|
* If any of the keys in $keys are not a legal value a \Psr\Cache\InvalidArgumentException |
||||
|
* MUST be thrown. |
||||
|
* |
||||
|
* @return array|\Traversable |
||||
|
* A traversable collection of Cache Items keyed by the cache keys of |
||||
|
* each item. A Cache item will be returned for each key, even if that |
||||
|
* key is not found. However, if no keys are specified then an empty |
||||
|
* traversable MUST be returned instead. |
||||
|
*/ |
||||
|
public function getItems(array $keys = array()); |
||||
|
|
||||
|
/** |
||||
|
* Confirms if the cache contains specified cache item. |
||||
|
* |
||||
|
* Note: This method MAY avoid retrieving the cached value for performance reasons. |
||||
|
* This could result in a race condition with CacheItemInterface::get(). To avoid |
||||
|
* such situation use CacheItemInterface::isHit() instead. |
||||
|
* |
||||
|
* @param string $key |
||||
|
* The key for which to check existence. |
||||
|
* |
||||
|
* @throws InvalidArgumentException |
||||
|
* If the $key string is not a legal value a \Psr\Cache\InvalidArgumentException |
||||
|
* MUST be thrown. |
||||
|
* |
||||
|
* @return bool |
||||
|
* True if item exists in the cache, false otherwise. |
||||
|
*/ |
||||
|
public function hasItem($key); |
||||
|
|
||||
|
/** |
||||
|
* Deletes all items in the pool. |
||||
|
* |
||||
|
* @return bool |
||||
|
* True if the pool was successfully cleared. False if there was an error. |
||||
|
*/ |
||||
|
public function clear(); |
||||
|
|
||||
|
/** |
||||
|
* Removes the item from the pool. |
||||
|
* |
||||
|
* @param string $key |
||||
|
* The key to delete. |
||||
|
* |
||||
|
* @throws InvalidArgumentException |
||||
|
* If the $key string is not a legal value a \Psr\Cache\InvalidArgumentException |
||||
|
* MUST be thrown. |
||||
|
* |
||||
|
* @return bool |
||||
|
* True if the item was successfully removed. False if there was an error. |
||||
|
*/ |
||||
|
public function deleteItem($key); |
||||
|
|
||||
|
/** |
||||
|
* Removes multiple items from the pool. |
||||
|
* |
||||
|
* @param string[] $keys |
||||
|
* An array of keys that should be removed from the pool. |
||||
|
|
||||
|
* @throws InvalidArgumentException |
||||
|
* If any of the keys in $keys are not a legal value a \Psr\Cache\InvalidArgumentException |
||||
|
* MUST be thrown. |
||||
|
* |
||||
|
* @return bool |
||||
|
* True if the items were successfully removed. False if there was an error. |
||||
|
*/ |
||||
|
public function deleteItems(array $keys); |
||||
|
|
||||
|
/** |
||||
|
* Persists a cache item immediately. |
||||
|
* |
||||
|
* @param CacheItemInterface $item |
||||
|
* The cache item to save. |
||||
|
* |
||||
|
* @return bool |
||||
|
* True if the item was successfully persisted. False if there was an error. |
||||
|
*/ |
||||
|
public function save(CacheItemInterface $item); |
||||
|
|
||||
|
/** |
||||
|
* Sets a cache item to be persisted later. |
||||
|
* |
||||
|
* @param CacheItemInterface $item |
||||
|
* The cache item to save. |
||||
|
* |
||||
|
* @return bool |
||||
|
* False if the item could not be queued or if a commit was attempted and failed. True otherwise. |
||||
|
*/ |
||||
|
public function saveDeferred(CacheItemInterface $item); |
||||
|
|
||||
|
/** |
||||
|
* Persists any deferred cache items. |
||||
|
* |
||||
|
* @return bool |
||||
|
* True if all not-yet-saved items were successfully saved or there were none. False otherwise. |
||||
|
*/ |
||||
|
public function commit(); |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace Psr\Cache; |
||||
|
|
||||
|
/** |
||||
|
* Exception interface for invalid cache arguments. |
||||
|
* |
||||
|
* Any time an invalid argument is passed into a method it must throw an |
||||
|
* exception class which implements Psr\Cache\InvalidArgumentException. |
||||
|
*/ |
||||
|
interface InvalidArgumentException extends CacheException |
||||
|
{ |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
composer.lock |
||||
|
composer.phar |
||||
|
/vendor/ |
||||
@ -0,0 +1,21 @@ |
|||||
|
The MIT License (MIT) |
||||
|
|
||||
|
Copyright (c) 2013-2016 container-interop |
||||
|
Copyright (c) 2016 PHP Framework Interoperability Group |
||||
|
|
||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of |
||||
|
this software and associated documentation files (the "Software"), to deal in |
||||
|
the Software without restriction, including without limitation the rights to |
||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of |
||||
|
the Software, and to permit persons to whom the Software is furnished to do so, |
||||
|
subject to the following conditions: |
||||
|
|
||||
|
The above copyright notice and this permission notice shall be included in all |
||||
|
copies or substantial portions of the Software. |
||||
|
|
||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS |
||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER |
||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||||
@ -0,0 +1,5 @@ |
|||||
|
# PSR Container |
||||
|
|
||||
|
This repository holds all interfaces/classes/traits related to [PSR-11](https://github.com/container-interop/fig-standards/blob/master/proposed/container.md). |
||||
|
|
||||
|
Note that this is not a container implementation of its own. See the specification for more details. |
||||
@ -0,0 +1,27 @@ |
|||||
|
{ |
||||
|
"name": "psr/container", |
||||
|
"type": "library", |
||||
|
"description": "Common Container Interface (PHP FIG PSR-11)", |
||||
|
"keywords": ["psr", "psr-11", "container", "container-interop", "container-interface"], |
||||
|
"homepage": "https://github.com/php-fig/container", |
||||
|
"license": "MIT", |
||||
|
"authors": [ |
||||
|
{ |
||||
|
"name": "PHP-FIG", |
||||
|
"homepage": "http://www.php-fig.org/" |
||||
|
} |
||||
|
], |
||||
|
"require": { |
||||
|
"php": ">=5.3.0" |
||||
|
}, |
||||
|
"autoload": { |
||||
|
"psr-4": { |
||||
|
"Psr\\Container\\": "src/" |
||||
|
} |
||||
|
}, |
||||
|
"extra": { |
||||
|
"branch-alias": { |
||||
|
"dev-master": "1.0.x-dev" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
<?php |
||||
|
/** |
||||
|
* @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file) |
||||
|
*/ |
||||
|
|
||||
|
namespace Psr\Container; |
||||
|
|
||||
|
/** |
||||
|
* Base interface representing a generic exception in a container. |
||||
|
*/ |
||||
|
interface ContainerExceptionInterface |
||||
|
{ |
||||
|
} |
||||
@ -0,0 +1,37 @@ |
|||||
|
<?php |
||||
|
/** |
||||
|
* @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file) |
||||
|
*/ |
||||
|
|
||||
|
namespace Psr\Container; |
||||
|
|
||||
|
/** |
||||
|
* Describes the interface of a container that exposes methods to read its entries. |
||||
|
*/ |
||||
|
interface ContainerInterface |
||||
|
{ |
||||
|
/** |
||||
|
* Finds an entry of the container by its identifier and returns it. |
||||
|
* |
||||
|
* @param string $id Identifier of the entry to look for. |
||||
|
* |
||||
|
* @throws NotFoundExceptionInterface No entry was found for **this** identifier. |
||||
|
* @throws ContainerExceptionInterface Error while retrieving the entry. |
||||
|
* |
||||
|
* @return mixed Entry. |
||||
|
*/ |
||||
|
public function get($id); |
||||
|
|
||||
|
/** |
||||
|
* Returns true if the container can return an entry for the given identifier. |
||||
|
* Returns false otherwise. |
||||
|
* |
||||
|
* `has($id)` returning true does not mean that `get($id)` will not throw an exception. |
||||
|
* It does however mean that `get($id)` will not throw a `NotFoundExceptionInterface`. |
||||
|
* |
||||
|
* @param string $id Identifier of the entry to look for. |
||||
|
* |
||||
|
* @return bool |
||||
|
*/ |
||||
|
public function has($id); |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
<?php |
||||
|
/** |
||||
|
* @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file) |
||||
|
*/ |
||||
|
|
||||
|
namespace Psr\Container; |
||||
|
|
||||
|
/** |
||||
|
* No entry was found in the container. |
||||
|
*/ |
||||
|
interface NotFoundExceptionInterface extends ContainerExceptionInterface |
||||
|
{ |
||||
|
} |
||||
@ -0,0 +1,36 @@ |
|||||
|
# Changelog |
||||
|
|
||||
|
All notable changes to this project will be documented in this file, in reverse chronological order by release. |
||||
|
|
||||
|
## 1.0.1 - 2016-08-06 |
||||
|
|
||||
|
### Added |
||||
|
|
||||
|
- Nothing. |
||||
|
|
||||
|
### Deprecated |
||||
|
|
||||
|
- Nothing. |
||||
|
|
||||
|
### Removed |
||||
|
|
||||
|
- Nothing. |
||||
|
|
||||
|
### Fixed |
||||
|
|
||||
|
- Updated all `@return self` annotation references in interfaces to use |
||||
|
`@return static`, which more closelly follows the semantics of the |
||||
|
specification. |
||||
|
- Updated the `MessageInterface::getHeaders()` return annotation to use the |
||||
|
value `string[][]`, indicating the format is a nested array of strings. |
||||
|
- Updated the `@link` annotation for `RequestInterface::withRequestTarget()` |
||||
|
to point to the correct section of RFC 7230. |
||||
|
- Updated the `ServerRequestInterface::withUploadedFiles()` parameter annotation |
||||
|
to add the parameter name (`$uploadedFiles`). |
||||
|
- Updated a `@throws` annotation for the `UploadedFileInterface::moveTo()` |
||||
|
method to correctly reference the method parameter (it was referencing an |
||||
|
incorrect parameter name previously). |
||||
|
|
||||
|
## 1.0.0 - 2016-05-18 |
||||
|
|
||||
|
Initial stable release; reflects accepted PSR-7 specification. |
||||
@ -0,0 +1,19 @@ |
|||||
|
Copyright (c) 2014 PHP Framework Interoperability Group |
||||
|
|
||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
|
of this software and associated documentation files (the "Software"), to deal |
||||
|
in the Software without restriction, including without limitation the rights |
||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
|
copies of the Software, and to permit persons to whom the Software is |
||||
|
furnished to do so, subject to the following conditions: |
||||
|
|
||||
|
The above copyright notice and this permission notice shall be included in |
||||
|
all copies or substantial portions of the Software. |
||||
|
|
||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||
|
THE SOFTWARE. |
||||
@ -0,0 +1,13 @@ |
|||||
|
PSR Http Message |
||||
|
================ |
||||
|
|
||||
|
This repository holds all interfaces/classes/traits related to |
||||
|
[PSR-7](http://www.php-fig.org/psr/psr-7/). |
||||
|
|
||||
|
Note that this is not a HTTP message implementation of its own. It is merely an |
||||
|
interface that describes a HTTP message. See the specification for more details. |
||||
|
|
||||
|
Usage |
||||
|
----- |
||||
|
|
||||
|
We'll certainly need some stuff in here. |
||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue