Replaced get_ranked_selections with record_details on Solver.
[zeroinstall.git] / tests / testautopolicy.py
blob269bae4de1abbc7e814c7c5280fbff424c7139a6
1 #!/usr/bin/env python2.4
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 from zeroinstall import NeedDownload
11 from zeroinstall.injector import model, basedir, autopolicy, gpg, iface_cache, namespaces, reader
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()
39 self.cache_iface(foo_iface_uri,
40 """<?xml version="1.0" ?>
41 <interface last-modified="1110752708"
42 uri="%s"
43 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
44 <name>Foo</name>
45 <summary>Foo</summary>
46 <description>Foo</description>
47 </interface>""" % foo_iface_uri)
48 iface_cache.iface_cache._interfaces = {}
49 assert not policy.need_download()
51 def testUnknownAlg(self):
52 self.cache_iface(foo_iface_uri,
53 """<?xml version="1.0" ?>
54 <interface
55 uri="%s"
56 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
57 <name>Foo</name>
58 <summary>Foo</summary>
59 <description>Foo</description>
60 <implementation id='unknown=123' version='1.0'>
61 <archive href='http://foo/foo.tgz' size='100'/>
62 </implementation>
63 </interface>""" % foo_iface_uri)
64 policy = autopolicy.AutoPolicy(foo_iface_uri,
65 download_only = False)
66 policy.freshness = 0
67 try:
68 assert policy.need_download()
69 assert False
70 except model.SafeException, ex:
71 assert 'Unknown digest algorithm' in str(ex)
73 def testDownload(self):
74 tmp = tempfile.NamedTemporaryFile()
75 tmp.write(
76 """<?xml version="1.0" ?>
77 <interface
78 main='ThisBetterNotExist'
79 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
80 <name>Foo</name>
81 <summary>Foo</summary>
82 <description>Foo</description>
83 <implementation version='1.0' id='/bin'/>
84 </interface>""")
85 tmp.flush()
86 policy = autopolicy.AutoPolicy(tmp.name, False, False)
87 try:
88 policy.download_and_execute(['Hello'])
89 assert 0
90 except model.SafeException, ex:
91 assert "ThisBetterNotExist" in str(ex)
92 tmp.close()
94 def testNoMain(self):
95 tmp = tempfile.NamedTemporaryFile()
96 tmp.write(
97 """<?xml version="1.0" ?>
98 <interface
99 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
100 <name>Foo</name>
101 <summary>Foo</summary>
102 <description>Foo</description>
103 <implementation version='1.0' id='/bin'/>
104 </interface>""")
105 tmp.flush()
106 policy = autopolicy.AutoPolicy(tmp.name, False, False)
107 try:
108 policy.download_and_execute(['Hello'])
109 assert 0
110 except model.SafeException, ex:
111 assert "library" in str(ex)
112 tmp.close()
114 def testNeedDL(self):
115 self.cache_iface(foo_iface_uri,
116 """<?xml version="1.0" ?>
117 <interface last-modified="0"
118 uri="%s"
119 main='ThisBetterNotExist'
120 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
121 <name>Foo</name>
122 <summary>Foo</summary>
123 <description>Foo</description>
124 <implementation version='1.0' id='sha1=123'>
125 <archive href='http://foo/foo.tgz' size='100'/>
126 </implementation>
127 </interface>""" % foo_iface_uri)
128 policy = autopolicy.AutoPolicy(foo_iface_uri, False, True)
129 policy.freshness = 0
130 policy.network_use = model.network_full
131 policy.recalculate()
132 assert policy.need_download()
133 try:
134 policy.start_downloading_impls()
135 assert False
136 except NeedDownload, ex:
137 pass
139 def testBinding(self):
140 local_impl = os.path.dirname(os.path.abspath(__file__))
141 tmp = tempfile.NamedTemporaryFile()
142 tmp.write(
143 """<?xml version="1.0" ?>
144 <interface
145 main='testautopolicy.py'
146 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
147 <name>Bar</name>
148 <summary>Bar</summary>
149 <description>Bar</description>
150 <group>
151 <requires interface='%s'>
152 <environment name='FOO_PATH' insert='.'/>
153 <environment name='BAR_PATH' insert='.' default='/a:/b'/>
154 <environment name='XDG_DATA_DIRS' insert='.'/>
155 </requires>
156 <environment name='SELF_GROUP' insert='group' mode='replace'/>
157 <implementation version='1.0' id='%s'>
158 <environment name='SELF_IMPL' insert='impl' mode='replace'/>
159 </implementation>
160 </group>
161 </interface>""" % (foo_iface_uri, local_impl))
162 tmp.flush()
163 self.cache_iface(foo_iface_uri,
164 """<?xml version="1.0" ?>
165 <interface last-modified="0"
166 uri="%s"
167 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
168 <name>Foo</name>
169 <summary>Foo</summary>
170 <description>Foo</description>
171 <implementation version='1.0' id='sha1=123'/>
172 </interface>""" % foo_iface_uri)
173 cached_impl = basedir.save_cache_path('0install.net',
174 'implementations',
175 'sha1=123')
176 policy = autopolicy.AutoPolicy(tmp.name, False,
177 dry_run = True)
178 policy.network_use = model.network_offline
179 os.environ['FOO_PATH'] = "old"
180 old, sys.stdout = sys.stdout, StringIO()
181 try:
182 policy.download_and_execute(['Hello'])
183 finally:
184 sys.stdout = old
185 self.assertEquals(cached_impl + '/.:old',
186 os.environ['FOO_PATH'])
187 self.assertEquals(cached_impl + '/.:/a:/b',
188 os.environ['BAR_PATH'])
190 self.assertEquals(os.path.join(local_impl, 'group'), os.environ['SELF_GROUP'])
191 self.assertEquals(os.path.join(local_impl, 'impl'), os.environ['SELF_IMPL'])
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 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 policy.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 iface = policy.get_interface(foo_iface_uri)
296 iface._main_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 policy.ready
340 try:
341 policy.download_and_execute([])
342 assert False
343 except model.SafeException, ex:
344 assert 'no download locations' in str(ex)
346 def testCycle(self):
347 self.cache_iface(foo_iface_uri,
348 """<?xml version="1.0" ?>
349 <interface last-modified="1110752708"
350 uri="%s"
351 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
352 <name>Foo</name>
353 <summary>Foo</summary>
354 <description>Foo</description>
355 <group>
356 <requires interface='%s'/>
357 <implementation id='sha1=123' version='1.0'/>
358 </group>
359 </interface>""" % (foo_iface_uri, foo_iface_uri))
360 policy = autopolicy.AutoPolicy(foo_iface_uri,
361 download_only = False)
362 policy.freshness = 0
363 policy.recalculate()
365 def testConstraints(self):
366 self.cache_iface('http://bar',
367 """<?xml version="1.0" ?>
368 <interface last-modified="1110752708"
369 uri="http://bar"
370 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
371 <name>Bar</name>
372 <summary>Bar</summary>
373 <description>Bar</description>
374 <implementation id='sha1=100' version='1.0'/>
375 <implementation id='sha1=150' stability='developer' version='1.5'/>
376 <implementation id='sha1=200' version='2.0'/>
377 </interface>""")
378 self.cache_iface(foo_iface_uri,
379 """<?xml version="1.0" ?>
380 <interface last-modified="1110752708"
381 uri="%s"
382 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
383 <name>Foo</name>
384 <summary>Foo</summary>
385 <description>Foo</description>
386 <group>
387 <requires interface='http://bar'>
388 <version/>
389 </requires>
390 <implementation id='sha1=123' version='1.0'/>
391 </group>
392 </interface>""" % foo_iface_uri)
393 policy = autopolicy.AutoPolicy(foo_iface_uri,
394 download_only = False)
395 policy.network_use = model.network_full
396 policy.freshness = 0
397 #logger.setLevel(logging.DEBUG)
398 policy.recalculate()
399 #logger.setLevel(logging.WARN)
400 foo_iface = policy.get_interface(foo_iface_uri)
401 bar_iface = policy.get_interface('http://bar')
402 assert policy.implementation[bar_iface].id == 'sha1=200'
404 dep = policy.implementation[foo_iface].dependencies['http://bar']
405 assert len(dep.restrictions) == 1
406 restriction = dep.restrictions[0]
408 restriction.before = model.parse_version('2.0')
409 policy.recalculate()
410 assert policy.implementation[bar_iface].id == 'sha1=100'
412 restriction.not_before = model.parse_version('1.5')
413 policy.recalculate()
414 assert policy.implementation[bar_iface].id == 'sha1=150'
416 suite = unittest.makeSuite(TestAutoPolicy)
417 if __name__ == '__main__':
418 sys.argv.append('-v')
419 unittest.main()