1ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh#! /usr/bin/env python
2ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
3ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom test import test_support
4ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport unittest
5ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport urlparse
6ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
7ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehRFC1808_BASE = "http://a/b/c/d;p?q#f"
8ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehRFC2396_BASE = "http://a/b/c/d;p?q"
9ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehRFC3986_BASE = 'http://a/b/c/d;p?q'
10ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehSIMPLE_BASE  = 'http://a/b/c/d'
11ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
12ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# A list of test cases.  Each test case is a two-tuple that contains
13ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# a string with the query and a dictionary with the expected result.
14ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
15ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehparse_qsl_test_cases = [
16ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    ("", []),
17ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    ("&", []),
18ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    ("&&", []),
19ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    ("=", [('', '')]),
20ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    ("=a", [('', 'a')]),
21ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    ("a", [('a', '')]),
22ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    ("a=", [('a', '')]),
23ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    ("a=", [('a', '')]),
24ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    ("&a=b", [('a', 'b')]),
25ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    ("a=a+b&b=b+c", [('a', 'a b'), ('b', 'b c')]),
26ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    ("a=1&a=2", [('a', '1'), ('a', '2')]),
27ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh]
28ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
29ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass UrlParseTestCase(unittest.TestCase):
30ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
31ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def checkRoundtrips(self, url, parsed, split):
32ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        result = urlparse.urlparse(url)
33ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(result, parsed)
34ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        t = (result.scheme, result.netloc, result.path,
35ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             result.params, result.query, result.fragment)
36ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(t, parsed)
37ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # put it back together and it should be the same
38ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        result2 = urlparse.urlunparse(result)
39ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(result2, url)
40ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(result2, result.geturl())
41ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
42ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # the result of geturl() is a fixpoint; we can always parse it
43ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # again to get the same result:
44ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        result3 = urlparse.urlparse(result.geturl())
45ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(result3.geturl(), result.geturl())
46ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(result3,          result)
47ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(result3.scheme,   result.scheme)
48ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(result3.netloc,   result.netloc)
49ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(result3.path,     result.path)
50ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(result3.params,   result.params)
51ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(result3.query,    result.query)
52ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(result3.fragment, result.fragment)
53ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(result3.username, result.username)
54ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(result3.password, result.password)
55ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(result3.hostname, result.hostname)
56ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(result3.port,     result.port)
57ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
58ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # check the roundtrip using urlsplit() as well
59ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        result = urlparse.urlsplit(url)
60ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(result, split)
61ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        t = (result.scheme, result.netloc, result.path,
62ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             result.query, result.fragment)
63ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(t, split)
64ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        result2 = urlparse.urlunsplit(result)
65ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(result2, url)
66ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(result2, result.geturl())
67ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
68ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # check the fixpoint property of re-parsing the result of geturl()
69ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        result3 = urlparse.urlsplit(result.geturl())
70ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(result3.geturl(), result.geturl())
71ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(result3,          result)
72ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(result3.scheme,   result.scheme)
73ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(result3.netloc,   result.netloc)
74ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(result3.path,     result.path)
75ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(result3.query,    result.query)
76ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(result3.fragment, result.fragment)
77ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(result3.username, result.username)
78ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(result3.password, result.password)
79ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(result3.hostname, result.hostname)
80ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(result3.port,     result.port)
81ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
82ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_qsl(self):
83ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        for orig, expect in parse_qsl_test_cases:
84ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            result = urlparse.parse_qsl(orig, keep_blank_values=True)
85ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.assertEqual(result, expect, "Error parsing %r" % orig)
86ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            expect_without_blanks = [v for v in expect if len(v[1])]
87ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            result = urlparse.parse_qsl(orig, keep_blank_values=False)
88ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.assertEqual(result, expect_without_blanks,
89ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    "Error parsing %r" % orig)
90ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
91ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
92ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_roundtrips(self):
93ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        testcases = [
94ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('file:///tmp/junk.txt',
95ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             ('file', '', '/tmp/junk.txt', '', '', ''),
96ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             ('file', '', '/tmp/junk.txt', '', '')),
97ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('imap://mail.python.org/mbox1',
98ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             ('imap', 'mail.python.org', '/mbox1', '', '', ''),
99ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             ('imap', 'mail.python.org', '/mbox1', '', '')),
100ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('mms://wms.sys.hinet.net/cts/Drama/09006251100.asf',
101ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             ('mms', 'wms.sys.hinet.net', '/cts/Drama/09006251100.asf',
102ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh              '', '', ''),
103ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             ('mms', 'wms.sys.hinet.net', '/cts/Drama/09006251100.asf',
104ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh              '', '')),
105ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('nfs://server/path/to/file.txt',
106ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             ('nfs', 'server', '/path/to/file.txt',  '', '', ''),
107ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             ('nfs', 'server', '/path/to/file.txt', '', '')),
108ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('svn+ssh://svn.zope.org/repos/main/ZConfig/trunk/',
109ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             ('svn+ssh', 'svn.zope.org', '/repos/main/ZConfig/trunk/',
110ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh              '', '', ''),
111ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             ('svn+ssh', 'svn.zope.org', '/repos/main/ZConfig/trunk/',
112ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh              '', '')),
113ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('git+ssh://git@github.com/user/project.git',
114ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('git+ssh', 'git@github.com','/user/project.git',
115ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             '','',''),
116ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('git+ssh', 'git@github.com','/user/project.git',
117ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             '', ''))
118ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ]
119ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        for url, parsed, split in testcases:
120ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.checkRoundtrips(url, parsed, split)
121ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
122ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_http_roundtrips(self):
123ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # urlparse.urlsplit treats 'http:' as an optimized special case,
124ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # so we test both 'http:' and 'https:' in all the following.
125ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # Three cheers for white box knowledge!
126ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        testcases = [
127ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('://www.python.org',
128ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             ('www.python.org', '', '', '', ''),
129ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             ('www.python.org', '', '', '')),
130ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('://www.python.org#abc',
131ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             ('www.python.org', '', '', '', 'abc'),
132ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             ('www.python.org', '', '', 'abc')),
133ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('://www.python.org?q=abc',
134ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             ('www.python.org', '', '', 'q=abc', ''),
135ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             ('www.python.org', '', 'q=abc', '')),
136ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('://www.python.org/#abc',
137ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             ('www.python.org', '/', '', '', 'abc'),
138ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             ('www.python.org', '/', '', 'abc')),
139ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('://a/b/c/d;p?q#f',
140ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             ('a', '/b/c/d', 'p', 'q', 'f'),
141ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             ('a', '/b/c/d;p', 'q', 'f')),
142ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ]
143ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        for scheme in ('http', 'https'):
144ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            for url, parsed, split in testcases:
145ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                url = scheme + url
146ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                parsed = (scheme,) + parsed
147ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                split = (scheme,) + split
148ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                self.checkRoundtrips(url, parsed, split)
149ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
150ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def checkJoin(self, base, relurl, expected):
151ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(urlparse.urljoin(base, relurl), expected,
152ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                         (base, relurl, expected))
153ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
154ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_unparse_parse(self):
155ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        for u in ['Python', './Python','x-newscheme://foo.com/stuff','x://y','x:/y','x:/','/',]:
156ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.assertEqual(urlparse.urlunsplit(urlparse.urlsplit(u)), u)
157ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.assertEqual(urlparse.urlunparse(urlparse.urlparse(u)), u)
158ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
159ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_RFC1808(self):
160ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # "normal" cases from RFC 1808:
161ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, 'g:h', 'g:h')
162ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, 'g', 'http://a/b/c/g')
163ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, './g', 'http://a/b/c/g')
164ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, 'g/', 'http://a/b/c/g/')
165ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, '/g', 'http://a/g')
166ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, '//g', 'http://g')
167ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, 'g?y', 'http://a/b/c/g?y')
168ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, 'g?y/./x', 'http://a/b/c/g?y/./x')
169ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, '#s', 'http://a/b/c/d;p?q#s')
170ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, 'g#s', 'http://a/b/c/g#s')
171ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, 'g#s/./x', 'http://a/b/c/g#s/./x')
172ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, 'g?y#s', 'http://a/b/c/g?y#s')
173ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, 'g;x', 'http://a/b/c/g;x')
174ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, 'g;x?y#s', 'http://a/b/c/g;x?y#s')
175ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, '.', 'http://a/b/c/')
176ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, './', 'http://a/b/c/')
177ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, '..', 'http://a/b/')
178ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, '../', 'http://a/b/')
179ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, '../g', 'http://a/b/g')
180ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, '../..', 'http://a/')
181ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, '../../', 'http://a/')
182ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, '../../g', 'http://a/g')
183ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
184ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # "abnormal" cases from RFC 1808:
185ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, '', 'http://a/b/c/d;p?q#f')
186ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, '../../../g', 'http://a/../g')
187ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, '../../../../g', 'http://a/../../g')
188ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, '/./g', 'http://a/./g')
189ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, '/../g', 'http://a/../g')
190ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, 'g.', 'http://a/b/c/g.')
191ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, '.g', 'http://a/b/c/.g')
192ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, 'g..', 'http://a/b/c/g..')
193ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, '..g', 'http://a/b/c/..g')
194ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, './../g', 'http://a/b/g')
195ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, './g/.', 'http://a/b/c/g/')
196ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, 'g/./h', 'http://a/b/c/g/h')
197ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC1808_BASE, 'g/../h', 'http://a/b/c/h')
198ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
199ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # RFC 1808 and RFC 1630 disagree on these (according to RFC 1808),
200ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # so we'll not actually run these tests (which expect 1808 behavior).
201ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        #self.checkJoin(RFC1808_BASE, 'http:g', 'http:g')
202ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        #self.checkJoin(RFC1808_BASE, 'http:', 'http:')
203ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
204ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_RFC2368(self):
205ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # Issue 11467: path that starts with a number is not parsed correctly
206ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(urlparse.urlparse('mailto:1337@example.org'),
207ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                ('mailto', '', '1337@example.org', '', '', ''))
208ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
209ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_RFC2396(self):
210ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # cases from RFC 2396
211ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, 'g:h', 'g:h')
212ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, 'g', 'http://a/b/c/g')
213ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, './g', 'http://a/b/c/g')
214ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, 'g/', 'http://a/b/c/g/')
215ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, '/g', 'http://a/g')
216ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, '//g', 'http://g')
217ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, 'g?y', 'http://a/b/c/g?y')
218ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, '#s', 'http://a/b/c/d;p?q#s')
219ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, 'g#s', 'http://a/b/c/g#s')
220ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, 'g?y#s', 'http://a/b/c/g?y#s')
221ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, 'g;x', 'http://a/b/c/g;x')
222ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, 'g;x?y#s', 'http://a/b/c/g;x?y#s')
223ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, '.', 'http://a/b/c/')
224ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, './', 'http://a/b/c/')
225ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, '..', 'http://a/b/')
226ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, '../', 'http://a/b/')
227ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, '../g', 'http://a/b/g')
228ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, '../..', 'http://a/')
229ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, '../../', 'http://a/')
230ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, '../../g', 'http://a/g')
231ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, '', RFC2396_BASE)
232ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, '../../../g', 'http://a/../g')
233ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, '../../../../g', 'http://a/../../g')
234ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, '/./g', 'http://a/./g')
235ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, '/../g', 'http://a/../g')
236ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, 'g.', 'http://a/b/c/g.')
237ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, '.g', 'http://a/b/c/.g')
238ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, 'g..', 'http://a/b/c/g..')
239ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, '..g', 'http://a/b/c/..g')
240ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, './../g', 'http://a/b/g')
241ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, './g/.', 'http://a/b/c/g/')
242ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, 'g/./h', 'http://a/b/c/g/h')
243ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, 'g/../h', 'http://a/b/c/h')
244ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, 'g;x=1/./y', 'http://a/b/c/g;x=1/y')
245ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, 'g;x=1/../y', 'http://a/b/c/y')
246ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, 'g?y/./x', 'http://a/b/c/g?y/./x')
247ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, 'g?y/../x', 'http://a/b/c/g?y/../x')
248ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, 'g#s/./x', 'http://a/b/c/g#s/./x')
249ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, 'g#s/../x', 'http://a/b/c/g#s/../x')
250ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
251ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_RFC3986(self):
252ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # Test cases from RFC3986
253ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, '?y','http://a/b/c/d;p?y')
254ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC2396_BASE, ';x', 'http://a/b/c/;x')
255ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, 'g:h','g:h')
256ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, 'g','http://a/b/c/g')
257ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, './g','http://a/b/c/g')
258ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, 'g/','http://a/b/c/g/')
259ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, '/g','http://a/g')
260ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, '//g','http://g')
261ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, '?y','http://a/b/c/d;p?y')
262ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, 'g?y','http://a/b/c/g?y')
263ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, '#s','http://a/b/c/d;p?q#s')
264ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, 'g#s','http://a/b/c/g#s')
265ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, 'g?y#s','http://a/b/c/g?y#s')
266ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, ';x','http://a/b/c/;x')
267ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, 'g;x','http://a/b/c/g;x')
268ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, 'g;x?y#s','http://a/b/c/g;x?y#s')
269ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, '','http://a/b/c/d;p?q')
270ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, '.','http://a/b/c/')
271ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, './','http://a/b/c/')
272ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, '..','http://a/b/')
273ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, '../','http://a/b/')
274ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, '../g','http://a/b/g')
275ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, '../..','http://a/')
276ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, '../../','http://a/')
277ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, '../../g','http://a/g')
278ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
279ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        #Abnormal Examples
280ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
281ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # The 'abnormal scenarios' are incompatible with RFC2986 parsing
282ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # Tests are here for reference.
283ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
284ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        #self.checkJoin(RFC3986_BASE, '../../../g','http://a/g')
285ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        #self.checkJoin(RFC3986_BASE, '../../../../g','http://a/g')
286ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        #self.checkJoin(RFC3986_BASE, '/./g','http://a/g')
287ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        #self.checkJoin(RFC3986_BASE, '/../g','http://a/g')
288ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
289ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, 'g.','http://a/b/c/g.')
290ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, '.g','http://a/b/c/.g')
291ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, 'g..','http://a/b/c/g..')
292ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, '..g','http://a/b/c/..g')
293ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, './../g','http://a/b/g')
294ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, './g/.','http://a/b/c/g/')
295ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, 'g/./h','http://a/b/c/g/h')
296ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, 'g/../h','http://a/b/c/h')
297ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, 'g;x=1/./y','http://a/b/c/g;x=1/y')
298ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, 'g;x=1/../y','http://a/b/c/y')
299ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, 'g?y/./x','http://a/b/c/g?y/./x')
300ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, 'g?y/../x','http://a/b/c/g?y/../x')
301ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, 'g#s/./x','http://a/b/c/g#s/./x')
302ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, 'g#s/../x','http://a/b/c/g#s/../x')
303ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        #self.checkJoin(RFC3986_BASE, 'http:g','http:g') # strict parser
304ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(RFC3986_BASE, 'http:g','http://a/b/c/g') # relaxed parser
305ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
306ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # Test for issue9721
307ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin('http://a/b/c/de', ';x','http://a/b/c/;x')
308ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
309ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_urljoins(self):
310ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(SIMPLE_BASE, 'g:h','g:h')
311ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(SIMPLE_BASE, 'http:g','http://a/b/c/g')
312ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(SIMPLE_BASE, 'http:','http://a/b/c/d')
313ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(SIMPLE_BASE, 'g','http://a/b/c/g')
314ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(SIMPLE_BASE, './g','http://a/b/c/g')
315ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(SIMPLE_BASE, 'g/','http://a/b/c/g/')
316ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(SIMPLE_BASE, '/g','http://a/g')
317ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(SIMPLE_BASE, '//g','http://g')
318ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(SIMPLE_BASE, '?y','http://a/b/c/d?y')
319ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(SIMPLE_BASE, 'g?y','http://a/b/c/g?y')
320ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(SIMPLE_BASE, 'g?y/./x','http://a/b/c/g?y/./x')
321ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(SIMPLE_BASE, '.','http://a/b/c/')
322ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(SIMPLE_BASE, './','http://a/b/c/')
323ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(SIMPLE_BASE, '..','http://a/b/')
324ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(SIMPLE_BASE, '../','http://a/b/')
325ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(SIMPLE_BASE, '../g','http://a/b/g')
326ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(SIMPLE_BASE, '../..','http://a/')
327ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(SIMPLE_BASE, '../../g','http://a/g')
328ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(SIMPLE_BASE, '../../../g','http://a/../g')
329ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(SIMPLE_BASE, './../g','http://a/b/g')
330ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(SIMPLE_BASE, './g/.','http://a/b/c/g/')
331ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(SIMPLE_BASE, '/./g','http://a/./g')
332ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(SIMPLE_BASE, 'g/./h','http://a/b/c/g/h')
333ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(SIMPLE_BASE, 'g/../h','http://a/b/c/h')
334ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(SIMPLE_BASE, 'http:g','http://a/b/c/g')
335ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(SIMPLE_BASE, 'http:','http://a/b/c/d')
336ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(SIMPLE_BASE, 'http:?y','http://a/b/c/d?y')
337ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(SIMPLE_BASE, 'http:g?y','http://a/b/c/g?y')
338ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin(SIMPLE_BASE, 'http:g?y/./x','http://a/b/c/g?y/./x')
339ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin('http:///', '..','http:///')
340ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin('', 'http://a/b/c/g?y/./x','http://a/b/c/g?y/./x')
341ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin('', 'http://a/./g', 'http://a/./g')
342ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin('svn://pathtorepo/dir1','dir2','svn://pathtorepo/dir2')
343ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.checkJoin('svn+ssh://pathtorepo/dir1','dir2','svn+ssh://pathtorepo/dir2')
344ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
345ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_RFC2732(self):
346ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        for url, hostname, port in [
347ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('http://Test.python.org:5432/foo/', 'test.python.org', 5432),
348ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('http://12.34.56.78:5432/foo/', '12.34.56.78', 5432),
349ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('http://[::1]:5432/foo/', '::1', 5432),
350ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('http://[dead:beef::1]:5432/foo/', 'dead:beef::1', 5432),
351ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('http://[dead:beef::]:5432/foo/', 'dead:beef::', 5432),
352ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('http://[dead:beef:cafe:5417:affe:8FA3:deaf:feed]:5432/foo/',
353ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             'dead:beef:cafe:5417:affe:8fa3:deaf:feed', 5432),
354ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('http://[::12.34.56.78]:5432/foo/', '::12.34.56.78', 5432),
355ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('http://[::ffff:12.34.56.78]:5432/foo/',
356ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             '::ffff:12.34.56.78', 5432),
357ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('http://Test.python.org/foo/', 'test.python.org', None),
358ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('http://12.34.56.78/foo/', '12.34.56.78', None),
359ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('http://[::1]/foo/', '::1', None),
360ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('http://[dead:beef::1]/foo/', 'dead:beef::1', None),
361ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('http://[dead:beef::]/foo/', 'dead:beef::', None),
362ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('http://[dead:beef:cafe:5417:affe:8FA3:deaf:feed]/foo/',
363ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             'dead:beef:cafe:5417:affe:8fa3:deaf:feed', None),
364ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('http://[::12.34.56.78]/foo/', '::12.34.56.78', None),
365ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('http://[::ffff:12.34.56.78]/foo/',
366ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             '::ffff:12.34.56.78', None),
367ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ]:
368ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            urlparsed = urlparse.urlparse(url)
369ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.assertEqual((urlparsed.hostname, urlparsed.port) , (hostname, port))
370ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
371ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        for invalid_url in [
372ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                'http://::12.34.56.78]/',
373ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                'http://[::1/foo/',
374ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                'ftp://[::1/foo/bad]/bad',
375ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                'http://[::1/foo/bad]/bad',
376ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                'http://[::ffff:12.34.56.78']:
377ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.assertRaises(ValueError, urlparse.urlparse, invalid_url)
378ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
379ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_urldefrag(self):
380ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        for url, defrag, frag in [
381ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('http://python.org#frag', 'http://python.org', 'frag'),
382ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('http://python.org', 'http://python.org', ''),
383ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('http://python.org/#frag', 'http://python.org/', 'frag'),
384ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('http://python.org/', 'http://python.org/', ''),
385ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('http://python.org/?q#frag', 'http://python.org/?q', 'frag'),
386ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('http://python.org/?q', 'http://python.org/?q', ''),
387ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('http://python.org/p#frag', 'http://python.org/p', 'frag'),
388ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ('http://python.org/p?q', 'http://python.org/p?q', ''),
389ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            (RFC1808_BASE, 'http://a/b/c/d;p?q', 'f'),
390ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            (RFC2396_BASE, 'http://a/b/c/d;p?q', ''),
391ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            ]:
392ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.assertEqual(urlparse.urldefrag(url), (defrag, frag))
393ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
394ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_urlsplit_attributes(self):
395ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        url = "HTTP://WWW.PYTHON.ORG/doc/#frag"
396ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        p = urlparse.urlsplit(url)
397ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.scheme, "http")
398ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.netloc, "WWW.PYTHON.ORG")
399ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.path, "/doc/")
400ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.query, "")
401ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.fragment, "frag")
402ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.username, None)
403ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.password, None)
404ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.hostname, "www.python.org")
405ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.port, None)
406ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # geturl() won't return exactly the original URL in this case
407ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # since the scheme is always case-normalized
408ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        #self.assertEqual(p.geturl(), url)
409ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
410ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        url = "http://User:Pass@www.python.org:080/doc/?query=yes#frag"
411ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        p = urlparse.urlsplit(url)
412ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.scheme, "http")
413ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.netloc, "User:Pass@www.python.org:080")
414ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.path, "/doc/")
415ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.query, "query=yes")
416ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.fragment, "frag")
417ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.username, "User")
418ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.password, "Pass")
419ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.hostname, "www.python.org")
420ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.port, 80)
421ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.geturl(), url)
422ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
423ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # Addressing issue1698, which suggests Username can contain
424ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # "@" characters.  Though not RFC compliant, many ftp sites allow
425ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # and request email addresses as usernames.
426ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
427ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        url = "http://User@example.com:Pass@www.python.org:080/doc/?query=yes#frag"
428ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        p = urlparse.urlsplit(url)
429ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.scheme, "http")
430ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.netloc, "User@example.com:Pass@www.python.org:080")
431ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.path, "/doc/")
432ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.query, "query=yes")
433ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.fragment, "frag")
434ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.username, "User@example.com")
435ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.password, "Pass")
436ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.hostname, "www.python.org")
437ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.port, 80)
438ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.geturl(), url)
439ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
440ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # Verify an illegal port of value greater than 65535 is set as None
441ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        url = "http://www.python.org:65536"
442ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        p = urlparse.urlsplit(url)
443ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.port, None)
444ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
445ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_issue14072(self):
446ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        p1 = urlparse.urlsplit('tel:+31-641044153')
447ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p1.scheme, 'tel')
448ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p1.path, '+31-641044153')
449ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
450ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        p2 = urlparse.urlsplit('tel:+31641044153')
451ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p2.scheme, 'tel')
452ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p2.path, '+31641044153')
453ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
454ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # Assert for urlparse
455ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        p1 = urlparse.urlparse('tel:+31-641044153')
456ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p1.scheme, 'tel')
457ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p1.path, '+31-641044153')
458ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
459ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        p2 = urlparse.urlparse('tel:+31641044153')
460ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p2.scheme, 'tel')
461ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p2.path, '+31641044153')
462ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
463ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
464ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_telurl_params(self):
465ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        p1 = urlparse.urlparse('tel:123-4;phone-context=+1-650-516')
466ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p1.scheme, 'tel')
467ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p1.path, '123-4')
468ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p1.params, 'phone-context=+1-650-516')
469ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
470ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        p1 = urlparse.urlparse('tel:+1-201-555-0123')
471ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p1.scheme, 'tel')
472ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p1.path, '+1-201-555-0123')
473ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p1.params, '')
474ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
475ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        p1 = urlparse.urlparse('tel:7042;phone-context=example.com')
476ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p1.scheme, 'tel')
477ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p1.path, '7042')
478ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p1.params, 'phone-context=example.com')
479ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
480ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        p1 = urlparse.urlparse('tel:863-1234;phone-context=+1-914-555')
481ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p1.scheme, 'tel')
482ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p1.path, '863-1234')
483ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p1.params, 'phone-context=+1-914-555')
484ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
485ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
486ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_attributes_bad_port(self):
487ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        """Check handling of non-integer ports."""
488ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        p = urlparse.urlsplit("http://www.example.net:foo")
489ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.netloc, "www.example.net:foo")
490ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertRaises(ValueError, lambda: p.port)
491ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
492ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        p = urlparse.urlparse("http://www.example.net:foo")
493ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.netloc, "www.example.net:foo")
494ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertRaises(ValueError, lambda: p.port)
495ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
496ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_attributes_without_netloc(self):
497ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # This example is straight from RFC 3261.  It looks like it
498ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # should allow the username, hostname, and port to be filled
499ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # in, but doesn't.  Since it's a URI and doesn't use the
500ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # scheme://netloc syntax, the netloc and related attributes
501ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # should be left empty.
502ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        uri = "sip:alice@atlanta.com;maddr=239.255.255.1;ttl=15"
503ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        p = urlparse.urlsplit(uri)
504ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.netloc, "")
505ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.username, None)
506ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.password, None)
507ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.hostname, None)
508ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.port, None)
509ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.geturl(), uri)
510ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
511ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        p = urlparse.urlparse(uri)
512ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.netloc, "")
513ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.username, None)
514ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.password, None)
515ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.hostname, None)
516ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.port, None)
517ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(p.geturl(), uri)
518ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
519ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_caching(self):
520ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # Test case for bug #1313119
521ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        uri = "http://example.com/doc/"
522ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        unicode_uri = unicode(uri)
523ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
524ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        urlparse.urlparse(unicode_uri)
525ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        p = urlparse.urlparse(uri)
526ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(type(p.scheme), type(uri))
527ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(type(p.hostname), type(uri))
528ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(type(p.path), type(uri))
529ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
530ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_noslash(self):
531ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # Issue 1637: http://foo.com?query is legal
532ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(urlparse.urlparse("http://example.com?blahblah=/foo"),
533ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                         ('http', 'example.com', '', '', 'blahblah=/foo', ''))
534ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
535ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_anyscheme(self):
536ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # Issue 7904: s3://foo.com/stuff has netloc "foo.com".
537ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(urlparse.urlparse("s3://foo.com/stuff"),
538ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                         ('s3','foo.com','/stuff','','',''))
539ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(urlparse.urlparse("x-newscheme://foo.com/stuff"),
540ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                         ('x-newscheme','foo.com','/stuff','','',''))
541ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(urlparse.urlparse("x-newscheme://foo.com/stuff?query#fragment"),
542ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                         ('x-newscheme','foo.com','/stuff','','query','fragment'))
543ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(urlparse.urlparse("x-newscheme://foo.com/stuff?query"),
544ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                         ('x-newscheme','foo.com','/stuff','','query',''))
545ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
546ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_withoutscheme(self):
547ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # Test urlparse without scheme
548ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # Issue 754016: urlparse goes wrong with IP:port without scheme
549ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # RFC 1808 specifies that netloc should start with //, urlparse expects
550ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # the same, otherwise it classifies the portion of url as path.
551ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(urlparse.urlparse("path"),
552ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                ('','','path','','',''))
553ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(urlparse.urlparse("//www.python.org:80"),
554ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                ('','www.python.org:80','','','',''))
555ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(urlparse.urlparse("http://www.python.org:80"),
556ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                ('http','www.python.org:80','','','',''))
557ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
558ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_portseparator(self):
559ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # Issue 754016 makes changes for port separator ':' from scheme separator
560ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(urlparse.urlparse("path:80"),
561ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                ('','','path:80','','',''))
562ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(urlparse.urlparse("http:"),('http','','','','',''))
563ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(urlparse.urlparse("https:"),('https','','','','',''))
564ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(urlparse.urlparse("http://www.python.org:80"),
565ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                ('http','www.python.org:80','','','',''))
566ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
567ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef test_main():
568ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    test_support.run_unittest(UrlParseTestCase)
569ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
570ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehif __name__ == "__main__":
571ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    test_main()
572