2 from basetest
import BaseTest
3 import sys
, tempfile
, os
, logging
4 from StringIO
import StringIO
7 sys
.path
.insert(0, '..')
9 from zeroinstall
.injector
import model
, gpg
, namespaces
, reader
, run
, fetch
10 from zeroinstall
.injector
.policy
import Policy
11 from zeroinstall
.support
import basedir
14 foo_iface_uri
= 'http://foo'
16 logger
= logging
.getLogger()
18 def recalculate(policy
):
19 policy
.need_download()
21 def download_and_execute(policy
, prog_args
, main
= None, dry_run
= True):
22 downloaded
= policy
.solve_and_download_impls()
24 policy
.config
.handler
.wait_for_blocker(downloaded
)
25 run
.execute_selections(policy
.solver
.selections
, prog_args
, stores
= policy
.config
.stores
, main
= main
, dry_run
= dry_run
)
27 class TestAutoPolicy(BaseTest
):
30 stream
= tempfile
.TemporaryFile()
31 stream
.write(data
.thomas_key
)
33 gpg
.import_key(stream
)
35 def cache_iface(self
, name
, data
):
36 cached_ifaces
= basedir
.save_cache_path('0install.net',
39 f
= open(os
.path
.join(cached_ifaces
, model
.escape(name
)), 'w')
43 def testNoNeedDl(self
):
44 policy
= Policy(foo_iface_uri
, config
= self
.config
)
46 assert policy
.need_download()
48 policy
= Policy(os
.path
.abspath('Foo.xml'), config
= self
.config
)
49 assert not policy
.need_download()
52 def testUnknownAlg(self
):
53 self
.cache_iface(foo_iface_uri
,
54 """<?xml version="1.0" ?>
57 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
59 <summary>Foo</summary>
60 <description>Foo</description>
61 <implementation main='.' id='unknown=123' version='1.0'>
62 <archive href='http://foo/foo.tgz' size='100'/>
64 </interface>""" % foo_iface_uri
)
65 self
.config
.fetcher
= fetch
.Fetcher(self
.config
)
66 policy
= Policy(foo_iface_uri
, config
= self
.config
)
69 assert policy
.need_download()
70 download_and_execute(policy
, [])
71 except model
.SafeException
as ex
:
72 assert 'Unknown digest algorithm' in str(ex
)
74 def testDownload(self
):
75 tmp
= tempfile
.NamedTemporaryFile()
77 """<?xml version="1.0" ?>
79 main='ThisBetterNotExist'
80 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
82 <summary>Foo</summary>
83 <description>Foo</description>
84 <implementation version='1.0' id='/bin'/>
87 policy
= Policy(tmp
.name
, config
= self
.config
)
89 download_and_execute(policy
, ['Hello'])
91 except model
.SafeException
as ex
:
92 assert "ThisBetterNotExist" in str(ex
)
96 tmp
= tempfile
.NamedTemporaryFile()
98 """<?xml version="1.0" ?>
100 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
102 <summary>Foo</summary>
103 <description>Foo</description>
104 <implementation version='1.0' id='/bin'/>
107 policy
= Policy(tmp
.name
, config
= self
.config
)
109 download_and_execute(policy
, ['Hello'])
111 except model
.SafeException
as ex
:
112 assert "library" in str(ex
), ex
115 def testNeedDL(self
):
116 self
.cache_iface(foo_iface_uri
,
117 """<?xml version="1.0" ?>
118 <interface last-modified="0"
120 main='ThisBetterNotExist'
121 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
123 <summary>Foo</summary>
124 <description>Foo</description>
125 <implementation version='1.0' id='sha1=123'>
126 <archive href='http://foo/foo.tgz' size='100'/>
128 </interface>""" % foo_iface_uri
)
129 policy
= Policy(foo_iface_uri
, config
= self
.config
)
131 policy
.network_use
= model
.network_full
133 assert policy
.need_download()
136 def testBinding(self
):
137 local_impl
= os
.path
.dirname(os
.path
.abspath(__file__
))
138 tmp
= tempfile
.NamedTemporaryFile()
140 """<?xml version="1.0" ?>
142 main='testautopolicy.py'
143 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
145 <summary>Bar</summary>
146 <description>Bar</description>
148 <requires interface='%s'>
149 <environment name='FOO_PATH' insert='.'/>
150 <environment name='BAR_PATH' insert='.' default='/a:/b'/>
151 <environment name='NO_PATH' value='val'/>
152 <environment name='XDG_DATA_DIRS' insert='.'/>
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'/>
159 </interface>""" % (foo_iface_uri
, local_impl
))
161 self
.cache_iface(foo_iface_uri
,
162 """<?xml version="1.0" ?>
163 <interface last-modified="0"
165 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
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',
174 policy
= Policy(tmp
.name
, config
= self
.config
)
175 policy
.network_use
= model
.network_offline
176 os
.environ
['FOO_PATH'] = "old"
177 old
, sys
.stdout
= sys
.stdout
, StringIO()
179 download_and_execute(policy
, ['Hello'])
182 self
.assertEqual(cached_impl
+ '/.:old',
183 os
.environ
['FOO_PATH'])
184 self
.assertEqual(cached_impl
+ '/.:/a:/b',
185 os
.environ
['BAR_PATH'])
186 self
.assertEqual('val', os
.environ
['NO_PATH'])
188 self
.assertEqual(os
.path
.join(local_impl
, 'group'), os
.environ
['SELF_GROUP'])
189 self
.assertEqual(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()
197 download_and_execute(policy
, ['Hello'])
200 self
.assertEqual(cached_impl
+ '/.',
201 os
.environ
['FOO_PATH'])
202 self
.assertEqual(cached_impl
+ '/.:/old',
203 os
.environ
['BAR_PATH'])
204 self
.assertEqual(cached_impl
+ '/.:/usr/local/share:/usr/share',
205 os
.environ
['XDG_DATA_DIRS'])
208 self
.cache_iface(foo_iface_uri
,
209 """<?xml version="1.0" ?>
210 <interface last-modified="0"
212 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
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"
222 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
223 <feed-for interface='%s'/>
225 <summary>Bar</summary>
226 <description>Bar</description>
227 <implementation version='1.0' id='sha1=123' main='dummy'>
228 <archive href='foo' size='10'/>
230 </interface>""" % foo_iface_uri
)
231 policy
= Policy(foo_iface_uri
, config
= self
.config
)
233 policy
.network_use
= model
.network_full
236 foo_iface
= self
.config
.iface_cache
.get_interface(foo_iface_uri
)
237 self
.assertEqual('sha1=123', policy
.implementation
[foo_iface
].id)
239 def testBadConfig(self
):
240 path
= basedir
.save_config_path(namespaces
.config_site
,
241 namespaces
.config_prog
)
242 glob
= os
.path
.join(path
, 'global')
243 assert not os
.path
.exists(glob
)
244 stream
= open(glob
, 'w')
245 stream
.write('hello!')
248 logger
.setLevel(logging
.ERROR
)
249 Policy(foo_iface_uri
, config
= self
.config
)
250 logger
.setLevel(logging
.WARN
)
252 def testNoLocal(self
):
253 self
.cache_iface(foo_iface_uri
,
254 """<?xml version="1.0" ?>
255 <interface last-modified="1110752708"
257 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
259 <summary>Foo</summary>
260 <description>Foo</description>
261 <feed src='/etc/passwd'/>
262 </interface>""" % foo_iface_uri
)
263 self
.config
.network_use
= model
.network_offline
265 self
.config
.iface_cache
.get_interface(foo_iface_uri
)
267 except reader
.InvalidInterface
as ex
:
268 assert 'Invalid feed URL' in str(ex
)
270 def testDLfeed(self
):
271 self
.cache_iface(foo_iface_uri
,
272 """<?xml version="1.0" ?>
273 <interface last-modified="1110752708"
275 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
277 <summary>Foo</summary>
278 <description>Foo</description>
279 <feed src='http://example.com'/>
280 </interface>""" % foo_iface_uri
)
281 policy
= Policy(foo_iface_uri
, config
= self
.config
)
282 policy
.network_use
= model
.network_full
285 assert policy
.need_download()
287 feed
= self
.config
.iface_cache
.get_feed(foo_iface_uri
)
288 feed
.feeds
= [model
.Feed('/BadFeed', None, False)]
290 logger
.setLevel(logging
.ERROR
)
291 assert policy
.need_download() # Triggers warning
292 logger
.setLevel(logging
.WARN
)
294 def testBestUnusable(self
):
295 self
.cache_iface(foo_iface_uri
,
296 """<?xml version="1.0" ?>
297 <interface last-modified="1110752708"
299 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
301 <summary>Foo</summary>
302 <description>Foo</description>
303 <implementation id='sha1=123' version='1.0' arch='odd-weird' main='dummy'/>
304 </interface>""" % foo_iface_uri
)
305 policy
= Policy(foo_iface_uri
, config
= self
.config
)
306 policy
.network_use
= model
.network_offline
308 assert not policy
.ready
, policy
.implementation
310 download_and_execute(policy
, [])
312 except model
.SafeException
as ex
:
313 assert "has no usable implementations" in str(ex
), ex
315 def testNoArchives(self
):
316 self
.cache_iface(foo_iface_uri
,
317 """<?xml version="1.0" ?>
318 <interface last-modified="1110752708"
320 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
322 <summary>Foo</summary>
323 <description>Foo</description>
324 <implementation id='sha1=123' version='1.0' main='dummy'/>
325 </interface>""" % foo_iface_uri
)
326 policy
= Policy(foo_iface_uri
, config
= self
.config
)
329 assert not policy
.ready
332 self
.cache_iface(foo_iface_uri
,
333 """<?xml version="1.0" ?>
334 <interface last-modified="1110752708"
336 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
338 <summary>Foo</summary>
339 <description>Foo</description>
341 <requires interface='%s'/>
342 <implementation id='sha1=123' version='1.0'>
343 <archive href='foo' size='10'/>
346 </interface>""" % (foo_iface_uri
, foo_iface_uri
))
347 policy
= Policy(foo_iface_uri
, config
= self
.config
)
351 def testConstraints(self
):
352 self
.cache_iface('http://bar',
353 """<?xml version="1.0" ?>
354 <interface last-modified="1110752708"
356 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
358 <summary>Bar</summary>
359 <description>Bar</description>
360 <implementation id='sha1=100' version='1.0'>
361 <archive href='foo' size='10'/>
363 <implementation id='sha1=150' stability='developer' version='1.5'>
364 <archive href='foo' size='10'/>
366 <implementation id='sha1=200' version='2.0'>
367 <archive href='foo' size='10'/>
370 self
.cache_iface(foo_iface_uri
,
371 """<?xml version="1.0" ?>
372 <interface last-modified="1110752708"
374 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
376 <summary>Foo</summary>
377 <description>Foo</description>
379 <requires interface='http://bar'>
382 <implementation id='sha1=123' version='1.0'>
383 <archive href='foo' size='10'/>
386 </interface>""" % foo_iface_uri
)
387 policy
= Policy(foo_iface_uri
, config
= self
.config
)
388 policy
.network_use
= model
.network_full
390 #logger.setLevel(logging.DEBUG)
392 #logger.setLevel(logging.WARN)
393 foo_iface
= self
.config
.iface_cache
.get_interface(foo_iface_uri
)
394 bar_iface
= self
.config
.iface_cache
.get_interface('http://bar')
395 assert policy
.implementation
[bar_iface
].id == 'sha1=200'
397 dep
= policy
.implementation
[foo_iface
].dependencies
['http://bar']
398 assert len(dep
.restrictions
) == 1
399 restriction
= dep
.restrictions
[0]
401 restriction
.before
= model
.parse_version('2.0')
403 assert policy
.implementation
[bar_iface
].id == 'sha1=100'
405 restriction
.not_before
= model
.parse_version('1.5')
407 assert policy
.implementation
[bar_iface
].id == 'sha1=150'
409 if __name__
== '__main__':