In unit-tests, always use StringIO, not io
[zeroinstall.git] / tests / testreader.py
blob5f9aad226955994bb8e3577b086b09a95b7405c8
1 #!/usr/bin/env python
2 from basetest import BaseTest
3 import sys, tempfile, logging
4 import unittest
5 import os
7 sys.path.insert(0, '..')
9 from zeroinstall.injector import model, gpg, reader
10 import data
12 foo_iface_uri = 'http://foo'
13 bar_iface_uri = 'http://localhost/bar'
15 logger = logging.getLogger()
17 class TestReader(BaseTest):
18 def setUp(self):
19 BaseTest.setUp(self)
21 stream = tempfile.TemporaryFile(mode = 'wb')
22 stream.write(data.thomas_key)
23 stream.seek(0)
24 gpg.import_key(stream)
25 stream.close()
27 def write_with_version(self, version):
28 tmp = tempfile.NamedTemporaryFile(mode = 'wt', prefix = 'test-')
29 tmp.write(
30 """<?xml version="1.0" ?>
31 <interface last-modified="1110752708"
32 uri="%s" %s
33 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
34 <name>Foo</name>
35 <summary>Foo</summary>
36 <description>Foo</description>
37 </interface>""" % (foo_iface_uri, version))
38 tmp.flush()
39 return tmp
41 def write_with_bindings(self, bindings):
42 tmp = tempfile.NamedTemporaryFile(mode = 'wt', prefix = 'test-')
43 tmp.write(
44 """<?xml version="1.0" ?>
45 <interface last-modified="1110752708"
46 uri="%s"
47 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
48 <name>Foo</name>
49 <summary>Foo</summary>
50 <description>Foo</description>
51 <group>
52 <requires interface='%s2'>
54 </requires>
55 <implementation id='sha1=123' version='1'/>
56 </group>
57 </interface>""" % (foo_iface_uri, foo_iface_uri, bindings))
58 tmp.flush()
59 return tmp
61 def testNoVersion(self):
62 tmp = self.write_with_version('')
63 reader.check_readable(foo_iface_uri, tmp.name)
65 def testNewEnough(self):
66 tmp = self.write_with_version('min-injector-version="0.19"')
67 reader.check_readable(foo_iface_uri, tmp.name)
69 def testTooOld(self):
70 tmp = self.write_with_version('min-injector-version="1000"')
71 try:
72 reader.check_readable(foo_iface_uri, tmp.name)
73 self.fail()
74 except reader.InvalidInterface as ex:
75 assert "1000" in str(ex)
77 def testCantUseBothInsertAndValueInEnvironmentBinding(self):
78 tmp = self.write_with_bindings("""
79 <environment name="DATA" value="" insert=""/>
80 """)
81 try:
82 reader.check_readable(foo_iface_uri, tmp.name)
83 self.fail()
84 except reader.InvalidInterface as ex:
85 assert "Binding contains both 'insert' and 'value'" in str(ex)
87 def testRequiresVersion(self):
88 tmp = tempfile.NamedTemporaryFile(mode = 'wt', prefix = 'test-')
89 tmp.write(
90 """<?xml version="1.0" ?>
91 <interface last-modified="1110752708"
92 uri="%s"
93 xmlns="http://zero-install.sourceforge.net/2004/injector/interface"
94 xmlns:my='http://my/namespace'>
95 <name>Foo</name>
96 <summary>Foo</summary>
97 <description>Foo</description>
98 <group>
99 <requires interface='%s' my:foo='test'>
100 <version not-before='2.3.4' before='3.4.5'/>
101 </requires>
102 <implementation id='sha1=123' version='1'/>
103 <requires interface='%s2'/>
104 </group>
105 </interface>""" % (foo_iface_uri, bar_iface_uri, bar_iface_uri))
106 tmp.flush()
107 iface = model.Interface(foo_iface_uri)
108 reader.update(iface, tmp.name, iface_cache = self.config.iface_cache)
109 feed = self.config.iface_cache.get_feed(foo_iface_uri)
111 impl = feed.implementations['sha1=123']
112 assert len(impl.dependencies) == 2
113 dep = impl.dependencies[bar_iface_uri]
114 assert len(dep.restrictions) == 1
115 res = dep.restrictions[0]
116 assert res.not_before == [[2, 3, 4], 0]
117 assert res.before == [[3, 4, 5], 0]
118 dep2 = impl.dependencies[bar_iface_uri + '2']
119 assert len(dep2.restrictions) == 0
120 str(dep)
121 str(dep2)
123 assert dep.metadata.get('http://my/namespace foo') == 'test'
124 assert dep.metadata.get('http://my/namespace food', None) == None
126 def testBindings(self):
127 tmp = tempfile.NamedTemporaryFile(mode = 'wt', prefix = 'test-')
128 tmp.write(
129 """<?xml version="1.0" ?>
130 <interface xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
131 <name>Foo</name>
132 <summary>Foo</summary>
133 <description>Foo</description>
134 <group>
135 <requires interface='http://example.com/foo.xml'>
136 <environment name='PATH' insert='bin'/>
137 <environment name='PATH' insert='bin' mode='prepend'/>
138 <environment name='PATH' insert='bin' default='/bin' mode='append'/>
139 <environment name='PATH' insert='bin' mode='replace'/>
140 <environment name='PATH' insert='bin' separator=',' />
141 </requires>
142 <implementation id='sha1=123' version='1'>
143 <environment name='SELF' insert='.' mode='replace'/>
144 </implementation>
145 </group>
146 </interface>""")
147 tmp.flush()
148 iface = model.Interface(foo_iface_uri)
149 reader.update(iface, tmp.name, local = True, iface_cache = self.config.iface_cache)
151 feed = self.config.iface_cache.get_feed(foo_iface_uri)
153 impl = feed.implementations['sha1=123']
155 assert len(impl.bindings) == 1
156 self.assertEqual(model.EnvironmentBinding.REPLACE, impl.bindings[0].mode)
158 assert len(impl.requires) == 1
159 dep = impl.requires[0]
161 assert len(dep.bindings) == 5
162 for b in dep.bindings:
163 self.assertEqual('PATH', b.name)
164 self.assertEqual('bin', b.insert)
165 self.assertEqual(model.EnvironmentBinding.PREPEND, dep.bindings[0].mode)
166 self.assertEqual(model.EnvironmentBinding.PREPEND, dep.bindings[1].mode)
167 self.assertEqual(model.EnvironmentBinding.APPEND, dep.bindings[2].mode)
168 self.assertEqual(model.EnvironmentBinding.REPLACE, dep.bindings[3].mode)
169 self.assertEqual(model.EnvironmentBinding.PREPEND, dep.bindings[4].mode)
171 self.assertEqual(os.path.join('/impl', 'bin:current'),
172 dep.bindings[0].get_value('/impl', 'current'))
173 self.assertEqual(os.path.join('/impl', 'bin,current'),
174 dep.bindings[4].get_value('/impl', 'current'))
176 self.assertEqual(None, dep.bindings[1].default)
177 self.assertEqual('/bin', dep.bindings[2].default)
179 def testVersions(self):
180 tmp = tempfile.NamedTemporaryFile(mode = 'wt', prefix = 'test-')
181 tmp.write(
182 """<?xml version="1.0" ?>
183 <interface
184 uri="%s"
185 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
186 <name>Foo</name>
187 <summary>Foo</summary>
188 <description>Foo</description>
189 <implementation id='sha1=123' version='1.0-rc3' version-modifier='-pre'/>
190 </interface>""" % foo_iface_uri)
191 tmp.flush()
192 iface = model.Interface(foo_iface_uri)
193 reader.update(iface, tmp.name, iface_cache = self.config.iface_cache)
194 feed = self.config.iface_cache.get_feed(foo_iface_uri)
195 impl = feed.implementations['sha1=123']
196 assert impl.version == [[1, 0], -1, [3], -2]
198 def testAttrs(self):
199 iface_cache = self.config.iface_cache
200 tmp = tempfile.NamedTemporaryFile(mode = 'wt', prefix = 'test-')
201 tmp.write(
202 """<?xml version="1.0" ?>
203 <interface last-modified="1110752708"
204 uri="%s"
205 xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
206 <name>Foo</name>
207 <summary>Foo</summary>
208 <description>Foo</description>
209 <group main='bin/sh' foo='foovalue' xmlns:bobpre='http://bob' bobpre:bob='bobvalue'>
210 <implementation id='sha1=123' version='1' bobpre:bob='newbobvalue'/>
211 <implementation id='sha1=124' version='2' main='next'/>
212 </group>
213 </interface>""" % foo_iface_uri)
214 tmp.flush()
215 iface = model.Interface(foo_iface_uri)
216 reader.update(iface, tmp.name, iface_cache = self.config.iface_cache)
218 feed = iface_cache.get_feed(foo_iface_uri)
220 assert len(feed.implementations) == 2
222 assert feed.implementations['sha1=123'].metadata['foo'] == 'foovalue'
223 assert feed.implementations['sha1=123'].metadata['main'] == 'bin/sh'
224 assert feed.implementations['sha1=123'].metadata['http://bob bob'] == 'newbobvalue'
226 assert feed.implementations['sha1=124'].metadata['http://bob bob'] == 'bobvalue'
227 assert feed.implementations['sha1=124'].metadata['main'] == 'next'
229 def testNative(self):
230 iface_cache = self.config.iface_cache
231 tmp = tempfile.NamedTemporaryFile(mode = 'wt', prefix = 'test-')
232 tmp.write(
233 """<?xml version="1.0" ?>
234 <interface xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
235 <name>Foo</name>
236 <summary>Foo</summary>
237 <description>Foo</description>
238 <package-implementation package='gimp'/>
239 <package-implementation package='python-bittorrent' foo='bar' main='/usr/bin/pbt'/>
240 </interface>""")
241 tmp.flush()
243 iface = model.Interface(foo_iface_uri)
244 reader.update(iface, tmp.name, True, iface_cache = self.config.iface_cache)
246 master_feed = iface_cache.get_feed(foo_iface_uri)
247 assert len(master_feed.implementations) == 0
248 distro_feed_url = master_feed.get_distro_feed()
250 feed = iface_cache.get_feed(distro_feed_url)
251 assert len(feed.implementations) == 1
253 impl = feed.implementations['package:deb:python-bittorrent:3.4.2-10:*']
254 assert impl.id == 'package:deb:python-bittorrent:3.4.2-10:*'
255 assert impl.upstream_stability == model.packaged
256 assert impl.user_stability == None
257 assert impl.requires == []
258 assert impl.main == '/usr/bin/pbt'
259 assert impl.metadata['foo'] == 'bar'
260 assert impl.feed == feed
262 def testLang(self):
263 tmp = tempfile.NamedTemporaryFile(mode = 'wt', prefix = 'test-')
264 tmp.write(
265 """<?xml version="1.0" ?>
266 <interface xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
267 <name>Foo</name>
268 <summary>Foo</summary>
269 <description>Foo</description>
270 <feed langs='fr en_GB' src='http://localhost/feed.xml'/>
271 <group>
272 <group langs='fr en_GB'>
273 <implementation id='sha1=124' version='2' langs='fr'/>
274 <implementation id='sha1=234' version='2'/>
275 </group>
276 <implementation id='sha1=345' version='2'/>
277 </group>
278 </interface>""")
279 tmp.flush()
281 feed = reader.load_feed(tmp.name, local = True)
283 assert len(feed.implementations) == 3
284 assert len(feed.feeds) == 1, feed.feeds
286 self.assertEqual('fr en-GB', feed.feeds[0].langs)
288 self.assertEqual('fr', feed.implementations['sha1=124'].langs)
289 self.assertEqual('fr en-GB', feed.implementations['sha1=234'].langs)
290 self.assertEqual('', feed.implementations['sha1=345'].langs)
292 if __name__ == '__main__':
293 unittest.main()