Factor out some common code in the tests
[zeroinstall/zeroinstall-mseaborn.git] / tests / testendtoend.py
blobd638d886794d0d1767f9eb3e049bc44ac7a54a69
1 #!/usr/bin/env python2.4
2 import os
3 import subprocess
4 import sys
5 import unittest
7 sys.path.insert(0, '..')
9 from basetest import BaseTest
10 from basetest import write_file
11 from zeroinstall.injector import autopolicy
12 from zeroinstall.injector import run
13 from zeroinstall.injector import selections
14 from zeroinstall.injector.iface_cache import iface_cache
15 from zeroinstall.zerostore import manifest
18 # Based on code in 0publish/archive.py
19 def manifest_for_dir(dir):
20 algorithm = manifest.get_algorithm("sha1new")
21 digest = algorithm.new_digest()
22 for line in algorithm.generate_manifest(dir):
23 digest.update(line + '\n')
24 return algorithm.getID(digest)
27 def command_for_policy(policy):
28 selns = selections.Selections(policy)
29 return run.get_executable_for_selections(selns)
32 class FileTreeWriter(object):
34 def __init__(self, files):
35 self._files = files
37 def write_tree(self, dest_path):
38 for filename, data in self._files:
39 pathname = os.path.join(dest_path, filename)
40 if not os.path.exists(os.path.dirname(pathname)):
41 os.makedirs(os.path.dirname(pathname))
42 write_file(pathname, data)
43 # Making everything executable is simpler.
44 os.chmod(pathname, 0777)
47 class TestEndToEnd(BaseTest):
48 def _make_archive(self, tree):
49 tar_file = os.path.join(self.make_temp_dir(), "archive.tar.gz")
50 temp_dir = self.make_temp_dir()
51 tree.write_tree(temp_dir)
52 subprocess.check_call(["tar", "-czf", tar_file, "-C", temp_dir, "."])
53 return """
54 <implementation id="%s" version="1">
55 <archive href="%s" size="%i"/>
56 </implementation>
57 """ % (manifest_for_dir(temp_dir), tar_file, os.path.getsize(tar_file))
59 def _check_output(self, policy, expected_output):
60 env = {}
61 run.add_env_bindings(env, selections.Selections(policy))
62 cmd_path = command_for_policy(policy)
63 proc = subprocess.Popen([cmd_path], env=env, stdout=subprocess.PIPE)
64 stdout, stderr = proc.communicate()
65 self.assertEquals(proc.wait(), 0)
66 self.assertEquals(stdout, expected_output)
68 def test_module_with_no_dependencies(self):
69 tree = FileTreeWriter([("hello-test", """\
70 #!/bin/sh
71 echo Hello world!
72 """)])
73 feed_file = self.make_temp_file("""
74 <interface xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
75 <name>Test</name>
76 <summary>Placeholder</summary>
77 <group main="hello-test">
79 </group>
80 </interface>
81 """ % self._make_archive(tree))
82 policy = autopolicy.AutoPolicy(
83 feed_file, download_only=True, dry_run=False)
84 policy.download_and_execute([])
85 self._check_output(policy, "Hello world!\n")
87 def test_module_with_dependency(self):
88 library_tree = FileTreeWriter([("share/useful", "useful-contents\n")])
89 main_tree = FileTreeWriter([("bin/hello-test", """\
90 #!/bin/sh
91 echo Got:
92 cat $LIBFOO/share/useful
93 """)])
94 library_feed = self.make_temp_file("""\
95 <?xml version="1.0" ?>
96 <interface xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
97 <name>Test</name>
98 <summary>Placeholder</summary>
99 <group>
101 </group>
102 </interface>
103 """ % self._make_archive(library_tree))
104 main_feed = self.make_temp_file("""
105 <interface xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
106 <name>Test</name>
107 <summary>Placeholder</summary>
108 <group main="bin/hello-test">
110 <requires interface="%s">
111 <environment name="LIBFOO" insert="."/>
112 </requires>
113 </group>
114 </interface>
115 """ % (self._make_archive(main_tree), library_feed))
116 policy = autopolicy.AutoPolicy(
117 main_feed, download_only=True, dry_run=False)
118 policy.download_and_execute([])
119 env = {}
120 run.add_env_bindings(env, selections.Selections(policy))
121 self.assertEquals(env.keys(), ["LIBFOO"])
122 self._check_output(policy, "Got:\nuseful-contents\n")
124 def test_self_environment_binding(self):
125 tree = FileTreeWriter([("share/useful", "useful-contents\n"),
126 ("bin/hello-test", """\
127 #!/bin/sh
128 echo Got:
129 cat $MY_DATA_DIR/share/useful
130 """)])
131 feed_file = self.make_temp_file("""
132 <interface xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
133 <name>Test</name>
134 <summary>Placeholder</summary>
135 <group main="bin/hello-test">
137 <environment name="MY_DATA_DIR" insert="."/>
138 </group>
139 </interface>
140 """ % self._make_archive(tree))
141 policy = autopolicy.AutoPolicy(
142 feed_file, download_only=True, dry_run=False)
143 policy.download_and_execute([])
144 env = {}
145 run.add_env_bindings(env, selections.Selections(policy))
146 self.assertEquals(env.keys(), ["MY_DATA_DIR"])
147 self._check_output(policy, "Got:\nuseful-contents\n")
149 def test_module_with_substitution_dependency(self):
150 library_tree = FileTreeWriter([("share/useful", "useful-contents\n")])
151 main_tree = FileTreeWriter([("bin/hello-test", """\
152 #!/bin/sh
153 echo Got:
154 cat MAGIC_EMBEDDED_STRING_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/share/useful
155 """)])
156 library_feed = self.make_temp_file("""\
157 <?xml version="1.0" ?>
158 <interface xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
159 <name>Test</name>
160 <summary>Placeholder</summary>
161 <group>
163 </group>
164 </interface>
165 """ % self._make_archive(library_tree))
166 main_feed = self.make_temp_file("""
167 <interface xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
168 <name>Test</name>
169 <summary>Placeholder</summary>
170 <group main="bin/hello-test">
172 <requires interface="%s">
173 <rewrite from="MAGIC_EMBEDDED_STRING_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"/>
174 </requires>
175 </group>
176 </interface>
177 """ % (self._make_archive(main_tree), library_feed))
178 policy = autopolicy.AutoPolicy(
179 main_feed, download_only=True, dry_run=False)
180 policy.download_and_execute([])
181 env = {}
182 run.add_env_bindings(env, selections.Selections(policy))
183 self.assertEquals(env.keys(), [])
184 self._check_output(policy, "Got:\nuseful-contents\n")
185 # Check that rewritten copies are cached.
186 self.assertEquals(command_for_policy(policy),
187 command_for_policy(policy))
189 def test_self_reference_substitution(self):
190 tree = FileTreeWriter([("share/useful", "useful-contents\n"),
191 ("bin/hello-test", """\
192 #!/bin/sh
193 echo Got:
194 cat MAGIC_EMBEDDED_STRING_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/share/useful
195 """)])
196 feed_file = self.make_temp_file("""
197 <interface xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
198 <name>Test</name>
199 <summary>Placeholder</summary>
200 <group main="bin/hello-test">
202 <rewrite from="MAGIC_EMBEDDED_STRING_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"/>
203 </group>
204 </interface>
205 """ % self._make_archive(tree))
206 policy = autopolicy.AutoPolicy(
207 feed_file, download_only=True, dry_run=False)
208 policy.download_and_execute([])
209 env = {}
210 run.add_env_bindings(env, selections.Selections(policy))
211 self.assertEquals(env.keys(), [])
212 self._check_output(policy, "Got:\nuseful-contents\n")
213 # Check that rewritten copies are cached.
214 self.assertEquals(command_for_policy(policy),
215 command_for_policy(policy))
217 def test_fixed_length_substitution_in_dependency(self):
218 original = "MAGIC_EMBEDDED_STRING_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
219 tree = FileTreeWriter([("bin/hello-test", """\
220 #!/bin/sh
221 echo -n MAGIC_EMBEDDED_STRING_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
222 """)])
223 feed_file = self.make_temp_file("""
224 <interface xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
225 <name>Test</name>
226 <summary>Placeholder</summary>
227 <group main="bin/hello-test">
229 <rewrite from="MAGIC_EMBEDDED_STRING_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"/>
230 </group>
231 </interface>
232 """ % self._make_archive(tree))
233 policy = autopolicy.AutoPolicy(
234 feed_file, download_only=True, dry_run=False)
235 policy.download_and_execute([])
236 cmd_path = command_for_policy(policy)
237 proc = subprocess.Popen([cmd_path], stdout=subprocess.PIPE)
238 stdout, stderr = proc.communicate()
239 self.assertEquals(proc.wait(), 0)
240 self.assertNotEquals(stdout, original)
241 self.assertEquals(len(stdout), len(original))
243 def test_fixed_length_substitution_in_self_dependency(self):
244 original = "MAGIC_EMBEDDED_STRING_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
245 library_tree = FileTreeWriter([])
246 binary_data = "".join(chr(c) for c in range(256))
247 main_tree = FileTreeWriter([("bin/hello-test", """\
248 #!/bin/sh
249 echo -n MAGIC_EMBEDDED_STRING_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
250 exit
251 """ + binary_data)])
252 library_feed = self.make_temp_file("""\
253 <?xml version="1.0" ?>
254 <interface xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
255 <name>Test</name>
256 <summary>Placeholder</summary>
257 <group>%s</group>
258 </interface>
259 """ % self._make_archive(library_tree))
260 main_feed = self.make_temp_file("""
261 <interface xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
262 <name>Test</name>
263 <summary>Placeholder</summary>
264 <group main="bin/hello-test">
266 <requires interface="%s">
267 <rewrite from="MAGIC_EMBEDDED_STRING_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"/>
268 </requires>
269 </group>
270 </interface>
271 """ % (self._make_archive(main_tree), library_feed))
272 policy = autopolicy.AutoPolicy(
273 main_feed, download_only=True, dry_run=False)
274 policy.download_and_execute([])
275 cmd_path = command_for_policy(policy)
276 proc = subprocess.Popen([cmd_path], stdout=subprocess.PIPE)
277 stdout, stderr = proc.communicate()
278 self.assertEquals(proc.wait(), 0)
279 self.assertNotEquals(stdout, original)
280 self.assertEquals(len(stdout), len(original))
282 def test_exponential_dependency_graph(self):
283 # This test will not fail when the code does the wrong
284 # thing, it will just take a long time to complete.
285 empty_archive = self._make_archive(FileTreeWriter([]))
286 library_feed = self.make_temp_file("""\
287 <?xml version="1.0" ?>
288 <interface xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
289 <name>Test</name>
290 <summary>Placeholder</summary>
291 <group>%s</group>
292 </interface>
293 """ % empty_archive)
294 for i in range(50):
295 library_feed = self.make_temp_file("""\
296 <?xml version="1.0" ?>
297 <interface xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
298 <name>Test</name>
299 <summary>Placeholder</summary>
300 <group>
301 %(impl)s
302 <environment name="BAR" insert="."/>
303 <requires interface="%(lib)s">
304 <rewrite from="MAGIC_EMBEDDED_STRING_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"/>
305 </requires>
306 <requires interface="%(lib)s">
307 <rewrite from="MAGIC_EMBEDDED_STRING_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"/>
308 </requires>
309 </group>
310 </interface>
311 """ % {"impl": empty_archive,
312 "lib": library_feed})
313 main_feed = self.make_temp_file("""
314 <interface xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
315 <name>Test</name>
316 <summary>Placeholder</summary>
317 <group main="bin/main">
319 <requires interface="%s">
320 <environment name="FOO" insert="."/>
321 </requires>
322 </group>
323 </interface>
324 """ % (self._make_archive(FileTreeWriter([("bin/main", "")])), library_feed))
325 policy = autopolicy.AutoPolicy(
326 main_feed, download_only=True, dry_run=False)
327 policy.download_and_execute([])
328 env = {}
329 run.add_env_bindings(env, selections.Selections(policy))
330 command_for_policy(policy)
333 suite = unittest.makeSuite(TestEndToEnd)
334 if __name__ == '__main__':
335 sys.argv.append('-v')
336 unittest.main()