From 20d44001771150ba8ca0236ba9a1c6dcdb3a03e4 Mon Sep 17 00:00:00 2001 From: Pavel Bisse Date: Thu, 13 Feb 2020 11:02:58 +0100 Subject: [PATCH 01/23] append some inspection fixes --- src/Collections/AbstractMetricCollection.php | 6 +++--- src/Collections/GaugeCollection.php | 4 ++-- src/Collections/LabelCollection.php | 4 ++-- src/Exceptions/LogicException.php | 8 -------- src/HttpResponse/OutputStream.php | 13 ++++--------- tests/Unit/Collections/CounterCollectionTest.php | 2 +- tests/Unit/Collections/GaugeCollectionTest.php | 2 +- 7 files changed, 13 insertions(+), 26 deletions(-) delete mode 100644 src/Exceptions/LogicException.php diff --git a/src/Collections/AbstractMetricCollection.php b/src/Collections/AbstractMetricCollection.php index 5f226b3..f9a6f12 100644 --- a/src/Collections/AbstractMetricCollection.php +++ b/src/Collections/AbstractMetricCollection.php @@ -28,8 +28,8 @@ final protected function __construct( NamesMetric $metricName, string $metricTyp * * @return static */ - public function withHelp( string $helpText ) - { + public function withHelp( string $helpText ) : AbstractMetricCollection + { $this->setHelp( $helpText ); return $this; @@ -59,4 +59,4 @@ final protected function getHelpString() : string return sprintf( '# HELP %s %s', $this->metricName->toString(), $this->help ); } -} \ No newline at end of file +} diff --git a/src/Collections/GaugeCollection.php b/src/Collections/GaugeCollection.php index dfb281d..c3e4408 100644 --- a/src/Collections/GaugeCollection.php +++ b/src/Collections/GaugeCollection.php @@ -110,7 +110,7 @@ private function sortMeasuredValues() : void usort( $this->gauges, - function ( Gauge $a, Gauge $b ) + static function (Gauge $a, Gauge $b ) { return $a->getMeasuredValue() <=> $b->getMeasuredValue(); } @@ -129,4 +129,4 @@ public function sumMeasuredValues() : float return $sum; } -} \ No newline at end of file +} diff --git a/src/Collections/LabelCollection.php b/src/Collections/LabelCollection.php index 2790f55..a872eee 100644 --- a/src/Collections/LabelCollection.php +++ b/src/Collections/LabelCollection.php @@ -80,7 +80,7 @@ public function getCombinedLabelString() : string } $labelStrings = array_map( - function ( ProvidesNamedValue $label ) + static function (ProvidesNamedValue $label ) { return $label->getLabelString(); }, @@ -89,4 +89,4 @@ function ( ProvidesNamedValue $label ) return '{' . implode( ', ', $labelStrings ) . '}'; } -} \ No newline at end of file +} diff --git a/src/Exceptions/LogicException.php b/src/Exceptions/LogicException.php deleted file mode 100644 index b8f6366..0000000 --- a/src/Exceptions/LogicException.php +++ /dev/null @@ -1,8 +0,0 @@ -resource ); - if ( !array_key_exists( $key, $metadata ) ) - { - return null; - } - - return $metadata[ $key ]; - } -} \ No newline at end of file + return $metadata[$key] ?? null; + } +} diff --git a/tests/Unit/Collections/CounterCollectionTest.php b/tests/Unit/Collections/CounterCollectionTest.php index 9a0023d..55d5c33 100644 --- a/tests/Unit/Collections/CounterCollectionTest.php +++ b/tests/Unit/Collections/CounterCollectionTest.php @@ -1,6 +1,6 @@ Date: Thu, 13 Feb 2020 11:17:34 +0100 Subject: [PATCH 02/23] append code style --- src/Collections/GaugeCollection.php | 2 +- src/Collections/LabelCollection.php | 2 +- src/HttpResponse/OutputStream.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Collections/GaugeCollection.php b/src/Collections/GaugeCollection.php index c3e4408..bae1b0c 100644 --- a/src/Collections/GaugeCollection.php +++ b/src/Collections/GaugeCollection.php @@ -110,7 +110,7 @@ private function sortMeasuredValues() : void usort( $this->gauges, - static function (Gauge $a, Gauge $b ) + static function ( Gauge $a, Gauge $b ) { return $a->getMeasuredValue() <=> $b->getMeasuredValue(); } diff --git a/src/Collections/LabelCollection.php b/src/Collections/LabelCollection.php index a872eee..8d6c5ff 100644 --- a/src/Collections/LabelCollection.php +++ b/src/Collections/LabelCollection.php @@ -80,7 +80,7 @@ public function getCombinedLabelString() : string } $labelStrings = array_map( - static function (ProvidesNamedValue $label ) + static function ( ProvidesNamedValue $label ) { return $label->getLabelString(); }, diff --git a/src/HttpResponse/OutputStream.php b/src/HttpResponse/OutputStream.php index e3ee730..82caa44 100644 --- a/src/HttpResponse/OutputStream.php +++ b/src/HttpResponse/OutputStream.php @@ -327,6 +327,6 @@ public function getMetadata( $key = null ) $metadata = stream_get_meta_data( $this->resource ); - return $metadata[$key] ?? null; + return $metadata[ $key ] ?? null; } } From d71276165dd2e586b251168899beb1c9910202de Mon Sep 17 00:00:00 2001 From: Nic Date: Mon, 29 Jan 2024 12:17:57 +0200 Subject: [PATCH 03/23] Update signatures for compatibility with php8. Update composer.json php dependency. Add php 8 Dockerfile. Add compatibility for tests. --- .docker/php/8.0/Dockerfile | 15 +++++++++++++++ composer.json | 2 +- docker-compose.yml | 16 ++++++++++++++-- src/Collections/CounterCollection.php | 4 ++-- src/Collections/GaugeCollection.php | 4 ++-- src/Collections/LabelCollection.php | 3 ++- src/HttpResponse.php | 4 ++-- src/Interfaces/ProvidesMetricLines.php | 4 ++-- src/Metrics/Histogram.php | 4 ++-- src/Metrics/Summary.php | 4 ++-- tests/Integration/OpenMetrics/parseFile.py | 8 ++++++-- tests/Unit/Types/LabelTest.php | 3 ++- tests/Unit/Types/MetricNameTest.php | 3 ++- 13 files changed, 54 insertions(+), 20 deletions(-) create mode 100644 .docker/php/8.0/Dockerfile diff --git a/.docker/php/8.0/Dockerfile b/.docker/php/8.0/Dockerfile new file mode 100644 index 0000000..f50d381 --- /dev/null +++ b/.docker/php/8.0/Dockerfile @@ -0,0 +1,15 @@ +FROM php:8.0-cli-alpine +ENV XDEBUG_VERSION 3.2.1 + +# Update system +RUN apk update && apk add --update linux-headers && apk add --no-cache git $PHPIZE_DEPS procps python3 \ + && pecl install xdebug-${XDEBUG_VERSION} \ + && docker-php-ext-enable xdebug + +RUN python3 -m ensurepip \ + && rm -r /usr/lib/python*/ensurepip \ + && pip3 install --upgrade pip setuptools \ + && pip3 install --upgrade prometheus_client path \ + && ln -s /usr/bin/python3 /usr/bin/python +# Cleanup +RUN apk del $PHPIZE_DEPS && rm -rf /var/cache/apk/* \ No newline at end of file diff --git a/composer.json b/composer.json index f561cc3..0683c3c 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,7 @@ } ], "require": { - "php": ">=7.1", + "php": "^7.1 || ^8.0", "psr/http-message": "^1.0" }, "autoload": { diff --git a/docker-compose.yml b/docker-compose.yml index 92f67d7..d714483 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -37,6 +37,18 @@ services: - ./:/repo working_dir: /repo + php80: + build: + dockerfile: Dockerfile + context: .docker/php/8.0 + container_name: om_et_php8.0 + restart: "no" + networks: + - om_et + volumes: + - ./:/repo + working_dir: /repo + composer: build: dockerfile: Dockerfile @@ -63,7 +75,7 @@ services: networks: default: - external: - name: "gateway" + name: "gateway" + external: true om_et: internal: true \ No newline at end of file diff --git a/src/Collections/CounterCollection.php b/src/Collections/CounterCollection.php index 164cc08..447dd1a 100644 --- a/src/Collections/CounterCollection.php +++ b/src/Collections/CounterCollection.php @@ -2,9 +2,9 @@ namespace OpenMetricsPhp\Exposition\Text\Collections; -use Iterator; use OpenMetricsPhp\Exposition\Text\Interfaces\NamesMetric; use OpenMetricsPhp\Exposition\Text\Metrics\Counter; +use Traversable; use function count; final class CounterCollection extends AbstractMetricCollection @@ -39,7 +39,7 @@ public function count() : int return count( $this->counters ); } - public function getMetricLines() : Iterator + public function getMetricLines() : Traversable { if ( 0 === $this->count() ) { diff --git a/src/Collections/GaugeCollection.php b/src/Collections/GaugeCollection.php index dfb281d..780f355 100644 --- a/src/Collections/GaugeCollection.php +++ b/src/Collections/GaugeCollection.php @@ -2,9 +2,9 @@ namespace OpenMetricsPhp\Exposition\Text\Collections; -use Iterator; use OpenMetricsPhp\Exposition\Text\Interfaces\NamesMetric; use OpenMetricsPhp\Exposition\Text\Metrics\Gauge; +use Traversable; use function count; use function implode; use function iterator_to_array; @@ -48,7 +48,7 @@ public function count() : int return count( $this->gauges ); } - public function getMetricLines() : Iterator + public function getMetricLines() : Traversable { if ( 0 === $this->count() ) { diff --git a/src/Collections/LabelCollection.php b/src/Collections/LabelCollection.php index 2790f55..2a24050 100644 --- a/src/Collections/LabelCollection.php +++ b/src/Collections/LabelCollection.php @@ -7,6 +7,7 @@ use OpenMetricsPhp\Exposition\Text\Exceptions\InvalidArgumentException; use OpenMetricsPhp\Exposition\Text\Interfaces\ProvidesNamedValue; use OpenMetricsPhp\Exposition\Text\Types\Label; +use Traversable; use function array_map; use function count; use function implode; @@ -62,7 +63,7 @@ public function add( ProvidesNamedValue $label, ProvidesNamedValue ...$labels ) } } - public function getIterator() : iterable + public function getIterator() : Traversable { yield from $this->labels; } diff --git a/src/HttpResponse.php b/src/HttpResponse.php index d14b2af..b15bdc1 100644 --- a/src/HttpResponse.php +++ b/src/HttpResponse.php @@ -2,11 +2,11 @@ namespace OpenMetricsPhp\Exposition\Text; -use Iterator; use OpenMetricsPhp\Exposition\Text\HttpResponse\OutputStream; use OpenMetricsPhp\Exposition\Text\Interfaces\ProvidesMetricLines; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\StreamInterface; +use Traversable; use function is_array; final class HttpResponse implements ResponseInterface @@ -61,7 +61,7 @@ public static function fromMetricCollections( private static function getAllMetricLines( ProvidesMetricLines $collection, ProvidesMetricLines ...$collections - ) : Iterator + ) : Traversable { yield from $collection->getMetricLines(); foreach ( $collections as $loopCollection ) diff --git a/src/Interfaces/ProvidesMetricLines.php b/src/Interfaces/ProvidesMetricLines.php index c04457d..7d49b55 100644 --- a/src/Interfaces/ProvidesMetricLines.php +++ b/src/Interfaces/ProvidesMetricLines.php @@ -2,11 +2,11 @@ namespace OpenMetricsPhp\Exposition\Text\Interfaces; -use Iterator; +use Traversable; interface ProvidesMetricLines { - public function getMetricLines() : Iterator; + public function getMetricLines() : Traversable; public function getMetricsString() : string; } \ No newline at end of file diff --git a/src/Metrics/Histogram.php b/src/Metrics/Histogram.php index 0e5ff7e..5bc5155 100644 --- a/src/Metrics/Histogram.php +++ b/src/Metrics/Histogram.php @@ -2,7 +2,6 @@ namespace OpenMetricsPhp\Exposition\Text\Metrics; -use Iterator; use OpenMetricsPhp\Exposition\Text\Collections\GaugeCollection; use OpenMetricsPhp\Exposition\Text\Exceptions\InvalidArgumentException; use OpenMetricsPhp\Exposition\Text\Interfaces\NamesMetric; @@ -12,6 +11,7 @@ use OpenMetricsPhp\Exposition\Text\Metrics\Aggregations\Sum; use OpenMetricsPhp\Exposition\Text\Metrics\Histogram\Bucket; use OpenMetricsPhp\Exposition\Text\Metrics\Histogram\InfiniteBucket; +use Traversable; use function iterator_to_array; use function sort; use const SORT_ASC; @@ -112,7 +112,7 @@ private function getHelpString() : string return sprintf( '# HELP %s %s', $this->metricName->toString(), $this->help ); } - public function getMetricLines() : Iterator + public function getMetricLines() : Traversable { yield $this->getTypeString(); diff --git a/src/Metrics/Summary.php b/src/Metrics/Summary.php index be554ad..3cfb39e 100644 --- a/src/Metrics/Summary.php +++ b/src/Metrics/Summary.php @@ -2,7 +2,6 @@ namespace OpenMetricsPhp\Exposition\Text\Metrics; -use Iterator; use OpenMetricsPhp\Exposition\Text\Collections\GaugeCollection; use OpenMetricsPhp\Exposition\Text\Exceptions\InvalidArgumentException; use OpenMetricsPhp\Exposition\Text\Interfaces\NamesMetric; @@ -10,6 +9,7 @@ use OpenMetricsPhp\Exposition\Text\Metrics\Aggregations\Count; use OpenMetricsPhp\Exposition\Text\Metrics\Aggregations\Sum; use OpenMetricsPhp\Exposition\Text\Metrics\Summary\Quantile; +use Traversable; use const SORT_ASC; use const SORT_NUMERIC; @@ -106,7 +106,7 @@ private function getHelpString() : string return sprintf( '# HELP %s %s', $this->metricName->toString(), $this->help ); } - public function getMetricLines() : Iterator + public function getMetricLines() : Traversable { yield $this->getTypeString(); diff --git a/tests/Integration/OpenMetrics/parseFile.py b/tests/Integration/OpenMetrics/parseFile.py index 3294d89..79884a3 100644 --- a/tests/Integration/OpenMetrics/parseFile.py +++ b/tests/Integration/OpenMetrics/parseFile.py @@ -1,8 +1,12 @@ from prometheus_client.openmetrics.parser import text_string_to_metric_families -from path import path import sys -metrics = path(sys.argv[1]).bytes() +if sys.version_info[0] == 3: + from path import Path + metrics = Path(sys.argv[1]).bytes().decode("utf-8") +else: + from path import path + metrics = path(sys.argv[1]).bytes() for family in text_string_to_metric_families(metrics): for sample in family.samples: diff --git a/tests/Unit/Types/LabelTest.php b/tests/Unit/Types/LabelTest.php index ba9652c..f7237ca 100644 --- a/tests/Unit/Types/LabelTest.php +++ b/tests/Unit/Types/LabelTest.php @@ -6,6 +6,7 @@ use OpenMetricsPhp\Exposition\Text\Tests\Traits\EmptyStringProviding; use OpenMetricsPhp\Exposition\Text\Types\Label; use PHPUnit\Framework\TestCase; +use Traversable; final class LabelTest extends TestCase { @@ -49,7 +50,7 @@ public function testThrowsExceptionForInvalidLabelName( string $name ) : void $this->fail( 'Expected an InvalidArgumentException to be thrown for invalid label name.' ); } - public function invalidLabelNameProvider() : iterable + public function invalidLabelNameProvider() : Traversable { yield from $this->emptyStringProvider(); diff --git a/tests/Unit/Types/MetricNameTest.php b/tests/Unit/Types/MetricNameTest.php index 6140a7f..4eafb8f 100644 --- a/tests/Unit/Types/MetricNameTest.php +++ b/tests/Unit/Types/MetricNameTest.php @@ -6,6 +6,7 @@ use OpenMetricsPhp\Exposition\Text\Tests\Traits\EmptyStringProviding; use OpenMetricsPhp\Exposition\Text\Types\MetricName; use PHPUnit\Framework\TestCase; +use Traversable; final class MetricNameTest extends TestCase { @@ -30,7 +31,7 @@ public function testThrowsExceptionForInvalidMetricName( string $metricName ) : $this->fail( 'Expected an InvalidArgumentException to be thrown for invalid metric name.' ); } - public function invalidMetricNameProvider() : iterable + public function invalidMetricNameProvider() : Traversable { yield from $this->emptyStringProvider(); From 665fe7e1394fbe45c1b28dd76ad063105e26de36 Mon Sep 17 00:00:00 2001 From: Holger Woltersdorf Date: Sat, 4 May 2024 10:42:08 +0200 Subject: [PATCH 04/23] Prepare docker environment for PHP7.1 to PHP8.3 & composer - Install PHPUnit directly in docker image --- .docker/composer/Dockerfile | 14 +++++++---- .docker/php/7.1/Dockerfile | 24 +++++++++++++----- .docker/php/7.2/Dockerfile | 25 +++++++++++++------ .docker/php/7.3/Dockerfile | 25 +++++++++++++------ .docker/php/7.4/Dockerfile | 22 +++++++++++++++++ .docker/php/8.0/Dockerfile | 33 +++++++++++++++---------- .docker/php/8.1/Dockerfile | 27 ++++++++++++++++++++ .docker/php/8.2/Dockerfile | 27 ++++++++++++++++++++ .docker/php/8.3/Dockerfile | 27 ++++++++++++++++++++ docker-compose.yml | 49 ++++++++++++++++++++++++++++++++++++- 10 files changed, 234 insertions(+), 39 deletions(-) create mode 100644 .docker/php/7.4/Dockerfile create mode 100644 .docker/php/8.1/Dockerfile create mode 100644 .docker/php/8.2/Dockerfile create mode 100644 .docker/php/8.3/Dockerfile diff --git a/.docker/composer/Dockerfile b/.docker/composer/Dockerfile index 2dcccbc..324dd12 100644 --- a/.docker/composer/Dockerfile +++ b/.docker/composer/Dockerfile @@ -1,8 +1,12 @@ FROM composer -ENV XDEBUG_VERSION 2.7.2 + +COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/ + # Update system -RUN apk update && apk upgrade && apk add --no-cache git $PHPIZE_DEPS procps \ - && pecl install xdebug-${XDEBUG_VERSION} \ - && docker-php-ext-enable xdebug +RUN set -ex && apk update && apk upgrade + +# Install xdebug +RUN set -ex && install-php-extensions xdebug-^3.3 + # Cleanup -RUN apk del $PHPIZE_DEPS && rm -rf /var/cache/apk/* \ No newline at end of file +RUN rm -rf /var/cache/apk/* \ No newline at end of file diff --git a/.docker/php/7.1/Dockerfile b/.docker/php/7.1/Dockerfile index 0e192e8..d7bbc8f 100644 --- a/.docker/php/7.1/Dockerfile +++ b/.docker/php/7.1/Dockerfile @@ -1,12 +1,24 @@ FROM php:7.1-cli-alpine -ENV XDEBUG_VERSION 2.7.2 -# Update system -RUN apk update && apk upgrade && apk add --no-cache git $PHPIZE_DEPS procps python2 \ - && pecl install xdebug-${XDEBUG_VERSION} \ - && docker-php-ext-enable xdebug + +ARG PHPUNIT_VERSION=7 +ARG XDEBUG_VERSION=2.7 + +COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/ +RUN set -ex apk update && apk upgrade && apk add --no-cache wget procps python2 + +## Install xdebug +RUN set -ex && install-php-extensions xdebug-^${XDEBUG_VERSION} + +## Install prometheus client RUN python -m ensurepip \ && rm -r /usr/lib/python*/ensurepip \ && pip install --upgrade pip setuptools \ && pip install --upgrade prometheus_client forked-path + +## Install phpunit +RUN wget https://phar.phpunit.de/phpunit-${PHPUNIT_VERSION}.phar \ + && chmod +x phpunit-${PHPUNIT_VERSION}.phar \ + && mv phpunit-${PHPUNIT_VERSION}.phar /usr/local/bin/phpunit + # Cleanup -RUN apk del $PHPIZE_DEPS && rm -rf /var/cache/apk/* +RUN rm -rf /var/cache/apk/* \ No newline at end of file diff --git a/.docker/php/7.2/Dockerfile b/.docker/php/7.2/Dockerfile index 5e4cdb7..b8f30f8 100644 --- a/.docker/php/7.2/Dockerfile +++ b/.docker/php/7.2/Dockerfile @@ -1,13 +1,24 @@ FROM php:7.2-cli-alpine -ENV XDEBUG_VERSION 2.7.2 -ENV XDEBUG_VERSION 2.7.2 -# Update system -RUN apk update && apk upgrade && apk add --no-cache git $PHPIZE_DEPS procps python2 \ - && pecl install xdebug-${XDEBUG_VERSION} \ - && docker-php-ext-enable xdebug + +ARG PHPUNIT_VERSION=8 +ARG XDEBUG_VERSION=3.1 + +COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/ +RUN set -ex apk update && apk upgrade && apk add --no-cache wget procps python2 + +## Install xdebug +RUN set -ex && install-php-extensions xdebug-^${XDEBUG_VERSION} + +## Install prometheus client RUN python -m ensurepip \ && rm -r /usr/lib/python*/ensurepip \ && pip install --upgrade pip setuptools \ && pip install --upgrade prometheus_client forked-path + +## Install phpunit +RUN wget https://phar.phpunit.de/phpunit-${PHPUNIT_VERSION}.phar \ + && chmod +x phpunit-${PHPUNIT_VERSION}.phar \ + && mv phpunit-${PHPUNIT_VERSION}.phar /usr/local/bin/phpunit + # Cleanup -RUN apk del $PHPIZE_DEPS && rm -rf /var/cache/apk/* \ No newline at end of file +RUN rm -rf /var/cache/apk/* \ No newline at end of file diff --git a/.docker/php/7.3/Dockerfile b/.docker/php/7.3/Dockerfile index bee95f7..5e98f77 100644 --- a/.docker/php/7.3/Dockerfile +++ b/.docker/php/7.3/Dockerfile @@ -1,13 +1,24 @@ FROM php:7.3-cli-alpine -ENV XDEBUG_VERSION 2.7.2 -ENV XDEBUG_VERSION 2.7.2 -# Update system -RUN apk update && apk upgrade && apk add --no-cache git $PHPIZE_DEPS procps python2 \ - && pecl install xdebug-${XDEBUG_VERSION} \ - && docker-php-ext-enable xdebug + +ARG PHPUNIT_VERSION=9 +ARG XDEBUG_VERSION=3.1 + +COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/ +RUN set -ex apk update && apk upgrade && apk add --no-cache wget procps python2 + +## Install xdebug +RUN set -ex && install-php-extensions xdebug-^${XDEBUG_VERSION} + +## Install prometheus client RUN python -m ensurepip \ && rm -r /usr/lib/python*/ensurepip \ && pip install --upgrade pip setuptools \ && pip install --upgrade prometheus_client forked-path + +## Install phpunit +RUN wget https://phar.phpunit.de/phpunit-${PHPUNIT_VERSION}.phar \ + && chmod +x phpunit-${PHPUNIT_VERSION}.phar \ + && mv phpunit-${PHPUNIT_VERSION}.phar /usr/local/bin/phpunit + # Cleanup -RUN apk del $PHPIZE_DEPS && rm -rf /var/cache/apk/* \ No newline at end of file +RUN rm -rf /var/cache/apk/* \ No newline at end of file diff --git a/.docker/php/7.4/Dockerfile b/.docker/php/7.4/Dockerfile new file mode 100644 index 0000000..ce4086b --- /dev/null +++ b/.docker/php/7.4/Dockerfile @@ -0,0 +1,22 @@ +FROM php:7.4-cli-alpine + +ARG PHPUNIT_VERSION=9 +ARG XDEBUG_VERSION=3.1 + +COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/ +RUN set -ex && apk update && apk upgrade && apk add --no-cache wget python3 py3-pip + +## Install xdebug +RUN set -ex && install-php-extensions xdebug-^${XDEBUG_VERSION} + +## Install prometheus client +RUN pip3 install --upgrade pip setuptools \ + && pip3 install --upgrade prometheus_client forked-path + +## Install phpunit +RUN wget https://phar.phpunit.de/phpunit-${PHPUNIT_VERSION}.phar \ + && chmod +x phpunit-${PHPUNIT_VERSION}.phar \ + && mv phpunit-${PHPUNIT_VERSION}.phar /usr/local/bin/phpunit + +# Cleanup +RUN rm -rf /var/cache/apk/* \ No newline at end of file diff --git a/.docker/php/8.0/Dockerfile b/.docker/php/8.0/Dockerfile index f50d381..3f41ad0 100644 --- a/.docker/php/8.0/Dockerfile +++ b/.docker/php/8.0/Dockerfile @@ -1,15 +1,22 @@ FROM php:8.0-cli-alpine -ENV XDEBUG_VERSION 3.2.1 - -# Update system -RUN apk update && apk add --update linux-headers && apk add --no-cache git $PHPIZE_DEPS procps python3 \ - && pecl install xdebug-${XDEBUG_VERSION} \ - && docker-php-ext-enable xdebug - -RUN python3 -m ensurepip \ - && rm -r /usr/lib/python*/ensurepip \ - && pip3 install --upgrade pip setuptools \ - && pip3 install --upgrade prometheus_client path \ - && ln -s /usr/bin/python3 /usr/bin/python + +ARG PHPUNIT_VERSION=9 +ARG XDEBUG_VERSION=3.3 + +COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/ +RUN set -ex apk update && apk upgrade && apk add --no-cache wget python3 py3-pip + +## Install xdebug +RUN set -ex && install-php-extensions xdebug-^${XDEBUG_VERSION} + +## Install prometheus client +RUN pip3 install --upgrade pip setuptools \ + && pip3 install --upgrade prometheus_client forked-path + +## Install phpunit +RUN wget https://phar.phpunit.de/phpunit-${PHPUNIT_VERSION}.phar \ + && chmod +x phpunit-${PHPUNIT_VERSION}.phar \ + && mv phpunit-${PHPUNIT_VERSION}.phar /usr/local/bin/phpunit + # Cleanup -RUN apk del $PHPIZE_DEPS && rm -rf /var/cache/apk/* \ No newline at end of file +RUN rm -rf /var/cache/apk/* \ No newline at end of file diff --git a/.docker/php/8.1/Dockerfile b/.docker/php/8.1/Dockerfile new file mode 100644 index 0000000..061cc34 --- /dev/null +++ b/.docker/php/8.1/Dockerfile @@ -0,0 +1,27 @@ +FROM php:8.1-cli-alpine + +ENV PATH="/root/.local/bin:${PATH}" +ARG PHPUNIT_VERSION=10 +ARG XDEBUG_VERSION=3.3 + +COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/ +RUN set -ex \ + && apk update && apk upgrade && apk add --no-cache wget pipx + +## Install xdebug +RUN set -ex \ + && install-php-extensions xdebug-^${XDEBUG_VERSION} + +## Install prometheus client +RUN pipx install pip \ + && pip3 install setuptools prometheus_client forked-path + +## Install phpunit +RUN wget https://phar.phpunit.de/phpunit-${PHPUNIT_VERSION}.phar \ + && chmod +x phpunit-${PHPUNIT_VERSION}.phar \ + && mv phpunit-${PHPUNIT_VERSION}.phar /usr/local/bin/phpunit + +# Cleanup +RUN set -ex \ + && apk del wget pipx \ + && rm -rf /var/cache/apk/* \ No newline at end of file diff --git a/.docker/php/8.2/Dockerfile b/.docker/php/8.2/Dockerfile new file mode 100644 index 0000000..1cf9fb6 --- /dev/null +++ b/.docker/php/8.2/Dockerfile @@ -0,0 +1,27 @@ +FROM php:8.2-cli-alpine + +ENV PATH="/root/.local/bin:${PATH}" +ARG PHPUNIT_VERSION=11 +ARG XDEBUG_VERSION=3.3 + +COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/ +RUN set -ex \ + && apk update && apk upgrade && apk add --no-cache wget pipx + +## Install xdebug +RUN set -ex \ + && install-php-extensions xdebug-^${XDEBUG_VERSION} + +## Install prometheus client +RUN pipx install pip \ + && pip3 install setuptools prometheus_client forked-path + +## Install phpunit +RUN wget https://phar.phpunit.de/phpunit-${PHPUNIT_VERSION}.phar \ + && chmod +x phpunit-${PHPUNIT_VERSION}.phar \ + && mv phpunit-${PHPUNIT_VERSION}.phar /usr/local/bin/phpunit + +# Cleanup +RUN set -ex \ + && apk del wget pipx \ + && rm -rf /var/cache/apk/* \ No newline at end of file diff --git a/.docker/php/8.3/Dockerfile b/.docker/php/8.3/Dockerfile new file mode 100644 index 0000000..fc325ab --- /dev/null +++ b/.docker/php/8.3/Dockerfile @@ -0,0 +1,27 @@ +FROM php:8.3-cli-alpine + +ENV PATH="/root/.local/bin:${PATH}" +ARG PHPUNIT_VERSION=11 +ARG XDEBUG_VERSION=3.3 + +COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/ +RUN set -ex \ + && apk update && apk upgrade && apk add --no-cache wget pipx + +## Install xdebug +RUN set -ex \ + && install-php-extensions xdebug-^${XDEBUG_VERSION} + +## Install prometheus client +RUN pipx install pip \ + && pip3 install setuptools prometheus_client forked-path + +## Install phpunit +RUN wget https://phar.phpunit.de/phpunit-${PHPUNIT_VERSION}.phar \ + && chmod +x phpunit-${PHPUNIT_VERSION}.phar \ + && mv phpunit-${PHPUNIT_VERSION}.phar /usr/local/bin/phpunit + +# Cleanup +RUN set -ex \ + && apk del wget pipx \ + && rm -rf /var/cache/apk/* \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index d714483..076a258 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -37,6 +37,18 @@ services: - ./:/repo working_dir: /repo + php74: + build: + dockerfile: Dockerfile + context: .docker/php/7.4 + container_name: om_et_php74 + restart: "no" + networks: + - om_et + volumes: + - ./:/repo + working_dir: /repo + php80: build: dockerfile: Dockerfile @@ -49,6 +61,42 @@ services: - ./:/repo working_dir: /repo + php81: + build: + dockerfile: Dockerfile + context: .docker/php/8.1 + container_name: om_et_php8.1 + restart: "no" + networks: + - om_et + volumes: + - ./:/repo + working_dir: /repo + + php82: + build: + dockerfile: Dockerfile + context: .docker/php/8.2 + container_name: om_et_php8.2 + restart: "no" + networks: + - om_et + volumes: + - ./:/repo + working_dir: /repo + + php83: + build: + dockerfile: Dockerfile + context: .docker/php/8.3 + container_name: om_et_php8.3 + restart: "no" + networks: + - om_et + volumes: + - ./:/repo + working_dir: /repo + composer: build: dockerfile: Dockerfile @@ -69,7 +117,6 @@ services: volumes: - ./:/repo working_dir: /repo - command: "analyze --level 5 src/" networks: - om_et From 00b156b0087100053aaba6aebbbbf152f04ce75b Mon Sep 17 00:00:00 2001 From: Holger Woltersdorf Date: Sat, 4 May 2024 12:20:42 +0200 Subject: [PATCH 05/23] Prepare test environment --- .docker/php/7.1/Dockerfile | 24 -------- .docker/php/7.4/Dockerfile | 7 ++- .docker/php/8.0/Dockerfile | 7 ++- .docker/php/8.1/Dockerfile | 8 +-- .docker/php/8.2/Dockerfile | 10 ++-- .docker/php/8.3/Dockerfile | 10 ++-- .gitignore | 5 +- Makefile | 116 +++++++++++++++++++++++++++++++++++++ build/phpunit.xml | 31 ---------- build/xdebug-filter.php | 12 ---- docker-compose.yml | 14 +---- tests/phpunit-10.xml | 16 +++++ tests/phpunit-8.xml | 22 +++++++ tests/phpunit-9.xml | 16 +++++ 14 files changed, 199 insertions(+), 99 deletions(-) delete mode 100644 .docker/php/7.1/Dockerfile create mode 100644 Makefile delete mode 100644 build/phpunit.xml delete mode 100644 build/xdebug-filter.php create mode 100644 tests/phpunit-10.xml create mode 100644 tests/phpunit-8.xml create mode 100644 tests/phpunit-9.xml diff --git a/.docker/php/7.1/Dockerfile b/.docker/php/7.1/Dockerfile deleted file mode 100644 index d7bbc8f..0000000 --- a/.docker/php/7.1/Dockerfile +++ /dev/null @@ -1,24 +0,0 @@ -FROM php:7.1-cli-alpine - -ARG PHPUNIT_VERSION=7 -ARG XDEBUG_VERSION=2.7 - -COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/ -RUN set -ex apk update && apk upgrade && apk add --no-cache wget procps python2 - -## Install xdebug -RUN set -ex && install-php-extensions xdebug-^${XDEBUG_VERSION} - -## Install prometheus client -RUN python -m ensurepip \ - && rm -r /usr/lib/python*/ensurepip \ - && pip install --upgrade pip setuptools \ - && pip install --upgrade prometheus_client forked-path - -## Install phpunit -RUN wget https://phar.phpunit.de/phpunit-${PHPUNIT_VERSION}.phar \ - && chmod +x phpunit-${PHPUNIT_VERSION}.phar \ - && mv phpunit-${PHPUNIT_VERSION}.phar /usr/local/bin/phpunit - -# Cleanup -RUN rm -rf /var/cache/apk/* \ No newline at end of file diff --git a/.docker/php/7.4/Dockerfile b/.docker/php/7.4/Dockerfile index ce4086b..d9b5996 100644 --- a/.docker/php/7.4/Dockerfile +++ b/.docker/php/7.4/Dockerfile @@ -18,5 +18,10 @@ RUN wget https://phar.phpunit.de/phpunit-${PHPUNIT_VERSION}.phar \ && chmod +x phpunit-${PHPUNIT_VERSION}.phar \ && mv phpunit-${PHPUNIT_VERSION}.phar /usr/local/bin/phpunit +# set Python alias +RUN ln -s /usr/bin/python3 /usr/bin/python + # Cleanup -RUN rm -rf /var/cache/apk/* \ No newline at end of file +RUN set -ex \ + && apk del wget \ + && rm -rf /var/cache/apk/* \ No newline at end of file diff --git a/.docker/php/8.0/Dockerfile b/.docker/php/8.0/Dockerfile index 3f41ad0..5bc656e 100644 --- a/.docker/php/8.0/Dockerfile +++ b/.docker/php/8.0/Dockerfile @@ -18,5 +18,10 @@ RUN wget https://phar.phpunit.de/phpunit-${PHPUNIT_VERSION}.phar \ && chmod +x phpunit-${PHPUNIT_VERSION}.phar \ && mv phpunit-${PHPUNIT_VERSION}.phar /usr/local/bin/phpunit +# set Python alias +RUN ln -s /usr/bin/python3 /usr/bin/python + # Cleanup -RUN rm -rf /var/cache/apk/* \ No newline at end of file +RUN set -ex \ + && apk del wget \ + && rm -rf /var/cache/apk/* \ No newline at end of file diff --git a/.docker/php/8.1/Dockerfile b/.docker/php/8.1/Dockerfile index 061cc34..c336d12 100644 --- a/.docker/php/8.1/Dockerfile +++ b/.docker/php/8.1/Dockerfile @@ -6,15 +6,15 @@ ARG XDEBUG_VERSION=3.3 COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/ RUN set -ex \ - && apk update && apk upgrade && apk add --no-cache wget pipx + && apk update && apk upgrade && apk add --no-cache wget python3 py3-pip ## Install xdebug RUN set -ex \ && install-php-extensions xdebug-^${XDEBUG_VERSION} ## Install prometheus client -RUN pipx install pip \ - && pip3 install setuptools prometheus_client forked-path +RUN set -ex \ + && pip3 install --break-system-packages setuptools prometheus_client forked-path ## Install phpunit RUN wget https://phar.phpunit.de/phpunit-${PHPUNIT_VERSION}.phar \ @@ -23,5 +23,5 @@ RUN wget https://phar.phpunit.de/phpunit-${PHPUNIT_VERSION}.phar \ # Cleanup RUN set -ex \ - && apk del wget pipx \ + && apk del wget \ && rm -rf /var/cache/apk/* \ No newline at end of file diff --git a/.docker/php/8.2/Dockerfile b/.docker/php/8.2/Dockerfile index 1cf9fb6..1665756 100644 --- a/.docker/php/8.2/Dockerfile +++ b/.docker/php/8.2/Dockerfile @@ -1,20 +1,20 @@ FROM php:8.2-cli-alpine ENV PATH="/root/.local/bin:${PATH}" -ARG PHPUNIT_VERSION=11 +ARG PHPUNIT_VERSION=10 ARG XDEBUG_VERSION=3.3 COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/ RUN set -ex \ - && apk update && apk upgrade && apk add --no-cache wget pipx + && apk update && apk upgrade && apk add --no-cache wget python3 py3-pip ## Install xdebug RUN set -ex \ && install-php-extensions xdebug-^${XDEBUG_VERSION} ## Install prometheus client -RUN pipx install pip \ - && pip3 install setuptools prometheus_client forked-path +RUN set -ex \ + && pip3 install --break-system-packages setuptools prometheus_client forked-path ## Install phpunit RUN wget https://phar.phpunit.de/phpunit-${PHPUNIT_VERSION}.phar \ @@ -23,5 +23,5 @@ RUN wget https://phar.phpunit.de/phpunit-${PHPUNIT_VERSION}.phar \ # Cleanup RUN set -ex \ - && apk del wget pipx \ + && apk del wget \ && rm -rf /var/cache/apk/* \ No newline at end of file diff --git a/.docker/php/8.3/Dockerfile b/.docker/php/8.3/Dockerfile index fc325ab..7ad751c 100644 --- a/.docker/php/8.3/Dockerfile +++ b/.docker/php/8.3/Dockerfile @@ -1,20 +1,20 @@ FROM php:8.3-cli-alpine ENV PATH="/root/.local/bin:${PATH}" -ARG PHPUNIT_VERSION=11 +ARG PHPUNIT_VERSION=10 ARG XDEBUG_VERSION=3.3 COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/ RUN set -ex \ - && apk update && apk upgrade && apk add --no-cache wget pipx + && apk update && apk upgrade && apk add --no-cache wget python3 py3-pip ## Install xdebug RUN set -ex \ && install-php-extensions xdebug-^${XDEBUG_VERSION} ## Install prometheus client -RUN pipx install pip \ - && pip3 install setuptools prometheus_client forked-path +RUN set -ex \ + && pip3 install --break-system-packages setuptools prometheus_client forked-path ## Install phpunit RUN wget https://phar.phpunit.de/phpunit-${PHPUNIT_VERSION}.phar \ @@ -23,5 +23,5 @@ RUN wget https://phar.phpunit.de/phpunit-${PHPUNIT_VERSION}.phar \ # Cleanup RUN set -ex \ - && apk del wget pipx \ + && apk del wget \ && rm -rf /var/cache/apk/* \ No newline at end of file diff --git a/.gitignore b/.gitignore index b436e12..146375b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ /.idea/ -/.vagrant/ /vendor/ -/build/logs/ -/build/.phpunit.result.cache +/tests/.phpunit.cache +/tests/.phpunit.result.cache /composer.lock diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ba6ef02 --- /dev/null +++ b/Makefile @@ -0,0 +1,116 @@ +.SILENT: +.PHONY: help + +## This help screen +help: + printf "Available commands\n\n" + awk '/^[a-zA-Z\-\_0-9]+:/ { \ + helpMessage = match(lastLine, /^## (.*)/); \ + if (helpMessage) { \ + helpCommand = substr($$1, 0, index($$1, ":")-1); \ + helpMessage = substr(lastLine, RSTART + 3, RLENGTH); \ + printf "\033[33m%-40s\033[0m %s\n", helpCommand, helpMessage; \ + } \ + } \ + { lastLine = $$0 }' $(MAKEFILE_LIST) + +PROJECT = exposition-text +IMAGE = php80 +DOCKER_COMPOSE_OPTIONS = -p $(PROJECT) -f docker-compose.yml +DOCKER_COMPOSE_BASE_COMMAND = docker-compose $(DOCKER_COMPOSE_OPTIONS) +DOCKER_COMPOSE_EXEC_COMMAND = $(DOCKER_COMPOSE_BASE_COMMAND) exec -T +DOCKER_COMPOSE_ISOLATED_RUN_COMMAND = $(DOCKER_COMPOSE_BASE_COMMAND) run --rm --no-deps + +## Install/Update whole setup +update: dcpull dcbuild composer-update +.PHONY: update + +## Build all custom docker images +dcbuild: pull-extension-installer + $(DOCKER_COMPOSE_BASE_COMMAND) build --pull --parallel +.PHONY: dcbuild + +pull-extension-installer: + docker pull mlocati/php-extension-installer +.PHONY: pull-extension-installer + +## Pull docker images +dcpull: + $(DOCKER_COMPOSE_BASE_COMMAND) pull +.PHONY: dcpull + +## Tear down docker compose setup +dcdown: + $(DOCKER_COMPOSE_BASE_COMMAND) down +.PHONY: dcdown + +## Validate composer config +composer-validate: + $(DOCKER_COMPOSE_ISOLATED_RUN_COMMAND) composer validate +.PHONY: composer-validate + +## Update composer dependencies +composer-update: + $(DOCKER_COMPOSE_ISOLATED_RUN_COMMAND) composer update --no-progress -o -vv +.PHONY: composer-update + +## Run PHPStan checks +phpstan: +.PHONY: phpstan + +## Run all tests on all PHP versions +tests: composer-validate test-php-7.2 test-php-7.3 test-php-7.4 test-php-8.0 test-php-8.1 test-php-8.2 +.PHONY: tests + +PHP_OPTIONS = -d error_reporting=-1 -dmemory_limit=-1 -d xdebug.mode=coverage +PHPUNIT_OPTIONS = --testdox + +## Run test on PHP 7.2 +test-php-7.2: dcdown + printf "\n\033[33mRun Tests on PHP 7.2\033[0m\n" + $(DOCKER_COMPOSE_ISOLATED_RUN_COMMAND) phpstan analyze -c tests/phpstan-72.neon --memory-limit=-1 --level=8 src/ + $(DOCKER_COMPOSE_ISOLATED_RUN_COMMAND) php72 php $(PHP_OPTIONS) /usr/local/bin/phpunit -c tests/phpunit-9.xml --testsuite=Unit $(PHPUNIT_OPTIONS) + $(DOCKER_COMPOSE_ISOLATED_RUN_COMMAND) php72 php $(PHP_OPTIONS) /usr/local/bin/phpunit -c tests/phpunit-9.xml --testsuite=Integration $(PHPUNIT_OPTIONS) +.PHONY: test-php-7.2 + +## Run test on PHP 7.3 +test-php-7.3: dcdown + printf "\n\033[33mRun Tests on PHP 7.3\033[0m\n" + $(DOCKER_COMPOSE_ISOLATED_RUN_COMMAND) php73 php $(PHP_OPTIONS) /usr/local/bin/phpunit -c tests/phpunit-9.xml --testsuite=Unit $(PHPUNIT_OPTIONS) + $(DOCKER_COMPOSE_ISOLATED_RUN_COMMAND) php73 php $(PHP_OPTIONS) /usr/local/bin/phpunit -c tests/phpunit-9.xml --testsuite=Integration $(PHPUNIT_OPTIONS) +.PHONY: test-php-7.3 + +## Run test on PHP 7.4 +test-php-7.4: dcdown + printf "\n\033[33mRun Tests on PHP 7.4\033[0m\n" + $(DOCKER_COMPOSE_ISOLATED_RUN_COMMAND) php74 php $(PHP_OPTIONS) /usr/local/bin/phpunit -c tests/phpunit-9.xml --testsuite=Unit $(PHPUNIT_OPTIONS) + $(DOCKER_COMPOSE_ISOLATED_RUN_COMMAND) php74 php $(PHP_OPTIONS) /usr/local/bin/phpunit -c tests/phpunit-9.xml --testsuite=Integration $(PHPUNIT_OPTIONS) +.PHONY: test-php-7.4 + +## Run test on PHP 8.0 +test-php-8.0: dcdown + printf "\n\033[33mRun Tests on PHP 8.0\033[0m\n" + $(DOCKER_COMPOSE_ISOLATED_RUN_COMMAND) php80 php $(PHP_OPTIONS) /usr/local/bin/phpunit -c tests/phpunit-9.xml --testsuite=Unit $(PHPUNIT_OPTIONS) + $(DOCKER_COMPOSE_ISOLATED_RUN_COMMAND) php80 php $(PHP_OPTIONS) /usr/local/bin/phpunit -c tests/phpunit-9.xml --testsuite=Integration $(PHPUNIT_OPTIONS) +.PHONY: test-php-8.0 + +## Run test on PHP 8.1 +test-php-8.1: dcdown + printf "\n\033[33mRun Tests on PHP 8.1\033[0m\n" + $(DOCKER_COMPOSE_ISOLATED_RUN_COMMAND) php81 php $(PHP_OPTIONS) /usr/local/bin/phpunit -c tests/phpunit-10.xml --testsuite=Unit $(PHPUNIT_OPTIONS) + $(DOCKER_COMPOSE_ISOLATED_RUN_COMMAND) php81 php $(PHP_OPTIONS) /usr/local/bin/phpunit -c tests/phpunit-10.xml --testsuite=Integration $(PHPUNIT_OPTIONS) +.PHONY: test-php-8.1 + +## Run test on PHP 8.2 +test-php-8.2: dcdown + printf "\n\033[33mRun Tests on PHP 8.2\033[0m\n" + $(DOCKER_COMPOSE_ISOLATED_RUN_COMMAND) php82 php $(PHP_OPTIONS) /usr/local/bin/phpunit -c tests/phpunit-10.xml --testsuite=Unit $(PHPUNIT_OPTIONS) + $(DOCKER_COMPOSE_ISOLATED_RUN_COMMAND) php82 php $(PHP_OPTIONS) /usr/local/bin/phpunit -c tests/phpunit-10.xml --testsuite=Integration $(PHPUNIT_OPTIONS) +.PHONY: test-php-8.2 + +## Run test on PHP 8.3 +test-php-8.3: dcdown + printf "\n\033[33mRun Tests on PHP 8.3\033[0m\n" + $(DOCKER_COMPOSE_ISOLATED_RUN_COMMAND) php83 php $(PHP_OPTIONS) /usr/local/bin/phpunit -c tests/phpunit-10.xml --testsuite=Unit $(PHPUNIT_OPTIONS) + $(DOCKER_COMPOSE_ISOLATED_RUN_COMMAND) php83 php $(PHP_OPTIONS) /usr/local/bin/phpunit -c tests/phpunit-10.xml --testsuite=Integration $(PHPUNIT_OPTIONS) +.PHONY: test-php-8.3 \ No newline at end of file diff --git a/build/phpunit.xml b/build/phpunit.xml deleted file mode 100644 index fe8cb62..0000000 --- a/build/phpunit.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - ../tests/Unit - - - ../tests/Integration - - - - - ../src - - - - - - Development - build/logs/TestDox.md - OpenMetricsPhp\Exposition\Text\Tests - - - - diff --git a/build/xdebug-filter.php b/build/xdebug-filter.php deleted file mode 100644 index 951dee4..0000000 --- a/build/xdebug-filter.php +++ /dev/null @@ -1,12 +0,0 @@ - + + + + ../tests/Unit + + + ../tests/Integration + + + + + ../src + + + diff --git a/tests/phpunit-8.xml b/tests/phpunit-8.xml new file mode 100644 index 0000000..ad9380d --- /dev/null +++ b/tests/phpunit-8.xml @@ -0,0 +1,22 @@ + + + + ../tests/Unit + + + ../tests/Integration + + + + + ../src + + + diff --git a/tests/phpunit-9.xml b/tests/phpunit-9.xml new file mode 100644 index 0000000..18b6f21 --- /dev/null +++ b/tests/phpunit-9.xml @@ -0,0 +1,16 @@ + + + + + ../src + + + + + ../tests/Unit + + + ../tests/Integration + + + From 73a6a6087f2e263d0bc68eb68c5c34b2994e606b Mon Sep 17 00:00:00 2001 From: Holger Woltersdorf Date: Sat, 4 May 2024 12:22:01 +0200 Subject: [PATCH 06/23] Always restore error handler --- src/HttpResponse/OutputStream.php | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/HttpResponse/OutputStream.php b/src/HttpResponse/OutputStream.php index 82caa44..6a48667 100644 --- a/src/HttpResponse/OutputStream.php +++ b/src/HttpResponse/OutputStream.php @@ -43,9 +43,14 @@ static function () E_WARNING ); - $this->resource = fopen( $stream, $mode ); - - restore_error_handler(); + try + { + $this->resource = fopen( $stream, $mode ); + } + finally + { + restore_error_handler(); + } return; } @@ -119,8 +124,8 @@ public function getSize() : ?int } /** - * @throws RuntimeException * @return int + * @throws RuntimeException */ public function tell() : int { @@ -171,8 +176,8 @@ public function isSeekable() : bool * @param int $offset * @param int $whence * - * @throws RuntimeException * @return bool + * @throws RuntimeException */ public function seek( $offset, $whence = SEEK_SET ) : bool { @@ -197,8 +202,8 @@ public function seek( $offset, $whence = SEEK_SET ) : bool } /** - * @throws RuntimeException * @return bool + * @throws RuntimeException */ public function rewind() : bool { @@ -223,8 +228,8 @@ public function isWritable() : bool /** * @param string $string * - * @throws RuntimeException * @return bool|int + * @throws RuntimeException */ public function write( $string ) { @@ -262,8 +267,8 @@ public function isReadable() : bool /** * @param int $length * - * @throws RuntimeException * @return string + * @throws RuntimeException */ public function read( $length ) : string { @@ -288,8 +293,8 @@ public function read( $length ) : string } /** - * @throws RuntimeException * @return string + * @throws RuntimeException */ public function getContents() : string { @@ -327,6 +332,6 @@ public function getMetadata( $key = null ) $metadata = stream_get_meta_data( $this->resource ); - return $metadata[ $key ] ?? null; - } + return $metadata[ $key ] ?? null; + } } From 5bf4a850626df93a156715e97c3183fd6bad84ae Mon Sep 17 00:00:00 2001 From: Holger Woltersdorf Date: Sat, 4 May 2024 12:22:38 +0200 Subject: [PATCH 07/23] Simplify data input for prometheus client --- tests/Integration/OpenMetrics/PythonParserTest.php | 2 +- tests/Integration/OpenMetrics/parseFile.py | 9 ++------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/tests/Integration/OpenMetrics/PythonParserTest.php b/tests/Integration/OpenMetrics/PythonParserTest.php index aeb5fb2..abff2af 100644 --- a/tests/Integration/OpenMetrics/PythonParserTest.php +++ b/tests/Integration/OpenMetrics/PythonParserTest.php @@ -59,7 +59,7 @@ public function testCanParseCounterMetricsWithPythonParser() : void private function assertParsedMetricOutput( string $expectedParserOutput, ProvidesMetricLines $metrics ) : void { $filename = tempnam( sys_get_temp_dir(), 'PythonParserTest_' ); - $command = sprintf( 'python %s/parseFile.py %s', __DIR__, $filename ); + $command = sprintf( 'cat "%s" | python %s/parseFile.py', $filename, __DIR__ ); file_put_contents( $filename, $metrics->getMetricsString() . "\n# EOF" ); diff --git a/tests/Integration/OpenMetrics/parseFile.py b/tests/Integration/OpenMetrics/parseFile.py index 79884a3..2ffbeb2 100644 --- a/tests/Integration/OpenMetrics/parseFile.py +++ b/tests/Integration/OpenMetrics/parseFile.py @@ -1,13 +1,8 @@ from prometheus_client.openmetrics.parser import text_string_to_metric_families import sys -if sys.version_info[0] == 3: - from path import Path - metrics = Path(sys.argv[1]).bytes().decode("utf-8") -else: - from path import path - metrics = path(sys.argv[1]).bytes() +input = sys.stdin.read() -for family in text_string_to_metric_families(metrics): +for family in text_string_to_metric_families(input): for sample in family.samples: print("Name: {0} Labels: {1} Value: {2} Timestamp: {3}".format(*sample)) \ No newline at end of file From 96c125926161375758f0879124907618a2724f80 Mon Sep 17 00:00:00 2001 From: Holger Woltersdorf Date: Sat, 4 May 2024 12:23:02 +0200 Subject: [PATCH 08/23] Fix test suite deprecations --- tests/Traits/EmptyStringProviding.php | 2 +- .../Unit/Collections/LabelCollectionTest.php | 14 +++++------ tests/Unit/HttpResponse/OutputStreamTest.php | 14 ----------- tests/Unit/Types/LabelTest.php | 23 ++++++++++++------- tests/Unit/Types/MetricNameTest.php | 15 ++++++++---- 5 files changed, 34 insertions(+), 34 deletions(-) diff --git a/tests/Traits/EmptyStringProviding.php b/tests/Traits/EmptyStringProviding.php index 9214666..a188504 100644 --- a/tests/Traits/EmptyStringProviding.php +++ b/tests/Traits/EmptyStringProviding.php @@ -4,7 +4,7 @@ trait EmptyStringProviding { - public function emptyStringProvider() : array + public static function emptyStringProvider() : array { return [ [ diff --git a/tests/Unit/Collections/LabelCollectionTest.php b/tests/Unit/Collections/LabelCollectionTest.php index 5092745..fa3628b 100644 --- a/tests/Unit/Collections/LabelCollectionTest.php +++ b/tests/Unit/Collections/LabelCollectionTest.php @@ -52,7 +52,7 @@ public function testCanCountLabelsInCollection() : void $this->assertSame( 0, $collection->count() ); /** @var ProvidesNamedValue $labelStub */ - $labelStub = $this->getMockBuilder( ProvidesNamedValue::class )->getMockForAbstractClass(); + $labelStub = $this->getMockBuilder( ProvidesNamedValue::class )->getMock(); $collection->add( $labelStub ); @@ -70,7 +70,7 @@ public function testCanGetLabelsAsCombinedLabelString() : void $this->assertSame( '', $collection->getCombinedLabelString() ); - $firstLabelStub = $this->getMockBuilder( ProvidesNamedValue::class )->getMockForAbstractClass(); + $firstLabelStub = $this->getMockBuilder( ProvidesNamedValue::class )->getMock(); $firstLabelStub->method( 'getName' )->willReturn( 'name1' ); $firstLabelStub->method( 'getLabelString' )->willReturn( 'name1="value1"' ); @@ -79,7 +79,7 @@ public function testCanGetLabelsAsCombinedLabelString() : void $this->assertSame( '{name1="value1"}', $collection->getCombinedLabelString() ); - $secondLabelStub = $this->getMockBuilder( ProvidesNamedValue::class )->getMockForAbstractClass(); + $secondLabelStub = $this->getMockBuilder( ProvidesNamedValue::class )->getMock(); $secondLabelStub->method( 'getName' )->willReturn( 'name2' ); $secondLabelStub->method( 'getLabelString' )->willReturn( 'name2="value2"' ); @@ -97,7 +97,7 @@ public function testLabelWithSameNameOverwritesPreviousLabel() : void { $collection = LabelCollection::new(); - $labelStub = $this->getMockBuilder( ProvidesNamedValue::class )->getMockForAbstractClass(); + $labelStub = $this->getMockBuilder( ProvidesNamedValue::class )->getMock(); $labelStub->method( 'getName' )->willReturn( 'name1' ); $labelStub->method( 'getLabelString' )->willReturn( 'name1="value1"' ); @@ -106,7 +106,7 @@ public function testLabelWithSameNameOverwritesPreviousLabel() : void $this->assertSame( '{name1="value1"}', $collection->getCombinedLabelString() ); - $overwriteLabelStub = $this->getMockBuilder( ProvidesNamedValue::class )->getMockForAbstractClass(); + $overwriteLabelStub = $this->getMockBuilder( ProvidesNamedValue::class )->getMock(); $overwriteLabelStub->method( 'getName' )->willReturn( 'name1' ); $overwriteLabelStub->method( 'getLabelString' )->willReturn( 'name1="value2"' ); @@ -126,11 +126,11 @@ public function testCanAddMultipleLabels() : void $this->assertSame( '', $collection->getCombinedLabelString() ); - $firstLabelStub = $this->getMockBuilder( ProvidesNamedValue::class )->getMockForAbstractClass(); + $firstLabelStub = $this->getMockBuilder( ProvidesNamedValue::class )->getMock(); $firstLabelStub->method( 'getName' )->willReturn( 'name1' ); $firstLabelStub->method( 'getLabelString' )->willReturn( 'name1="value1"' ); - $secondLabelStub = $this->getMockBuilder( ProvidesNamedValue::class )->getMockForAbstractClass(); + $secondLabelStub = $this->getMockBuilder( ProvidesNamedValue::class )->getMock(); $secondLabelStub->method( 'getName' )->willReturn( 'name2' ); $secondLabelStub->method( 'getLabelString' )->willReturn( 'name2="value2"' ); diff --git a/tests/Unit/HttpResponse/OutputStreamTest.php b/tests/Unit/HttpResponse/OutputStreamTest.php index b2833ec..226980c 100644 --- a/tests/Unit/HttpResponse/OutputStreamTest.php +++ b/tests/Unit/HttpResponse/OutputStreamTest.php @@ -90,20 +90,6 @@ public function testSeekThrowsExceptionIfNoResourceIsAvailable() : void $stream->seek( 0 ); } - /** - * @throws InvalidArgumentException - * @throws RuntimeException - */ - public function testSeekThrowsExceptionOnErrorSeekingWithinStream() : void - { - $stream = new OutputStream( 'php://memory', 'w+b' ); - - $this->expectException( RuntimeException::class ); - $this->expectExceptionMessage( 'Error seeking within stream' ); - - $stream->seek( 1 ); - } - /** * @throws InvalidArgumentException * @throws RuntimeException diff --git a/tests/Unit/Types/LabelTest.php b/tests/Unit/Types/LabelTest.php index f7237ca..001f8eb 100644 --- a/tests/Unit/Types/LabelTest.php +++ b/tests/Unit/Types/LabelTest.php @@ -13,20 +13,21 @@ final class LabelTest extends TestCase use EmptyStringProviding; /** - * @param string $value + * @param string $string * * @throws InvalidArgumentException * @throws \PHPUnit\Framework\AssertionFailedError * * @dataProvider emptyStringProvider */ - public function testThrowsExceptionForEmptyValue( string $value ) : void + #[DataProvider('emptyStringProvider')] + public function testThrowsExceptionForEmptyValue( string $string ) : void { $this->expectException( InvalidArgumentException::class ); $this->expectExceptionMessage( 'Label value cannot be empty.' ); /** @noinspection UnusedFunctionResultInspection */ - Label::fromNameAndValue( 'name', $value ); + Label::fromNameAndValue( 'name', $string ); $this->fail( 'Expected an InvalidArgumentException to be thrown for an empty label value.' ); } @@ -50,9 +51,15 @@ public function testThrowsExceptionForInvalidLabelName( string $name ) : void $this->fail( 'Expected an InvalidArgumentException to be thrown for invalid label name.' ); } - public function invalidLabelNameProvider() : Traversable + public static function invalidLabelNameProvider() : Traversable { - yield from $this->emptyStringProvider(); + yield from array_map( + static function ( array $record ) : array + { + return ['name' => $record['string']]; + }, + self::emptyStringProvider() + ); yield from [ [ @@ -96,7 +103,7 @@ public function testCanGetLabelString( string $name, string $value, string $expe $this->assertSame( $expectedLabelString, $label->getLabelString() ); } - public function labelStringsProvider() : array + public static function labelStringsProvider() : array { return [ [ @@ -165,7 +172,7 @@ public function testCanGetNameAndValueFromLabelString( $this->assertSame( $expectedValue, $label->getValue() ); } - public function labelStringToNameValueProvider() : array + public static function labelStringToNameValueProvider() : array { return [ [ @@ -215,7 +222,7 @@ public function testThrowsExceptionForInvalidLabelStrings( string $labelString ) $this->fail( 'Expected exception for invalid label string.' ); } - public function invalidLabelStringProvider() : array + public static function invalidLabelStringProvider() : array { return [ [ diff --git a/tests/Unit/Types/MetricNameTest.php b/tests/Unit/Types/MetricNameTest.php index 4eafb8f..3190ed2 100644 --- a/tests/Unit/Types/MetricNameTest.php +++ b/tests/Unit/Types/MetricNameTest.php @@ -7,6 +7,7 @@ use OpenMetricsPhp\Exposition\Text\Types\MetricName; use PHPUnit\Framework\TestCase; use Traversable; +use function array_map; final class MetricNameTest extends TestCase { @@ -31,9 +32,15 @@ public function testThrowsExceptionForInvalidMetricName( string $metricName ) : $this->fail( 'Expected an InvalidArgumentException to be thrown for invalid metric name.' ); } - public function invalidMetricNameProvider() : Traversable + public static function invalidMetricNameProvider() : Traversable { - yield from $this->emptyStringProvider(); + yield from array_map( + static function ( array $record ) : array + { + return ['metricName' => $record['string']]; + }, + self::emptyStringProvider() + ); yield from [ [ @@ -68,7 +75,7 @@ public function testCanGetMetricNameAsString( string $metricName, string $expect $this->assertSame( $expectedString, $metricNameObject->toString() ); } - public function validMetricNameProvider() : array + public static function validMetricNameProvider() : array { return [ [ @@ -106,7 +113,7 @@ public function testCanCheckIfMetricNamesAreEqual( string $name, string $otherNa $this->assertSame( $expectedResult, $other->equals( $metricName ) ); } - public function equalityMetricNameProvider() : array + public static function equalityMetricNameProvider() : array { return [ [ From 6e577a168cc6c981f11eff874ed32be4b9ba537f Mon Sep 17 00:00:00 2001 From: Holger Woltersdorf Date: Sat, 4 May 2024 12:23:34 +0200 Subject: [PATCH 09/23] Remove tooly composer script in favour of direct installs of PHPUnit in the docker images --- composer.json | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/composer.json b/composer.json index 0683c3c..6278409 100644 --- a/composer.json +++ b/composer.json @@ -26,26 +26,6 @@ } }, "require-dev": { - "ext-xdebug": "*", - "tm/tooly-composer-script": "~1.4", - "hollodotme/phpunit-testdox-markdown": "~1.0.0" - }, - "scripts": { - "post-install-cmd": "Tooly\\ScriptHandler::installPharTools", - "post-update-cmd": "Tooly\\ScriptHandler::installPharTools" - }, - "extra": { - "tools": { - "phpunit7": { - "url": "https://phar.phpunit.de/phpunit-7.phar", - "only-dev": true, - "replace": true - }, - "phpunit8": { - "url": "https://phar.phpunit.de/phpunit-8.phar", - "only-dev": true, - "replace": true - } - } + "ext-xdebug": "*" } } From 709a4d1e4630fd2472582707e30259b41e30a53c Mon Sep 17 00:00:00 2001 From: Holger Woltersdorf Date: Sat, 4 May 2024 13:01:41 +0200 Subject: [PATCH 10/23] Update PHP version constraint lower bound --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 6278409..951aa3f 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,7 @@ } ], "require": { - "php": "^7.1 || ^8.0", + "php": "^7.2 || ^8.0", "psr/http-message": "^1.0" }, "autoload": { From 5057e33e13ada8bcaf16312e35b0470170e5fdec Mon Sep 17 00:00:00 2001 From: Holger Woltersdorf Date: Sat, 4 May 2024 13:01:56 +0200 Subject: [PATCH 11/23] Fix PHPStan inspection issues --- src/Collections/CounterCollection.php | 13 ++++++------- src/Collections/GaugeCollection.php | 11 ++++------- src/Collections/LabelCollection.php | 9 ++++++--- src/HttpResponse.php | 8 +++++++- src/HttpResponse/OutputStream.php | 6 +++--- src/Interfaces/CollectsMetrics.php | 5 +++++ src/Interfaces/ProvidesMetricLines.php | 3 +++ src/Metrics/Histogram.php | 16 +++++++--------- src/Metrics/Summary.php | 22 ++++++++++------------ 9 files changed, 51 insertions(+), 42 deletions(-) diff --git a/src/Collections/CounterCollection.php b/src/Collections/CounterCollection.php index 447dd1a..061df02 100644 --- a/src/Collections/CounterCollection.php +++ b/src/Collections/CounterCollection.php @@ -9,12 +9,12 @@ final class CounterCollection extends AbstractMetricCollection { - /** @var array|Counter[] */ + /** @var array */ private $counters = []; public static function withMetricName( NamesMetric $metricName ) : self { - return new static( $metricName, 'counter' ); + return new self( $metricName, 'counter' ); } public static function fromCounters( NamesMetric $metricName, Counter $counter, Counter ...$counters ) : self @@ -27,11 +27,7 @@ public static function fromCounters( NamesMetric $metricName, Counter $counter, public function add( Counter $counter, Counter ...$counters ) : void { - $this->counters[] = $counter; - if ( [] !== $counters ) - { - $this->counters = array_merge( $this->counters, $counters ); - } + $this->counters = array_merge( $this->counters, [$counter], $counters ); } public function count() : int @@ -39,6 +35,9 @@ public function count() : int return count( $this->counters ); } + /** + * @return Traversable + */ public function getMetricLines() : Traversable { if ( 0 === $this->count() ) diff --git a/src/Collections/GaugeCollection.php b/src/Collections/GaugeCollection.php index 7dedab3..04b6c23 100644 --- a/src/Collections/GaugeCollection.php +++ b/src/Collections/GaugeCollection.php @@ -33,13 +33,7 @@ public static function fromGauges( NamesMetric $metricName, Gauge $gauge, Gauge public function add( Gauge $gauge, Gauge ...$gauges ) : void { - $this->gauges[] = $gauge; - - if ( [] !== $gauges ) - { - $this->gauges = array_merge( $this->gauges, $gauges ); - } - + $this->gauges = array_merge( $this->gauges, [$gauge], $gauges ); $this->sorted = false; } @@ -48,6 +42,9 @@ public function count() : int return count( $this->gauges ); } + /** + * @return Traversable + */ public function getMetricLines() : Traversable { if ( 0 === $this->count() ) diff --git a/src/Collections/LabelCollection.php b/src/Collections/LabelCollection.php index 7239620..875734c 100644 --- a/src/Collections/LabelCollection.php +++ b/src/Collections/LabelCollection.php @@ -12,9 +12,12 @@ use function count; use function implode; +/** + * @implements IteratorAggregate + */ final class LabelCollection implements Countable, IteratorAggregate { - /** @var array|ProvidesNamedValue[] */ + /** @var array */ private $labels; private function __construct() @@ -36,10 +39,10 @@ public static function fromLabels( ProvidesNamedValue $label, ProvidesNamedValue } /** - * @param array $labels + * @param array $labels * - * @throws InvalidArgumentException * @return LabelCollection + * @throws InvalidArgumentException */ public static function fromAssocArray( array $labels ) : self { diff --git a/src/HttpResponse.php b/src/HttpResponse.php index b15bdc1..70afefe 100644 --- a/src/HttpResponse.php +++ b/src/HttpResponse.php @@ -14,7 +14,7 @@ final class HttpResponse implements ResponseInterface /** @var string */ private $protocolVersion; - /** @var array */ + /** @var array> */ private $headers; /** @var int */ @@ -58,6 +58,12 @@ public static function fromMetricCollections( return new self( $outputStream ); } + /** + * @param ProvidesMetricLines $collection + * @param ProvidesMetricLines ...$collections + * + * @return Traversable + */ private static function getAllMetricLines( ProvidesMetricLines $collection, ProvidesMetricLines ...$collections diff --git a/src/HttpResponse/OutputStream.php b/src/HttpResponse/OutputStream.php index 6a48667..dd597ab 100644 --- a/src/HttpResponse/OutputStream.php +++ b/src/HttpResponse/OutputStream.php @@ -120,7 +120,7 @@ public function getSize() : ?int $stats = fstat( $this->resource ); - return $stats['size']; + return $stats !== false ? $stats['size'] : 0; } /** @@ -314,11 +314,11 @@ public function getContents() : string } /** - * @param null $key + * @param null|string $key * * @return array|mixed|null */ - public function getMetadata( $key = null ) + public function getMetadata( ?string $key = null ) { if ( !is_resource( $this->resource ) ) { diff --git a/src/Interfaces/CollectsMetrics.php b/src/Interfaces/CollectsMetrics.php index 290626c..5129d8b 100644 --- a/src/Interfaces/CollectsMetrics.php +++ b/src/Interfaces/CollectsMetrics.php @@ -6,6 +6,11 @@ interface CollectsMetrics extends ProvidesMetricLines, Countable { + /** + * @param NamesMetric $metricName + * + * @return CollectsMetrics + */ public static function withMetricName( NamesMetric $metricName ); public function getMetricName() : NamesMetric; diff --git a/src/Interfaces/ProvidesMetricLines.php b/src/Interfaces/ProvidesMetricLines.php index 7d49b55..aefe423 100644 --- a/src/Interfaces/ProvidesMetricLines.php +++ b/src/Interfaces/ProvidesMetricLines.php @@ -6,6 +6,9 @@ interface ProvidesMetricLines { + /** + * @return Traversable + */ public function getMetricLines() : Traversable; public function getMetricsString() : string; diff --git a/src/Metrics/Histogram.php b/src/Metrics/Histogram.php index 5bc5155..9b5461a 100644 --- a/src/Metrics/Histogram.php +++ b/src/Metrics/Histogram.php @@ -2,6 +2,7 @@ namespace OpenMetricsPhp\Exposition\Text\Metrics; +use Iterator; use OpenMetricsPhp\Exposition\Text\Collections\GaugeCollection; use OpenMetricsPhp\Exposition\Text\Exceptions\InvalidArgumentException; use OpenMetricsPhp\Exposition\Text\Interfaces\NamesMetric; @@ -41,11 +42,11 @@ private function __construct( NamesMetric $metricName ) /** * @param GaugeCollection $collection - * @param array $bounds + * @param array $bounds * @param string $suffix * - * @throws InvalidArgumentException * @return Histogram + * @throws InvalidArgumentException */ public static function fromGaugeCollectionWithBounds( GaugeCollection $collection, @@ -55,10 +56,7 @@ public static function fromGaugeCollectionWithBounds( { $histogram = new self( $collection->getMetricName()->withSuffix( $suffix ) ); - foreach ( $histogram->getBucketsForBounds( $collection, $bounds ) as $bucket ) - { - $histogram->buckets[] = $bucket; - } + $histogram->buckets = iterator_to_array( $histogram->getBucketsForBounds( $collection, $bounds ), true ); $countMeasurements = $collection->count(); $histogram->buckets[] = InfiniteBucket::new( $countMeasurements ); @@ -70,12 +68,12 @@ public static function fromGaugeCollectionWithBounds( /** * @param GaugeCollection $collection - * @param array $bounds + * @param array $bounds * + * @return Iterator * @throws InvalidArgumentException - * @return iterable */ - private function getBucketsForBounds( GaugeCollection $collection, array $bounds ) : iterable + private function getBucketsForBounds( GaugeCollection $collection, array $bounds ) : Iterator { sort( $bounds, SORT_NUMERIC | SORT_ASC ); diff --git a/src/Metrics/Summary.php b/src/Metrics/Summary.php index 3cfb39e..d4059b7 100644 --- a/src/Metrics/Summary.php +++ b/src/Metrics/Summary.php @@ -2,6 +2,7 @@ namespace OpenMetricsPhp\Exposition\Text\Metrics; +use Iterator; use OpenMetricsPhp\Exposition\Text\Collections\GaugeCollection; use OpenMetricsPhp\Exposition\Text\Exceptions\InvalidArgumentException; use OpenMetricsPhp\Exposition\Text\Interfaces\NamesMetric; @@ -10,6 +11,7 @@ use OpenMetricsPhp\Exposition\Text\Metrics\Aggregations\Sum; use OpenMetricsPhp\Exposition\Text\Metrics\Summary\Quantile; use Traversable; +use function iterator_to_array; use const SORT_ASC; use const SORT_NUMERIC; @@ -24,7 +26,7 @@ final class Summary implements ProvidesMetricLines /** @var string */ private $metricType; - /** @var array */ + /** @var array */ private $quantiles; private function __construct( NamesMetric $metricName ) @@ -37,11 +39,11 @@ private function __construct( NamesMetric $metricName ) /** * @param GaugeCollection $collection - * @param array $quantiles + * @param array $quantiles * @param string $suffix * - * @throws InvalidArgumentException * @return Summary + * @throws InvalidArgumentException */ public static function fromGaugeCollectionWithQuantiles( GaugeCollection $collection, @@ -49,12 +51,8 @@ public static function fromGaugeCollectionWithQuantiles( string $suffix = '' ) : self { - $summary = new self( $collection->getMetricName()->withSuffix( $suffix ) ); - - foreach ( $summary->getQuantiles( $collection, $quantiles ) as $quantile ) - { - $summary->quantiles[] = $quantile; - } + $summary = new self( $collection->getMetricName()->withSuffix( $suffix ) ); + $summary->quantiles = iterator_to_array( $summary->getQuantiles( $collection, $quantiles ), true ); $summary->quantiles[] = Sum::new( $collection->sumMeasuredValues() ); $summary->quantiles[] = Count::new( $collection->count() ); @@ -64,12 +62,12 @@ public static function fromGaugeCollectionWithQuantiles( /** * @param GaugeCollection $collection - * @param array $quantiles + * @param array $quantiles * + * @return Iterator * @throws InvalidArgumentException - * @return iterable */ - private function getQuantiles( GaugeCollection $collection, array $quantiles ) : iterable + private function getQuantiles( GaugeCollection $collection, array $quantiles ) : Iterator { sort( $quantiles, SORT_NUMERIC | SORT_ASC ); From 09a35364a1a33b41a850d81e77ac5e67ae0029c9 Mon Sep 17 00:00:00 2001 From: Holger Woltersdorf Date: Sat, 4 May 2024 13:02:33 +0200 Subject: [PATCH 12/23] Finish install & test tasks --- Makefile | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index ba6ef02..7e44183 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,11 @@ DOCKER_COMPOSE_BASE_COMMAND = docker-compose $(DOCKER_COMPOSE_OPTIONS) DOCKER_COMPOSE_EXEC_COMMAND = $(DOCKER_COMPOSE_BASE_COMMAND) exec -T DOCKER_COMPOSE_ISOLATED_RUN_COMMAND = $(DOCKER_COMPOSE_BASE_COMMAND) run --rm --no-deps -## Install/Update whole setup +## Install whole setup +install: dcpull dcbuild composer-install +.PHONY: update + +## Update whole setup update: dcpull dcbuild composer-update .PHONY: update @@ -54,12 +58,18 @@ composer-update: $(DOCKER_COMPOSE_ISOLATED_RUN_COMMAND) composer update --no-progress -o -vv .PHONY: composer-update +## Install composer dependencies +composer-install: + $(DOCKER_COMPOSE_ISOLATED_RUN_COMMAND) composer install --no-progress -o -a -vv +.PHONY: composer-install + ## Run PHPStan checks phpstan: + $(DOCKER_COMPOSE_ISOLATED_RUN_COMMAND) phpstan analyze --memory-limit=-1 --level=8 src/ .PHONY: phpstan ## Run all tests on all PHP versions -tests: composer-validate test-php-7.2 test-php-7.3 test-php-7.4 test-php-8.0 test-php-8.1 test-php-8.2 +tests: composer-validate phpstan test-php-7.2 test-php-7.3 test-php-7.4 test-php-8.0 test-php-8.1 test-php-8.2 .PHONY: tests PHP_OPTIONS = -d error_reporting=-1 -dmemory_limit=-1 -d xdebug.mode=coverage @@ -68,7 +78,6 @@ PHPUNIT_OPTIONS = --testdox ## Run test on PHP 7.2 test-php-7.2: dcdown printf "\n\033[33mRun Tests on PHP 7.2\033[0m\n" - $(DOCKER_COMPOSE_ISOLATED_RUN_COMMAND) phpstan analyze -c tests/phpstan-72.neon --memory-limit=-1 --level=8 src/ $(DOCKER_COMPOSE_ISOLATED_RUN_COMMAND) php72 php $(PHP_OPTIONS) /usr/local/bin/phpunit -c tests/phpunit-9.xml --testsuite=Unit $(PHPUNIT_OPTIONS) $(DOCKER_COMPOSE_ISOLATED_RUN_COMMAND) php72 php $(PHP_OPTIONS) /usr/local/bin/phpunit -c tests/phpunit-9.xml --testsuite=Integration $(PHPUNIT_OPTIONS) .PHONY: test-php-7.2 From 4eb4d82236f0658a2dff232c530f98f4b64f9889 Mon Sep 17 00:00:00 2001 From: Holger Woltersdorf Date: Sat, 4 May 2024 13:03:58 +0200 Subject: [PATCH 13/23] Add github CI & release workflow --- .github/workflows/ci.yml | 89 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..65a8d5a --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,89 @@ +name: CI and release + +on: + push: + branches: + - master + - development + + tags: + - 'v*.*.*' + + pull_request: + + schedule: + - cron: "7 7 * * *" + +jobs: + static-analysis: + runs-on: ubuntu-latest + + steps: + - name: GIT--checkout + uses: actions/checkout@v4 + + - name: Pull docker services + run: make install + + - name: Composer validate + run: make composer-validate + + - name: Run PHPStan + run: vendor/bin/phpstan + + tests: + runs-on: ubuntu-latest + strategy: + matrix: + php: + - "7.2" + - "7.3" + - "7.4" + - "8.0" + - "8.1" + - "8.2" + - "8.3" + steps: + - name: GIT--checkout + uses: actions/checkout@v4 + + - name: Install environment + run: make install + + - name: Run unit tests on PHP ${{ matrix.php }} + run: make -s "test-php-${{ matrix.php }}" + env: + COMPOSE_INTERACTIVE_NO_CLI: 1 + + release: + needs: + - static-analysis + - tests + + runs-on: ubuntu-latest + if: github.event_name == 'push' + + steps: + - name: GIT--Checkout + uses: actions/checkout@v4 + + - name: Extract version + if: success() + run: | + # Strip git ref prefix from version + RELEASE_VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,') + + # Strip "v" prefix from tag name + [[ "${{ github.ref }}" == "refs/tags/"* ]] && RELEASE_VERSION=$(echo $RELEASE_VERSION | sed -e 's/^v//') + + echo $RELEASE_VERSION + echo "RELEASE_VERSION=$RELEASE_VERSION" >> $GITHUB_ENV + + - name: Create release + if: ${{ success() && startsWith(github.ref, 'refs/tags/') }} + uses: softprops/action-gh-release@v1 + with: + name: Version ${{ env.RELEASE_VERSION }} + body_path: CHANGELOG.md + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file From 273555546126b318c7c30f65ba8f4eec93ed439a Mon Sep 17 00:00:00 2001 From: Holger Woltersdorf Date: Sat, 4 May 2024 13:08:52 +0200 Subject: [PATCH 14/23] Optimize resource usage for static analysis --- .github/workflows/ci.yml | 4 ++-- Makefile | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 65a8d5a..7147355 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,8 +22,8 @@ jobs: - name: GIT--checkout uses: actions/checkout@v4 - - name: Pull docker services - run: make install + - name: Install tools for static analysis + run: make install-static-analysis - name: Composer validate run: make composer-validate diff --git a/Makefile b/Makefile index 7e44183..9068a21 100644 --- a/Makefile +++ b/Makefile @@ -25,6 +25,10 @@ DOCKER_COMPOSE_ISOLATED_RUN_COMMAND = $(DOCKER_COMPOSE_BASE_COMMAND) run --rm -- install: dcpull dcbuild composer-install .PHONY: update +install-static-analysis: dcpull + $(DOCKER_COMPOSE_BASE_COMMAND) build composer --pull --parallel +.PHONY: install-static-analysis + ## Update whole setup update: dcpull dcbuild composer-update .PHONY: update From ef9e362876c8bdfda77eed472cf5550f5996b050 Mon Sep 17 00:00:00 2001 From: Holger Woltersdorf Date: Sat, 4 May 2024 13:11:46 +0200 Subject: [PATCH 15/23] Fix CI build --- .github/workflows/ci.yml | 14 ++------------ Makefile | 2 +- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7147355..4b64a7b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,16 +33,6 @@ jobs: tests: runs-on: ubuntu-latest - strategy: - matrix: - php: - - "7.2" - - "7.3" - - "7.4" - - "8.0" - - "8.1" - - "8.2" - - "8.3" steps: - name: GIT--checkout uses: actions/checkout@v4 @@ -50,8 +40,8 @@ jobs: - name: Install environment run: make install - - name: Run unit tests on PHP ${{ matrix.php }} - run: make -s "test-php-${{ matrix.php }}" + - name: Run all tests + run: make tests env: COMPOSE_INTERACTIVE_NO_CLI: 1 diff --git a/Makefile b/Makefile index 9068a21..130a38e 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,7 @@ install: dcpull dcbuild composer-install .PHONY: update install-static-analysis: dcpull - $(DOCKER_COMPOSE_BASE_COMMAND) build composer --pull --parallel + $(DOCKER_COMPOSE_BASE_COMMAND) build --pull --parallel composer .PHONY: install-static-analysis ## Update whole setup From edcee7c8fdf20814cdbf7977e47bcdfe9afd26d9 Mon Sep 17 00:00:00 2001 From: Holger Woltersdorf Date: Sat, 4 May 2024 13:15:12 +0200 Subject: [PATCH 16/23] Networks in docker compose config --- docker-compose.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index f68d43c..20719ed 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -96,7 +96,7 @@ services: working_dir: /repo command: "update -o -v" networks: - - default + - om_et phpstan: image: phpstan/phpstan:latest @@ -109,8 +109,4 @@ services: - om_et networks: - default: - name: "gateway" - external: true - om_et: - internal: true \ No newline at end of file + om_et: \ No newline at end of file From d55ff8aa62a9c5a513a4cbf524674e7a9953a5ec Mon Sep 17 00:00:00 2001 From: Holger Woltersdorf Date: Sat, 4 May 2024 13:16:59 +0200 Subject: [PATCH 17/23] Fix phpstan task call --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4b64a7b..55ea064 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,7 +29,7 @@ jobs: run: make composer-validate - name: Run PHPStan - run: vendor/bin/phpstan + run: make phpstan tests: runs-on: ubuntu-latest From 3a0a75295a1dd0b040c6737bef5654bc9385ccf4 Mon Sep 17 00:00:00 2001 From: Holger Woltersdorf Date: Sat, 4 May 2024 13:18:27 +0200 Subject: [PATCH 18/23] add missing composer install --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 55ea064..f6aea69 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,6 +28,9 @@ jobs: - name: Composer validate run: make composer-validate + - name: Composer validate + run: make composer-install + - name: Run PHPStan run: make phpstan From 1bb0344d322df082e87557ce762922c64e07188c Mon Sep 17 00:00:00 2001 From: Holger Woltersdorf Date: Sat, 4 May 2024 13:24:32 +0200 Subject: [PATCH 19/23] Run tests in matrix to avoid building docker images multiple times --- .github/workflows/ci.yml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f6aea69..8b0b508 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,15 +36,25 @@ jobs: tests: runs-on: ubuntu-latest + strategy: + matrix: + php: + - 7.2 + - 7.3 + - 7.4 + - 8.0 + - 8.1 + - 8.2 + - 8.3 steps: - name: GIT--checkout uses: actions/checkout@v4 - name: Install environment - run: make install + run: make composer-install - name: Run all tests - run: make tests + run: make -s test-php-${{matrix.php}} env: COMPOSE_INTERACTIVE_NO_CLI: 1 From 75ceecbfba6a9e86adf5ecbdf3ba19e524ba65ba Mon Sep 17 00:00:00 2001 From: Holger Woltersdorf Date: Sat, 4 May 2024 13:26:37 +0200 Subject: [PATCH 20/23] Quote php versions --- .github/workflows/ci.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8b0b508..ac862b0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,13 +39,13 @@ jobs: strategy: matrix: php: - - 7.2 - - 7.3 - - 7.4 - - 8.0 - - 8.1 - - 8.2 - - 8.3 + - "7.2" + - "7.3" + - "7.4" + - "8.0" + - "8.1" + - "8.2" + - "8.3" steps: - name: GIT--checkout uses: actions/checkout@v4 @@ -54,7 +54,7 @@ jobs: run: make composer-install - name: Run all tests - run: make -s test-php-${{matrix.php}} + run: make -s "test-php-${{matrix.php}}" env: COMPOSE_INTERACTIVE_NO_CLI: 1 From f35d7f756b696e0c4dc742d3ea477838cacfa0f9 Mon Sep 17 00:00:00 2001 From: Holger Woltersdorf Date: Sat, 4 May 2024 13:34:10 +0200 Subject: [PATCH 21/23] Extract interface for label collection --- src/Collections/LabelCollection.php | 8 ++------ src/Interfaces/CollectsLabels.php | 16 ++++++++++++++++ src/Metrics/Counter.php | 11 ++++++----- src/Metrics/Gauge.php | 5 +++-- 4 files changed, 27 insertions(+), 13 deletions(-) create mode 100644 src/Interfaces/CollectsLabels.php diff --git a/src/Collections/LabelCollection.php b/src/Collections/LabelCollection.php index 875734c..a1f1c83 100644 --- a/src/Collections/LabelCollection.php +++ b/src/Collections/LabelCollection.php @@ -2,9 +2,8 @@ namespace OpenMetricsPhp\Exposition\Text\Collections; -use Countable; -use IteratorAggregate; use OpenMetricsPhp\Exposition\Text\Exceptions\InvalidArgumentException; +use OpenMetricsPhp\Exposition\Text\Interfaces\CollectsLabels; use OpenMetricsPhp\Exposition\Text\Interfaces\ProvidesNamedValue; use OpenMetricsPhp\Exposition\Text\Types\Label; use Traversable; @@ -12,10 +11,7 @@ use function count; use function implode; -/** - * @implements IteratorAggregate - */ -final class LabelCollection implements Countable, IteratorAggregate +final class LabelCollection implements CollectsLabels { /** @var array */ private $labels; diff --git a/src/Interfaces/CollectsLabels.php b/src/Interfaces/CollectsLabels.php new file mode 100644 index 0000000..046d6a4 --- /dev/null +++ b/src/Interfaces/CollectsLabels.php @@ -0,0 +1,16 @@ + + */ +interface CollectsLabels extends Countable, IteratorAggregate +{ + public function add( ProvidesNamedValue $label, ProvidesNamedValue ...$labels ) : void; + + public function getCombinedLabelString() : string; +} \ No newline at end of file diff --git a/src/Metrics/Counter.php b/src/Metrics/Counter.php index c1f9574..94add07 100644 --- a/src/Metrics/Counter.php +++ b/src/Metrics/Counter.php @@ -4,6 +4,7 @@ use OpenMetricsPhp\Exposition\Text\Collections\LabelCollection; use OpenMetricsPhp\Exposition\Text\Exceptions\InvalidArgumentException; +use OpenMetricsPhp\Exposition\Text\Interfaces\CollectsLabels; use OpenMetricsPhp\Exposition\Text\Interfaces\ProvidesNamedValue; use OpenMetricsPhp\Exposition\Text\Interfaces\ProvidesSampleString; @@ -15,7 +16,7 @@ final class Counter implements ProvidesSampleString /** @var int|null */ private $timestamp; - /** @var LabelCollection */ + /** @var CollectsLabels */ private $labels; /** @@ -49,8 +50,8 @@ private function guardCounterIsValid( float $counter ) : void /** * @param float $counterValue * - * @throws InvalidArgumentException * @return Counter + * @throws InvalidArgumentException */ public static function fromValue( float $counterValue ) : self { @@ -61,8 +62,8 @@ public static function fromValue( float $counterValue ) : self * @param float $counterValue * @param int $timestamp * - * @throws InvalidArgumentException * @return Counter + * @throws InvalidArgumentException */ public static function fromValueAndTimestamp( float $counterValue, int $timestamp ) : self { @@ -76,9 +77,9 @@ public function withLabels( ProvidesNamedValue $label, ProvidesNamedValue ...$la return $this; } - public function withLabelCollection( LabelCollection $labels ) : self + public function withLabelCollection( CollectsLabels $labels ) : self { - foreach ( $labels->getIterator() as $label ) + foreach ( $labels as $label ) { $this->addLabels( $label ); } diff --git a/src/Metrics/Gauge.php b/src/Metrics/Gauge.php index 1968759..4a29c20 100644 --- a/src/Metrics/Gauge.php +++ b/src/Metrics/Gauge.php @@ -3,6 +3,7 @@ namespace OpenMetricsPhp\Exposition\Text\Metrics; use OpenMetricsPhp\Exposition\Text\Collections\LabelCollection; +use OpenMetricsPhp\Exposition\Text\Interfaces\CollectsLabels; use OpenMetricsPhp\Exposition\Text\Interfaces\ProvidesMeasuredValue; use OpenMetricsPhp\Exposition\Text\Interfaces\ProvidesNamedValue; use OpenMetricsPhp\Exposition\Text\Interfaces\ProvidesSampleString; @@ -16,7 +17,7 @@ final class Gauge implements ProvidesSampleString, ProvidesMeasuredValue /** @var int|null */ private $timestamp; - /** @var LabelCollection */ + /** @var CollectsLabels */ private $labels; /** @@ -50,7 +51,7 @@ public function withLabels( ProvidesNamedValue $label, ProvidesNamedValue ...$la return $this; } - public function withLabelCollection( LabelCollection $labels ) : self + public function withLabelCollection( CollectsLabels $labels ) : self { foreach ( $labels->getIterator() as $label ) { From 028c0dd67edde666cbc0881ba0c3e9e29c5b57b6 Mon Sep 17 00:00:00 2001 From: Holger Woltersdorf Date: Sat, 4 May 2024 13:37:27 +0200 Subject: [PATCH 22/23] Update documentation --- .github/CONTRIBUTING.md | 28 ++++++++++++++++++++++++++-- README.md | 19 ++++++++++--------- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index d872a4a..7e5b60e 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -18,8 +18,32 @@ We accept contributions via pull requests on [GitHub](https://github.com/openmet - **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please squash them before submitting. -## Running tests +### Install development environment ```bash -$ php vendor/bin/phpunit.phar -c build/ +make install +``` + +### Run PHPStan + +```bash +make phpstan +``` + +### Run PHP-version specific tests + +```bash +make test-php-7.2 +make test-php-7.3 +make test-php-7.4 +make test-php-8.0 +make test-php-8.1 +make test-php-8.2 +make test-php-8.3 +``` + +### Run all tests + +```bash +make tests ``` diff --git a/README.md b/README.md index cfdbfea..7cdff0d 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,4 @@ -[![CircleCI](https://circleci.com/gh/openmetrics-php/exposition-text.svg?style=svg)](https://circleci.com/gh/openmetrics-php/exposition-text) -[![Latest Stable Version](https://poser.pugx.org/openmetrics-php/exposition-text/v/stable)](https://packagist.org/packages/openmetrics-php/exposition-text) -[![Total Downloads](https://poser.pugx.org/openmetrics-php/exposition-text/downloads)](https://packagist.org/packages/openmetrics-php/exposition-text) -[![codecov](https://codecov.io/gh/openmetrics-php/exposition-text/branch/master/graph/badge.svg)](https://codecov.io/gh/openmetrics-php/exposition-text) -[![phpstan enabled](https://img.shields.io/badge/phpstan-enabled-green.svg)](https://github.com/phpstan/phpstan) +[![CI and release](https://github.com/openmetrics-php/exposition-text/actions/workflows/ci.yml/badge.svg)](https://github.com/openmetrics-php/exposition-text/actions/workflows/ci.yml) # OpenMetrics-PHP Exposition Text @@ -24,9 +20,15 @@ into existing frameworks / code bases. **Please note:** that the following content-type header is used for the HTTP response by default `Content-Type: application/openmetrics-text; charset=utf-8` as [discussed here](https://github.com/OpenObservability/OpenMetrics/issues/79). -## Requirements +## Supported PHP Versions -* PHP >= 7.1 +* 7.2 +* 7.3 +* 7.4 +* 8.0 +* 8.1 +* 8.2 +* 8.3 ## Installation @@ -261,7 +263,6 @@ your_metric_name_summary_count 10 ## Contributing -Contributions are welcome and will be fully credited. +Contributions are welcome and will be fully credited. Please see the [contribution guide](.github/CONTRIBUTING.md) for details. - From 2774dfd0bd7adec358f5e7031c86ce5f1060bd0f Mon Sep 17 00:00:00 2001 From: Holger Woltersdorf Date: Sat, 4 May 2024 14:08:48 +0200 Subject: [PATCH 23/23] Remove HttpResponse & OutputStream class in order to get rid of the dependency to psr/http-message, #12 * Remove tests * Update examples --- CHANGELOG.md | 13 + composer.json | 3 +- examples/counters.php | 3 +- examples/gauges.php | 3 +- examples/histogram.php | 3 +- examples/summary.php | 3 +- src/HttpResponse.php | 179 -------- src/HttpResponse/OutputStream.php | 337 -------------- tests/Unit/HttpResponse/OutputStreamTest.php | 438 ------------------- tests/Unit/HttpResponseTest.php | 201 --------- 10 files changed, 18 insertions(+), 1165 deletions(-) delete mode 100644 src/HttpResponse.php delete mode 100644 src/HttpResponse/OutputStream.php delete mode 100644 tests/Unit/HttpResponse/OutputStreamTest.php delete mode 100644 tests/Unit/HttpResponseTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e81078..bcb7c56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,19 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/) and [Keep a CHANGELOG](http://keepachangelog.com). +## [0.4.0] - 2024-05-04 + +* Dropped support for PHP 7.1 +* Added support for PHP 8.3 +* Removed `HttpResponse` class in order to get rid of the dependency to `psr/http-message` — see [#12] + * Users must implement or use their own response class to publish the metrics via HTTP +* Fix deprecation warnings for IteratorAggregate since PHP 8.1 — see [#8] +* Moved CI to GitHub Actions + +[#12]: https://github.com/openmetrics-php/exposition-text/issues/12 + +[#8]: https://github.com/openmetrics-php/exposition-text/issues/8 + ## [0.3.1] - 2019-02-19 ### Fixed diff --git a/composer.json b/composer.json index 951aa3f..ded8efb 100644 --- a/composer.json +++ b/composer.json @@ -12,8 +12,7 @@ } ], "require": { - "php": "^7.2 || ^8.0", - "psr/http-message": "^1.0" + "php": "^7.2 || ^8.0" }, "autoload": { "psr-4": { diff --git a/examples/counters.php b/examples/counters.php index 902a5a8..94b914f 100644 --- a/examples/counters.php +++ b/examples/counters.php @@ -4,7 +4,6 @@ use OpenMetricsPhp\Exposition\Text\Collections\CounterCollection; use OpenMetricsPhp\Exposition\Text\Collections\LabelCollection; -use OpenMetricsPhp\Exposition\Text\HttpResponse; use OpenMetricsPhp\Exposition\Text\Metrics\Counter; use OpenMetricsPhp\Exposition\Text\Types\Label; use OpenMetricsPhp\Exposition\Text\Types\MetricName; @@ -45,4 +44,4 @@ Counter::fromValueAndTimestamp( 8, time() )->withLabelCollection( $labels ) ); -HttpResponse::fromMetricCollections( $counters )->respond(); \ No newline at end of file +echo $counters->getMetricsString(); \ No newline at end of file diff --git a/examples/gauges.php b/examples/gauges.php index 5b5b539..6b9d716 100644 --- a/examples/gauges.php +++ b/examples/gauges.php @@ -4,7 +4,6 @@ use OpenMetricsPhp\Exposition\Text\Collections\GaugeCollection; use OpenMetricsPhp\Exposition\Text\Collections\LabelCollection; -use OpenMetricsPhp\Exposition\Text\HttpResponse; use OpenMetricsPhp\Exposition\Text\Metrics\Gauge; use OpenMetricsPhp\Exposition\Text\Types\Label; use OpenMetricsPhp\Exposition\Text\Types\MetricName; @@ -42,4 +41,4 @@ Gauge::fromValueAndTimestamp( 23.4, time() )->withLabelCollection( $labels ) ); -HttpResponse::fromMetricCollections( $gauges )->respond(); \ No newline at end of file +echo $gauges->getMetricsString(); \ No newline at end of file diff --git a/examples/histogram.php b/examples/histogram.php index 7a8f8b3..3d82787 100644 --- a/examples/histogram.php +++ b/examples/histogram.php @@ -3,7 +3,6 @@ namespace YourVendor\YourProject; use OpenMetricsPhp\Exposition\Text\Collections\GaugeCollection; -use OpenMetricsPhp\Exposition\Text\HttpResponse; use OpenMetricsPhp\Exposition\Text\Metrics\Gauge; use OpenMetricsPhp\Exposition\Text\Metrics\Histogram; use OpenMetricsPhp\Exposition\Text\Types\MetricName; @@ -23,4 +22,4 @@ $histogram = Histogram::fromGaugeCollectionWithBounds( $gauges, [30, 46, 78.9, 90], '_histogram' ) ->withHelp( 'Explanation of the histogram' ); -HttpResponse::fromMetricCollections( $histogram )->respond(); \ No newline at end of file +echo $histogram->getMetricsString(); \ No newline at end of file diff --git a/examples/summary.php b/examples/summary.php index 1cf32f8..da54568 100644 --- a/examples/summary.php +++ b/examples/summary.php @@ -3,7 +3,6 @@ namespace YourVendor\YourProject; use OpenMetricsPhp\Exposition\Text\Collections\GaugeCollection; -use OpenMetricsPhp\Exposition\Text\HttpResponse; use OpenMetricsPhp\Exposition\Text\Metrics\Gauge; use OpenMetricsPhp\Exposition\Text\Metrics\Summary; use OpenMetricsPhp\Exposition\Text\Types\MetricName; @@ -23,4 +22,4 @@ $summary = Summary::fromGaugeCollectionWithQuantiles( $gauges, [0.3, 0.5, 0.75, 0.9], '_summary' ) ->withHelp( 'Explanation of the summary' ); -HttpResponse::fromMetricCollections( $summary )->respond(); \ No newline at end of file +echo $summary->getMetricsString(); \ No newline at end of file diff --git a/src/HttpResponse.php b/src/HttpResponse.php deleted file mode 100644 index 70afefe..0000000 --- a/src/HttpResponse.php +++ /dev/null @@ -1,179 +0,0 @@ -> */ - private $headers; - - /** @var int */ - private $statusCode; - - /** @var string */ - private $reasonPhrase; - - /** @var StreamInterface */ - private $body; - - private function __construct( StreamInterface $body ) - { - $this->protocolVersion = '1.1'; - $this->headers = ['Content-Type' => ['application/openmetrics-text; charset=utf-8']]; - $this->statusCode = 200; - $this->reasonPhrase = 'OK'; - $this->body = $body; - } - - /** - * @param ProvidesMetricLines $collection - * @param ProvidesMetricLines ...$collections - * - * @throws Exceptions\InvalidArgumentException - * @throws Exceptions\RuntimeException - * @return HttpResponse - */ - public static function fromMetricCollections( - ProvidesMetricLines $collection, - ProvidesMetricLines ...$collections - ) : self - { - $outputStream = new OutputStream( 'php://temp', 'w+b' ); - - foreach ( self::getAllMetricLines( $collection, ...$collections ) as $line ) - { - $outputStream->write( $line . "\n" ); - } - - return new self( $outputStream ); - } - - /** - * @param ProvidesMetricLines $collection - * @param ProvidesMetricLines ...$collections - * - * @return Traversable - */ - private static function getAllMetricLines( - ProvidesMetricLines $collection, - ProvidesMetricLines ...$collections - ) : Traversable - { - yield from $collection->getMetricLines(); - foreach ( $collections as $loopCollection ) - { - yield from $loopCollection->getMetricLines(); - } - } - - public function getProtocolVersion() : string - { - return $this->protocolVersion; - } - - public function withProtocolVersion( $version ) : self - { - $response = clone $this; - $response->protocolVersion = (string)$version; - - return $response; - } - - public function getHeaders() : array - { - return $this->headers; - } - - public function hasHeader( $name ) : bool - { - return isset( $this->headers[ (string)$name ] ); - } - - public function getHeader( $name ) : array - { - return $this->headers[ (string)$name ] ?? []; - } - - public function getHeaderLine( $name ) : string - { - if ( $this->hasHeader( $name ) ) - { - return implode( ',', $this->getHeader( $name ) ); - } - - return ''; - } - - public function withHeader( $name, $value ) - { - $this->headers[ $name ] = !is_array( $value ) ? [$value] : $value; - - return $this; - } - - public function withAddedHeader( $name, $value ) : self - { - return (clone $this)->withHeader( $name, $value ); - } - - public function withoutHeader( $name ) : self - { - $response = clone $this; - unset( $response->headers[ (string)$name ] ); - - return $response; - } - - public function getBody() : StreamInterface - { - return $this->body; - } - - public function withBody( StreamInterface $body ) : self - { - $response = clone $this; - $response->body = $body; - - return $response; - } - - public function getStatusCode() : int - { - return $this->statusCode; - } - - public function withStatus( $code, $reasonPhrase = '' ) : self - { - $response = clone $this; - $response->statusCode = $code; - $response->reasonPhrase = $reasonPhrase; - - return $response; - } - - public function getReasonPhrase() : string - { - return $this->reasonPhrase; - } - - public function respond() : void - { - foreach ( array_keys( $this->headers ) as $name ) - { - header( $name . ': ' . $this->getHeaderLine( $name ), true, $this->statusCode ); - } - - echo $this->body; - flush(); - } -} \ No newline at end of file diff --git a/src/HttpResponse/OutputStream.php b/src/HttpResponse/OutputStream.php deleted file mode 100644 index dd597ab..0000000 --- a/src/HttpResponse/OutputStream.php +++ /dev/null @@ -1,337 +0,0 @@ -resource = $stream; - - return; - } - - if ( is_string( $stream ) ) - { - set_error_handler( - static function () - { - throw new InvalidArgumentException( - 'Invalid file provided for stream; must be a valid path with valid permissions' - ); - }, - E_WARNING - ); - - try - { - $this->resource = fopen( $stream, $mode ); - } - finally - { - restore_error_handler(); - } - - return; - } - - throw new InvalidArgumentException( - 'Invalid stream provided; must be a string stream identifier or stream resource' - ); - } - - /** - * @return string - */ - public function __toString() : string - { - if ( !$this->isReadable() ) - { - return ''; - } - - try - { - $this->rewind(); - - return $this->getContents(); - } - catch ( RuntimeException $e ) - { - return ''; - } - } - - public function close() : void - { - if ( !$this->resource ) - { - return; - } - - $resource = $this->detach(); - - if ( is_resource( $resource ) ) - { - fclose( $resource ); - } - } - - /** - * @return bool|false|null|resource - */ - public function detach() - { - $resource = $this->resource; - $this->resource = null; - - return $resource; - } - - /** - * @return int|null - */ - public function getSize() : ?int - { - if ( !is_resource( $this->resource ) ) - { - return null; - } - - $stats = fstat( $this->resource ); - - return $stats !== false ? $stats['size'] : 0; - } - - /** - * @return int - * @throws RuntimeException - */ - public function tell() : int - { - if ( !$this->resource ) - { - throw new RuntimeException( 'No resource available; cannot tell position' ); - } - - $result = ftell( $this->resource ); - - if ( !is_int( $result ) ) - { - throw new RuntimeException( 'Error occurred during tell operation' ); - } - - return $result; - } - - /** - * @return bool - */ - public function eof() : bool - { - if ( !$this->resource ) - { - return true; - } - - return feof( $this->resource ); - } - - /** - * @return bool - */ - public function isSeekable() : bool - { - if ( !$this->resource ) - { - return false; - } - - $meta = stream_get_meta_data( $this->resource ); - - return (bool)$meta['seekable']; - } - - /** - * @param int $offset - * @param int $whence - * - * @return bool - * @throws RuntimeException - */ - public function seek( $offset, $whence = SEEK_SET ) : bool - { - if ( !$this->resource ) - { - throw new RuntimeException( 'No resource available; cannot seek position' ); - } - - if ( !$this->isSeekable() ) - { - throw new RuntimeException( 'Stream is not seekable' ); - } - - $result = fseek( $this->resource, $offset, $whence ); - - if ( 0 !== $result ) - { - throw new RuntimeException( 'Error seeking within stream' ); - } - - return true; - } - - /** - * @return bool - * @throws RuntimeException - */ - public function rewind() : bool - { - return $this->seek( 0 ); - } - - /** - * @return bool - */ - public function isWritable() : bool - { - if ( !$this->resource ) - { - return false; - } - - $meta = stream_get_meta_data( $this->resource ); - - return is_writable( $meta['uri'] ); - } - - /** - * @param string $string - * - * @return bool|int - * @throws RuntimeException - */ - public function write( $string ) - { - if ( !$this->resource ) - { - throw new RuntimeException( 'No resource available; cannot write' ); - } - - $result = fwrite( $this->resource, $string ); - - if ( false === $result ) - { - throw new RuntimeException( 'Error writing to stream' ); - } - - return $result; - } - - /** - * @return bool - */ - public function isReadable() : bool - { - if ( !$this->resource ) - { - return false; - } - - $meta = stream_get_meta_data( $this->resource ); - $mode = $meta['mode']; - - return (false !== strpos( $mode, 'r' ) || false !== strpos( $mode, '+' )); - } - - /** - * @param int $length - * - * @return string - * @throws RuntimeException - */ - public function read( $length ) : string - { - if ( !$this->resource ) - { - throw new RuntimeException( 'No resource available; cannot read' ); - } - - if ( !$this->isReadable() ) - { - throw new RuntimeException( 'Stream is not readable' ); - } - - $result = fread( $this->resource, $length ); - - if ( false === $result ) - { - throw new RuntimeException( 'Error reading stream' ); - } - - return $result; - } - - /** - * @return string - * @throws RuntimeException - */ - public function getContents() : string - { - if ( !is_resource( $this->resource ) || !$this->isReadable() ) - { - return ''; - } - - $result = stream_get_contents( $this->resource ); - - if ( false === $result ) - { - throw new RuntimeException( 'Error reading from stream' ); - } - - return $result; - } - - /** - * @param null|string $key - * - * @return array|mixed|null - */ - public function getMetadata( ?string $key = null ) - { - if ( !is_resource( $this->resource ) ) - { - return null; - } - - if ( null === $key ) - { - return stream_get_meta_data( $this->resource ); - } - - $metadata = stream_get_meta_data( $this->resource ); - - return $metadata[ $key ] ?? null; - } -} diff --git a/tests/Unit/HttpResponse/OutputStreamTest.php b/tests/Unit/HttpResponse/OutputStreamTest.php deleted file mode 100644 index 226980c..0000000 --- a/tests/Unit/HttpResponse/OutputStreamTest.php +++ /dev/null @@ -1,438 +0,0 @@ -write( 'Unit-Test' ); - $stream->rewind(); - - $this->assertSame( 'Unit-Test', $stream->read( 1024 ) ); - - $stream->close(); - } - - /** - * @throws InvalidArgumentException - * @throws RuntimeException - */ - public function testReadThrowsExceptionWhenNoResourceIsAvailable() : void - { - $stream = new OutputStream( 'php://memory', 'w+b' ); - $stream->close(); - - $this->expectException( RuntimeException::class ); - $this->expectExceptionMessage( 'No resource available; cannot read' ); - - /** @noinspection UnusedFunctionResultInspection */ - $stream->read( 1 ); - } - - /** - * @throws InvalidArgumentException - * @throws RuntimeException - */ - public function testReadThrowsExceptionForNonReadableStreams() : void - { - $nonReadableStream = new OutputStream( 'php://output', 'wb' ); - - $this->expectException( RuntimeException::class ); - $this->expectExceptionMessage( 'Stream is not readable' ); - - /** @noinspection UnusedFunctionResultInspection */ - $nonReadableStream->read( 1 ); - } - - /** - * @throws RuntimeException - * @throws InvalidArgumentException - * @throws ExpectationFailedException - * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException - */ - public function testSeek() : void - { - $stream = new OutputStream( 'php://memory', 'w+b' ); - $stream->write( 'Unit-Test' ); - $stream->seek( 5 ); - - $this->assertSame( 'Test', $stream->read( 1024 ) ); - } - - /** - * @throws InvalidArgumentException - * @throws RuntimeException - */ - public function testSeekThrowsExceptionIfNoResourceIsAvailable() : void - { - $stream = new OutputStream( 'php://memory', 'w+b' ); - $stream->close(); - - $this->expectException( RuntimeException::class ); - $this->expectExceptionMessage( 'No resource available; cannot seek position' ); - - $stream->seek( 0 ); - } - - /** - * @throws InvalidArgumentException - * @throws RuntimeException - */ - public function testSeekThrowsExceptionForNonSeekableStreams() : void - { - $stream = new OutputStream( 'php://output', 'wb' ); - - $this->expectException( RuntimeException::class ); - $this->expectExceptionMessage( 'Stream is not seekable' ); - - $stream->seek( 1 ); - } - - /** - * @throws InvalidArgumentException - * @throws ExpectationFailedException - * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException - * @throws RuntimeException - */ - public function testGetSize() : void - { - $stream = new OutputStream( 'php://memory', 'w+b' ); - $stream->write( 'Unit-Test' ); - - $this->assertSame( 9, $stream->getSize() ); - - $stream->close(); - - $this->assertNull( $stream->getSize() ); - } - - /** - * @throws \InvalidArgumentException - * @throws ExpectationFailedException - * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException - */ - public function testGetMetadata() : void - { - $stream = new OutputStream( 'php://memory', 'w+b' ); - - $expectedMetaData = [ - 'eof' => false, - 'unread_bytes' => 0, - 'seekable' => true, - 'uri' => 'php://memory', - 'timed_out' => false, - 'blocked' => true, - 'wrapper_type' => 'PHP', - 'stream_type' => 'MEMORY', - 'mode' => 'w+b', - ]; - - $this->assertEquals( $expectedMetaData, $stream->getMetadata() ); - $this->assertSame( 'PHP', $stream->getMetadata( 'wrapper_type' ) ); - $this->assertNull( $stream->getMetadata( 'no-meta-data-key' ) ); - - $stream->close(); - - $this->assertNull( $stream->getMetadata() ); - } - - /** - * @throws \InvalidArgumentException - * @throws ExpectationFailedException - * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException - * @throws RuntimeException - */ - public function test__toString() : void - { - $stream = new OutputStream( 'php://memory', 'w+b' ); - $stream->write( 'Unit-Test' ); - - $this->assertSame( 'Unit-Test', (string)$stream ); - $this->assertSame( 'Unit-Test', $stream->__toString() ); - - $nonReadableStream = new OutputStream( 'php://stdout', 'wb' ); - $nonReadableStream->write( 'Unit-Test' ); - - $this->assertSame( '', (string)$nonReadableStream ); - $this->assertSame( '', $nonReadableStream->__toString() ); - } - - /** - * @throws \InvalidArgumentException - * @throws ExpectationFailedException - * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException - * @throws RuntimeException - */ - public function testEof() : void - { - $stream = new OutputStream( 'php://memory', 'w+b' ); - $stream->write( 'Unit-Test' ); - $stream->rewind(); - - $this->assertFalse( $stream->eof() ); - - while ( !$stream->eof() ) - { - $stream->read( 11 ); - } - - $this->assertTrue( $stream->eof() ); - - $stream->close(); - - $this->assertTrue( $stream->eof() ); - } - - /** - * @throws \InvalidArgumentException - * @throws ExpectationFailedException - * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException - */ - public function testIsWritable() : void - { - $tempFile = tempnam( sys_get_temp_dir(), 'Unit-Test-OutputStream-' ); - $writableStream = new OutputStream( $tempFile, 'w+b' ); - - $this->assertTrue( $writableStream->isWritable() ); - - $writableStream->close(); - - $this->assertFalse( $writableStream->isWritable() ); - - $nonWritableStream = new OutputStream( 'php://input', 'rb' ); - - $this->assertFalse( $nonWritableStream->isWritable() ); - - @unlink( $tempFile ); - } - - /** - * @throws \InvalidArgumentException - * @throws ExpectationFailedException - * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException - * @throws RuntimeException - */ - public function testRewind() : void - { - $stream = new OutputStream( 'php://memory', 'w+b' ); - $stream->write( 'Unit-Test' ); - - $this->assertSame( 9, $stream->tell() ); - - $stream->rewind(); - - $this->assertSame( 0, $stream->tell() ); - } - - /** - * @throws \InvalidArgumentException - * @throws ExpectationFailedException - * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException - */ - public function testClose() : void - { - $stream = new OutputStream( 'php://memory', 'w+b' ); - $stream->close(); - - $this->assertNull( $stream->detach() ); - - $stream->close(); - - $this->assertNull( $stream->detach() ); - } - - /** - * @throws \InvalidArgumentException - * @throws ExpectationFailedException - * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException - * @throws RuntimeException - */ - public function testTell() : void - { - $stream = new OutputStream( 'php://memory', 'w+b' ); - $stream->write( 'Unit-Test' ); - - $this->assertSame( 9, $stream->tell() ); - - $stream->seek( 3 ); - - $this->assertSame( 3, $stream->tell() ); - } - - /** - * @throws InvalidArgumentException - * @throws RuntimeException - */ - public function testTellThrowsExceptionIfNoResourceIsAvailable() : void - { - $stream = new OutputStream( 'php://memory', 'w+b' ); - $stream->close(); - - $this->expectException( RuntimeException::class ); - $this->expectExceptionMessage( 'No resource available; cannot tell position' ); - - $stream->tell(); - } - - /** - * @throws \InvalidArgumentException - * @throws ExpectationFailedException - * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException - * @throws RuntimeException - */ - public function testDetach() : void - { - $stream = new OutputStream( 'php://memory', 'w+b' ); - $stream->write( 'Unit-Test' ); - - $resource = $stream->detach(); - - $this->assertIsResource( $resource ); - - $this->assertNull( $stream->detach() ); - } - - /** - * @throws \InvalidArgumentException - * @throws ExpectationFailedException - * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException - * @throws RuntimeException - */ - public function testGetContents() : void - { - $stream = new OutputStream( 'php://memory', 'w+b' ); - $stream->write( 'Unit-Test' ); - - $stream->seek( 5 ); - - $this->assertSame( 'Test', $stream->getContents() ); - - $stream->rewind(); - - $this->assertSame( 'Unit-Test', $stream->getContents() ); - - $stream->close(); - - $this->assertSame( '', $stream->getContents() ); - } - - /** - * @throws \InvalidArgumentException - * @throws ExpectationFailedException - * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException - */ - public function testIsReadable() : void - { - $readableStream = new OutputStream( 'php://memory', 'w+b' ); - - $this->assertTrue( $readableStream->isReadable() ); - - $readableStream->close(); - - $this->assertFalse( $readableStream->isReadable() ); - - $nonReadableStream = new OutputStream( 'php://output', 'wb' ); - - $this->assertFalse( $nonReadableStream->isReadable() ); - } - - /** - * @throws \InvalidArgumentException - * @throws ExpectationFailedException - * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException - * @throws RuntimeException - */ - public function testWrite() : void - { - $stream = new OutputStream( 'php://memory', 'w+b' ); - - $this->assertSame( 9, $stream->write( 'Unit-Test' ) ); - } - - /** - * @throws InvalidArgumentException - * @throws RuntimeException - */ - public function testWriteThrowsExceptionIfNoResourceIsAvailable() : void - { - $stream = new OutputStream( 'php://memory', 'w+b' ); - $stream->close(); - - $this->expectException( RuntimeException::class ); - $this->expectExceptionMessage( 'No resource available; cannot write' ); - - $stream->write( 'Unit-Test' ); - } - - /** - * @throws \InvalidArgumentException - * @throws ExpectationFailedException - * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException - */ - public function testIsSeekable() : void - { - $seekableStream = new OutputStream( 'php://input', 'rb' ); - - $this->assertTrue( $seekableStream->isSeekable() ); - - $seekableStream->close(); - - $this->assertFalse( $seekableStream->isSeekable() ); - } - - /** - * @throws \InvalidArgumentException - * @throws ExpectationFailedException - * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException - */ - public function testCanConstructStreamFromResource() : void - { - $resource = fopen( 'php://memory', 'w+b' ); - $stream = new OutputStream( $resource ); - - $this->assertSame( $resource, $stream->detach() ); - } - - /** - * @throws InvalidArgumentException - */ - public function testThrowsExceptionForInvalidStream() : void - { - $this->expectException( InvalidArgumentException::class ); - $this->expectExceptionMessage( - 'Invalid file provided for stream; must be a valid path with valid permissions' - ); - - new OutputStream( 'file:///does/not/exist' ); - } - - /** - * @throws InvalidArgumentException - */ - public function testThrowsExceptionForInvalidStreamType() : void - { - $this->expectException( InvalidArgumentException::class ); - $this->expectExceptionMessage( - 'Invalid stream provided; must be a string stream identifier or stream resource' - ); - - /** @noinspection PhpParamsInspection */ - new OutputStream( ['stream'] ); - } -} diff --git a/tests/Unit/HttpResponseTest.php b/tests/Unit/HttpResponseTest.php deleted file mode 100644 index 022ebb2..0000000 --- a/tests/Unit/HttpResponseTest.php +++ /dev/null @@ -1,201 +0,0 @@ -getExampleGaugeCollection(); - $counterCollection = $this->getExampleCounterCollection(); - - $expectedOutput = "# TYPE unit_test_gauges gauge\n"; - $expectedOutput .= "# HELP unit_test_gauges Test gauges\n"; - $expectedOutput .= "unit_test_gauges 12.300000\n"; - $expectedOutput .= "unit_test_gauges 45.600000\n"; - $expectedOutput .= "unit_test_gauges 78.900000\n"; - $expectedOutput .= "# TYPE unit_test_counters counter\n"; - $expectedOutput .= "# HELP unit_test_counters Test counters\n"; - $expectedOutput .= "unit_test_counters_total 12.300000\n"; - $expectedOutput .= "unit_test_counters_total 45.600000\n"; - $expectedOutput .= "unit_test_counters_total 78.900000\n"; - - $this->expectOutputString( $expectedOutput ); - - HttpResponse::fromMetricCollections( $gaugeCollection, $counterCollection )->respond(); - - /** @noinspection ForgottenDebugOutputInspection */ - $this->assertContains( 'Content-Type: application/openmetrics-text; charset=utf-8', xdebug_get_headers() ); - } - - /** - * @throws InvalidArgumentException - * @return GaugeCollection - */ - private function getExampleGaugeCollection() : GaugeCollection - { - return GaugeCollection::fromGauges( - MetricName::fromString( 'unit_test_gauges' ), - Gauge::fromValue( 12.3 ), - Gauge::fromValue( 45.6 ), - Gauge::fromValue( 78.9 ) - )->withHelp( - 'Test gauges' - ); - } - - /** - * @throws InvalidArgumentException - * @return CounterCollection - */ - private function getExampleCounterCollection() : CounterCollection - { - return CounterCollection::fromCounters( - MetricName::fromString( 'unit_test_counters' ), - Counter::fromValue( 12.3 ), - Counter::fromValue( 45.6 ), - Counter::fromValue( 78.9 ) - )->withHelp( - 'Test counters' - ); - } - - /** - * @throws InvalidArgumentException - * @throws \InvalidArgumentException - * @throws \PHPUnit\Framework\ExpectationFailedException - * @throws \RuntimeException - * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException - */ - public function testCanGetInstanceWithAddedHeader() : void - { - $response = HttpResponse::fromMetricCollections( $this->getExampleCounterCollection() ); - $withAddedHeader = $response->withAddedHeader( 'X-Test', 'Unit' ); - - $this->assertNotSame( $withAddedHeader, $response ); - $this->assertCount( 2, $withAddedHeader->getHeaders() ); - $this->assertCount( 1, $response->getHeaders() ); - } - - /** - * @throws InvalidArgumentException - * @throws \InvalidArgumentException - * @throws \OpenMetricsPhp\Exposition\Text\Exceptions\RuntimeException - * @throws \PHPUnit\Framework\ExpectationFailedException - * @throws \RuntimeException - * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException - */ - public function testCanGetInstanceWithBody() : void - { - $stream = new HttpResponse\OutputStream( 'php://memory', 'w+b' ); - $stream->write( 'Unit-Test' ); - - $response = HttpResponse::fromMetricCollections( $this->getExampleCounterCollection() ); - $withBody = $response->withBody( $stream ); - - $this->assertNotSame( $withBody, $response ); - $this->assertNotSame( $withBody->getBody(), $response->getBody() ); - $this->assertSame( 9, $withBody->getBody()->getSize() ); - $this->assertSame( 179, $response->getBody()->getSize() ); - } - - /** - * @throws InvalidArgumentException - * @throws \InvalidArgumentException - * @throws \PHPUnit\Framework\ExpectationFailedException - * @throws \RuntimeException - * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException - */ - public function testCanGetInstanceWithProtocolVersion() : void - { - $response = HttpResponse::fromMetricCollections( $this->getExampleCounterCollection() ); - $withProtocolVersion = $response->withProtocolVersion( '1.0' ); - - $this->assertNotSame( $response, $withProtocolVersion ); - $this->assertSame( '1.0', $withProtocolVersion->getProtocolVersion() ); - $this->assertSame( '1.1', $response->getProtocolVersion() ); - } - - /** - * @throws InvalidArgumentException - * @throws \InvalidArgumentException - * @throws \PHPUnit\Framework\ExpectationFailedException - * @throws \RuntimeException - * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException - */ - public function testCanGetInstanceWithoutHeader() : void - { - $response = HttpResponse::fromMetricCollections( $this->getExampleCounterCollection() ); - $withoutHeader = $response->withoutHeader( 'Content-Type' ); - - $this->assertNotSame( $withoutHeader, $response ); - $this->assertCount( 0, $withoutHeader->getHeaders() ); - $this->assertCount( 1, $response->getHeaders() ); - } - - /** - * @throws InvalidArgumentException - * @throws \InvalidArgumentException - * @throws \PHPUnit\Framework\ExpectationFailedException - * @throws \RuntimeException - * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException - */ - public function testCanGetInstanceWithStatus() : void - { - $response = HttpResponse::fromMetricCollections( $this->getExampleCounterCollection() ); - $withStatus = $response->withStatus( 500, 'Internal Server Error' ); - - $this->assertNotSame( $withStatus, $response ); - $this->assertSame( 500, $withStatus->getStatusCode() ); - $this->assertSame( 'Internal Server Error', $withStatus->getReasonPhrase() ); - $this->assertSame( 200, $response->getStatusCode() ); - $this->assertSame( 'OK', $response->getReasonPhrase() ); - } - - /** - * @throws InvalidArgumentException - * @throws \InvalidArgumentException - * @throws \PHPUnit\Framework\ExpectationFailedException - * @throws \RuntimeException - * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException - */ - public function testCanGetDefaultValues() : void - { - $response = HttpResponse::fromMetricCollections( - $this->getExampleCounterCollection(), - $this->getExampleGaugeCollection() - ); - - $this->assertSame( - ['Content-Type' => ['application/openmetrics-text; charset=utf-8']], - $response->getHeaders() - ); - - $this->assertSame( '1.1', $response->getProtocolVersion() ); - $this->assertSame( 'OK', $response->getReasonPhrase() ); - $this->assertSame( 200, $response->getStatusCode() ); - $this->assertSame( - 'application/openmetrics-text; charset=utf-8', - $response->getHeaderLine( 'Content-Type' ) - ); - $this->assertSame( '', $response->getHeaderLine( 'Not-existing-key' ) ); - $this->assertTrue( $response->hasHeader( 'Content-Type' ) ); - } -}