Improved UI for versions menu
[zeroinstall/zeroinstall-rsl.git] / tests / testautopolicy.py
blob56d21ce89c9bc9e43ba838c6753f5b28b99ca9e4
1 #!/usr/bin/env python2.5
2 from basetest import BaseTest
3 import sys, tempfile, os, logging
4 from StringIO import StringIO
5 import unittest
7 sys.path.insert(0, '..')
9 from zeroinstall import NeedDownload
10 from zeroinstall.injector import model, autopolicy, gpg, iface_cache, namespaces, reader
11 from zeroinstall.support import basedir
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()
40 policy = autopolicy.AutoPolicy(os.path.abspath('Foo.xml'),
41 download_only = False)
42 assert not policy.need_download()
44 def testUnknownAlg(self):
45 self.cache_iface(foo_iface_uri,
46 """<?xml version="1.0" ?>
47 <interface
48 uri="%s"
49 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
50 <name>Foo</name>
51 <summary>Foo</summary>
52 <description>Foo</description>
53 <implementation id='unknown=123' version='1.0'>
54 <archive href='http://foo/foo.tgz' size='100'/>
55 </implementation>
56 </interface>""" % foo_iface_uri)
57 policy = autopolicy.AutoPolicy(foo_iface_uri,
58 download_only = False)
59 policy.freshness = 0
60 try:
61 assert policy.need_download()
62 policy.execute([])
63 except model.SafeException, ex:
64 assert 'Unknown digest algorithm' in str(ex)
66 def testDownload(self):
67 tmp = tempfile.NamedTemporaryFile()
68 tmp.write(
69 """<?xml version="1.0" ?>
70 <interface
71 main='ThisBetterNotExist'
72 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
73 <name>Foo</name>
74 <summary>Foo</summary>
75 <description>Foo</description>
76 <implementation version='1.0' id='/bin'/>
77 </interface>""")
78 tmp.flush()
79 policy = autopolicy.AutoPolicy(tmp.name, False, False)
80 try:
81 policy.download_and_execute(['Hello'])
82 assert 0
83 except model.SafeException, ex:
84 assert "ThisBetterNotExist" in str(ex)
85 tmp.close()
87 def testNoMain(self):
88 tmp = tempfile.NamedTemporaryFile()
89 tmp.write(
90 """<?xml version="1.0" ?>
91 <interface
92 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
93 <name>Foo</name>
94 <summary>Foo</summary>
95 <description>Foo</description>
96 <implementation version='1.0' id='/bin'/>
97 </interface>""")
98 tmp.flush()
99 policy = autopolicy.AutoPolicy(tmp.name, False, False)
100 try:
101 policy.download_and_execute(['Hello'])
102 assert 0
103 except model.SafeException, ex:
104 assert "library" in str(ex)
105 tmp.close()
107 def testNeedDL(self):
108 self.cache_iface(foo_iface_uri,
109 """<?xml version="1.0" ?>
110 <interface last-modified="0"
111 uri="%s"
112 main='ThisBetterNotExist'
113 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
114 <name>Foo</name>
115 <summary>Foo</summary>
116 <description>Foo</description>
117 <implementation version='1.0' id='sha1=123'>
118 <archive href='http://foo/foo.tgz' size='100'/>
119 </implementation>
120 </interface>""" % foo_iface_uri)
121 policy = autopolicy.AutoPolicy(foo_iface_uri, False, True)
122 policy.freshness = 0
123 policy.network_use = model.network_full
124 policy.recalculate()
125 assert policy.need_download()
126 assert policy.ready
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 policy.download_only = True
204 policy.download_and_execute(['Hello'])
206 def testFeeds(self):
207 self.cache_iface(foo_iface_uri,
208 """<?xml version="1.0" ?>
209 <interface last-modified="0"
210 uri="%s"
211 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
212 <name>Foo</name>
213 <summary>Foo</summary>
214 <description>Foo</description>
215 <feed src='http://bar'/>
216 </interface>""" % foo_iface_uri)
217 self.cache_iface('http://bar',
218 """<?xml version="1.0" ?>
219 <interface last-modified="0"
220 uri="http://bar"
221 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
222 <feed-for interface='%s'/>
223 <name>Bar</name>
224 <summary>Bar</summary>
225 <description>Bar</description>
226 <implementation version='1.0' id='sha1=123'/>
227 </interface>""" % foo_iface_uri)
228 policy = autopolicy.AutoPolicy(foo_iface_uri, False,
229 dry_run = True)
230 policy.freshness = 0
231 policy.network_use = model.network_full
232 policy.recalculate()
233 assert policy.ready
234 foo_iface = iface_cache.iface_cache.get_interface(foo_iface_uri)
235 self.assertEquals('sha1=123', policy.implementation[foo_iface].id)
237 def testBadConfig(self):
238 path = basedir.save_config_path(namespaces.config_site,
239 namespaces.config_prog)
240 glob = os.path.join(path, 'global')
241 assert not os.path.exists(glob)
242 stream = file(glob, 'w')
243 stream.write('hello!')
244 stream.close()
246 logger.setLevel(logging.ERROR)
247 policy = autopolicy.AutoPolicy(foo_iface_uri,
248 download_only = False)
249 logger.setLevel(logging.WARN)
251 def testNoLocal(self):
252 self.cache_iface(foo_iface_uri,
253 """<?xml version="1.0" ?>
254 <interface last-modified="1110752708"
255 uri="%s"
256 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
257 <name>Foo</name>
258 <summary>Foo</summary>
259 <description>Foo</description>
260 <feed src='/etc/passwd'/>
261 </interface>""" % foo_iface_uri)
262 policy = autopolicy.AutoPolicy(foo_iface_uri,
263 download_only = False)
264 policy.network_use = model.network_offline
265 try:
266 iface_cache.iface_cache.get_interface(foo_iface_uri)
267 assert False
268 except reader.InvalidInterface, ex:
269 assert 'Invalid feed URL' in str(ex)
271 def testDLfeed(self):
272 self.cache_iface(foo_iface_uri,
273 """<?xml version="1.0" ?>
274 <interface last-modified="1110752708"
275 uri="%s"
276 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
277 <name>Foo</name>
278 <summary>Foo</summary>
279 <description>Foo</description>
280 <feed src='http://example.com'/>
281 </interface>""" % foo_iface_uri)
282 policy = autopolicy.AutoPolicy(foo_iface_uri, dry_run = True)
283 policy.network_use = model.network_full
284 policy.freshness = 0
286 try:
287 policy.recalculate()
288 assert False
289 except NeedDownload, ex:
290 pass
292 iface = iface_cache.iface_cache.get_interface(foo_iface_uri)
293 iface._main_feed.feeds = [model.Feed('/BadFeed', None, False)]
295 logger.setLevel(logging.ERROR)
296 policy.recalculate() # Triggers warning
297 logger.setLevel(logging.WARN)
299 def testBestUnusable(self):
300 self.cache_iface(foo_iface_uri,
301 """<?xml version="1.0" ?>
302 <interface last-modified="1110752708"
303 uri="%s"
304 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
305 <name>Foo</name>
306 <summary>Foo</summary>
307 <description>Foo</description>
308 <implementation id='sha1=123' version='1.0' arch='odd-weird'/>
309 </interface>""" % foo_iface_uri)
310 policy = autopolicy.AutoPolicy(foo_iface_uri,
311 download_only = False)
312 policy.network_use = model.network_offline
313 policy.recalculate()
314 assert not policy.ready, policy.implementation
315 try:
316 policy.download_and_execute([])
317 assert False
318 except model.SafeException, ex:
319 assert "Can't find all required implementations" in str(ex)
321 def testNoArchives(self):
322 self.cache_iface(foo_iface_uri,
323 """<?xml version="1.0" ?>
324 <interface last-modified="1110752708"
325 uri="%s"
326 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
327 <name>Foo</name>
328 <summary>Foo</summary>
329 <description>Foo</description>
330 <implementation id='sha1=123' version='1.0'/>
331 </interface>""" % foo_iface_uri)
332 policy = autopolicy.AutoPolicy(foo_iface_uri,
333 download_only = False)
334 policy.freshness = 0
335 policy.recalculate()
336 assert policy.ready
337 try:
338 policy.download_and_execute([])
339 assert False
340 except model.SafeException, ex:
341 assert 'no download locations' in str(ex), ex
343 def testCycle(self):
344 self.cache_iface(foo_iface_uri,
345 """<?xml version="1.0" ?>
346 <interface last-modified="1110752708"
347 uri="%s"
348 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
349 <name>Foo</name>
350 <summary>Foo</summary>
351 <description>Foo</description>
352 <group>
353 <requires interface='%s'/>
354 <implementation id='sha1=123' version='1.0'/>
355 </group>
356 </interface>""" % (foo_iface_uri, foo_iface_uri))
357 policy = autopolicy.AutoPolicy(foo_iface_uri,
358 download_only = False)
359 policy.freshness = 0
360 policy.recalculate()
362 def testConstraints(self):
363 self.cache_iface('http://bar',
364 """<?xml version="1.0" ?>
365 <interface last-modified="1110752708"
366 uri="http://bar"
367 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
368 <name>Bar</name>
369 <summary>Bar</summary>
370 <description>Bar</description>
371 <implementation id='sha1=100' version='1.0'/>
372 <implementation id='sha1=150' stability='developer' version='1.5'/>
373 <implementation id='sha1=200' version='2.0'/>
374 </interface>""")
375 self.cache_iface(foo_iface_uri,
376 """<?xml version="1.0" ?>
377 <interface last-modified="1110752708"
378 uri="%s"
379 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
380 <name>Foo</name>
381 <summary>Foo</summary>
382 <description>Foo</description>
383 <group>
384 <requires interface='http://bar'>
385 <version/>
386 </requires>
387 <implementation id='sha1=123' version='1.0'/>
388 </group>
389 </interface>""" % foo_iface_uri)
390 policy = autopolicy.AutoPolicy(foo_iface_uri,
391 download_only = False)
392 policy.network_use = model.network_full
393 policy.freshness = 0
394 #logger.setLevel(logging.DEBUG)
395 policy.recalculate()
396 #logger.setLevel(logging.WARN)
397 foo_iface = iface_cache.iface_cache.get_interface(foo_iface_uri)
398 bar_iface = iface_cache.iface_cache.get_interface('http://bar')
399 assert policy.implementation[bar_iface].id == 'sha1=200'
401 dep = policy.implementation[foo_iface].dependencies['http://bar']
402 assert len(dep.restrictions) == 1
403 restriction = dep.restrictions[0]
405 restriction.before = model.parse_version('2.0')
406 policy.recalculate()
407 assert policy.implementation[bar_iface].id == 'sha1=100'
409 restriction.not_before = model.parse_version('1.5')
410 policy.recalculate()
411 assert policy.implementation[bar_iface].id == 'sha1=150'
413 suite = unittest.makeSuite(TestAutoPolicy)
414 if __name__ == '__main__':
415 sys.argv.append('-v')
416 unittest.main()