diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 5cb0839c..9ed491d8 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -4,71 +4,242 @@ on: - push - pull_request -env: - COMPOSER_FLAGS: "--ansi --no-interaction --no-progress --prefer-dist" - jobs: tests: name: "CI" - runs-on: ubuntu-latest + runs-on: "${{ matrix.operating-system }}" strategy: + fail-fast: false + matrix: php-version: - "7.2" - "7.3" - "7.4" - "8.0" - # disabled for now as phpspec/prophecy does not allow 8.1 - # - "8.1" + - "8.1" + dependencies: [highest] + + operating-system: + - "ubuntu-latest" + include: - php-version: "7.2" dependencies: lowest - - php-version: "8.0" + operating-system: ubuntu-latest + - php-version: "8.1" dependencies: lowest + operating-system: ubuntu-latest steps: - name: "Checkout" uses: "actions/checkout@v2" + - name: Run CouchDB + timeout-minutes: 1 + continue-on-error: true + uses: "cobot/couchdb-action@master" + with: + couchdb version: '2.3.1' + + - name: Run MongoDB + uses: supercharge/mongodb-github-action@1.7.0 + with: + mongodb-version: 5.0 + - name: "Install PHP" uses: "shivammathur/setup-php@v2" with: coverage: "none" php-version: "${{ matrix.php-version }}" extensions: mongodb, redis, amqp - - - name: Get composer cache directory - id: composercache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - - name: Cache dependencies - uses: actions/cache@v2 - with: - path: ${{ steps.composercache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: ${{ runner.os }}-composer- + tools: "composer:v2" + ini-values: "memory_limit=-1" - name: Add require for mongodb/mongodb to make tests runnable - run: 'composer require ${{ env.COMPOSER_FLAGS }} mongodb/mongodb --dev --no-update' + run: 'composer require mongodb/mongodb --dev --no-update' - - name: "Handle lowest dependencies update" - if: "contains(matrix.dependencies, 'lowest')" - run: "echo \"COMPOSER_FLAGS=$COMPOSER_FLAGS --prefer-lowest\" >> $GITHUB_ENV" - - - name: "Install latest dependencies" + - name: "Change dependencies" run: | - composer update ${{ env.COMPOSER_FLAGS }} + composer require --no-update --no-interaction --dev elasticsearch/elasticsearch:^7 + composer config --no-plugins allow-plugins.ocramius/package-versions true + + - name: "Update dependencies with composer" + uses: "ramsey/composer-install@v1" + with: + dependency-versions: "${{ matrix.dependencies }}" - name: "Run tests" - run: "composer exec phpunit -- --verbose" + run: "composer exec phpunit -- --exclude-group Elasticsearch,Elastica --verbose" - name: "Run tests with psr/log 3" if: "contains(matrix.dependencies, 'highest') && matrix.php-version >= '8.0'" run: | composer remove --no-update --dev graylog2/gelf-php ruflin/elastica elasticsearch/elasticsearch rollbar/rollbar composer require --no-update psr/log:^3 - composer update -W ${{ env.COMPOSER_FLAGS }} - composer exec phpunit -- --verbose + composer update -W + composer exec phpunit -- --exclude-group Elasticsearch,Elastica --verbose + + tests-es-7: + name: "CI with ES ${{ matrix.es-version }} on PHP ${{ matrix.php-version }}" + + needs: "tests" + + runs-on: "${{ matrix.operating-system }}" + + strategy: + fail-fast: false + + matrix: + operating-system: + - "ubuntu-latest" + + php-version: + - "7.2" + - "7.3" + - "7.4" + - "8.0" + - "8.1" + + dependencies: + - "highest" + - "lowest" + + es-version: + - "7.0.0" + - "7.17.0" + + exclude: + # php 7.3 is required + - php-version: "7.2" + es-version: "7.17.0" + # tests failing due an error in deprecated guzzlehttp/ringphp + - php-version: "7.3" + es-version: "7.0.0" + - php-version: "7.4" + es-version: "7.0.0" + + steps: + - name: "Checkout" + uses: "actions/checkout@v2" + + # required for elasticsearch + - name: Configure sysctl limits + run: | + sudo swapoff -a + sudo sysctl -w vm.swappiness=1 + sudo sysctl -w fs.file-max=262144 + sudo sysctl -w vm.max_map_count=262144 + + - name: Run Elasticsearch + timeout-minutes: 1 + uses: elastic/elastic-github-actions/elasticsearch@master + with: + stack-version: "${{ matrix.es-version }}" + + - name: "Install PHP" + uses: "shivammathur/setup-php@v2" + with: + coverage: "none" + php-version: "${{ matrix.php-version }}" + extensions: mongodb, redis, amqp + tools: "composer:v2" + ini-values: "memory_limit=-1" + + - name: "Change dependencies" + run: "composer require --no-update --no-interaction --dev elasticsearch/elasticsearch:^${{ matrix.es-version }}" + + - name: "Update dependencies with composer" + uses: "ramsey/composer-install@v1" + with: + dependency-versions: "${{ matrix.dependencies }}" + + - name: "Run tests" + run: "composer exec phpunit -- --group Elasticsearch,Elastica --verbose" + + - name: "Run tests with psr/log 3" + if: "contains(matrix.dependencies, 'highest') && matrix.php-version >= '8.0'" + run: | + composer remove --no-update --dev graylog2/gelf-php ruflin/elastica elasticsearch/elasticsearch rollbar/rollbar + composer require --no-update --no-interaction --dev ruflin/elastica elasticsearch/elasticsearch:^7 + composer require --no-update psr/log:^3 + composer update -W + composer exec phpunit -- --group Elasticsearch,Elastica --verbose + + tests-es-8: + name: "CI with ES ${{ matrix.es-version }} on PHP ${{ matrix.php-version }}" + + needs: "tests" + + runs-on: "${{ matrix.operating-system }}" + + strategy: + fail-fast: false + + matrix: + operating-system: + - "ubuntu-latest" + + php-version: + # ES 8 requires PHP 7.4+ + - "7.4" + - "8.0" + - "8.1" + + dependencies: + - "highest" + - "lowest" + + es-version: + - "8.0.0" + - "8.2.0" + + steps: + - name: "Checkout" + uses: "actions/checkout@v2" + + # required for elasticsearch + - name: Configure sysctl limits + run: | + sudo swapoff -a + sudo sysctl -w vm.swappiness=1 + sudo sysctl -w fs.file-max=262144 + sudo sysctl -w vm.max_map_count=262144 + + - name: Run Elasticsearch + timeout-minutes: 1 + uses: elastic/elastic-github-actions/elasticsearch@master + with: + stack-version: "${{ matrix.es-version }}" + + - name: "Install PHP" + uses: "shivammathur/setup-php@v2" + with: + coverage: "none" + php-version: "${{ matrix.php-version }}" + extensions: mongodb, redis, amqp + tools: "composer:v2" + ini-values: "memory_limit=-1" + + - name: "Change dependencies" + run: | + composer remove --no-update --dev graylog2/gelf-php ruflin/elastica elasticsearch/elasticsearch rollbar/rollbar + composer require --no-update --no-interaction --dev elasticsearch/elasticsearch:^8 + + - name: "Update dependencies with composer" + uses: "ramsey/composer-install@v1" + with: + dependency-versions: "${{ matrix.dependencies }}" + + - name: "Run tests" + run: "composer exec phpunit -- --group Elasticsearch,Elastica --verbose" + + - name: "Run tests with psr/log 3" + if: "contains(matrix.dependencies, 'highest') && matrix.php-version >= '8.0'" + run: | + composer require --no-update psr/log:^3 + composer update -W + composer exec phpunit -- --group Elasticsearch,Elastica --verbose diff --git a/composer.json b/composer.json index 1c0a5c22..52cb35f6 100644 --- a/composer.json +++ b/composer.json @@ -17,19 +17,22 @@ "psr/log": "^1.0.1 || ^2.0 || ^3.0" }, "require-dev": { + "ext-json": "*", "aws/aws-sdk-php": "^2.4.9 || ^3.0", "doctrine/couchdb": "~1.0@dev", - "elasticsearch/elasticsearch": "^7", + "elasticsearch/elasticsearch": "^7 || ^8", "graylog2/gelf-php": "^1.4.2", + "guzzlehttp/guzzle": "^7.4", + "guzzlehttp/psr7": "^2.2", "mongodb/mongodb": "^1.8", "php-amqplib/php-amqplib": "~2.4 || ^3", "php-console/php-console": "^3.1.3", "phpspec/prophecy": "^1.15", "phpstan/phpstan": "^0.12.91", - "phpunit/phpunit": "^8.5", + "phpunit/phpunit": "^8.5.14", "predis/predis": "^1.1", "rollbar/rollbar": "^1.3 || ^2 || ^3", - "ruflin/elastica": ">=0.90@dev", + "ruflin/elastica": "^7", "swiftmailer/swiftmailer": "^5.3|^6.0", "symfony/mailer": "^5.4 || ^6", "symfony/mime": "^5.4 || ^6" @@ -72,6 +75,9 @@ "config": { "lock": false, "sort-packages": true, - "platform-check": false + "platform-check": false, + "allow-plugins": { + "composer/package-versions-deprecated": true + } } } diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 961f7ce4..4a368cd2 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -35,3 +35,6 @@ parameters: - '#::popProcessor\(\) should return callable#' - '#Parameter \#1 \$ of callable \(callable\(Monolog\\Handler\\Record\): Monolog\\Handler\\Record\)#' - '#is incompatible with native type array.#' + + # legacy elasticsearch namespace failures + - '# Elastic\\Elasticsearch\\#' diff --git a/src/Monolog/Handler/ElasticsearchHandler.php b/src/Monolog/Handler/ElasticsearchHandler.php index b9d323d8..e88375c0 100644 --- a/src/Monolog/Handler/ElasticsearchHandler.php +++ b/src/Monolog/Handler/ElasticsearchHandler.php @@ -11,6 +11,7 @@ namespace Monolog\Handler; +use Elastic\Elasticsearch\Response\Elasticsearch; use Throwable; use RuntimeException; use Monolog\Logger; @@ -19,6 +20,8 @@ use Monolog\Formatter\ElasticsearchFormatter; use InvalidArgumentException; use Elasticsearch\Common\Exceptions\RuntimeException as ElasticsearchRuntimeException; use Elasticsearch\Client; +use Elastic\Elasticsearch\Exception\InvalidArgumentException as ElasticInvalidArgumentException; +use Elastic\Elasticsearch\Client as Client8; /** * Elasticsearch handler @@ -44,7 +47,7 @@ use Elasticsearch\Client; class ElasticsearchHandler extends AbstractProcessingHandler { /** - * @var Client + * @var Client|Client8 */ protected $client; @@ -54,11 +57,20 @@ class ElasticsearchHandler extends AbstractProcessingHandler protected $options = []; /** - * @param Client $client Elasticsearch Client object - * @param mixed[] $options Handler configuration + * @var bool */ - public function __construct(Client $client, array $options = [], $level = Logger::DEBUG, bool $bubble = true) + private $needsType; + + /** + * @param Client|Client8 $client Elasticsearch Client object + * @param mixed[] $options Handler configuration + */ + public function __construct($client, array $options = [], $level = Logger::DEBUG, bool $bubble = true) { + if (!$client instanceof Client && !$client instanceof Client8) { + throw new \TypeError('Elasticsearch\Client or Elastic\Elasticsearch\Client instance required'); + } + parent::__construct($level, $bubble); $this->client = $client; $this->options = array_merge( @@ -69,6 +81,14 @@ class ElasticsearchHandler extends AbstractProcessingHandler ], $options ); + + if ($client instanceof Client8 || $client::VERSION[0] === '7') { + $this->needsType = false; + // force the type to _doc for ES8/ES7 + $this->options['type'] = '_doc'; + } else { + $this->needsType = true; + } } /** @@ -133,9 +153,11 @@ class ElasticsearchHandler extends AbstractProcessingHandler foreach ($records as $record) { $params['body'][] = [ - 'index' => [ + 'index' => $this->needsType ? [ '_index' => $record['_index'], '_type' => $record['_type'], + ] : [ + '_index' => $record['_index'], ], ]; unset($record['_index'], $record['_type']); @@ -143,6 +165,7 @@ class ElasticsearchHandler extends AbstractProcessingHandler $params['body'][] = $record; } + /** @var Elasticsearch */ $responses = $this->client->bulk($params); if ($responses['errors'] === true) { @@ -160,9 +183,9 @@ class ElasticsearchHandler extends AbstractProcessingHandler * * Only the first error is converted into an exception. * - * @param mixed[] $responses returned by $this->client->bulk() + * @param mixed[]|Elasticsearch $responses returned by $this->client->bulk() */ - protected function createExceptionFromResponses(array $responses): ElasticsearchRuntimeException + protected function createExceptionFromResponses($responses): Throwable { foreach ($responses['items'] ?? [] as $item) { if (isset($item['index']['error'])) { @@ -170,6 +193,10 @@ class ElasticsearchHandler extends AbstractProcessingHandler } } + if (class_exists(ElasticInvalidArgumentException::class)) { + return new ElasticInvalidArgumentException('Elasticsearch failed to index one or more records.'); + } + return new ElasticsearchRuntimeException('Elasticsearch failed to index one or more records.'); } @@ -178,10 +205,14 @@ class ElasticsearchHandler extends AbstractProcessingHandler * * @param mixed[] $error */ - protected function createExceptionFromError(array $error): ElasticsearchRuntimeException + protected function createExceptionFromError(array $error): Throwable { $previous = isset($error['caused_by']) ? $this->createExceptionFromError($error['caused_by']) : null; + if (class_exists(ElasticInvalidArgumentException::class)) { + return new ElasticInvalidArgumentException($error['type'] . ': ' . $error['reason'], 0, $previous); + } + return new ElasticsearchRuntimeException($error['type'] . ': ' . $error['reason'], 0, $previous); } } diff --git a/src/Monolog/Test/TestCase.php b/src/Monolog/Test/TestCase.php index 1824fde4..c4e42496 100644 --- a/src/Monolog/Test/TestCase.php +++ b/src/Monolog/Test/TestCase.php @@ -25,6 +25,15 @@ use Monolog\Formatter\FormatterInterface; */ class TestCase extends \PHPUnit\Framework\TestCase { + public function tearDown(): void + { + parent::tearDown(); + + if (isset($this->handler)) { + unset($this->handler); + } + } + /** * @param mixed[] $context * diff --git a/tests/Monolog/Formatter/ScalarFormatterTest.php b/tests/Monolog/Formatter/ScalarFormatterTest.php index c72227f7..596ed78f 100644 --- a/tests/Monolog/Formatter/ScalarFormatterTest.php +++ b/tests/Monolog/Formatter/ScalarFormatterTest.php @@ -22,6 +22,13 @@ class ScalarFormatterTest extends \PHPUnit\Framework\TestCase $this->formatter = new ScalarFormatter(); } + public function tearDown(): void + { + parent::tearDown(); + + unset($this->formatter); + } + public function buildTrace(\Exception $e) { $data = []; diff --git a/tests/Monolog/Handler/AmqpHandlerTest.php b/tests/Monolog/Handler/AmqpHandlerTest.php index c2de874c..62d41a5e 100644 --- a/tests/Monolog/Handler/AmqpHandlerTest.php +++ b/tests/Monolog/Handler/AmqpHandlerTest.php @@ -78,7 +78,7 @@ class AmqpHandlerTest extends TestCase public function testHandlePhpAmqpLib() { - if (!class_exists('PhpAmqpLib\Connection\AMQPConnection')) { + if (!class_exists('PhpAmqpLib\Channel\AMQPChannel')) { $this->markTestSkipped("php-amqplib not installed"); } diff --git a/tests/Monolog/Handler/DynamoDbHandlerTest.php b/tests/Monolog/Handler/DynamoDbHandlerTest.php index 2b237bfa..92c9c4c3 100644 --- a/tests/Monolog/Handler/DynamoDbHandlerTest.php +++ b/tests/Monolog/Handler/DynamoDbHandlerTest.php @@ -45,6 +45,13 @@ class DynamoDbHandlerTest extends TestCase $this->client = $clientMockBuilder->getMock(); } + public function tearDown(): void + { + parent::tearDown(); + + unset($this->client); + } + public function testConstruct() { $this->assertInstanceOf('Monolog\Handler\DynamoDbHandler', new DynamoDbHandler($this->client, 'foo')); diff --git a/tests/Monolog/Handler/ElasticaHandlerTest.php b/tests/Monolog/Handler/ElasticaHandlerTest.php index 7fb9808e..c03fefd0 100644 --- a/tests/Monolog/Handler/ElasticaHandlerTest.php +++ b/tests/Monolog/Handler/ElasticaHandlerTest.php @@ -19,6 +19,9 @@ use Elastica\Client; use Elastica\Request; use Elastica\Response; +/** + * @group Elastica + */ class ElasticaHandlerTest extends TestCase { /** @@ -48,6 +51,13 @@ class ElasticaHandlerTest extends TestCase ->getMock(); } + public function tearDown(): void + { + parent::tearDown(); + + unset($this->client); + } + /** * @covers Monolog\Handler\ElasticaHandler::write * @covers Monolog\Handler\ElasticaHandler::handleBatch @@ -155,60 +165,6 @@ class ElasticaHandlerTest extends TestCase ]; } - /** - * Integration test using localhost Elastic Search server version <7 - * - * @covers Monolog\Handler\ElasticaHandler::__construct - * @covers Monolog\Handler\ElasticaHandler::handleBatch - * @covers Monolog\Handler\ElasticaHandler::bulkSend - * @covers Monolog\Handler\ElasticaHandler::getDefaultFormatter - */ - public function testHandleIntegration() - { - $msg = [ - 'level' => Logger::ERROR, - 'level_name' => 'ERROR', - 'channel' => 'meh', - 'context' => ['foo' => 7, 'bar', 'class' => new \stdClass], - 'datetime' => new \DateTimeImmutable("@0"), - 'extra' => [], - 'message' => 'log', - ]; - - $expected = $msg; - $expected['datetime'] = $msg['datetime']->format(\DateTime::ISO8601); - $expected['context'] = [ - 'class' => '[object] (stdClass: {})', - 'foo' => 7, - 0 => 'bar', - ]; - - $client = new Client(); - $handler = new ElasticaHandler($client, $this->options); - - try { - $handler->handleBatch([$msg]); - } catch (\RuntimeException $e) { - $this->markTestSkipped("Cannot connect to Elastic Search server on localhost"); - } - - // check document id from ES server response - $documentId = $this->getCreatedDocId($client->getLastResponse()); - $this->assertNotEmpty($documentId, 'No elastic document id received'); - - // retrieve document source from ES and validate - $document = $this->getDocSourceFromElastic( - $client, - $this->options['index'], - $this->options['type'], - $documentId - ); - $this->assertEquals($expected, $document); - - // remove test index from ES - $client->request("/{$this->options['index']}", Request::DELETE); - } - /** * Integration test using localhost Elastic Search server version 7+ * @@ -237,7 +193,9 @@ class ElasticaHandlerTest extends TestCase 0 => 'bar', ]; - $client = new Client(); + $clientOpts = ['url' => 'http://elastic:changeme@127.0.0.1:9200']; + $client = new Client($clientOpts); + $handler = new ElasticaHandler($client, $this->options); try { @@ -271,9 +229,14 @@ class ElasticaHandlerTest extends TestCase protected function getCreatedDocId(Response $response) { $data = $response->getData(); - if (!empty($data['items'][0]['create']['_id'])) { - return $data['items'][0]['create']['_id']; + + if (!empty($data['items'][0]['index']['_id'])) { + return $data['items'][0]['index']['_id']; } + + var_dump('Unexpected response: ', $data); + + return null; } /** diff --git a/tests/Monolog/Handler/ElasticsearchHandlerTest.php b/tests/Monolog/Handler/ElasticsearchHandlerTest.php index 764c54c9..e84cdbd6 100644 --- a/tests/Monolog/Handler/ElasticsearchHandlerTest.php +++ b/tests/Monolog/Handler/ElasticsearchHandlerTest.php @@ -11,17 +11,22 @@ namespace Monolog\Handler; -use Elasticsearch\ClientBuilder; use Monolog\Formatter\ElasticsearchFormatter; use Monolog\Formatter\NormalizerFormatter; use Monolog\Test\TestCase; use Monolog\Logger; use Elasticsearch\Client; +use Elastic\Elasticsearch\Client as Client8; +use Elasticsearch\ClientBuilder; +use Elastic\Elasticsearch\ClientBuilder as ClientBuilder8; +/** + * @group Elasticsearch + */ class ElasticsearchHandlerTest extends TestCase { /** - * @var Client mock + * @var Client|Client8 mock */ protected $client; @@ -35,63 +40,23 @@ class ElasticsearchHandlerTest extends TestCase public function setUp(): void { - // Elasticsearch lib required - if (!class_exists('Elasticsearch\Client')) { - $this->markTestSkipped('elasticsearch/elasticsearch not installed'); - } + $hosts = ['http://elastic:changeme@127.0.0.1:9200']; + $this->client = $this->getClientBuilder() + ->setHosts($hosts) + ->build(); - // base mock Elasticsearch Client object - $this->client = $this->getMockBuilder('Elasticsearch\Client') - ->onlyMethods(['bulk']) - ->disableOriginalConstructor() - ->getMock(); + try { + $this->client->info(); + } catch (\Throwable $e) { + $this->markTestSkipped('Could not connect to Elasticsearch on 127.0.0.1:9200'); + } } - /** - * @covers Monolog\Handler\ElasticsearchHandler::write - * @covers Monolog\Handler\ElasticsearchHandler::handleBatch - * @covers Monolog\Handler\ElasticsearchHandler::bulkSend - * @covers Monolog\Handler\ElasticsearchHandler::getDefaultFormatter - */ - public function testHandle() + public function tearDown(): void { - // log message - $msg = [ - 'level' => Logger::ERROR, - 'level_name' => 'ERROR', - 'channel' => 'meh', - 'context' => ['foo' => 7, 'bar', 'class' => new \stdClass], - 'datetime' => new \DateTimeImmutable("@0"), - 'extra' => [], - 'message' => 'log', - ]; + parent::tearDown(); - // format expected result - $formatter = new ElasticsearchFormatter($this->options['index'], $this->options['type']); - $data = $formatter->format($msg); - unset($data['_index'], $data['_type']); - - $expected = [ - 'body' => [ - [ - 'index' => [ - '_index' => $this->options['index'], - '_type' => $this->options['type'], - ], - ], - $data, - ], - ]; - - // setup ES client mock - $this->client->expects($this->any()) - ->method('bulk') - ->with($expected); - - // perform tests - $handler = new ElasticsearchHandler($this->client, $this->options); - $handler->handle($msg); - $handler->handleBatch([$msg]); + unset($this->client); } /** @@ -108,7 +73,7 @@ class ElasticsearchHandlerTest extends TestCase } /** - * @covers Monolog\Handler\ElasticsearchHandler::setFormatter + * @covers Monolog\Handler\ElasticsearchHandler::setFormatter */ public function testSetFormatterInvalid() { @@ -132,6 +97,11 @@ class ElasticsearchHandlerTest extends TestCase 'type' => $this->options['type'], 'ignore_error' => false, ]; + + if ($this->client instanceof Client8 || $this->client::VERSION[0] === '7') { + $expected['type'] = '_doc'; + } + $handler = new ElasticsearchHandler($this->client, $this->options); $this->assertEquals($expected, $handler->getOptions()); } @@ -142,10 +112,10 @@ class ElasticsearchHandlerTest extends TestCase */ public function testConnectionErrors($ignore, $expectedError) { - $hosts = [['host' => '127.0.0.1', 'port' => 1]]; - $client = ClientBuilder::create() - ->setHosts($hosts) - ->build(); + $hosts = ['http://127.0.0.1:1']; + $client = $this->getClientBuilder() + ->setHosts($hosts) + ->build(); $handlerOpts = ['ignore_error' => $ignore]; $handler = new ElasticsearchHandler($client, $handlerOpts); @@ -178,7 +148,7 @@ class ElasticsearchHandlerTest extends TestCase * @covers Monolog\Handler\ElasticsearchHandler::bulkSend * @covers Monolog\Handler\ElasticsearchHandler::getDefaultFormatter */ - public function testHandleIntegration() + public function testHandleBatchIntegration() { $msg = [ 'level' => Logger::ERROR, @@ -198,21 +168,26 @@ class ElasticsearchHandlerTest extends TestCase 0 => 'bar', ]; - $hosts = [['host' => '127.0.0.1', 'port' => 9200]]; - $client = ClientBuilder::create() + $hosts = ['http://elastic:changeme@127.0.0.1:9200']; + $client = $this->getClientBuilder() ->setHosts($hosts) ->build(); $handler = new ElasticsearchHandler($client, $this->options); - - try { - $handler->handleBatch([$msg]); - } catch (\RuntimeException $e) { - $this->markTestSkipped('Cannot connect to Elasticsearch server on localhost'); - } + $handler->handleBatch([$msg]); // check document id from ES server response - $documentId = $this->getCreatedDocId($client->transport->getLastConnection()->getLastRequestInfo()); - $this->assertNotEmpty($documentId, 'No elastic document id received'); + if ($client instanceof Client8) { + $messageBody = $client->getTransport()->getLastResponse()->getBody(); + + $info = json_decode((string) $messageBody, true); + $this->assertNotNull($info, 'Decoding failed'); + + $documentId = $this->getCreatedDocIdV8($info); + $this->assertNotEmpty($documentId, 'No elastic document id received'); + } else { + $documentId = $this->getCreatedDocId($client->transport->getLastConnection()->getLastRequestInfo()); + $this->assertNotEmpty($documentId, 'No elastic document id received'); + } // retrieve document source from ES and validate $document = $this->getDocSourceFromElastic( @@ -241,25 +216,45 @@ class ElasticsearchHandlerTest extends TestCase if (!empty($data['items'][0]['index']['_id'])) { return $data['items'][0]['index']['_id']; } + + return null; + } + + /** + * Return last created document id from ES response + * + * @param array $data Elasticsearch last request info + * @return string|null + */ + protected function getCreatedDocIdV8(array $data) + { + if (!empty($data['items'][0]['index']['_id'])) { + return $data['items'][0]['index']['_id']; + } + + return null; } /** * Retrieve document by id from Elasticsearch * - * @param Client $client Elasticsearch client + * @param Client|Client8 $client Elasticsearch client * @param string $index * @param string $type * @param string $documentId * @return array */ - protected function getDocSourceFromElastic(Client $client, $index, $type, $documentId) + protected function getDocSourceFromElastic($client, $index, $type, $documentId) { $params = [ 'index' => $index, - 'type' => $type, 'id' => $documentId, ]; + if (!$client instanceof Client8 && $client::VERSION[0] !== '7') { + $params['type'] = $type; + } + $data = $client->get($params); if (!empty($data['_source'])) { @@ -268,4 +263,16 @@ class ElasticsearchHandlerTest extends TestCase return []; } + + /** + * @return ClientBuilder|ClientBuilder8 + */ + private function getClientBuilder() + { + if (class_exists(ClientBuilder8::class)) { + return ClientBuilder8::create(); + } + + return ClientBuilder::create(); + } } diff --git a/tests/Monolog/Handler/FlowdockHandlerTest.php b/tests/Monolog/Handler/FlowdockHandlerTest.php index 04bf063d..45c8799c 100644 --- a/tests/Monolog/Handler/FlowdockHandlerTest.php +++ b/tests/Monolog/Handler/FlowdockHandlerTest.php @@ -38,6 +38,13 @@ class FlowdockHandlerTest extends TestCase } } + public function tearDown(): void + { + parent::tearDown(); + + unset($this->res); + } + public function testWriteHeader() { $this->createHandler(); diff --git a/tests/Monolog/Handler/HandlerWrapperTest.php b/tests/Monolog/Handler/HandlerWrapperTest.php index 87a117b1..67cc2a32 100644 --- a/tests/Monolog/Handler/HandlerWrapperTest.php +++ b/tests/Monolog/Handler/HandlerWrapperTest.php @@ -32,6 +32,13 @@ class HandlerWrapperTest extends TestCase $this->wrapper = new HandlerWrapper($this->handler); } + public function tearDown(): void + { + parent::tearDown(); + + unset($this->wrapper); + } + /** * @return array */ diff --git a/tests/Monolog/Handler/InsightOpsHandlerTest.php b/tests/Monolog/Handler/InsightOpsHandlerTest.php index 9c98d379..808084e8 100644 --- a/tests/Monolog/Handler/InsightOpsHandlerTest.php +++ b/tests/Monolog/Handler/InsightOpsHandlerTest.php @@ -30,6 +30,13 @@ class InsightOpsHandlerTest extends TestCase */ private $handler; + public function tearDown(): void + { + parent::tearDown(); + + unset($this->resource); + } + public function testWriteContent() { $this->createHandler(); diff --git a/tests/Monolog/Handler/LogEntriesHandlerTest.php b/tests/Monolog/Handler/LogEntriesHandlerTest.php index 034d6ab8..3d7273c8 100644 --- a/tests/Monolog/Handler/LogEntriesHandlerTest.php +++ b/tests/Monolog/Handler/LogEntriesHandlerTest.php @@ -29,6 +29,13 @@ class LogEntriesHandlerTest extends TestCase */ private $handler; + public function tearDown(): void + { + parent::tearDown(); + + unset($this->res); + } + public function testWriteContent() { $this->createHandler(); diff --git a/tests/Monolog/Handler/LogmaticHandlerTest.php b/tests/Monolog/Handler/LogmaticHandlerTest.php index c30a1794..1cb4254e 100644 --- a/tests/Monolog/Handler/LogmaticHandlerTest.php +++ b/tests/Monolog/Handler/LogmaticHandlerTest.php @@ -29,6 +29,13 @@ class LogmaticHandlerTest extends TestCase */ private $handler; + public function tearDown(): void + { + parent::tearDown(); + + unset($this->res); + } + public function testWriteContent() { $this->createHandler(); diff --git a/tests/Monolog/Handler/PHPConsoleHandlerTest.php b/tests/Monolog/Handler/PHPConsoleHandlerTest.php index 98d8a4b2..f1ffcf96 100644 --- a/tests/Monolog/Handler/PHPConsoleHandlerTest.php +++ b/tests/Monolog/Handler/PHPConsoleHandlerTest.php @@ -56,6 +56,13 @@ class PHPConsoleHandlerTest extends TestCase $this->connector->setErrorsDispatcher($this->errorDispatcher); } + public function tearDown(): void + { + parent::tearDown(); + + unset($this->connector, $this->debugDispatcher, $this->errorDispatcher); + } + protected function initDebugDispatcherMock(Connector $connector) { return $this->getMockBuilder('PhpConsole\Dispatcher\Debug') diff --git a/tests/Monolog/Handler/PushoverHandlerTest.php b/tests/Monolog/Handler/PushoverHandlerTest.php index 2c77d30c..8596e356 100644 --- a/tests/Monolog/Handler/PushoverHandlerTest.php +++ b/tests/Monolog/Handler/PushoverHandlerTest.php @@ -25,6 +25,13 @@ class PushoverHandlerTest extends TestCase private $res; private $handler; + public function tearDown(): void + { + parent::tearDown(); + + unset($this->res); + } + public function testWriteHeader() { $this->createHandler(); diff --git a/tests/Monolog/Handler/RollbarHandlerTest.php b/tests/Monolog/Handler/RollbarHandlerTest.php index 0aa7cbff..60e08d6d 100644 --- a/tests/Monolog/Handler/RollbarHandlerTest.php +++ b/tests/Monolog/Handler/RollbarHandlerTest.php @@ -44,6 +44,13 @@ class RollbarHandlerTest extends TestCase $this->setupRollbarLoggerMock(); } + public function tearDown(): void + { + parent::tearDown(); + + unset($this->rollbarLogger, $this->reportedExceptionArguments); + } + /** * When reporting exceptions to Rollbar the * level has to be set in the payload data diff --git a/tests/Monolog/Handler/RotatingFileHandlerTest.php b/tests/Monolog/Handler/RotatingFileHandlerTest.php index 5446f40e..dd77c853 100644 --- a/tests/Monolog/Handler/RotatingFileHandlerTest.php +++ b/tests/Monolog/Handler/RotatingFileHandlerTest.php @@ -39,6 +39,18 @@ class RotatingFileHandlerTest extends TestCase }); } + public function tearDown(): void + { + parent::tearDown(); + + foreach (glob(__DIR__.'/Fixtures/*.rot') as $file) { + unlink($file); + } + restore_error_handler(); + + unset($this->lastError); + } + private function assertErrorWasTriggered($code, $message) { if (empty($this->lastError)) { @@ -239,12 +251,4 @@ class RotatingFileHandlerTest extends TestCase $handler->handle($this->getRecord()); $this->assertEquals('footest', file_get_contents($log)); } - - public function tearDown(): void - { - foreach (glob(__DIR__.'/Fixtures/*.rot') as $file) { - unlink($file); - } - restore_error_handler(); - } } diff --git a/tests/Monolog/Handler/SlackHandlerTest.php b/tests/Monolog/Handler/SlackHandlerTest.php index c6e30a75..4e4d8220 100644 --- a/tests/Monolog/Handler/SlackHandlerTest.php +++ b/tests/Monolog/Handler/SlackHandlerTest.php @@ -39,6 +39,13 @@ class SlackHandlerTest extends TestCase } } + public function tearDown(): void + { + parent::tearDown(); + + unset($this->res); + } + public function testWriteHeader() { $this->createHandler(); diff --git a/tests/Monolog/Handler/SocketHandlerTest.php b/tests/Monolog/Handler/SocketHandlerTest.php index 272dd704..ba5a1bad 100644 --- a/tests/Monolog/Handler/SocketHandlerTest.php +++ b/tests/Monolog/Handler/SocketHandlerTest.php @@ -30,6 +30,13 @@ class SocketHandlerTest extends TestCase */ private $res; + public function tearDown(): void + { + parent::tearDown(); + + unset($this->res); + } + public function testInvalidHostname() { $this->expectException(\UnexpectedValueException::class); diff --git a/tests/Monolog/Handler/StreamHandlerTest.php b/tests/Monolog/Handler/StreamHandlerTest.php index 43a520bc..8c69cc58 100644 --- a/tests/Monolog/Handler/StreamHandlerTest.php +++ b/tests/Monolog/Handler/StreamHandlerTest.php @@ -271,20 +271,20 @@ STRING; $this->markTestSkipped('We could not set a memory limit that would trigger the error.'); } - $stream = tmpfile(); + try { + $stream = tmpfile(); - if ($stream === false) { - $this->markTestSkipped('We could not create a temp file to be use as a stream.'); + if ($stream === false) { + $this->markTestSkipped('We could not create a temp file to be use as a stream.'); + } + + $handler = new StreamHandler($stream); + stream_get_contents($stream, 1024); + + $this->assertEquals($expectedChunkSize, $handler->getStreamChunkSize()); + } finally { + ini_set('memory_limit', $previousValue); } - - $exceptionRaised = false; - - $handler = new StreamHandler($stream); - stream_get_contents($stream, 1024); - - ini_set('memory_limit', $previousValue); - - $this->assertEquals($expectedChunkSize, $handler->getStreamChunkSize()); } /** @@ -298,10 +298,13 @@ STRING; $this->markTestSkipped('We could not set a memory limit that would trigger the error.'); } - $stream = tmpfile(); - new StreamHandler($stream); - stream_get_contents($stream); - ini_set('memory_limit', $previousValue); - $this->assertTrue(true); + try { + $stream = tmpfile(); + new StreamHandler($stream); + stream_get_contents($stream); + $this->assertTrue(true); + } finally { + ini_set('memory_limit', $previousValue); + } } } diff --git a/tests/Monolog/Handler/SwiftMailerHandlerTest.php b/tests/Monolog/Handler/SwiftMailerHandlerTest.php index 51596c39..9dd65e61 100644 --- a/tests/Monolog/Handler/SwiftMailerHandlerTest.php +++ b/tests/Monolog/Handler/SwiftMailerHandlerTest.php @@ -28,6 +28,13 @@ class SwiftMailerHandlerTest extends TestCase ->getMock(); } + public function tearDown(): void + { + parent::tearDown(); + + unset($this->mailer); + } + public function testMessageCreationIsLazyWhenUsingCallback() { $this->mailer->expects($this->never()) diff --git a/tests/Monolog/Handler/SymfonyMailerHandlerTest.php b/tests/Monolog/Handler/SymfonyMailerHandlerTest.php index af1e926a..ea4b9e26 100644 --- a/tests/Monolog/Handler/SymfonyMailerHandlerTest.php +++ b/tests/Monolog/Handler/SymfonyMailerHandlerTest.php @@ -30,6 +30,13 @@ class SymfonyMailerHandlerTest extends TestCase ->getMock(); } + public function tearDown(): void + { + parent::tearDown(); + + unset($this->mailer); + } + public function testMessageCreationIsLazyWhenUsingCallback() { $this->mailer->expects($this->never()) diff --git a/tests/Monolog/Handler/ZendMonitorHandlerTest.php b/tests/Monolog/Handler/ZendMonitorHandlerTest.php index e8fe55c5..e01c0db6 100644 --- a/tests/Monolog/Handler/ZendMonitorHandlerTest.php +++ b/tests/Monolog/Handler/ZendMonitorHandlerTest.php @@ -25,6 +25,13 @@ class ZendMonitorHandlerTest extends TestCase } } + public function tearDown(): void + { + parent::tearDown(); + + unset($this->zendMonitorHandler); + } + /** * @covers Monolog\Handler\ZendMonitorHandler::write */ diff --git a/tests/Monolog/PsrLogCompatTest.php b/tests/Monolog/PsrLogCompatTest.php index eaeb3552..e22f6054 100644 --- a/tests/Monolog/PsrLogCompatTest.php +++ b/tests/Monolog/PsrLogCompatTest.php @@ -25,6 +25,13 @@ class PsrLogCompatTest extends TestCase { private $handler; + public function tearDown(): void + { + parent::tearDown(); + + unset($this->handler); + } + public function getLogger(): LoggerInterface { $logger = new Logger('foo'); diff --git a/tests/Monolog/SignalHandlerTest.php b/tests/Monolog/SignalHandlerTest.php index e73ad8fd..8c28fc14 100644 --- a/tests/Monolog/SignalHandlerTest.php +++ b/tests/Monolog/SignalHandlerTest.php @@ -39,8 +39,10 @@ class SignalHandlerTest extends TestCase } } - protected function tearDown(): void + public function tearDown(): void { + parent::tearDown(); + if ($this->asyncSignalHandling !== null) { pcntl_async_signals($this->asyncSignalHandling); } @@ -53,6 +55,8 @@ class SignalHandlerTest extends TestCase pcntl_signal($signo, $handler); } } + + unset($this->signalHandlers, $this->blockedSignals, $this->asyncSignalHandling); } private function setSignalHandler($signo, $handler = SIG_DFL)