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