Browse Source

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

Jordi Boggiano 9 years ago
parent
commit
c6a9f28e24

+ 4 - 2
composer.json

@@ -17,7 +17,7 @@
         "psr/log": "^1.0"
     },
     "require-dev": {
-        "phpunit/phpunit": "^5.3",
+        "phpunit/phpunit": "^5.5",
         "graylog2/gelf-php": "^1.4.2",
         "sentry/sentry": "^0.13",
         "ruflin/elastica": ">=0.90 <3.0",
@@ -26,7 +26,9 @@
         "php-amqplib/php-amqplib": "~2.4",
         "swiftmailer/swiftmailer": "~5.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": {
         "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",

+ 1 - 1
src/Monolog/Test/TestCase.php

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

+ 2 - 2
tests/Monolog/Handler/AmqpHandlerTest.php

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

+ 1 - 1
tests/Monolog/Handler/DynamoDbHandlerTest.php

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

+ 16 - 17
tests/Monolog/Handler/FlowdockHandlerTest.php

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

+ 1 - 1
tests/Monolog/Handler/GelfHandlerTest.php

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

+ 1 - 1
tests/Monolog/Handler/HandlerWrapperTest.php

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

+ 57 - 48
tests/Monolog/Handler/HipChatHandlerTest.php

@@ -26,11 +26,10 @@ class HipChatHandlerTest extends TestCase
 
     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'));
-        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);
 
         return $content;
@@ -38,10 +37,9 @@ class HipChatHandlerTest extends TestCase
 
     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'));
-        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);
 
@@ -50,10 +48,9 @@ class HipChatHandlerTest extends TestCase
 
     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'));
-        fseek($this->res, 0);
-        $content = fread($this->res, 1024);
+        $content = $this->socket->getOutput();
 
         $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()
     {
-        $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'));
-        fseek($this->res, 0);
-        $content = fread($this->res, 1024);
+        $content = $this->socket->getOutput();
 
         $this->assertRegexp('/notify=false&message=test1&message_format=text&color=red$/', $content);
 
@@ -106,21 +102,19 @@ class HipChatHandlerTest extends TestCase
 
     public function testWriteWithComplexMessage()
     {
-        $this->createHandler();
+        $this->initHandlerAndSocket();
         $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);
     }
 
     public function testWriteTruncatesLongMessage()
     {
-        $this->createHandler();
+        $this->initHandlerAndSocket();
         $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);
     }
 
@@ -129,11 +123,10 @@ class HipChatHandlerTest extends TestCase
      */
     public function testWriteWithErrorLevelsAndColors($level, $expectedColor)
     {
-        $this->createHandler();
+        $this->initHandlerAndSocket();
         $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);
     }
 
@@ -156,13 +149,10 @@ class HipChatHandlerTest extends TestCase
      */
     public function testHandleBatch($records, $expectedColor)
     {
-        $this->createHandler();
-
+        $this->initHandlerAndSocket();
         $this->handler->handleBatch($records);
 
-        fseek($this->res, 0);
-        $content = fread($this->res, 1024);
-
+        $content = $this->socket->getOutput();
         $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')
+    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');
+    }
+
+    private function initHandlerAndSocket($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
-        );
+        $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, '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));
+        $reflectionProperty->setValue($this->handler, '127.0.0.1:51984');
 
         $this->handler->setFormatter($this->getIdentityFormatter());
     }
 
-    public function testCreateWithTooLongNameV2()
+    private function closeSocket()
     {
-        // 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');
+        $this->socket->stop();
+    }
+
+    public function tearDown()
+    {
+        if (isset($this->socket)) {
+            $this->closeSocket();
+            unset($this->socket);
+        }
     }
 }

+ 44 - 27
tests/Monolog/Handler/LogEntriesHandlerTest.php

@@ -31,12 +31,10 @@ class LogEntriesHandlerTest extends TestCase
 
     public function testWriteContent()
     {
-        $this->createHandler();
+        $this->initHandlerAndSocket();
         $this->handler->handle($this->getRecord(Logger::CRITICAL, 'Critical write test'));
 
-        fseek($this->res, 0);
-        $content = fread($this->res, 1024);
-
+        $content = $this->closeSocket();
         $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->createHandler();
+        $this->initHandlerAndSocket();
         $this->handler->handleBatch($records);
 
-        fseek($this->res, 0);
-        $content = fread($this->res, 1024);
-
+        $content = $this->closeSocket();
         $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');
-        $args = ['testToken', $useSSL, Logger::DEBUG, true];
-        $this->res = fopen('php://memory', 'a');
-        $this->handler = $this->getMock(
-            '\Monolog\Handler\LogEntriesHandler',
-            ['fsockopen', 'streamSetTimeout', 'closeSocket'],
-            $args
-        );
+        $this->handler = new LogEntriesHandler('testToken', $useSSL, Logger::DEBUG, true);
 
         $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));
+        $reflectionProperty->setValue($this->handler, '127.0.0.1:51984');
+    }
+
+    private function closeSocket()
+    {
+        $this->socket->stop();
+
+        return $this->socket->getOutput();
+    }
+
+    public function tearDown()
+    {
+        if (isset($this->socket)) {
+            $this->closeSocket();
+            unset($this->socket);
+        }
     }
 }

+ 44 - 25
tests/Monolog/Handler/LogmaticHandlerTest.php

@@ -31,11 +31,10 @@ class LogmaticHandlerTest extends TestCase
 
     public function testWriteContent()
     {
-        $this->createHandler();
+        $this->initHandlerAndSocket();
         $this->handler->handle($this->getRecord(Logger::CRITICAL, 'Critical write test'));
 
-        fseek($this->res, 0);
-        $content = fread($this->res, 1024);
+        $content = $this->closeSocket();
 
         $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->createHandler();
+        $this->initHandlerAndSocket();
         $this->handler->handleBatch($records);
 
-        fseek($this->res, 0);
-        $content = fread($this->res, 1024);
+        $content = $this->closeSocket();
 
         $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');
-        $args = ['testToken', 'testHostname', 'testAppname', $useSSL, Logger::DEBUG, true];
-        $this->res = fopen('php://memory', 'a');
-        $this->handler = $this->getMock(
-            '\Monolog\Handler\LogmaticHandler',
-            ['fsockopen', 'streamSetTimeout', 'closeSocket'],
-            $args
-        );
+        $this->handler = new LogmaticHandler('testToken', 'testHostname', 'testAppname', $useSSL, Logger::DEBUG, true);
 
         $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));
+        $reflectionProperty->setValue($this->handler, '127.0.0.1:51984');
+    }
+
+    private function closeSocket()
+    {
+        $this->socket->stop();
+
+        return $this->socket->getOutput();
+    }
+
+    public function tearDown()
+    {
+        if (isset($this->socket)) {
+            $this->closeSocket();
+            unset($this->socket);
+        }
     }
 }

+ 1 - 1
tests/Monolog/Handler/MailHandlerTest.php

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

+ 1 - 1
tests/Monolog/Handler/PsrHandlerTest.php

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

+ 54 - 40
tests/Monolog/Handler/PushoverHandlerTest.php

@@ -27,11 +27,10 @@ class PushoverHandlerTest extends TestCase
 
     public function testWriteHeader()
     {
-        $this->createHandler();
+        $this->initHandlerAndSocket();
         $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);
+        $content = $this->closeSocket();
 
         $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()
     {
-        $this->createHandler('myToken', 'myUser', 'Backup finished - SQL1');
+        $this->initHandlerAndSocket('myToken', 'myUser', 'Backup finished - SQL1');
         $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
-        fseek($this->res, 0);
-        $content = fread($this->res, 1024);
+        $content = $this->closeSocket();
 
         $this->assertRegexp('/title=Backup\+finished\+-\+SQL1/', $content);
     }
 
     public function testWriteWithComplexMessage()
     {
-        $this->createHandler();
+        $this->initHandlerAndSocket();
         $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);
+        $content = $this->closeSocket();
 
         $this->assertRegexp('/message=Backup\+of\+database\+%22example%22\+finished\+in\+16\+minutes\./', $content);
     }
@@ -70,11 +67,10 @@ class PushoverHandlerTest extends TestCase
     public function testWriteWithTooLongMessage()
     {
         $message = str_pad('test', 520, 'a');
-        $this->createHandler();
+        $this->initHandlerAndSocket();
         $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);
+        $content = $this->closeSocket();
 
         $expectedMessage = substr($message, 0, 505);
 
@@ -83,59 +79,77 @@ class PushoverHandlerTest extends TestCase
 
     public function testWriteWithHighPriority()
     {
-        $this->createHandler();
+        $this->initHandlerAndSocket();
         $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
-        fseek($this->res, 0);
-        $content = fread($this->res, 1024);
+        $content = $this->closeSocket();
 
         $this->assertRegexp('/token=myToken&user=myUser&message=test1&title=Monolog&timestamp=\d{10}&priority=1$/', $content);
     }
 
     public function testWriteWithEmergencyPriority()
     {
-        $this->createHandler();
+        $this->initHandlerAndSocket();
         $this->handler->handle($this->getRecord(Logger::EMERGENCY, 'test1'));
-        fseek($this->res, 0);
-        $content = fread($this->res, 1024);
+        $content = $this->closeSocket();
 
         $this->assertRegexp('/token=myToken&user=myUser&message=test1&title=Monolog&timestamp=\d{10}&priority=2&retry=30&expire=25200$/', $content);
     }
 
     public function testWriteToMultipleUsers()
     {
-        $this->createHandler('myToken', ['userA', 'userB']);
+        $this->initHandlerAndSocket('myToken', ['userA', 'userB']);
         $this->handler->handle($this->getRecord(Logger::EMERGENCY, 'test1'));
-        fseek($this->res, 0);
-        $content = fread($this->res, 1024);
+        $content = $this->closeSocket();
 
         $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);
     }
 
-    private function createHandler($token = 'myToken', $user = 'myUser', $title = 'Monolog')
+    private function initHandlerAndSocket($token = 'myToken', $user = 'myUser', $title = 'Monolog')
     {
-        $constructorArgs = [$token, $user, $title];
-        $this->res = fopen('php://memory', 'a');
-        $this->handler = $this->getMock(
-            '\Monolog\Handler\PushoverHandler',
-            ['fsockopen', 'streamSetTimeout', 'closeSocket'],
-            $constructorArgs
-        );
+        $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 PushoverHandler($token, $user, $title);
 
         $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));
+        $reflectionProperty->setValue($this->handler, '127.0.0.1:51984');
 
         $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);
+        }
+    }
 }

+ 3 - 3
tests/Monolog/Handler/RavenHandlerTest.php

@@ -167,10 +167,10 @@ class RavenHandlerTest extends TestCase
         $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');
 
-        $formatter = $this->getMock('Monolog\\Formatter\\FormatterInterface');
+        $formatter = $this->createMock('Monolog\\Formatter\\FormatterInterface');
         $formatter->expects($this->once())->method('format')->with($this->callback(function ($record) {
             return $record['level'] == 400;
         }));
@@ -189,7 +189,7 @@ class RavenHandlerTest extends TestCase
             $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->setLevel(Logger::ERROR);
         $handler->handleBatch($records);

+ 15 - 13
tests/Monolog/Handler/RedisHandlerTest.php

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

+ 54 - 40
tests/Monolog/Handler/SlackHandlerTest.php

@@ -40,36 +40,32 @@ class SlackHandlerTest extends TestCase
 
     public function testWriteHeader()
     {
-        $this->createHandler();
+        $this->initHandlerAndSocket();
         $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);
     }
 
     public function testWriteContent()
     {
-        $this->createHandler();
+        $this->initHandlerAndSocket();
         $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);
     }
 
     public function testWriteContentUsesFormatterIfProvided()
     {
-        $this->createHandler('myToken', 'channel1', 'Monolog', false);
+        $this->initHandlerAndSocket('myToken', 'channel1', 'Monolog', false);
         $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
-        fseek($this->res, 0);
-        $content = fread($this->res, 1024);
+        $content = $this->closeSocket();
 
-        $this->createHandler('myToken', 'channel1', 'Monolog', false);
+        $this->initHandlerAndSocket('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);
+        $content2 = $this->closeSocket();
 
         $this->assertRegexp('/token=myToken&channel=channel1&username=Monolog&text=test1.*$/', $content);
         $this->assertRegexp('/token=myToken&channel=channel1&username=Monolog&text=foo--test2.*$/', $content2);
@@ -77,11 +73,10 @@ class SlackHandlerTest extends TestCase
 
     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'));
-        fseek($this->res, 0);
-        $content = fread($this->res, 1024);
 
+        $content = $this->closeSocket();
         $this->assertRegexp('/icon_emoji=%3Aalien%3A$/', $content);
     }
 
@@ -90,21 +85,19 @@ class SlackHandlerTest extends TestCase
      */
     public function testWriteContentWithColors($level, $expectedColor)
     {
-        $this->createHandler();
+        $this->initHandlerAndSocket();
         $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);
     }
 
     public function testWriteContentWithPlainTextMessage()
     {
-        $this->createHandler('myToken', 'channel1', 'Monolog', false);
+        $this->initHandlerAndSocket('myToken', 'channel1', 'Monolog', false);
         $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);
     }
 
@@ -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];
-        $this->res = fopen('php://memory', 'a');
-        $this->handler = $this->getMock(
-            '\Monolog\Handler\SlackHandler',
-            ['fsockopen', 'streamSetTimeout', 'closeSocket'],
-            $constructorArgs
-        );
+        $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 SlackHandler($token, $channel, $username, $useAttachment, $iconEmoji, Logger::DEBUG, true, $useShortAttachment, $includeExtra);
 
         $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));
+        $reflectionProperty->setValue($this->handler, '127.0.0.1:51984');
 
         $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);
+        }
+    }
 }

+ 69 - 145
tests/Monolog/Handler/SocketHandlerTest.php

@@ -88,10 +88,8 @@ class SocketHandlerTest extends TestCase
      */
     public function testExceptionIsThrownOnFsockopenError()
     {
-        $this->setMockHandler(['fsockopen']);
-        $this->handler->expects($this->once())
-            ->method('fsockopen')
-            ->will($this->returnValue(false));
+        $this->createHandler('tcp://127.0.0.1:51985');
+
         $this->writeRecord('Hello world');
     }
 
@@ -100,23 +98,9 @@ class SocketHandlerTest extends TestCase
      */
     public function testExceptionIsThrownOnPfsockopenError()
     {
-        $this->setMockHandler(['pfsockopen']);
-        $this->handler->expects($this->once())
-            ->method('pfsockopen')
-            ->will($this->returnValue(false));
+        $this->createHandler('tcp://127.0.0.1:51985');
         $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');
     }
 
@@ -125,46 +109,12 @@ class SocketHandlerTest extends TestCase
      */
     public function testWriteFailsOnIfFwriteReturnsFalse()
     {
-        $this->setMockHandler(['fwrite']);
-
-        $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->initHandlerAndSocket();
         $this->writeRecord('Hello world');
-    }
-
-    /**
-     * @expectedException RuntimeException
-     */
-    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]));
+        $reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'resource');
+        $reflectionProperty->setAccessible(true);
+        fclose($reflectionProperty->getValue($this->handler));
 
         $this->writeRecord('Hello world');
     }
@@ -174,92 +124,54 @@ class SocketHandlerTest extends TestCase
      */
     public function testWriteFailsOnIncompleteWrite()
     {
-        $this->setMockHandler(['fwrite', 'streamGetMetadata']);
-
-        $res = $this->res;
-        $callback = function ($string) use ($res) {
-            fclose($res);
-
-            return strlen('Hello');
-        };
+        $this->initHandlerAndSocket();
 
-        $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' => false]));
+        $this->handler->setWritingTimeout(1);
 
-        $this->writeRecord('Hello world');
+        // 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->writeRecord(str_repeat("bbbbbbbbbb\n", 700));
+        $this->assertTrue(true); // asserting to make sure we reach this point
+        $this->writeRecord(str_repeat("cccccccccc\n", 700));
+        $this->fail('The test should not reach here');
     }
 
     public function testWriteWithMemoryFile()
     {
-        $this->setMockHandler();
+        $this->initHandlerAndSocket();
         $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(['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');
+        $this->closeSocket();
+        $this->assertEquals('test1test2test3', $this->socket->getOutput());
     }
 
     public function testClose()
     {
-        $this->setMockHandler();
+        $this->initHandlerAndSocket();
         $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->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()
     {
-        $this->setMockHandler();
+        $this->initHandlerAndSocket();
         $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(['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);
+        $reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'resource');
+        $reflectionProperty->setAccessible(true);
 
-        $this->writeRecord('Hello world');
+        $this->assertTrue(is_resource($reflectionProperty->getValue($this->handler)));
+        $this->handler->close();
+        $this->assertTrue(is_resource($reflectionProperty->getValue($this->handler)));
     }
 
     private function createHandler($connectionString)
@@ -273,37 +185,49 @@ class SocketHandlerTest extends TestCase
         $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'];
-        $newMethods = array_diff($methods, $defaultMethods);
-
-        $finalMethods = array_merge($defaultMethods, $newMethods);
+$sock = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp'));
+socket_bind($sock, '127.0.0.1', 51984);
+socket_listen($sock);
+$res = socket_accept($sock);
+socket_set_option($res, SOL_SOCKET, SO_RCVTIMEO, array("sec" => 0, "usec" => 500));
+$bytesRead = 0;
+while ($read = socket_read($res, 1024)) {
+    echo $read;
+    $bytesRead += strlen($read);
+    if ($bytesRead > 10000) {
+        socket_close($res);
+        socket_close($sock);
+        die('CLOSED');
+    }
+}
+echo 'EXIT';
+socket_close($res);
+SCRIPT
+);
 
-        $this->handler = $this->getMock(
-            '\Monolog\Handler\SocketHandler', $finalMethods, ['localhost:1234']
-        );
+        $this->socket = new \Symfony\Component\Process\Process(escapeshellarg(PHP_BINARY).' '.escapeshellarg($tmpFile));
+        $this->socket->start();
 
-        if (!in_array('fsockopen', $methods)) {
-            $this->handler->expects($this->any())
-                ->method('fsockopen')
-                ->will($this->returnValue($this->res));
-        }
+        $this->handler = new SocketHandler('tcp://127.0.0.1:51984');
+        $this->handler->setFormatter($this->getIdentityFormatter());
+    }
 
-        if (!in_array('pfsockopen', $methods)) {
-            $this->handler->expects($this->any())
-                ->method('pfsockopen')
-                ->will($this->returnValue($this->res));
-        }
+    private function closeSocket()
+    {
+        $this->socket->stop();
+    }
 
-        if (!in_array('streamSetTimeout', $methods)) {
-            $this->handler->expects($this->any())
-                ->method('streamSetTimeout')
-                ->will($this->returnValue(true));
+    public function tearDown()
+    {
+        if (isset($this->socket)) {
+            $this->closeSocket();
+            unset($this->socket);
         }
-
-        $this->handler->setFormatter($this->getIdentityFormatter());
     }
 }

+ 1 - 1
tests/Monolog/Handler/SyslogUdpHandlerTest.php

@@ -29,7 +29,7 @@ class SyslogUdpHandlerTest extends \PHPUnit_Framework_TestCase
         $handler = new SyslogUdpHandler("127.0.0.1", 514, "authpriv");
         $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))
             ->method('write')
             ->with("lol", "<".(LOG_AUTHPRIV + LOG_WARNING).">1 ");

+ 54 - 12
tests/Monolog/Handler/UdpSocketTest.php

@@ -21,28 +21,28 @@ class UdpSocketTest extends TestCase
 {
     public function testWeDoNotTruncateShortMessages()
     {
-        $socket = $this->getMock('\Monolog\Handler\SyslogUdp\UdpSocket', ['send'], ['lol', 'lol']);
-
-        $socket->expects($this->at(0))
-            ->method('send')
-            ->with("HEADER: The quick brown fox jumps over the lazy dog");
+        $this->initSocket();
 
+        $socket = new UdpSocket('127.0.0.1', 51984);
         $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()
     {
-        $socket = $this->getMock('\Monolog\Handler\SyslogUdp\UdpSocket', ['send'], ['lol', 'lol']);
-
-        $truncatedString = str_repeat("derp", 16254).'d';
+        $this->initSocket();
 
-        $socket->expects($this->exactly(1))
-            ->method('send')
-            ->with("HEADER" . $truncatedString);
+        $socket = new UdpSocket('127.0.0.1', 51984);
 
         $longString = str_repeat("derp", 20000);
-
         $socket->write($longString, "HEADER");
+
+        $truncatedString = str_repeat("derp", 16254).'d';
+
+        $this->closeSocket();
+        $this->assertEquals('HEADER'.$truncatedString, $this->socket->getOutput());
     }
 
     public function testDoubleCloseDoesNotError()
@@ -61,4 +61,46 @@ class UdpSocketTest extends TestCase
         $socket->close();
         $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);
+        }
+    }
+
 }

+ 24 - 22
tests/Monolog/LoggerTest.php

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