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