Skip to content
This repository has been archived by the owner on Jan 29, 2020. It is now read-only.

Commit

Permalink
Merge pull request #234 from fcabralpacheco/test-against-iana
Browse files Browse the repository at this point in the history
Adds response reason phrases test against IANA.
  • Loading branch information
weierophinney committed Apr 6, 2017
2 parents e750944 + 15c2d96 commit d512c6c
Show file tree
Hide file tree
Showing 5 changed files with 296 additions and 8 deletions.
4 changes: 3 additions & 1 deletion composer.json
Expand Up @@ -25,7 +25,9 @@
},
"require-dev": {
"phpunit/phpunit": "^4.6 || ^5.5",
"zendframework/zend-coding-standard": "~1.0.0"
"zendframework/zend-coding-standard": "~1.0.0",
"ext-dom": "*",
"ext-libxml": "*"
},
"provide": {
"psr/http-message-implementation": "~1.0.0"
Expand Down
14 changes: 7 additions & 7 deletions src/Response.php
Expand Up @@ -42,7 +42,7 @@ class Response implements ResponseInterface
204 => 'No Content',
205 => 'Reset Content',
206 => 'Partial Content',
207 => 'Multi-status',
207 => 'Multi-Status',
208 => 'Already Reported',
226 => 'IM Used',
// REDIRECTION CODES
Expand All @@ -64,15 +64,15 @@ class Response implements ResponseInterface
405 => 'Method Not Allowed',
406 => 'Not Acceptable',
407 => 'Proxy Authentication Required',
408 => 'Request Time-out',
408 => 'Request Timeout',
409 => 'Conflict',
410 => 'Gone',
411 => 'Length Required',
412 => 'Precondition Failed',
413 => 'Request Entity Too Large',
414 => 'Request-URI Too Large',
413 => 'Payload Too Large',
414 => 'URI Too Long',
415 => 'Unsupported Media Type',
416 => 'Requested range not satisfiable',
416 => 'Range Not Satisfiable',
417 => 'Expectation Failed',
418 => 'I\'m a teapot',
421 => 'Misdirected Request',
Expand All @@ -92,8 +92,8 @@ class Response implements ResponseInterface
501 => 'Not Implemented',
502 => 'Bad Gateway',
503 => 'Service Unavailable',
504 => 'Gateway Time-out',
505 => 'HTTP Version not supported',
504 => 'Gateway Timeout',
505 => 'HTTP Version Not Supported',
506 => 'Variant Also Negotiates',
507 => 'Insufficient Storage',
508 => 'Loop Detected',
Expand Down
57 changes: 57 additions & 0 deletions test/ResponseTest.php
Expand Up @@ -66,6 +66,63 @@ public function testReasonPhraseDefaultsToStandards()
$this->assertEquals('Unprocessable Entity', $response->getReasonPhrase());
}

public function ianaCodesReasonPhrasesProvider()
{
$ianaHttpStatusCodes = new \DOMDocument();

libxml_set_streams_context(
stream_context_create(
[
'http' => [
'method' => 'GET',
'timeout' => 30,
],
]
)
);

$ianaHttpStatusCodes->load('https://www.iana.org/assignments/http-status-codes/http-status-codes.xml');

if (! $ianaHttpStatusCodes->relaxNGValidate(__DIR__ . '/TestAsset/http-status-codes.rng')) {
self::fail();
}

$ianaCodesReasonPhrases = [];

$xpath = new \DomXPath($ianaHttpStatusCodes);
$xpath->registerNamespace('ns', 'http://www.iana.org/assignments');

$records = $xpath->query('//ns:record');

foreach ($records as $record) {
$value = $xpath->query('.//ns:value', $record)->item(0)->nodeValue;
$description = $xpath->query('.//ns:description', $record)->item(0)->nodeValue;

if (in_array($description, ['Unassigned', '(Unused)'])) {
continue;
}

if (preg_match('/^([0-9]+)\s*\-\s*([0-9]+)$/', $value, $matches)) {
for ($value = $matches[1]; $value <= $matches[2]; $value++) {
$ianaCodesReasonPhrases[] = [$value, $description];
}
} else {
$ianaCodesReasonPhrases[] = [$value, $description];
}
}

return $ianaCodesReasonPhrases;
}

/**
* @dataProvider ianaCodesReasonPhrasesProvider
*/
public function testReasonPhraseDefaultsAgainstIana($code, $reasonPhrase)
{
$response = $this->response->withStatus($code);
$this->assertEquals($reasonPhrase, $response->getReasonPhrase());
}

public function testCanSetCustomReasonPhrase()
{
$response = $this->response->withStatus(422, 'Foo Bar!');
Expand Down
31 changes: 31 additions & 0 deletions test/TestAsset/http-status-codes.rng
@@ -0,0 +1,31 @@
<?xml version='1.0'?>
<grammar xmlns="http://relaxng.org/ns/structure/1.0"
datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"
ns="http://www.iana.org/assignments">

<include href="iana-registry.rng"/>

<start>
<element name="registry">
<ref name="registryMeta"/>
<element name="registry">
<ref name="registryMeta"/>
<zeroOrMore>
<element name="record">
<optional>
<attribute name="date"><ref name="genericDate"/></attribute>
</optional>
<optional>
<attribute name="updated"><ref name="genericDate"/></attribute>
</optional>
<element name="value"><ref name="genericRange"/></element>
<element name="description"><text/></element>
<ref name="references"/>
</element>
</zeroOrMore>
</element>
<ref name="people"/>
</element>
</start>

</grammar>
198 changes: 198 additions & 0 deletions test/TestAsset/iana-registry.rng
@@ -0,0 +1,198 @@
<?xml version='1.0'?>
<grammar xmlns="http://relaxng.org/ns/structure/1.0"
datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"
ns="http://www.iana.org/assignments">

<define name="registryMeta">
<interleave>
<attribute name="id"><data type="ID"/></attribute>
<optional><element name="title"><ref name="text_with_references"/></element></optional>
<optional><element name="created"><ref name="genericDate"/></element></optional>
<optional><element name="updated"><data type="date"/></element></optional>
<optional><element name="registration_rule"><ref
name="text_with_references"/></element></optional>
<optional><element name="expert"><text/></element></optional>
<optional><element name="description"><ref name="text_with_references"/></element></optional>
<zeroOrMore><element name="note"><ref name="text_with_references"/></element></zeroOrMore>
<ref name="references"/>
<optional><element name="hide"><empty/></element></optional>
<zeroOrMore><element name="category"><text/></element></zeroOrMore>
<zeroOrMore><ref name="range"/></zeroOrMore>
<optional><ref name="file"/></optional>
</interleave>
</define>

<define name="range">
<element name="range">
<interleave>
<element name="value"><text/></element>
<optional><element name="hex"><text/></element></optional>
<element name="registration_rule"><ref name="text_with_references"/></element>
<optional><element name="note"><ref name="text_with_references"/></element></optional>
<optional><ref name="xref"/></optional>
</interleave>
</element>
</define>

<define name="people">
<element name="people">
<zeroOrMore>
<element name="person">
<attribute name="id"><data type="ID"/></attribute>
<optional><element name="name"><text/></element></optional>
<optional><element name="org"><text/></element></optional>
<zeroOrMore><element name="uri"><data type="anyURI"/></element></zeroOrMore>
<optional><element name="updated"><ref name="genericDate"/></element></optional>
</element>
</zeroOrMore>
</element>
</define>

<define name="xref">
<element name="xref">
<optional>
<attribute name="lastupdated"><ref name="genericDate"/></attribute>
</optional>
<choice>
<group>
<attribute name="type"><value>uri</value></attribute>
<attribute name="data"><data type="anyURI"/></attribute>
</group>
<group>
<attribute name="type"><value>rfc</value></attribute>
<attribute name="data">
<data type="string">
<param name="pattern">(rfc|bcp|std)\d+</param>
</data>
</attribute>
</group>
<group>
<attribute name="type"><value>rfc-errata</value></attribute>
<attribute name="data"><data type="positiveInteger"/></attribute>
</group>
<group>
<attribute name="type"><value>draft</value></attribute>
<attribute name="data">
<data type="string">
<param name="pattern">(draft|RFC)(-[a-zA-Z0-9]+)+</param>
</data>
</attribute>
</group>
<group>
<attribute name="type"><value>registry</value></attribute>
<attribute name="data"><data type="NCName"/></attribute>
</group>
<group>
<attribute name="type"><value>person</value></attribute>
<attribute name="data"><data type="NCName"/></attribute>
</group>
<group>
<attribute name="type"><value>text</value></attribute>
</group>
<group>
<attribute name="type"><value>note</value></attribute>
<attribute name="data"><data type="positiveInteger"/></attribute>
</group>
<group>
<attribute name="type"><value>unicode</value></attribute>
<attribute name="data">
<data type="string">
<param name="pattern">ucd\d+\.\d+\.\d+</param>
</data>
</attribute>
</group>
</choice>
<text/>
</element>
</define>

<define name="references">
<zeroOrMore>
<ref name="xref"/>
</zeroOrMore>
</define>

<define name="text_with_references">
<interleave>
<zeroOrMore>
<text/>
<optional><ref name="xref"/></optional>
</zeroOrMore>
</interleave>
</define>

<define name="richText">
<zeroOrMore>
<choice>
<interleave>
<ref name="text_with_references"/>
<optional><element name="br"><empty/></element></optional>
</interleave>
<element name="paragraph">
<interleave>
<ref name="text_with_references"/>
<optional><element name="br"><empty/></element></optional>
</interleave>
</element>
<element name="artwork"><text/></element>
</choice>
</zeroOrMore>
</define>

<define name="genericRange">
<data type="string">
<param name="pattern">(\d+|0x[\da-fA-F]+)(\s*-\s*(\d+|0x[\da-fA-F]+))?</param>
</data>
</define>

<define name="genericDate">
<choice>
<data type="date"/>
<data type="gYearMonth"/>
</choice>
</define>

<define name="hex32">
<data type="string">
<param name="pattern">0x[0-9]{8}</param>
</data>
</define>

<define name="binary">
<data type="string">
<param name="pattern">[0-1]+</param>
</data>
</define>

<define name="footnotes">
<zeroOrMore>
<element name="footnote">
<attribute name="anchor"><data type="positiveInteger"/></attribute>
<interleave>
<zeroOrMore>
<text/>
<optional><ref name="xref"/></optional>
</zeroOrMore>
</interleave>
</element>
</zeroOrMore>
</define>

<define name="file">
<element name="file">
<attribute name="type">
<choice>
<value>legacy</value>
<value>mib</value>
<value>template</value>
<value>json</value>
</choice>
</attribute>
<optional>
<attribute name="name"/>
</optional>
<data type="anyURI"/>
</element>
</define>

</grammar>

0 comments on commit d512c6c

Please sign in to comment.