Don't try to read dpkg database unless its directory is accessible to us.
[zeroinstall/zeroinstall-mseaborn.git] / tests / testautopolicy.py
blobe41b7be23db3bad1a8745562639be6758cac1c77
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, basedir, autopolicy, gpg, iface_cache, namespaces, reader
12 import data
14 foo_iface_uri = 'http://foo'
16 logger = logging.getLogger()
18 class TestAutoPolicy(BaseTest):
19 def setUp(self):
20 BaseTest.setUp(self)
21 stream = tempfile.TemporaryFile()
22 stream.write(data.thomas_key)
23 stream.seek(0)
24 gpg.import_key(stream)
26 def cache_iface(self, name, data):
27 cached_ifaces = basedir.save_cache_path('0install.net',
28 'interfaces')
30 f = file(os.path.join(cached_ifaces, model.escape(name)), 'w')
31 f.write(data)
32 f.close()
34 def testNoNeedDl(self):
35 policy = autopolicy.AutoPolicy(foo_iface_uri,
36 download_only = False)
37 policy.freshness = 0
38 assert policy.need_download()
39 self.cache_iface(foo_iface_uri,
40 """<?xml version="1.0" ?>
41 <interface last-modified="1110752708"
42 uri="%s"
43 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
44 <name>Foo</name>
45 <summary>Foo</summary>
46 <description>Foo</description>
47 </interface>""" % foo_iface_uri)
48 iface_cache.iface_cache._interfaces = {}
49 assert not policy.need_download()
51 def testUnknownAlg(self):
52 self.cache_iface(foo_iface_uri,
53 """<?xml version="1.0" ?>
54 <interface
55 uri="%s"
56 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
57 <name>Foo</name>
58 <summary>Foo</summary>
59 <description>Foo</description>
60 <implementation id='unknown=123' version='1.0'>
61 <archive href='http://foo/foo.tgz' size='100'/>
62 </implementation>
63 </interface>""" % foo_iface_uri)
64 policy = autopolicy.AutoPolicy(foo_iface_uri,
65 download_only = False)
66 policy.freshness = 0
67 try:
68 assert policy.need_download()
69 assert False
70 except model.SafeException, ex:
71 assert 'Unknown digest algorithm' in str(ex)
73 def testDownload(self):
74 tmp = tempfile.NamedTemporaryFile()
75 tmp.write(
76 """<?xml version="1.0" ?>
77 <interface
78 main='ThisBetterNotExist'
79 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
80 <name>Foo</name>
81 <summary>Foo</summary>
82 <description>Foo</description>
83 <implementation version='1.0' id='/bin'/>
84 </interface>""")
85 tmp.flush()
86 policy = autopolicy.AutoPolicy(tmp.name, False, False)
87 try:
88 policy.download_and_execute(['Hello'])
89 assert 0
90 except model.SafeException, ex:
91 assert "ThisBetterNotExist" in str(ex)
92 tmp.close()
94 def testNoMain(self):
95 tmp = tempfile.NamedTemporaryFile()
96 tmp.write(
97 """<?xml version="1.0" ?>
98 <interface
99 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
100 <name>Foo</name>
101 <summary>Foo</summary>
102 <description>Foo</description>
103 <implementation version='1.0' id='/bin'/>
104 </interface>""")
105 tmp.flush()
106 policy = autopolicy.AutoPolicy(tmp.name, False, False)
107 try:
108 policy.download_and_execute(['Hello'])
109 assert 0
110 except model.SafeException, ex:
111 assert "library" in str(ex)
112 tmp.close()
114 def testNeedDL(self):
115 self.cache_iface(foo_iface_uri,
116 """<?xml version="1.0" ?>
117 <interface last-modified="0"
118 uri="%s"
119 main='ThisBetterNotExist'
120 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
121 <name>Foo</name>
122 <summary>Foo</summary>
123 <description>Foo</description>
124 <implementation version='1.0' id='sha1=123'>
125 <archive href='http://foo/foo.tgz' size='100'/>
126 </implementation>
127 </interface>""" % foo_iface_uri)
128 policy = autopolicy.AutoPolicy(foo_iface_uri, False, True)
129 policy.freshness = 0
130 policy.network_use = model.network_full
131 policy.recalculate()
132 assert policy.need_download()
133 try:
134 policy.start_downloading_impls()
135 assert False
136 except NeedDownload, ex:
137 pass
139 def testBinding(self):
140 local_impl = os.path.dirname(os.path.abspath(__file__))
141 tmp = tempfile.NamedTemporaryFile()
142 tmp.write(
143 """<?xml version="1.0" ?>
144 <interface
145 main='testautopolicy.py'
146 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
147 <name>Bar</name>
148 <summary>Bar</summary>
149 <description>Bar</description>
150 <group>
151 <requires interface='%s'>
152 <environment name='FOO_PATH' insert='.'/>
153 <environment name='BAR_PATH' insert='.' default='/a:/b'/>
154 <environment name='XDG_DATA_DIRS' insert='.'/>
155 </requires>
156 <environment name='SELF_GROUP' insert='group' mode='replace'/>
157 <implementation version='1.0' id='%s'>
158 <environment name='SELF_IMPL' insert='impl' mode='replace'/>
159 </implementation>
160 </group>
161 </interface>""" % (foo_iface_uri, local_impl))
162 tmp.flush()
163 self.cache_iface(foo_iface_uri,
164 """<?xml version="1.0" ?>
165 <interface last-modified="0"
166 uri="%s"
167 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
168 <name>Foo</name>
169 <summary>Foo</summary>
170 <description>Foo</description>
171 <implementation version='1.0' id='sha1=123'/>
172 </interface>""" % foo_iface_uri)
173 cached_impl = basedir.save_cache_path('0install.net',
174 'implementations',
175 'sha1=123')
176 policy = autopolicy.AutoPolicy(tmp.name, False,
177 dry_run = True)
178 policy.network_use = model.network_offline
179 os.environ['FOO_PATH'] = "old"
180 old, sys.stdout = sys.stdout, StringIO()
181 try:
182 policy.download_and_execute(['Hello'])
183 finally:
184 sys.stdout = old
185 self.assertEquals(cached_impl + '/.:old',
186 os.environ['FOO_PATH'])
187 self.assertEquals(cached_impl + '/.:/a:/b',
188 os.environ['BAR_PATH'])
190 self.assertEquals(os.path.join(local_impl, 'group'), os.environ['SELF_GROUP'])
191 self.assertEquals(os.path.join(local_impl, 'impl'), os.environ['SELF_IMPL'])
193 del os.environ['FOO_PATH']
194 if 'XDG_DATA_DIRS' in os.environ:
195 del os.environ['XDG_DATA_DIRS']
196 os.environ['BAR_PATH'] = '/old'
197 old, sys.stdout = sys.stdout, StringIO()
198 try:
199 policy.download_and_execute(['Hello'])
200 finally:
201 sys.stdout = old
202 self.assertEquals(cached_impl + '/.',
203 os.environ['FOO_PATH'])
204 self.assertEquals(cached_impl + '/.:/old',
205 os.environ['BAR_PATH'])
206 self.assertEquals(cached_impl + '/.:/usr/local/share:/usr/share',
207 os.environ['XDG_DATA_DIRS'])
209 def testFeeds(self):
210 self.cache_iface(foo_iface_uri,
211 """<?xml version="1.0" ?>
212 <interface last-modified="0"
213 uri="%s"
214 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
215 <name>Foo</name>
216 <summary>Foo</summary>
217 <description>Foo</description>
218 <feed src='http://bar'/>
219 </interface>""" % foo_iface_uri)
220 self.cache_iface('http://bar',
221 """<?xml version="1.0" ?>
222 <interface last-modified="0"
223 uri="http://bar"
224 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
225 <feed-for interface='%s'/>
226 <name>Bar</name>
227 <summary>Bar</summary>
228 <description>Bar</description>
229 <implementation version='1.0' id='sha1=123'/>
230 </interface>""" % foo_iface_uri)
231 policy = autopolicy.AutoPolicy(foo_iface_uri, False,
232 dry_run = True)
233 policy.freshness = 0
234 policy.network_use = model.network_full
235 policy.recalculate()
236 assert policy.ready
237 foo_iface = policy.get_interface(foo_iface_uri)
238 self.assertEquals('sha1=123', policy.implementation[foo_iface].id)
240 def testBadConfig(self):
241 path = basedir.save_config_path(namespaces.config_site,
242 namespaces.config_prog)
243 glob = os.path.join(path, 'global')
244 assert not os.path.exists(glob)
245 stream = file(glob, 'w')
246 stream.write('hello!')
247 stream.close()
249 logger.setLevel(logging.ERROR)
250 policy = autopolicy.AutoPolicy(foo_iface_uri,
251 download_only = False)
252 logger.setLevel(logging.WARN)
254 def testRanking(self):
255 self.cache_iface('http://bar',
256 """<?xml version="1.0" ?>
257 <interface last-modified="1110752708"
258 uri="http://bar"
259 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
260 <name>Bar</name>
261 <summary>Bar</summary>
262 <description>Bar</description>
263 <implementation id='sha1=125' version='1.0' arch='odd-weird' stability='buggy'/>
264 <implementation id='sha1=126' version='1.0'/>
265 </interface>""")
266 self.cache_iface(foo_iface_uri,
267 """<?xml version="1.0" ?>
268 <interface last-modified="1110752708"
269 uri="%s"
270 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
271 <name>Foo</name>
272 <summary>Foo</summary>
273 <description>Foo</description>
274 <feed src='http://example.com' arch='odd-unknown'/>
275 <feed src='http://bar'/>
276 <implementation id='sha1=123' version='1.0' arch='odd-strange'/>
277 <implementation id='sha1=124' version='1.0' arch='odd-weird'/>
278 </interface>""" % foo_iface_uri)
279 policy = autopolicy.AutoPolicy(foo_iface_uri,
280 download_only = False)
281 policy.network_use = model.network_full
282 policy.freshness = 0
283 impls = policy.get_ranked_implementations(
284 policy.get_interface(policy.root))
285 assert len(impls) == 4
287 logger.setLevel(logging.ERROR)
288 policy.network_use = model.network_offline # Changes sort order tests
289 policy.recalculate() # Triggers feed-for warning
290 logger.setLevel(logging.WARN)
292 def testNoLocal(self):
293 self.cache_iface(foo_iface_uri,
294 """<?xml version="1.0" ?>
295 <interface last-modified="1110752708"
296 uri="%s"
297 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
298 <name>Foo</name>
299 <summary>Foo</summary>
300 <description>Foo</description>
301 <feed src='/etc/passwd'/>
302 </interface>""" % foo_iface_uri)
303 policy = autopolicy.AutoPolicy(foo_iface_uri,
304 download_only = False)
305 policy.network_use = model.network_offline
306 try:
307 policy.get_interface(foo_iface_uri)
308 assert False
309 except reader.InvalidInterface, ex:
310 assert 'Invalid feed URL' in str(ex)
312 def testDLfeed(self):
313 self.cache_iface(foo_iface_uri,
314 """<?xml version="1.0" ?>
315 <interface last-modified="1110752708"
316 uri="%s"
317 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
318 <name>Foo</name>
319 <summary>Foo</summary>
320 <description>Foo</description>
321 <feed src='http://example.com'/>
322 </interface>""" % foo_iface_uri)
323 policy = autopolicy.AutoPolicy(foo_iface_uri, dry_run = True)
324 policy.network_use = model.network_full
325 policy.freshness = 0
327 try:
328 policy.recalculate()
329 assert False
330 except NeedDownload, ex:
331 pass
333 iface = policy.get_interface(foo_iface_uri)
334 iface._main_feed.feeds = [model.Feed('/BadFeed', None, False)]
336 logger.setLevel(logging.ERROR)
337 policy.recalculate() # Triggers warning
338 logger.setLevel(logging.WARN)
340 def testBestUnusable(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 <implementation id='sha1=123' version='1.0' arch='odd-weird'/>
350 </interface>""" % foo_iface_uri)
351 policy = autopolicy.AutoPolicy(foo_iface_uri,
352 download_only = False)
353 policy.network_use = model.network_offline
354 policy.recalculate()
355 assert not policy.ready
356 try:
357 policy.download_and_execute([])
358 assert False
359 except model.SafeException, ex:
360 assert "Can't find all required implementations" in str(ex)
362 def testNoArchives(self):
363 self.cache_iface(foo_iface_uri,
364 """<?xml version="1.0" ?>
365 <interface last-modified="1110752708"
366 uri="%s"
367 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
368 <name>Foo</name>
369 <summary>Foo</summary>
370 <description>Foo</description>
371 <implementation id='sha1=123' version='1.0'/>
372 </interface>""" % foo_iface_uri)
373 policy = autopolicy.AutoPolicy(foo_iface_uri,
374 download_only = False)
375 policy.freshness = 0
376 policy.recalculate()
377 assert policy.ready
378 try:
379 policy.download_and_execute([])
380 assert False
381 except model.SafeException, ex:
382 assert 'no download locations' in str(ex)
384 def testCycle(self):
385 self.cache_iface(foo_iface_uri,
386 """<?xml version="1.0" ?>
387 <interface last-modified="1110752708"
388 uri="%s"
389 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
390 <name>Foo</name>
391 <summary>Foo</summary>
392 <description>Foo</description>
393 <group>
394 <requires interface='%s'/>
395 <implementation id='sha1=123' version='1.0'/>
396 </group>
397 </interface>""" % (foo_iface_uri, foo_iface_uri))
398 policy = autopolicy.AutoPolicy(foo_iface_uri,
399 download_only = False)
400 policy.freshness = 0
401 policy.recalculate()
403 def testConstraints(self):
404 self.cache_iface('http://bar',
405 """<?xml version="1.0" ?>
406 <interface last-modified="1110752708"
407 uri="http://bar"
408 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
409 <name>Bar</name>
410 <summary>Bar</summary>
411 <description>Bar</description>
412 <implementation id='sha1=100' version='1.0'/>
413 <implementation id='sha1=150' stability='developer' version='1.5'/>
414 <implementation id='sha1=200' version='2.0'/>
415 </interface>""")
416 self.cache_iface(foo_iface_uri,
417 """<?xml version="1.0" ?>
418 <interface last-modified="1110752708"
419 uri="%s"
420 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
421 <name>Foo</name>
422 <summary>Foo</summary>
423 <description>Foo</description>
424 <group>
425 <requires interface='http://bar'>
426 <version/>
427 </requires>
428 <implementation id='sha1=123' version='1.0'/>
429 </group>
430 </interface>""" % foo_iface_uri)
431 policy = autopolicy.AutoPolicy(foo_iface_uri,
432 download_only = False)
433 policy.network_use = model.network_full
434 policy.freshness = 0
435 #logger.setLevel(logging.DEBUG)
436 policy.recalculate()
437 #logger.setLevel(logging.WARN)
438 foo_iface = policy.get_interface(foo_iface_uri)
439 bar_iface = policy.get_interface('http://bar')
440 assert policy.implementation[bar_iface].id == 'sha1=200'
442 dep = policy.implementation[foo_iface].dependencies['http://bar']
443 assert len(dep.restrictions) == 1
444 restriction = dep.restrictions[0]
446 restriction.before = model.parse_version('2.0')
447 policy.recalculate()
448 assert policy.implementation[bar_iface].id == 'sha1=100'
450 restriction.not_before = model.parse_version('1.5')
451 policy.recalculate()
452 assert policy.implementation[bar_iface].id == 'sha1=150'
454 suite = unittest.makeSuite(TestAutoPolicy)
455 if __name__ == '__main__':
456 sys.argv.append('-v')
457 unittest.main()