diff options
author | tailor <cygnus@janrain.com> | 2006-01-12 19:03:09 +0000 |
---|---|---|
committer | tailor <cygnus@janrain.com> | 2006-01-12 19:03:09 +0000 |
commit | de2024e48e2bfd665823459aad4407fa507e6691 (patch) | |
tree | cb9a9eac6d5c746fb6d16aa973a3e00fd76af988 | |
parent | 33b9f915920fd196beb8f7c337de39fe25f99ab5 (diff) | |
download | php-openid-de2024e48e2bfd665823459aad4407fa507e6691.zip php-openid-de2024e48e2bfd665823459aad4407fa507e6691.tar.gz php-openid-de2024e48e2bfd665823459aad4407fa507e6691.tar.bz2 |
[project @ Fixed bugs in parser and added parser tests]
-rw-r--r-- | Net/OpenID/Consumer/Parse.php | 18 | ||||
-rw-r--r-- | Tests/Net/OpenID/Parse.php | 168 | ||||
-rw-r--r-- | Tests/Net/OpenID/linkparse.txt | 583 | ||||
-rw-r--r-- | Tests/TestDriver.php | 1 |
4 files changed, 762 insertions, 8 deletions
diff --git a/Net/OpenID/Consumer/Parse.php b/Net/OpenID/Consumer/Parse.php index b49d462..dbb05eb 100644 --- a/Net/OpenID/Consumer/Parse.php +++ b/Net/OpenID/Consumer/Parse.php @@ -61,13 +61,13 @@ function Net_OpenID_html_find() function Net_OpenID_head_find() { - return Net_OpenID_tagMatcher('head'); + return Net_OpenID_tagMatcher('head', array('body')); } -$_Net_OpenID_link_find = sprintf("/<link\b(?!:)[^\>]*>/%s", - $_Net_OpenID_re_flags); +$_Net_OpenID_attr_find = '\b(\w+)=("[^"]*"|\'[^\']*\'|[^\'"\s\/<>]+)'; -$_Net_OpenID_attr_find = '(\w+)=("[^"]*"|\'[^\']*\'|[^\s>]*)'; +$_Net_OpenID_link_find = sprintf("/<link\b(?!:)([^>]*)(?!<)>/%s", + $_Net_OpenID_re_flags); $_Net_OpenID_entity_replacements = array( 'amp' => '&', @@ -150,10 +150,12 @@ function Net_OpenID_parseLinkAttrs($html) preg_match_all($_Net_OpenID_attr_find, $link, $attr_matches); $link_attrs = array(); foreach ($attr_matches[0] as $index => $full_match) { - $link_attrs[$attr_matches[1][$index]] = - Net_OpenID_replace_entities( - Net_OpenID_remove_quotes( - $attr_matches[2][$index])); + $name = $attr_matches[1][$index]; + $value = Net_OpenID_replace_entities( + Net_OpenID_remove_quotes( + $attr_matches[2][$index])); + + $link_attrs[$name] = $value; } $link_data[] = $link_attrs; } diff --git a/Tests/Net/OpenID/Parse.php b/Tests/Net/OpenID/Parse.php new file mode 100644 index 0000000..5d6c0a4 --- /dev/null +++ b/Tests/Net/OpenID/Parse.php @@ -0,0 +1,168 @@ +<?php + +/** + * Tests for the Consumer parsing functions. + * + * PHP versions 4 and 5 + * + * LICENSE: See the COPYING file included in this distribution. + * + * @package OpenID + * @author JanRain, Inc. <openid@janrain.com> + * @copyright 2005 Janrain, Inc. + * @license http://www.gnu.org/copyleft/lesser.html LGPL + */ + +require_once('Net/OpenID/Consumer/Parse.php'); + +class Tests_Net_OpenID_Link extends PHPUnit_TestCase { + function Tests_Net_OpenID_Link($case) + { + list($desc, $markup, $links, $case_text) = $case; + $this->desc = $desc; + $this->markup = $markup; + $this->expected_links = $links; + $this->case_text = $case_text; + } + + function getName() + { + return $this->desc; + } + + function runTest() + { + $parsed = Net_OpenID_parseLinkAttrs($this->markup); + $i = 0; + + foreach ($this->expected_links as $expected) { + list($is_optional_link, $expected_link) = $expected; + if ($is_optional_link && + ($i >= count($parsed))) { + continue; + } + + $act_link = $parsed[$i]; + + $increment = true; + foreach ($expected_link as $attr => $data) { + list($is_optional_attr, $value) = $data; + + if ($is_optional_attr) { + $actual_value = null; + if (array_key_exists($attr, $act_link)) { + $actual_value = $act_link[$attr]; + } else { + continue; + } + } else { + $actual_value = $act_link[$attr]; + } + + if ($is_optional_link && + ($value != $actual_value)) { + $increment = false; + break; + } + + $this->assertEquals($value, $actual_value); + } + + if ($increment) { + $i++; + } + } + + $this->assertEquals($i, count($parsed)); + } +} + +class NumTestCases extends PHPUnit_TestCase { + function NumTestCases($test_cases, $num_tests) + { + $this->test_cases = $test_cases; + $this->num_tests = $num_tests; + } + + function runTest() + { + $this->assertEquals(count($this->test_cases), + $this->num_tests); + } +} + +class Tests_Net_OpenID_Parse extends PHPUnit_TestSuite { + + function parseLink($line) + { + $parts = explode(" ", $line); + $optional = intval($parts[0] == 'Link*:'); + assert($optional || ($parts[0] == 'Link:')); + + $attrs = array(); + foreach (array_slice($parts, 1) as $attr) { + list($k, $v) = explode("=", $attr, 2); + if ($k[strlen($k) - 1] == '*') { + $attr_optional = 1; + $k = substr($k, 0, strlen($k) - 1); + } else { + $attr_optional = 0; + } + + $attrs[$k] = array($attr_optional, $v); + } + + return array($optional, $attrs); + } + + function parseCase($s) + { + list($header, $markup) = explode("\n\n", $s, 2); + $lines = explode("\n", $header); + $name = array_shift($lines); + assert(strpos($name, 'Name: ') == 0); + $desc = substr($name, 6); + $parsed = array(); + foreach ($lines as $line) { + $parsed[] = $this->parseLink($line); + } + + return array($desc, $markup, $parsed); + } + + function parseTests($s) + { + $tests = array(); + + $cases = explode("\n\n\n", $s); + $header = array_shift($cases); + list($tests_line, $unused) = explode("\n", $header, 2); + list($k, $v) = explode(": ", $tests_line); + assert($k == 'Num Tests'); + $num_tests = intval($v); + + foreach (array_slice($cases, 0, count($cases) - 1) as $case) { + list($desc, $markup, $links) = $this->parseCase($case); + $tests[] = array($desc, $markup, $links, $case); + } + + return array($num_tests, $tests); + } + + function Tests_Net_OpenID_Parse() + { + $here = realpath(dirname(__FILE__)); + $test_data_file_name = $here . DIRECTORY_SEPARATOR . 'linkparse.txt'; + $test_data = file_get_contents($test_data_file_name); + + list($num_tests, $test_cases) = $this->parseTests($test_data); + + $this->addTest(new NumTestCases($test_cases, $num_tests)); + + foreach ($test_cases as $case) { + $this->addTest(new Tests_Net_OpenID_Link($case)); + } + } +} + +?>
\ No newline at end of file diff --git a/Tests/Net/OpenID/linkparse.txt b/Tests/Net/OpenID/linkparse.txt new file mode 100644 index 0000000..2206395 --- /dev/null +++ b/Tests/Net/OpenID/linkparse.txt @@ -0,0 +1,583 @@ +Num Tests: 72 + +OpenID link parsing test cases +Copyright (C) 2005-2006, JanRain, Inc. +See COPYING for license information. + +File format +----------- + +All text before the first triple-newline (this chunk) should be ignored. + +This file may be interpreted as Latin-1 or UTF-8. + +Test cases separated by three line separators (`\n\n\n'). The test +cases consist of a headers section followed by a data block. These are +separated by a double newline. The headers consist of the header name, +followed by a colon, a space, the value, and a newline. There must be +one, and only one, `Name' header for a test case. There may be zero or +more link headers. The `Link' header consists of whitespace-separated +attribute pairs. A link header with an empty string as a value +indicates an empty but present link tag. The attribute pairs are `=' +separated and not quoted. + +Optional Links and attributes have a trailing `*'. A compilant +implementation may produce this as output or may not. A compliant +implementation will not produce any output that is absent from this +file. + + +Name: No link tag at all + +<html> +<head> +</head> +</html> + + +Name: Link element first + +<link> + + +Name: Link inside HTML, not head + +<html> +<link> + + +Name: Link inside head, not html + +<head> +<link> + + +Name: Link inside html, after head + +<html> +<head> +</head> +<link> + + +Name: Link inside html, before head + +<html> +<link> +<head> + + +Name: Link before html and head + +<link> +<html> +<head> + + +Name: Link after html document with head + +<html> +<head> +</head> +</html> +<link> + + +Name: Link inside html inside head, inside another html + +<html> +<head> +<html> +<link> + + +Name: Link inside html inside head + +<head> +<html> +<link> + + +Name: link inside body inside head inside html + +<html> +<head> +<body> +<link> + + +Name: Link inside head inside head inside html + +<html> +<head> +<head> +<link> + + +Name: Link inside script inside head inside html + +<html> +<head> +<script> +<link> +</script> + + +Name: Link inside comment inside head inside html + +<html> +<head/> +<link> + + +Name: Link inside of head after short head + +<html> +<head/> +<head> +<link> + + +Name: Plain vanilla +Link: + +<html> +<head> +<link> + + +Name: Ignore tags in the <script:... > namespace +Link*: + +<html> +<head> +<script:paddypan> +<link> +</script:paddypan> + + +Name: Short link tag +Link: + +<html> +<head> +<link/> + + +Name: Spaces in the HTML tag +Link: + +<html > +<head> +<link> + + +Name: Spaces in the head tag +Link: + +<html> +<head > +<link> + + +Name: Spaces in the link tag +Link: + +<html> +<head> +<link > + + +Name: No whitespace +Link: + +<html><head><link> + + +Name: Closed head tag +Link: + +<html> +<head> +<link> +</head> + + +Name: One good, one bad (after close head) +Link: + +<html> +<head> +<link> +</head> +<link> + + +Name: One good, one bad (after open body) +Link: + +<html> +<head> +<link> +<body> +<link> + + +Name: ill formed (missing close head) +Link: + +<html> +<head> +<link> +</html> + + +Name: Ill formed (no close head, link after </html>) +Link: + +<html> +<head> +<link> +</html> +<link> + + +Name: Ignore random tags inside of html +Link: + +<html> +<delicata> +<head> +<title> +<link> + + +Name: case-folding +Link*: + +<HtMl> +<hEaD> +<LiNk> + + +Name: unexpected tags +Link: + +<butternut> +<html> +<summer> +<head> +<turban> +<link> + + +Name: un-closed script tags +Link*: + +<html> +<head> +<script> +<link> + + +Name: un-closed script tags (no whitespace) +Link*: + +<html><head><script><link> + + +Name: un-closed comment +Link*: + +<html> +<head> +<!-- +<link> + + +Name: un-closed CDATA +Link*: + +<html> +<head> +<![CDATA[ +<link> + + +Name: cdata-like +Link*: + +<html> +<head> +<![ACORN[ +<link> +]]> + + +Name: comment close only +Link: + +<html> +<head> +<link> +--> + + +Name: Vanilla, two links +Link: +Link: + +<html> +<head> +<link> +<link> + + +Name: extra tag, two links +Link: +Link: + +<html> +<gold nugget> +<head> +<link> +<link> + + +Name: case-fold, body ends, two links +Link: +Link*: + +<html> +<head> +<link> +<LiNk> +<body> +<link> + + +Name: simple, non-quoted rel +Link: rel=openid.server + +<html><head><link rel=openid.server> + + +Name: short tag has rel +Link: rel=openid.server + +<html><head><link rel=openid.server/> + + +Name: short tag w/space has rel +Link: rel=openid.server + +<html><head><link rel=openid.server /> + + +Name: extra non-attribute, has rel +Link: rel=openid.server + +<html><head><link hubbard rel=openid.server> + + +Name: non-attr, has rel, short +Link: rel=openid.server + +<html><head><link hubbard rel=openid.server/> + + +Name: non-attr, has rel, short, space +Link: rel=openid.server + +<html><head><link hubbard rel=openid.server /> + + +Name: misplaced slash has rel +Link: rel=openid.server + +<html><head><link / rel=openid.server> + + +Name: quoted rel +Link: rel=openid.server + +<html><head><link rel="openid.server"> + + +Name: single-quoted rel +Link: rel=openid.server + +<html><head><link rel='openid.server'> + + +Name: two links w/ rel +Link: x=y +Link: a=b + +<html><head><link x=y><link a=b> + + +Name: non-entity +Link: x=&y + +<html><head><link x=&y> + + +Name: quoted non-entity +Link: x=&y + +<html><head><link x="&y"> + + +Name: quoted entity +Link: x=& + +<html><head><link x="&"> + + +Name: entity not processed +Link: x= + +<html><head><link x=""> + + +Name: < +Link: x=< + +<html><head><link x="<"> + + +Name: > +Link: x=> + +<html><head><link x=">"> + + +Name: " +Link: x=" + +<html><head><link x="""> + + +Name: &" +Link: x=&" + +<html><head><link x="&""> + + +Name: mixed entity and non-entity +Link: x=&"…> + +<html><head><link x="&"…>"> + + +Name: mixed entity and non-entity (w/normal chars) +Link: x=x&"…>x + +<html><head><link x="x&"…>x"> + + +Name: broken tags +Link*: x=y + +<html><head><link x=y<> + + +Name: missing close pointy +Link: z=y + +<html><head><link x=y<link z=y /> + + +Name: missing attribute value +Link: x=y y*= +Link: x=y + +<html><head><link x=y y=><link x=y /> + + +Name: Missing close pointy (no following) +Link*: x=y + +<html><head><link x=y + + +Name: Should be quoted +Link: x*=< + +<html><head><link x="<"> + + +Name: Should be quoted (2) +Link: x*=> + +<html><head><link x=">"> + + +Name: Repeated attribute +Link: x=y + +<html><head><link x=z x=y> + + +Name: Repeated attribute (2) +Link: x=y + +<html><head><link x=y x=y> + + +Name: Two attributes +Link: x=y y=z + +<html><head><link x=y y=z> + + +Name: Well-formed link rel="openid.server" +Link: rel=openid.server href=http://www.myopenid.com/server + +<html> + <head> + <link rel="openid.server" + href="http://www.myopenid.com/server" /> + </head> +</html> + + +Name: Well-formed link rel="openid.server" and "openid.delegate" +Link: rel=openid.server href=http://www.myopenid.com/server +Link: rel=openid.delegate href=http://example.myopenid.com/ + +<html><head><link rel="openid.server" + href="http://www.myopenid.com/server" /> + <link rel="openid.delegate" href="http://example.myopenid.com/" /> +</head></html> + + +Name: from brian's livejournal page +Link: rel=stylesheet href=http://www.livejournal.com/~serotta/res/319998/stylesheet?1130478711 type=text/css +Link: rel=openid.server href=http://www.livejournal.com/openid/server.bml + +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <link rel="stylesheet" + href="http://www.livejournal.com/~serotta/res/319998/stylesheet?1130478711" + type="text/css" /> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <meta name="foaf:maker" + content="foaf:mbox_sha1sum '12f8abdacb5b1a806711e23249da592c0d316260'" /> + <meta name="robots" content="noindex, nofollow, noarchive" /> + <meta name="googlebot" content="nosnippet" /> + <link rel="openid.server" + href="http://www.livejournal.com/openid/server.bml" /> + <title>Brian</title> + </head> + + +Name: non-ascii (Latin-1 or UTF8) +Link: x=® + +<html><head><link x="®"> + + diff --git a/Tests/TestDriver.php b/Tests/TestDriver.php index 6986f02..ea9ee95 100644 --- a/Tests/TestDriver.php +++ b/Tests/TestDriver.php @@ -136,6 +136,7 @@ $_test_names = array( 'HMACSHA1', 'Association', 'StoreTest', + 'Parse' ); function selectTests($names) |