updated translations
[zeroinstall/zeroinstall-afb.git] / tests / testmodel.py
blobf623eeb9c7dbb6a854efcaa201343a8197737ff3
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 import basetest
4 from basetest import BaseTest, empty_feed
5 import sys, os
6 from xml.dom import minidom
7 import unittest
8 from StringIO import StringIO
10 sys.path.insert(0, '..')
11 from zeroinstall.injector import model, qdom, namespaces
13 mydir = os.path.dirname(__file__)
15 class TestModel(BaseTest):
16 def testLevels(self):
17 assert model.network_offline in model.network_levels
18 assert model.network_minimal in model.network_levels
19 assert model.network_full in model.network_levels
21 def testStabilities(self):
22 assert 'insecure' in model.stability_levels
23 assert 'buggy' in model.stability_levels
24 assert 'developer' in model.stability_levels
25 assert 'testing' in model.stability_levels
26 assert 'stable' in model.stability_levels
27 assert 'preferred' in model.stability_levels
28 str(model.insecure)
30 def testEscape(self):
31 self.assertEquals("", model.escape(""))
32 self.assertEquals("hello", model.escape("hello"))
33 self.assertEquals("%20", model.escape(" "))
35 self.assertEquals("file%3a%2f%2ffoo%7ebar",
36 model.escape("file://foo~bar"))
37 self.assertEquals("file%3a%2f%2ffoo%25bar",
38 model.escape("file://foo%bar"))
40 self.assertEquals("file:##foo%7ebar",
41 model._pretty_escape("file://foo~bar"))
42 self.assertEquals("file:##foo%25bar",
43 model._pretty_escape("file://foo%bar"))
45 def testUnescape(self):
46 self.assertEquals("", model.unescape(""))
47 self.assertEquals("hello", model.unescape("hello"))
48 self.assertEquals(" ", model.unescape("%20"))
50 self.assertEquals("file://foo~bar",
51 model.unescape("file%3a%2f%2ffoo%7ebar"))
52 self.assertEquals("file://foo%bar",
53 model.unescape("file%3a%2f%2ffoo%25bar"))
55 self.assertEquals("file://foo",
56 model.unescape("file:##foo"))
57 self.assertEquals("file://foo~bar",
58 model.unescape("file:##foo%7ebar"))
59 self.assertEquals("file://foo%bar",
60 model.unescape("file:##foo%25bar"))
62 def testEscaping(self):
63 def check(str):
64 self.assertEquals(str, model.unescape(model.escape(str)))
65 self.assertEquals(str, model.unescape(model._pretty_escape(str)))
67 check(u'http://example.com')
68 check(u'http://example%46com')
69 check(u'http:##example#com')
70 check(u'http://example.com/foo/bar.xml')
71 check(u'%20%21~&!"£ :@;,./{}$%^&()')
73 def testBadInterface(self):
74 try:
75 model.Interface('foo')
76 assert 0
77 except model.SafeException:
78 pass
80 def testInterface(self):
81 i = model.Interface('http://foo')
82 self.assertEquals('(foo)', i.get_name())
83 feed = model.ZeroInstallFeed(empty_feed, local_path = '/foo')
84 self.assertEquals('Empty', feed.get_name())
85 repr(i)
87 def testMetadata(self):
88 main_feed = model.ZeroInstallFeed(empty_feed, local_path = '/foo')
89 e = qdom.parse(StringIO('<ns:b xmlns:ns="a" foo="bar"/>'))
90 main_feed.metadata = [e]
91 assert main_feed.get_metadata('a', 'b') == [e]
92 assert main_feed.get_metadata('b', 'b') == []
93 assert main_feed.get_metadata('a', 'a') == []
94 assert e.getAttribute('foo') == 'bar'
96 def testLocale(self):
97 local_path = os.path.join(mydir, 'Local.xml')
98 dom = qdom.parse(open(local_path))
99 feed = model.ZeroInstallFeed(dom, local_path = local_path)
100 # (defaults to en-US if no language is set in the locale)
101 self.assertEquals("Local feed (English)", feed.summary)
102 self.assertEquals("English", feed.description)
104 self.assertEquals(4, len(feed.summaries))
105 self.assertEquals(2, len(feed.descriptions))
107 try:
108 basetest.test_locale = ('es_ES', 'UTF8')
110 self.assertEquals("Fuente local", feed.summary)
111 self.assertEquals(u"Español", feed.description)
113 basetest.test_locale = ('en_GB', 'UTF8')
115 self.assertEquals("Local feed (English GB)", feed.summary)
117 basetest.test_locale = ('fr_FR', 'UTF8')
119 self.assertEquals("Local feed (English)", feed.summary)
120 self.assertEquals("English", feed.description)
121 finally:
122 basetest.test_locale = (None, None)
124 def testCommand(self):
125 local_path = os.path.join(mydir, 'Command.xml')
126 dom = qdom.parse(open(local_path))
127 feed = model.ZeroInstallFeed(dom, local_path = local_path)
129 assert feed.implementations['a'].main == 'foo'
130 assert feed.implementations['a'].commands['run'].path == 'foo'
131 assert feed.implementations['a'].commands['test'].path == 'test-foo'
133 assert feed.implementations['b'].main == 'bar'
134 assert feed.implementations['b'].commands['run'].path == 'bar'
135 assert feed.implementations['b'].commands['test'].path == 'test-foo'
137 assert feed.implementations['c'].main == 'runnable/missing'
138 assert feed.implementations['c'].commands['run'].path == 'runnable/missing'
139 assert feed.implementations['c'].commands['test'].path == 'test-baz'
141 def testStabPolicy(self):
142 i = model.Interface('http://foo')
143 self.assertEquals(None, i.stability_policy)
144 i.set_stability_policy(model.buggy)
145 self.assertEquals(model.buggy, i.stability_policy)
147 def testImpl(self):
148 i = model.Interface('http://foo')
149 a = model.ZeroInstallImplementation(i, 'foo', None)
150 assert a.id == 'foo'
151 assert a.size == a.version == a.user_stability == None
152 assert a.arch == a.upstream_stability == None
153 assert a.dependencies == {}
154 assert a.download_sources == []
155 assert a.get_stability() is model.testing
156 a.upstream_stability = model.stable
157 assert a.get_stability() is model.stable
158 a.user_stability = model.buggy
159 assert a.get_stability() is model.buggy
160 a.version = model.parse_version('1.2.3')
161 self.assertEquals('1.2.3', a.get_version())
162 a.version = model.parse_version('1.2.3-rc2-post')
163 self.assertEquals('1.2.3-rc2-post', a.get_version())
164 assert str(a) == 'foo'
166 b = model.ZeroInstallImplementation(i, 'foo', None)
167 b.version = [1,2,1]
168 assert b > a
170 def testDownloadSource(self):
171 f = model.ZeroInstallFeed(empty_feed, local_path = '/foo')
172 a = model.ZeroInstallImplementation(f, 'foo', None)
173 a.add_download_source('ftp://foo', 1024, None)
174 a.add_download_source('ftp://foo.tgz', 1025, 'foo')
175 assert a.download_sources[0].url == 'ftp://foo'
176 assert a.download_sources[0].size == 1024
177 assert a.download_sources[0].extract == None
178 assert a.feed is f
180 def testEnvBind(self):
181 a = model.EnvironmentBinding('PYTHONPATH', 'path')
182 assert a.name == 'PYTHONPATH'
183 assert a.insert == 'path'
184 str(a)
186 def testEnvModes(self):
187 prepend = model.EnvironmentBinding('PYTHONPATH', 'lib', None, model.EnvironmentBinding.PREPEND)
188 assert prepend.name == 'PYTHONPATH'
189 assert prepend.insert == 'lib'
190 assert prepend.mode is model.EnvironmentBinding.PREPEND
192 self.assertEquals('/impl/lib:/usr/lib', prepend.get_value('/impl', '/usr/lib'))
193 self.assertEquals('/impl/lib', prepend.get_value('/impl', None))
195 append = model.EnvironmentBinding('PYTHONPATH', 'lib', '/opt/lib', model.EnvironmentBinding.APPEND)
196 assert append.name == 'PYTHONPATH'
197 assert append.insert == 'lib'
198 assert append.mode is model.EnvironmentBinding.APPEND
200 self.assertEquals('/usr/lib:/impl/lib', append.get_value('/impl', '/usr/lib'))
201 self.assertEquals('/opt/lib:/impl/lib', append.get_value('/impl', None))
203 append = model.EnvironmentBinding('PYTHONPATH', 'lib', None, model.EnvironmentBinding.REPLACE)
204 assert append.name == 'PYTHONPATH'
205 assert append.insert == 'lib'
206 assert append.mode is model.EnvironmentBinding.REPLACE
208 self.assertEquals('/impl/lib', append.get_value('/impl', '/usr/lib'))
209 self.assertEquals('/impl/lib', append.get_value('/impl', None))
211 assert model.EnvironmentBinding('PYTHONPATH', 'lib').mode == model.EnvironmentBinding.PREPEND
213 def testOverlay(self):
214 for xml, expected in [('<overlay/>', '<overlay . on />'),
215 ('<overlay src="usr"/>', '<overlay usr on />'),
216 ('<overlay src="package" mount-point="/usr/games"/>', '<overlay package on /usr/games>')]:
217 e = qdom.parse(StringIO(xml))
218 ol = model.process_binding(e)
219 self.assertEquals(expected, str(ol))
221 doc = minidom.parseString('<doc/>')
222 new_xml = str(ol._toxml(doc).toxml())
223 new_e = qdom.parse(StringIO(new_xml))
224 new_ol = model.process_binding(new_e)
225 self.assertEquals(expected, str(new_ol))
227 def testDep(self):
228 b = model.InterfaceDependency('http://foo', element = qdom.Element(namespaces.XMLNS_IFACE, 'requires', {}))
229 assert not b.restrictions
230 assert not b.bindings
231 str(b)
233 def testFeed(self):
234 f = model.Feed('http://feed', arch = None, user_override = False)
235 assert f.uri == 'http://feed'
236 assert f.os == None
237 assert f.machine == None
238 assert f.arch == None
239 assert f.user_override == False
241 f = model.Feed('http://feed', arch = 'Linux-*', user_override = True)
242 assert f.uri == 'http://feed'
243 assert f.os == 'Linux'
244 assert f.machine == None
245 assert f.arch == 'Linux-*'
246 assert f.user_override == True
248 f = model.Feed('http://feed', arch = '*-i386', user_override = True)
249 assert f.uri == 'http://feed'
250 assert f.os == None
251 assert f.machine == 'i386'
252 assert f.arch == '*-i386'
253 assert f.user_override == True
254 assert str(f).startswith('<Feed from')
256 try:
257 f = model.Feed('http://feed', arch = 'i386', user_override = True)
258 assert False
259 except model.SafeException, ex:
260 assert 'Malformed arch' in str(ex)
262 def testCanonical(self):
263 try:
264 model.canonical_iface_uri('http://foo')
265 assert False
266 except model.SafeException, ex:
267 assert 'Missing /' in str(ex)
269 self.assertEquals('http://foo/',
270 model.canonical_iface_uri('http://foo/'))
271 try:
272 model.canonical_iface_uri('bad-name')
273 assert False
274 except model.SafeException, ex:
275 assert 'Bad interface name' in str(ex)
277 def testVersions(self):
278 def pv(v):
279 parsed = model.parse_version(v)
280 assert model.format_version(parsed) == v
281 return parsed
283 assert pv('1.0') > pv('0.9')
284 assert pv('1.0') > pv('1')
285 assert pv('1.0') == pv('1.0')
286 assert pv('0.9.9') < pv('1.0')
287 assert pv('10') > pv('2')
289 def invalid(v):
290 try:
291 pv(v)
292 assert False
293 except model.SafeException:
294 pass
295 invalid('.')
296 invalid('hello')
297 invalid('2./1')
298 invalid('.1')
299 invalid('')
301 # Check parsing
302 assert pv('1') == [[1], 0]
303 assert pv('1.0') == [[1,0], 0]
304 assert pv('1.0-pre5') == [[1,0], -2, [5], 0]
305 assert pv('1.0-rc5') == [[1,0], -1, [5], 0]
306 assert pv('1.0-5') == [[1,0], 0, [5], 0]
307 assert pv('1.0-post5') == [[1,0], 1, [5], 0]
308 assert pv('1.0-post') == [[1,0], 1]
309 assert pv('1-rc2.0-pre2-post') == [[1], -1, [2,0], -2, [2], 1]
310 assert pv('1-rc2.0-pre-post') == [[1], -1, [2,0], -2, [], 1]
312 assert pv('1.0-0') > pv('1.0')
313 assert pv('1.0-1') > pv('1.0-0')
314 assert pv('1.0-0') < pv('1.0-1')
316 assert pv('1.0-pre99') > pv('1.0-pre1')
317 assert pv('1.0-pre99') < pv('1.0-rc1')
318 assert pv('1.0-rc1') < pv('1.0')
319 assert pv('1.0') < pv('1.0-0')
320 assert pv('1.0-0') < pv('1.0-post')
321 assert pv('2.1.9-pre-1') > pv('2.1.9-pre')
323 assert pv('2-post999') < pv('3-pre1')
325 if __name__ == '__main__':
326 unittest.main()