diff --git a/.github/workflows/test.Dockerfile b/.github/workflows/test.Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..a7acaf1e821c211ad0f0ee45ab06729ebabcccdc --- /dev/null +++ b/.github/workflows/test.Dockerfile @@ -0,0 +1,18 @@ +ARG PHP_VERSION=latest +FROM php:${PHP_VERSION}-cli-alpine + +WORKDIR /workdir + +# install composer +RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer +ENV COMPOSER_ALLOW_SUPERUSER=1 +ENV COMPOSER_HTACCESS_PROTECT=0 +ENV COMPOSER_CACHE_DIR=/.composer + +# install PHP extension pcov +RUN apk add --no-cache --virtual .build-deps $PHPIZE_DEPS \ + && mkdir -p /usr/src/php/ext/pcov && curl -fsSL https://pecl.php.net/get/pcov | tar xvz -C /usr/src/php/ext/pcov --strip 1 \ + && docker-php-ext-install pcov \ + && docker-php-ext-enable pcov \ + && rm -Rf /usr/src/php/ext/pcov \ + && apk del --no-cache .build-deps diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000000000000000000000000000000000000..cbb4248f5c42b6931261996abdf0f942f8255c43 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,105 @@ +name: Test + +on: + pull_request: + push: + branches: + - master + - '[0-9]+.x' + +jobs: + php: + runs-on: ubuntu-latest + strategy: + matrix: + include: + - PHP_VERSION: 7.1 + CODE_COVERAGE: false + RUN_PHPSTAN: false + RUN_PSALM: false + RUN_BENCHMARK: false + - PHP_VERSION: 7.2 + CODE_COVERAGE: true + RUN_PHPSTAN: false + RUN_PSALM: false + RUN_BENCHMARK: false + - PHP_VERSION: 7.3 + CODE_COVERAGE: true + RUN_PHPSTAN: false + RUN_PSALM: false + RUN_BENCHMARK: false + - PHP_VERSION: 7.4 + CODE_COVERAGE: true + RUN_PHPSTAN: true + RUN_PSALM: true + RUN_BENCHMARK: true + - PHP_VERSION: 8.0-rc + CODE_COVERAGE: true + RUN_PHPSTAN: true + RUN_PSALM: true + RUN_BENCHMARK: true + COMPOSER_EXTRA_ARGS: --ignore-platform-reqs + + steps: + - uses: actions/checkout@v2 + + - name: Cache Docker Image + id: cache-docker-image + uses: actions/cache@v2 + with: + path: /tmp/docker-image.tar + key: cache-docker-image-test:${{ matrix.PHP_VERSION }} + + - name: Load Docker Image + if: steps.cache-docker-image.outputs.cache-hit == 'true' + run: docker load --input /tmp/docker-image.tar + + - name: Build Docker Image + if: steps.cache-docker-image.outputs.cache-hit != 'true' + run: docker build -f .github/workflows/test.Dockerfile -t 'test:${{ matrix.PHP_VERSION }}' --build-arg 'PHP_VERSION=${{ matrix.PHP_VERSION }}' . + + - name: Cache Composer Cache Files + uses: actions/cache@v2 + with: + path: /tmp/composer-cache-files + key: cache-composer-cache-files-${{ matrix.PHP_VERSION }} + restore-keys: | + cache-composer-cache-files- + + - name: Install Composer Dependencies + run: | + if [ "${{ matrix.RUN_PHPSTAN }}" != "true" ]; then composer remove --dev phpstan/phpstan --no-update --no-interaction; fi + if [ "${{ matrix.RUN_PSALM }}" != "true" ]; then composer remove --dev vimeo/psalm --no-update --no-interaction; fi + if [ "${{ matrix.RUN_BENCHMARK }}" != "true" ]; then composer remove --dev phpbench/phpbench --no-update --no-interaction; fi + docker run --rm -u "$(id -u):$(id -g)" -v "$(pwd):/workdir" -v '/tmp/composer-cache-files:/.composer' 'test:${{ matrix.PHP_VERSION }}' composer install --no-interaction --no-progress --prefer-dist ${{ matrix.COMPOSER_EXTRA_ARGS }} + + - name: Run Unit Test + run: | + if [ "${{ matrix.CODE_COVERAGE }}" == "true" ]; then + docker run --rm -u "$(id -u):$(id -g)" -v "$(pwd):/workdir" 'test:${{ matrix.PHP_VERSION }}' php -d 'zend.assertions=1' -d 'pcov.enabled=1' ./vendor/bin/phpunit --coverage-clover=.clover.xml + else + docker run --rm -u "$(id -u):$(id -g)" -v "$(pwd):/workdir" 'test:${{ matrix.PHP_VERSION }}' php -d 'zend.assertions=1' ./vendor/bin/phpunit + fi + + - name: Upload Codecov Report + uses: codecov/codecov-action@v1 + if: ${{ matrix.CODE_COVERAGE }} + with: + token: ${{ secrets.CODECOV_TOKEN }} + file: .clover.xml + + - name: Run PHPStan + if: ${{ matrix.RUN_PHPSTAN }} + run: docker run --rm -u "$(id -u):$(id -g)" -v "$(pwd):/workdir" 'test:${{ matrix.PHP_VERSION }}' php -d 'memory_limit=2G' ./vendor/bin/phpstan analyse --level max src/ tests/ + + - name: Run psalm + if: ${{ matrix.RUN_PSALM }} + run: mkdir -p "$HOME/.cache/psalm" && docker run --rm -u "$(id -u):$(id -g)" -v "$(pwd):/workdir" -v "$HOME/.cache/psalm:/.cache/psalm" 'test:${{ matrix.PHP_VERSION }}' php ./vendor/bin/psalm + + - name: Run benchmark + if: ${{ matrix.RUN_BENCHMARK }} + run: docker run --rm -u "$(id -u):$(id -g)" -v "$(pwd):/workdir" 'test:${{ matrix.PHP_VERSION }}' php -d 'zend.assertions=-1' ./vendor/bin/phpbench run --no-interaction --revs=1 --retry-threshold=100 --progress=travis + + - name: Export Docker Image + if: steps.cache-docker-image.outputs.cache-hit != 'true' + run: docker save --output /tmp/docker-image.tar 'test:${{ matrix.PHP_VERSION }}' diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index fb23a5d3ecf1b529d9ccb8a998a4c14ebaec42db..0000000000000000000000000000000000000000 --- a/.travis.yml +++ /dev/null @@ -1,83 +0,0 @@ -sudo: false -language: php - -cache: - directories: - - $HOME/.composer/cache - - $HOME/.local - - $HOME/ocular.phar - - $HOME/phpDocumentor.phar - -env: - global: - - CODE_COVERAGE="0" - - PHPDOC="0" - -matrix: - fast_finish: true - include: - - php: 7.1 - env: - - CODE_COVERAGE="1" - - BENCHMARK="0" - - php: 7.2 - env: - - CODE_COVERAGE="1" - - BENCHMARK="0" - - php: 7.3 - env: - - CODE_COVERAGE="1" - - BENCHMARK="1" - - php: 7.4 - env: - - CODE_COVERAGE="1" - - BENCHMARK="1" - - php: nightly - env: - - CODE_COVERAGE="0" - - BENCHMARK="0" - - IGNORE_PLATFORM_REQS="1" - allow_failures: - - php: nightly - -install: - - if [ "${CODE_COVERAGE}" == "0" ]; then - phpenv config-rm xdebug.ini || return 0; - fi - - if [ "${CODE_COVERAGE}" == "1" ]; then - wget -q -N -t 3 --retry-connrefused 'https://scrutinizer-ci.com/ocular.phar' || return 0; - fi - - if [ "${BENCHMARK}" == "0" ]; then - composer remove --dev phpbench/phpbench --no-update; - fi - - if [ "${IGNORE_PLATFORM_REQS}" == "1" ]; then - composer install -n --ignore-platform-reqs; - else - composer install -n; - fi - -script: - - if [ "$CODE_COVERAGE" == "1" ]; then - php -d 'zend.assertions=1' vendor/bin/phpunit --verbose --coverage-text --coverage-clover=coverage.clover; - else - php -d 'zend.assertions=1' vendor/bin/phpunit --verbose; - fi - - # run phpstan - - php vendor/bin/phpstan analyse --level max src/ tests/ - - # run psalm - - php vendor/bin/psalm - - # run benchmarks to make sure they are working fine - - if [ "${BENCHMARK}" == "1" ]; then - php vendor/bin/phpbench run --no-interaction --revs=1 --retry-threshold=100; - fi - -after_script: - - if [ "${CODE_COVERAGE}" == "1" ]; then - php ocular.phar code-coverage:upload --format=php-clover coverage.clover; - fi - -notifications: - email: false diff --git a/README.md b/README.md index aa5fe3d5cedba9f5a5e7a20b1435e866e4c50f80..0fa03ac7ae780a5846ac064b1190e618d683fef4 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,11 @@ # php-enum -[](http://travis-ci.org/marc-mabe/php-enum) -[](https://scrutinizer-ci.com/g/marc-mabe/php-enum/) -[](https://scrutinizer-ci.com/g/marc-mabe/php-enum/) -[](https://packagist.org/packages/marc-mabe/php-enum) +[](https://github.com/marc-mabe/php-enum/actions?query=workflow%3ATest%20branch%3Amaster) +[](https://codecov.io/gh/marc-mabe/php-enum/branch/master/) +[](https://github.com/marc-mabe/php-enum/blob/master/LICENSE.txt) [](https://packagist.org/packages/marc-mabe/php-enum) +[](https://packagist.org/packages/marc-mabe/php-enum) +[](https://packagist.org/packages/marc-mabe/php-enum) +[](https://packagist.org/packages/marc-mabe/php-enum/dependents?order_by=downloads) This is a native PHP implementation to add enumeration support to PHP. It's an abstract class that needs to be extended to use it. diff --git a/src/Enum.php b/src/Enum.php index c9de2ea6a1e9d1b47a1b11e5a08d122d6ba7089e..905724a08fca988797ab69ee6fef386c50e4ea58 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -392,6 +392,8 @@ abstract class Enum $constants = $scopeConstants + $constants; } while (($reflection = $reflection->getParentClass()) && $reflection->name !== __CLASS__); + /** @var array<string, null|bool|int|float|string|array<mixed>> $constants */ + assert( self::noAmbiguousValues($constants), 'Ambiguous enumerator values detected for ' . static::class diff --git a/tests/MabeEnumTest/EnumMapTest.php b/tests/MabeEnumTest/EnumMapTest.php index 21e8311e23e81e1debb42aa8bd4f6be43d5f1cec..c390dcf96097c9a1ddfc0db4d468568a975a3802 100644 --- a/tests/MabeEnumTest/EnumMapTest.php +++ b/tests/MabeEnumTest/EnumMapTest.php @@ -477,10 +477,13 @@ class EnumMapTest extends TestCase public function testIsEmpty(): void { - /** @var array<int, string> $items2 */ - $items2 = array_combine(Enum32::getValues(), Enum32::getNames()); + $makeItems2 = function () { + foreach (Enum32::getEnumerators() as $enumerator) { + yield $enumerator => $enumerator->getName(); + } + }; $map1 = new EnumMap(Enum32::class, []); - $map2 = new EnumMap(Enum32::class, $items2); + $map2 = new EnumMap(Enum32::class, $makeItems2()); $this->assertTrue($map1->isEmpty()); $this->assertFalse($map2->isEmpty());