summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Tests/Services/Yadis/Discover.php171
-rw-r--r--Tests/Services/Yadis/DiscoverData.php148
-rw-r--r--Tests/Services/Yadis/ParseHTML.php88
-rw-r--r--Tests/Services/Yadis/TestUtil.php28
-rw-r--r--Tests/Services/Yadis/XRDS.php188
-rw-r--r--Tests/Services/Yadis/Yadis.php92
-rw-r--r--Tests/Services/Yadis/data/accept.txt118
-rw-r--r--Tests/Services/Yadis/data/brian.multi.xrds38
-rw-r--r--Tests/Services/Yadis/data/brian.multi_uri.xrds16
-rw-r--r--Tests/Services/Yadis/data/brian.xrds16
-rw-r--r--Tests/Services/Yadis/data/brian_priority.xrds22
-rw-r--r--Tests/Services/Yadis/data/example-xrds.xml14
-rw-r--r--Tests/Services/Yadis/data/manifest.txt30
-rw-r--r--Tests/Services/Yadis/data/no-xrd.xml7
-rw-r--r--Tests/Services/Yadis/data/not-xrds.xml2
-rw-r--r--Tests/Services/Yadis/data/test1-discover.txt137
-rw-r--r--Tests/Services/Yadis/data/test1-parsehtml.txt125
-rw-r--r--Tests/Services/Yadis/data/test1-xrd.xml39
-rw-r--r--Tests/Services/Yadis/data/uri_priority.xrds16
19 files changed, 1295 insertions, 0 deletions
diff --git a/Tests/Services/Yadis/Discover.php b/Tests/Services/Yadis/Discover.php
new file mode 100644
index 0000000..27a9ebc
--- /dev/null
+++ b/Tests/Services/Yadis/Discover.php
@@ -0,0 +1,171 @@
+<?php
+
+require_once "PHPUnit.php";
+require_once "Tests/Services/Yadis/DiscoverData.php";
+require_once "Services/Yadis/Yadis.php";
+require_once "Services/Yadis/HTTPFetcher.php";
+
+$__status_header_re = '/Status: (\d+) .*?$/m';
+
+function mkResponse($data)
+{
+ global $__status_header_re;
+
+ $matches = array();
+ $status_mo = preg_match($__status_header_re, $data, $matches);
+ list($headers_str, $body) = explode("\n\n", $data, 2);
+ $headers = array();
+ foreach (explode("\n", $headers_str) as $line) {
+ list($k, $v) = explode(":", $line, 2);
+ $k = strtolower(trim($k));
+ $v = trim($v);
+ $headers[$k] = $v;
+ }
+ $status = intval($matches[1]);
+ $r = new Services_Yadis_HTTPResponse(null, $status, $headers, $body);
+ return $r;
+}
+class TestFetcher {
+ function TestFetcher($base_url)
+ {
+ $this->base_url = $base_url;
+ }
+
+ function get($url, $headers = null)
+ {
+ $current_url = $url;
+ while (true) {
+ $parsed = parse_url($current_url);
+ $path = substr($parsed['path'], 1);
+ $data = generateSample($path, $this->base_url);
+
+ if ($data === null) {
+ return new Services_Yadis_HTTPResponse($current_url,
+ 404,
+ array(),
+ '');
+ }
+
+ $response = mkResponse($data);
+ if (in_array($response->status, array(301, 302, 303, 307))) {
+ $current_url = $response->headers['location'];
+ } else {
+ $response->final_url = $current_url;
+ return $response;
+ }
+ }
+ }
+}
+
+class MockFetcher {
+ function MockFetcher() {
+ $this->count = 0;
+ }
+
+ function get($uri, $headers = null, $body = null)
+ {
+ $this->count++;
+ if ($this->count == 1) {
+ $headers = array(strtolower('X-XRDS-Location') . ': http://unittest/404');
+ return new Services_Yadis_HTTPResponse($uri, 200, $headers, '');
+ } else {
+ return new Services_Yadis_HTTPResponse($uri, 404);
+ }
+ }
+}
+
+class TestSecondGet extends PHPUnit_TestCase {
+ function test_404()
+ {
+ $uri = "http://something.unittest/";
+ $response = null;
+ $fetcher = new MockFetcher();
+ $this->assertTrue(
+ Services_Yadis_Yadis::discover($uri, $response, $fetcher) === null);
+ }
+}
+
+class _TestCase extends PHPUnit_TestCase {
+ var $base_url = 'http://invalid.unittest/';
+
+ function _TestCase($input_name, $id_name, $result_name, $success)
+ {
+ $this->input_name = $input_name;
+ $this->id_name = $id_name;
+ $this->result_name = $result_name;
+ $this->success = $success;
+ $this->fetcher = new TestFetcher($this->base_url);
+ parent::PHPUnit_TestCase();
+ }
+
+ function setUp()
+ {
+ list($this->input_url, $this->expected) = generateResult($this->base_url,
+ $this->input_name,
+ $this->id_name,
+ $this->result_name,
+ $this->success);
+ }
+
+ function runTest()
+ {
+ if ($this->expected === null) {
+ $response = array();
+ $this->assertTrue(
+ Services_Yadis_Yadis::discover($this->input_url, $response,
+ $this->fetcher) === null);
+ } else {
+ $response = array();
+ $result = Services_Yadis_Yadis::discover($this->input_url,
+ $response,
+ $this->fetcher);
+
+ if ($result === null) {
+ $this->fail("Discovery result was null");
+ return;
+ }
+
+ $this->assertEquals($this->input_url, $result->request_uri);
+
+ $msg = 'Identity URL mismatch: actual = %s, expected = %s';
+ $msg = sprintf($msg, $result->uri, $this->expected->uri);
+ $this->assertEquals($this->expected->uri, $result->uri, $msg);
+
+ $msg = 'Content mismatch: actual = %s, expected = %s';
+ $msg = sprintf($msg, $result->body, $this->expected->body);
+ $this->assertEquals($this->expected->body, $result->body, $msg);
+
+ $this->assertEquals($this->expected->xrds_uri, $result->xrds_uri);
+ $this->assertEquals($this->expected->content_type, $result->content_type);
+ }
+ }
+
+ function getName()
+ {
+ if ($this->input_url) {
+ return $this->input_url;
+ } else {
+ return $this->input_name;
+ }
+ }
+}
+
+class Tests_Services_Yadis_Discover extends PHPUnit_TestSuite {
+
+ function getName()
+ {
+ return "Tests_Services_Yadis_Discover";
+ }
+
+ function Tests_Services_Yadis_Discover()
+ {
+ global $testlist;
+
+ foreach ($testlist as $test) {
+ list($success, $input_name, $id_name, $result_name) = $test;
+ $this->addTest(new _TestCase($input_name, $id_name, $result_name, $success));
+ }
+ }
+}
+
+?> \ No newline at end of file
diff --git a/Tests/Services/Yadis/DiscoverData.php b/Tests/Services/Yadis/DiscoverData.php
new file mode 100644
index 0000000..5fb9865
--- /dev/null
+++ b/Tests/Services/Yadis/DiscoverData.php
@@ -0,0 +1,148 @@
+<?php
+
+require_once "Services/Yadis/Yadis.php";
+require_once "Tests/Services/Yadis/TestUtil.php";
+
+$testlist = array(
+ // success, input_name, id_name, result_name
+ array(true, "equiv", "equiv", "xrds"),
+ array(true, "header", "header", "xrds"),
+ array(true, "lowercase_header", "lowercase_header", "xrds"),
+ array(true, "xrds", "xrds", "xrds"),
+ array(true, "xrds_ctparam", "xrds_ctparam", "xrds_ctparam"),
+ array(true, "xrds_ctcase", "xrds_ctcase", "xrds_ctcase"),
+ array(false, "xrds_html", "xrds_html", "xrds_html"),
+ array(true, "redir_equiv", "equiv", "xrds"),
+ array(true, "redir_header", "header", "xrds"),
+ array(true, "redir_xrds", "xrds", "xrds"),
+ array(false, "redir_xrds_html", "xrds_html", "xrds_html"),
+ array(true, "redir_redir_equiv", "equiv", "xrds"),
+ array(false, "404_server_response", null, null),
+ array(false, "404_with_header", null, null),
+ array(false, "404_with_meta", null, null),
+ array(false, "201_server_response", null, null),
+ array(false, "500_server_response", null, null)
+ );
+
+function getExampleXRDS()
+{
+ return Tests_Services_Yadis_readdata('example-xrds.xml');
+}
+
+$example_xrds = getExampleXRDS();
+$default_test_file = 'test1-discover.txt';
+
+$discover_tests = array();
+
+function readTests($filename)
+{
+ $data = Tests_Services_Yadis_readdata($filename);
+
+ if ($data === null) {
+ return null;
+ }
+
+ $tests = array();
+ foreach (preg_split("/\f\n/", $data) as $case) {
+ list($name, $content) = explode("\n", $case, 2);
+ $tests[$name] = $content;
+ }
+ return $tests;
+}
+
+function getData($filename, $name)
+{
+ global $discover_tests;
+ if (!array_key_exists($filename, $discover_tests)) {
+ $data = readTests($filename);
+ if ($data === null) {
+ return null;
+ }
+ $discover_tests[$filename] = $data;
+ }
+
+ $file_tests = $discover_tests[$filename];
+
+ if (array_key_exists($name, $file_tests)) {
+ return $file_tests[$name];
+ } else {
+ return null;
+ }
+}
+
+function fillTemplate($test_name, $template, $base_url, $example_xrds)
+{
+ $mapping = array(
+ array('URL_BASE/', $base_url),
+ array('<XRDS Content>', $example_xrds),
+ array('YADIS_HEADER', 'X-XRDS-Location'),
+ array('NAME', $test_name));
+
+ foreach ($mapping as $pair) {
+ list($k, $v) = $pair;
+ $template = str_replace($k, $v, $template);
+ }
+
+ return $template;
+}
+
+function generateSample($test_name, $base_url,
+ $_example_xrds = null, $filename = null)
+{
+ global $example_xrds, $default_test_file;
+
+ if ($_example_xrds === null) {
+ $_example_xrds = $example_xrds;
+ }
+
+ if ($filename === null) {
+ $filename = $default_test_file;
+ }
+
+ $template = getData($filename, $test_name);
+
+ if ($template === null) {
+ return null;
+ }
+
+ return fillTemplate($test_name, $template, $base_url, $_example_xrds);
+}
+
+function generateResult($base_url, $input_name, $id_name, $result_name, $success)
+{
+ $input_url = $base_url . $input_name; // urlparse.urljoin(base_url, input_name)
+
+ // If the name is null then we expect the protocol to fail, which
+ // we represent by null
+ if ($id_name === null) {
+ // assert result_name is null
+ return array($input_url, null); // DiscoveryFailure
+ }
+
+ $result = generateSample($result_name, $base_url);
+ list($headers, $content) = explode("\n\n", $result, 2);
+ $header_lines = explode("\n", $headers);
+ $ctype = null;
+ foreach ($header_lines as $header_line) {
+ if (strpos($header_line, 'Content-Type:') === 0) {
+ list($temp, $ctype) = explode(":", $header_line, 2);
+ $ctype = trim($ctype);
+ break;
+ }
+ }
+
+ $id_url = $base_url . $id_name;
+
+ $result = new Services_Yadis_Yadis();
+ $result->uri = $id_url;
+ if ($success) {
+ $result->xrds_uri = $base_url . $result_name;
+ } else {
+ $result->xrds_uri = null;
+ }
+ $result->content_type = $ctype;
+ $result->body = $content;
+ return array($input_url, $result);
+}
+
+?> \ No newline at end of file
diff --git a/Tests/Services/Yadis/ParseHTML.php b/Tests/Services/Yadis/ParseHTML.php
new file mode 100644
index 0000000..744af45
--- /dev/null
+++ b/Tests/Services/Yadis/ParseHTML.php
@@ -0,0 +1,88 @@
+<?php
+
+/**
+ * Tests for the Yadis HTML parsing functionality.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @package Yadis
+ * @author JanRain, Inc. <openid@janrain.com>
+ * @copyright 2005 Janrain, Inc.
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL
+ */
+
+require_once 'Tests/Services/Yadis/TestUtil.php';
+require_once 'Services/Yadis/ParseHTML.php';
+require_once 'PHPUnit.php';
+
+class Tests_Services_Yadis_ParseTest extends PHPUnit_TestCase {
+ function Tests_Services_Yadis_ParseTest($case)
+ {
+ list($result, $comment, $html) = $case;
+
+ $this->result = $result;
+ $this->comment = $comment;
+ $this->html_string = $html;
+ $this->parser = new Services_Yadis_ParseHTML();
+ }
+
+ function getName()
+ {
+ return $this->comment;
+ }
+
+ function runTest()
+ {
+ $value = $this->parser->getHTTPEquiv($this->html_string);
+
+ if ($this->result == "EOF") {
+ $this->assertTrue($value === null);
+ } else if ($this->result == "None") {
+ $this->assertTrue($value === null);
+ } else {
+ $this->assertEquals($this->result, $value);
+ }
+ }
+}
+
+class Tests_Services_Yadis_ParseHTML extends PHPUnit_TestSuite {
+
+ function getName()
+ {
+ return "Tests_Services_Yadis_Parse";
+ }
+
+ function parseTests($s)
+ {
+ $tests = array();
+
+ $cases = preg_split("/\f\n/", $s);
+
+ foreach ($cases as $case) {
+ // Split the case text on newline, and keep the first two
+ // lines and re-join the rest (those are the HTML).
+ $parts = explode("\n", $case);
+ $result = $parts[0];
+ $html_comment = $parts[1];
+ $html_string = implode("\n", array_slice($parts, 2));
+ $tests[] = array($result, $html_comment, $html_string);
+ }
+
+ return $tests;
+ }
+
+ function Tests_Services_Yadis_ParseHTML()
+ {
+ $test_data = Tests_Services_Yadis_readdata('test1-parsehtml.txt');
+
+ $test_cases = $this->parseTests($test_data);
+
+ foreach ($test_cases as $case) {
+ $this->addTest(new Tests_Services_Yadis_ParseTest($case));
+ }
+ }
+}
+
+?> \ No newline at end of file
diff --git a/Tests/Services/Yadis/TestUtil.php b/Tests/Services/Yadis/TestUtil.php
new file mode 100644
index 0000000..e6d7a57
--- /dev/null
+++ b/Tests/Services/Yadis/TestUtil.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * Utilites for test functions
+ */
+
+function Tests_Services_Yadis_datafile($name, $reader)
+{
+ $path = dirname(realpath(__FILE__));
+ $sep = DIRECTORY_SEPARATOR;
+ $filename = $path . $sep . 'data' . $sep . $name;
+ $data = $reader($filename);
+ if ($data === false) {
+ $msg = "Failed to open data file: $name";
+ trigger_error($msg, E_USER_ERROR);
+ }
+ return $data;
+}
+
+function Tests_Services_Yadis_readdata($name)
+{
+ return Tests_Services_Yadis_datafile($name, 'file_get_contents');
+}
+
+function Tests_Services_Yadis_readlines($name)
+{
+ return Tests_Services_Yadis_datafile($name, 'file');
+}
diff --git a/Tests/Services/Yadis/XRDS.php b/Tests/Services/Yadis/XRDS.php
new file mode 100644
index 0000000..8b24de3
--- /dev/null
+++ b/Tests/Services/Yadis/XRDS.php
@@ -0,0 +1,188 @@
+<?php
+
+/**
+ * XRDS-parsing tests for the Yadis library.
+ */
+
+require_once 'PHPUnit.php';
+require_once 'Services/Yadis/XRDS.php';
+require_once 'Tests/Services/Yadis/TestUtil.php';
+
+class Tests_Services_Yadis_XRDS extends PHPUnit_TestCase {
+
+ function test_good()
+ {
+ $xml = Tests_Services_Yadis_readdata("brian.xrds");
+ $xrds = Services_Yadis_XRDS::parseXRDS($xml);
+
+ $this->assertTrue($xrds !== null);
+
+ if ($xrds) {
+ $this->assertEquals(count($xrds->services()), 1);
+ } else {
+ $this->fail("Could not test XRDS service list because the ".
+ "XRDS object is null");
+ }
+ }
+
+ function test_good_multi()
+ {
+ $xml = Tests_Services_Yadis_readdata("brian.multi.xrds");
+ $xrds = Services_Yadis_XRDS::parseXRDS($xml);
+ $this->assertTrue($xrds !== null);
+ $this->assertEquals(count($xrds->services()), 1);
+ $s = $xrds->services();
+ $s = $s[0];
+
+ $types = $s->getTypes();
+
+ $this->assertTrue(count($types) == 1);
+ $this->assertEquals('http://openid.net/signon/1.0',
+ $types[0]);
+ }
+
+ function test_good_uri_multi()
+ {
+ $xml = Tests_Services_Yadis_readdata("brian.multi_uri.xrds");
+ $xrds = Services_Yadis_XRDS::parseXRDS($xml);
+ $this->assertTrue($xrds !== null);
+ $this->assertEquals(1, count($xrds->services()));
+ }
+
+ function test_uri_sorting()
+ {
+ $xml = Tests_Services_Yadis_readdata("uri_priority.xrds");
+ $xrds = Services_Yadis_XRDS::parseXRDS($xml);
+ $services = $xrds->services();
+ $uris = $services[0]->getURIs();
+
+ $expected_uris = array(
+ "http://zero.priority/",
+ "http://one.priority/",
+ "http://no.priority/"
+ );
+
+ $this->assertEquals($uris, $expected_uris);
+ }
+
+ function test_bad()
+ {
+ $this->assertTrue(Services_Yadis_XRDS::parseXRDS(null) === null);
+ $this->assertTrue(Services_Yadis_XRDS::parseXRDS(5) === null);
+ $this->assertTrue(Services_Yadis_XRDS::parseXRDS('') === null);
+ $this->assertTrue(Services_Yadis_XRDS::parseXRDS('<html></html>') ===
+ null);
+ $this->assertTrue(Services_Yadis_XRDS::parseXRDS("\x00") === null);
+ }
+
+ function test_services_filters()
+ {
+ // First, just be sure that service objects do the right
+ // thing.
+ $xml = Tests_Services_Yadis_readdata("brian_priority.xrds");
+ $xrds = Services_Yadis_XRDS::parseXRDS($xml,
+ array('openid' =>
+ 'http://openid.net/xmlns/1.0'));
+ $this->assertTrue($xrds !== null);
+
+ // Get list of service objects.
+ $services = $xrds->services();
+ $this->assertEquals(count($services), 2, "first service count");
+
+ // Query the two service objecs.
+ $s1 = $services[0];
+ $this->assertEquals($s1->getPriority(), 1, "first priority check");
+ $types = $s1->getTypes();
+ $this->assertEquals(count($types), 1, "first type check");
+
+ $s2 = $services[1];
+ $this->assertEquals($s2->getPriority(), 2, "second priority check");
+ $types = $s2->getTypes();
+ $this->assertEquals(count($types), 1, "second type check");
+
+ function _DelegateFilter(&$service)
+ {
+ if ($service->getElements('openid:Delegate')) {
+ return true;
+ }
+ return false;
+ }
+
+ // Make sure that a filter which matches both DOES match both.
+ $this->assertEquals(count(
+ $xrds->services(array("_DelegateFilter"))), 2,
+ "_DelegateFilter check");
+
+ // This filter should match all services in the document.
+ function _HasTypeAndURI(&$service)
+ {
+ if ($service->getTypes() &&
+ $service->getURIs()) {
+ return true;
+ }
+ return false;
+ }
+
+ // This filter should only match one.
+ function _URIMatchesSchtuff(&$service)
+ {
+ $uris = $service->getURIs();
+
+ foreach ($uris as $uri) {
+ if (preg_match("|schtuff|", $uri)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // This filter should only match one.
+ function _URIMatchesMyOpenID(&$service)
+ {
+ $uris = $service->getURIs();
+
+ foreach ($uris as $uri) {
+ if (preg_match("|myopenid|", $uri)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Make sure a pair of filters in ALL mode only match one service.
+ $this->assertEquals(count(
+ $xrds->services(array("_HasTypeAndURI",
+ "_URIMatchesSchtuff"),
+ SERVICES_YADIS_MATCH_ALL)), 1,
+ "_HasTypeAndURI / _URIMatchesSchtuff check");
+
+ // Make sure a pair of filters in ALL mode only match one service.
+ $this->assertEquals(count(
+ $xrds->services(array("_HasTypeAndURI",
+ "_URIMatchesMyOpenID"),
+ SERVICES_YADIS_MATCH_ALL)), 1,
+ "_HasTypeAndURI / _URIMatchesMyOpenID check");
+
+ // Make sure a pair of filters in ANY mode matches both services.
+ $this->assertEquals(count(
+ $xrds->services(array("_URIMatchesMyOpenID",
+ "_URIMatchesSchtuff"))), 2,
+ "_URIMatchesMyOpenID / _URIMatchesSchtuff check");
+
+ // Make sure the order of the services returned (when using
+ // filters) is correct.
+ $s = $xrds->services(array("_URIMatchesMyOpenID",
+ "_URIMatchesSchtuff"));
+
+ $this->assertTrue($s[0]->getPriority() === 1, "s[0] priority check");
+ $this->assertTrue($s[1]->getPriority() === 2, "s[1] priority check");
+
+ // Make sure a bad filter mode gets us a null service list.
+ $this->assertTrue($xrds->services(array("_URIMatchesMyOpenID",
+ "_URIMatchesSchtuff"),
+ "bogus") === null,
+ "bogus filter check");
+ }
+}
+
+?> \ No newline at end of file
diff --git a/Tests/Services/Yadis/Yadis.php b/Tests/Services/Yadis/Yadis.php
new file mode 100644
index 0000000..2a8752e
--- /dev/null
+++ b/Tests/Services/Yadis/Yadis.php
@@ -0,0 +1,92 @@
+<?php
+
+/**
+ * Tests for the core of the PHP Yadis library.
+ */
+
+require_once 'PHPUnit.php';
+require_once 'Services/Yadis/Yadis.php';
+require_once 'Tests/Services/Yadis/TestUtil.php';
+
+class Tests_Services_Yadis_DiscoveryTest extends PHPUnit_TestCase {
+
+ function Tests_Services_Yadis_DiscoveryTest($input_url, $redir_uri,
+ $xrds_uri, $num)
+ {
+ $this->input_url = $input_url;
+ $this->redir_uri = $redir_uri;
+ $this->xrds_uri = $xrds_uri;
+ $this->num = $num;
+ }
+
+ function getName()
+ {
+ return "Yadis discovery test ".$this->num;
+ }
+
+ function runTest()
+ {
+ $http_response = null;
+
+ $y = Services_Yadis_Yadis::discover($this->input_url,
+ $http_response,
+ Services_Yadis_Yadis::getHTTPFetcher());
+ $this->assertTrue($y !== null);
+
+ // Compare parts of returned Yadis object to expected URLs.
+ $this->assertEquals($this->redir_uri, $y->uri);
+
+ if ($this->xrds_uri) {
+ $this->assertEquals($this->xrds_uri, $y->xrds_uri);
+ // Compare contents of actual HTTP GET with that of Yadis
+ // response.
+ $f = Services_Yadis_Yadis::getHTTPFetcher();
+ $response = $f->get($this->xrds_uri);
+
+ $this->assertEquals($response->body, $y->body);
+ } else {
+ $this->assertTrue($y->xrds_uri === null);
+ }
+ }
+}
+
+class Tests_Services_Yadis_Yadis extends PHPUnit_TestSuite {
+
+ function getName()
+ {
+ return "Tests_Services_Yadis_Yadis";
+ }
+
+ function parseTests($data)
+ {
+ $cases = explode("\n", $data);
+ $tests = array();
+
+ foreach ($cases as $line) {
+ if ($line && ($line[0] != "#")) {
+ $tests[] = explode("\t", $line, 3);
+ }
+ }
+
+ return $tests;
+ }
+
+ function Tests_Services_Yadis_Yadis()
+ {
+ $test_data = Tests_Services_Yadis_readdata('manifest.txt');
+
+ $test_cases = $this->parseTests($test_data);
+
+ $i = 0;
+ foreach ($test_cases as $case) {
+ $i++;
+ list($input, $redir, $xrds) = $case;
+ $this->addTest(new Tests_Services_Yadis_DiscoveryTest($input,
+ $redir,
+ $xrds, $i));
+ }
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/Tests/Services/Yadis/data/accept.txt b/Tests/Services/Yadis/data/accept.txt
new file mode 100644
index 0000000..0853321
--- /dev/null
+++ b/Tests/Services/Yadis/data/accept.txt
@@ -0,0 +1,118 @@
+# Accept: [Accept: header value from RFC2616,
+# http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html]
+# Available: [whitespace-separated content types]
+# Expected: [Accept-header like list, containing the available content
+# types with their q-values]
+
+Accept: */*
+Available: text/plain
+Expected: text/plain; q=1.0
+
+Accept: */*
+Available: text/plain, text/html
+Expected: text/plain; q=1.0, text/html; q=1.0
+
+# The order matters
+Accept: */*
+Available: text/html, text/plain
+Expected: text/html; q=1.0, text/plain; q=1.0
+
+Accept: text/*, */*; q=0.9
+Available: text/plain, image/jpeg
+Expected: text/plain; q=1.0, image/jpeg; q=0.9
+
+Accept: text/*, */*; q=0.9
+Available: image/jpeg, text/plain
+Expected: text/plain; q=1.0, image/jpeg; q=0.9
+
+# wildcard subtypes still reject differing main types
+Accept: text/*
+Available: image/jpeg, text/plain
+Expected: text/plain; q=1.0
+
+Accept: text/html
+Available: text/html
+Expected: text/html; q=1.0
+
+Accept: text/html, text/*
+Available: text/html
+Expected: text/html; q=1.0
+
+Accept: text/html, text/*
+Available: text/plain, text/html
+Expected: text/plain; q=1.0, text/html; q=1.0
+
+Accept: text/html, text/*; q=0.9
+Available: text/plain, text/html
+Expected: text/html; q=1.0, text/plain; q=0.9
+
+# If a more specific type has a higher q-value, then the higher value wins
+Accept: text/*; q=0.9, text/html
+Available: text/plain, text/html
+Expected: text/html; q=1.0, text/plain; q=0.9
+
+Accept: */*, text/*; q=0.9, text/html; q=0.1
+Available: text/plain, text/html, image/monkeys
+Expected: image/monkeys; q=1.0, text/plain; q=0.9, text/html; q=0.1
+
+Accept: text/*, text/html; q=0
+Available: text/html
+Expected:
+
+Accept: text/*, text/html; q=0
+Available: text/html, text/plain
+Expected: text/plain; q=1.0
+
+Accept: text/html
+Available: text/plain
+Expected:
+
+Accept: application/xrds+xml, text/html; q=0.9
+Available: application/xrds+xml, text/html
+Expected: application/xrds+xml; q=1.0, text/html; q=0.9
+
+Accept: application/xrds+xml, */*; q=0.9
+Available: application/xrds+xml, text/html
+Expected: application/xrds+xml; q=1.0, text/html; q=0.9
+
+Accept: application/xrds+xml, application/xhtml+xml; q=0.9, text/html; q=0.8, text/xml; q=0.7
+Available: application/xrds+xml, text/html
+Expected: application/xrds+xml; q=1.0, text/html; q=0.8
+
+# See http://www.rfc-editor.org/rfc/rfc3023.txt, section A.13
+Accept: application/xrds
+Available: application/xrds+xml
+Expected:
+
+Accept: application/xrds+xml
+Available: application/xrds
+Expected:
+
+Accept: application/xml
+Available: application/xrds+xml
+Expected:
+
+Available: application/xrds+xml
+Accept: application/xml
+Expected:
+
+
+
+#################################################
+# The tests below this line are documentation of how this library
+# works. If the implementation changes, it's acceptable to change the
+# test to reflect that. These are specified so that we can make sure
+# that the current implementation actually works the way that we
+# expect it to given these inputs.
+
+Accept: text/html;level=1
+Available: text/html
+Expected: text/html; q=1.0
+
+Accept: text/html; level=1, text/html; level=9; q=0.1
+Available: text/html
+Expected: text/html; q=1.0
+
+Accept: text/html; level=9; q=0.1, text/html; level=1
+Available: text/html
+Expected: text/html; q=1.0
diff --git a/Tests/Services/Yadis/data/brian.multi.xrds b/Tests/Services/Yadis/data/brian.multi.xrds
new file mode 100644
index 0000000..1bc95de
--- /dev/null
+++ b/Tests/Services/Yadis/data/brian.multi.xrds
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xrds:XRDS
+ xmlns:xrds="xri://$xrds"
+ xmlns:openid="http://openid.net/xmlns/1.0"
+ xmlns="xri://$xrd*($v*2.0)">
+ <XRD>
+
+ <Service priority="2">
+ <Type>http://openid.net/signon/1.1</Type>
+ <URI>http://www.myopenid.com/server</URI>
+ <openid:Delegate>http://frank.myopenid.com/</openid:Delegate>
+ </Service>
+
+ </XRD>
+ <XRD>
+
+ <Service priority="1">
+ <Type>http://bar.com/</Type>
+ <URI>http://bar.com/server</URI>
+ </Service>
+
+ <Service priority="2">
+ <Type>http://foo.com</Type>
+ <URI>http://foo.com/server</URI>
+ </Service>
+
+ </XRD>
+ <XRD>
+
+ <Service priority="0">
+ <Type>http://openid.net/signon/1.0</Type>
+ <URI>http://www.myopenid.com/server</URI>
+ <openid:Delegate>http://brian.myopenid.com/</openid:Delegate>
+ </Service>
+
+ </XRD>
+</xrds:XRDS>
+
diff --git a/Tests/Services/Yadis/data/brian.multi_uri.xrds b/Tests/Services/Yadis/data/brian.multi_uri.xrds
new file mode 100644
index 0000000..fce5ef7
--- /dev/null
+++ b/Tests/Services/Yadis/data/brian.multi_uri.xrds
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xrds:XRDS
+ xmlns:xrds="xri://$xrds"
+ xmlns:openid="http://openid.net/xmlns/1.0"
+ xmlns="xri://$xrd*($v*2.0)">
+ <XRD>
+
+ <Service>
+ <Type>http://openid.net/signon/1.0</Type>
+ <URI>http://www.myopenid.com/server</URI>
+ <URI>http://example.com/server</URI>
+ </Service>
+
+ </XRD>
+</xrds:XRDS>
+
diff --git a/Tests/Services/Yadis/data/brian.xrds b/Tests/Services/Yadis/data/brian.xrds
new file mode 100644
index 0000000..c7539fe
--- /dev/null
+++ b/Tests/Services/Yadis/data/brian.xrds
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xrds:XRDS
+ xmlns:xrds="xri://$xrds"
+ xmlns:openid="http://openid.net/xmlns/1.0"
+ xmlns="xri://$xrd*($v*2.0)">
+ <XRD>
+
+ <Service priority="0">
+ <Type>http://openid.net/signon/1.0</Type>
+ <URI>http://www.myopenid.com/server</URI>
+ <openid:Delegate>http://brian.myopenid.com/</openid:Delegate>
+ </Service>
+
+ </XRD>
+</xrds:XRDS>
+
diff --git a/Tests/Services/Yadis/data/brian_priority.xrds b/Tests/Services/Yadis/data/brian_priority.xrds
new file mode 100644
index 0000000..273077d
--- /dev/null
+++ b/Tests/Services/Yadis/data/brian_priority.xrds
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xrds:XRDS
+ xmlns:xrds="xri://$xrds"
+ xmlns:openid="http://openid.net/xmlns/1.0"
+ xmlns="xri://$xrd*($v*2.0)">
+ <XRD>
+
+ <Service priority="2">
+ <Type>http://openid.net/signon/1.0</Type>
+ <URI>http://www.schtuff.com/?action=openid_server</URI>
+ <openid:Delegate>http://users.schtuff.com/brian</openid:Delegate>
+ </Service>
+
+ <Service priority="1">
+ <Type>http://openid.net/signon/1.0</Type>
+ <URI>http://www.myopenid.com/server</URI>
+ <openid:Delegate>http://brian.myopenid.com/</openid:Delegate>
+ </Service>
+
+ </XRD>
+</xrds:XRDS>
+
diff --git a/Tests/Services/Yadis/data/example-xrds.xml b/Tests/Services/Yadis/data/example-xrds.xml
new file mode 100644
index 0000000..101ba3b
--- /dev/null
+++ b/Tests/Services/Yadis/data/example-xrds.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Sample XRDS file at: NAME -->
+<xrds:XRDS
+ xmlns:xrds="xri://$xrds"
+ xmlns="xri://$xrd*($v*2.0)">
+ <XRD>
+
+ <Service priority="0">
+ <Type>http://example.com/</Type>
+ <URI>http://www.openidenabled.com/</URI>
+ </Service>
+
+ </XRD>
+</xrds:XRDS>
diff --git a/Tests/Services/Yadis/data/manifest.txt b/Tests/Services/Yadis/data/manifest.txt
new file mode 100644
index 0000000..2f05d5e
--- /dev/null
+++ b/Tests/Services/Yadis/data/manifest.txt
@@ -0,0 +1,30 @@
+# This file contains test cases for doing YADIS identity URL and
+# service discovery. For each case, there are three URLs. The first
+# URL is the user input. The second is the identity URL and the third
+# is the URL from which the XRDS document should be read.
+#
+# The file format is as follows:
+# User URL <tab> Identity URL <tab> XRDS URL <newline>
+#
+# blank lines and lines starting with # should be ignored.
+#
+# To use this test:
+#
+# 1. Run your discovery routine on the User URL.
+#
+# 2. Compare the identity URL returned by the discovery routine to the
+# identity URL on that line of the file. It must be an EXACT match.
+#
+# 3. Do a regular HTTP GET on the XRDS URL. Compare the content that
+# was returned by your discovery routine with the content returned
+# from that URL. It should also be an exact match.
+
+http://www.openidenabled.com/resources/yadis-test/discover/equiv http://www.openidenabled.com/resources/yadis-test/discover/equiv http://www.openidenabled.com/resources/yadis-test/discover/xrds
+http://www.openidenabled.com/resources/yadis-test/discover/header http://www.openidenabled.com/resources/yadis-test/discover/header http://www.openidenabled.com/resources/yadis-test/discover/xrds
+http://www.openidenabled.com/resources/yadis-test/discover/xrds http://www.openidenabled.com/resources/yadis-test/discover/xrds http://www.openidenabled.com/resources/yadis-test/discover/xrds
+http://www.openidenabled.com/resources/yadis-test/discover/xrds_html http://www.openidenabled.com/resources/yadis-test/discover/xrds_html
+http://www.openidenabled.com/resources/yadis-test/discover/redir_equiv http://www.openidenabled.com/resources/yadis-test/discover/equiv http://www.openidenabled.com/resources/yadis-test/discover/xrds
+http://www.openidenabled.com/resources/yadis-test/discover/redir_header http://www.openidenabled.com/resources/yadis-test/discover/header http://www.openidenabled.com/resources/yadis-test/discover/xrds
+http://www.openidenabled.com/resources/yadis-test/discover/redir_xrds http://www.openidenabled.com/resources/yadis-test/discover/xrds http://www.openidenabled.com/resources/yadis-test/discover/xrds
+http://www.openidenabled.com/resources/yadis-test/discover/redir_xrds_html http://www.openidenabled.com/resources/yadis-test/discover/xrds_html
+http://www.openidenabled.com/resources/yadis-test/discover/redir_redir_equiv http://www.openidenabled.com/resources/yadis-test/discover/equiv http://www.openidenabled.com/resources/yadis-test/discover/xrds
diff --git a/Tests/Services/Yadis/data/no-xrd.xml b/Tests/Services/Yadis/data/no-xrd.xml
new file mode 100644
index 0000000..ca66f73
--- /dev/null
+++ b/Tests/Services/Yadis/data/no-xrd.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xrds:XRDS
+ xmlns:xrds="xri://$xrds"
+ xmlns:openid="http://openid.net/xmlns/1.0"
+ xmlns:typekey="http://typekey.com/xmlns/1.0"
+ xmlns="xri://$xrd*($v*2.0)">
+</xrds:XRDS>
diff --git a/Tests/Services/Yadis/data/not-xrds.xml b/Tests/Services/Yadis/data/not-xrds.xml
new file mode 100644
index 0000000..7f5bfd5
--- /dev/null
+++ b/Tests/Services/Yadis/data/not-xrds.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<x></x>
diff --git a/Tests/Services/Yadis/data/test1-discover.txt b/Tests/Services/Yadis/data/test1-discover.txt
new file mode 100644
index 0000000..7ec9b87
--- /dev/null
+++ b/Tests/Services/Yadis/data/test1-discover.txt
@@ -0,0 +1,137 @@
+equiv
+Status: 200 OK
+Content-Type: text/html
+
+<html>
+<head>
+<meta http-equiv="YADIS_HEADER" content="URL_BASE/xrds">
+<title>Joe Schmoe's Homepage</title>
+</head>
+<body>
+<h1>Joe Schmoe's Homepage</h1>
+<p>Blah blah blah blah blah blah blah</p>
+</body>
+</html>
+
+header
+Status: 200 OK
+Content-Type: text/html
+YADIS_HEADER: URL_BASE/xrds
+
+<html>
+<head>
+<title>Joe Schmoe's Homepage</title>
+</head>
+<body>
+<h1>Joe Schmoe's Homepage</h1>
+<p>Blah blah blah blah blah blah blah</p>
+</body>
+
+xrds
+Status: 200 OK
+Content-Type: application/xrds+xml
+
+<XRDS Content>
+
+xrds_ctparam
+Status: 200 OK
+Content-Type: application/xrds+xml; charset=UTF8
+
+<XRDS Content>
+
+xrds_ctcase
+Status: 200 OK
+Content-Type: appliCATION/XRDS+xml
+
+<XRDS Content>
+
+xrds_html
+Status: 200 OK
+Content-Type: text/html
+
+<XRDS Content>
+
+redir_equiv
+Status: 302 Found
+Content-Type: text/plain
+Location: URL_BASE/equiv
+
+You are presently being redirected.
+
+redir_header
+Status: 302 Found
+Content-Type: text/plain
+Location: URL_BASE/header
+
+You are presently being redirected.
+
+redir_xrds
+Status: 302 Found
+Content-Type: application/xrds+xml
+Location: URL_BASE/xrds
+
+<XRDS Content>
+
+redir_xrds_html
+Status: 302 Found
+Content-Type: text/plain
+Location: URL_BASE/xrds_html
+
+You are presently being redirected.
+
+redir_redir_equiv
+Status: 302 Found
+Content-Type: text/plain
+Location: URL_BASE/redir_equiv
+
+You are presently being redirected.
+
+lowercase_header
+Status: 200 OK
+Content-Type: text/html
+x-xrds-location: URL_BASE/xrds
+
+<html>
+<head>
+<title>Joe Schmoe's Homepage</title>
+</head>
+<body>
+<h1>Joe Schmoe's Homepage</h1>
+<p>Blah blah blah blah blah blah blah</p>
+</body>
+
+404_server_response
+Status: 404 Not Found
+
+EEk!
+
+500_server_response
+Status: 500 Server error
+
+EEk!
+
+201_server_response
+Status: 201 Created
+
+EEk!
+
+404_with_header
+Status: 404 Not Found
+YADIS_HEADER: URL_BASE/xrds
+
+EEk!
+
+404_with_meta
+Status: 404 Not Found
+Content-Type: text/html
+
+<html>
+<head>
+<meta http-equiv="YADIS_HEADER" content="URL_BASE/xrds">
+<title>Joe Schmoe's Homepage</title>
+</head>
+<body>
+<h1>Joe Schmoe's Homepage</h1>
+<p>Blah blah blah blah blah blah blah</p>
+</body>
+</html>
diff --git a/Tests/Services/Yadis/data/test1-parsehtml.txt b/Tests/Services/Yadis/data/test1-parsehtml.txt
new file mode 100644
index 0000000..e124380
--- /dev/null
+++ b/Tests/Services/Yadis/data/test1-parsehtml.txt
@@ -0,0 +1,125 @@
+found
+<!-- minimal well-formed success case -->
+<html><head><meta http-equiv="X-XRDS-Location" content="found"></head></html>
+
+found
+<!-- minimal success case -->
+<html><head><meta http-equiv="X-XRDS-Location" content="found">
+
+found
+<!-- ignore bogus top-level tags -->
+</porky><html><head><meta http-equiv="X-XRDS-Location" content="found">
+
+found
+<!-- Case folding for header name -->
+<html><head><meta http-equiv="x-xrds-location" content="found">
+
+found
+<!-- missing <html> tag -->
+<head><meta http-equiv="X-XRDS-Location" content="found">
+
+found
+<!-- case folding for tag names -->
+<html><head><META http-equiv="X-XRDS-Location" content="found">
+
+found
+<!-- Stop after first one found -->
+<html><head>
+<meta http-equiv="x-xrds-location" content="found">
+<meta http-equiv="x-xrds-location" content="not-found">
+
+&
+<!-- standard entity -->
+<head><meta http-equiv="X-XRDS-Location" content="&amp;">
+
+found
+<!-- hex entity -->
+<html>
+ <head>
+ <meta http-equiv="X-XRDS-Location" content="&#x66;ound">
+ </head>
+</html>
+
+found
+<!-- decimal entity -->
+<html>
+ <head>
+ <meta http-equiv="X-XRDS-Location" content="&#102;ound">
+ </head>
+</html>
+
+/
+<!-- hex entity -->
+<html>
+ <head>
+ <meta http-equiv="X-XRDS-Location" content="&#x2f;">
+ </head>
+</html>
+
+
+<!-- empty string -->
+<html><head><meta http-equiv="X-XRDS-Location" content="">
+
+EOF
+<!-- No markup, except this comment -->
+
+None
+<!-- No meta, just standard HTML -->
+<html>
+ <head>
+ <title>A boring document</title>
+ </head>
+ <body>
+ <h1>A boring document</h1>
+ <p>There's really nothing interesting about this</p>
+ </body>
+</html>
+
+EOF
+<!-- No <html> or <head> -->
+<meta http-equiv="X-XRDS-Location" content="found">
+
+EOF
+<!-- No <head> tag -->
+<html><meta http-equiv="X-XRDS-Location" content="found">
+
+None
+<!-- No <html> or <head> and a <body> -->
+<body><meta http-equiv="X-XRDS-Location" content="found">
+
+None
+<!-- <head> and <html> reversed -->
+<head><html><meta http-equiv="X-XRDS-Location" content="found">
+
+None
+<!-- <meta> is inside of <body> -->
+<html><head><body><meta http-equiv="X-XRDS-Location" content="found">
+
+None
+<!-- <meta> is inside of <body> -->
+<html>
+ <head>
+ <title>Someone's blog</title>
+ </head>
+ <body>
+ <h1>My blog</h1>
+ <p>This is my blog</p>
+ <h2>Comments</h2>
+ <p><meta http-equiv="X-XRDS-Location" content="found"></p>
+ </body>
+</html>
+
+None
+<!-- short head tag -->
+<html><head/>
+<meta http-equiv="X-XRDS-Location" content="found">
+
+None
+<!-- <body> comes first -->
+<body><html><head>
+<meta http-equiv="X-XRDS-Location" content="found">
+
+None
+<!-- </body> comes first -->
+</body><html><head>
+<meta http-equiv="X-XRDS-Location" content="found">
diff --git a/Tests/Services/Yadis/data/test1-xrd.xml b/Tests/Services/Yadis/data/test1-xrd.xml
new file mode 100644
index 0000000..60e5ca7
--- /dev/null
+++ b/Tests/Services/Yadis/data/test1-xrd.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xrds:XRDS
+ xmlns:xrds="xri://$xrds"
+ xmlns:openid="http://openid.net/xmlns/1.0"
+ xmlns:typekey="http://typekey.com/xmlns/1.0"
+ xmlns="xri://$xrd*($v*2.0)">
+ <XRD>
+
+ <Service priority="0">
+ <Type>http://openid.net/signon/1.0</Type>
+ <URI>http://www.myopenid.com/server</URI>
+ <openid:Delegate>http://josh.myopenid.com/</openid:Delegate>
+ </Service>
+
+ <Service priority="20">
+ <Type>http://lid.netmesh.org/sso/2.0b5</Type>
+ <Type>http://lid.netmesh.org/2.0b5</Type>
+ <URI>http://mylid.net/josh</URI>
+ </Service>
+
+ <Service priority="10">
+ <Type>http://openid.net/signon/1.0</Type>
+ <URI>http://www.livejournal.com/openid/server.bml</URI>
+ <openid:Delegate>http://www.livejournal.com/users/nedthealpaca/</openid:Delegate>
+ </Service>
+
+ <Service priority="15">
+ <Type>http://typekey.com/services/1.0</Type>
+ <typekey:MemberName>joshhoyt</typekey:MemberName>
+ </Service>
+
+ <Service priority="5">
+ <Type>http://openid.net/signon/1.0</Type>
+ <URI>http://www.schtuff.com/openid</URI>
+ <openid:Delegate>http://users.schtuff.com/josh</openid:Delegate>
+ </Service>
+
+ </XRD>
+</xrds:XRDS>
diff --git a/Tests/Services/Yadis/data/uri_priority.xrds b/Tests/Services/Yadis/data/uri_priority.xrds
new file mode 100644
index 0000000..b1a2f65
--- /dev/null
+++ b/Tests/Services/Yadis/data/uri_priority.xrds
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xrds:XRDS
+ xmlns:xrds="xri://$xrds"
+ xmlns:openid="http://openid.net/xmlns/1.0"
+ xmlns="xri://$xrd*($v*2.0)">
+ <XRD>
+
+ <Service>
+ <Type>http://openid.net/signon/1.0</Type>
+ <URI>http://no.priority/</URI>
+ <URI priority="1">http://one.priority/</URI>
+ <URI priority="0">http://zero.priority/</URI>
+ </Service>
+
+ </XRD>
+</xrds:XRDS>