Don't do a background check for updates if we're in off-line mode.
[zeroinstall.git] / tests / testautopolicy.py
blob2e8b60393fb839e225256c6df7a1193e488d8ca1
1 #!/usr/bin/env python2.3
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 config_home = tempfile.mktemp()
11 cache_home = tempfile.mktemp()
12 os.environ['XDG_CONFIG_HOME'] = config_home
13 os.environ['XDG_CACHE_HOME'] = cache_home
14 os.environ['XDG_CACHE_DIRS'] = ''
16 from zeroinstall import NeedDownload
17 from zeroinstall.injector import model, basedir, autopolicy, gpg, iface_cache, namespaces, reader
18 import data
19 reload(basedir)
21 foo_iface_uri = 'http://foo'
23 logger = logging.getLogger()
25 class TestAutoPolicy(BaseTest):
26 def setUp(self):
27 BaseTest.setUp(self)
28 stream = tempfile.TemporaryFile()
29 stream.write(data.thomas_key)
30 stream.seek(0)
31 gpg.import_key(stream)
33 def cache_iface(self, name, data):
34 cached_ifaces = basedir.save_cache_path('0install.net',
35 'interfaces')
37 f = file(os.path.join(cached_ifaces, model.escape(name)), 'w')
38 f.write(data)
39 f.close()
41 def testNoNeedDl(self):
42 policy = autopolicy.AutoPolicy(foo_iface_uri,
43 download_only = False)
44 policy.freshness = 0
45 assert policy.need_download()
46 self.cache_iface(foo_iface_uri,
47 """<?xml version="1.0" ?>
48 <interface last-modified="1110752708"
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 </interface>""" % foo_iface_uri)
55 iface_cache.iface_cache._interfaces = {}
56 assert not policy.need_download()
58 def testUnknownAlg(self):
59 self.cache_iface(foo_iface_uri,
60 """<?xml version="1.0" ?>
61 <interface
62 uri="%s"
63 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
64 <name>Foo</name>
65 <summary>Foo</summary>
66 <description>Foo</description>
67 <implementation id='unknown=123' version='1.0'>
68 <archive href='http://foo/foo.tgz' size='100'/>
69 </implementation>
70 </interface>""" % foo_iface_uri)
71 policy = autopolicy.AutoPolicy(foo_iface_uri,
72 download_only = False)
73 policy.freshness = 0
74 try:
75 assert policy.need_download()
76 assert False
77 except model.SafeException, ex:
78 assert 'Unknown digest algorithm' in str(ex)
80 def testDownload(self):
81 tmp = tempfile.NamedTemporaryFile()
82 tmp.write(
83 """<?xml version="1.0" ?>
84 <interface
85 main='ThisBetterNotExist'
86 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
87 <name>Foo</name>
88 <summary>Foo</summary>
89 <description>Foo</description>
90 <implementation version='1.0' id='/bin'/>
91 </interface>""")
92 tmp.flush()
93 policy = autopolicy.AutoPolicy(tmp.name, False, False)
94 try:
95 policy.download_and_execute(['Hello'])
96 assert 0
97 except model.SafeException, ex:
98 assert "ThisBetterNotExist" in str(ex)
99 tmp.close()
101 def testNoMain(self):
102 tmp = tempfile.NamedTemporaryFile()
103 tmp.write(
104 """<?xml version="1.0" ?>
105 <interface
106 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
107 <name>Foo</name>
108 <summary>Foo</summary>
109 <description>Foo</description>
110 <implementation version='1.0' id='/bin'/>
111 </interface>""")
112 tmp.flush()
113 policy = autopolicy.AutoPolicy(tmp.name, False, False)
114 try:
115 policy.download_and_execute(['Hello'])
116 assert 0
117 except model.SafeException, ex:
118 assert "library" in str(ex)
119 tmp.close()
121 def testNeedDL(self):
122 self.cache_iface(foo_iface_uri,
123 """<?xml version="1.0" ?>
124 <interface last-modified="0"
125 uri="%s"
126 main='ThisBetterNotExist'
127 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
128 <name>Foo</name>
129 <summary>Foo</summary>
130 <description>Foo</description>
131 <implementation version='1.0' id='sha1=123'>
132 <archive href='http://foo/foo.tgz' size='100'/>
133 </implementation>
134 </interface>""" % foo_iface_uri)
135 policy = autopolicy.AutoPolicy(foo_iface_uri, False, True)
136 policy.freshness = 0
137 policy.network_use = model.network_full
138 policy.recalculate()
139 assert policy.need_download()
140 try:
141 policy.start_downloading_impls()
142 assert False
143 except NeedDownload, ex:
144 pass
146 def testBinding(self):
147 tmp = tempfile.NamedTemporaryFile()
148 tmp.write(
149 """<?xml version="1.0" ?>
150 <interface
151 main='testautopolicy.py'
152 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
153 <name>Bar</name>
154 <summary>Bar</summary>
155 <description>Bar</description>
156 <group>
157 <requires interface='%s'>
158 <environment name='FOO_PATH' insert='.'/>
159 <environment name='BAR_PATH' insert='.' default='/a:/b'/>
160 <environment name='XDG_DATA_DIRS' insert='.'/>
161 </requires>
162 <implementation version='1.0' id='%s'/>
163 </group>
164 </interface>""" % (foo_iface_uri, os.path.dirname(os.path.abspath(__file__))))
165 tmp.flush()
166 self.cache_iface(foo_iface_uri,
167 """<?xml version="1.0" ?>
168 <interface last-modified="0"
169 uri="%s"
170 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
171 <name>Foo</name>
172 <summary>Foo</summary>
173 <description>Foo</description>
174 <implementation version='1.0' id='sha1=123'/>
175 </interface>""" % foo_iface_uri)
176 cached_impl = basedir.save_cache_path('0install.net',
177 'implementations',
178 'sha1=123')
179 policy = autopolicy.AutoPolicy(tmp.name, False,
180 dry_run = True)
181 policy.network_use = model.network_offline
182 os.environ['FOO_PATH'] = "old"
183 old, sys.stdout = sys.stdout, StringIO()
184 try:
185 policy.download_and_execute(['Hello'])
186 finally:
187 sys.stdout = old
188 self.assertEquals(cached_impl + '/.:old',
189 os.environ['FOO_PATH'])
190 self.assertEquals(cached_impl + '/.:/a:/b',
191 os.environ['BAR_PATH'])
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.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.recalculate()
402 def testConstraints(self):
403 self.cache_iface('http://bar',
404 """<?xml version="1.0" ?>
405 <interface last-modified="1110752708"
406 uri="http://bar"
407 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
408 <name>Bar</name>
409 <summary>Bar</summary>
410 <description>Bar</description>
411 <implementation id='sha1=100' version='1.0'/>
412 <implementation id='sha1=150' stability='developer' version='1.5'/>
413 <implementation id='sha1=200' version='2.0'/>
414 </interface>""")
415 self.cache_iface(foo_iface_uri,
416 """<?xml version="1.0" ?>
417 <interface last-modified="1110752708"
418 uri="%s"
419 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
420 <name>Foo</name>
421 <summary>Foo</summary>
422 <description>Foo</description>
423 <group>
424 <requires interface='http://bar'>
425 <version/>
426 </requires>
427 <implementation id='sha1=123' version='1.0'/>
428 </group>
429 </interface>""" % foo_iface_uri)
430 policy = autopolicy.AutoPolicy(foo_iface_uri,
431 download_only = False)
432 policy.network_use = model.network_full
433 policy.freshness = 0
434 #logger.setLevel(logging.DEBUG)
435 policy.recalculate()
436 #logger.setLevel(logging.WARN)
437 foo_iface = policy.get_interface(foo_iface_uri)
438 bar_iface = policy.get_interface('http://bar')
439 assert policy.implementation[bar_iface].id == 'sha1=200'
441 dep = policy.implementation[foo_iface].dependencies['http://bar']
442 assert len(dep.restrictions) == 1
443 restriction = dep.restrictions[0]
445 restriction.before = model.parse_version('2.0')
446 policy.recalculate()
447 assert policy.implementation[bar_iface].id == 'sha1=100'
449 restriction.not_before = model.parse_version('1.5')
450 policy.recalculate()
451 assert policy.implementation[bar_iface].id == 'sha1=150'
453 suite = unittest.makeSuite(TestAutoPolicy)
454 if __name__ == '__main__':
455 sys.argv.append('-v')
456 unittest.main()