diff --git a/.github/workflows/Main.yaml b/.github/workflows/Main.yaml new file mode 100644 index 0000000..c831e1b --- /dev/null +++ b/.github/workflows/Main.yaml @@ -0,0 +1,60 @@ +name: PHPUnit +on: [push] +jobs: + PHPUnit-Autobahn: + runs-on: ubuntu-22.04 + strategy: + matrix: + php_version: [ 7.4, 8.0, 8.1, 8.2 ] + buffer_type: [ memory, tmpfile ] + test: [ tests/ClientTest.php, tests/ServerTest.php ] + steps: + # Install PHP + - name: Setup PHP with PECL extension + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php_version }} + extensions: pcntl + # Clone code + - uses: actions/checkout@v3 + # Composer install + - uses: php-actions/composer@v6 + with: + args: --ignore-platform-reqs + # Prepare the environment + - name: Disable xdebug + run: phpenv config-rm xdebug.ini || true + - name: Add docker GPG key to apt + run: curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg + - name: Add docker apt repo + run: echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null + - name: Apt update + run: sudo apt-get update + - name: Install docker + run: sudo apt install docker-ce + # Run PHPUnit + - name: PHPUnit + run: ./vendor/bin/phpunit ${{ matrix.test }} + env: + BUFFERTYPE: ${{ matrix.buffer_type }} + PHPUnit-Other: + runs-on: ubuntu-22.04 + strategy: + matrix: + php_version: [ 7.4, 8.0, 8.1, 8.2 ] + steps: + # Install PHP + - name: Setup PHP with PECL extension + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php_version }} + extensions: pcntl + # Clone code + - uses: actions/checkout@v3 + # Composer install + - uses: php-actions/composer@v6 + with: + args: --ignore-platform-reqs + # Run PHPUnit + - name: PHPUnit + run: ./vendor/bin/phpunit ${{ matrix.test }} diff --git a/.gitignore b/.gitignore index f1e92f1..92cb61d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ -# Created by https://www.toptal.com/developers/gitignore/api/phpstorm,composer,macos,windows -# Edit at https://www.toptal.com/developers/gitignore?templates=phpstorm,composer,macos,windows +# Created by https://www.toptal.com/developers/gitignore/api/macos,windows,composer,phpstorm,phpunit +# Edit at https://www.toptal.com/developers/gitignore?templates=macos,windows,composer,phpstorm,phpunit ### Composer ### composer.phar @@ -18,6 +18,7 @@ composer.phar # Icon must end with two \r Icon + # Thumbnails ._* @@ -37,6 +38,10 @@ Network Trash Folder Temporary Items .apdisk +### macOS Patch ### +# iCloud generated files +*.icloud + ### PhpStorm ### # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 @@ -48,6 +53,9 @@ Temporary Items .idea/**/dictionaries .idea/**/shelf +# AWS User-specific +.idea/**/aws.xml + # Generated files .idea/**/contentModel.xml @@ -98,6 +106,9 @@ atlassian-ide-plugin.xml # Cursive Clojure plugin .idea/replstate.xml +# SonarLint plugin +.idea/sonarlint/ + # Crashlytics plugin (for Android Studio and IntelliJ) com_crashlytics_export_strings.xml crashlytics.properties @@ -140,6 +151,25 @@ fabric.properties # https://plugins.jetbrains.com/plugin/12206-codestream .idea/codestream.xml +# Azure Toolkit for IntelliJ plugin +# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij +.idea/**/azureSettings.xml + +### PHPUnit ### +# Covers PHPUnit +# Reference: https://phpunit.de/ + +# Generated files +.phpunit.result.cache +.phpunit.cache + +# PHPUnit +/app/phpunit.xml +/phpunit.xml + +# Build data +/build/ + ### Windows ### # Windows thumbnail cache files Thumbs.db @@ -166,4 +196,4 @@ $RECYCLE.BIN/ # Windows shortcuts *.lnk -# End of https://www.toptal.com/developers/gitignore/api/phpstorm,composer,macos,windows +# End of https://www.toptal.com/developers/gitignore/api/macos,windows,composer,phpstorm,phpunit diff --git a/.styleci.yml b/.styleci.yml deleted file mode 100644 index 0a5e877..0000000 --- a/.styleci.yml +++ /dev/null @@ -1,28 +0,0 @@ -preset: recommended -risky: true - -enabled: - - concat_with_spaces - - dir_constant - - uppercase_constants - - declare_strict_types - - ternary_to_null_coalescing - - group_import - -disabled: - - symfony_braces - - class_definition - - concat_without_spaces - - declare_equal_normalize - - lowercase_constants - - include - - phpdoc_summary - - no_blank_lines_after_class_opening - - single_class_element_per_statement - - alpha_ordered_imports - - return_type_declaration - - single_import_per_statement - -finder: - name: - - "*.php" diff --git a/.travis.yml b/.travis.yml deleted file mode 100755 index 18dce52..0000000 --- a/.travis.yml +++ /dev/null @@ -1,42 +0,0 @@ -language: php -cache: - directories: - - $HOME/.composer/cache/files - - $HOME/.cache/pip - -php: - - 7.4 - - 8.0 - - 8.1 - - nightly - -env: - - $TESTSCRIPT=tests/ClientTest.php $BUFFERTPE=memory - - $TESTSCRIPT=tests/ClientTest.php $BUFFERTPE=tmpfile - - $TESTSCRIPT=tests/ServerTest.php $BUFFERTPE=memory - - $TESTSCRIPT=tests/ServerTest.php $BUFFERTPE=tmpfile - - $TESTSCRIPT=tests/UpdatesWrapperTest.php - -matrix: - fast_finish: true - allow_failures: - - php: nightly - -before_script: - - sudo apt-get update - - sudo apt-get install python-pip python-virtualenv - - virtualenv ~/wstest - - source ~/wstest/bin/activate - - pip install autobahntestsuite - - phpenv config-rm xdebug.ini || true - - composer install - -script: - - vendor/bin/phpunit $TESTSCRIPT buffertype=$BUFFERTPE - -notifications: - email: - recipients: - - admin@kevinmeijer.nl - on_success: change - on_failure: always diff --git a/Resources/Autobahn/fuzzingclient.json b/Resources/Autobahn/fuzzingclient.json index be52da7..3d77350 100644 --- a/Resources/Autobahn/fuzzingclient.json +++ b/Resources/Autobahn/fuzzingclient.json @@ -1,8 +1,8 @@ { - "outdir": "/tmp/reports/", + "outdir": "/reports/", "servers": [ { - "url": "ws://127.0.0.1:9001" + "url": "ws://host.docker.internal:9001" } ], "cases": ["*"], diff --git a/Resources/Autobahn/fuzzingserver.json b/Resources/Autobahn/fuzzingserver.json index 226528a..acf2efe 100644 --- a/Resources/Autobahn/fuzzingserver.json +++ b/Resources/Autobahn/fuzzingserver.json @@ -1,6 +1,6 @@ { "url": "ws://127.0.0.1:9001", - "outdir": "/tmp/reports/", + "outdir": "/reports/", "cases": ["*"], "exclude-cases": [], "exclude-agent-cases": {} diff --git a/VERSION b/VERSION index ef538c2..ff365e0 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.1.2 +3.1.3 diff --git a/composer.json b/composer.json index 36cb480..1e36c92 100755 --- a/composer.json +++ b/composer.json @@ -14,12 +14,12 @@ } ], "require-dev": { - "phpunit/phpunit": "^9.3", + "phpunit/phpunit": "^9.6", "ext-pcntl": "*", "ext-json": "*" }, "require": { - "php": "^7.3.0 || ^8.0.0", + "php": "^7.4.0 || ^8.0.0", "ext-sockets": "*", "psr/log": "^1.0" }, @@ -45,5 +45,10 @@ "non-feature-branches": [ "develop", "master" - ] + ], + "config": { + "platform": { + "php": "7.4" + } + } } diff --git a/composer.lock b/composer.lock index 87b5a11..2d954af 100644 --- a/composer.lock +++ b/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "8a5e2096fecc6806ba71b467f2f0bc97", + "content-hash": "ad4c5caef932d052d0be7eedbcef0f1b", "packages": [ { "name": "psr/log", - "version": "1.1.3", + "version": "1.1.4", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc" + "reference": "d49695b909c3b7628b6289db5479a1c204601f11" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/0f73288fd15629204f9d42b7055f72dacbe811fc", - "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc", + "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11", "shasum": "" }, "require": { @@ -41,7 +41,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for logging libraries", @@ -52,37 +52,38 @@ "psr-3" ], "support": { - "source": "https://github.com/php-fig/log/tree/1.1.3" + "source": "https://github.com/php-fig/log/tree/1.1.4" }, - "time": "2020-03-23T09:12:05+00:00" + "time": "2021-05-03T11:20:27+00:00" } ], "packages-dev": [ { "name": "doctrine/instantiator", - "version": "1.4.0", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b" + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/d56bf6102915de5702778fe20f2de3b2fe570b5b", - "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^8.0", + "doctrine/coding-standard": "^9 || ^11", "ext-pdo": "*", "ext-phar": "*", - "phpbench/phpbench": "^0.13 || 1.0.0-alpha2", - "phpstan/phpstan": "^0.12", - "phpstan/phpstan-phpunit": "^0.12", - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" + "phpbench/phpbench": "^0.16 || ^1", + "phpstan/phpstan": "^1.4", + "phpstan/phpstan-phpunit": "^1", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.30 || ^5.4" }, "type": "library", "autoload": { @@ -109,7 +110,7 @@ ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.4.0" + "source": "https://github.com/doctrine/instantiator/tree/1.5.0" }, "funding": [ { @@ -125,41 +126,42 @@ "type": "tidelift" } ], - "time": "2020-11-10T18:47:58+00:00" + "time": "2022-12-30T00:15:36+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.10.2", + "version": "1.11.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220" + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/776f831124e9c62e1a2c601ecc52e776d8bb7220", - "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, - "replace": { - "myclabs/deep-copy": "self.version" + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3,<3.2.2" }, "require-dev": { - "doctrine/collections": "^1.0", - "doctrine/common": "^2.6", - "phpunit/phpunit": "^7.1" + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", "autoload": { - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - }, "files": [ "src/DeepCopy/deep_copy.php" - ] + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -175,7 +177,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.10.2" + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" }, "funding": [ { @@ -183,20 +185,20 @@ "type": "tidelift" } ], - "time": "2020-11-13T09:40:50+00:00" + "time": "2023-03-08T13:26:56+00:00" }, { "name": "nikic/php-parser", - "version": "v4.10.2", + "version": "v4.16.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "658f1be311a230e0907f5dfe0213742aff0596de" + "reference": "19526a33fb561ef417e822e85f08a00db4059c17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/658f1be311a230e0907f5dfe0213742aff0596de", - "reference": "658f1be311a230e0907f5dfe0213742aff0596de", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/19526a33fb561ef417e822e85f08a00db4059c17", + "reference": "19526a33fb561ef417e822e85f08a00db4059c17", "shasum": "" }, "require": { @@ -237,22 +239,22 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.10.2" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.16.0" }, - "time": "2020-09-26T10:30:38+00:00" + "time": "2023-06-25T14:52:30+00:00" }, { "name": "phar-io/manifest", - "version": "2.0.1", + "version": "2.0.3", "source": { "type": "git", "url": "https://github.com/phar-io/manifest.git", - "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133" + "reference": "97803eca37d319dfa7826cc2437fc020857acb53" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/85265efd3af7ba3ca4b2a2c34dbfc5788dd29133", - "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53", "shasum": "" }, "require": { @@ -297,22 +299,22 @@ "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", "support": { "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/master" + "source": "https://github.com/phar-io/manifest/tree/2.0.3" }, - "time": "2020-06-27T14:33:11+00:00" + "time": "2021-07-20T11:28:43+00:00" }, { "name": "phar-io/version", - "version": "3.0.2", + "version": "3.2.1", "source": { "type": "git", "url": "https://github.com/phar-io/version.git", - "reference": "c6bb6825def89e0a32220f88337f8ceaf1975fa0" + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/c6bb6825def89e0a32220f88337f8ceaf1975fa0", - "reference": "c6bb6825def89e0a32220f88337f8ceaf1975fa0", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", "shasum": "" }, "require": { @@ -348,261 +350,36 @@ "description": "Library for handling version information and constraints", "support": { "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/master" - }, - "time": "2020-06-27T14:39:04+00:00" - }, - { - "name": "phpdocumentor/reflection-common", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-2.x": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", - "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" - ], - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", - "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" - }, - "time": "2020-06-27T09:03:43+00:00" - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "5.2.2", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/069a785b2141f5bcf49f3e353548dc1cce6df556", - "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556", - "shasum": "" - }, - "require": { - "ext-filter": "*", - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.3", - "webmozart/assert": "^1.9.1" - }, - "require-dev": { - "mockery/mockery": "~1.3.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - }, - { - "name": "Jaap van Otterdijk", - "email": "account@ijaap.nl" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/master" - }, - "time": "2020-09-03T19:13:55+00:00" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "1.4.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", - "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.0" - }, - "require-dev": { - "ext-tokenizer": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-1.x": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "support": { - "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.4.0" - }, - "time": "2020-09-17T18:55:26+00:00" - }, - { - "name": "phpspec/prophecy", - "version": "1.12.1", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "8ce87516be71aae9b956f81906aaf0338e0d8a2d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/8ce87516be71aae9b956f81906aaf0338e0d8a2d", - "reference": "8ce87516be71aae9b956f81906aaf0338e0d8a2d", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.2", - "php": "^7.2 || ~8.0, <8.1", - "phpdocumentor/reflection-docblock": "^5.2", - "sebastian/comparator": "^3.0 || ^4.0", - "sebastian/recursion-context": "^3.0 || ^4.0" - }, - "require-dev": { - "phpspec/phpspec": "^6.0", - "phpunit/phpunit": "^8.0 || ^9.0 <9.3" + "source": "https://github.com/phar-io/version/tree/3.2.1" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.11.x-dev" - } - }, - "autoload": { - "psr-4": { - "Prophecy\\": "src/Prophecy" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - }, - { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" - } - ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", - "keywords": [ - "Double", - "Dummy", - "fake", - "mock", - "spy", - "stub" - ], - "support": { - "issues": "https://github.com/phpspec/prophecy/issues", - "source": "https://github.com/phpspec/prophecy/tree/1.12.1" - }, - "time": "2020-09-29T09:10:42+00:00" + "time": "2022-02-21T01:04:05+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "9.2.4", + "version": "9.2.26", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "0a7f0acf9269c190fd982b5c04423feae986b6e0" + "reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/0a7f0acf9269c190fd982b5c04423feae986b6e0", - "reference": "0a7f0acf9269c190fd982b5c04423feae986b6e0", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/443bc6912c9bd5b409254a40f4b0f4ced7c80ea1", + "reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.10.2", + "nikic/php-parser": "^4.15", "php": ">=7.3", "phpunit/php-file-iterator": "^3.0.3", "phpunit/php-text-template": "^2.0.2", "sebastian/code-unit-reverse-lookup": "^2.0.2", "sebastian/complexity": "^2.0", "sebastian/environment": "^5.1.2", - "sebastian/lines-of-code": "^1.0", + "sebastian/lines-of-code": "^1.0.3", "sebastian/version": "^3.0.1", "theseer/tokenizer": "^1.2.0" }, @@ -610,8 +387,8 @@ "phpunit/phpunit": "^9.3" }, "suggest": { - "ext-pcov": "*", - "ext-xdebug": "*" + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "type": "library", "extra": { @@ -644,7 +421,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.4" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.26" }, "funding": [ { @@ -652,20 +429,20 @@ "type": "github" } ], - "time": "2020-11-27T06:15:15+00:00" + "time": "2023-03-06T12:58:08+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "3.0.5", + "version": "3.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "aa4be8575f26070b100fccb67faabb28f21f66f8" + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/aa4be8575f26070b100fccb67faabb28f21f66f8", - "reference": "aa4be8575f26070b100fccb67faabb28f21f66f8", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", "shasum": "" }, "require": { @@ -704,7 +481,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.5" + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" }, "funding": [ { @@ -712,7 +489,7 @@ "type": "github" } ], - "time": "2020-09-28T05:57:25+00:00" + "time": "2021-12-02T12:48:52+00:00" }, { "name": "phpunit/php-invoker", @@ -897,20 +674,20 @@ }, { "name": "phpunit/phpunit", - "version": "9.4.3", + "version": "9.6.9", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "9fa359ff5ddaa5eb2be2bedb08a6a5787a5807ab" + "reference": "a9aceaf20a682aeacf28d582654a1670d8826778" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/9fa359ff5ddaa5eb2be2bedb08a6a5787a5807ab", - "reference": "9fa359ff5ddaa5eb2be2bedb08a6a5787a5807ab", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a9aceaf20a682aeacf28d582654a1670d8826778", + "reference": "a9aceaf20a682aeacf28d582654a1670d8826778", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.3.1", + "doctrine/instantiator": "^1.3.1 || ^2", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", @@ -918,34 +695,29 @@ "ext-xml": "*", "ext-xmlwriter": "*", "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.1", + "phar-io/manifest": "^2.0.3", "phar-io/version": "^3.0.2", "php": ">=7.3", - "phpspec/prophecy": "^1.12.1", - "phpunit/php-code-coverage": "^9.2", + "phpunit/php-code-coverage": "^9.2.13", "phpunit/php-file-iterator": "^3.0.5", "phpunit/php-invoker": "^3.1.1", "phpunit/php-text-template": "^2.0.3", "phpunit/php-timer": "^5.0.2", "sebastian/cli-parser": "^1.0.1", "sebastian/code-unit": "^1.0.6", - "sebastian/comparator": "^4.0.5", + "sebastian/comparator": "^4.0.8", "sebastian/diff": "^4.0.3", "sebastian/environment": "^5.1.3", - "sebastian/exporter": "^4.0.3", + "sebastian/exporter": "^4.0.5", "sebastian/global-state": "^5.0.1", "sebastian/object-enumerator": "^4.0.3", "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^2.3", + "sebastian/type": "^3.2", "sebastian/version": "^3.0.2" }, - "require-dev": { - "ext-pdo": "*", - "phpspec/prophecy-phpunit": "^2.0.1" - }, "suggest": { - "ext-soap": "*", - "ext-xdebug": "*" + "ext-soap": "To be able to generate mocks based on WSDL files", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "bin": [ "phpunit" @@ -953,15 +725,15 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.4-dev" + "dev-master": "9.6-dev" } }, "autoload": { - "classmap": [ - "src/" - ], "files": [ "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -984,19 +756,24 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.4.3" + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.9" }, "funding": [ { - "url": "https://phpunit.de/donate.html", + "url": "https://phpunit.de/sponsors.html", "type": "custom" }, { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" } ], - "time": "2020-11-10T12:53:30+00:00" + "time": "2023-06-11T06:13:56+00:00" }, { "name": "sebastian/cli-parser", @@ -1167,16 +944,16 @@ }, { "name": "sebastian/comparator", - "version": "4.0.6", + "version": "4.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382" + "reference": "fa0f136dd2334583309d32b62544682ee972b51a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a", "shasum": "" }, "require": { @@ -1229,7 +1006,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.6" + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" }, "funding": [ { @@ -1237,7 +1014,7 @@ "type": "github" } ], - "time": "2020-10-26T15:49:45+00:00" + "time": "2022-09-14T12:41:17+00:00" }, { "name": "sebastian/complexity", @@ -1298,16 +1075,16 @@ }, { "name": "sebastian/diff", - "version": "4.0.4", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" + "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131", + "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131", "shasum": "" }, "require": { @@ -1352,7 +1129,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.5" }, "funding": [ { @@ -1360,20 +1137,20 @@ "type": "github" } ], - "time": "2020-10-26T13:10:38+00:00" + "time": "2023-05-07T05:35:17+00:00" }, { "name": "sebastian/environment", - "version": "5.1.3", + "version": "5.1.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "388b6ced16caa751030f6a69e588299fa09200ac" + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/388b6ced16caa751030f6a69e588299fa09200ac", - "reference": "388b6ced16caa751030f6a69e588299fa09200ac", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", "shasum": "" }, "require": { @@ -1415,7 +1192,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.3" + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" }, "funding": [ { @@ -1423,20 +1200,20 @@ "type": "github" } ], - "time": "2020-09-28T05:52:38+00:00" + "time": "2023-02-03T06:03:51+00:00" }, { "name": "sebastian/exporter", - "version": "4.0.3", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65" + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/d89cc98761b8cb5a1a235a6b703ae50d34080e65", - "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", "shasum": "" }, "require": { @@ -1485,14 +1262,14 @@ } ], "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", + "homepage": "https://www.github.com/sebastianbergmann/exporter", "keywords": [ "export", "exporter" ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.3" + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" }, "funding": [ { @@ -1500,20 +1277,20 @@ "type": "github" } ], - "time": "2020-09-28T05:24:23+00:00" + "time": "2022-09-14T06:03:37+00:00" }, { "name": "sebastian/global-state", - "version": "5.0.2", + "version": "5.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "a90ccbddffa067b51f574dea6eb25d5680839455" + "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/a90ccbddffa067b51f574dea6eb25d5680839455", - "reference": "a90ccbddffa067b51f574dea6eb25d5680839455", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2", "shasum": "" }, "require": { @@ -1556,7 +1333,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.2" + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5" }, "funding": [ { @@ -1564,20 +1341,20 @@ "type": "github" } ], - "time": "2020-10-26T15:55:19+00:00" + "time": "2022-02-14T08:28:10+00:00" }, { "name": "sebastian/lines-of-code", - "version": "1.0.2", + "version": "1.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "acf76492a65401babcf5283296fa510782783a7a" + "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/acf76492a65401babcf5283296fa510782783a7a", - "reference": "acf76492a65401babcf5283296fa510782783a7a", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", "shasum": "" }, "require": { @@ -1613,7 +1390,7 @@ "homepage": "https://github.com/sebastianbergmann/lines-of-code", "support": { "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.2" + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" }, "funding": [ { @@ -1621,7 +1398,7 @@ "type": "github" } ], - "time": "2020-10-26T17:03:56+00:00" + "time": "2020-11-28T06:42:11+00:00" }, { "name": "sebastian/object-enumerator", @@ -1737,16 +1514,16 @@ }, { "name": "sebastian/recursion-context", - "version": "4.0.4", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", "shasum": "" }, "require": { @@ -1785,10 +1562,10 @@ } ], "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" }, "funding": [ { @@ -1796,7 +1573,7 @@ "type": "github" } ], - "time": "2020-10-26T13:17:30+00:00" + "time": "2023-02-03T06:07:39+00:00" }, { "name": "sebastian/resource-operations", @@ -1855,28 +1632,28 @@ }, { "name": "sebastian/type", - "version": "2.3.1", + "version": "3.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "81cd61ab7bbf2de744aba0ea61fae32f721df3d2" + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/81cd61ab7bbf2de744aba0ea61fae32f721df3d2", - "reference": "81cd61ab7bbf2de744aba0ea61fae32f721df3d2", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", "shasum": "" }, "require": { "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^9.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -1899,7 +1676,7 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/2.3.1" + "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" }, "funding": [ { @@ -1907,7 +1684,7 @@ "type": "github" } ], - "time": "2020-10-26T13:18:59+00:00" + "time": "2023-02-03T06:13:03+00:00" }, { "name": "sebastian/version", @@ -1962,97 +1739,18 @@ ], "time": "2020-09-28T06:39:44+00:00" }, - { - "name": "symfony/polyfill-ctype", - "version": "v1.20.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "f4ba089a5b6366e453971d3aad5fe8e897b37f41" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/f4ba089a5b6366e453971d3aad5fe8e897b37f41", - "reference": "f4ba089a5b6366e453971d3aad5fe8e897b37f41", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-ctype": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.20-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for ctype functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], - "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.20.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2020-10-23T14:02:19+00:00" - }, { "name": "theseer/tokenizer", - "version": "1.2.0", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "75a63c33a8577608444246075ea0af0d052e452a" + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/75a63c33a8577608444246075ea0af0d052e452a", - "reference": "75a63c33a8577608444246075ea0af0d052e452a", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", "shasum": "" }, "require": { @@ -2081,7 +1779,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/master" + "source": "https://github.com/theseer/tokenizer/tree/1.2.1" }, "funding": [ { @@ -2089,60 +1787,7 @@ "type": "github" } ], - "time": "2020-07-12T23:59:07+00:00" - }, - { - "name": "webmozart/assert", - "version": "1.9.1", - "source": { - "type": "git", - "url": "https://github.com/webmozart/assert.git", - "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389", - "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0 || ^8.0", - "symfony/polyfill-ctype": "^1.8" - }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<3.9.1" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.36 || ^7.5.13" - }, - "type": "library", - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "support": { - "issues": "https://github.com/webmozart/assert/issues", - "source": "https://github.com/webmozart/assert/tree/master" - }, - "time": "2020-07-08T17:02:28+00:00" + "time": "2021-07-28T10:34:58+00:00" } ], "aliases": [], @@ -2151,12 +1796,15 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": "^7.3.0 || ^8.0.0", + "php": "^7.4.0 || ^8.0.0", "ext-sockets": "*" }, "platform-dev": { "ext-pcntl": "*", "ext-json": "*" }, - "plugin-api-version": "2.0.0" + "platform-overrides": { + "php": "7.4" + }, + "plugin-api-version": "2.3.0" } diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..31cf532 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,11 @@ + + + + + + ./tests + ./tests/ClientTest.php + ./tests/ServerTest.php + + + diff --git a/src/PHPWebSockets/Client.php b/src/PHPWebSockets/Client.php index 90242d6..c0cd638 100644 --- a/src/PHPWebSockets/Client.php +++ b/src/PHPWebSockets/Client.php @@ -239,7 +239,12 @@ public function handleRead() : \Generator { if (strlen($newData) === 0) { - $this->_log(LogLevel::DEBUG, 'Read length of 0, socket is closed'); + if (!feof($this->getStream())) { + $this->_log(LogLevel::DEBUG, 'Read length of 0, ignoring'); + return; + } + + $this->_log(LogLevel::DEBUG, 'FEOF returns true and no more bytes to read, socket is closed'); $this->_isClosed = TRUE; @@ -254,72 +259,69 @@ public function handleRead() : \Generator { $this->close(); return; + } - } else { - - // If we've received data we can be sure we're connected - $this->_isConnectingAsync = FALSE; - - $handshakeAccepted = $this->handshakeAccepted(); - if (!$handshakeAccepted) { + // If we've received data we can be sure we're connected + $this->_isConnectingAsync = FALSE; - $headersEnd = strpos($newData, "\r\n\r\n"); - if ($headersEnd === FALSE) { + $handshakeAccepted = $this->handshakeAccepted(); + if (!$handshakeAccepted) { - $this->_log(LogLevel::DEBUG, 'Handshake data didn\'t finished yet, waiting..'); + $headersEnd = strpos($newData, "\r\n\r\n"); + if ($headersEnd === FALSE) { - if ($this->_readBuffer === NULL) { - $this->_readBuffer = ''; - } + $this->_log(LogLevel::DEBUG, 'Handshake data didn\'t finished yet, waiting..'); - $this->_readBuffer .= $newData; + if ($this->_readBuffer === NULL) { + $this->_readBuffer = ''; + } - if (strlen($this->_readBuffer) > $this->getMaxHandshakeLength()) { + $this->_readBuffer .= $newData; - yield new Update\Error(Update\Error::C_READ_HANDSHAKE_TO_LARGE, $this); - $this->close(); + if (strlen($this->_readBuffer) > $this->getMaxHandshakeLength()) { - } + yield new Update\Error(Update\Error::C_READ_HANDSHAKE_TO_LARGE, $this); + $this->close(); - return; // Still waiting for headers } - if ($this->_readBuffer !== NULL) { - - $newData = $this->_readBuffer . $newData; - $this->_readBuffer = NULL; + return; // Still waiting for headers + } - } + if ($this->_readBuffer !== NULL) { - $rawHandshake = substr($newData, 0, $headersEnd); + $newData = $this->_readBuffer . $newData; + $this->_readBuffer = NULL; - if (strlen($newData) > strlen($rawHandshake)) { // Place all data that came after the header back into the buffer - $newData = substr($newData, $headersEnd + 4); - } + } - $this->_headers = \PHPWebSockets::ParseHTTPHeaders($rawHandshake); - if (($this->_headers['status-code'] ?? NULL) === 101) { + $rawHandshake = substr($newData, 0, $headersEnd); - $this->_handshakeAccepted = TRUE; - $this->_hasHandshake = TRUE; + if (strlen($newData) > strlen($rawHandshake)) { // Place all data that came after the header back into the buffer + $newData = substr($newData, $headersEnd + 4); + } - yield new Update\Read(Update\Read::C_CONNECTION_ACCEPTED, $this); - } else { + $this->_headers = \PHPWebSockets::ParseHTTPHeaders($rawHandshake); + if (($this->_headers['status-code'] ?? NULL) === 101) { - $this->close(); + $this->_handshakeAccepted = TRUE; + $this->_hasHandshake = TRUE; - yield new Update\Read(Update\Read::C_CONNECTION_DENIED, $this); + yield new Update\Read(Update\Read::C_CONNECTION_ACCEPTED, $this); + } else { - } + $this->close(); - $handshakeAccepted = $this->handshakeAccepted(); + yield new Update\Read(Update\Read::C_CONNECTION_DENIED, $this); } - if ($handshakeAccepted) { - yield from $this->_handlePacket($newData); - } + $handshakeAccepted = $this->handshakeAccepted(); + + } + if ($handshakeAccepted) { + yield from $this->_handlePacket($newData); } } diff --git a/src/PHPWebSockets/Server/Connection.php b/src/PHPWebSockets/Server/Connection.php index 2521e94..8906a12 100644 --- a/src/PHPWebSockets/Server/Connection.php +++ b/src/PHPWebSockets/Server/Connection.php @@ -131,6 +131,13 @@ public function handleRead() : \Generator { if (strlen($newData) === 0) { + if (!feof($this->getStream())) { + $this->_log(LogLevel::DEBUG, 'Read length of 0, ignoring'); + return; + } + + $this->_log(LogLevel::DEBUG, 'FEOF returns true and no more bytes to read, socket is closed'); + $this->_isClosed = TRUE; if (!$this->hasHandshake()) { @@ -144,68 +151,65 @@ public function handleRead() : \Generator { $this->close(); return; + } - } else { - - $hasHandshake = $this->hasHandshake(); - if (!$hasHandshake) { - - $headersEnd = strpos($newData, "\r\n\r\n"); - if ($headersEnd === FALSE) { + $hasHandshake = $this->hasHandshake(); + if (!$hasHandshake) { - $this->_log(LogLevel::DEBUG, 'Handshake data hasn\'t finished yet, waiting..'); + $headersEnd = strpos($newData, "\r\n\r\n"); + if ($headersEnd === FALSE) { - if ($this->_readBuffer === NULL) { - $this->_readBuffer = ''; - } + $this->_log(LogLevel::DEBUG, 'Handshake data hasn\'t finished yet, waiting..'); - $this->_readBuffer .= $newData; + if ($this->_readBuffer === NULL) { + $this->_readBuffer = ''; + } - if (strlen($this->_readBuffer) > $this->getMaxHandshakeLength()) { + $this->_readBuffer .= $newData; - $this->writeRaw($this->_server->getErrorPageForCode(431), FALSE); // Request Header Fields Too Large - $this->setCloseAfterWrite(); + if (strlen($this->_readBuffer) > $this->getMaxHandshakeLength()) { - yield new Update\Error(Update\Error::C_READ_HANDSHAKE_TO_LARGE, $this); + $this->writeRaw($this->_server->getErrorPageForCode(431), FALSE); // Request Header Fields Too Large + $this->setCloseAfterWrite(); - } + yield new Update\Error(Update\Error::C_READ_HANDSHAKE_TO_LARGE, $this); - return; // Still waiting for headers } - if ($this->_readBuffer !== NULL) { + return; // Still waiting for headers + } - $newData = $this->_readBuffer . $newData; - $this->_readBuffer = NULL; + if ($this->_readBuffer !== NULL) { - } + $newData = $this->_readBuffer . $newData; + $this->_readBuffer = NULL; - $rawHandshake = substr($newData, 0, $headersEnd); + } - if (strlen($newData) > strlen($rawHandshake)) { - $newData = substr($newData, $headersEnd + 4); - } + $rawHandshake = substr($newData, 0, $headersEnd); - $responseCode = 0; - if ($this->_doHandshake($rawHandshake, $responseCode)) { - yield new Update\Read(Update\Read::C_NEW_CONNECTION, $this); - } else { + if (strlen($newData) > strlen($rawHandshake)) { + $newData = substr($newData, $headersEnd + 4); + } - $this->writeRaw($this->_server->getErrorPageForCode($responseCode), FALSE); - $this->setCloseAfterWrite(); + $responseCode = 0; + if ($this->_doHandshake($rawHandshake, $responseCode)) { + yield new Update\Read(Update\Read::C_NEW_CONNECTION, $this); + } else { - yield new Update\Error(Update\Error::C_READ_HANDSHAKE_FAILURE, $this); + $this->writeRaw($this->_server->getErrorPageForCode($responseCode), FALSE); + $this->setCloseAfterWrite(); - } - - $hasHandshake = $this->hasHandshake(); + yield new Update\Error(Update\Error::C_READ_HANDSHAKE_FAILURE, $this); } - if ($hasHandshake) { - yield from $this->_handlePacket($newData); - } + $hasHandshake = $this->hasHandshake(); + + } + if ($hasHandshake) { + yield from $this->_handlePacket($newData); } } diff --git a/tests/ClientTest.php b/tests/ClientTest.php index 31870e9..72d704c 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -35,7 +35,7 @@ class ClientTest extends TestCase { - protected const ADDRESS = 'tcp://127.0.0.1:9001'; + protected const CONTAINER_NAME = 'fuzzingserver'; protected const VALID_BUFFER_TYPES = [ 'memory', 'tmpfile', @@ -55,6 +55,20 @@ class ClientTest extends TestCase { */ protected $_bufferType = NULL; + /** + * The URI to connect to + * + * @var string + */ + protected $_serverURI; + + /** + * The output directory for reports + * + * @var string + */ + protected $_reportsDir; + /** * The amount of cases to run * @@ -80,23 +94,45 @@ protected function setUp() : void { $this->_bufferType = getenv('BUFFERTYPE') ?: NULL; } - $this->assertContains($this->_bufferType, static::VALID_BUFFER_TYPES, 'Invalid buffer type'); + $this->assertContains($this->_bufferType, static::VALID_BUFFER_TYPES, 'Invalid buffer type, env: ' . implode(', ', getenv())); \PHPWebSockets::Log(LogLevel::INFO, 'Using buffer type ' . $this->_bufferType); + $this->_reportsDir = sys_get_temp_dir() . '/ws_reports'; + if (!is_dir($this->_reportsDir)) { + mkdir($this->_reportsDir); + } + $descriptorSpec = [['pipe', 'r'], STDOUT, STDERR]; - $this->_autobahnProcess = proc_open('wstest -m fuzzingserver -s Resources/Autobahn/fuzzingserver.json', $descriptorSpec, $pipes, realpath(__DIR__ . '/../')); + $serverPort = 9001; + $image = 'crossbario/autobahn-testsuite'; + $cmd = 'docker run --rm \ + -v "' . realpath(__DIR__ . '/../Resources/Autobahn') . ':/config" \ + -v "' . $this->_reportsDir . ':/reports" \ + -p ' . $serverPort . ':9001 \ + --name ' . escapeshellarg(self::CONTAINER_NAME) . ' \ + ' . $image . ' \ + wstest -m fuzzingserver -s /config/fuzzingserver.json + '; - $sleepSec = 2; + \PHPWebSockets::Log(LogLevel::INFO, 'Pulling image ' . $image); + passthru('docker pull ' . $image); + + $this->_autobahnProcess = proc_open($cmd, $descriptorSpec, $pipes); + + $sleepSec = 5; \PHPWebSockets::Log(LogLevel::INFO, 'Sleeping ' . $sleepSec . ' seconds to wait for the fuzzing server to start'); sleep($sleepSec); + $serverIP = trim(exec('docker inspect -f "{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}" ' . self::CONTAINER_NAME)); + $this->_serverURI = 'tcp://' . $serverIP . ':' . $serverPort; + $client = $this->_createClient(); - $connectResult = $client->connect(static::ADDRESS, '/getCaseCount'); + $connectResult = $client->connect($this->_serverURI, '/getCaseCount'); - $this->assertTrue($connectResult, 'Unable to connect to server: ' . $client->getLastError()); + $this->assertTrue($connectResult, 'Unable to connect to address ' . $this->_serverURI . ': ' . $client->getLastError()); while ($client->isOpen()) { @@ -133,6 +169,7 @@ protected function tearDown() : void { \PHPWebSockets::Log(LogLevel::INFO, 'Tearing down'); proc_terminate($this->_autobahnProcess); + exec('docker container stop ' . escapeshellarg(self::CONTAINER_NAME)); } @@ -143,7 +180,7 @@ public function testClient() : void { for ($i = 0; $i < $this->_caseCount; $i++) { $client = $this->_createClient(); - $client->connect(static::ADDRESS, '/runCase?case=' . ($i + 1) . '&agent=' . $client->getUserAgent()); + $client->connect($this->_serverURI, '/runCase?case=' . ($i + 1) . '&agent=' . $client->getUserAgent()); while ($client->isOpen()) { @@ -174,7 +211,7 @@ public function testClient() : void { \PHPWebSockets::Log(LogLevel::INFO, 'All test cases ran, asking for report update'); $client = $this->_createClient(); - $client->connect(static::ADDRESS, '/updateReports?agent=' . $client->getUserAgent()); + $client->connect($this->_serverURI, '/updateReports?agent=' . $client->getUserAgent()); while ($client->isOpen()) { foreach ($client->update(NULL) as $key => $value) { @@ -183,11 +220,11 @@ public function testClient() : void { } \PHPWebSockets::Log(LogLevel::INFO, 'Reports finished, getting results..'); - $outputFile = '/tmp/reports/index.json'; + $outputFile = $this->_reportsDir . '/index.json'; $this->assertFileExists($outputFile); $testCases = json_decode(file_get_contents($outputFile), TRUE)[$client->getUserAgent()] ?? NULL; - $this->assertNotNull('Unable to get test case results'); + $this->assertNotNull($testCases, 'Unable to get test case results'); $hasFailures = FALSE; foreach ($testCases as $case => $data) { diff --git a/tests/Helpers/client.php b/tests/Helpers/client.php index 6ce6c54..75a9dc5 100755 --- a/tests/Helpers/client.php +++ b/tests/Helpers/client.php @@ -73,6 +73,7 @@ $lastMessage = 0; $pingCount = 0; $lastPing = 0; +$didCloseOrDisconnect = FALSE; while ($client->isOpen()) { @@ -81,7 +82,10 @@ } if ($cliArgs['close-at'] > 0.0 && microtime(TRUE) >= $cliArgs['close-at']) { - $client->close(); + if (!$didCloseOrDisconnect) { + $client->close(); + $didCloseOrDisconnect = TRUE; + } } foreach ($client->update(0.1) as $update) { @@ -93,10 +97,13 @@ } if ($cliArgs['message-count'] > 0 && $messageCount > $cliArgs['message-count']) { - $client->sendDisconnect(\PHPWebSockets::CLOSECODE_NORMAL); + if (!$didCloseOrDisconnect) { + $client->sendDisconnect(\PHPWebSockets::CLOSECODE_NORMAL); + $didCloseOrDisconnect = TRUE; + } } - if ($client->isDisconnecting()) { + if (!$client->isOpen() || $client->isDisconnecting()) { continue; } diff --git a/tests/ServerTest.php b/tests/ServerTest.php index 86df36d..79dddbe 100644 --- a/tests/ServerTest.php +++ b/tests/ServerTest.php @@ -34,7 +34,8 @@ class ServerTest extends TestCase { - protected const ADDRESS = 'tcp://127.0.0.1:9001'; + protected const ADDRESS = 'tcp://0.0.0.0:9001'; + protected const CONTAINER_NAME = 'fuzzingclient'; protected const VALID_BUFFER_TYPES = [ 'memory', 'tmpfile', @@ -54,6 +55,13 @@ class ServerTest extends TestCase { */ protected $_bufferType = NULL; + /** + * The output directory for reports + * + * @var string + */ + protected $_reportsDir; + /** * The websocket server * @@ -86,16 +94,31 @@ protected function setUp() : void { $this->_bufferType = getenv('BUFFERTYPE') ?: NULL; } - $this->assertContains($this->_bufferType, static::VALID_BUFFER_TYPES, 'Invalid buffer type'); + $this->assertContains($this->_bufferType, static::VALID_BUFFER_TYPES, 'Invalid buffer type, env: ' . implode(', ', getenv())); \PHPWebSockets::Log(LogLevel::INFO, 'Using buffer type ' . $this->_bufferType); $this->_wsServer = new \PHPWebSockets\Server(self::ADDRESS); + $this->_reportsDir = sys_get_temp_dir() . '/ws_reports'; + if (!is_dir($this->_reportsDir)) { + mkdir($this->_reportsDir); + } $descriptorSpec = [['pipe', 'r'], STDOUT, STDERR]; - $this->_autobahnProcess = proc_open('wstest -m fuzzingclient -s Resources/Autobahn/fuzzingclient.json', $descriptorSpec, $pipes, realpath(__DIR__ . '/../')); + $image = 'crossbario/autobahn-testsuite'; + $cmd = 'docker run --rm \ + -v "' . realpath(__DIR__ . '/../Resources/Autobahn') . ':/config" \ + -v "' . $this->_reportsDir . ':/reports" \ + --add-host host.docker.internal:host-gateway \ + --name ' . escapeshellarg(static::CONTAINER_NAME) . ' \ + ' . $image . ' \ + wstest -m fuzzingclient -s /config/fuzzingclient.json + '; + + \PHPWebSockets::Log(LogLevel::INFO, 'Pulling image ' . $image); + passthru('docker pull ' . $image); - sleep(2); + $this->_autobahnProcess = proc_open($cmd, $descriptorSpec, $pipes); } @@ -103,6 +126,7 @@ protected function tearDown() : void { \PHPWebSockets::Log(LogLevel::INFO, 'Tearing down'); proc_terminate($this->_autobahnProcess); + exec('docker container stop ' . escapeshellarg(self::CONTAINER_NAME)); } @@ -180,12 +204,12 @@ public function testServer() { \PHPWebSockets::Log(LogLevel::INFO, 'Getting results..'); - $outputFile = '/tmp/reports/index.json'; + $outputFile = $this->_reportsDir . '/index.json'; $this->assertFileExists($outputFile); $hasFailures = FALSE; $testCases = json_decode(file_get_contents($outputFile), TRUE)[$this->_wsServer->getServerIdentifier()] ?? NULL; - $this->assertNotNull('Unable to get test case results'); + $this->assertNotNull($testCases, 'Unable to get test case results'); foreach ($testCases as $case => $data) { diff --git a/tests/UpdatesWrapperTest.php b/tests/UpdatesWrapperTest.php index da30267..1e1bc71 100644 --- a/tests/UpdatesWrapperTest.php +++ b/tests/UpdatesWrapperTest.php @@ -178,12 +178,13 @@ public function testWrapperNormal() { $descriptorSpec = [['pipe', 'r'], STDOUT, STDERR]; $clientProcess = proc_open('./tests/Helpers/client.php --address=' . escapeshellarg(self::ADDRESS) . ' --message=' . escapeshellarg('Hello world') . ' --message-count=5', $descriptorSpec, $pipes, realpath(__DIR__ . '/../')); - while (proc_get_status($clientProcess)['running'] ?? FALSE) { + while (($status = proc_get_status($clientProcess))['running'] ?? FALSE) { $this->_updatesWrapper->update(0.5, $this->_wsServer->getConnections(TRUE)); } + $this->assertEquals(0, $status['exitcode'], 'Helper did not exit cleanly'); $this->assertEmpty($this->_wsServer->getConnections(FALSE)); $this->assertEmpty($this->_connectionList); @@ -200,12 +201,13 @@ public function testWrapperAsyncClient() { $descriptorSpec = [['pipe', 'r'], STDOUT, STDERR]; $clientProcess = proc_open('./tests/Helpers/client.php --address=' . escapeshellarg(self::ADDRESS) . ' --message=' . escapeshellarg('Hello world') . ' --message-count=5 --async', $descriptorSpec, $pipes, realpath(__DIR__ . '/../')); - while (proc_get_status($clientProcess)['running'] ?? FALSE) { + while (($status = proc_get_status($clientProcess))['running'] ?? FALSE) { $this->_updatesWrapper->update(0.5, $this->_wsServer->getConnections(TRUE)); } + $this->assertEquals(0, $status['exitcode'], 'Helper did not exit cleanly'); $this->assertEmpty($this->_wsServer->getConnections(FALSE)); $this->assertEmpty($this->_connectionList); @@ -225,6 +227,8 @@ public function testWrapperClientDisappeared() { $descriptorSpec = [['pipe', 'r'], STDOUT, STDERR]; $clientProcess = proc_open('./tests/Helpers/client.php --address=' . escapeshellarg(self::ADDRESS) . ' --message=' . escapeshellarg('Hello world') . ' --die-at=' . escapeshellarg((string) $dieAt), $descriptorSpec, $pipes, realpath(__DIR__ . '/../')); + $status = NULL; + while (microtime(TRUE) <= $runUntil) { $this->_updatesWrapper->update(0.5, $this->_wsServer->getConnections(TRUE)); @@ -243,6 +247,7 @@ public function testWrapperClientDisappeared() { } + $this->assertEquals(0, $status['exitcode'], 'Helper did not exit cleanly'); $this->assertEmpty($this->_wsServer->getConnections(FALSE)); $this->assertEmpty($this->_connectionList); @@ -289,6 +294,9 @@ public function testWrapperServerClose() { } + $status = proc_get_status($clientProcess); + + $this->assertEquals(0, $status['exitcode'], 'Helper did not exit cleanly'); $this->assertEmpty($this->_wsServer->getConnections(FALSE)); $this->assertEmpty($this->_connectionList); @@ -311,12 +319,14 @@ public function testWrapperClientClose() { $this->_updatesWrapper->update(0.5, $this->_wsServer->getConnections(TRUE)); - if (!proc_get_status($clientProcess)['running'] ?? FALSE) { + $status = proc_get_status($clientProcess); + if (!($status['running'] ?? FALSE)) { break; } } + $this->assertEquals(0, $status['exitcode'], 'Helper did not exit cleanly'); $this->assertEmpty($this->_wsServer->getConnections(FALSE)); $this->assertEmpty($this->_connectionList); @@ -337,6 +347,8 @@ public function testWrapperClientRefuse() { $descriptorSpec = [['pipe', 'r'], STDOUT, STDERR]; $clientProcess = proc_open('./tests/Helpers/client.php --address=' . escapeshellarg(self::ADDRESS) . ' --message=' . escapeshellarg('Hello world') . ' --message-count=1', $descriptorSpec, $pipes, realpath(__DIR__ . '/../')); + $status = NULL; + while (microtime(TRUE) <= $runUntil) { $this->_updatesWrapper->update(0.5, $this->_wsServer->getConnections(TRUE)); @@ -355,6 +367,7 @@ public function testWrapperClientRefuse() { } + $this->assertEquals(0, $status['exitcode'], 'Helper did not exit cleanly'); $this->assertEmpty($this->_wsServer->getConnections(FALSE)); $this->assertEmpty($this->_connectionList); @@ -377,6 +390,8 @@ public function testWrapperAsyncClientTCPRefuse() { $descriptorSpec = [['pipe', 'r'], STDOUT, STDERR]; $clientProcess = proc_open('./tests/Helpers/client.php --address=' . escapeshellarg('tcp://127.0.0.1:9000') . ' --message=' . escapeshellarg('Hello world') . ' --message-count=1 --async', $descriptorSpec, $pipes, realpath(__DIR__ . '/../')); + $status = NULL; + while (microtime(TRUE) <= $runUntil) { $this->_updatesWrapper->update(0.5, $this->_wsServer->getConnections(TRUE)); @@ -395,6 +410,7 @@ public function testWrapperAsyncClientTCPRefuse() { } + $this->assertEquals(0, $status['exitcode'], 'Helper did not exit cleanly'); $this->assertEmpty($this->_wsServer->getConnections(FALSE)); $this->assertEmpty($this->_connectionList); @@ -455,6 +471,9 @@ public function testDoubleClose() { } + $status = proc_get_status($clientProcess); + + $this->assertEquals(0, $status['exitcode'], 'Helper did not exit cleanly'); $this->assertEmpty($this->_wsServer->getConnections(FALSE)); $this->assertEmpty($this->_connectionList);