1
0
mirror of https://github.com/Seldaek/monolog.git synced 2025-08-03 03:37:34 +02:00

Fix a ton of tests for latest phpunit and turn faked-stream tests into real network tests with a local server

This commit is contained in:
Jordi Boggiano
2016-09-19 18:20:42 +02:00
parent d3c8c9bea1
commit c6a9f28e24
20 changed files with 457 additions and 413 deletions

View File

@@ -17,7 +17,7 @@
"psr/log": "^1.0" "psr/log": "^1.0"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^5.3", "phpunit/phpunit": "^5.5",
"graylog2/gelf-php": "^1.4.2", "graylog2/gelf-php": "^1.4.2",
"sentry/sentry": "^0.13", "sentry/sentry": "^0.13",
"ruflin/elastica": ">=0.90 <3.0", "ruflin/elastica": ">=0.90 <3.0",
@@ -26,7 +26,9 @@
"php-amqplib/php-amqplib": "~2.4", "php-amqplib/php-amqplib": "~2.4",
"swiftmailer/swiftmailer": "~5.3", "swiftmailer/swiftmailer": "~5.3",
"php-console/php-console": "^3.1.3", "php-console/php-console": "^3.1.3",
"jakub-onderka/php-parallel-lint": "^0.9" "jakub-onderka/php-parallel-lint": "^0.9",
"symfony/process": "^3.1",
"predis/predis": "^1.1"
}, },
"suggest": { "suggest": {
"graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",

View File

@@ -56,7 +56,7 @@ class TestCase extends \PHPUnit_Framework_TestCase
*/ */
protected function getIdentityFormatter() protected function getIdentityFormatter()
{ {
$formatter = $this->getMock('Monolog\\Formatter\\FormatterInterface'); $formatter = $this->createMock('Monolog\\Formatter\\FormatterInterface');
$formatter->expects($this->any()) $formatter->expects($this->any())
->method('format') ->method('format')
->will($this->returnCallback(function ($record) { ->will($this->returnCallback(function ($record) {

View File

@@ -33,7 +33,7 @@ class AmqpHandlerTest extends TestCase
$messages = []; $messages = [];
$exchange = $this->getMock('AMQPExchange', ['publish', 'setName'], [], '', false); $exchange = $this->createMock('AMQPExchange', ['publish', 'setName'], [], '', false);
$exchange->expects($this->any()) $exchange->expects($this->any())
->method('publish') ->method('publish')
->will($this->returnCallback(function ($message, $routing_key, $flags = 0, $attributes = []) use (&$messages) { ->will($this->returnCallback(function ($message, $routing_key, $flags = 0, $attributes = []) use (&$messages) {
@@ -81,7 +81,7 @@ class AmqpHandlerTest extends TestCase
$messages = []; $messages = [];
$exchange = $this->getMock('PhpAmqpLib\Channel\AMQPChannel', ['basic_publish', '__destruct'], [], '', false); $exchange = $this->createMock('PhpAmqpLib\Channel\AMQPChannel', ['basic_publish', '__destruct'], [], '', false);
$exchange->expects($this->any()) $exchange->expects($this->any())
->method('basic_publish') ->method('basic_publish')

View File

@@ -47,7 +47,7 @@ class DynamoDbHandlerTest extends TestCase
public function testHandle() public function testHandle()
{ {
$record = $this->getRecord(); $record = $this->getRecord();
$formatter = $this->getMock('Monolog\Formatter\FormatterInterface'); $formatter = $this->createMock('Monolog\Formatter\FormatterInterface');
$formatted = ['foo' => 1, 'bar' => 2]; $formatted = ['foo' => 1, 'bar' => 2];
$handler = new DynamoDbHandler($this->client, 'foo'); $handler = new DynamoDbHandler($this->client, 'foo');
$handler->setFormatter($formatter); $handler->setFormatter($formatter);

View File

@@ -53,7 +53,7 @@ class FlowdockHandlerTest extends TestCase
/** /**
* @depends testWriteHeader * @depends testWriteHeader
*/ */
public function testWriteContent($content) public function testWriteContent(string $content)
{ {
$this->assertRegexp('/"source":"test_source"/', $content); $this->assertRegexp('/"source":"test_source"/', $content);
$this->assertRegexp('/"from_address":"source@test\.com"/', $content); $this->assertRegexp('/"from_address":"source@test\.com"/', $content);
@@ -61,28 +61,27 @@ class FlowdockHandlerTest extends TestCase
private function createHandler($token = 'myToken') private function createHandler($token = 'myToken')
{ {
$constructorArgs = [$token, Logger::DEBUG];
$this->res = fopen('php://memory', 'a'); $this->res = fopen('php://memory', 'a');
$this->handler = $this->getMock( $this->handler = $this->prophesize('Monolog\Handler\FlowdockHandler');
'\Monolog\Handler\FlowdockHandler',
['fsockopen', 'streamSetTimeout', 'closeSocket'], $this->handler = new class($token, Logger::DEBUG) extends FlowdockHandler {
$constructorArgs public function fsockopen() {
); return $this->mockedResource;
}
public function streamSetTimeout() {
return true;
}
public function closeSocket() {
return true;
}
};
$this->handler->mockedResource = $this->res;
$reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString'); $reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString');
$reflectionProperty->setAccessible(true); $reflectionProperty->setAccessible(true);
$reflectionProperty->setValue($this->handler, 'localhost:1234'); $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')); $this->handler->setFormatter(new FlowdockFormatter('test_source', 'source@test.com'));
} }
} }

View File

@@ -43,7 +43,7 @@ class GelfHandlerTest extends TestCase
protected function getMessagePublisher() protected function getMessagePublisher()
{ {
return $this->getMock('Gelf\Publisher', ['publish'], [], '', false); return $this->createMock('Gelf\Publisher', ['publish'], [], '', false);
} }
public function testDebug() public function testDebug()

View File

@@ -28,7 +28,7 @@ class HandlerWrapperTest extends TestCase
public function setUp() public function setUp()
{ {
parent::setUp(); parent::setUp();
$this->handler = $this->getMock('Monolog\\Handler\\HandlerInterface'); $this->handler = $this->createMock('Monolog\\Handler\\HandlerInterface');
$this->wrapper = new HandlerWrapper($this->handler); $this->wrapper = new HandlerWrapper($this->handler);
} }

View File

@@ -26,11 +26,10 @@ class HipChatHandlerTest extends TestCase
public function testWriteV2() public function testWriteV2()
{ {
$this->createHandler('myToken', 'room1', 'Monolog', false, 'hipchat.foo.bar', 'v2'); $this->initHandlerAndSocket('myToken', 'room1', 'Monolog', false, 'hipchat.foo.bar', 'v2');
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
fseek($this->res, 0);
$content = fread($this->res, 1024);
$content = $this->socket->getOutput();
$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); $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; return $content;
@@ -38,10 +37,9 @@ class HipChatHandlerTest extends TestCase
public function testWriteV2Notify() public function testWriteV2Notify()
{ {
$this->createHandler('myToken', 'room1', 'Monolog', true, 'hipchat.foo.bar', 'v2'); $this->initHandlerAndSocket('myToken', 'room1', 'Monolog', true, 'hipchat.foo.bar', 'v2');
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
fseek($this->res, 0); $content = $this->socket->getOutput();
$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); $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);
@@ -50,10 +48,9 @@ class HipChatHandlerTest extends TestCase
public function testRoomSpaces() public function testRoomSpaces()
{ {
$this->createHandler('myToken', 'room name', 'Monolog', false, 'hipchat.foo.bar', 'v2'); $this->initHandlerAndSocket('myToken', 'room name', 'Monolog', false, 'hipchat.foo.bar', 'v2');
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
fseek($this->res, 0); $content = $this->socket->getOutput();
$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); $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);
@@ -94,10 +91,9 @@ class HipChatHandlerTest extends TestCase
public function testWriteContentV2WithoutName() public function testWriteContentV2WithoutName()
{ {
$this->createHandler('myToken', 'room1', null, false, 'hipchat.foo.bar', 'v2'); $this->initHandlerAndSocket('myToken', 'room1', null, false, 'hipchat.foo.bar', 'v2');
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
fseek($this->res, 0); $content = $this->socket->getOutput();
$content = fread($this->res, 1024);
$this->assertRegexp('/notify=false&message=test1&message_format=text&color=red$/', $content); $this->assertRegexp('/notify=false&message=test1&message_format=text&color=red$/', $content);
@@ -106,21 +102,19 @@ class HipChatHandlerTest extends TestCase
public function testWriteWithComplexMessage() public function testWriteWithComplexMessage()
{ {
$this->createHandler(); $this->initHandlerAndSocket();
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'Backup of database "example" finished in 16 minutes.')); $this->handler->handle($this->getRecord(Logger::CRITICAL, 'Backup of database "example" finished in 16 minutes.'));
fseek($this->res, 0);
$content = fread($this->res, 1024);
$content = $this->socket->getOutput();
$this->assertRegexp('/message=Backup\+of\+database\+%22example%22\+finished\+in\+16\+minutes\./', $content); $this->assertRegexp('/message=Backup\+of\+database\+%22example%22\+finished\+in\+16\+minutes\./', $content);
} }
public function testWriteTruncatesLongMessage() public function testWriteTruncatesLongMessage()
{ {
$this->createHandler(); $this->initHandlerAndSocket();
$this->handler->handle($this->getRecord(Logger::CRITICAL, str_repeat('abcde', 2000))); $this->handler->handle($this->getRecord(Logger::CRITICAL, str_repeat('abcde', 2000)));
fseek($this->res, 0);
$content = fread($this->res, 12000);
$content = $this->socket->getOutput();
$this->assertRegexp('/message='.str_repeat('abcde', 1900).'\+%5Btruncated%5D/', $content); $this->assertRegexp('/message='.str_repeat('abcde', 1900).'\+%5Btruncated%5D/', $content);
} }
@@ -129,11 +123,10 @@ class HipChatHandlerTest extends TestCase
*/ */
public function testWriteWithErrorLevelsAndColors($level, $expectedColor) public function testWriteWithErrorLevelsAndColors($level, $expectedColor)
{ {
$this->createHandler(); $this->initHandlerAndSocket();
$this->handler->handle($this->getRecord($level, 'Backup of database "example" finished in 16 minutes.')); $this->handler->handle($this->getRecord($level, 'Backup of database "example" finished in 16 minutes.'));
fseek($this->res, 0);
$content = fread($this->res, 1024);
$content = $this->socket->getOutput();
$this->assertRegexp('/color='.$expectedColor.'/', $content); $this->assertRegexp('/color='.$expectedColor.'/', $content);
} }
@@ -156,13 +149,10 @@ class HipChatHandlerTest extends TestCase
*/ */
public function testHandleBatch($records, $expectedColor) public function testHandleBatch($records, $expectedColor)
{ {
$this->createHandler(); $this->initHandlerAndSocket();
$this->handler->handleBatch($records); $this->handler->handleBatch($records);
fseek($this->res, 0); $content = $this->socket->getOutput();
$content = fread($this->res, 1024);
$this->assertRegexp('/color='.$expectedColor.'/', $content); $this->assertRegexp('/color='.$expectedColor.'/', $content);
} }
@@ -200,36 +190,55 @@ class HipChatHandlerTest extends TestCase
]; ];
} }
private function createHandler($token = 'myToken', $room = 'room1', $name = 'Monolog', $notify = false, $host = 'api.hipchat.com', $version = 'v1')
{
$constructorArgs = [$token, $room, $name, $notify, Logger::DEBUG, true, true, 'text', $host, $version];
$this->res = fopen('php://memory', 'a');
$this->handler = $this->getMock(
'\Monolog\Handler\HipChatHandler',
['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());
}
public function testCreateWithTooLongNameV2() public function testCreateWithTooLongNameV2()
{ {
// creating a handler with too long of a name but using the v2 api doesn't matter. // 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'); $hipChatHandler = new HipChatHandler('token', 'room', 'SixteenCharsHere', false, Logger::CRITICAL, true, true, 'test', 'api.hipchat.com', 'v2');
} }
private function initHandlerAndSocket($token = 'myToken', $room = 'room1', $name = 'Monolog', $notify = false, $host = 'api.hipchat.com', $version = 'v1')
{
$tmpFile = sys_get_temp_dir().'/monolog-test-socket.php';
file_put_contents($tmpFile, <<<'SCRIPT'
<?php
$sock = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp'));
socket_bind($sock, '127.0.0.1', 51984);
socket_listen($sock);
while (true) {
$res = socket_accept($sock);
socket_set_option($res, SOL_SOCKET, SO_RCVTIMEO, array("sec" => 0, "usec" => 500));
while ($read = socket_read($res, 1024)) {
echo $read;
}
socket_close($res);
}
SCRIPT
);
$this->socket = new \Symfony\Component\Process\Process(escapeshellarg(PHP_BINARY).' '.escapeshellarg($tmpFile));
$this->socket->start();
$this->handler = new HipChatHandler($token, $room, $name, $notify, Logger::DEBUG, true, true, 'text', $host, $version);
$reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString');
$reflectionProperty->setAccessible(true);
$reflectionProperty->setValue($this->handler, '127.0.0.1:51984');
$this->handler->setFormatter($this->getIdentityFormatter());
}
private function closeSocket()
{
$this->socket->stop();
}
public function tearDown()
{
if (isset($this->socket)) {
$this->closeSocket();
unset($this->socket);
}
}
} }

View File

@@ -31,12 +31,10 @@ class LogEntriesHandlerTest extends TestCase
public function testWriteContent() public function testWriteContent()
{ {
$this->createHandler(); $this->initHandlerAndSocket();
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'Critical write test')); $this->handler->handle($this->getRecord(Logger::CRITICAL, 'Critical write test'));
fseek($this->res, 0); $content = $this->closeSocket();
$content = fread($this->res, 1024);
$this->assertRegexp('/testToken \[\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}\+00:00\] test.CRITICAL: Critical write test/', $content); $this->assertRegexp('/testToken \[\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}\+00:00\] test.CRITICAL: Critical write test/', $content);
} }
@@ -47,38 +45,57 @@ class LogEntriesHandlerTest extends TestCase
$this->getRecord(), $this->getRecord(),
$this->getRecord(), $this->getRecord(),
]; ];
$this->createHandler(); $this->initHandlerAndSocket();
$this->handler->handleBatch($records); $this->handler->handleBatch($records);
fseek($this->res, 0); $content = $this->closeSocket();
$content = fread($this->res, 1024);
$this->assertRegexp('/(testToken \[\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}\+00:00\] .* \[\] \[\]\n){3}/', $content); $this->assertRegexp('/(testToken \[\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}\+00:00\] .* \[\] \[\]\n){3}/', $content);
} }
private function createHandler() private function initHandlerAndSocket()
{ {
$tmpFile = sys_get_temp_dir().'/monolog-test-socket.php';
file_put_contents($tmpFile, <<<'SCRIPT'
<?php
$sock = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp'));
socket_bind($sock, '127.0.0.1', 51984);
socket_listen($sock);
while (true) {
$res = socket_accept($sock);
socket_set_option($res, SOL_SOCKET, SO_RCVTIMEO, array("sec" => 0, "usec" => 500));
while ($read = socket_read($res, 1024)) {
echo $read;
}
socket_close($res);
}
SCRIPT
);
$this->socket = new \Symfony\Component\Process\Process(escapeshellarg(PHP_BINARY).' '.escapeshellarg($tmpFile));
$this->socket->start();
$useSSL = extension_loaded('openssl'); $useSSL = extension_loaded('openssl');
$args = ['testToken', $useSSL, Logger::DEBUG, true]; $this->handler = new LogEntriesHandler('testToken', $useSSL, Logger::DEBUG, true);
$this->res = fopen('php://memory', 'a');
$this->handler = $this->getMock(
'\Monolog\Handler\LogEntriesHandler',
['fsockopen', 'streamSetTimeout', 'closeSocket'],
$args
);
$reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString'); $reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString');
$reflectionProperty->setAccessible(true); $reflectionProperty->setAccessible(true);
$reflectionProperty->setValue($this->handler, 'localhost:1234'); $reflectionProperty->setValue($this->handler, '127.0.0.1:51984');
}
$this->handler->expects($this->any()) private function closeSocket()
->method('fsockopen') {
->will($this->returnValue($this->res)); $this->socket->stop();
$this->handler->expects($this->any())
->method('streamSetTimeout') return $this->socket->getOutput();
->will($this->returnValue(true)); }
$this->handler->expects($this->any())
->method('closeSocket') public function tearDown()
->will($this->returnValue(true)); {
if (isset($this->socket)) {
$this->closeSocket();
unset($this->socket);
}
} }
} }

View File

@@ -31,11 +31,10 @@ class LogmaticHandlerTest extends TestCase
public function testWriteContent() public function testWriteContent()
{ {
$this->createHandler(); $this->initHandlerAndSocket();
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'Critical write test')); $this->handler->handle($this->getRecord(Logger::CRITICAL, 'Critical write test'));
fseek($this->res, 0); $content = $this->closeSocket();
$content = fread($this->res, 1024);
$this->assertRegexp('/testToken {"message":"Critical write test","context":\[\],"level":500,"level_name":"CRITICAL","channel":"test","datetime":"(.*)","extra":\[\],"hostname":"testHostname","appname":"testAppname"}/', $content); $this->assertRegexp('/testToken {"message":"Critical write test","context":\[\],"level":500,"level_name":"CRITICAL","channel":"test","datetime":"(.*)","extra":\[\],"hostname":"testHostname","appname":"testAppname"}/', $content);
} }
@@ -47,38 +46,58 @@ class LogmaticHandlerTest extends TestCase
$this->getRecord(), $this->getRecord(),
$this->getRecord(), $this->getRecord(),
]; ];
$this->createHandler(); $this->initHandlerAndSocket();
$this->handler->handleBatch($records); $this->handler->handleBatch($records);
fseek($this->res, 0); $content = $this->closeSocket();
$content = fread($this->res, 1024);
$this->assertRegexp('/testToken {"message":"test","context":\[\],"level":300,"level_name":"WARNING","channel":"test","datetime":"(.*)","extra":\[\],"hostname":"testHostname","appname":"testAppname"}/', $content); $this->assertRegexp('/testToken {"message":"test","context":\[\],"level":300,"level_name":"WARNING","channel":"test","datetime":"(.*)","extra":\[\],"hostname":"testHostname","appname":"testAppname"}/', $content);
} }
private function createHandler() private function initHandlerAndSocket()
{ {
$tmpFile = sys_get_temp_dir().'/monolog-test-socket.php';
file_put_contents($tmpFile, <<<'SCRIPT'
<?php
$sock = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp'));
socket_bind($sock, '127.0.0.1', 51984);
socket_listen($sock);
while (true) {
$res = socket_accept($sock);
socket_set_option($res, SOL_SOCKET, SO_RCVTIMEO, array("sec" => 0, "usec" => 500));
while ($read = socket_read($res, 1024)) {
echo $read;
}
socket_close($res);
}
SCRIPT
);
$this->socket = new \Symfony\Component\Process\Process(escapeshellarg(PHP_BINARY).' '.escapeshellarg($tmpFile));
$this->socket->start();
$useSSL = extension_loaded('openssl'); $useSSL = extension_loaded('openssl');
$args = ['testToken', 'testHostname', 'testAppname', $useSSL, Logger::DEBUG, true]; $this->handler = new LogmaticHandler('testToken', 'testHostname', 'testAppname', $useSSL, Logger::DEBUG, true);
$this->res = fopen('php://memory', 'a');
$this->handler = $this->getMock(
'\Monolog\Handler\LogmaticHandler',
['fsockopen', 'streamSetTimeout', 'closeSocket'],
$args
);
$reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString'); $reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString');
$reflectionProperty->setAccessible(true); $reflectionProperty->setAccessible(true);
$reflectionProperty->setValue($this->handler, 'localhost:1234'); $reflectionProperty->setValue($this->handler, '127.0.0.1:51984');
}
$this->handler->expects($this->any()) private function closeSocket()
->method('fsockopen') {
->will($this->returnValue($this->res)); $this->socket->stop();
$this->handler->expects($this->any())
->method('streamSetTimeout') return $this->socket->getOutput();
->will($this->returnValue(true)); }
$this->handler->expects($this->any())
->method('closeSocket') public function tearDown()
->will($this->returnValue(true)); {
if (isset($this->socket)) {
$this->closeSocket();
unset($this->socket);
}
} }
} }

View File

@@ -21,7 +21,7 @@ class MailHandlerTest extends TestCase
*/ */
public function testHandleBatch() public function testHandleBatch()
{ {
$formatter = $this->getMock('Monolog\\Formatter\\FormatterInterface'); $formatter = $this->createMock('Monolog\\Formatter\\FormatterInterface');
$formatter->expects($this->once()) $formatter->expects($this->once())
->method('formatBatch'); // Each record is formatted ->method('formatBatch'); // Each record is formatted

View File

@@ -39,7 +39,7 @@ class PsrHandlerTest extends TestCase
$message = 'Hello, world! ' . $level; $message = 'Hello, world! ' . $level;
$context = ['foo' => 'bar', 'level' => $level]; $context = ['foo' => 'bar', 'level' => $level];
$psrLogger = $this->getMock('Psr\Log\NullLogger'); $psrLogger = $this->createMock('Psr\Log\NullLogger');
$psrLogger->expects($this->once()) $psrLogger->expects($this->once())
->method('log') ->method('log')
->with(strtolower($levelName), $message, $context); ->with(strtolower($levelName), $message, $context);

View File

@@ -27,11 +27,10 @@ class PushoverHandlerTest extends TestCase
public function testWriteHeader() public function testWriteHeader()
{ {
$this->createHandler(); $this->initHandlerAndSocket();
$this->handler->setHighPriorityLevel(Logger::EMERGENCY); // skip priority notifications $this->handler->setHighPriorityLevel(Logger::EMERGENCY); // skip priority notifications
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
fseek($this->res, 0); $content = $this->closeSocket();
$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); $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);
@@ -48,21 +47,19 @@ class PushoverHandlerTest extends TestCase
public function testWriteWithComplexTitle() public function testWriteWithComplexTitle()
{ {
$this->createHandler('myToken', 'myUser', 'Backup finished - SQL1'); $this->initHandlerAndSocket('myToken', 'myUser', 'Backup finished - SQL1');
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
fseek($this->res, 0); $content = $this->closeSocket();
$content = fread($this->res, 1024);
$this->assertRegexp('/title=Backup\+finished\+-\+SQL1/', $content); $this->assertRegexp('/title=Backup\+finished\+-\+SQL1/', $content);
} }
public function testWriteWithComplexMessage() public function testWriteWithComplexMessage()
{ {
$this->createHandler(); $this->initHandlerAndSocket();
$this->handler->setHighPriorityLevel(Logger::EMERGENCY); // skip priority notifications $this->handler->setHighPriorityLevel(Logger::EMERGENCY); // skip priority notifications
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'Backup of database "example" finished in 16 minutes.')); $this->handler->handle($this->getRecord(Logger::CRITICAL, 'Backup of database "example" finished in 16 minutes.'));
fseek($this->res, 0); $content = $this->closeSocket();
$content = fread($this->res, 1024);
$this->assertRegexp('/message=Backup\+of\+database\+%22example%22\+finished\+in\+16\+minutes\./', $content); $this->assertRegexp('/message=Backup\+of\+database\+%22example%22\+finished\+in\+16\+minutes\./', $content);
} }
@@ -70,11 +67,10 @@ class PushoverHandlerTest extends TestCase
public function testWriteWithTooLongMessage() public function testWriteWithTooLongMessage()
{ {
$message = str_pad('test', 520, 'a'); $message = str_pad('test', 520, 'a');
$this->createHandler(); $this->initHandlerAndSocket();
$this->handler->setHighPriorityLevel(Logger::EMERGENCY); // skip priority notifications $this->handler->setHighPriorityLevel(Logger::EMERGENCY); // skip priority notifications
$this->handler->handle($this->getRecord(Logger::CRITICAL, $message)); $this->handler->handle($this->getRecord(Logger::CRITICAL, $message));
fseek($this->res, 0); $content = $this->closeSocket();
$content = fread($this->res, 1024);
$expectedMessage = substr($message, 0, 505); $expectedMessage = substr($message, 0, 505);
@@ -83,59 +79,77 @@ class PushoverHandlerTest extends TestCase
public function testWriteWithHighPriority() public function testWriteWithHighPriority()
{ {
$this->createHandler(); $this->initHandlerAndSocket();
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
fseek($this->res, 0); $content = $this->closeSocket();
$content = fread($this->res, 1024);
$this->assertRegexp('/token=myToken&user=myUser&message=test1&title=Monolog&timestamp=\d{10}&priority=1$/', $content); $this->assertRegexp('/token=myToken&user=myUser&message=test1&title=Monolog&timestamp=\d{10}&priority=1$/', $content);
} }
public function testWriteWithEmergencyPriority() public function testWriteWithEmergencyPriority()
{ {
$this->createHandler(); $this->initHandlerAndSocket();
$this->handler->handle($this->getRecord(Logger::EMERGENCY, 'test1')); $this->handler->handle($this->getRecord(Logger::EMERGENCY, 'test1'));
fseek($this->res, 0); $content = $this->closeSocket();
$content = fread($this->res, 1024);
$this->assertRegexp('/token=myToken&user=myUser&message=test1&title=Monolog&timestamp=\d{10}&priority=2&retry=30&expire=25200$/', $content); $this->assertRegexp('/token=myToken&user=myUser&message=test1&title=Monolog&timestamp=\d{10}&priority=2&retry=30&expire=25200$/', $content);
} }
public function testWriteToMultipleUsers() public function testWriteToMultipleUsers()
{ {
$this->createHandler('myToken', ['userA', 'userB']); $this->initHandlerAndSocket('myToken', ['userA', 'userB']);
$this->handler->handle($this->getRecord(Logger::EMERGENCY, 'test1')); $this->handler->handle($this->getRecord(Logger::EMERGENCY, 'test1'));
fseek($this->res, 0); $content = $this->closeSocket();
$content = fread($this->res, 1024);
$this->assertRegexp('/token=myToken&user=userA&message=test1&title=Monolog&timestamp=\d{10}&priority=2&retry=30&expire=25200POST/', $content); $this->assertRegexp('/token=myToken&user=userA&message=test1&title=Monolog&timestamp=\d{10}&priority=2&retry=30&expire=25200POST/', $content);
$this->assertRegexp('/token=myToken&user=userB&message=test1&title=Monolog&timestamp=\d{10}&priority=2&retry=30&expire=25200$/', $content); $this->assertRegexp('/token=myToken&user=userB&message=test1&title=Monolog&timestamp=\d{10}&priority=2&retry=30&expire=25200$/', $content);
} }
private function createHandler($token = 'myToken', $user = 'myUser', $title = 'Monolog') private function initHandlerAndSocket($token = 'myToken', $user = 'myUser', $title = 'Monolog')
{ {
$constructorArgs = [$token, $user, $title]; $tmpFile = sys_get_temp_dir().'/monolog-test-socket.php';
$this->res = fopen('php://memory', 'a'); file_put_contents($tmpFile, <<<'SCRIPT'
$this->handler = $this->getMock( <?php
'\Monolog\Handler\PushoverHandler',
['fsockopen', 'streamSetTimeout', 'closeSocket'], $sock = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp'));
$constructorArgs socket_bind($sock, '127.0.0.1', 51984);
); socket_listen($sock);
while (true) {
$res = socket_accept($sock);
socket_set_option($res, SOL_SOCKET, SO_RCVTIMEO, array("sec" => 0, "usec" => 500));
while ($read = socket_read($res, 1024)) {
echo $read;
}
socket_close($res);
}
SCRIPT
);
$this->socket = new \Symfony\Component\Process\Process(escapeshellarg(PHP_BINARY).' '.escapeshellarg($tmpFile));
$this->socket->start();
$this->handler = new PushoverHandler($token, $user, $title);
$reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString'); $reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString');
$reflectionProperty->setAccessible(true); $reflectionProperty->setAccessible(true);
$reflectionProperty->setValue($this->handler, 'localhost:1234'); $reflectionProperty->setValue($this->handler, '127.0.0.1:51984');
$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()); $this->handler->setFormatter($this->getIdentityFormatter());
} }
private function closeSocket()
{
$this->socket->stop();
return $this->socket->getOutput();
}
public function tearDown()
{
if (isset($this->socket)) {
$this->closeSocket();
unset($this->socket);
}
}
} }

View File

@@ -167,10 +167,10 @@ class RavenHandlerTest extends TestCase
$records[] = $this->getRecord(Logger::WARNING, 'warning'); $records[] = $this->getRecord(Logger::WARNING, 'warning');
$records[] = $this->getRecord(Logger::WARNING, 'warning'); $records[] = $this->getRecord(Logger::WARNING, 'warning');
$logFormatter = $this->getMock('Monolog\\Formatter\\FormatterInterface'); $logFormatter = $this->createMock('Monolog\\Formatter\\FormatterInterface');
$logFormatter->expects($this->once())->method('formatBatch'); $logFormatter->expects($this->once())->method('formatBatch');
$formatter = $this->getMock('Monolog\\Formatter\\FormatterInterface'); $formatter = $this->createMock('Monolog\\Formatter\\FormatterInterface');
$formatter->expects($this->once())->method('format')->with($this->callback(function ($record) { $formatter->expects($this->once())->method('format')->with($this->callback(function ($record) {
return $record['level'] == 400; return $record['level'] == 400;
})); }));
@@ -189,7 +189,7 @@ class RavenHandlerTest extends TestCase
$this->getRecord(Logger::INFO, 'information'), $this->getRecord(Logger::INFO, 'information'),
]; ];
$handler = $this->getMock('Monolog\Handler\RavenHandler', ['handle'], [$this->getRavenClient()]); $handler = $this->createMock('Monolog\Handler\RavenHandler', ['handle'], [$this->getRavenClient()]);
$handler->expects($this->never())->method('handle'); $handler->expects($this->never())->method('handle');
$handler->setLevel(Logger::ERROR); $handler->setLevel(Logger::ERROR);
$handler->handleBatch($records); $handler->handleBatch($records);

View File

@@ -27,24 +27,24 @@ class RedisHandlerTest extends TestCase
public function testConstructorShouldWorkWithPredis() public function testConstructorShouldWorkWithPredis()
{ {
$redis = $this->getMock('Predis\Client'); $redis = $this->createMock('Predis\Client');
$this->assertInstanceof('Monolog\Handler\RedisHandler', new RedisHandler($redis, 'key')); $this->assertInstanceof('Monolog\Handler\RedisHandler', new RedisHandler($redis, 'key'));
} }
public function testConstructorShouldWorkWithRedis() public function testConstructorShouldWorkWithRedis()
{ {
$redis = $this->getMock('Redis'); $redis = $this->createMock('Redis');
$this->assertInstanceof('Monolog\Handler\RedisHandler', new RedisHandler($redis, 'key')); $this->assertInstanceof('Monolog\Handler\RedisHandler', new RedisHandler($redis, 'key'));
} }
public function testPredisHandle() public function testPredisHandle()
{ {
$redis = $this->getMock('Predis\Client', ['rpush']); $redis = $this->createMock('Predis\Client', ['__call']);
// Predis\Client uses rpush // Predis\Client uses rpush
$redis->expects($this->once()) $redis->expects($this->once())
->method('rpush') ->method('__call')
->with('key', 'test'); ->with('rpush', ['key', 'test']);
$record = $this->getRecord(Logger::WARNING, 'test', ['data' => new \stdClass, 'foo' => 34]); $record = $this->getRecord(Logger::WARNING, 'test', ['data' => new \stdClass, 'foo' => 34]);
@@ -55,7 +55,7 @@ class RedisHandlerTest extends TestCase
public function testRedisHandle() public function testRedisHandle()
{ {
$redis = $this->getMock('Redis', ['rpush']); $redis = $this->createMock('Redis', ['rpush']);
// Redis uses rPush // Redis uses rPush
$redis->expects($this->once()) $redis->expects($this->once())
@@ -71,7 +71,7 @@ class RedisHandlerTest extends TestCase
public function testRedisHandleCapped() public function testRedisHandleCapped()
{ {
$redis = $this->getMock('Redis', ['multi', 'rpush', 'ltrim', 'exec']); $redis = $this->createMock('Redis', ['multi', 'rpush', 'ltrim', 'exec']);
// Redis uses multi // Redis uses multi
$redis->expects($this->once()) $redis->expects($this->once())
@@ -99,16 +99,18 @@ class RedisHandlerTest extends TestCase
public function testPredisHandleCapped() public function testPredisHandleCapped()
{ {
$redis = $this->getMock('Predis\Client', ['transaction']); $redis = $this->createMock('Predis\Client', ['transaction']);
$redisTransaction = $this->getMock('Predis\Client', ['rpush', 'ltrim']); $redisTransaction = $this->createMock('Predis\Client', ['__call']);
$redisTransaction->expects($this->once()) $redisTransaction->expects($this->at(0))
->method('rpush') ->method('__call')
->with('rpush')
->will($this->returnSelf()); ->will($this->returnSelf());
$redisTransaction->expects($this->once()) $redisTransaction->expects($this->at(1))
->method('ltrim') ->method('__call')
->with('ltrim')
->will($this->returnSelf()); ->will($this->returnSelf());
// Redis uses multi // Redis uses multi

View File

@@ -40,36 +40,32 @@ class SlackHandlerTest extends TestCase
public function testWriteHeader() public function testWriteHeader()
{ {
$this->createHandler(); $this->initHandlerAndSocket();
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
fseek($this->res, 0);
$content = fread($this->res, 1024);
$content = $this->closeSocket();
$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); $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() public function testWriteContent()
{ {
$this->createHandler(); $this->initHandlerAndSocket();
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
fseek($this->res, 0);
$content = fread($this->res, 1024);
$content = $this->closeSocket();
$this->assertRegexp('/token=myToken&channel=channel1&username=Monolog&text=&attachments=.*$/', $content); $this->assertRegexp('/token=myToken&channel=channel1&username=Monolog&text=&attachments=.*$/', $content);
} }
public function testWriteContentUsesFormatterIfProvided() public function testWriteContentUsesFormatterIfProvided()
{ {
$this->createHandler('myToken', 'channel1', 'Monolog', false); $this->initHandlerAndSocket('myToken', 'channel1', 'Monolog', false);
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
fseek($this->res, 0); $content = $this->closeSocket();
$content = fread($this->res, 1024);
$this->createHandler('myToken', 'channel1', 'Monolog', false); $this->initHandlerAndSocket('myToken', 'channel1', 'Monolog', false);
$this->handler->setFormatter(new LineFormatter('foo--%message%')); $this->handler->setFormatter(new LineFormatter('foo--%message%'));
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test2')); $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test2'));
fseek($this->res, 0); $content2 = $this->closeSocket();
$content2 = fread($this->res, 1024);
$this->assertRegexp('/token=myToken&channel=channel1&username=Monolog&text=test1.*$/', $content); $this->assertRegexp('/token=myToken&channel=channel1&username=Monolog&text=test1.*$/', $content);
$this->assertRegexp('/token=myToken&channel=channel1&username=Monolog&text=foo--test2.*$/', $content2); $this->assertRegexp('/token=myToken&channel=channel1&username=Monolog&text=foo--test2.*$/', $content2);
@@ -77,11 +73,10 @@ class SlackHandlerTest extends TestCase
public function testWriteContentWithEmoji() public function testWriteContentWithEmoji()
{ {
$this->createHandler('myToken', 'channel1', 'Monolog', true, 'alien'); $this->initHandlerAndSocket('myToken', 'channel1', 'Monolog', true, 'alien');
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
fseek($this->res, 0);
$content = fread($this->res, 1024);
$content = $this->closeSocket();
$this->assertRegexp('/icon_emoji=%3Aalien%3A$/', $content); $this->assertRegexp('/icon_emoji=%3Aalien%3A$/', $content);
} }
@@ -90,21 +85,19 @@ class SlackHandlerTest extends TestCase
*/ */
public function testWriteContentWithColors($level, $expectedColor) public function testWriteContentWithColors($level, $expectedColor)
{ {
$this->createHandler(); $this->initHandlerAndSocket();
$this->handler->handle($this->getRecord($level, 'test1')); $this->handler->handle($this->getRecord($level, 'test1'));
fseek($this->res, 0);
$content = fread($this->res, 1024);
$content = $this->closeSocket();
$this->assertRegexp('/color%22%3A%22'.$expectedColor.'/', $content); $this->assertRegexp('/color%22%3A%22'.$expectedColor.'/', $content);
} }
public function testWriteContentWithPlainTextMessage() public function testWriteContentWithPlainTextMessage()
{ {
$this->createHandler('myToken', 'channel1', 'Monolog', false); $this->initHandlerAndSocket('myToken', 'channel1', 'Monolog', false);
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
fseek($this->res, 0);
$content = fread($this->res, 1024);
$content = $this->closeSocket();
$this->assertRegexp('/text=test1/', $content); $this->assertRegexp('/text=test1/', $content);
} }
@@ -122,30 +115,51 @@ class SlackHandlerTest extends TestCase
]; ];
} }
private function createHandler($token = 'myToken', $channel = 'channel1', $username = 'Monolog', $useAttachment = true, $iconEmoji = null, $useShortAttachment = false, $includeExtra = false) private function initHandlerAndSocket($token = 'myToken', $channel = 'channel1', $username = 'Monolog', $useAttachment = true, $iconEmoji = null, $useShortAttachment = false, $includeExtra = false)
{ {
$constructorArgs = [$token, $channel, $username, $useAttachment, $iconEmoji, Logger::DEBUG, true, $useShortAttachment, $includeExtra]; $tmpFile = sys_get_temp_dir().'/monolog-test-socket.php';
$this->res = fopen('php://memory', 'a'); file_put_contents($tmpFile, <<<'SCRIPT'
$this->handler = $this->getMock( <?php
'\Monolog\Handler\SlackHandler',
['fsockopen', 'streamSetTimeout', 'closeSocket'], $sock = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp'));
$constructorArgs socket_bind($sock, '127.0.0.1', 51984);
); socket_listen($sock);
while (true) {
$res = socket_accept($sock);
socket_set_option($res, SOL_SOCKET, SO_RCVTIMEO, array("sec" => 0, "usec" => 500));
while ($read = socket_read($res, 1024)) {
echo $read;
}
socket_close($res);
}
SCRIPT
);
$this->socket = new \Symfony\Component\Process\Process(escapeshellarg(PHP_BINARY).' '.escapeshellarg($tmpFile));
$this->socket->start();
$this->handler = new SlackHandler($token, $channel, $username, $useAttachment, $iconEmoji, Logger::DEBUG, true, $useShortAttachment, $includeExtra);
$reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString'); $reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString');
$reflectionProperty->setAccessible(true); $reflectionProperty->setAccessible(true);
$reflectionProperty->setValue($this->handler, 'localhost:1234'); $reflectionProperty->setValue($this->handler, '127.0.0.1:51984');
$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()); $this->handler->setFormatter($this->getIdentityFormatter());
} }
private function closeSocket()
{
$this->socket->stop();
return $this->socket->getOutput();
}
public function tearDown()
{
if (isset($this->socket)) {
$this->closeSocket();
unset($this->socket);
}
}
} }

View File

@@ -88,10 +88,8 @@ class SocketHandlerTest extends TestCase
*/ */
public function testExceptionIsThrownOnFsockopenError() public function testExceptionIsThrownOnFsockopenError()
{ {
$this->setMockHandler(['fsockopen']); $this->createHandler('tcp://127.0.0.1:51985');
$this->handler->expects($this->once())
->method('fsockopen')
->will($this->returnValue(false));
$this->writeRecord('Hello world'); $this->writeRecord('Hello world');
} }
@@ -100,23 +98,9 @@ class SocketHandlerTest extends TestCase
*/ */
public function testExceptionIsThrownOnPfsockopenError() public function testExceptionIsThrownOnPfsockopenError()
{ {
$this->setMockHandler(['pfsockopen']); $this->createHandler('tcp://127.0.0.1:51985');
$this->handler->expects($this->once())
->method('pfsockopen')
->will($this->returnValue(false));
$this->handler->setPersistent(true); $this->handler->setPersistent(true);
$this->writeRecord('Hello world');
}
/**
* @expectedException UnexpectedValueException
*/
public function testExceptionIsThrownIfCannotSetTimeout()
{
$this->setMockHandler(['streamSetTimeout']);
$this->handler->expects($this->once())
->method('streamSetTimeout')
->will($this->returnValue(false));
$this->writeRecord('Hello world'); $this->writeRecord('Hello world');
} }
@@ -125,46 +109,12 @@ class SocketHandlerTest extends TestCase
*/ */
public function testWriteFailsOnIfFwriteReturnsFalse() public function testWriteFailsOnIfFwriteReturnsFalse()
{ {
$this->setMockHandler(['fwrite']); $this->initHandlerAndSocket();
$callback = function ($arg) {
$map = [
'Hello world' => 6,
'world' => false,
];
return $map[$arg];
};
$this->handler->expects($this->exactly(2))
->method('fwrite')
->will($this->returnCallback($callback));
$this->writeRecord('Hello world'); $this->writeRecord('Hello world');
}
/** $reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'resource');
* @expectedException RuntimeException $reflectionProperty->setAccessible(true);
*/ fclose($reflectionProperty->getValue($this->handler));
public function testWriteFailsIfStreamTimesOut()
{
$this->setMockHandler(['fwrite', 'streamGetMetadata']);
$callback = function ($arg) {
$map = [
'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(['timed_out' => true]));
$this->writeRecord('Hello world'); $this->writeRecord('Hello world');
} }
@@ -174,92 +124,54 @@ class SocketHandlerTest extends TestCase
*/ */
public function testWriteFailsOnIncompleteWrite() public function testWriteFailsOnIncompleteWrite()
{ {
$this->setMockHandler(['fwrite', 'streamGetMetadata']); $this->initHandlerAndSocket();
$res = $this->res; $this->handler->setWritingTimeout(1);
$callback = function ($string) use ($res) {
fclose($res);
return strlen('Hello'); // the socket will close itself after processing 10000 bytes so while processing b, and then c write fails
}; $this->writeRecord(str_repeat("aaaaaaaaaa\n", 700));
$this->assertTrue(true); // asserting to make sure we reach this point
$this->handler->expects($this->exactly(1)) $this->writeRecord(str_repeat("bbbbbbbbbb\n", 700));
->method('fwrite') $this->assertTrue(true); // asserting to make sure we reach this point
->will($this->returnCallback($callback)); $this->writeRecord(str_repeat("cccccccccc\n", 700));
$this->handler->expects($this->exactly(1)) $this->fail('The test should not reach here');
->method('streamGetMetadata')
->will($this->returnValue(['timed_out' => false]));
$this->writeRecord('Hello world');
} }
public function testWriteWithMemoryFile() public function testWriteWithMemoryFile()
{ {
$this->setMockHandler(); $this->initHandlerAndSocket();
$this->writeRecord('test1'); $this->writeRecord('test1');
$this->writeRecord('test2'); $this->writeRecord('test2');
$this->writeRecord('test3'); $this->writeRecord('test3');
fseek($this->res, 0); $this->closeSocket();
$this->assertEquals('test1test2test3', fread($this->res, 1024)); $this->assertEquals('test1test2test3', $this->socket->getOutput());
}
public function testWriteWithMock()
{
$this->setMockHandler(['fwrite']);
$callback = function ($arg) {
$map = [
'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() public function testClose()
{ {
$this->setMockHandler(); $this->initHandlerAndSocket();
$this->writeRecord('Hello world'); $this->writeRecord('Hello world');
$this->assertInternalType('resource', $this->res);
$reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'resource');
$reflectionProperty->setAccessible(true);
$this->assertInternalType('resource', $reflectionProperty->getValue($this->handler));
$this->handler->close(); $this->handler->close();
$this->assertFalse(is_resource($this->res), "Expected resource to be closed after closing handler"); $this->assertFalse(is_resource($reflectionProperty->getValue($this->handler)), "Expected resource to be closed after closing handler");
} }
public function testCloseDoesNotClosePersistentSocket() public function testCloseDoesNotClosePersistentSocket()
{ {
$this->setMockHandler(); $this->initHandlerAndSocket();
$this->handler->setPersistent(true); $this->handler->setPersistent(true);
$this->writeRecord('Hello world'); $this->writeRecord('Hello world');
$this->assertTrue(is_resource($this->res));
$reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'resource');
$reflectionProperty->setAccessible(true);
$this->assertTrue(is_resource($reflectionProperty->getValue($this->handler)));
$this->handler->close(); $this->handler->close();
$this->assertTrue(is_resource($this->res)); $this->assertTrue(is_resource($reflectionProperty->getValue($this->handler)));
}
/**
* @expectedException \RuntimeException
*/
public function testAvoidInfiniteLoopWhenNoDataIsWrittenForAWritingTimeoutSeconds()
{
$this->setMockHandler(['fwrite', 'streamGetMetadata']);
$this->handler->expects($this->any())
->method('fwrite')
->will($this->returnValue(0));
$this->handler->expects($this->any())
->method('streamGetMetadata')
->will($this->returnValue(['timed_out' => false]));
$this->handler->setWritingTimeout(1);
$this->writeRecord('Hello world');
} }
private function createHandler($connectionString) private function createHandler($connectionString)
@@ -273,37 +185,49 @@ class SocketHandlerTest extends TestCase
$this->handler->handle($this->getRecord(Logger::WARNING, $string)); $this->handler->handle($this->getRecord(Logger::WARNING, $string));
} }
private function setMockHandler(array $methods = []) private function initHandlerAndSocket()
{ {
$this->res = fopen('php://memory', 'a'); $tmpFile = sys_get_temp_dir().'/monolog-test-socket.php';
file_put_contents($tmpFile, <<<'SCRIPT'
<?php
$defaultMethods = ['fsockopen', 'pfsockopen', 'streamSetTimeout']; $sock = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp'));
$newMethods = array_diff($methods, $defaultMethods); socket_bind($sock, '127.0.0.1', 51984);
socket_listen($sock);
$finalMethods = array_merge($defaultMethods, $newMethods); $res = socket_accept($sock);
socket_set_option($res, SOL_SOCKET, SO_RCVTIMEO, array("sec" => 0, "usec" => 500));
$this->handler = $this->getMock( $bytesRead = 0;
'\Monolog\Handler\SocketHandler', $finalMethods, ['localhost:1234'] while ($read = socket_read($res, 1024)) {
); echo $read;
$bytesRead += strlen($read);
if (!in_array('fsockopen', $methods)) { if ($bytesRead > 10000) {
$this->handler->expects($this->any()) socket_close($res);
->method('fsockopen') socket_close($sock);
->will($this->returnValue($this->res)); die('CLOSED');
} }
}
if (!in_array('pfsockopen', $methods)) { echo 'EXIT';
$this->handler->expects($this->any()) socket_close($res);
->method('pfsockopen') SCRIPT
->will($this->returnValue($this->res)); );
}
$this->socket = new \Symfony\Component\Process\Process(escapeshellarg(PHP_BINARY).' '.escapeshellarg($tmpFile));
if (!in_array('streamSetTimeout', $methods)) { $this->socket->start();
$this->handler->expects($this->any())
->method('streamSetTimeout') $this->handler = new SocketHandler('tcp://127.0.0.1:51984');
->will($this->returnValue(true)); $this->handler->setFormatter($this->getIdentityFormatter());
} }
$this->handler->setFormatter($this->getIdentityFormatter()); private function closeSocket()
{
$this->socket->stop();
}
public function tearDown()
{
if (isset($this->socket)) {
$this->closeSocket();
unset($this->socket);
}
} }
} }

View File

@@ -29,7 +29,7 @@ class SyslogUdpHandlerTest extends \PHPUnit_Framework_TestCase
$handler = new SyslogUdpHandler("127.0.0.1", 514, "authpriv"); $handler = new SyslogUdpHandler("127.0.0.1", 514, "authpriv");
$handler->setFormatter(new \Monolog\Formatter\ChromePHPFormatter()); $handler->setFormatter(new \Monolog\Formatter\ChromePHPFormatter());
$socket = $this->getMock('\Monolog\Handler\SyslogUdp\UdpSocket', ['write'], ['lol', 'lol']); $socket = $this->createMock('\Monolog\Handler\SyslogUdp\UdpSocket', ['write'], ['lol', 'lol']);
$socket->expects($this->at(0)) $socket->expects($this->at(0))
->method('write') ->method('write')
->with("lol", "<".(LOG_AUTHPRIV + LOG_WARNING).">1 "); ->with("lol", "<".(LOG_AUTHPRIV + LOG_WARNING).">1 ");

View File

@@ -21,28 +21,28 @@ class UdpSocketTest extends TestCase
{ {
public function testWeDoNotTruncateShortMessages() public function testWeDoNotTruncateShortMessages()
{ {
$socket = $this->getMock('\Monolog\Handler\SyslogUdp\UdpSocket', ['send'], ['lol', 'lol']); $this->initSocket();
$socket->expects($this->at(0))
->method('send')
->with("HEADER: The quick brown fox jumps over the lazy dog");
$socket = new UdpSocket('127.0.0.1', 51984);
$socket->write("The quick brown fox jumps over the lazy dog", "HEADER: "); $socket->write("The quick brown fox jumps over the lazy dog", "HEADER: ");
$this->closeSocket();
$this->assertEquals('HEADER: The quick brown fox jumps over the lazy dog', $this->socket->getOutput());
} }
public function testLongMessagesAreTruncated() public function testLongMessagesAreTruncated()
{ {
$socket = $this->getMock('\Monolog\Handler\SyslogUdp\UdpSocket', ['send'], ['lol', 'lol']); $this->initSocket();
$socket = new UdpSocket('127.0.0.1', 51984);
$longString = str_repeat("derp", 20000);
$socket->write($longString, "HEADER");
$truncatedString = str_repeat("derp", 16254).'d'; $truncatedString = str_repeat("derp", 16254).'d';
$socket->expects($this->exactly(1)) $this->closeSocket();
->method('send') $this->assertEquals('HEADER'.$truncatedString, $this->socket->getOutput());
->with("HEADER" . $truncatedString);
$longString = str_repeat("derp", 20000);
$socket->write($longString, "HEADER");
} }
public function testDoubleCloseDoesNotError() public function testDoubleCloseDoesNotError()
@@ -61,4 +61,46 @@ class UdpSocketTest extends TestCase
$socket->close(); $socket->close();
$socket->write('foo', "HEADER"); $socket->write('foo', "HEADER");
} }
private function initSocket()
{
$tmpFile = sys_get_temp_dir().'/monolog-test-socket.php';
file_put_contents($tmpFile, <<<'SCRIPT'
<?php
$sock = socket_create(AF_INET, SOCK_DGRAM, getprotobyname('udp'));
socket_bind($sock, '127.0.0.1', 51984);
echo 'INIT';
while (true) {
socket_recvfrom($sock, $read, 100*1024, 0, $ip, $port);
echo $read;
}
SCRIPT
);
$this->socket = new \Symfony\Component\Process\Process(escapeshellarg(PHP_BINARY).' '.escapeshellarg($tmpFile));
$this->socket->start();
while (true) {
if ($this->socket->getOutput() === 'INIT') {
$this->socket->clearOutput();
break;
}
usleep(100);
}
}
private function closeSocket()
{
usleep(100);
$this->socket->stop();
}
public function tearDown()
{
if (isset($this->socket)) {
$this->closeSocket();
unset($this->socket);
}
}
} }

View File

@@ -90,10 +90,11 @@ class LoggerTest extends \PHPUnit_Framework_TestCase
{ {
$logger = new Logger(__METHOD__); $logger = new Logger(__METHOD__);
$handler = $this->getMock('Monolog\Handler\NullHandler', ['handle']); $handler = $this->prophesize('Monolog\Handler\NullHandler');
$handler->expects($this->once()) $handler->handle(\Prophecy\Argument::any())->shouldBeCalled();
->method('handle'); $handler->isHandling(['level' => 300])->willReturn(true);
$logger->pushHandler($handler);
$logger->pushHandler($handler->reveal());
$this->assertTrue($logger->warning('test')); $this->assertTrue($logger->warning('test'));
} }
@@ -105,10 +106,11 @@ class LoggerTest extends \PHPUnit_Framework_TestCase
{ {
$logger = new Logger(__METHOD__); $logger = new Logger(__METHOD__);
$handler = $this->getMock('Monolog\Handler\NullHandler', ['handle'], [Logger::ERROR]); $handler = $this->prophesize('Monolog\Handler\NullHandler');
$handler->expects($this->never()) $handler->handle()->shouldNotBeCalled();
->method('handle'); $handler->isHandling(['level' => 300])->willReturn(false);
$logger->pushHandler($handler);
$logger->pushHandler($handler->reveal());
$this->assertFalse($logger->warning('test')); $this->assertFalse($logger->warning('test'));
} }
@@ -219,7 +221,7 @@ class LoggerTest extends \PHPUnit_Framework_TestCase
public function testProcessorsAreCalledOnlyOnce() public function testProcessorsAreCalledOnlyOnce()
{ {
$logger = new Logger(__METHOD__); $logger = new Logger(__METHOD__);
$handler = $this->getMock('Monolog\Handler\HandlerInterface'); $handler = $this->createMock('Monolog\Handler\HandlerInterface');
$handler->expects($this->any()) $handler->expects($this->any())
->method('isHandling') ->method('isHandling')
->will($this->returnValue(true)) ->will($this->returnValue(true))
@@ -250,7 +252,7 @@ class LoggerTest extends \PHPUnit_Framework_TestCase
public function testProcessorsNotCalledWhenNotHandled() public function testProcessorsNotCalledWhenNotHandled()
{ {
$logger = new Logger(__METHOD__); $logger = new Logger(__METHOD__);
$handler = $this->getMock('Monolog\Handler\HandlerInterface'); $handler = $this->createMock('Monolog\Handler\HandlerInterface');
$handler->expects($this->once()) $handler->expects($this->once())
->method('isHandling') ->method('isHandling')
->will($this->returnValue(false)) ->will($this->returnValue(false))
@@ -270,7 +272,7 @@ class LoggerTest extends \PHPUnit_Framework_TestCase
{ {
$logger = new Logger(__METHOD__); $logger = new Logger(__METHOD__);
$handler1 = $this->getMock('Monolog\Handler\HandlerInterface'); $handler1 = $this->createMock('Monolog\Handler\HandlerInterface');
$handler1->expects($this->never()) $handler1->expects($this->never())
->method('isHandling') ->method('isHandling')
->will($this->returnValue(false)) ->will($this->returnValue(false))
@@ -281,7 +283,7 @@ class LoggerTest extends \PHPUnit_Framework_TestCase
; ;
$logger->pushHandler($handler1); $logger->pushHandler($handler1);
$handler2 = $this->getMock('Monolog\Handler\HandlerInterface'); $handler2 = $this->createMock('Monolog\Handler\HandlerInterface');
$handler2->expects($this->once()) $handler2->expects($this->once())
->method('isHandling') ->method('isHandling')
->will($this->returnValue(true)) ->will($this->returnValue(true))
@@ -292,7 +294,7 @@ class LoggerTest extends \PHPUnit_Framework_TestCase
; ;
$logger->pushHandler($handler2); $logger->pushHandler($handler2);
$handler3 = $this->getMock('Monolog\Handler\HandlerInterface'); $handler3 = $this->createMock('Monolog\Handler\HandlerInterface');
$handler3->expects($this->once()) $handler3->expects($this->once())
->method('isHandling') ->method('isHandling')
->will($this->returnValue(false)) ->will($this->returnValue(false))
@@ -310,7 +312,7 @@ class LoggerTest extends \PHPUnit_Framework_TestCase
*/ */
public function testHandlersNotCalledBeforeFirstHandlingWithAssocArray() public function testHandlersNotCalledBeforeFirstHandlingWithAssocArray()
{ {
$handler1 = $this->getMock('Monolog\Handler\HandlerInterface'); $handler1 = $this->createMock('Monolog\Handler\HandlerInterface');
$handler1->expects($this->never()) $handler1->expects($this->never())
->method('isHandling') ->method('isHandling')
->will($this->returnValue(false)) ->will($this->returnValue(false))
@@ -320,7 +322,7 @@ class LoggerTest extends \PHPUnit_Framework_TestCase
->will($this->returnValue(false)) ->will($this->returnValue(false))
; ;
$handler2 = $this->getMock('Monolog\Handler\HandlerInterface'); $handler2 = $this->createMock('Monolog\Handler\HandlerInterface');
$handler2->expects($this->once()) $handler2->expects($this->once())
->method('isHandling') ->method('isHandling')
->will($this->returnValue(true)) ->will($this->returnValue(true))
@@ -330,7 +332,7 @@ class LoggerTest extends \PHPUnit_Framework_TestCase
->will($this->returnValue(false)) ->will($this->returnValue(false))
; ;
$handler3 = $this->getMock('Monolog\Handler\HandlerInterface'); $handler3 = $this->createMock('Monolog\Handler\HandlerInterface');
$handler3->expects($this->once()) $handler3->expects($this->once())
->method('isHandling') ->method('isHandling')
->will($this->returnValue(false)) ->will($this->returnValue(false))
@@ -351,7 +353,7 @@ class LoggerTest extends \PHPUnit_Framework_TestCase
{ {
$logger = new Logger(__METHOD__); $logger = new Logger(__METHOD__);
$handler1 = $this->getMock('Monolog\Handler\HandlerInterface'); $handler1 = $this->createMock('Monolog\Handler\HandlerInterface');
$handler1->expects($this->any()) $handler1->expects($this->any())
->method('isHandling') ->method('isHandling')
->will($this->returnValue(true)) ->will($this->returnValue(true))
@@ -362,7 +364,7 @@ class LoggerTest extends \PHPUnit_Framework_TestCase
; ;
$logger->pushHandler($handler1); $logger->pushHandler($handler1);
$handler2 = $this->getMock('Monolog\Handler\HandlerInterface'); $handler2 = $this->createMock('Monolog\Handler\HandlerInterface');
$handler2->expects($this->any()) $handler2->expects($this->any())
->method('isHandling') ->method('isHandling')
->will($this->returnValue(true)) ->will($this->returnValue(true))
@@ -383,7 +385,7 @@ class LoggerTest extends \PHPUnit_Framework_TestCase
{ {
$logger = new Logger(__METHOD__); $logger = new Logger(__METHOD__);
$handler1 = $this->getMock('Monolog\Handler\HandlerInterface'); $handler1 = $this->createMock('Monolog\Handler\HandlerInterface');
$handler1->expects($this->any()) $handler1->expects($this->any())
->method('isHandling') ->method('isHandling')
->will($this->returnValue(true)) ->will($this->returnValue(true))
@@ -393,7 +395,7 @@ class LoggerTest extends \PHPUnit_Framework_TestCase
; ;
$logger->pushHandler($handler1); $logger->pushHandler($handler1);
$handler2 = $this->getMock('Monolog\Handler\HandlerInterface'); $handler2 = $this->createMock('Monolog\Handler\HandlerInterface');
$handler2->expects($this->any()) $handler2->expects($this->any())
->method('isHandling') ->method('isHandling')
->will($this->returnValue(true)) ->will($this->returnValue(true))
@@ -414,7 +416,7 @@ class LoggerTest extends \PHPUnit_Framework_TestCase
{ {
$logger = new Logger(__METHOD__); $logger = new Logger(__METHOD__);
$handler1 = $this->getMock('Monolog\Handler\HandlerInterface'); $handler1 = $this->createMock('Monolog\Handler\HandlerInterface');
$handler1->expects($this->any()) $handler1->expects($this->any())
->method('isHandling') ->method('isHandling')
->will($this->returnValue(false)) ->will($this->returnValue(false))
@@ -423,7 +425,7 @@ class LoggerTest extends \PHPUnit_Framework_TestCase
$logger->pushHandler($handler1); $logger->pushHandler($handler1);
$this->assertFalse($logger->isHandling(Logger::DEBUG)); $this->assertFalse($logger->isHandling(Logger::DEBUG));
$handler2 = $this->getMock('Monolog\Handler\HandlerInterface'); $handler2 = $this->createMock('Monolog\Handler\HandlerInterface');
$handler2->expects($this->any()) $handler2->expects($this->any())
->method('isHandling') ->method('isHandling')
->will($this->returnValue(true)) ->will($this->returnValue(true))