Browse Source

Initial URL tests and fixes

master
J. King 4 years ago
parent
commit
0f4d851c6a
  1. 51
      lib/Url.php
  2. 514
      tests/cases/Util/Url/AbstractUriTestCase.php
  3. 38
      tests/cases/Util/Url/README
  4. 1877
      tests/cases/Util/Url/setters_tests.json
  5. 149
      tests/cases/Util/Url/toascii.json
  6. 6731
      tests/cases/Util/Url/urltestdata.json
  7. 9
      tests/cases/Util/UrlTest.php
  8. 2
      tests/phpunit.dist.xml

51
lib/Url.php

@ -63,8 +63,9 @@ PCRE;
)?
$>six
PCRE;
protected const SCHEME_PATTERN = "<^[a-z][a-z0-9\.\-\+]*$>i";
protected const PORT_PATTERN = "<^\d+$>";
protected const SCHEME_PATTERN = "<^(?:[a-z][a-z0-9\.\-\+]*|)$>i";
protected const IPV6_PATTERN = "<^\[[a-f0-9:]+\]$>i";
protected const PORT_PATTERN = "<^\d*$>";
protected const ESCAPE_CHARS = [
'user' => [":", "@", "/", "?", "#"],
'pass' => ["@", "/", "?", "#"],
@ -87,20 +88,20 @@ PCRE;
public function __construct(string $url, ?UriInterface $baseUrl = null) {
if (preg_match(self::URI_PATTERN, $url, $match)) {
[$url, $scheme, $authority, $path, $query, $fragment] = $match;
[$url, $scheme, $authority, $path, $query, $fragment] = array_pad($match, 6, "");
foreach (["scheme", "path", "query", "fragment"] as $part) {
if (strlen($$part)) {
if ($part === "query" || $part === "fragment") {
$$part = substr($$part, 1);
}
$this->__set($part, $$part);
$this->set($part, $$part);
}
}
if (strlen($authority)) {
if (preg_match(self::AUTHORITY_PATTERN, $authority, $match)) {
[$authority, $user, $pass, $host, $port] = $match;
[$authority, $user, $pass, $host, $port] = array_pad($match, 5, "");
foreach (["user", "pass", "host", "port"] as $part) {
$this->__set($part, $$part);
$this->set($part, $$part);
}
}
}
@ -158,54 +159,57 @@ PCRE;
public function withFragment($fragment) {
$out = clone $this;
$out->fragment = $fragment;
$out->set("fragment", $fragment);
return $out;
}
public function withHost($host) {
if ($host === "") {
$host = null;
}
$out = clone $this;
$out->host = $host;
$out->set("host", $host);
return $out;
}
public function withPath($path) {
$out = clone $this;
$out->path = $path;
$out->set("path", $path);
return $out;
}
public function withPort($port) {
$out = clone $this;
$out->port = $port;
$out->set("port", $port);
return $out;
}
public function withQuery($query) {
$out = clone $this;
$out->query = $query;
$out->set("query", $query);
return $out;
}
public function withScheme($scheme) {
$out = clone $this;
$out->scheme = $scheme;
$out->set("scheme", $scheme);
return $out;
}
public function withUserInfo($user, $password = null) {
$out = clone $this;
$out->user = $user;
$out->pass = $password;
$out->set("user", $user);
$out->set("pass", $password);
return $out;
}
public function __toString() {
$out = "";
$out .= strlen($this->scheme) ? $this->scheme.":" : "";
if (is_null($this->host)) {
$out .= strlen($this->scheme) ? $this->scheme.":" : "";
$out .= $this->path;
} else {
$out .= $this->scheme."://";
$out .= "//";
$out .= $this->getAuthority();
$out .= ($this->path[0] ?? "") === "/" ? "" : "/";
$out .= preg_replace("<^/{2,}/>", "/", $this->path);
@ -219,7 +223,7 @@ PCRE;
return $this->$name;
}
public function __set(string $name, $value): void {
protected function set(string $name, $value): void {
switch ($name) {
case "host":
$this->host = $this->normalizeHost($value);
@ -322,17 +326,22 @@ PCRE;
/** Normalizes a hostname per IDNA:2008 */
protected function normalizeHost(?string $host): ?string {
$host = trim($host);
if (!is_null($host) && strlen($host)) {
if ($host[0] === "[" && substr($host, -1) === "]") {
if (preg_match(self::IPV6_PATTERN, $host)) {
// normalize IPv6 addresses
$addr = @inet_pton(substr($host, 1, strlen($host) - 2));
if ($addr !== false) {
return "[".inet_ntop($addr)."]";
}
}
$idn = idn_to_ascii($host, \IDNA_NONTRANSITIONAL_TO_ASCII, \INTL_IDNA_VARIANT_UTS46);
$host = $idn !== false ? idn_to_utf8($idn, \IDNA_NONTRANSITIONAL_TO_UNICODE, \INTL_IDNA_VARIANT_UTS46) : $host;
$idn = idn_to_ascii($host, \IDNA_NONTRANSITIONAL_TO_ASCII | \IDNA_CHECK_BIDI | \IDNA_CHECK_CONTEXTJ, \INTL_IDNA_VARIANT_UTS46);
if ($idn === false) {
throw new \InvalidArgumentException("Invalid host in URL");
}
$host = idn_to_utf8($idn, \IDNA_NONTRANSITIONAL_TO_UNICODE | \IDNA_USE_STD3_RULES, \INTL_IDNA_VARIANT_UTS46);
if ($host === false) {
throw new \InvalidArgumentException("Invalid host in URL");
}
}
return $host;
}

514
tests/cases/Util/Url/AbstractUriTestCase.php

@ -0,0 +1,514 @@
<?php
namespace JKingWeb\Lax\TestCase\Util\Url;
use Psr\Http\Message\UriInterface;
use PHPUnit\Framework\TestCase;
use InvalidArgumentException;
abstract class AbstractUriTestCase extends TestCase
{
/**
* @var UriInterface
*/
protected $uri;
protected $uri_string = 'http://login:pass@secure.example.com:443/test/query.php?kingkong=toto#doc3';
/**
* UriInterface factory
*
* @param string $uri
*
* @return UriInterface
*/
abstract protected function createUri($uri = '');
protected function setUp(): void
{
$this->uri = $this->createUri($this->uri_string);
}
protected function tearDown(): void
{
$this->uri = null;
}
/**
* @group scheme
* @dataProvider schemeProvider
*
* The value returned MUST be normalized to lowercase, per RFC 3986
* Section 3.1.
*/
public function testGetScheme($scheme, $expected)
{
$uri = $this->uri->withScheme($scheme);
$this->assertInstanceOf(UriInterface::class, $uri);
$this->assertSame($expected, $uri->getScheme(), 'Scheme must be normalized according to RFC3986');
}
public function schemeProvider()
{
return [
'normalized scheme' => ['HtTpS', 'https'],
'simple scheme' => ['http', 'http'],
'no scheme' => ['', ''],
];
}
/**
* @group userinfo
* @dataProvider userInfoProvider
*
* If a user is present in the URI, this will return that value;
* additionally, if the password is also present, it will be appended to the
* user value, with a colon (":") separating the values.
*
*/
public function testGetUserInfo($user, $pass, $expected)
{
$uri = $this->uri->withUserInfo($user, $pass);
$this->assertInstanceOf(UriInterface::class, $uri);
$this->assertSame($expected, $uri->getUserInfo(), 'UserInfo must be normalized according to RFC3986');
}
public function userInfoProvider()
{
return [
'with userinfo' => ['iGoR', 'rAsMuZeN', 'iGoR:rAsMuZeN'],
'no userinfo' => ['', '', ''],
'no pass' => ['iGoR', '', 'iGoR'],
'pass is null' => ['iGoR', null, 'iGoR'],
'case sensitive' => ['IgOr', 'RaSm0537', 'IgOr:RaSm0537'],
];
}
/**
* @group host
* @dataProvider hostProvider
*
* The value returned MUST be normalized to lowercase, per RFC 3986
* Section 3.2.2.
*
*/
public function testGetHost($host, $expected)
{
$uri = $this->uri->withHost($host);
$this->assertInstanceOf(UriInterface::class, $uri);
$this->assertSame($expected, $uri->getHost(), 'Host must be normalized according to RFC3986');
}
public function hostProvider()
{
return [
'normalized host' => ["MaStEr.eXaMpLe.CoM", "master.example.com"],
"simple host" => ["www.example.com", "www.example.com"],
"IPv6 Host" => ["[::1]", "[::1]"],
];
}
/**
* @group port
* @dataProvider portProvider
*
* If a port is present, and it is non-standard for the current scheme,
* this method MUST return it as an integer. If the port is the standard port
* used with the current scheme, this method SHOULD return null.
*
* If no port is present, and no scheme is present, this method MUST return
* a null value.
*
* If no port is present, but a scheme is present, this method MAY return
* the standard port for that scheme, but SHOULD return null.
*/
public function testPort($uri, $port, $expected)
{
$uri = $this->createUri($uri)->withPort($port);
$this->assertInstanceOf(UriInterface::class, $uri);
$this->assertSame($expected, $uri->getPort(), 'port must be an int or null');
}
public function portProvider()
{
return [
'non standard port for http' => ['http://www.example.com', 443, 443],
'remove port' => ['http://www.example.com', null, null],
'standard port on schemeless http url' => ['//www.example.com', 80, 80],
];
}
/**
* @group port
*/
public function testUriWithStandardPort()
{
$uri = $this->createUri('http://example.com:80');
$this->assertContains($uri->getPort(), [80, null], "If no port is present, but a scheme is present, this method MAY return the standard port for that scheme, but SHOULD return null.");
}
/**
* @group authority
* @dataProvider authorityProvider
*
* If the port component is not set or is the standard port for the current
* scheme, it SHOULD NOT be included.
*/
public function testGetAuthority($scheme, $user, $pass, $host, $port, $authority)
{
$uri = $this
->createUri()
->withHost($host)
->withScheme($scheme)
->withUserInfo($user, $pass)
->withPort($port)
;
$this->assertSame($authority, $uri->getAuthority());
}
public function authorityProvider()
{
return [
'authority' => [
'scheme' => 'http',
'user' => 'iGoR',
'pass' => 'rAsMuZeN',
'host' => 'master.example.com',
'port' => 443,
'authority' => 'iGoR:rAsMuZeN@master.example.com:443',
],
'without port' => [
'scheme' => 'http',
'user' => 'iGoR',
'pass' => 'rAsMuZeN',
'host' => 'master.example.com',
'port' => null,
'authority' => 'iGoR:rAsMuZeN@master.example.com',
],
'with standard port' => [
'scheme' => 'http',
'user' => 'iGoR',
'pass' => 'rAsMuZeN',
'host' => 'master.example.com',
'port' => 80,
'authority' => 'iGoR:rAsMuZeN@master.example.com:80',
],
"authority without pass" => [
'scheme' => 'http',
'user' => 'iGoR',
'pass' => '',
'host' => 'master.example.com',
'port' => null,
'authority' => 'iGoR@master.example.com',
],
"authority without port and userinfo" => [
'scheme' => 'http',
'user' => '',
'pass' => '',
'host' => 'master.example.com',
'port' => null,
'authority' => 'master.example.com',
],
];
}
/**
* @group query
* @dataProvider queryProvider
*
* The value returned MUST be percent-encoded, but MUST NOT double-encode
* any characters. To determine what characters to encode, please refer to
* RFC 3986, Sections 2 and 3.4.
*/
public function testGetQuery($query, $expected)
{
$uri = $this->uri->withQuery($query);
$this->assertInstanceOf(UriInterface::class, $uri);
$this->assertSame($expected, $uri->getQuery(), 'Query must be normalized according to RFC3986');
}
public function queryProvider()
{
return [
'normalized query' => ['foo.bar=%7evalue', 'foo.bar=~value'],
'empty query' => ['', ''],
'same param query' => ['foo.bar=1&foo.bar=1', 'foo.bar=1&foo.bar=1'],
'same param query' => ['?foo=1', '?foo=1'],
];
}
/**
* @group fragment
* @dataProvider fragmentProvider
*
* The value returned MUST be percent-encoded, but MUST NOT double-encode
* any characters. To determine what characters to encode, please refer to
* RFC 3986, Sections 2 and 3.5.
*/
public function testGetFragment($fragment, $expected)
{
$uri = $this->uri->withFragment($fragment);
$this->assertInstanceOf(UriInterface::class, $uri);
$this->assertSame($expected, $uri->getFragment(), 'Fragment must be normalized according to RFC3986');
}
public function fragmentProvider()
{
return [
'URL with full components' => ['fragment', 'fragment'],
'URL with non-encodable fragment' => ["azAZ0-9/?-._~!$&'()*+,;=:@", "azAZ0-9/?-._~!$&'()*+,;=:@"],
];
}
/**
* @group uri
* @dataProvider stringProvider
*
* - If a scheme is present, it MUST be suffixed by ":".
* - If an authority is present, it MUST be prefixed by "//".
* - The path can be concatenated without delimiters. But there are two
* cases where the path has to be adjusted to make the URI reference
* valid as PHP does not allow to throw an exception in __toString():
* - If the path is rootless and an authority is present, the path MUST
* be prefixed by "/".
* - If the path is starting with more than one "/" and no authority is
* present, the starting slashes MUST be reduced to one.
* - If a query is present, it MUST be prefixed by "?".
* - If a fragment is present, it MUST be prefixed by "#".
*/
public function testToString($scheme, $user, $pass, $host, $port, $path, $query, $fragment, $expected)
{
$uri = $this->createUri()
->withHost($host)
->withScheme($scheme)
->withUserInfo($user, $pass)
->withPort($port)
->withPath($path)
->withQuery($query)
->withFragment($fragment)
;
$this->assertSame(
$expected,
(string) $uri,
'URI string must be normalized according to RFC3986 rules'
);
}
public function stringProvider()
{
return [
'URL normalized' => [
'scheme' => 'HtTps',
'user' => 'iGoR',
'pass' => 'rAsMuZeN',
'host' => 'MaStEr.eXaMpLe.CoM',
'port' => 443,
'path' => '/%7ejohndoe/%a1/index.php',
'query' => 'foo.bar=%7evalue',
'fragment' => 'fragment',
'uri' => 'https://iGoR:rAsMuZeN@master.example.com:443/~johndoe/%A1/index.php?foo.bar=~value#fragment'
],
'URL without scheme' => [
'scheme' => '',
'user' => '',
'pass' => '',
'host' => 'www.example.com',
'port' => 443,
'path' => '/foo/bar',
'query' => 'param=value',
'fragment' => 'fragment',
'uri' => '//www.example.com:443/foo/bar?param=value#fragment',
],
'URL without authority and scheme' => [
'scheme' => '',
'user' => '',
'pass' => '',
'host' => '',
'port' => null,
'path' => 'foo/bar',
'query' => '',
'fragment' => '',
'uri' => 'foo/bar',
],
];
}
/**
* @group fragment
*/
public function testRemoveFragment()
{
$uri = 'http://example.com/path/to/me';
$this->assertSame($uri, (string) $this->createUri($uri.'#doc')->withFragment(''));
}
/**
* @group query
*/
public function testRemoveQuery()
{
$uri = 'http://example.com/path/to/me';
$this->assertSame($uri, (string) (string) $this->createUri($uri.'?name=value')->withQuery(''));
}
/**
* @group path
*/
public function testRemovePath()
{
$uri = 'http://example.com';
$this->assertContains(
(string) $this->createUri($uri.'/path/to/me')->withPath(''),
[$uri, $uri.'/']
);
}
/**
* @group port
*/
public function testRemovePort()
{
$this->assertSame(
'http://example.com/path/to/me',
(string) $this->createUri('http://example.com:81/path/to/me')->withPort(null)
);
}
/**
* @group userinfo
*/
public function testRemoveUserInfo()
{
$this->assertSame(
'http://example.com/path/to/me',
(string) $this->createUri('http://user:pass@example.com/path/to/me')->withUserInfo('')
);
}
/**
* @group scheme
*/
public function testRemoveScheme()
{
$this->assertSame(
'//example.com/path/to/me',
(string) $this->createUri('http://example.com/path/to/me')->withScheme('')
);
}
/**
* @group authority
*/
public function testRemoveAuthority()
{
$uri = 'http://user:login@example.com:82/path?q=v#doc';
$uri_with_host = $this->createUri($uri)
->withScheme('')
->withUserInfo('')
->withPort(null)
->withHost('')
;
$this->assertSame('/path?q=v#doc', (string) $uri_with_host);
}
/**
* @group scheme
* @dataProvider withSchemeFailedProvider
*/
public function testWithSchemeFailed($scheme)
{
$this->expectException(InvalidArgumentException::class);
$this->uri->withScheme($scheme);
}
public function withSchemeFailedProvider()
{
return [
'invalid char' => ['in,valid'],
'integer like string' => ['123'],
];
}
/**
* @group host
* @dataProvider withHostFailedProvider
*/
public function testWithHostFailed($host)
{
$this->expectException(InvalidArgumentException::class);
$this->uri->withHost($host);
}
public function withHostFailedProvider()
{
return [
'dot in front' => ['.example.com'],
'hyphen suffix' => ['host.com-'],
'multiple dot' => ['.......'],
'one dot' => ['.'],
'empty label' => ['tot. .coucou.com'],
'space in the label' => ['re view'],
'underscore in label' => ['_bad.host.com'],
'label too long' => [implode('', array_fill(0, 12, 'banana')).'.secure.example.com'],
'too many labels' => [implode('.', array_fill(0, 128, 'a'))],
'Invalid IPv4 format' => ['[127.0.0.1]'],
'Invalid IPv6 format' => ['[[::1]]'],
'Invalid IPv6 format 2' => ['[::1'],
'space character in starting label' => ['example. com'],
'invalid character in host label' => ["examp\0le.com"],
'invalid IP with scope' => ['[127.2.0.1%253]'],
'invalid scope IPv6' => ['ab23::1234%251'],
'invalid scope ID' => ['fe80::1234%25?@'],
'invalid scope ID with utf8 character' => ['fe80::1234%25€'],
];
}
/**
* @group host
*/
public function testModificationFailedWithInvalidHost()
{
$this->expectException(InvalidArgumentException::class);
$this->createUri('http://example.com')->withHost('?');
}
/**
* @group uri
* @dataProvider invalidURI
*/
public function testCreateFromInvalidUrlKO($uri)
{
$this->expectException(InvalidArgumentException::class);
$this->createUri($uri);
}
public function invalidURI()
{
return [
['http://user@:80'],
];
}
/**
* @group uri
*/
public function testEmptyValueDetection()
{
$expected = '//0:0@0/0?0#0';
$this->assertSame($expected, (string) $this->createUri($expected));
}
/**
* @group path
* @group uri
*/
public function testPathDetection()
{
$expected = 'foo/bar:';
$this->assertSame($expected, $this->createUri($expected)->getPath());
}
}

38
tests/cases/Util/Url/README

@ -0,0 +1,38 @@
The Url class used in Lax is an original work, but its test suite is largely
composed of existing test corpuses from the following sources:
1. The Web Platform Test suite
<https://github.com/web-platform-tests/wpt/tree/1c72611f0020534154146177001ff8758de254fd/url/resources>
2. Bakame PSR-7 UriInterface test suite
<https://github.com/bakame-php/psr7-uri-interface-tests/tree/5a556fdfe668a6c6a14772efeba6134c0b7dae34>
Their license texts are reproduced below.
Copyright 2019 web-platform-tests contributors
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Copyright (c) 2015 ignace nyamagana butera
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

1877
tests/cases/Util/Url/setters_tests.json

File diff suppressed because it is too large

149
tests/cases/Util/Url/toascii.json

@ -0,0 +1,149 @@
[
"This resource is focused on highlighting issues with UTS #46 ToASCII",
{
"comment": "Label with hyphens in 3rd and 4th position",
"input": "aa--",
"output": "aa--"
},
{
"input": "a†--",
"output": "xn--a---kp0a"
},
{
"input": "ab--c",
"output": "ab--c"
},
{
"comment": "Label with leading hyphen",
"input": "-x",
"output": "-x"
},
{
"input": "-†",
"output": "xn----xhn"
},
{
"input": "-x.xn--nxa",
"output": "-x.xn--nxa"
},
{
"input": "-x.β",
"output": "-x.xn--nxa"
},
{
"comment": "Label with trailing hyphen",
"input": "x-.xn--nxa",
"output": "x-.xn--nxa"
},
{
"input": "x-.β",
"output": "x-.xn--nxa"
},
{
"comment": "Empty labels",
"input": "x..xn--nxa",
"output": "x..xn--nxa"
},
{
"input": "x..β",
"output": "x..xn--nxa"
},
{
"comment": "Invalid Punycode",
"input": "xn--a",
"output": null
},
{
"input": "xn--a.xn--nxa",
"output": null
},
{
"input": "xn--a.β",
"output": null
},
{
"comment": "Valid Punycode",
"input": "xn--nxa.xn--nxa",
"output": "xn--nxa.xn--nxa"
},
{
"comment": "Mixed",
"input": "xn--nxa.β",
"output": "xn--nxa.xn--nxa"
},
{
"input": "ab--c.xn--nxa",
"output": "ab--c.xn--nxa"
},
{
"input": "ab--c.β",
"output": "ab--c.xn--nxa"
},
{
"comment": "CheckJoiners is true",
"input": "\u200D.example",
"output": null
},
{
"input": "xn--1ug.example",
"output": null
},
{
"comment": "CheckBidi is true",
"input": "يa",
"output": null
},
{
"input": "xn--a-yoc",
"output": null
},
{
"comment": "processing_option is Nontransitional_Processing",
"input": "ශ්‍රී",
"output": "xn--10cl1a0b660p"
},
{
"input": "نامه‌ای",
"output": "xn--mgba3gch31f060k"
},
{
"comment": "U+FFFD",
"input": "\uFFFD.com",
"output": null
},
{
"comment": "U+FFFD character encoded in Punycode",
"input": "xn--zn7c.com",
"output": null
},
{
"comment": "Label longer than 63 code points",
"input": "x01234567890123456789012345678901234567890123456789012345678901x",
"output": "x01234567890123456789012345678901234567890123456789012345678901x"
},
{
"input": "x01234567890123456789012345678901234567890123456789012345678901†",
"output": "xn--x01234567890123456789012345678901234567890123456789012345678901-6963b"
},
{
"input": "x01234567890123456789012345678901234567890123456789012345678901x.xn--nxa",
"output": "x01234567890123456789012345678901234567890123456789012345678901x.xn--nxa"
},
{
"input": "x01234567890123456789012345678901234567890123456789012345678901x.β",
"output": "x01234567890123456789012345678901234567890123456789012345678901x.xn--nxa"
},
{
"comment": "Domain excluding TLD longer than 253 code points",
"input": "01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.x",
"output": "01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.x"
},
{
"input": "01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.xn--nxa",
"output": "01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.xn--nxa"
},
{
"input": "01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.β",
"output": "01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.xn--nxa"
}
]

6731
tests/cases/Util/Url/urltestdata.json

File diff suppressed because it is too large

9
tests/cases/Util/UrlTest.php

@ -7,11 +7,12 @@ declare(strict_types=1);
namespace JKingWeb\Lax\TestCase\Util;
use JKingWeb\Lax\Url;
use JKingWeb\Lax\TestCase\Util\Url\AbstractUriTestCase;
/** @covers JKingWeb\Lax\Url<extended> */
class UrlTest extends \PHPUnit\Framework\TestCase {
public function testTemp(): void {
$url = "https://me:secret@example.com:443/file?question#bit";
$this->assertSame((string) new Url("https://me:secret@example.com:443/file?question#bit"), $url);
class UrlTest extends AbstractUriTestCase {
//class UrlTest extends \PHPUnit\Framework\TestCase {
protected function createUri($uri = '') {
return new Url($uri);
}
}

2
tests/phpunit.dist.xml

@ -9,7 +9,7 @@
beStrictAboutTestsThatDoNotTestAnything="true"
beStrictAboutOutputDuringTests="true"
forceCoversAnnotation="true"
executionOrder="defects"
executionOrder="default"
>
<filter>

Loading…
Cancel
Save