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