diff --git a/.horde.yml b/.horde.yml index 01a3b34..96e6964 100644 --- a/.horde.yml +++ b/.horde.yml @@ -43,10 +43,13 @@ dependencies: psr/http-client: ^1.0.3 dev: composer: - horde/test: ^3 horde/url: ^3 optional: ext: curl: '*' http: '*' vendor: horde + +quality: + phpstan: + level: 9 diff --git a/TESTING.md b/TESTING.md new file mode 100644 index 0000000..634d062 --- /dev/null +++ b/TESTING.md @@ -0,0 +1,53 @@ +# Testing Horde_Http + +## Test Suites + +The test suite follows PSR-4 structure. It is divided into two types: + +### Unit Tests (test/Unit/) +Fast and isolated tests which don't make real HTTP calls. Run these during development: + +```bash +phpunit --testsuite="horde/http unit tests" +``` + +Time: ~0.4 seconds, 130 tests (includes mock client tests) + +### Live Integration Tests (test/Live/) +Slow tests that make real HTTP calls to external servers. Run these as needed to debug specific issues: + +```bash +phpunit --testsuite="horde/http live integration tests" +``` + +Time: ~10+ seconds (network dependent), 24 tests + +## Running All Tests + +```bash +# Default: runs unit tests only (fast ~0.3s) +phpunit + +# Run live integration tests +phpunit --testsuite="horde/http live integration tests" + +# Run all tests (unit + live) +phpunit --testsuite="horde/http unit tests" --testsuite="horde/http live integration tests" +``` + +## Test Configuration + +Integration tests use horde.org by default. Set the `HTTP_TEST_CONFIG` environment variable for a different target: + +```bash +export HTTP_TEST_CONFIG='{"http":{"server":"example.com"}}' +phpunit --testsuite="horde/http live integration tests" +``` + +## Test Structure + +Tests use PSR-4 autoloading: +- test/Unit/ => Horde\Http\Test\Unit\ +- test/Live/ => Horde\Http\Test\Live\ + +No bootstrap file needed - phpunit.xml.dist directly uses `vendor/autoload.php`. diff --git a/composer.json b/composer.json index 5109adb..d9f0123 100644 --- a/composer.json +++ b/composer.json @@ -16,19 +16,19 @@ "role": "lead" } ], - "time": "2026-03-07", + "time": "2026-03-23", "repositories": [], "require": { "php": "^7.4 || ^8", - "horde/exception": "^3 || dev-FRAMEWORK_6_0", - "horde/support": "^3 || dev-FRAMEWORK_6_0", + "horde/exception": "^3", + "horde/support": "^3", "psr/http-message": "^2", "psr/http-factory": "^1.0.2", "psr/http-client": "^1.0.3" }, "require-dev": { - "horde/test": "^3 || dev-FRAMEWORK_6_0", - "horde/url": "^3 || dev-FRAMEWORK_6_0" + "horde/test": "^3", + "horde/url": "^3" }, "suggest": { "ext-curl": "*", @@ -57,10 +57,5 @@ "psr/http-message-implementation": "^2", "psr/http-factory-implementation": "^1.0.2", "psr/http-client-implementation": "^1.0.3" - }, - "extra": { - "branch-alias": { - "dev-FRAMEWORK_6_0": "3.x-dev" - } } } \ No newline at end of file diff --git a/doc/Horde/Http/examples/get-example-dot-com.php b/doc/Horde/Http/examples/get-example-dot-com.php index 029c83c..1d44c14 100644 --- a/doc/Horde/Http/examples/get-example-dot-com.php +++ b/doc/Horde/Http/examples/get-example-dot-com.php @@ -1,8 +1,9 @@ * @license http://www.horde.org/licenses/bsd BSD diff --git a/doc/Horde/Http/examples/get-horde.org.php b/doc/Horde/Http/examples/get-horde.org.php index 43ba029..491b0a9 100644 --- a/doc/Horde/Http/examples/get-horde.org.php +++ b/doc/Horde/Http/examples/get-horde.org.php @@ -1,8 +1,9 @@ * @license http://www.horde.org/licenses/bsd BSD @@ -34,25 +35,25 @@ // PSR-18 client $client = new CurlClient( - new ResponseFactory, - new StreamFactory, - new ClientOptions + new ResponseFactory(), + new StreamFactory(), + new ClientOptions() ); print("Modern PSR-18 Curl Client: Plain HTTP GET\n"); -$requestFactory = new RequestFactory; +$requestFactory = new RequestFactory(); $request = $requestFactory->createRequest('GET', 'http://www.horde.org'); $response = $client->sendRequest($request); -print($response->getStatusCode() . "\n\n" . $response->getReasonPhrase() ."\n\n"); +print($response->getStatusCode() . "\n\n" . $response->getReasonPhrase() . "\n\n"); print("Modern PSR-18 Curl Client: HTTPS GET\n"); -$requestFactory = new RequestFactory; +$requestFactory = new RequestFactory(); $request = $requestFactory->createRequest('GET', 'https://www.horde.org'); $response = $client->sendRequest($request); -print($response->getStatusCode() . "\n\n" . $response->getReasonPhrase() ."\n\n"); +print($response->getStatusCode() . "\n\n" . $response->getReasonPhrase() . "\n\n"); print("Modern PSR-18 Curl Client: HTTPS GitHub\n"); -$requestFactory = new RequestFactory; +$requestFactory = new RequestFactory(); $request = $requestFactory->createRequest('GET', 'https://api.github.com/'); $response = $client->sendRequest($request); -print($response->getStatusCode() . "\n\n" . $response->getReasonPhrase() ."\n\n"); -print($response->getBody()->getContents()); \ No newline at end of file +print($response->getStatusCode() . "\n\n" . $response->getReasonPhrase() . "\n\n"); +print($response->getBody()->getContents()); diff --git a/lib/Horde/Http/Response/Mock.php b/lib/Horde/Http/Response/Mock.php index 67477ee..d15f443 100644 --- a/lib/Horde/Http/Response/Mock.php +++ b/lib/Horde/Http/Response/Mock.php @@ -22,6 +22,13 @@ */ class Horde_Http_Response_Mock extends Horde_Http_Response_Base { + /** + * Response stream. + * + * @var resource + */ + protected $_stream; + /** * Constructor */ diff --git a/phpunit.xml.dist b/phpunit.xml.dist index ad4e1b1..435ad01 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,27 +1,26 @@ + defaultTestSuite="horde/http unit tests"> - - test + + test/Unit + + + test/Live - + lib src - + diff --git a/src/Client/Curl.php b/src/Client/Curl.php index 962b4fe..6216bdc 100644 --- a/src/Client/Curl.php +++ b/src/Client/Curl.php @@ -1,7 +1,7 @@ errors[0]['message']) && - preg_match('/HTTP\/(\d+\.\d+) (\d{3}) (.*)$/', $this->errors[0]['message'], $matches) + isset($this->errors[0]['message']) + && preg_match('/HTTP\/(\d+\.\d+) (\d{3}) (.*)$/', $this->errors[0]['message'], $matches) ) { // Create a Response for the HTTP error code return $this->responseFactory->createResponse($matches[0]); @@ -138,7 +138,7 @@ public function sendRequest(RequestInterface $request): ResponseInterface } $meta = stream_get_meta_data($streamResource); - $headers = isset($meta['wrapper_data']) ? $meta['wrapper_data'] : []; + $headers = $meta['wrapper_data'] ?? []; //return new Response $headerList = $this->parseHeaders($headers); diff --git a/src/Client/Mock.php b/src/Client/Mock.php index 2d6b636..6c54740 100644 --- a/src/Client/Mock.php +++ b/src/Client/Mock.php @@ -1,6 +1,7 @@ streamFactory->createStream($body); + $stream = $this->streamFactory->createStream($body); } else { $stream = $this->streamFactory->createStreamFromResource($body); } @@ -111,7 +116,7 @@ public function addResponse( $response = $response->withAddedHeader($name, $header); } $this->responses[] = $response; - return $response; + return $response; } /** diff --git a/src/Client/Options.php b/src/Client/Options.php index edb52b2..762d565 100644 --- a/src/Client/Options.php +++ b/src/Client/Options.php @@ -1,6 +1,7 @@ 5, 'timeout' => 5, 'userAgent' => 'Horde\Http H6', - 'verifyPeer' => true + 'verifyPeer' => true, ]; public function __construct(iterable $param = []) @@ -57,4 +60,4 @@ public function getOption(string $name) { return $this->options[$name] ?? null; } -} \ No newline at end of file +} diff --git a/src/Client/ParseHeadersTrait.php b/src/Client/ParseHeadersTrait.php index b385983..4d991f5 100644 --- a/src/Client/ParseHeadersTrait.php +++ b/src/Client/ParseHeadersTrait.php @@ -1,13 +1,14 @@ parsedHttpVersion = $httpMatches[1]; - $this->parsedCode = (int)$httpMatches[2]; + $this->parsedCode = (int) $httpMatches[2]; $bucket = new CaseInsensitiveArray(); $lastHeader = null; } @@ -52,7 +53,7 @@ private function parseHeaders($headers) if ($tmp = $bucket[$headerName]) { if (!is_array($tmp)) { - $tmp = array($tmp); + $tmp = [$tmp]; } $tmp[] = $headerValue; $headerValue = $tmp; @@ -60,8 +61,8 @@ private function parseHeaders($headers) $bucket[$headerName] = $headerValue; $lastHeader = $headerName; - } elseif (preg_match("|^\s+(.+)$|", $headerLine, $m) && - !is_null($lastHeader)) { + } elseif (preg_match("|^\s+(.+)$|", $headerLine, $m) + && !is_null($lastHeader)) { if (is_array($bucket[$lastHeader])) { $tmp = $bucket[$lastHeader]; end($tmp); @@ -75,4 +76,4 @@ private function parseHeaders($headers) return $bucket; } -} \ No newline at end of file +} diff --git a/src/Client/Peclhttp.php b/src/Client/Peclhttp.php index 9242670..7ab4ac2 100644 --- a/src/Client/Peclhttp.php +++ b/src/Client/Peclhttp.php @@ -1,6 +1,7 @@ \http\Client\Curl\PROXY_SOCKS4, - Constants::PROXY_SOCKS5 => \http\Client\Curl\PROXY_SOCKS5 + Constants::PROXY_SOCKS5 => \http\Client\Curl\PROXY_SOCKS5, ]; protected StreamFactoryInterface $streamFactory; protected ResponseFactoryInterface $responseFactory; @@ -115,13 +118,13 @@ protected function httpOptions() // Set options $httpOptions = [ 'headers' => $this->headers, - 'redirect' => (int)$this->options->getOption('redirects'), + 'redirect' => (int) $this->options->getOption('redirects'), 'ssl' => [ 'verifypeer' => $this->options->getOption('verifyPeer'), - 'verifyhost' => $this->options->getOption('verifyPeer') + 'verifyhost' => $this->options->getOption('verifyPeer'), ], 'timeout' => $this->options->getOption('timeout'), - 'useragent' => $this->options->getOption('userAgent') + 'useragent' => $this->options->getOption('userAgent'), ]; // Proxy settings @@ -136,7 +139,7 @@ protected function httpOptions() } if ($this->proxyType == Constants::PROXY_SOCKS4 || $this->proxyType == Constants::PROXY_SOCKS5) { $httpOptions['proxytype'] = $this->proxyType(); - } else if ($this->options->getOption('proxyType') != Constants::PROXY_HTTP) { + } elseif ($this->options->getOption('proxyType') != Constants::PROXY_HTTP) { throw new ClientException(sprintf('Proxy type %s not supported by this request type!', $this->options->getOption('proxyType'))); } } @@ -187,4 +190,4 @@ public function sendRequest(RequestInterface $request): ResponseInterface $psr7Response = $this->convertPeclHttpResponseToPsr7($httpResponse); return $psr7Response; } -} \ No newline at end of file +} diff --git a/src/ClientException.php b/src/ClientException.php index 370c5e0..ebe597f 100644 --- a/src/ClientException.php +++ b/src/ClientException.php @@ -1,15 +1,15 @@ 21, 'http' => 80, - 'https' => 443 + 'https' => 443, ]; @@ -56,18 +59,18 @@ class Constants 'a+', 'c+', 'r','r+', 'w+', 'x+', 'a+b', 'c+b', 'rb','r+b', 'w+b', 'x+b', 'a+t', 'c+t', 'rt','r+t', 'w+t', 'x+t', - + ]; /** * Stream modes that can be written to - * + * * @const WRITABLE_STREAM_MODES string[] Modes as reported by stream_get_meta */ public const WRITABLE_STREAM_MODES = [ 'a', 'a+', 'w', 'w+', 'r+', 'rw', 'x+', 'c+', - 'wb', 'w+b', 'r+b', 'x+b', 'c+b', - 'w+t', 'r+t', 'x+t', 'c+t' + 'wb', 'w+b', 'r+b', 'x+b', 'c+b', + 'w+t', 'r+t', 'x+t', 'c+t', ]; /** @@ -136,4 +139,4 @@ class Constants 510 => 'Not Extended', 511 => 'Network Authentication Required', ]; -} \ No newline at end of file +} diff --git a/src/Exception.php b/src/Exception.php index 1883632..32e5512 100644 --- a/src/Exception.php +++ b/src/Exception.php @@ -1,6 +1,7 @@ * @category Horde * @copyright 2007-2017 Horde LLC @@ -116,8 +119,7 @@ public function __construct( RequestFactoryInterface $requestFactory, StreamFactoryInterface $streamFactory, bool $httpMethodOverride = false - ) - { + ) { $this->requestFactory = $requestFactory; $this->streamFactory = $streamFactory; $this->client = $client; @@ -133,7 +135,7 @@ public function __construct( * @throws ClientException * @return ResponseInterface */ - public function get($uri = null, $headers = array()) + public function get($uri = null, $headers = []) { return $this->request('GET', $uri, null, $headers); } @@ -148,7 +150,7 @@ public function get($uri = null, $headers = array()) * @throws Exception * @return ResponseInterface */ - public function post($uri = null, $data = null, $headers = array()) + public function post($uri = null, $data = null, $headers = []) { return $this->request('POST', $uri, $data, $headers); } @@ -163,11 +165,11 @@ public function post($uri = null, $data = null, $headers = array()) * @throws Exception * @return ResponseInterface */ - public function put($uri = null, $data = null, $headers = array()): ResponseInterface + public function put($uri = null, $data = null, $headers = []): ResponseInterface { if ($this->httpMethodOverride) { $headers = array_merge( - array('X-HTTP-Method-Override' => 'PUT'), + ['X-HTTP-Method-Override' => 'PUT'], $headers ); return $this->post($uri, $data, $headers); @@ -185,11 +187,11 @@ public function put($uri = null, $data = null, $headers = array()): ResponseInte * @throws Exception * @return ResponseInterface */ - public function delete($uri = null, $headers = array()): ResponseInterface + public function delete($uri = null, $headers = []): ResponseInterface { if ($this->httpMethodOverride) { $headers = array_merge( - array('X-HTTP-Method-Override' => 'DELETE'), + ['X-HTTP-Method-Override' => 'DELETE'], $headers ); return $this->post($uri, null, $headers); @@ -207,7 +209,7 @@ public function delete($uri = null, $headers = array()): ResponseInterface * @throws Exception * @return ResponseInterface */ - public function head($uri = null, $headers = array()) + public function head($uri = null, $headers = []) { return $this->request('HEAD', $uri, null, $headers); } @@ -229,9 +231,11 @@ public function head($uri = null, $headers = array()) * @return ResponseInterface */ public function request( - string $method, $uri = null, $data = null, iterable $headers = [] - ) - { + string $method, + $uri = null, + $data = null, + iterable $headers = [] + ) { if (empty($uri)) { $uri = $this->uri; } diff --git a/src/MessageImplementation.php b/src/MessageImplementation.php index 5efb3a6..fa4ab08 100644 --- a/src/MessageImplementation.php +++ b/src/MessageImplementation.php @@ -5,8 +5,9 @@ use InvalidArgumentException; use Horde_String; use Psr\Http\Message\StreamInterface; -use \Psr\Http\Message\MessageInterface; -use \Psr\Http\Message\RequestInterface; +use Psr\Http\Message\MessageInterface; +use Psr\Http\Message\RequestInterface; + /** * Reusable implementation of Message. * We want to avoid creating a semantically useless hierarchy of classes as @@ -214,7 +215,7 @@ public function getHeaderLine(string $name): string * @param string $name Case-insensitive header field name. * @param string|string[] $value Header value(s). * @return static - * @throws \InvalidArgumentException for invalid header names or values. + * @throws InvalidArgumentException for invalid header names or values. */ public function withHeader(string $name, $value): MessageInterface { @@ -313,7 +314,7 @@ private function storeHeader($name, string|array $value) * @param string $name Case-insensitive header field name to add. * @param string|string[] $value Header value(s). * @return static - * @throws \InvalidArgumentException for invalid header names or values. + * @throws InvalidArgumentException for invalid header names or values. */ public function withAddedHeader(string $name, $value): MessageInterface { @@ -381,7 +382,7 @@ public function getBody(): StreamInterface * * @param StreamInterface $body Body. * @return static - * @throws \InvalidArgumentException When the body is not valid. + * @throws InvalidArgumentException When the body is not valid. */ public function withBody(StreamInterface $body): MessageInterface { diff --git a/src/NetworkException.php b/src/NetworkException.php index 034b1f5..272f05d 100644 --- a/src/NetworkException.php +++ b/src/NetworkException.php @@ -1,13 +1,15 @@ request; } -} \ No newline at end of file +} diff --git a/src/Request.php b/src/Request.php index 971580e..84a10a2 100644 --- a/src/Request.php +++ b/src/Request.php @@ -1,14 +1,16 @@ getHeaderLine($name); } $extHttpRequest = new \http\Client\Request( - $request->getMethod(), + $request->getMethod(), (string) $request->getUri(), $extHttpReqHeaders, $extHttpReqBody ); return $extHttpRequest; } -} \ No newline at end of file +} diff --git a/src/RequestException.php b/src/RequestException.php index 77bbaff..7287f6c 100644 --- a/src/RequestException.php +++ b/src/RequestException.php @@ -1,13 +1,15 @@ request; } -} \ No newline at end of file +} diff --git a/src/RequestFactory.php b/src/RequestFactory.php index 545697d..8903cc2 100644 --- a/src/RequestFactory.php +++ b/src/RequestFactory.php @@ -1,21 +1,23 @@ httpStatusCode = $status; $this->httpReasonPhrase = $reason; - foreach ($headers as $header => $value) - { + foreach ($headers as $header => $value) { $this->storeHeader($header, $value); } if ($body instanceof StreamInterface) { @@ -83,7 +84,7 @@ public function getStatusCode(): int * provided status code; if none is provided, implementations MAY * use the defaults as suggested in the HTTP specification. * @return static - * @throws \InvalidArgumentException For invalid status code arguments. + * @throws InvalidArgumentException For invalid status code arguments. */ public function withStatus(int $code, string $reasonPhrase = ''): ResponseInterface { @@ -120,4 +121,4 @@ public function getReasonPhrase(): string } return Constants::REASON_PHRASES[$this->httpStatusCode]; } -} \ No newline at end of file +} diff --git a/src/Response/PeclHttpToPsr7.php b/src/Response/PeclHttpToPsr7.php index e299930..66d5e03 100644 --- a/src/Response/PeclHttpToPsr7.php +++ b/src/Response/PeclHttpToPsr7.php @@ -1,9 +1,11 @@ getTransferInfo(); } catch (\http\Exception $e) { @@ -45,4 +47,4 @@ private function convertPeclHttpResponseToPsr7(PeclHttpResponse $httpResponse } return $psr7Response; } -} \ No newline at end of file +} diff --git a/src/ResponseFactory.php b/src/ResponseFactory.php index c92f908..31bc818 100644 --- a/src/ResponseFactory.php +++ b/src/ResponseFactory.php @@ -1,5 +1,7 @@ stream = $factory->createStream($body); } - // If body is null or empty string, it will create an empty stream on access + // If body is null or empty string, it will create an empty stream on access $this->serverParams = $serverParams; // TODO: parse queryParams from uri @@ -133,7 +136,7 @@ public function withCookieParams(array $cookies): ServerRequestInterface */ public function getQueryParams(): array { - return $this->queryParams; + return $this->queryParams; } /** @@ -163,7 +166,7 @@ public function withQueryParams(array $query): ServerRequestInterface $ret = clone $this; $ret->queryParams = $query; - return $ret; + return $ret; } /** @@ -178,7 +181,7 @@ public function withQueryParams(array $query): ServerRequestInterface * @return array An array tree of UploadedFileInterface instances; an empty * array MUST be returned if no data is present. */ - public function getUploadedFiles(): array + public function getUploadedFiles(): array { return $this->uploadedFiles; } @@ -192,7 +195,7 @@ public function getUploadedFiles(): array * * @param array $uploadedFiles An array tree of UploadedFileInterface instances. * @return static - * @throws \InvalidArgumentException if an invalid structure is provided. + * @throws InvalidArgumentException if an invalid structure is provided. */ public function withUploadedFiles(array $uploadedFiles): ServerRequestInterface { @@ -216,7 +219,7 @@ public function withUploadedFiles(array $uploadedFiles): ServerRequestInterface * @return null|array|object The deserialized body parameters, if any. * These will typically be an array or object. */ - public function getParsedBody(): null|array|object + public function getParsedBody(): array|object|null { return $this->parsedBody; } @@ -246,7 +249,7 @@ public function getParsedBody(): null|array|object * @param null|array|object $data The deserialized body data. This will * typically be in an array or object. * @return static - * @throws \InvalidArgumentException if an unsupported argument type is + * @throws InvalidArgumentException if an unsupported argument type is * provided. */ public function withParsedBody($data): ServerRequestInterface diff --git a/src/Stream.php b/src/Stream.php index dfe670a..1a64978 100644 --- a/src/Stream.php +++ b/src/Stream.php @@ -1,6 +1,9 @@ stream = $stream; $this->streamFactory = $streamFactory; $this->size = $size; @@ -65,7 +64,7 @@ public function __construct( * an exception. * * @return StreamInterface Stream representation of the uploaded file. - * @throws \RuntimeException in cases when no stream is available or can be + * @throws RuntimeException in cases when no stream is available or can be * created. */ public function getStream(): StreamInterface @@ -105,8 +104,8 @@ public function getStream(): StreamInterface * @see http://php.net/is_uploaded_file * @see http://php.net/move_uploaded_file * @param string $targetPath Path to which to move the uploaded file. - * @throws \InvalidArgumentException if the $targetPath specified is invalid. - * @throws \RuntimeException on any error during the move operation, or on + * @throws InvalidArgumentException if the $targetPath specified is invalid. + * @throws RuntimeException on any error during the move operation, or on * the second or subsequent call to the method. */ public function moveTo(string $targetPath): void @@ -124,10 +123,10 @@ public function moveTo(string $targetPath): void while (!$this->stream->eof()) { $target->write($this->stream->read($this->copyChunkSize)); } - + $this->hasCalledMoveTo = true; } - + /** * Retrieve the file size. * @@ -137,11 +136,11 @@ public function moveTo(string $targetPath): void * * @return int|null The file size in bytes or null if unknown. */ - public function getSize(): int|null + public function getSize(): ?int { return $this->size; } - + /** * Retrieve the error associated with the uploaded file. * @@ -160,7 +159,7 @@ public function getError(): int { return $this->error; } - + /** * Retrieve the filename sent by the client. * @@ -174,11 +173,11 @@ public function getError(): int * @return string|null The filename sent by the client or null if none * was provided. */ - public function getClientFilename(): string|null + public function getClientFilename(): ?string { - return $this->clientFileName; + return $this->clientFileName; } - + /** * Retrieve the media type sent by the client. * @@ -192,7 +191,7 @@ public function getClientFilename(): string|null * @return string|null The media type sent by the client or null if none * was provided. */ - public function getClientMediaType(): string|null + public function getClientMediaType(): ?string { return $this->clientMediaType; } diff --git a/src/UploadedFileFactory.php b/src/UploadedFileFactory.php index dc8fb42..6bbc89c 100644 --- a/src/UploadedFileFactory.php +++ b/src/UploadedFileFactory.php @@ -1,10 +1,15 @@ scheme = isset($parts['scheme']) ? HordeString::lower($parts['scheme']) : ''; @@ -285,7 +288,7 @@ public function getFragment(): string * * @param string $scheme The scheme to use with the new instance. * @return static A new instance with the specified scheme. - * @throws \InvalidArgumentException for invalid or unsupported schemes. + * @throws InvalidArgumentException for invalid or unsupported schemes. */ public function withScheme($scheme): self { @@ -336,7 +339,7 @@ public function withUserInfo($user, $password = null): self * * @param string $host The hostname to use with the new instance. * @return static A new instance with the specified host. - * @throws \InvalidArgumentException for invalid hostnames. + * @throws InvalidArgumentException for invalid hostnames. */ public function withHost($host): self { @@ -372,7 +375,7 @@ public function withHost($host): self * @param null|int $port The port to use with the new instance; a null value * removes the port information. * @return static A new instance with the specified port. - * @throws \InvalidArgumentException for invalid ports. + * @throws InvalidArgumentException for invalid ports. */ public function withPort($port): self { @@ -414,7 +417,7 @@ public function withPort($port): self * * @param string $path The path to use with the new instance. * @return static A new instance with the specified path. - * @throws \InvalidArgumentException for invalid paths. + * @throws InvalidArgumentException for invalid paths. */ public function withPath($path): self { @@ -442,7 +445,7 @@ public function withPath($path): self * * @param string $query The query string to use with the new instance. * @return static A new instance with the specified query string. - * @throws \InvalidArgumentException for invalid query strings. + * @throws InvalidArgumentException for invalid query strings. */ public function withQuery($query): self { @@ -515,7 +518,7 @@ public function __toString(): string $path = '/' . $path; } if (empty($authority) && substr($path, 0, 2) == '//') { - $path = '/' . \ltrim($path, '/'); + $path = '/' . ltrim($path, '/'); } $uri .= $path; } diff --git a/src/UriFactory.php b/src/UriFactory.php index d4eb310..d210812 100644 --- a/src/UriFactory.php +++ b/src/UriFactory.php @@ -1,16 +1,19 @@ run(); +Horde_Test_AllTests::init(__FILE__)->run(); diff --git a/test/Unnamespaced/ClientTest.php b/test/Live/Unnamespaced/ClientTest.php similarity index 77% rename from test/Unnamespaced/ClientTest.php rename to test/Live/Unnamespaced/ClientTest.php index c8b080e..29ff09a 100644 --- a/test/Unnamespaced/ClientTest.php +++ b/test/Live/Unnamespaced/ClientTest.php @@ -1,7 +1,7 @@ $request) + ['request' => $request] ); $client->{'request.timeout'} = 10; $this->assertEquals(10, $request->timeout); } - /** - * @expectedException Horde_Http_Exception - */ public function testSetUnknownOption() { $this->expectException('Horde_Http_Exception'); $request = new Horde_Http_Request_Mock(); $client = new Horde_Http_Client( - array('request' => $request) + ['request' => $request] ); $client->timeout = 10; } diff --git a/test/Unnamespaced/CurlTest.php b/test/Live/Unnamespaced/CurlTest.php similarity index 70% rename from test/Unnamespaced/CurlTest.php rename to test/Live/Unnamespaced/CurlTest.php index f7b8498..eec584b 100644 --- a/test/Unnamespaced/CurlTest.php +++ b/test/Live/Unnamespaced/CurlTest.php @@ -1,22 +1,26 @@ new Horde_Http_Request_Fopen() - )); + $client = new Horde_Http_Client([ + 'request' => new Horde_Http_Request_Fopen(), + ]); $response = $client->get($this->_server . '/doesntexist'); $body = $response->getBody(); $this->assertTrue(strlen($body) > 0); diff --git a/test/Unnamespaced/Peclhttp2Test.php b/test/Live/Unnamespaced/Peclhttp2Test.php similarity index 82% rename from test/Unnamespaced/Peclhttp2Test.php rename to test/Live/Unnamespaced/Peclhttp2Test.php index 4afa6df..a984be3 100644 --- a/test/Unnamespaced/Peclhttp2Test.php +++ b/test/Live/Unnamespaced/Peclhttp2Test.php @@ -1,13 +1,15 @@ new self::$_requestClass()) + ['request' => new self::$_requestClass()] ); $response = $client->get('http://' . $this->_server); @@ -77,26 +80,23 @@ public function testRequest() public function testThrowsOnBadUri() { $client = new Horde_Http_Client([ - 'request' => new self::$_requestClass() + 'request' => new self::$_requestClass(), ]); $this->expectException(Horde_Http_Exception::class); $client->get('http://doesntexist/'); } - /** - * @expectedException Horde_Http_Exception - */ public function testThrowsOnInvalidProxyType() { $client = new Horde_Http_Client( - array( + [ 'request' => new self::$_requestClass( - array( + [ 'proxyServer' => 'localhost', - 'proxyType' => Horde_Http::PROXY_SOCKS4 - ) - ) - ) + 'proxyType' => Horde_Http::PROXY_SOCKS4, + ] + ), + ] ); $this->expectException(Horde_Http_Exception::class); $client->get('http://www.example.com/'); @@ -106,7 +106,7 @@ public function testReturnsResponseInsteadOfExceptionOn404() { $this->_skipMissingConfig(); $client = new Horde_Http_Client( - array('request' => new self::$_requestClass()) + ['request' => new self::$_requestClass()] ); $response = $client->get('http://' . $this->_server . '/doesntexist'); $this->assertEquals(404, $response->code); @@ -116,7 +116,7 @@ public function testGetBodyAfter404() { $this->_skipMissingConfig(); $client = new Horde_Http_Client( - array('request' => new self::$_requestClass()) + ['request' => new self::$_requestClass()] ); $response = $client->get('http://' . $this->_server . '/doesntexist'); $content = $response->getBody(); diff --git a/test/Unnamespaced/MockTest.php b/test/Unit/MockTest.php similarity index 67% rename from test/Unnamespaced/MockTest.php rename to test/Unit/MockTest.php index 04114c4..7cbb59f 100644 --- a/test/Unnamespaced/MockTest.php +++ b/test/Unit/MockTest.php @@ -1,4 +1,5 @@ * @license http://www.horde.org/licenses/bsd * @link http://www.horde.org/libraries/Horde_Http + * @coversNothing */ class MockTest extends TestCase { public function testNoResponses() { $mock = new Horde_Http_Request_Mock(); - $client = new Horde_Http_Client(array('request' => $mock)); + $client = new Horde_Http_Client(['request' => $mock]); $this->assertNull($client->get()); } @@ -46,7 +50,7 @@ public function testPreparedResponse() $response = new Horde_Http_Response_Mock('', $stream->fopen()); $mock = new Horde_Http_Request_Mock(); $mock->setResponse($response); - $client = new Horde_Http_Client(array('request' => $mock)); + $client = new Horde_Http_Client(['request' => $mock]); $this->assertEquals('Test', $client->get()->getBody()); } @@ -54,7 +58,7 @@ public function testAddResponseBody() { $mock = new Horde_Http_Request_Mock(); $mock->addResponse('Test'); - $client = new Horde_Http_Client(array('request' => $mock)); + $client = new Horde_Http_Client(['request' => $mock]); $this->assertEquals('Test', $client->get()->getBody()); } @@ -62,7 +66,7 @@ public function testAddResponseCode() { $mock = new Horde_Http_Request_Mock(); $mock->addResponse('Test', 404); - $client = new Horde_Http_Client(array('request' => $mock)); + $client = new Horde_Http_Client(['request' => $mock]); $this->assertEquals(404, $client->get()->code); } @@ -70,24 +74,24 @@ public function testAddResponseUri() { $mock = new Horde_Http_Request_Mock(); $mock->addResponse('Test', 404, 'http://example.org'); - $client = new Horde_Http_Client(array('request' => $mock)); + $client = new Horde_Http_Client(['request' => $mock]); $this->assertEquals('http://example.org', $client->get()->uri); } public function testAddResponseHeader() { $mock = new Horde_Http_Request_Mock(); - $mock->addResponse('Test', 404, 'http://example.org', array('Test: TEST')); - $client = new Horde_Http_Client(array('request' => $mock)); + $mock->addResponse('Test', 404, 'http://example.org', ['Test: TEST']); + $client = new Horde_Http_Client(['request' => $mock]); $this->assertEquals('TEST', $client->get()->getHeader('test')); - $this->assertEquals(array('test' => 'TEST'), $client->get()->headers); + $this->assertEquals(['test' => 'TEST'], $client->get()->headers); } public function testAddStringResponses() { $mock = new Horde_Http_Request_Mock(); - $mock->addResponses(array('A', 'B')); - $client = new Horde_Http_Client(array('request' => $mock)); + $mock->addResponses(['A', 'B']); + $client = new Horde_Http_Client(['request' => $mock]); $client->get(); $this->assertEquals('B', $client->get()->getBody()); } @@ -96,18 +100,18 @@ public function testAddArrayResponses() { $mock = new Horde_Http_Request_Mock(); $mock->addResponses( - array( - array('body' => 'A'), - array('code' => 404), - array('uri' => 'http://example.org'), - array('headers' => 'Test: TEST'), - ) + [ + ['body' => 'A'], + ['code' => 404], + ['uri' => 'http://example.org'], + ['headers' => 'Test: TEST'], + ] ); - $client = new Horde_Http_Client(array('request' => $mock)); + $client = new Horde_Http_Client(['request' => $mock]); $this->assertEquals('A', $client->get()->getBody()); $this->assertEquals(404, $client->get()->code); $this->assertEquals('http://example.org', $client->get()->uri); $this->assertEquals('TEST', $client->get()->getHeader('test')); - $this->assertEquals(array('test' => 'TEST'), $client->get()->headers); + $this->assertEquals(['test' => 'TEST'], $client->get()->headers); } } diff --git a/test/ResponseTest.php b/test/Unit/ResponseTest.php similarity index 93% rename from test/ResponseTest.php rename to test/Unit/ResponseTest.php index 782d1bf..8216966 100644 --- a/test/ResponseTest.php +++ b/test/Unit/ResponseTest.php @@ -1,22 +1,23 @@ expectException(InvalidArgumentException::class); - $this->expectDeprecationMessageMatches('/0x00, 0x0d, 0x0a$/'); + $this->expectExceptionMessageMatches('/0x00, 0x0d, 0x0a$/'); $headerName = 'TestHeader'; $headerValue = chr(0x00); $headerValue .= chr(0x0D); @@ -30,7 +31,7 @@ public function testStoreHeaderWithWrongHeaderValues() public function testHeaderThrowsExceptionWithWrongHeaderNames() { $this->expectException(InvalidArgumentException::class); - $this->expectDeprecationMessageMatches('/0x01, 0x05, 0x0a, 0x00, 0x20$/'); + $this->expectExceptionMessageMatches('/0x01, 0x05, 0x0a, 0x00, 0x20$/'); $headerName = 'TestHeader'; $headerName = chr(0x01); $headerName .= chr(0x05); diff --git a/test/ServerRequestTest.php b/test/Unit/ServerRequestTest.php similarity index 96% rename from test/ServerRequestTest.php rename to test/Unit/ServerRequestTest.php index 662dde1..14d813a 100644 --- a/test/ServerRequestTest.php +++ b/test/Unit/ServerRequestTest.php @@ -1,6 +1,6 @@ requestFactory = new RequestFactory(); @@ -65,7 +70,7 @@ public function testHeaderDoesNotThrowErrorsForAllowedCharactersInValue() public function testHeaderThrowsExceptionWhen0a0d00InValue() { $this->expectException(InvalidArgumentException::class); - $this->expectDeprecationMessageMatches('/0x0a, 0x0d, 0x00$/'); + $this->expectExceptionMessageMatches('/0x0a, 0x0d, 0x00$/'); $headerName = 'Testheadersssbla'; $headerValue = 'Trestvalue'; $headerValue .= chr(0x0A); @@ -79,7 +84,7 @@ public function testHeaderThrowsExceptionWhen0a0d00InValue() public function testHeaderThrowsExceptionWhenAsciiCharactersTill32InName() { // This request should be refused due to invalid ascii characters in $headerName $this->expectException(InvalidArgumentException::class); - $this->expectDeprecationMessageMatches('/0x01, 0x05, 0x0a, 0x00, 0x20$/'); + $this->expectExceptionMessageMatches('/0x01, 0x05, 0x0a, 0x00, 0x20$/'); $headerName = 'TestHeader'; $headerName = chr(0x01); $headerName .= chr(0x05); @@ -361,7 +366,7 @@ public function testGetBodyReturnsNewStreamIfNotSet() public function testWithBodyCreatesWithNewBody() { $request = new ServerRequest('GET', '/foo', [], 'testbody'); - $stream = $this->createMock(StreamInterface::class); + $stream = $this->createStub(StreamInterface::class); $request = $request->withBody($stream); $body = $request->getBody(); $this->assertEquals($stream, $body); @@ -370,7 +375,7 @@ public function testWithBodyCreatesWithNewBody() public function testWithBodyPreservesMessage() { $request = new ServerRequest('GET', '/foo', [], 'testbody'); - $newRequest = $request->withBody($this->createMock(StreamInterface::class)); + $newRequest = $request->withBody($this->createStub(StreamInterface::class)); $body = $request->getBody(); $this->assertEquals('testbody', (string) $body); } @@ -442,7 +447,7 @@ public function testWithMethodPreservesMessage() public function testWithUriCreatesWithNewUri() { $path = '/new/path'; - $uri = $this->createMock(Uri::class); + $uri = $this->createStub(Uri::class); $uri->method('getPath')->willReturn($path); $request = new ServerRequest('GET', '/foo'); $request = $request->withUri($uri); @@ -452,7 +457,7 @@ public function testWithUriCreatesWithNewUri() public function testWithUriPreservesMessage() { $path = '/foo'; - $uri = $this->createMock(Uri::class); + $uri = $this->createStub(Uri::class); $uri->method('getPath')->willReturn('/new/path'); $request = new ServerRequest('GET', $path); $newRequest = $request->withUri($uri); @@ -463,7 +468,7 @@ public function testWithUriWritesHostHeader() { $path = '/foo'; $hostValue = 'custom.host.value'; - $uri = $this->createMock(Uri::class); + $uri = $this->createStub(Uri::class); $uri->method('getHost')->willReturn('localhost'); $request = new ServerRequest('GET', $path, ['host' => $hostValue]); $request = $request->withUri($uri); @@ -474,7 +479,7 @@ public function testWithUriPreservesHostHeader() { $path = '/foo'; $hostValue = 'custom.host.value'; - $uri = $this->createMock(Uri::class); + $uri = $this->createStub(Uri::class); $uri->method('getHost')->willReturn('localhost'); $request = new ServerRequest('GET', $path, ['host' => $hostValue]); $request = $request->withUri($uri, true); @@ -487,7 +492,7 @@ public function testServerRequestSetsHostAndPortHeader() { $host = 'https://www.horde.org/'; $port = 6000; - $uri = $this->createMock(Uri::class); + $uri = $this->createStub(Uri::class); $uri->method('getHost')->willReturn($host); $uri->method('getPort')->willReturn($port); $request = new ServerRequest('GET', $uri); @@ -497,7 +502,7 @@ public function testServerRequestSetsHostAndPortHeader() public function testServerRequestSetsHostHeaderNoPort() { $host = 'https://www.horde.org/'; - $uri = $this->createMock(Uri::class); + $uri = $this->createStub(Uri::class); $uri->method('getHost')->willReturn($host); $request = new ServerRequest('GET', $uri); $this->assertEquals(["$host"], $request->getHeader('Host')); @@ -544,7 +549,7 @@ public function testWithQueryParamsPreservesMessage() public function testWithUploadedFilesCreatesWithNewUploadedFiles() { - $files = [$this->createMock(UploadedFileInterface::class)]; + $files = [$this->createStub(UploadedFileInterface::class)]; $request = new ServerRequest('GET', '/foo'); $request = $request->withUploadedFiles($files); $this->assertEquals($files, $request->getUploadedFiles()); @@ -552,7 +557,7 @@ public function testWithUploadedFilesCreatesWithNewUploadedFiles() public function testWithUploadedFilesPreservesMessage() { - $files = [$this->createMock(UploadedFileInterface::class)]; + $files = [$this->createStub(UploadedFileInterface::class)]; $request = new ServerRequest('GET', '/foo'); $newRequest = $request->withUploadedFiles($files); $this->assertEquals([], $request->getUploadedFiles()); diff --git a/test/StreamTest.php b/test/Unit/StreamTest.php similarity index 93% rename from test/StreamTest.php rename to test/Unit/StreamTest.php index eb8701d..1e47c5a 100644 --- a/test/StreamTest.php +++ b/test/Unit/StreamTest.php @@ -1,23 +1,25 @@ isSeekable(); - $this->assertSame(true, $isReadable);; + $this->assertSame(true, $isReadable); + ; } public function testIsNotSeekable() @@ -25,7 +27,8 @@ public function testIsNotSeekable() $stream = new Stream(fopen('php://temp', 'r')); $stream->close(); $isReadable = $stream->isSeekable(); - $this->assertSame(false, $isReadable);; + $this->assertSame(false, $isReadable); + ; } public function testExceptionWhenNoResource() @@ -69,7 +72,8 @@ public function testTellImmediately() { $stream = new Stream(fopen('php://temp', 'r+')); $tell = $stream->tell(); - $this->assertSame(0, $tell);; + $this->assertSame(0, $tell); + ; } public function testTell() @@ -77,7 +81,8 @@ public function testTell() $stream = new Stream(fopen('php://temp', 'r+')); $stream->write('123456789TestXYZ'); $tell = $stream->tell(); - $this->assertSame(16, $tell);; + $this->assertSame(16, $tell); + ; } public function testWriteReadAndEof() diff --git a/test/UriTest.php b/test/Unit/UriTest.php similarity index 98% rename from test/UriTest.php rename to test/Unit/UriTest.php index b3c9893..7cb8ae8 100644 --- a/test/UriTest.php +++ b/test/Unit/UriTest.php @@ -1,6 +1,6 @@