Better exception handling in GUI.
[zeroinstall/zeroinstall-rsl.git] / tests / testautopolicy.py
blob955c1e19747064fb5c0d668517f3ad9e1600129e
1 #!/usr/bin/env python2.4
2 from basetest import BaseTest
3 import sys, tempfile, os, shutil, logging
4 from StringIO import StringIO
5 import unittest
6 from logging import getLogger, DEBUG, INFO
8 sys.path.insert(0, '..')
10 from zeroinstall import NeedDownload
11 from zeroinstall.injector import model, autopolicy, gpg, iface_cache, namespaces, reader
12 from zeroinstall.support import basedir
13 import data
15 foo_iface_uri = 'http://foo'
17 logger = logging.getLogger()
19 class TestAutoPolicy(BaseTest):
20 def setUp(self):
21 BaseTest.setUp(self)
22 stream = tempfile.TemporaryFile()
23 stream.write(data.thomas_key)
24 stream.seek(0)
25 gpg.import_key(stream)
27 def cache_iface(self, name, data):
28 cached_ifaces = basedir.save_cache_path('0install.net',
29 'interfaces')
31 f = file(os.path.join(cached_ifaces, model.escape(name)), 'w')
32 f.write(data)
33 f.close()
35 def testNoNeedDl(self):
36 policy = autopolicy.AutoPolicy(foo_iface_uri,
37 download_only = False)
38 policy.freshness = 0
39 assert policy.need_download()
41 policy = autopolicy.AutoPolicy(os.path.abspath('Foo.xml'),
42 download_only = False)
43 assert not policy.need_download()
45 def testUnknownAlg(self):
46 self.cache_iface(foo_iface_uri,
47 """<?xml version="1.0" ?>
48 <interface
49 uri="%s"
50 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
51 <name>Foo</name>
52 <summary>Foo</summary>
53 <description>Foo</description>
54 <implementation id='unknown=123' version='1.0'>
55 <archive href='http://foo/foo.tgz' size='100'/>
56 </implementation>
57 </interface>""" % foo_iface_uri)
58 policy = autopolicy.AutoPolicy(foo_iface_uri,
59 download_only = False)
60 policy.freshness = 0
61 try:
62 assert policy.need_download()
63 policy.execute([])
64 except model.SafeException, ex:
65 assert 'Unknown digest algorithm' in str(ex)
67 def testDownload(self):
68 tmp = tempfile.NamedTemporaryFile()
69 tmp.write(
70 """<?xml version="1.0" ?>
71 <interface
72 main='ThisBetterNotExist'
73 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
74 <name>Foo</name>
75 <summary>Foo</summary>
76 <description>Foo</description>
77 <implementation version='1.0' id='/bin'/>
78 </interface>""")
79 tmp.flush()
80 policy = autopolicy.AutoPolicy(tmp.name, False, False)
81 try:
82 policy.download_and_execute(['Hello'])
83 assert 0
84 except model.SafeException, ex:
85 assert "ThisBetterNotExist" in str(ex)
86 tmp.close()
88 def testNoMain(self):
89 tmp = tempfile.NamedTemporaryFile()
90 tmp.write(
91 """<?xml version="1.0" ?>
92 <interface
93 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
94 <name>Foo</name>
95 <summary>Foo</summary>
96 <description>Foo</description>
97 <implementation version='1.0' id='/bin'/>
98 </interface>""")
99 tmp.flush()
100 policy = autopolicy.AutoPolicy(tmp.name, False, False)
101 try:
102 policy.download_and_execute(['Hello'])
103 assert 0
104 except model.SafeException, ex:
105 assert "library" in str(ex)
106 tmp.close()
108 def testNeedDL(self):
109 self.cache_iface(foo_iface_uri,
110 """<?xml version="1.0" ?>
111 <interface last-modified="0"
112 uri="%s"
113 main='ThisBetterNotExist'
114 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
115 <name>Foo</name>
116 <summary>Foo</summary>
117 <description>Foo</description>
118 <implementation version='1.0' id='sha1=123'>
119 <archive href='http://foo/foo.tgz' size='100'/>
120 </implementation>
121 </interface>""" % foo_iface_uri)
122 policy = autopolicy.AutoPolicy(foo_iface_uri, False, True)
123 policy.freshness = 0
124 policy.network_use = model.network_full
125 policy.recalculate()
126 assert policy.need_download()
127 try:
128 policy.execute([], main = 'NOTHING')
129 assert False
130 except NeedDownload, ex:
131 pass
133 def testBinding(self):
134 local_impl = os.path.dirname(os.path.abspath(__file__))
135 tmp = tempfile.NamedTemporaryFile()
136 tmp.write(
137 """<?xml version="1.0" ?>
138 <interface
139 main='testautopolicy.py'
140 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
141 <name>Bar</name>
142 <summary>Bar</summary>
143 <description>Bar</description>
144 <group>
145 <requires interface='%s'>
146 <environment name='FOO_PATH' insert='.'/>
147 <environment name='BAR_PATH' insert='.' default='/a:/b'/>
148 <environment name='XDG_DATA_DIRS' insert='.'/>
149 </requires>
150 <environment name='SELF_GROUP' insert='group' mode='replace'/>
151 <implementation version='1.0' id='%s'>
152 <environment name='SELF_IMPL' insert='impl' mode='replace'/>
153 </implementation>
154 </group>
155 </interface>""" % (foo_iface_uri, local_impl))
156 tmp.flush()
157 self.cache_iface(foo_iface_uri,
158 """<?xml version="1.0" ?>
159 <interface last-modified="0"
160 uri="%s"
161 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
162 <name>Foo</name>
163 <summary>Foo</summary>
164 <description>Foo</description>
165 <implementation version='1.0' id='sha1=123'/>
166 </interface>""" % foo_iface_uri)
167 cached_impl = basedir.save_cache_path('0install.net',
168 'implementations',
169 'sha1=123')
170 policy = autopolicy.AutoPolicy(tmp.name, False,
171 dry_run = True)
172 policy.network_use = model.network_offline
173 os.environ['FOO_PATH'] = "old"
174 old, sys.stdout = sys.stdout, StringIO()
175 try:
176 policy.download_and_execute(['Hello'])
177 finally:
178 sys.stdout = old
179 self.assertEquals(cached_impl + '/.:old',
180 os.environ['FOO_PATH'])
181 self.assertEquals(cached_impl + '/.:/a:/b',
182 os.environ['BAR_PATH'])
184 self.assertEquals(os.path.join(local_impl, 'group'), os.environ['SELF_GROUP'])
185 self.assertEquals(os.path.join(local_impl, 'impl'), os.environ['SELF_IMPL'])
187 del os.environ['FOO_PATH']
188 if 'XDG_DATA_DIRS' in os.environ:
189 del os.environ['XDG_DATA_DIRS']
190 os.environ['BAR_PATH'] = '/old'
191 old, sys.stdout = sys.stdout, StringIO()
192 try:
193 policy.download_and_execute(['Hello'])
194 finally:
195 sys.stdout = old
196 self.assertEquals(cached_impl + '/.',
197 os.environ['FOO_PATH'])
198 self.assertEquals(cached_impl + '/.:/old',
199 os.environ['BAR_PATH'])
200 self.assertEquals(cached_impl + '/.:/usr/local/share:/usr/share',
201 os.environ['XDG_DATA_DIRS'])
203 def testFeeds(self):
204 self.cache_iface(foo_iface_uri,
205 """<?xml version="1.0" ?>
206 <interface last-modified="0"
207 uri="%s"
208 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
209 <name>Foo</name>
210 <summary>Foo</summary>
211 <description>Foo</description>
212 <feed src='http://bar'/>
213 </interface>""" % foo_iface_uri)
214 self.cache_iface('http://bar',
215 """<?xml version="1.0" ?>
216 <interface last-modified="0"
217 uri="http://bar"
218 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
219 <feed-for interface='%s'/>
220 <name>Bar</name>
221 <summary>Bar</summary>
222 <description>Bar</description>
223 <implementation version='1.0' id='sha1=123'/>
224 </interface>""" % foo_iface_uri)
225 policy = autopolicy.AutoPolicy(foo_iface_uri, False,
226 dry_run = True)
227 policy.freshness = 0
228 policy.network_use = model.network_full
229 policy.recalculate()
230 assert policy.ready
231 foo_iface = policy.get_interface(foo_iface_uri)
232 self.assertEquals('sha1=123', policy.implementation[foo_iface].id)
234 def testBadConfig(self):
235 path = basedir.save_config_path(namespaces.config_site,
236 namespaces.config_prog)
237 glob = os.path.join(path, 'global')
238 assert not os.path.exists(glob)
239 stream = file(glob, 'w')
240 stream.write('hello!')
241 stream.close()
243 logger.setLevel(logging.ERROR)
244 policy = autopolicy.AutoPolicy(foo_iface_uri,
245 download_only = False)
246 logger.setLevel(logging.WARN)
248 def testNoLocal(self):
249 self.cache_iface(foo_iface_uri,
250 """<?xml version="1.0" ?>
251 <interface last-modified="1110752708"
252 uri="%s"
253 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
254 <name>Foo</name>
255 <summary>Foo</summary>
256 <description>Foo</description>
257 <feed src='/etc/passwd'/>
258 </interface>""" % foo_iface_uri)
259 policy = autopolicy.AutoPolicy(foo_iface_uri,
260 download_only = False)
261 policy.network_use = model.network_offline
262 try:
263 policy.get_interface(foo_iface_uri)
264 assert False
265 except reader.InvalidInterface, ex:
266 assert 'Invalid feed URL' in str(ex)
268 def testDLfeed(self):
269 self.cache_iface(foo_iface_uri,
270 """<?xml version="1.0" ?>
271 <interface last-modified="1110752708"
272 uri="%s"
273 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
274 <name>Foo</name>
275 <summary>Foo</summary>
276 <description>Foo</description>
277 <feed src='http://example.com'/>
278 </interface>""" % foo_iface_uri)
279 policy = autopolicy.AutoPolicy(foo_iface_uri, dry_run = True)
280 policy.network_use = model.network_full
281 policy.freshness = 0
283 try:
284 policy.recalculate()
285 assert False
286 except NeedDownload, ex:
287 pass
289 iface = policy.get_interface(foo_iface_uri)
290 iface._main_feed.feeds = [model.Feed('/BadFeed', None, False)]
292 logger.setLevel(logging.ERROR)
293 policy.recalculate() # Triggers warning
294 logger.setLevel(logging.WARN)
296 def testBestUnusable(self):
297 self.cache_iface(foo_iface_uri,
298 """<?xml version="1.0" ?>
299 <interface last-modified="1110752708"
300 uri="%s"
301 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
302 <name>Foo</name>
303 <summary>Foo</summary>
304 <description>Foo</description>
305 <implementation id='sha1=123' version='1.0' arch='odd-weird'/>
306 </interface>""" % foo_iface_uri)
307 policy = autopolicy.AutoPolicy(foo_iface_uri,
308 download_only = False)
309 policy.network_use = model.network_offline
310 policy.recalculate()
311 assert not policy.ready, policy.implementation
312 try:
313 policy.download_and_execute([])
314 assert False
315 except model.SafeException, ex:
316 assert "Can't find all required implementations" in str(ex)
318 def testNoArchives(self):
319 self.cache_iface(foo_iface_uri,
320 """<?xml version="1.0" ?>
321 <interface last-modified="1110752708"
322 uri="%s"
323 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
324 <name>Foo</name>
325 <summary>Foo</summary>
326 <description>Foo</description>
327 <implementation id='sha1=123' version='1.0'/>
328 </interface>""" % foo_iface_uri)
329 policy = autopolicy.AutoPolicy(foo_iface_uri,
330 download_only = False)
331 policy.freshness = 0
332 policy.recalculate()
333 assert policy.ready
334 try:
335 policy.download_and_execute([])
336 assert False
337 except model.SafeException, ex:
338 assert 'no download locations' in str(ex), ex
340 def testCycle(self):
341 self.cache_iface(foo_iface_uri,
342 """<?xml version="1.0" ?>
343 <interface last-modified="1110752708"
344 uri="%s"
345 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
346 <name>Foo</name>
347 <summary>Foo</summary>
348 <description>Foo</description>
349 <group>
350 <requires interface='%s'/>
351 <implementation id='sha1=123' version='1.0'/>
352 </group>
353 </interface>""" % (foo_iface_uri, foo_iface_uri))
354 policy = autopolicy.AutoPolicy(foo_iface_uri,
355 download_only = False)
356 policy.freshness = 0
357 policy.recalculate()
359 def testConstraints(self):
360 self.cache_iface('http://bar',
361 """<?xml version="1.0" ?>
362 <interface last-modified="1110752708"
363 uri="http://bar"
364 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
365 <name>Bar</name>
366 <summary>Bar</summary>
367 <description>Bar</description>
368 <implementation id='sha1=100' version='1.0'/>
369 <implementation id='sha1=150' stability='developer' version='1.5'/>
370 <implementation id='sha1=200' version='2.0'/>
371 </interface>""")
372 self.cache_iface(foo_iface_uri,
373 """<?xml version="1.0" ?>
374 <interface last-modified="1110752708"
375 uri="%s"
376 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
377 <name>Foo</name>
378 <summary>Foo</summary>
379 <description>Foo</description>
380 <group>
381 <requires interface='http://bar'>
382 <version/>
383 </requires>
384 <implementation id='sha1=123' version='1.0'/>
385 </group>
386 </interface>""" % foo_iface_uri)
387 policy = autopolicy.AutoPolicy(foo_iface_uri,
388 download_only = False)
389 policy.network_use = model.network_full
390 policy.freshness = 0
391 #logger.setLevel(logging.DEBUG)
392 policy.recalculate()
393 #logger.setLevel(logging.WARN)
394 foo_iface = policy.get_interface(foo_iface_uri)
395 bar_iface = policy.get_interface('http://bar')
396 assert policy.implementation[bar_iface].id == 'sha1=200'
398 dep = policy.implementation[foo_iface].dependencies['http://bar']
399 assert len(dep.restrictions) == 1
400 restriction = dep.restrictions[0]
402 restriction.before = model.parse_version('2.0')
403 policy.recalculate()
404 assert policy.implementation[bar_iface].id == 'sha1=100'
406 restriction.not_before = model.parse_version('1.5')
407 policy.recalculate()
408 assert policy.implementation[bar_iface].id == 'sha1=150'
410 suite = unittest.makeSuite(TestAutoPolicy)
411 if __name__ == '__main__':
412 sys.argv.append('-v')
413 unittest.main()