API changes: use Feed rather than Interface in many places
[zeroinstall/zeroinstall-afb.git] / tests / testautopolicy.py
bloba41fc2c9965c3579bb0f8defa77caf4170512c27
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
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()
43 assert policy.ready
45 def testUnknownAlg(self):
46 self.cache_iface(foo_iface_uri,
47 """<?xml version="1.0" ?>
48 <interface
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 <implementation id='unknown=123' version='1.0'>
55 <archive href='http://foo/foo.tgz' size='100'/>
56 </implementation>
57 </interface>""" % foo_iface_uri)
58 policy = autopolicy.AutoPolicy(foo_iface_uri,
59 download_only = False)
60 policy.freshness = 0
61 try:
62 assert policy.need_download()
63 policy.execute([])
64 except model.SafeException, ex:
65 assert 'Unknown digest algorithm' in str(ex)
67 def testDownload(self):
68 tmp = tempfile.NamedTemporaryFile()
69 tmp.write(
70 """<?xml version="1.0" ?>
71 <interface
72 main='ThisBetterNotExist'
73 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
74 <name>Foo</name>
75 <summary>Foo</summary>
76 <description>Foo</description>
77 <implementation version='1.0' id='/bin'/>
78 </interface>""")
79 tmp.flush()
80 policy = autopolicy.AutoPolicy(tmp.name, False, False)
81 try:
82 policy.download_and_execute(['Hello'])
83 assert 0
84 except model.SafeException, ex:
85 assert "ThisBetterNotExist" in str(ex)
86 tmp.close()
88 def testNoMain(self):
89 tmp = tempfile.NamedTemporaryFile()
90 tmp.write(
91 """<?xml version="1.0" ?>
92 <interface
93 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
94 <name>Foo</name>
95 <summary>Foo</summary>
96 <description>Foo</description>
97 <implementation version='1.0' id='/bin'/>
98 </interface>""")
99 tmp.flush()
100 policy = autopolicy.AutoPolicy(tmp.name, False, False)
101 try:
102 policy.download_and_execute(['Hello'])
103 assert 0
104 except model.SafeException, ex:
105 assert "library" in str(ex)
106 tmp.close()
108 def testNeedDL(self):
109 self.cache_iface(foo_iface_uri,
110 """<?xml version="1.0" ?>
111 <interface last-modified="0"
112 uri="%s"
113 main='ThisBetterNotExist'
114 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
115 <name>Foo</name>
116 <summary>Foo</summary>
117 <description>Foo</description>
118 <implementation version='1.0' id='sha1=123'>
119 <archive href='http://foo/foo.tgz' size='100'/>
120 </implementation>
121 </interface>""" % foo_iface_uri)
122 policy = autopolicy.AutoPolicy(foo_iface_uri, False, True)
123 policy.freshness = 0
124 policy.network_use = model.network_full
125 policy.recalculate()
126 assert policy.need_download()
127 assert policy.ready
128 try:
129 policy.execute([], main = 'NOTHING')
130 assert False
131 except NeedDownload, ex:
132 pass
134 def testBinding(self):
135 local_impl = os.path.dirname(os.path.abspath(__file__))
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 <environment name='SELF_GROUP' insert='group' mode='replace'/>
152 <implementation version='1.0' id='%s'>
153 <environment name='SELF_IMPL' insert='impl' mode='replace'/>
154 </implementation>
155 </group>
156 </interface>""" % (foo_iface_uri, local_impl))
157 tmp.flush()
158 self.cache_iface(foo_iface_uri,
159 """<?xml version="1.0" ?>
160 <interface last-modified="0"
161 uri="%s"
162 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
163 <name>Foo</name>
164 <summary>Foo</summary>
165 <description>Foo</description>
166 <implementation version='1.0' id='sha1=123'/>
167 </interface>""" % foo_iface_uri)
168 cached_impl = basedir.save_cache_path('0install.net',
169 'implementations',
170 'sha1=123')
171 policy = autopolicy.AutoPolicy(tmp.name, False,
172 dry_run = True)
173 policy.network_use = model.network_offline
174 os.environ['FOO_PATH'] = "old"
175 old, sys.stdout = sys.stdout, StringIO()
176 try:
177 policy.download_and_execute(['Hello'])
178 finally:
179 sys.stdout = old
180 self.assertEquals(cached_impl + '/.:old',
181 os.environ['FOO_PATH'])
182 self.assertEquals(cached_impl + '/.:/a:/b',
183 os.environ['BAR_PATH'])
185 self.assertEquals(os.path.join(local_impl, 'group'), os.environ['SELF_GROUP'])
186 self.assertEquals(os.path.join(local_impl, 'impl'), os.environ['SELF_IMPL'])
188 del os.environ['FOO_PATH']
189 if 'XDG_DATA_DIRS' in os.environ:
190 del os.environ['XDG_DATA_DIRS']
191 os.environ['BAR_PATH'] = '/old'
192 old, sys.stdout = sys.stdout, StringIO()
193 try:
194 policy.download_and_execute(['Hello'])
195 finally:
196 sys.stdout = old
197 self.assertEquals(cached_impl + '/.',
198 os.environ['FOO_PATH'])
199 self.assertEquals(cached_impl + '/.:/old',
200 os.environ['BAR_PATH'])
201 self.assertEquals(cached_impl + '/.:/usr/local/share:/usr/share',
202 os.environ['XDG_DATA_DIRS'])
204 policy.download_only = True
205 policy.download_and_execute(['Hello'])
207 def testFeeds(self):
208 self.cache_iface(foo_iface_uri,
209 """<?xml version="1.0" ?>
210 <interface last-modified="0"
211 uri="%s"
212 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
213 <name>Foo</name>
214 <summary>Foo</summary>
215 <description>Foo</description>
216 <feed src='http://bar'/>
217 </interface>""" % foo_iface_uri)
218 self.cache_iface('http://bar',
219 """<?xml version="1.0" ?>
220 <interface last-modified="0"
221 uri="http://bar"
222 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
223 <feed-for interface='%s'/>
224 <name>Bar</name>
225 <summary>Bar</summary>
226 <description>Bar</description>
227 <implementation version='1.0' id='sha1=123'>
228 <archive href='foo' size='10'/>
229 </implementation>
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 = iface_cache.iface_cache.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 testNoLocal(self):
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='/etc/passwd'/>
264 </interface>""" % foo_iface_uri)
265 policy = autopolicy.AutoPolicy(foo_iface_uri,
266 download_only = False)
267 policy.network_use = model.network_offline
268 try:
269 iface_cache.iface_cache.get_interface(foo_iface_uri)
270 assert False
271 except reader.InvalidInterface, ex:
272 assert 'Invalid feed URL' in str(ex)
274 def testDLfeed(self):
275 self.cache_iface(foo_iface_uri,
276 """<?xml version="1.0" ?>
277 <interface last-modified="1110752708"
278 uri="%s"
279 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
280 <name>Foo</name>
281 <summary>Foo</summary>
282 <description>Foo</description>
283 <feed src='http://example.com'/>
284 </interface>""" % foo_iface_uri)
285 policy = autopolicy.AutoPolicy(foo_iface_uri, dry_run = True)
286 policy.network_use = model.network_full
287 policy.freshness = 0
289 try:
290 policy.recalculate()
291 assert False
292 except NeedDownload, ex:
293 pass
295 feed = iface_cache.iface_cache.get_feed(foo_iface_uri)
296 feed.feeds = [model.Feed('/BadFeed', None, False)]
298 logger.setLevel(logging.ERROR)
299 policy.recalculate() # Triggers warning
300 logger.setLevel(logging.WARN)
302 def testBestUnusable(self):
303 self.cache_iface(foo_iface_uri,
304 """<?xml version="1.0" ?>
305 <interface last-modified="1110752708"
306 uri="%s"
307 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
308 <name>Foo</name>
309 <summary>Foo</summary>
310 <description>Foo</description>
311 <implementation id='sha1=123' version='1.0' arch='odd-weird'/>
312 </interface>""" % foo_iface_uri)
313 policy = autopolicy.AutoPolicy(foo_iface_uri,
314 download_only = False)
315 policy.network_use = model.network_offline
316 policy.recalculate()
317 assert not policy.ready, policy.implementation
318 try:
319 policy.download_and_execute([])
320 assert False
321 except model.SafeException, ex:
322 assert "Can't find all required implementations" in str(ex)
324 def testNoArchives(self):
325 self.cache_iface(foo_iface_uri,
326 """<?xml version="1.0" ?>
327 <interface last-modified="1110752708"
328 uri="%s"
329 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
330 <name>Foo</name>
331 <summary>Foo</summary>
332 <description>Foo</description>
333 <implementation id='sha1=123' version='1.0'/>
334 </interface>""" % foo_iface_uri)
335 policy = autopolicy.AutoPolicy(foo_iface_uri,
336 download_only = False)
337 policy.freshness = 0
338 policy.recalculate()
339 assert not policy.ready
341 def testCycle(self):
342 self.cache_iface(foo_iface_uri,
343 """<?xml version="1.0" ?>
344 <interface last-modified="1110752708"
345 uri="%s"
346 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
347 <name>Foo</name>
348 <summary>Foo</summary>
349 <description>Foo</description>
350 <group>
351 <requires interface='%s'/>
352 <implementation id='sha1=123' version='1.0'>
353 <archive href='foo' size='10'/>
354 </implementation>
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 <archive href='foo' size='10'/>
373 </implementation>
374 <implementation id='sha1=150' stability='developer' version='1.5'>
375 <archive href='foo' size='10'/>
376 </implementation>
377 <implementation id='sha1=200' version='2.0'>
378 <archive href='foo' size='10'/>
379 </implementation>
380 </interface>""")
381 self.cache_iface(foo_iface_uri,
382 """<?xml version="1.0" ?>
383 <interface last-modified="1110752708"
384 uri="%s"
385 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
386 <name>Foo</name>
387 <summary>Foo</summary>
388 <description>Foo</description>
389 <group>
390 <requires interface='http://bar'>
391 <version/>
392 </requires>
393 <implementation id='sha1=123' version='1.0'>
394 <archive href='foo' size='10'/>
395 </implementation>
396 </group>
397 </interface>""" % foo_iface_uri)
398 policy = autopolicy.AutoPolicy(foo_iface_uri,
399 download_only = False)
400 policy.network_use = model.network_full
401 policy.freshness = 0
402 #logger.setLevel(logging.DEBUG)
403 policy.recalculate()
404 #logger.setLevel(logging.WARN)
405 foo_iface = iface_cache.iface_cache.get_interface(foo_iface_uri)
406 bar_iface = iface_cache.iface_cache.get_interface('http://bar')
407 assert policy.implementation[bar_iface].id == 'sha1=200'
409 dep = policy.implementation[foo_iface].dependencies['http://bar']
410 assert len(dep.restrictions) == 1
411 restriction = dep.restrictions[0]
413 restriction.before = model.parse_version('2.0')
414 policy.recalculate()
415 assert policy.implementation[bar_iface].id == 'sha1=100'
417 restriction.not_before = model.parse_version('1.5')
418 policy.recalculate()
419 assert policy.implementation[bar_iface].id == 'sha1=150'
421 if __name__ == '__main__':
422 unittest.main()