Added license info to feed
[0publish.git] / tests / testlocal.py
blobc798d359748d2551f2b2cf72c2f82bd922024fcd
1 #!/usr/bin/env python
2 import sys, os, tempfile, StringIO
3 from zeroinstall.injector.namespaces import XMLNS_IFACE
4 from zeroinstall.injector.reader import InvalidInterface
5 from zeroinstall.injector import model, reader, qdom
6 import unittest
7 from xml.dom import minidom
9 sys.path.insert(0, '..')
11 import create, merge, release
13 header = """<?xml version="1.0" ?>
14 <interface xmlns="http://zero-install.sourceforge.net/2004/injector/interface"
15 uri='http://test/hello.xml'>
16 <name>test</name>
17 <summary>for testing</summary>
18 <description>This is for testing.</description>
19 """
20 footer = """
21 </interface>
22 """
24 def parse(xml):
25 stream = StringIO.StringIO(xml)
26 return model.ZeroInstallFeed(qdom.parse(stream))
28 local_file = os.path.join(os.path.dirname(__file__), 'local.xml')
29 local_file_req = os.path.join(os.path.dirname(__file__), 'local-req.xml')
30 local_file_if = os.path.join(os.path.dirname(__file__), 'local-if.xml')
31 local_file_command = os.path.join(os.path.dirname(__file__), 'local-command.xml')
32 local_file_ns = os.path.join(os.path.dirname(__file__), 'local-ns.xml')
33 local_file_main_and_command = os.path.join(os.path.dirname(__file__), 'local-main-and-command.xml')
34 local_file_zi13 = os.path.join(os.path.dirname(__file__), 'zeroinstall-injector-1.3.xml')
36 def tap(s):
37 #print s
38 return s
40 class TestLocal(unittest.TestCase):
41 def testCreate(self):
42 master = parse(create.create_from_local(local_file))
43 assert master.url == 'http://test/hello.xml', master
44 assert len(master.implementations) == 1
46 def testMergeFirst(self):
47 master = parse(merge.merge(header + footer, local_file))
48 assert master.url == 'http://test/hello.xml', master
49 assert len(master.implementations) == 1
51 def testMergeSecond(self):
52 master = parse(merge.merge(header + "<implementation id='sha1=123' version='1'/>" + footer, local_file))
53 assert master.url == 'http://test/hello.xml', master
54 assert len(master.implementations) == 2
56 def testMergeTwice(self):
57 try:
58 once = merge.merge(header + "<implementation id='sha1=123' version='1'/>" + footer, local_file)
59 twice = merge.merge(once, local_file)
60 assert 0
61 except Exception as ex:
62 assert 'Duplicate ID' in str(ex)
64 def testMergeGroup(self):
65 master = parse(merge.merge(header + "<group>\n <implementation id='sha1=123' version='1'/>\n </group>" + footer, local_file))
66 assert master.url == 'http://test/hello.xml', master
67 assert len(master.implementations) == 2
68 assert master.implementations['sha1=002'].requires == []
70 def testMergeLocalReq(self):
71 master = parse(tap(merge.merge(header + "<group x='x'>\n <implementation id='sha1=123' version='1'/>\n </group>" + footer, local_file_req)))
72 assert master.url == 'http://test/hello.xml', master
73 assert len(master.implementations) == 2
74 deps = master.implementations['sha1=003'].requires
75 assert len(deps) == 1
76 assert deps[0].interface == 'http://foo', deps[0]
78 assert master.implementations['sha1=003'].metadata['http://mynamespace/foo bob'] == 'bob'
80 def testNotSubset(self):
81 master = parse(merge.merge(header + "<group a='a'>\n <implementation id='sha1=123' version='1'/>\n </group>" + footer, local_file))
82 assert master.url == 'http://test/hello.xml', master
83 assert len(master.implementations) == 2
84 assert master.implementations['sha1=123'].metadata.get('a', None) == 'a'
85 assert master.implementations['sha1=002'].metadata.get('a', None) == None
87 master = parse(merge.merge(header + """\n
88 <group>
89 <requires interface='http://foo' meta='foo'/>
90 <implementation id='sha1=004' version='1'/>
91 </group>
92 <group>
93 <requires interface='http://foo'>
94 <version before='1'/>
95 </requires>
96 <implementation id='sha1=001' version='1'/>
97 </group>""" + footer, local_file_req))
98 assert len(master.implementations['sha1=001'].requires[0].restrictions) == 1
99 assert len(master.implementations['sha1=003'].requires[0].restrictions) == 0
101 assert master.implementations['sha1=004'].requires[0].metadata.get('meta', None) == 'foo'
102 assert master.implementations['sha1=003'].requires[0].metadata.get('meta', None) == None
104 assert master.implementations['sha1=003'].main == 'hello'
106 def testMergeBest(self):
107 master_xml = merge.merge(header + """\n
108 <group>
109 <implementation id='sha1=123' version='1'/>
110 </group>
111 <group>
112 <requires interface='http://foo'/>
113 <implementation id='sha1=002' version='2'/>
114 </group>""" + footer, local_file_req)
115 master = parse(master_xml)
116 assert master.url == 'http://test/hello.xml', master
117 assert len(master.implementations) == 3
118 deps = master.implementations['sha1=003'].requires
119 assert len(deps) == 1
120 assert deps[0].interface == 'http://foo', deps[0]
122 assert len(minidom.parseString(master_xml).documentElement.getElementsByTagNameNS(XMLNS_IFACE, 'group')) == 2
124 # Again, but with the groups the other way around
125 master_xml = merge.merge(header + """\n
126 <group>
127 <requires interface='http://foo'/>
128 <implementation id='sha1=002' version='2'/>
129 </group>
130 <group>
131 <implementation id='sha1=123' version='1'/>
132 </group>""" + footer, local_file_req)
133 master = parse(master_xml)
134 assert master.url == 'http://test/hello.xml', master
135 assert len(master.implementations) == 3
136 deps = master.implementations['sha1=003'].requires
137 assert len(deps) == 1
138 assert deps[0].interface == 'http://foo', deps[0]
140 assert len(minidom.parseString(master_xml).documentElement.getElementsByTagNameNS(XMLNS_IFACE, 'group')) == 2
142 def testMergeNS(self):
143 master_xml = merge.merge(header + footer, local_file_ns)
144 master = parse(master_xml)
145 assert master.url == 'http://test/hello.xml', master
146 assert len(master.implementations) == 1
147 commands = master.implementations['sha1=003'].commands
148 assert len(commands) == 1
149 assert commands['run'].path == 'run.sh', commands['run'].path
151 new_root = minidom.parseString(master_xml).documentElement
152 assert len(new_root.getElementsByTagNameNS(XMLNS_IFACE, 'group')) == 1
153 assert len(new_root.getElementsByTagNameNS(XMLNS_IFACE, 'requires')) == 1
154 assert len(new_root.getElementsByTagNameNS(XMLNS_IFACE, 'command')) == 1
156 foo_test, = new_root.getElementsByTagNameNS('http://mynamespace/foo', 'test')
157 foo1_test, = new_root.getElementsByTagNameNS('http://myother/foo', 'test')
159 def testMergeCommand(self):
160 # We create a new group inside this one, sharing the <requires> and adding the <command>
161 master_xml = merge.merge(header + """
162 <group>
163 <requires interface='http://foo'>
164 <environment name='TESTING' value='true' mode='replace'/>
165 </requires>
166 <implementation id='sha1=002' version='2'/>
167 </group>""" + footer, local_file_command)
168 master = parse(master_xml)
169 assert master.url == 'http://test/hello.xml', master
170 assert len(master.implementations) == 2
171 commands = master.implementations['sha1=003'].commands
172 assert len(commands) == 1
173 assert commands['run'].path == 'run.sh', commands['run'].path
175 new_root = minidom.parseString(master_xml).documentElement
176 assert len(new_root.getElementsByTagNameNS(XMLNS_IFACE, 'group')) == 2
177 assert len(new_root.getElementsByTagNameNS(XMLNS_IFACE, 'requires')) == 1
178 assert len(new_root.getElementsByTagNameNS(XMLNS_IFACE, 'command')) == 1
180 # We create a new top-level group inside this one, as we can't share the test command
181 master_xml = merge.merge(header + """
182 <group>
183 <requires interface='http://foo'>
184 <environment name='TESTING' value='true' mode='replace'/>
185 </requires>
186 <command name='test' path='test.sh'/>
187 <implementation id='sha1=002' version='2'/>
188 </group>""" + footer, local_file_command)
189 master = parse(master_xml)
190 assert master.url == 'http://test/hello.xml', master
191 assert len(master.implementations) == 2
192 commands = master.implementations['sha1=003'].commands
193 assert len(commands) == 1
194 assert commands['run'].path == 'run.sh', commands['run'].path
196 new_root = minidom.parseString(master_xml).documentElement
197 assert len(new_root.getElementsByTagNameNS(XMLNS_IFACE, 'group')) == 2
198 assert len(new_root.getElementsByTagNameNS(XMLNS_IFACE, 'requires')) == 2
199 assert len(new_root.getElementsByTagNameNS(XMLNS_IFACE, 'command')) == 2
201 # We share the <requires> and override the <command>
202 master_xml = merge.merge(header + """
203 <group>
204 <requires interface='http://foo'>
205 <environment name='TESTING' value='true' mode='replace'/>
206 </requires>
207 <command name='run' path='old-run.sh'/>
208 <implementation id='sha1=002' version='2'/>
209 </group>""" + footer, local_file_command)
210 master = parse(master_xml)
211 assert master.url == 'http://test/hello.xml', master
212 assert len(master.implementations) == 2
213 commands = master.implementations['sha1=003'].commands
214 assert len(commands) == 1
215 assert commands['run'].path == 'run.sh', commands['run'].path
217 new_root = minidom.parseString(master_xml).documentElement
218 assert len(new_root.getElementsByTagNameNS(XMLNS_IFACE, 'group')) == 2
219 assert len(new_root.getElementsByTagNameNS(XMLNS_IFACE, 'requires')) == 1
220 assert len(new_root.getElementsByTagNameNS(XMLNS_IFACE, 'command')) == 2
222 # We share the <requires> and the <command>
223 master_xml = merge.merge(header + """
224 <group>
225 <requires interface='http://foo'>
226 <environment name='TESTING' value='true' mode='replace'/>
227 </requires>
228 <command name='run' path='run.sh'/>
229 <implementation id='sha1=002' version='2'/>
230 </group>""" + footer, local_file_command)
231 master = parse(master_xml)
232 assert master.url == 'http://test/hello.xml', master
233 assert len(master.implementations) == 2
234 commands = master.implementations['sha1=003'].commands
235 assert len(commands) == 1
236 assert commands['run'].path == 'run.sh', commands['run'].path
238 new_root = minidom.parseString(master_xml).documentElement
239 assert len(new_root.getElementsByTagNameNS(XMLNS_IFACE, 'group')) == 1
240 assert len(new_root.getElementsByTagNameNS(XMLNS_IFACE, 'requires')) == 1
241 assert len(new_root.getElementsByTagNameNS(XMLNS_IFACE, 'command')) == 1
243 def testMerge2(self):
244 master_xml = merge.merge(header + """
245 <group license="OSI Approved :: GNU Lesser General Public License (LGPL)" main="0launch">
246 <command name="run" path="0launch">
247 <runner interface="http://repo.roscidus.com/python/python">
248 <version before="3"/>
249 </runner>
250 </command>
252 <group>
253 <command name="run" path="0launch"/>
254 <implementation id="sha1new=7d1ecfbd76a42d56f029f9d0c72e4ac26c8561de" released="2011-07-23" version="1.2"/>
255 </group>
256 </group>
257 """ + footer, local_file_zi13)
258 doc = minidom.parseString(master_xml)
260 n_groups = len(doc.getElementsByTagName("group"))
261 assert n_groups == 2
263 def testMergeMainAndCommand(self):
264 # Ensure the main attribute doesn't get promoted over the command
266 # Case 1: the group already has a suitable main and command.
267 # We simply add the new implementation to the group, without its own main.
268 master_xml = merge.merge(header + """
269 <group main='main'>
270 <command name='run' path='run.sh'/>
271 <implementation id="sha1=001" version="0.1"/>
272 </group>
273 """ + footer, local_file_main_and_command)
274 feed = parse(master_xml)
276 assert feed.implementations['sha1=001'].main == "run.sh"
277 assert feed.implementations['sha1=002'].main == "run.sh"
279 # Case 2: the group doesn't specify a main.
280 # We need to create a sub-group for it.
281 master_xml = merge.merge(header + """
282 <group>
283 <command name='run' path='run.sh'/>
284 <implementation id="sha1=001" version="0.1"/>
285 </group>
286 """ + footer, local_file_main_and_command)
287 feed = parse(master_xml)
289 assert feed.implementations['sha1=001'].main == "run.sh"
290 assert feed.implementations['sha1=002'].main == "run.sh"
292 def testMergeIf0installVersion(self):
293 master_xml = merge.merge(header + """
294 <group>
295 <command name='run' path='run.sh'/>
296 <implementation id="sha1=004" version="0.4"/>
297 </group>
298 """ + footer, local_file_if)
299 doc = minidom.parseString(master_xml)
301 n_commands = len(doc.getElementsByTagName("command"))
302 assert n_commands == 3
304 # We can share the run-old.sh <command>
305 master_xml = merge.merge(header + """
306 <group>
307 <command name='run' path='run-old.sh' if-0install-version='..!2'/>
308 <command name='run' path='run-mid.sh' if-0install-version='2..'/>
309 <implementation id="sha1=004" version="0.4"/>
310 </group>
311 """ + footer, local_file_if)
312 doc = minidom.parseString(master_xml)
314 n_commands = len(doc.getElementsByTagName("command"))
315 assert n_commands == 3
317 def testLocalContext(self):
318 def get_context(xml_frag):
319 doc = minidom.parseString(header + xml_frag + footer)
320 impls = list(doc.getElementsByTagNameNS(XMLNS_IFACE, 'implementation'))
321 assert len(impls) == 1
322 return merge.Context(impls[0])
324 ctx = get_context("<implementation id='sha1=001' version='1'/>")
325 assert ctx.attribs[(None, 'id')] == 'sha1=001'
326 assert ctx.attribs[(None, 'version')] == '1'
328 ctx = get_context("<group t='t' x='1' y:z='2' xmlns:y='yns'><implementation id='sha1=001' version='1' t='r'/></group>")
329 assert ctx.attribs[(None, 'id')] == 'sha1=001'
330 assert ctx.attribs[(None, 'version')] == '1'
331 assert ctx.attribs[(None, 't')] == 'r'
332 assert ctx.attribs[(None, 'x')] == '1'
333 assert ctx.attribs[('yns', 'z')] == '2'
335 def testSetAtttibs(self):
336 local_data = open(local_file).read()
337 result = release.set_attributes(local_data, '0.2', id = 'sha1=98765', version='3.7', main = None)
338 feed = model.ZeroInstallFeed(qdom.parse(StringIO.StringIO(str(result))), "local.xml")
339 assert len(feed.implementations) == 1
340 assert feed.implementations['sha1=98765'].get_version() == '3.7'
342 try:
343 result = release.set_attributes(local_data, '0.3', id = 'sha1=98765', version='3.7', main = None)
344 assert 0
345 except Exception, ex:
346 assert str(ex) == 'No implementations with version=0.3'
348 suite = unittest.makeSuite(TestLocal)
349 if __name__ == '__main__':
350 unittest.main()