Renamed <executable> to <executable-in-path>
[zeroinstall.git] / tests / testinstall.py
blob2b6033d399d15ec3ab74f5539c73edb40bba7382
1 #!/usr/bin/env python
2 from basetest import BaseTest, TestStores
3 import sys, os, tempfile
4 from StringIO import StringIO
5 import unittest
7 sys.path.insert(0, '..')
8 from zeroinstall import cmd
9 from zeroinstall.injector import model, selections, qdom, reader, policy, handler, gpg
11 mydir = os.path.dirname(__file__)
13 class Reply:
14 def __init__(self, reply):
15 self.reply = reply
17 def readline(self):
18 return self.reply
20 class TestInstall(BaseTest):
21 def run_0install(self, args):
22 old_stdout = sys.stdout
23 old_stderr = sys.stderr
24 try:
25 sys.stdout = StringIO()
26 sys.stderr = StringIO()
27 ex = None
28 try:
29 cmd.main(args, config = self.config)
30 except NameError:
31 raise
32 except SystemExit:
33 pass
34 except TypeError:
35 raise
36 except AttributeError:
37 raise
38 except AssertionError:
39 raise
40 except Exception as ex:
41 pass
42 out = sys.stdout.getvalue()
43 err = sys.stderr.getvalue()
44 if ex is not None:
45 err += str(ex.__class__)
46 finally:
47 sys.stdout = old_stdout
48 sys.stderr = old_stderr
49 return (out, err)
51 def testHelp(self):
52 out, err = self.run_0install([])
53 assert out.lower().startswith("usage:")
54 assert 'add-feed' in out
55 assert '--version' in out
56 assert not err, err
58 out2, err = self.run_0install(['--help'])
59 assert not err, err
60 assert out2 == out
62 out, err = self.run_0install(['--version'])
63 assert 'Thomas Leonard' in out
64 assert not err, err
66 out, err = self.run_0install(['foobar'])
67 assert 'Unknown sub-command' in err, err
69 def testSelect(self):
70 out, err = self.run_0install(['select'])
71 assert out.lower().startswith("usage:")
72 assert '--xml' in out
74 out, err = self.run_0install(['select', 'Local.xml'])
75 assert not err, err
76 assert 'Version: 0.1' in out
78 local_uri = model.canonical_iface_uri('Local.xml')
79 out, err = self.run_0install(['select', 'Local.xml'])
80 assert not err, err
81 assert 'Version: 0.1' in out
83 out, err = self.run_0install(['select', 'Local.xml', '--xml'])
84 sels = selections.Selections(qdom.parse(StringIO(str(out))))
85 assert sels.selections[local_uri].version == '0.1'
87 out, err = self.run_0install(['select', 'selections.xml'])
88 assert not err, err
89 assert 'Version: 1\n' in out
90 assert '(not cached)' in out
92 def testDownload(self):
93 out, err = self.run_0install(['download'])
94 assert out.lower().startswith("usage:")
95 assert '--show' in out
97 out, err = self.run_0install(['download', 'Local.xml', '--show'])
98 assert not err, err
99 assert 'Version: 0.1' in out
101 local_uri = model.canonical_iface_uri('Local.xml')
102 out, err = self.run_0install(['download', 'Local.xml', '--xml'])
103 assert not err, err
104 sels = selections.Selections(qdom.parse(StringIO(str(out))))
105 assert sels.selections[local_uri].version == '0.1'
107 out, err = self.run_0install(['download', 'Local.xml', '--show', '--with-store=/foo'])
108 assert not err, err
109 assert self.config.stores.stores[-1].dir == '/foo'
111 out, err = self.run_0install(['download', '--offline', 'selections.xml'])
112 assert 'Would download' in err
113 self.config.network_use = model.network_full
115 self.config.stores = TestStores()
116 digest = 'sha1=3ce644dc725f1d21cfcf02562c76f375944b266a'
117 self.config.fetcher.allow_download(digest)
118 out, err = self.run_0install(['download', 'Hello.xml', '--show'])
119 assert not err, err
120 assert self.config.stores.lookup_any([digest]).startswith('/fake')
121 assert 'Version: 1\n' in out
123 out, err = self.run_0install(['download', '--offline', 'selections.xml', '--show'])
124 assert '/fake_store' in out
125 self.config.network_use = model.network_full
127 def testDownloadSelections(self):
128 self.config.stores = TestStores()
129 digest = 'sha1=3ce644dc725f1d21cfcf02562c76f375944b266a'
130 self.config.fetcher.allow_download(digest)
131 hello = reader.load_feed('Hello.xml')
132 self.config.fetcher.allow_feed_download('http://example.com:8000/Hello.xml', hello)
133 out, err = self.run_0install(['download', 'selections.xml', '--show'])
134 assert not err, err
135 assert self.config.stores.lookup_any([digest]).startswith('/fake')
136 assert 'Version: 1\n' in out
138 def testUpdate(self):
139 out, err = self.run_0install(['update'])
140 assert out.lower().startswith("usage:")
141 assert '--message' in out, out
143 # Updating a local feed with no dependencies
144 out, err = self.run_0install(['update', 'Local.xml'])
145 assert not err, err
146 assert 'No updates found' in out, out
148 # Using a remote feed for the first time
149 self.config.stores = TestStores()
150 binary_feed = reader.load_feed('Binary.xml')
151 self.config.fetcher.allow_download('sha1=123')
152 self.config.fetcher.allow_feed_download('http://foo/Binary.xml', binary_feed)
153 out, err = self.run_0install(['update', 'http://foo/Binary.xml'])
154 assert not err, err
155 assert 'Binary.xml: new -> 1.0' in out, out
157 # No updates.
158 self.config.fetcher.allow_feed_download('http://foo/Binary.xml', binary_feed)
159 out, err = self.run_0install(['update', 'http://foo/Binary.xml'])
160 assert not err, err
161 assert 'No updates found' in out, out
163 # New binary release available.
164 new_binary_feed = reader.load_feed('Binary.xml')
165 new_binary_feed.implementations['sha1=123'].version = model.parse_version('1.1')
166 self.config.fetcher.allow_feed_download('http://foo/Binary.xml', new_binary_feed)
167 out, err = self.run_0install(['update', 'http://foo/Binary.xml'])
168 assert not err, err
169 assert 'Binary.xml: 1.0 -> 1.1' in out, out
171 # Compiling from source for the first time.
172 source_feed = reader.load_feed('Source.xml')
173 compiler_feed = reader.load_feed('Compiler.xml')
174 self.config.fetcher.allow_download('sha1=234')
175 self.config.fetcher.allow_download('sha1=345')
176 self.config.fetcher.allow_feed_download('http://foo/Compiler.xml', compiler_feed)
177 self.config.fetcher.allow_feed_download('http://foo/Binary.xml', binary_feed)
178 self.config.fetcher.allow_feed_download('http://foo/Source.xml', source_feed)
179 out, err = self.run_0install(['update', 'http://foo/Binary.xml', '--source'])
180 assert not err, err
181 assert 'Binary.xml: new -> 1.0' in out, out
182 assert 'Compiler.xml: new -> 1.0' in out, out
184 # New compiler released.
185 new_compiler_feed = reader.load_feed('Compiler.xml')
186 new_compiler_feed.implementations['sha1=345'].version = model.parse_version('1.1')
187 self.config.fetcher.allow_feed_download('http://foo/Compiler.xml', new_compiler_feed)
188 self.config.fetcher.allow_feed_download('http://foo/Binary.xml', binary_feed)
189 self.config.fetcher.allow_feed_download('http://foo/Source.xml', source_feed)
190 out, err = self.run_0install(['update', 'http://foo/Binary.xml', '--source'])
191 assert not err, err
192 assert 'Compiler.xml: 1.0 -> 1.1' in out, out
194 # A dependency disappears.
195 new_source_feed = reader.load_feed('Source.xml')
196 new_source_feed.implementations['sha1=234'].requires = []
197 self.config.fetcher.allow_feed_download('http://foo/Compiler.xml', new_compiler_feed)
198 self.config.fetcher.allow_feed_download('http://foo/Binary.xml', binary_feed)
199 self.config.fetcher.allow_feed_download('http://foo/Source.xml', new_source_feed)
200 out, err = self.run_0install(['update', 'http://foo/Binary.xml', '--source'])
201 assert not err, err
202 assert 'No longer used: http://foo/Compiler.xml' in out, out
204 def testConfig(self):
205 out, err = self.run_0install(['config', '--help'])
206 assert out.lower().startswith("usage:")
207 assert '--console' in out
209 out, err = self.run_0install(['config'])
210 assert not err, err
211 assert 'full' in out, out
212 assert 'freshness = 0' in out, out
213 assert 'help_with_testing = False' in out, out
215 out, err = self.run_0install(['config', 'help_with_testing'])
216 assert out == 'False\n', out
218 file_config = policy.load_config(handler.Handler())
219 def get_value(name):
220 old_stdout = sys.stdout
221 sys.stdout = StringIO()
222 try:
223 cmd.config.handle(file_config, None, [name])
224 cmd_output = sys.stdout.getvalue()
225 finally:
226 sys.stdout = old_stdout
227 return cmd_output
229 assert get_value('freshness') == '30d\n'
230 assert get_value('network_use') == 'full\n'
231 assert get_value('help_with_testing') == 'False\n'
233 cmd.config.handle(file_config, None, ['freshness', '5m'])
234 cmd.config.handle(file_config, None, ['help_with_testing', 'True'])
235 cmd.config.handle(file_config, None, ['network_use', 'minimal'])
236 assert file_config.freshness == 5 * 60
237 assert file_config.network_use == model.network_minimal
238 assert file_config.help_with_testing == True
240 file_config2 = policy.load_config(handler.Handler())
241 assert file_config2.freshness == 5 * 60
242 assert file_config2.network_use == model.network_minimal
243 assert file_config2.help_with_testing == True
245 cmd.config.handle(file_config, None, ['help_with_testing', 'falsE'])
246 assert file_config.help_with_testing == False
248 for period in ['1s', '2d', '3.5m', '4h', '5d']:
249 secs = cmd.config.TimeInterval.parse(period)
250 assert cmd.config.TimeInterval.format(secs) == period
252 def testAddFeed(self):
253 binary_iface = self.config.iface_cache.get_interface('http://foo/Binary.xml')
255 out, err = self.run_0install(['list-feeds', binary_iface.uri])
256 assert "(no feeds)" in out, out
257 assert not err, err
259 out, err = self.run_0install(['add-feed'])
260 assert out.lower().startswith("usage:")
261 assert 'NEW-FEED' in out
263 sys.stdin = Reply('1')
264 assert binary_iface.extra_feeds == []
266 out, err = self.run_0install(['add-feed', 'Source.xml'])
267 assert not err, err
268 assert "Add as feed for 'http://foo/Binary.xml'" in out, out
269 assert len(binary_iface.extra_feeds) == 1
271 out, err = self.run_0install(['list-feeds', binary_iface.uri])
272 assert "Source.xml" in out
273 assert not err, err
275 out, err = self.run_0install(['remove-feed', 'Source.xml'])
276 assert not err, err
277 assert "Remove as feed for 'http://foo/Binary.xml'" in out, out
278 assert len(binary_iface.extra_feeds) == 0
280 source_feed = reader.load_feed('Source.xml')
281 self.config.fetcher.allow_feed_download('http://foo/Source.xml', source_feed)
282 out, err = self.run_0install(['add-feed', 'http://foo/Source.xml'])
283 assert not err, err
284 assert 'Downloading feed; please wait' in out, out
285 assert len(binary_iface.extra_feeds) == 1
287 def testImport(self):
288 out, err = self.run_0install(['import'])
289 assert out.lower().startswith("usage:")
290 assert 'FEED' in out
292 stream = file('6FCF121BE2390E0B.gpg')
293 gpg.import_key(stream)
294 stream.close()
295 sys.stdin = Reply('Y\n')
296 out, err = self.run_0install(['import', 'Hello.xml'])
297 assert not out, out
298 assert 'Trusting DE937DD411906ACF7C263B396FCF121BE2390E0B for example.com:8000' in err, out
300 def testList(self):
301 out, err = self.run_0install(['list', 'foo', 'bar'])
302 assert out.lower().startswith("usage:")
303 assert 'PATTERN' in out
305 out, err = self.run_0install(['list'])
306 assert not err, err
307 assert '' == out, repr(out)
309 self.testImport()
311 out, err = self.run_0install(['list'])
312 assert not err, err
313 assert 'http://example.com:8000/Hello.xml\n' == out, repr(out)
315 out, err = self.run_0install(['list', 'foo'])
316 assert not err, err
317 assert '' == out, repr(out)
319 out, err = self.run_0install(['list', 'hello'])
320 assert not err, err
321 assert 'http://example.com:8000/Hello.xml\n' == out, repr(out)
323 def testRun(self):
324 out, err = self.run_0install(['run'])
325 assert out.lower().startswith("usage:")
326 assert 'URI' in out, out
328 out, err = self.run_0install(['run', '--dry-run', 'runnable/Runnable.xml', '--help'])
329 assert not err, err
330 assert 'arg-for-runner' in out, out
331 assert '--help' in out, out
333 def testDigest(self):
334 hw = os.path.join(mydir, 'HelloWorld.tgz')
335 out, err = self.run_0install(['digest', '--algorithm=sha1', hw])
336 assert out == 'sha1=3ce644dc725f1d21cfcf02562c76f375944b266a\n', out
337 assert not err, err
339 out, err = self.run_0install(['digest', hw])
340 assert out == 'sha1new=290eb133e146635fe37713fd58174324a16d595f\n', out
341 assert not err, err
343 out, err = self.run_0install(['digest', hw, 'HelloWorld'])
344 assert out == 'sha1new=491678c37f77fadafbaae66b13d48d237773a68f\n', out
345 assert not err, err
347 tmp = tempfile.mkdtemp(prefix = '0install')
348 out, err = self.run_0install(['digest', tmp])
349 assert out == 'sha1new=da39a3ee5e6b4b0d3255bfef95601890afd80709\n', out
350 assert not err, err
351 os.rmdir(tmp)
353 if __name__ == '__main__':
354 unittest.main()