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