diff --git a/.travis.yml b/.travis.yml index d6e27d3f..1aeaccab 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,36 +10,17 @@ env: global: - COMPOSER_ARGS="--no-interaction" - COVERAGE_DEPS="php-coveralls/php-coveralls" - - LEGACY_DEPS="phpunit/phpunit" matrix: include: - - php: 5.6 - env: - - DEPS=lowest - - php: 5.6 - env: - - DEPS=locked - - php: 5.6 - env: - - DEPS=latest - - php: 7 - env: - - DEPS=lowest - - php: 7 - env: - - DEPS=locked - - CHECK_CS=true - - TEST_COVERAGE=true - - php: 7 - env: - - DEPS=latest - php: 7.1 env: - DEPS=lowest - php: 7.1 env: - DEPS=locked + - CS_CHECK=true + - TEST_COVERAGE=true - php: 7.1 env: - DEPS=latest @@ -54,12 +35,10 @@ matrix: - DEPS=latest before_install: - - if [[ $TEST_COVERAGE != 'true' && "$(php --version | grep xdebug -ci)" -ge 1 ]]; then phpenv config-rm xdebug.ini || return 0 ; fi - - travis_retry composer self-update + - if [[ $TEST_COVERAGE != 'true' ]]; then phpenv config-rm xdebug.ini || return 0 ; fi install: - - travis_retry composer install $COMPOSER_ARGS --ignore-platform-reqs - - if [[ $TRAVIS_PHP_VERSION =~ ^5.6 ]]; then travis_retry composer update $COMPOSER_ARGS --with-dependencies $LEGACY_DEPS ; fi + - travis_retry composer install $COMPOSER_ARGS - if [[ $DEPS == 'latest' ]]; then travis_retry composer update $COMPOSER_ARGS ; fi - if [[ $DEPS == 'lowest' ]]; then travis_retry composer update --prefer-lowest --prefer-stable $COMPOSER_ARGS ; fi - if [[ $TEST_COVERAGE == 'true' ]]; then travis_retry composer require --dev $COMPOSER_ARGS $COVERAGE_DEPS ; fi @@ -67,7 +46,7 @@ install: script: - if [[ $TEST_COVERAGE == 'true' ]]; then composer test-coverage ; else composer test ; fi - - if [[ $CHECK_CS == 'true' ]]; then composer cs-check ; fi + - if [[ $CS_CHECK == 'true' ]]; then composer cs-check ; fi after_script: - if [[ $TEST_COVERAGE == 'true' ]]; then travis_retry php vendor/bin/php-coveralls -v ; fi diff --git a/composer.json b/composer.json index cc6d19d6..3487b3b7 100644 --- a/composer.json +++ b/composer.json @@ -1,17 +1,19 @@ { "name": "zendframework/zend-diactoros", "description": "PSR HTTP Message implementations", - "type": "library", - "license": "BSD-2-Clause", + "license": "BSD-3-Clause", "keywords": [ "http", "psr", "psr-7" ], - "homepage": "https://github.com/zendframework/zend-diactoros", "support": { + "docs": "https://docs.zendframework.com/zend-diactoros/", "issues": "https://github.com/zendframework/zend-diactoros/issues", - "source": "https://github.com/zendframework/zend-diactoros" + "source": "https://github.com/zendframework/zend-diactoros", + "rss": "https://github.com/zendframework/zend-diactoros/releases.atom", + "slack": "https://zendframework-slack.herokuapp.com", + "forum": "https://discourse.zendframework.com/c/questions/exprssive" }, "config": { "sort-packages": true @@ -23,14 +25,14 @@ } }, "require": { - "php": "^5.6 || ^7.0", + "php": "^7.1", "psr/http-message": "^1.0" }, "require-dev": { "ext-dom": "*", "ext-libxml": "*", - "phpunit/phpunit": "^5.7.16 || ^6.0.8", - "zendframework/zend-coding-standard": "~1.0" + "phpunit/phpunit": "^7.0.2", + "zendframework/zend-coding-standard": "~1.0.0" }, "provide": { "psr/http-message-implementation": "1.0" @@ -43,11 +45,7 @@ "autoload-dev": { "psr-4": { "ZendTest\\Diactoros\\": "test/" - }, - "files": [ - "test/TestAsset/Functions.php", - "test/TestAsset/SapiResponse.php" - ] + } }, "scripts": { "check": [ diff --git a/composer.lock b/composer.lock index 13676458..1d7e2252 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "de254758c5d28198ad8441fb154fc7f3", + "content-hash": "4d4f844a2da49f40e494f8db82fcc69b", "packages": [ { "name": "psr/http-message", @@ -60,32 +60,32 @@ "packages-dev": [ { "name": "doctrine/instantiator", - "version": "1.0.5", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" + "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", + "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", "shasum": "" }, "require": { - "php": ">=5.3,<8.0-DEV" + "php": "^7.1" }, "require-dev": { "athletic/athletic": "~0.1.8", "ext-pdo": "*", "ext-phar": "*", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~2.0" + "phpunit/phpunit": "^6.2.3", + "squizlabs/php_codesniffer": "^3.0.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.2.x-dev" } }, "autoload": { @@ -110,41 +110,44 @@ "constructor", "instantiate" ], - "time": "2015-06-14T21:17:01+00:00" + "time": "2017-07-22T11:58:36+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.6.1", + "version": "1.7.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "8e6e04167378abf1ddb4d3522d8755c5fd90d102" + "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/8e6e04167378abf1ddb4d3522d8755c5fd90d102", - "reference": "8e6e04167378abf1ddb4d3522d8755c5fd90d102", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", + "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", "shasum": "" }, "require": { - "php": ">=5.4.0" + "php": "^5.6 || ^7.0" }, "require-dev": { - "doctrine/collections": "1.*", - "phpunit/phpunit": "~4.1" + "doctrine/collections": "^1.0", + "doctrine/common": "^2.6", + "phpunit/phpunit": "^4.1" }, "type": "library", "autoload": { "psr-4": { "DeepCopy\\": "src/DeepCopy/" - } + }, + "files": [ + "src/DeepCopy/deep_copy.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "description": "Create deep copies (clones) of your objects", - "homepage": "https://github.com/myclabs/DeepCopy", "keywords": [ "clone", "copy", @@ -152,7 +155,7 @@ "object", "object graph" ], - "time": "2017-04-12T18:52:22+00:00" + "time": "2017-10-19T19:58:43+00:00" }, { "name": "phar-io/manifest", @@ -258,16 +261,16 @@ }, { "name": "phpdocumentor/reflection-common", - "version": "1.0", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c" + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c", - "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", "shasum": "" }, "require": { @@ -308,33 +311,39 @@ "reflection", "static analysis" ], - "time": "2015-12-27T11:43:31+00:00" + "time": "2017-09-11T18:02:19+00:00" }, { "name": "phpdocumentor/reflection-docblock", - "version": "3.2.2", + "version": "4.3.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "4aada1f93c72c35e22fb1383b47fee43b8f1d157" + "reference": "94fd0001232e47129dd3504189fa1c7225010d08" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/4aada1f93c72c35e22fb1383b47fee43b8f1d157", - "reference": "4aada1f93c72c35e22fb1383b47fee43b8f1d157", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94fd0001232e47129dd3504189fa1c7225010d08", + "reference": "94fd0001232e47129dd3504189fa1c7225010d08", "shasum": "" }, "require": { - "php": ">=5.5", - "phpdocumentor/reflection-common": "^1.0@dev", - "phpdocumentor/type-resolver": "^0.3.0", + "php": "^7.0", + "phpdocumentor/reflection-common": "^1.0.0", + "phpdocumentor/type-resolver": "^0.4.0", "webmozart/assert": "^1.0" }, "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^4.4" + "doctrine/instantiator": "~1.0.5", + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^6.4" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev" + } + }, "autoload": { "psr-4": { "phpDocumentor\\Reflection\\": [ @@ -353,20 +362,20 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2017-08-08T06:39:58+00:00" + "time": "2017-11-30T07:14:17+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "0.3.0", + "version": "0.4.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "fb3933512008d8162b3cdf9e18dba9309b7c3773" + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/fb3933512008d8162b3cdf9e18dba9309b7c3773", - "reference": "fb3933512008d8162b3cdf9e18dba9309b7c3773", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", "shasum": "" }, "require": { @@ -400,37 +409,37 @@ "email": "me@mikevanriel.com" } ], - "time": "2017-06-03T08:32:36+00:00" + "time": "2017-07-14T14:27:02+00:00" }, { "name": "phpspec/prophecy", - "version": "v1.7.0", + "version": "1.7.5", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "93d39f1f7f9326d746203c7c056f300f7f126073" + "reference": "dfd6be44111a7c41c2e884a336cc4f461b3b2401" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/93d39f1f7f9326d746203c7c056f300f7f126073", - "reference": "93d39f1f7f9326d746203c7c056f300f7f126073", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/dfd6be44111a7c41c2e884a336cc4f461b3b2401", + "reference": "dfd6be44111a7c41c2e884a336cc4f461b3b2401", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", "sebastian/comparator": "^1.1|^2.0", "sebastian/recursion-context": "^1.0|^2.0|^3.0" }, "require-dev": { "phpspec/phpspec": "^2.5|^3.2", - "phpunit/phpunit": "^4.8 || ^5.6.5" + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.6.x-dev" + "dev-master": "1.7.x-dev" } }, "autoload": { @@ -463,45 +472,44 @@ "spy", "stub" ], - "time": "2017-03-02T20:05:34+00:00" + "time": "2018-02-19T10:16:54+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "5.2.2", + "version": "6.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "8ed1902a57849e117b5651fc1a5c48110946c06b" + "reference": "f8ca4b604baf23dab89d87773c28cc07405189ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/8ed1902a57849e117b5651fc1a5c48110946c06b", - "reference": "8ed1902a57849e117b5651fc1a5c48110946c06b", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f8ca4b604baf23dab89d87773c28cc07405189ba", + "reference": "f8ca4b604baf23dab89d87773c28cc07405189ba", "shasum": "" }, "require": { "ext-dom": "*", "ext-xmlwriter": "*", - "php": "^7.0", + "php": "^7.1", "phpunit/php-file-iterator": "^1.4.2", "phpunit/php-text-template": "^1.2.1", - "phpunit/php-token-stream": "^1.4.11 || ^2.0", + "phpunit/php-token-stream": "^3.0", "sebastian/code-unit-reverse-lookup": "^1.0.1", "sebastian/environment": "^3.0", "sebastian/version": "^2.0.1", "theseer/tokenizer": "^1.1" }, "require-dev": { - "ext-xdebug": "^2.5", - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^7.0" }, "suggest": { - "ext-xdebug": "^2.5.5" + "ext-xdebug": "^2.6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.2.x-dev" + "dev-master": "6.0-dev" } }, "autoload": { @@ -516,7 +524,7 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -527,20 +535,20 @@ "testing", "xunit" ], - "time": "2017-08-03T12:40:43+00:00" + "time": "2018-02-02T07:01:41+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "1.4.2", + "version": "1.4.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5" + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5", - "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", "shasum": "" }, "require": { @@ -574,7 +582,7 @@ "filesystem", "iterator" ], - "time": "2016-10-03T07:40:28+00:00" + "time": "2017-11-27T13:52:08+00:00" }, { "name": "phpunit/php-text-template", @@ -619,28 +627,28 @@ }, { "name": "phpunit/php-timer", - "version": "1.0.9", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" + "reference": "8b8454ea6958c3dee38453d3bd571e023108c91f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/8b8454ea6958c3dee38453d3bd571e023108c91f", + "reference": "8b8454ea6958c3dee38453d3bd571e023108c91f", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "php": "^7.1" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + "phpunit/phpunit": "^7.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -655,7 +663,7 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -664,33 +672,33 @@ "keywords": [ "timer" ], - "time": "2017-02-26T11:10:40+00:00" + "time": "2018-02-01T13:07:23+00:00" }, { "name": "phpunit/php-token-stream", - "version": "2.0.1", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "9a02332089ac48e704c70f6cefed30c224e3c0b0" + "reference": "21ad88bbba7c3d93530d93994e0a33cd45f02ace" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/9a02332089ac48e704c70f6cefed30c224e3c0b0", - "reference": "9a02332089ac48e704c70f6cefed30c224e3c0b0", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/21ad88bbba7c3d93530d93994e0a33cd45f02ace", + "reference": "21ad88bbba7c3d93530d93994e0a33cd45f02ace", "shasum": "" }, "require": { "ext-tokenizer": "*", - "php": "^7.0" + "php": "^7.1" }, "require-dev": { - "phpunit/phpunit": "^6.2.4" + "phpunit/phpunit": "^7.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -713,20 +721,20 @@ "keywords": [ "tokenizer" ], - "time": "2017-08-20T05:47:52+00:00" + "time": "2018-02-01T13:16:43+00:00" }, { "name": "phpunit/phpunit", - "version": "6.3.0", + "version": "7.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "9501bab711403a1ab5b8378a8adb4ec3db3debdb" + "reference": "e2f8aa21bc54b6ba218bdd4f9e0dac1e9bc3b4e9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/9501bab711403a1ab5b8378a8adb4ec3db3debdb", - "reference": "9501bab711403a1ab5b8378a8adb4ec3db3debdb", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e2f8aa21bc54b6ba218bdd4f9e0dac1e9bc3b4e9", + "reference": "e2f8aa21bc54b6ba218bdd4f9e0dac1e9bc3b4e9", "shasum": "" }, "require": { @@ -738,15 +746,15 @@ "myclabs/deep-copy": "^1.6.1", "phar-io/manifest": "^1.0.1", "phar-io/version": "^1.0", - "php": "^7.0", + "php": "^7.1", "phpspec/prophecy": "^1.7", - "phpunit/php-code-coverage": "^5.2.2", - "phpunit/php-file-iterator": "^1.4.2", + "phpunit/php-code-coverage": "^6.0", + "phpunit/php-file-iterator": "^1.4.3", "phpunit/php-text-template": "^1.2.1", - "phpunit/php-timer": "^1.0.9", - "phpunit/phpunit-mock-objects": "^4.0.3", - "sebastian/comparator": "^2.0.2", - "sebastian/diff": "^2.0", + "phpunit/php-timer": "^2.0", + "phpunit/phpunit-mock-objects": "^6.0", + "sebastian/comparator": "^2.1", + "sebastian/diff": "^3.0", "sebastian/environment": "^3.1", "sebastian/exporter": "^3.1", "sebastian/global-state": "^2.0", @@ -754,16 +762,12 @@ "sebastian/resource-operations": "^1.0", "sebastian/version": "^2.0.1" }, - "conflict": { - "phpdocumentor/reflection-docblock": "3.0.2", - "phpunit/dbunit": "<3.0" - }, "require-dev": { "ext-pdo": "*" }, "suggest": { "ext-xdebug": "*", - "phpunit/php-invoker": "^1.1" + "phpunit/php-invoker": "^2.0" }, "bin": [ "phpunit" @@ -771,7 +775,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "6.3.x-dev" + "dev-master": "7.0-dev" } }, "autoload": { @@ -797,33 +801,30 @@ "testing", "xunit" ], - "time": "2017-08-04T05:20:39+00:00" + "time": "2018-02-26T07:03:12+00:00" }, { "name": "phpunit/phpunit-mock-objects", - "version": "4.0.4", + "version": "6.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "2f789b59ab89669015ad984afa350c4ec577ade0" + "reference": "e3249dedc2d99259ccae6affbc2684eac37c2e53" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/2f789b59ab89669015ad984afa350c4ec577ade0", - "reference": "2f789b59ab89669015ad984afa350c4ec577ade0", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/e3249dedc2d99259ccae6affbc2684eac37c2e53", + "reference": "e3249dedc2d99259ccae6affbc2684eac37c2e53", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.5", - "php": "^7.0", + "php": "^7.1", "phpunit/php-text-template": "^1.2.1", - "sebastian/exporter": "^3.0" - }, - "conflict": { - "phpunit/phpunit": "<6.0" + "sebastian/exporter": "^3.1" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^7.0" }, "suggest": { "ext-soap": "*" @@ -831,7 +832,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0.x-dev" + "dev-master": "6.0.x-dev" } }, "autoload": { @@ -846,7 +847,7 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -856,7 +857,7 @@ "mock", "xunit" ], - "time": "2017-08-03T14:08:16+00:00" + "time": "2018-02-15T05:27:38+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -905,30 +906,30 @@ }, { "name": "sebastian/comparator", - "version": "2.0.2", + "version": "2.1.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "ae068fede81d06e7bb9bb46a367210a3d3e1fe6a" + "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/ae068fede81d06e7bb9bb46a367210a3d3e1fe6a", - "reference": "ae068fede81d06e7bb9bb46a367210a3d3e1fe6a", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/34369daee48eafb2651bea869b4b15d75ccc35f9", + "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9", "shasum": "" }, "require": { "php": "^7.0", - "sebastian/diff": "^2.0", - "sebastian/exporter": "^3.0" + "sebastian/diff": "^2.0 || ^3.0", + "sebastian/exporter": "^3.1" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^6.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "2.1.x-dev" } }, "autoload": { @@ -959,38 +960,39 @@ } ], "description": "Provides the functionality to compare PHP values for equality", - "homepage": "http://www.github.com/sebastianbergmann/comparator", + "homepage": "https://github.com/sebastianbergmann/comparator", "keywords": [ "comparator", "compare", "equality" ], - "time": "2017-08-03T07:14:59+00:00" + "time": "2018-02-01T13:46:46+00:00" }, { "name": "sebastian/diff", - "version": "2.0.1", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd" + "reference": "e09160918c66281713f1c324c1f4c4c3037ba1e8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/347c1d8b49c5c3ee30c7040ea6fc446790e6bddd", - "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/e09160918c66281713f1c324c1f4c4c3037ba1e8", + "reference": "e09160918c66281713f1c324c1f4c4c3037ba1e8", "shasum": "" }, "require": { - "php": "^7.0" + "php": "^7.1" }, "require-dev": { - "phpunit/phpunit": "^6.2" + "phpunit/phpunit": "^7.0", + "symfony/process": "^2 || ^3.3 || ^4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -1015,9 +1017,12 @@ "description": "Diff implementation", "homepage": "https://github.com/sebastianbergmann/diff", "keywords": [ - "diff" + "diff", + "udiff", + "unidiff", + "unified diff" ], - "time": "2017-08-03T08:09:46+00:00" + "time": "2018-02-01T13:45:15+00:00" }, { "name": "sebastian/environment", @@ -1537,16 +1542,16 @@ }, { "name": "webmozart/assert", - "version": "1.2.0", + "version": "1.3.0", "source": { "type": "git", "url": "https://github.com/webmozart/assert.git", - "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f" + "reference": "0df1908962e7a3071564e857d86874dad1ef204a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/2db61e59ff05fe5126d152bd0655c9ea113e550f", - "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f", + "url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a", + "reference": "0df1908962e7a3071564e857d86874dad1ef204a", "shasum": "" }, "require": { @@ -1583,7 +1588,7 @@ "check", "validate" ], - "time": "2016-11-23T20:04:58+00:00" + "time": "2018-01-29T19:49:41+00:00" }, { "name": "zendframework/zend-coding-standard", @@ -1621,7 +1626,7 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": "^5.6 || ^7.0" + "php": "^7.1" }, "platform-dev": { "ext-dom": "*", diff --git a/src/Response/EmitterInterface.php b/src/Response/EmitterInterface.php deleted file mode 100644 index f27b4a9c..00000000 --- a/src/Response/EmitterInterface.php +++ /dev/null @@ -1,32 +0,0 @@ -assertNoPreviousOutput(); - - $this->emitHeaders($response); - $this->emitStatusLine($response); - $this->emitBody($response); - } - - /** - * Emit the message body. - * - * @param ResponseInterface $response - */ - private function emitBody(ResponseInterface $response) - { - echo $response->getBody(); - } -} diff --git a/src/Response/SapiEmitterTrait.php b/src/Response/SapiEmitterTrait.php deleted file mode 100644 index ce9612c8..00000000 --- a/src/Response/SapiEmitterTrait.php +++ /dev/null @@ -1,102 +0,0 @@ - 0 && ob_get_length() > 0) { - throw new RuntimeException('Output has been emitted previously; cannot emit response'); - } - } - - /** - * Emit the status line. - * - * Emits the status line using the protocol version and status code from - * the response; if a reason phrase is available, it, too, is emitted. - * - * It is important to mention that this method should be called after - * `emitHeaders()` in order to prevent PHP from changing the status code of - * the emitted response. - * - * @param ResponseInterface $response - * - * @see \Zend\Diactoros\Response\SapiEmitterTrait::emitHeaders() - */ - private function emitStatusLine(ResponseInterface $response) - { - $reasonPhrase = $response->getReasonPhrase(); - $statusCode = $response->getStatusCode(); - - header(sprintf( - 'HTTP/%s %d%s', - $response->getProtocolVersion(), - $statusCode, - ($reasonPhrase ? ' ' . $reasonPhrase : '') - ), true, $statusCode); - } - - /** - * Emit response headers. - * - * Loops through each header, emitting each; if the header value - * is an array with multiple values, ensures that each is sent - * in such a way as to create aggregate headers (instead of replace - * the previous). - * - * @param ResponseInterface $response - */ - private function emitHeaders(ResponseInterface $response) - { - $statusCode = $response->getStatusCode(); - - foreach ($response->getHeaders() as $header => $values) { - $name = $this->filterHeader($header); - $first = $name === 'Set-Cookie' ? false : true; - foreach ($values as $value) { - header(sprintf( - '%s: %s', - $name, - $value - ), $first, $statusCode); - $first = false; - } - } - } - - /** - * Filter a header name to wordcase - * - * @param string $header - * @return string - */ - private function filterHeader($header) - { - $filtered = str_replace('-', ' ', $header); - $filtered = ucwords($filtered); - return str_replace(' ', '-', $filtered); - } -} diff --git a/src/Response/SapiStreamEmitter.php b/src/Response/SapiStreamEmitter.php deleted file mode 100644 index e06c99f2..00000000 --- a/src/Response/SapiStreamEmitter.php +++ /dev/null @@ -1,127 +0,0 @@ -assertNoPreviousOutput(); - $this->emitHeaders($response); - $this->emitStatusLine($response); - - $range = $this->parseContentRange($response->getHeaderLine('Content-Range')); - - if (is_array($range) && $range[0] === 'bytes') { - $this->emitBodyRange($range, $response, $maxBufferLength); - return; - } - - $this->emitBody($response, $maxBufferLength); - } - - /** - * Emit the message body. - * - * @param ResponseInterface $response - * @param int $maxBufferLength - */ - private function emitBody(ResponseInterface $response, $maxBufferLength) - { - $body = $response->getBody(); - - if ($body->isSeekable()) { - $body->rewind(); - } - - if (! $body->isReadable()) { - echo $body; - return; - } - - while (! $body->eof()) { - echo $body->read($maxBufferLength); - } - } - - /** - * Emit a range of the message body. - * - * @param array $range - * @param ResponseInterface $response - * @param int $maxBufferLength - */ - private function emitBodyRange(array $range, ResponseInterface $response, $maxBufferLength) - { - list($unit, $first, $last, $length) = $range; - - $body = $response->getBody(); - - $length = $last - $first + 1; - - if ($body->isSeekable()) { - $body->seek($first); - - $first = 0; - } - - if (! $body->isReadable()) { - echo substr($body->getContents(), $first, $length); - return; - } - - $remaining = $length; - - while ($remaining >= $maxBufferLength && ! $body->eof()) { - $contents = $body->read($maxBufferLength); - $remaining -= strlen($contents); - - echo $contents; - } - - if ($remaining > 0 && ! $body->eof()) { - echo $body->read($remaining); - } - } - - /** - * Parse content-range header - * http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.16 - * - * @param string $header - * @return false|array [unit, first, last, length]; returns false if no - * content range or an invalid content range is provided - */ - private function parseContentRange($header) - { - if (preg_match('/(?P[\w]+)\s+(?P\d+)-(?P\d+)\/(?P\d+|\*)/', $header, $matches)) { - return [ - $matches['unit'], - (int) $matches['first'], - (int) $matches['last'], - $matches['length'] === '*' ? '*' : (int) $matches['length'], - ]; - } - return false; - } -} diff --git a/src/Server.php b/src/Server.php deleted file mode 100644 index dfe84004..00000000 --- a/src/Server.php +++ /dev/null @@ -1,180 +0,0 @@ -callback = $callback; - $this->request = $request; - $this->response = $response; - } - - /** - * Allow retrieving the request, response and callback as properties - * - * @param string $name - * @return mixed - * @throws OutOfBoundsException for invalid properties - */ - public function __get($name) - { - if (! property_exists($this, $name)) { - throw new OutOfBoundsException('Cannot retrieve arbitrary properties from server'); - } - return $this->{$name}; - } - - /** - * Set alternate response emitter to use. - * - * @param Response\EmitterInterface $emitter - */ - public function setEmitter(Response\EmitterInterface $emitter) - { - $this->emitter = $emitter; - } - - /** - * Create a Server instance - * - * Creates a server instance from the callback and the following - * PHP environmental values: - * - * - server; typically this will be the $_SERVER superglobal - * - query; typically this will be the $_GET superglobal - * - body; typically this will be the $_POST superglobal - * - cookies; typically this will be the $_COOKIE superglobal - * - files; typically this will be the $_FILES superglobal - * - * @param callable $callback - * @param array $server - * @param array $query - * @param array $body - * @param array $cookies - * @param array $files - * @return static - */ - public static function createServer( - callable $callback, - array $server, - array $query, - array $body, - array $cookies, - array $files - ) { - $request = ServerRequestFactory::fromGlobals($server, $query, $body, $cookies, $files); - $response = new Response(); - return new static($callback, $request, $response); - } - - /** - * Create a Server instance from an existing request object - * - * Provided a callback, an existing request object, and optionally an - * existing response object, create and return the Server instance. - * - * If no Response object is provided, one will be created. - * - * @param callable $callback - * @param ServerRequestInterface $request - * @param null|ResponseInterface $response - * @return static - */ - public static function createServerFromRequest( - callable $callback, - ServerRequestInterface $request, - ResponseInterface $response = null - ) { - if (! $response) { - $response = new Response(); - } - return new static($callback, $request, $response); - } - - /** - * "Listen" to an incoming request - * - * If provided a $finalHandler, that callable will be used for - * incomplete requests. - * - * @param null|callable $finalHandler - */ - public function listen(callable $finalHandler = null) - { - $callback = $this->callback; - - $response = $callback($this->request, $this->response, $finalHandler); - if (! $response instanceof ResponseInterface) { - $response = $this->response; - } - - $this->getEmitter()->emit($response); - } - - /** - * Retrieve the current response emitter. - * - * If none has been registered, lazy-loads a Response\SapiEmitter. - * - * @return Response\EmitterInterface - */ - private function getEmitter() - { - if (! $this->emitter) { - $this->emitter = new Response\SapiEmitter(); - } - - return $this->emitter; - } -} diff --git a/test/PhpInputStreamTest.php b/test/PhpInputStreamTest.php index e9887b1f..25eec9bc 100644 --- a/test/PhpInputStreamTest.php +++ b/test/PhpInputStreamTest.php @@ -33,7 +33,7 @@ public function getFileContents() return file_get_contents($this->file); } - public function assertStreamContents($test, $message = null) + public function assertStreamContents($test, $message = '') { $content = $this->getFileContents(); $this->assertSame($content, $test, $message); diff --git a/test/Response/AbstractEmitterTest.php b/test/Response/AbstractEmitterTest.php index 48bb95ee..f367ca68 100644 --- a/test/Response/AbstractEmitterTest.php +++ b/test/Response/AbstractEmitterTest.php @@ -9,7 +9,7 @@ use PHPUnit\Framework\TestCase; use Zend\Diactoros\Response; -use Zend\Diactoros\Response\SapiEmitter; +use Zend\HttpHandlerRunner\Emitter\SapiEmitter; use ZendTest\Diactoros\TestAsset\HeaderStack; abstract class AbstractEmitterTest extends TestCase diff --git a/test/Response/SapiEmitterTest.php b/test/Response/SapiEmitterTest.php deleted file mode 100644 index ab1b18ef..00000000 --- a/test/Response/SapiEmitterTest.php +++ /dev/null @@ -1,14 +0,0 @@ -emitter = new SapiStreamEmitter(); - } - - public function testEmitCallbackStreamResponse() - { - $stream = new CallbackStream(function () { - return 'it works'; - }); - $response = (new Response()) - ->withStatus(200) - ->withBody($stream); - ob_start(); - $this->emitter->emit($response); - $this->assertSame('it works', ob_get_clean()); - } - - public function testDoesNotInjectContentLengthHeaderIfStreamSizeIsUnknown() - { - $stream = $this->prophesize(StreamInterface::class); - $stream->__toString()->willReturn('Content!'); - $stream->isSeekable()->willReturn(false); - $stream->isReadable()->willReturn(false); - $stream->eof()->willReturn(true); - $stream->rewind()->willReturn(true); - $stream->getSize()->willReturn(null); - $response = (new Response()) - ->withStatus(200) - ->withBody($stream->reveal()); - - ob_start(); - $this->emitter->emit($response); - ob_end_clean(); - foreach (HeaderStack::stack() as $header) { - $this->assertNotContains('Content-Length:', $header['header']); - } - } - - /** - * Create a new stream prophecy and setup common promises - * - * @param string|callable $contents Stream contents. - * @param integer $size Size of stream contents. - * @param integer $startPosition Start position of internal stream data pointer. - * @param callable|null $trackPeakBufferLength Called on "read" calls. - * Receives data length (i.e. data length <= buffer length). - * @return ObjectProphecy Returns new stream prophecy. - */ - private function setUpStreamProphecy($contents, $size, $startPosition, callable $trackPeakBufferLength = null) - { - $position = $startPosition; - - $stream = $this->prophesize('Psr\Http\Message\StreamInterface'); - - $stream->__toString()->will(function () use ($contents, $size, & $position) { - if (is_callable($contents)) { - $data = $contents(0); - } else { - $data = $contents; - } - - $position = $size; - - return $data; - }); - - $stream->getSize()->willReturn($size); - - $stream->tell()->will(function () use (& $position) { - return $position; - }); - - $stream->eof()->will(function () use ($size, & $position) { - return ($position >= $size); - }); - - $stream->seek(Argument::type('integer'), Argument::any())->will(function ($args) use ($size, & $position) { - if ($args[0] < $size) { - $position = $args[0]; - return true; - } - - return false; - }); - - $stream->rewind()->will(function () use (& $position) { - $position = 0; - return true; - }); - - $stream->read(Argument::type('integer')) - ->will(function ($args) use ($contents, & $position, & $trackPeakBufferLength) { - if (is_callable($contents)) { - $data = $contents($position, $args[0]); - } else { - $data = substr($contents, $position, $args[0]); - } - - if ($trackPeakBufferLength) { - $trackPeakBufferLength($args[0]); - } - - $position += strlen($data); - - return $data; - }); - - $stream->getContents()->will(function () use ($contents, & $position) { - if (is_callable($contents)) { - $remainingContents = $contents($position); - } else { - $remainingContents = substr($contents, $position); - } - - $position += strlen($remainingContents); - - return $remainingContents; - }); - - return $stream; - } - - public function emitStreamResponseProvider() - { - return [ - [true, true, '01234567890987654321', 10], - [true, true, '01234567890987654321', 20], - [true, true, '01234567890987654321', 100], - [true, true, '01234567890987654321012', 10], - [true, true, '01234567890987654321012', 20], - [true, true, '01234567890987654321012', 100], - [true, false, '01234567890987654321', 10], - [true, false, '01234567890987654321', 20], - [true, false, '01234567890987654321', 100], - [true, false, '01234567890987654321012', 10], - [true, false, '01234567890987654321012', 20], - [true, false, '01234567890987654321012', 100], - [false, true, '01234567890987654321', 10], - [false, true, '01234567890987654321', 20], - [false, true, '01234567890987654321', 100], - [false, true, '01234567890987654321012', 10], - [false, true, '01234567890987654321012', 20], - [false, true, '01234567890987654321012', 100], - [false, false, '01234567890987654321', 10], - [false, false, '01234567890987654321', 20], - [false, false, '01234567890987654321', 100], - [false, false, '01234567890987654321012', 10], - [false, false, '01234567890987654321012', 20], - [false, false, '01234567890987654321012', 100], - ]; - } - - /** - * @param boolean $seekable Indicates if stream is seekable - * @param boolean $readable Indicates if stream is readable - * @param string $contents Contents stored in stream - * @param integer $maxBufferLength Maximum buffer length used in the emitter call. - * @dataProvider emitStreamResponseProvider - */ - public function testEmitStreamResponse($seekable, $readable, $contents, $maxBufferLength) - { - $size = strlen($contents); - $startPosition = 0; - $peakBufferLength = 0; - $rewindCalled = false; - $fullContentsCalled = false; - - $stream = $this->setUpStreamProphecy( - $contents, - $size, - $startPosition, - function ($bufferLength) use (& $peakBufferLength) { - if ($bufferLength > $peakBufferLength) { - $peakBufferLength = $bufferLength; - } - } - ); - - $stream->isSeekable()->willReturn($seekable); - $stream->isReadable()->willReturn($readable); - - $response = (new Response()) - ->withStatus(200) - ->withBody($stream->reveal()); - - ob_start(); - $this->emitter->emit($response, $maxBufferLength); - $emittedContents = ob_get_clean(); - - if ($seekable) { - $rewindPredictionClosure = function () use (& $rewindCalled) { - $rewindCalled = true; - }; - - $stream->rewind()->should($rewindPredictionClosure); - $stream->seek(0)->should($rewindPredictionClosure); - $stream->seek(0, SEEK_SET)->should($rewindPredictionClosure); - } else { - $stream->rewind()->shouldNotBeCalled(); - $stream->seek(Argument::type('integer'), Argument::any())->shouldNotBeCalled(); - } - - if ($readable) { - $stream->__toString()->shouldNotBeCalled(); - $stream->read(Argument::type('integer'))->shouldBeCalled(); - $stream->eof()->shouldBeCalled(); - $stream->getContents()->shouldNotBeCalled(); - } else { - $fullContentsPredictionClosure = function () use (& $fullContentsCalled) { - $fullContentsCalled = true; - }; - - $stream->__toString()->should($fullContentsPredictionClosure); - $stream->read(Argument::type('integer'))->shouldNotBeCalled(); - $stream->eof()->shouldNotBeCalled(); - - if ($seekable) { - $stream->getContents()->should($fullContentsPredictionClosure); - } else { - $stream->getContents()->shouldNotBeCalled(); - } - } - - $stream->checkProphecyMethodsPredictions(); - - $this->assertSame($seekable, $rewindCalled); - $this->assertSame(! $readable, $fullContentsCalled); - $this->assertSame($contents, $emittedContents); - $this->assertLessThanOrEqual($maxBufferLength, $peakBufferLength); - } - - public function emitRangeStreamResponseProvider() - { - return [ - [true, true, ['bytes', 10, 20, '*'], '01234567890987654321', 5], - [true, true, ['bytes', 10, 20, '*'], '01234567890987654321', 10], - [true, true, ['bytes', 10, 20, '*'], '01234567890987654321', 100], - [true, true, ['bytes', 10, 20, '*'], '01234567890987654321012', 5], - [true, true, ['bytes', 10, 20, '*'], '01234567890987654321012', 10], - [true, true, ['bytes', 10, 20, '*'], '01234567890987654321012', 100], - [true, true, ['bytes', 10, 100, '*'], '01234567890987654321', 5], - [true, true, ['bytes', 10, 100, '*'], '01234567890987654321', 10], - [true, true, ['bytes', 10, 100, '*'], '01234567890987654321', 100], - [true, true, ['bytes', 10, 100, '*'], '01234567890987654321012', 5], - [true, true, ['bytes', 10, 100, '*'], '01234567890987654321012', 10], - [true, true, ['bytes', 10, 100, '*'], '01234567890987654321012', 100], - [true, false, ['bytes', 10, 20, '*'], '01234567890987654321', 5], - [true, false, ['bytes', 10, 20, '*'], '01234567890987654321', 10], - [true, false, ['bytes', 10, 20, '*'], '01234567890987654321', 100], - [true, false, ['bytes', 10, 20, '*'], '01234567890987654321012', 5], - [true, false, ['bytes', 10, 20, '*'], '01234567890987654321012', 10], - [true, false, ['bytes', 10, 20, '*'], '01234567890987654321012', 100], - [true, false, ['bytes', 10, 100, '*'], '01234567890987654321', 5], - [true, false, ['bytes', 10, 100, '*'], '01234567890987654321', 10], - [true, false, ['bytes', 10, 100, '*'], '01234567890987654321', 100], - [true, false, ['bytes', 10, 100, '*'], '01234567890987654321012', 5], - [true, false, ['bytes', 10, 100, '*'], '01234567890987654321012', 10], - [true, false, ['bytes', 10, 100, '*'], '01234567890987654321012', 100], - [false, true, ['bytes', 10, 20, '*'], '01234567890987654321', 5], - [false, true, ['bytes', 10, 20, '*'], '01234567890987654321', 10], - [false, true, ['bytes', 10, 20, '*'], '01234567890987654321', 100], - [false, true, ['bytes', 10, 20, '*'], '01234567890987654321012', 5], - [false, true, ['bytes', 10, 20, '*'], '01234567890987654321012', 10], - [false, true, ['bytes', 10, 20, '*'], '01234567890987654321012', 100], - [false, true, ['bytes', 10, 100, '*'], '01234567890987654321', 5], - [false, true, ['bytes', 10, 100, '*'], '01234567890987654321', 10], - [false, true, ['bytes', 10, 100, '*'], '01234567890987654321', 100], - [false, true, ['bytes', 10, 100, '*'], '01234567890987654321012', 5], - [false, true, ['bytes', 10, 100, '*'], '01234567890987654321012', 10], - [false, true, ['bytes', 10, 100, '*'], '01234567890987654321012', 100], - [false, false, ['bytes', 10, 20, '*'], '01234567890987654321', 5], - [false, false, ['bytes', 10, 20, '*'], '01234567890987654321', 10], - [false, false, ['bytes', 10, 20, '*'], '01234567890987654321', 100], - [false, false, ['bytes', 10, 20, '*'], '01234567890987654321012', 5], - [false, false, ['bytes', 10, 20, '*'], '01234567890987654321012', 10], - [false, false, ['bytes', 10, 20, '*'], '01234567890987654321012', 100], - [false, false, ['bytes', 10, 100, '*'], '01234567890987654321', 5], - [false, false, ['bytes', 10, 100, '*'], '01234567890987654321', 10], - [false, false, ['bytes', 10, 100, '*'], '01234567890987654321', 100], - [false, false, ['bytes', 10, 100, '*'], '01234567890987654321012', 5], - [false, false, ['bytes', 10, 100, '*'], '01234567890987654321012', 10], - [false, false, ['bytes', 10, 100, '*'], '01234567890987654321012', 100], - ]; - } - - - /** - * @param boolean $seekable Indicates if stream is seekable - * @param boolean $readable Indicates if stream is readable - * @param array $range Emitted range of data [$unit, $first, $last, $length] - * @param string $contents Contents stored in stream - * @param integer $maxBufferLength Maximum buffer length used in the emitter call. - * @dataProvider emitRangeStreamResponseProvider - */ - public function testEmitRangeStreamResponse($seekable, $readable, array $range, $contents, $maxBufferLength) - { - list($unit, $first, $last, $length) = $range; - $size = strlen($contents); - - if ($readable && ! $seekable) { - $startPosition = $first; - } else { - $startPosition = 0; - } - - $peakBufferLength = 0; - $seekCalled = false; - - $stream = $this->setUpStreamProphecy( - $contents, - $size, - $startPosition, - function ($bufferLength) use (& $peakBufferLength) { - if ($bufferLength > $peakBufferLength) { - $peakBufferLength = $bufferLength; - } - } - ); - $stream->isSeekable()->willReturn($seekable); - $stream->isReadable()->willReturn($readable); - - $response = (new Response()) - ->withStatus(200) - ->withHeader('Content-Range', 'bytes ' . $first . '-' . $last . '/*') - ->withBody($stream->reveal()); - - ob_start(); - $this->emitter->emit($response, $maxBufferLength); - $emittedContents = ob_get_clean(); - - $stream->rewind()->shouldNotBeCalled(); - - if ($seekable) { - $seekPredictionClosure = function () use (& $seekCalled) { - $seekCalled = true; - }; - - $stream->seek($first)->should($seekPredictionClosure); - $stream->seek($first, SEEK_SET)->should($seekPredictionClosure); - } else { - $stream->seek(Argument::type('integer'), Argument::any())->shouldNotBeCalled(); - } - - $stream->__toString()->shouldNotBeCalled(); - - if ($readable) { - $stream->read(Argument::type('integer'))->shouldBeCalled(); - $stream->eof()->shouldBeCalled(); - $stream->getContents()->shouldNotBeCalled(); - } else { - $stream->read(Argument::type('integer'))->shouldNotBeCalled(); - $stream->eof()->shouldNotBeCalled(); - $stream->getContents()->shouldBeCalled(); - } - - $stream->checkProphecyMethodsPredictions(); - - $this->assertSame($seekable, $seekCalled); - $this->assertSame(substr($contents, $first, $last - $first + 1), $emittedContents); - $this->assertLessThanOrEqual($maxBufferLength, $peakBufferLength); - } - - public function emitMemoryUsageProvider() - { - return [ - [true, true, 1000, 20, null, 512], - [true, true, 1000, 20, null, 4096], - [true, true, 1000, 20, null, 8192], - [true, false, 100, 320, null, 512], - [true, false, 100, 320, null, 4096], - [true, false, 100, 320, null, 8192], - [false, true, 1000, 20, null, 512], - [false, true, 1000, 20, null, 4096], - [false, true, 1000, 20, null, 8192], - [false, false, 100, 320, null, 512], - [false, false, 100, 320, null, 4096], - [false, false, 100, 320, null, 8192], - [true, true, 1000, 20, [25, 75], 512], - [true, true, 1000, 20, [25, 75], 4096], - [true, true, 1000, 20, [25, 75], 8192], - [false, true, 1000, 20, [25, 75], 512], - [false, true, 1000, 20, [25, 75], 4096], - [false, true, 1000, 20, [25, 75], 8192], - [true, true, 1000, 20, [250, 750], 512], - [true, true, 1000, 20, [250, 750], 4096], - [true, true, 1000, 20, [250, 750], 8192], - [false, true, 1000, 20, [250, 750], 512], - [false, true, 1000, 20, [250, 750], 4096], - [false, true, 1000, 20, [250, 750], 8192], - ]; - } - - /** - * @param boolean $seekable Indicates if stream is seekable - * @param boolean $readable Indicates if stream is readable - * @param integer $sizeBlocks Number the blocks of stream data. - * Block size is equal to $maxBufferLength. - * @param integer $maxAllowedBlocks Maximum allowed memory usage in block units. - * @param array|null $rangeBlocks Emitted range of data in block units [$firstBlock, $lastBlock]. - * @param integer $maxBufferLength Maximum buffer length used in the emitter call. - * - * @dataProvider emitMemoryUsageProvider - */ - public function testEmitMemoryUsage( - $seekable, - $readable, - $sizeBlocks, - $maxAllowedBlocks, - $rangeBlocks, - $maxBufferLength - ) { - - $sizeBytes = $maxBufferLength * $sizeBlocks; - $maxAllowedMemoryUsage = $maxBufferLength * $maxAllowedBlocks; - $peakBufferLength = 0; - $peakMemoryUsage = 0; - - $position = 0; - - if ($rangeBlocks) { - $first = $maxBufferLength * $rangeBlocks[0]; - $last = ($maxBufferLength * $rangeBlocks[1]) + $maxBufferLength - 1; - - if ($readable && ! $seekable) { - $position = $first; - } - } - - $closureTrackMemoryUsage = function () use (& $peakMemoryUsage) { - $peakMemoryUsage = max($peakMemoryUsage, memory_get_usage()); - }; - - $stream = $this->setUpStreamProphecy( - function ($position, $length = null) use (& $sizeBytes) { - if (! $length) { - $length = $sizeBytes - $position; - } - - return str_repeat('0', $length); - }, - $sizeBytes, - $position, - function ($bufferLength) use (& $peakBufferLength) { - if ($bufferLength > $peakBufferLength) { - $peakBufferLength = $bufferLength; - } - } - ); - $stream->isSeekable()->willReturn($seekable); - $stream->isReadable()->willReturn($readable); - - $response = (new Response()) - ->withStatus(200) - ->withBody($stream->reveal()); - - - if ($rangeBlocks) { - $response = $response->withHeader('Content-Range', 'bytes ' . $first . '-' . $last . '/*'); - } - - ob_start( - function () use (& $closureTrackMemoryUsage) { - $closureTrackMemoryUsage(); - - return ''; - }, - $maxBufferLength - ); - - gc_collect_cycles(); - - gc_disable(); - - $this->emitter->emit($response, $maxBufferLength); - - ob_end_flush(); - - gc_enable(); - - gc_collect_cycles(); - - $localMemoryUsage = memory_get_usage(); - - $this->assertLessThanOrEqual($maxBufferLength, $peakBufferLength); - $this->assertLessThanOrEqual($maxAllowedMemoryUsage, $peakMemoryUsage - $localMemoryUsage); - } - - public function testEmitEmptyResponse() - { - $response = (new EmptyResponse()) - ->withStatus(204); - - ob_start(); - $this->emitter->emit($response); - $this->assertEmpty($response->getHeaderLine('content-type')); - $this->assertEmpty(ob_get_clean()); - } - - public function testEmitHtmlResponse() - { - $contents = '' - . '' - . ' ' - . '

Hello world

' - . ' ' - . ''; - - $response = (new HtmlResponse($contents)) - ->withStatus(200); - - ob_start(); - $this->emitter->emit($response); - $this->assertSame('text/html; charset=utf-8', $response->getHeaderLine('content-type')); - $this->assertSame($contents, ob_get_clean()); - } - - public function emitJsonResponseProvider() - { - return [ - [0.1 ], - ['test' ], - [true ], - [1 ], - [['key1' => 'value1'] ], - [null ], - [[[0.1, 0.2], ['test', 'test2'], [true, false], ['key1' => 'value1'], [null]]], - ]; - } - - /** - * @param string $contents Contents stored in stream - * @dataProvider emitJsonResponseProvider - */ - public function testEmitJsonResponse($contents) - { - $response = (new JsonResponse($contents)) - ->withStatus(200); - - ob_start(); - $this->emitter->emit($response); - $this->assertSame('application/json', $response->getHeaderLine('content-type')); - $this->assertSame(json_encode($contents), ob_get_clean()); - } - - public function testEmitTextResponse() - { - $contents = 'Hello world'; - - $response = (new TextResponse($contents)) - ->withStatus(200); - - ob_start(); - $this->emitter->emit($response); - $this->assertSame('text/plain; charset=utf-8', $response->getHeaderLine('content-type')); - $this->assertSame($contents, ob_get_clean()); - } - - public function contentRangeProvider() - { - return [ - ['bytes 0-2/*', 'Hello world', 'Hel'], - ['bytes 3-6/*', 'Hello world', 'lo w'], - ['items 0-0/1', 'Hello world', 'Hello world'], - ]; - } - - /** - * @dataProvider contentRangeProvider - */ - public function testContentRange($header, $body, $expected) - { - $response = (new Response()) - ->withHeader('Content-Range', $header); - - $response->getBody()->write($body); - - ob_start(); - $this->emitter->emit($response); - $this->assertSame($expected, ob_get_clean()); - } - - public function testContentRangeUnseekableBody() - { - $body = new CallbackStream(function () { - return 'Hello world'; - }); - $response = (new Response()) - ->withBody($body) - ->withHeader('Content-Range', 'bytes 3-6/*'); - - ob_start(); - $this->emitter->emit($response); - $this->assertSame('lo w', ob_get_clean()); - } -} diff --git a/test/ServerTest.php b/test/ServerTest.php deleted file mode 100644 index 5bdac59c..00000000 --- a/test/ServerTest.php +++ /dev/null @@ -1,312 +0,0 @@ -callback = function ($req, $res, $done) { - // Intentionally empty - }; - $this->request = $this->createMock(ServerRequestInterface::class); - $this->response = $this->createMock(ResponseInterface::class); - } - - public function tearDown() - { - HeaderStack::reset(); - } - - public function testCreateServerFromRequestReturnsServerInstanceWithProvidedObjects() - { - $server = Server::createServerFromRequest( - $this->callback, - $this->request, - $this->response - ); - - $this->assertInstanceOf(Server::class, $server); - $this->assertSame($this->callback, $server->callback); - $this->assertSame($this->request, $server->request); - $this->assertSame($this->response, $server->response); - } - - public function testCreateServerFromRequestWillCreateResponseIfNotProvided() - { - $server = Server::createServerFromRequest( - $this->callback, - $this->request - ); - - $this->assertInstanceOf(Server::class, $server); - $this->assertSame($this->callback, $server->callback); - $this->assertSame($this->request, $server->request); - $this->assertInstanceOf(Response::class, $server->response); - } - - public function testCannotAccessArbitraryProperties() - { - $server = new Server( - $this->callback, - $this->request, - $this->response - ); - $prop = uniqid(); - - $this->expectException(OutOfBoundsException::class); - - $server->$prop; - } - - public function testEmitterSetter() - { - $server = new Server( - $this->callback, - $this->request, - $this->response - ); - $emmiter = $this->createMock(EmitterInterface::class); - $emmiter->expects($this->once())->method('emit'); - - $server->setEmitter($emmiter); - - $this->expectOutputString(''); - $server->listen(); - } - - public function testCreateServerWillCreateDefaultInstancesForRequestAndResponse() - { - $server = [ - 'HTTP_HOST' => 'example.com', - 'HTTP_ACCEPT' => 'application/json', - 'REQUEST_METHOD' => 'POST', - 'REQUEST_URI' => '/foo/bar', - 'QUERY_STRING' => 'bar=baz', - ]; - $server = Server::createServer($this->callback, $server, [], [], [], []); - $this->assertInstanceOf(Server::class, $server); - $this->assertSame($this->callback, $server->callback); - - $this->assertInstanceOf(ServerRequest::class, $server->request); - $request = $server->request; - $this->assertSame('POST', $request->getMethod()); - $this->assertSame('/foo/bar', $request->getUri()->getPath()); - $this->assertTrue($request->hasHeader('Accept')); - - $this->assertInstanceOf(Response::class, $server->response); - } - - public function testListenInvokesCallbackAndSendsResponse() - { - $server = [ - 'HTTP_HOST' => 'example.com', - 'HTTP_ACCEPT' => 'application/json', - 'REQUEST_METHOD' => 'POST', - 'REQUEST_URI' => '/foo/bar', - 'QUERY_STRING' => 'bar=baz', - ]; - - $callback = function ($req, $res) { - $res = $res->withAddedHeader('Content-Type', 'text/plain'); - $res->getBody()->write('FOOBAR'); - return $res; - }; - $server = Server::createServer($callback, $server, [], [], [], []); - - $this->expectOutputString('FOOBAR'); - $server->listen(); - - $this->assertTrue(HeaderStack::has('HTTP/1.1 200 OK')); - $this->assertTrue(HeaderStack::has('Content-Type: text/plain')); - } - - public function testListenEmitsStatusHeaderWithoutReasonPhraseIfNoReasonPhrase() - { - $server = [ - 'HTTP_HOST' => 'example.com', - 'HTTP_ACCEPT' => 'application/json', - 'REQUEST_METHOD' => 'POST', - 'REQUEST_URI' => '/foo/bar', - 'QUERY_STRING' => 'bar=baz', - ]; - - $callback = function (ServerRequestInterface $req, ResponseInterface $res) { - $res = $res->withStatus(299); - $res = $res->withAddedHeader('Content-Type', 'text/plain'); - $res->getBody()->write('FOOBAR'); - return $res; - }; - $server = Server::createServer($callback, $server, [], [], [], []); - - $this->expectOutputString('FOOBAR'); - $server->listen(); - - $this->assertTrue(HeaderStack::has('HTTP/1.1 299')); - $this->assertTrue(HeaderStack::has('Content-Type: text/plain')); - } - - public function testEnsurePercentCharactersDoNotResultInOutputError() - { - $server = [ - 'HTTP_HOST' => 'example.com', - 'HTTP_ACCEPT' => 'application/json', - 'REQUEST_METHOD' => 'POST', - 'REQUEST_URI' => '/foo/bar', - 'QUERY_STRING' => 'bar=baz', - ]; - - $callback = function (ServerRequestInterface $req, ResponseInterface $res) { - $res = $res->withAddedHeader('Content-Type', 'text/plain'); - $res->getBody()->write('100%'); - return $res; - }; - $server = Server::createServer($callback, $server, [], [], [], []); - - $this->expectOutputString('100%'); - $server->listen(); - - $this->assertTrue(HeaderStack::has('HTTP/1.1 200 OK')); - $this->assertTrue(HeaderStack::has('Content-Type: text/plain')); - } - - public function testEmitsHeadersWithMultipleValuesMultipleTimes() - { - $server = [ - 'HTTP_HOST' => 'example.com', - 'REQUEST_METHOD' => 'GET', - 'REQUEST_URI' => '/foo/bar', - ]; - - $callback = function (ServerRequestInterface $req, ResponseInterface $res) { - $res = $res->withAddedHeader('Content-Type', 'text/plain'); - $res = $res->withAddedHeader( - 'Set-Cookie', - 'foo=bar; expires=Wed, 1 Oct 2014 10:30; path=/foo; domain=example.com' - ); - $res = $res->withAddedHeader( - 'Set-Cookie', - 'bar=baz; expires=Wed, 8 Oct 2014 10:30; path=/foo/bar; domain=example.com' - ); - return $res; - }; - $server = Server::createServer($callback, $server, [], [], [], []); - - $server->listen(); - - $this->assertTrue(HeaderStack::has('HTTP/1.1 200 OK')); - $this->assertTrue(HeaderStack::has('Content-Type: text/plain')); - $this->assertTrue( - HeaderStack::has('Set-Cookie: foo=bar; expires=Wed, 1 Oct 2014 10:30; path=/foo; domain=example.com') - ); - $this->assertTrue( - HeaderStack::has('Set-Cookie: bar=baz; expires=Wed, 8 Oct 2014 10:30; path=/foo/bar; domain=example.com') - ); - - return HeaderStack::stack(); - } - - /** - * @group 5 - * @depends testEmitsHeadersWithMultipleValuesMultipleTimes - */ - public function testHeaderOrderIsHonoredWhenEmitted($stack) - { - $header = array_pop($stack); - $this->assertContains('Content-Type: text/plain', $header); - - $header = array_pop($stack); - $this->assertContains( - 'Set-Cookie: bar=baz; expires=Wed, 8 Oct 2014 10:30; path=/foo/bar; domain=example.com', - $header - ); - - $header = array_pop($stack); - $this->assertContains( - 'Set-Cookie: foo=bar; expires=Wed, 1 Oct 2014 10:30; path=/foo; domain=example.com', - $header - ); - - $header = array_pop($stack); - $this->assertContains('HTTP/1.1 200 OK', $header); - } - - public function testListenPassesCallableArgumentToCallback() - { - $phpunit = $this; - $invoked = false; - $request = $this->request; - $response = $this->response; - - $this->response - ->expects($this->once()) - ->method('getHeaders') - ->will($this->returnValue([])); - - $responseBody = new Stream('php://temp'); - $this->response - ->expects($this->any()) - ->method('getBody') - ->willReturn($responseBody); - $this->response - ->expects($this->any()) - ->method('withHeader') - ->willReturnSelf(); - - $final = function ($req, $res, $err = null) use ($phpunit, $request, $response, &$invoked) { - $phpunit->assertSame($request, $req); - $phpunit->assertSame($response, $res); - $invoked = true; - }; - - $callback = function ($req, $res, callable $final = null) use ($phpunit) { - if (! $final) { - $phpunit->fail('No final callable passed!'); - } - - $final($req, $res); - }; - - $server = Server::createServerFromRequest( - $callback, - $this->request, - $this->response - ); - $server->listen($final); - $this->assertTrue($invoked); - } -} diff --git a/test/TestAsset/Functions.php b/test/TestAsset/HeaderStack.php similarity index 52% rename from test/TestAsset/Functions.php rename to test/TestAsset/HeaderStack.php index f1d0a5e0..a5c3e433 100644 --- a/test/TestAsset/Functions.php +++ b/test/TestAsset/HeaderStack.php @@ -1,21 +1,7 @@ $string, - 'replace' => $replace, - 'status_code' => $statusCode, - ] - ); -} diff --git a/test/TestAsset/SapiResponse.php b/test/TestAsset/SapiResponse.php deleted file mode 100644 index 11a937b2..00000000 --- a/test/TestAsset/SapiResponse.php +++ /dev/null @@ -1,51 +0,0 @@ - $string, - 'replace' => $replace, - 'status_code' => $http_response_code, - ] - ); -}