2
# Copyright 2006-2009 Canonical Ltd. All rights reserved.
4
# This file is part of lazr.uri
6
# lazr.uri is free software: you can redistribute it and/or modify it
7
# under the terms of the GNU Lesser General Public License as published by
8
# the Free Software Foundation, version 3 of the License.
10
# lazr.uri is distributed in the hope that it will be useful, but WITHOUT
11
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13
# License for more details.
15
# You should have received a copy of the GNU Lesser General Public License
16
# along with lazr.uri. If not, see <http://www.gnu.org/licenses/>.
24
from collections import defaultdict
27
from lazr.uri import (
28
InvalidURIError, URI, find_uris_in_text, merge, remove_dot_segments)
31
class URITestCase(unittest.TestCase):
33
def test_normalisation(self):
34
# URI normalisation examples from Section 6.2.2 of RFC 3986.
35
self.assertEqual(str(URI('eXAMPLE://a/./b/../b/%63/%7bfoo%7d')),
36
'example://a/b/c/%7Bfoo%7D')
38
self.assertEqual(str(URI('http://www.EXAMPLE.com/')),
39
'http://www.example.com/')
40
self.assertEqual(str(URI('http://www.gnome.org/%7ejamesh/')),
41
'http://www.gnome.org/~jamesh/')
43
# Port number normalisation, and adding missing slash for URIs
45
self.assertEqual(str(URI('http://example.com')),
46
'http://example.com/')
47
self.assertEqual(str(URI('http://example.com:/')),
48
'http://example.com/')
49
self.assertEqual(str(URI('http://example.com:80/')),
50
'http://example.com/')
52
def test_hashable(self):
54
['eXAMPLE://a/./b/../b/%63/%7bfoo%7d',
55
'example://a/b/c/%7Bfoo%7D'],
56
['http://www.EXAMPLE.com/',
57
'http://www.example.com/'],
58
['http://www.gnome.org/%7ejamesh/',
59
'http://www.gnome.org/~jamesh/'],
60
['http://example.com',
61
'http://example.com/',
62
'http://example.com:/',
63
'http://example.com:80/'],
65
uri_hashes = defaultdict(list)
66
for uri_group in uri_groups:
68
uri_hashes[hash(URI(uri))].append(uri)
69
self.assertEqual(len(uri_groups), len(uri_hashes))
70
for uri_group in uri_groups:
73
sorted(uri_hashes[hash(URI(uri_group[0]))]))
75
def test_invalid_uri(self):
76
self.assertRaises(InvalidURIError, URI, 'http://€xample.com/')
79
# Test that the merge() function performs as described in
80
# Section 5.2.3 of RFC 3986
81
self.assertEqual(merge('', 'foo', has_authority=True), '/foo')
82
self.assertEqual(merge('', 'foo', has_authority=False), 'foo')
83
self.assertEqual(merge('/a/b/c', 'foo', has_authority=True),
85
self.assertEqual(merge('/a/b/', 'foo', has_authority=True),
88
def test_remove_dot_segments(self):
89
# remove_dot_segments() examples from Section 5.2.4 of RFC 3986:
90
self.assertEqual(remove_dot_segments('/a/b/c/./../../g'), '/a/g')
91
self.assertEqual(remove_dot_segments('mid/content=5/../6'), 'mid/6')
93
def test_normal_resolution(self):
94
# Normal URI resolution examples from Section 5.4.1 of RFC 3986:
95
base = URI('http://a/b/c/d;p?q')
96
def resolve(relative):
97
return str(base.resolve(relative))
98
self.assertEqual(resolve('g:h'), 'g:h')
99
self.assertEqual(resolve('g'), 'http://a/b/c/g')
100
self.assertEqual(resolve('./g'), 'http://a/b/c/g')
101
self.assertEqual(resolve('g/'), 'http://a/b/c/g/')
102
self.assertEqual(resolve('/g'), 'http://a/g')
103
# The extra slash here comes from normalisation:
104
self.assertEqual(resolve('//g'), 'http://g/')
105
self.assertEqual(resolve('?y'), 'http://a/b/c/d;p?y')
106
self.assertEqual(resolve('g?y'), 'http://a/b/c/g?y')
107
self.assertEqual(resolve('#s'), 'http://a/b/c/d;p?q#s')
108
self.assertEqual(resolve('g#s'), 'http://a/b/c/g#s')
109
self.assertEqual(resolve('g?y#s'), 'http://a/b/c/g?y#s')
110
self.assertEqual(resolve(';x'), 'http://a/b/c/;x')
111
self.assertEqual(resolve('g;x'), 'http://a/b/c/g;x')
112
self.assertEqual(resolve('g;x?y#s'), 'http://a/b/c/g;x?y#s')
113
self.assertEqual(resolve(''), 'http://a/b/c/d;p?q')
114
self.assertEqual(resolve('.'), 'http://a/b/c/')
115
self.assertEqual(resolve('./'), 'http://a/b/c/')
116
self.assertEqual(resolve('..'), 'http://a/b/')
117
self.assertEqual(resolve('../'), 'http://a/b/')
118
self.assertEqual(resolve('../g'), 'http://a/b/g')
119
self.assertEqual(resolve('../..'), 'http://a/')
120
self.assertEqual(resolve('../../'), 'http://a/')
121
self.assertEqual(resolve('../../g'), 'http://a/g')
123
def test_abnormal_resolution(self):
124
# Abnormal URI resolution examples from Section 5.4.2 of RFC 3986:
125
base = URI('http://a/b/c/d;p?q')
126
def resolve(relative):
127
return str(base.resolve(relative))
128
self.assertEqual(resolve('../../../g'), 'http://a/g')
129
self.assertEqual(resolve('../../../../g'),'http://a/g')
130
self.assertEqual(resolve('/./g'), 'http://a/g')
131
self.assertEqual(resolve('/../g'), 'http://a/g')
132
self.assertEqual(resolve('g.'), 'http://a/b/c/g.')
133
self.assertEqual(resolve('.g'), 'http://a/b/c/.g')
134
self.assertEqual(resolve('g..'), 'http://a/b/c/g..')
135
self.assertEqual(resolve('..g'), 'http://a/b/c/..g')
136
self.assertEqual(resolve('./../g'), 'http://a/b/g')
137
self.assertEqual(resolve('./g/.'), 'http://a/b/c/g/')
138
self.assertEqual(resolve('g/./h'), 'http://a/b/c/g/h')
139
self.assertEqual(resolve('g/../h'), 'http://a/b/c/h')
140
self.assertEqual(resolve('g;x=1/./y'), 'http://a/b/c/g;x=1/y')
141
self.assertEqual(resolve('g;x=1/../y'), 'http://a/b/c/y')
142
self.assertEqual(resolve('g?y/./x'), 'http://a/b/c/g?y/./x')
143
self.assertEqual(resolve('g?y/../x'), 'http://a/b/c/g?y/../x')
144
self.assertEqual(resolve('g#s/./x'), 'http://a/b/c/g#s/./x')
145
self.assertEqual(resolve('g#s/../x'), 'http://a/b/c/g#s/../x')
146
# XXX 2009-01-30 jamesh:
147
# I've disabled this test since we refuse to accept HTTP URIs
148
# without a hostname component.
149
#self.assertEqual(resolve('http:g'), 'http:g')
151
def test_underDomain_matches_subdomain(self):
152
# URI.underDomain should return True when asked whether the url is
153
# under one of its parent domains.
154
uri = URI('http://code.launchpad.dev/foo')
155
self.assertTrue(uri.underDomain('code.launchpad.dev'))
156
self.assertTrue(uri.underDomain('launchpad.dev'))
157
self.assertTrue(uri.underDomain(''))
159
def test_underDomain_doesnt_match_non_subdomain(self):
160
# URI.underDomain should return False when asked whether the url is
161
# under a domain which isn't one of its parents.
162
uri = URI('http://code.launchpad.dev/foo')
163
self.assertFalse(uri.underDomain('beta.code.launchpad.dev'))
164
self.assertFalse(uri.underDomain('google.com'))
165
self.assertFalse(uri.underDomain('unchpad.dev'))
168
def additional_tests():
169
return unittest.TestLoader().loadTestsFromName(__name__)