More unit-tests and bug fixes
[zeroinstall.git] / tests / testinstall.py
blobd021919e428d4e878085c081b000d0e710785cae
1 #!/usr/bin/env python
2 from basetest import BaseTest, TestStores
3 import sys, tempfile, os
4 from StringIO import StringIO
5 import unittest
7 sys.path.insert(0, '..')
8 from zeroinstall import cmd, SafeException
9 from zeroinstall.injector import model, selections, qdom, reader, policy, handler, gpg
11 class Reply:
12 def __init__(self, reply):
13 self.reply = reply
15 def readline(self):
16 return self.reply
18 class TestInstall(BaseTest):
19 def run_0install(self, args):
20 old_stdout = sys.stdout
21 old_stderr = sys.stderr
22 try:
23 sys.stdout = StringIO()
24 sys.stderr = StringIO()
25 ex = None
26 try:
27 cmd.main(args, config = self.config)
28 except NameError:
29 raise
30 except SystemExit:
31 pass
32 except TypeError:
33 raise
34 except AttributeError:
35 raise
36 except AssertionError:
37 raise
38 except Exception, ex:
39 pass
40 out = sys.stdout.getvalue()
41 err = sys.stderr.getvalue()
42 if ex is not None:
43 err += str(ex.__class__)
44 finally:
45 sys.stdout = old_stdout
46 sys.stderr = old_stderr
47 return (out, err)
49 def testHelp(self):
50 out, err = self.run_0install([])
51 assert out.lower().startswith("usage:")
52 assert 'add-feed' in out
53 assert '--version' in out
54 assert not err, err
56 out2, err = self.run_0install(['--help'])
57 assert not err, err
58 assert out2 == out
60 out, err = self.run_0install(['--version'])
61 assert 'Thomas Leonard' in out
62 assert not err, err
64 out, err = self.run_0install(['foobar'])
65 assert 'Unknown sub-command' in err, err
67 def testSelect(self):
68 out, err = self.run_0install(['select'])
69 assert out.lower().startswith("usage:")
70 assert '--xml' in out
72 out, err = self.run_0install(['select', 'Local.xml'])
73 assert not err, err
74 assert 'Version: 0.1' in out
76 local_uri = model.canonical_iface_uri('Local.xml')
77 out, err = self.run_0install(['select', 'Local.xml'])
78 assert not err, err
79 assert 'Version: 0.1' in out
81 out, err = self.run_0install(['select', 'Local.xml', '--xml'])
82 sels = selections.Selections(qdom.parse(StringIO(str(out))))
83 assert sels.selections[local_uri].version == '0.1'
85 out, err = self.run_0install(['select', 'selections.xml'])
86 assert not err, err
87 assert 'Version: 1\n' in out
88 assert '(not cached)' in out
90 def testDownload(self):
91 out, err = self.run_0install(['download'])
92 assert out.lower().startswith("usage:")
93 assert '--show' in out
95 out, err = self.run_0install(['download', 'Local.xml', '--show'])
96 assert not err, err
97 assert 'Version: 0.1' in out
99 local_uri = model.canonical_iface_uri('Local.xml')
100 out, err = self.run_0install(['download', 'Local.xml', '--xml'])
101 assert not err, err
102 sels = selections.Selections(qdom.parse(StringIO(str(out))))
103 assert sels.selections[local_uri].version == '0.1'
105 out, err = self.run_0install(['download', 'Local.xml', '--show', '--with-store=/foo'])
106 assert not err, err
107 assert self.config.stores.stores[-1].dir == '/foo'
109 out, err = self.run_0install(['download', '--offline', 'selections.xml'])
110 assert 'Would download' in err
111 self.config.network_use = model.network_full
113 self.config.stores = TestStores()
114 digest = 'sha1=3ce644dc725f1d21cfcf02562c76f375944b266a'
115 self.config.fetcher.allow_download(digest)
116 out, err = self.run_0install(['download', 'Hello.xml', '--show'])
117 assert not err, err
118 assert self.config.stores.lookup_any([digest]).startswith('/fake')
119 assert 'Version: 1\n' in out
121 out, err = self.run_0install(['download', '--offline', 'selections.xml', '--show'])
122 assert '/fake_store' in out
123 self.config.network_use = model.network_full
125 def testDownloadSelections(self):
126 self.config.stores = TestStores()
127 digest = 'sha1=3ce644dc725f1d21cfcf02562c76f375944b266a'
128 self.config.fetcher.allow_download(digest)
129 hello = reader.load_feed('Hello.xml')
130 self.config.fetcher.allow_feed_download('http://example.com:8000/Hello.xml', hello)
131 out, err = self.run_0install(['download', 'selections.xml', '--show'])
132 assert not err, err
133 assert self.config.stores.lookup_any([digest]).startswith('/fake')
134 assert 'Version: 1\n' in out
136 def testUpdate(self):
137 out, err = self.run_0install(['update'])
138 assert out.lower().startswith("usage:")
139 assert '--message' in out, out
141 # Updating a local feed with no dependencies
142 out, err = self.run_0install(['update', 'Local.xml'])
143 assert not err, err
144 assert 'No updates found' in out, out
146 # Using a remote feed for the first time
147 self.config.stores = TestStores()
148 binary_feed = reader.load_feed('Binary.xml')
149 self.config.fetcher.allow_download('sha1=123')
150 self.config.fetcher.allow_feed_download('http://foo/Binary.xml', binary_feed)
151 out, err = self.run_0install(['update', 'http://foo/Binary.xml'])
152 assert not err, err
153 assert 'Binary.xml: new -> 1.0' in out, out
155 # No updates.
156 self.config.fetcher.allow_feed_download('http://foo/Binary.xml', binary_feed)
157 out, err = self.run_0install(['update', 'http://foo/Binary.xml'])
158 assert not err, err
159 assert 'No updates found' in out, out
161 # New binary release available.
162 new_binary_feed = reader.load_feed('Binary.xml')
163 new_binary_feed.implementations['sha1=123'].version = model.parse_version('1.1')
164 self.config.fetcher.allow_feed_download('http://foo/Binary.xml', new_binary_feed)
165 out, err = self.run_0install(['update', 'http://foo/Binary.xml'])
166 assert not err, err
167 assert 'Binary.xml: 1.0 -> 1.1' in out, out
169 # Compiling from source for the first time.
170 source_feed = reader.load_feed('Source.xml')
171 compiler_feed = reader.load_feed('Compiler.xml')
172 self.config.fetcher.allow_download('sha1=234')
173 self.config.fetcher.allow_download('sha1=345')
174 self.config.fetcher.allow_feed_download('http://foo/Compiler.xml', compiler_feed)
175 self.config.fetcher.allow_feed_download('http://foo/Binary.xml', binary_feed)
176 self.config.fetcher.allow_feed_download('http://foo/Source.xml', source_feed)
177 out, err = self.run_0install(['update', 'http://foo/Binary.xml', '--source'])
178 assert not err, err
179 assert 'Binary.xml: new -> 1.0' in out, out
180 assert 'Compiler.xml: new -> 1.0' in out, out
182 # New compiler released.
183 new_compiler_feed = reader.load_feed('Compiler.xml')
184 new_compiler_feed.implementations['sha1=345'].version = model.parse_version('1.1')
185 self.config.fetcher.allow_feed_download('http://foo/Compiler.xml', new_compiler_feed)
186 self.config.fetcher.allow_feed_download('http://foo/Binary.xml', binary_feed)
187 self.config.fetcher.allow_feed_download('http://foo/Source.xml', source_feed)
188 out, err = self.run_0install(['update', 'http://foo/Binary.xml', '--source'])
189 assert not err, err
190 assert 'Compiler.xml: 1.0 -> 1.1' in out, out
192 # A dependency disappears.
193 new_source_feed = reader.load_feed('Source.xml')
194 new_source_feed.implementations['sha1=234'].requires = []
195 self.config.fetcher.allow_feed_download('http://foo/Compiler.xml', new_compiler_feed)
196 self.config.fetcher.allow_feed_download('http://foo/Binary.xml', binary_feed)
197 self.config.fetcher.allow_feed_download('http://foo/Source.xml', new_source_feed)
198 out, err = self.run_0install(['update', 'http://foo/Binary.xml', '--source'])
199 assert not err, err
200 assert 'No longer used: http://foo/Compiler.xml' in out, out
202 def testConfig(self):
203 out, err = self.run_0install(['config', '--help'])
204 assert out.lower().startswith("usage:")
205 assert '--console' in out
207 out, err = self.run_0install(['config'])
208 assert not err, err
209 assert 'full' in out, out
210 assert 'freshness = 0' in out, out
211 assert 'help_with_testing = False' in out, out
213 out, err = self.run_0install(['config', 'help_with_testing'])
214 assert out == 'False\n', out
216 file_config = policy.load_config(handler.Handler())
217 def get_value(name):
218 old_stdout = sys.stdout
219 sys.stdout = StringIO()
220 try:
221 cmd.config.handle(file_config, None, [name])
222 cmd_output = sys.stdout.getvalue()
223 finally:
224 sys.stdout = old_stdout
225 return cmd_output
227 assert get_value('freshness') == '30d\n'
228 assert get_value('network_use') == 'full\n'
229 assert get_value('help_with_testing') == 'False\n'
231 cmd.config.handle(file_config, None, ['freshness', '5m'])
232 cmd.config.handle(file_config, None, ['help_with_testing', 'True'])
233 cmd.config.handle(file_config, None, ['network_use', 'minimal'])
234 assert file_config.freshness == 5 * 60
235 assert file_config.network_use == model.network_minimal
236 assert file_config.help_with_testing == True
238 file_config2 = policy.load_config(handler.Handler())
239 assert file_config2.freshness == 5 * 60
240 assert file_config2.network_use == model.network_minimal
241 assert file_config2.help_with_testing == True
243 cmd.config.handle(file_config, None, ['help_with_testing', 'falsE'])
244 assert file_config.help_with_testing == False
246 for period in ['1s', '2d', '3.5m', '4h', '5d']:
247 secs = cmd.config.TimeInterval.parse(period)
248 assert cmd.config.TimeInterval.format(secs) == period
250 def testAddFeed(self):
251 out, err = self.run_0install(['add-feed'])
252 assert out.lower().startswith("usage:")
253 assert 'NEW-FEED' in out
255 sys.stdin = Reply('1')
256 binary_iface = self.config.iface_cache.get_interface('http://foo/Binary.xml')
257 assert binary_iface.extra_feeds == []
259 out, err = self.run_0install(['add-feed', 'Source.xml'])
260 assert not err, err
261 assert "Add as feed for 'http://foo/Binary.xml'" in out, out
262 assert len(binary_iface.extra_feeds) == 1
265 out, err = self.run_0install(['remove-feed', 'Source.xml'])
266 assert not err, err
267 assert "Remove as feed for 'http://foo/Binary.xml'" in out, out
268 assert len(binary_iface.extra_feeds) == 0
270 source_feed = reader.load_feed('Source.xml')
271 self.config.fetcher.allow_feed_download('http://foo/Source.xml', source_feed)
272 out, err = self.run_0install(['add-feed', 'http://foo/Source.xml'])
273 assert not err, err
274 assert 'Downloading feed; please wait' in out, out
275 assert len(binary_iface.extra_feeds) == 1
277 def testImport(self):
278 out, err = self.run_0install(['import'])
279 assert out.lower().startswith("usage:")
280 assert 'FEED' in out
282 stream = file('6FCF121BE2390E0B.gpg')
283 gpg.import_key(stream)
284 stream.close()
285 sys.stdin = Reply('Y\n')
286 out, err = self.run_0install(['import', 'Hello.xml'])
287 assert not out, out
288 assert 'Trusting DE937DD411906ACF7C263B396FCF121BE2390E0B for example.com:8000' in err, out
290 def testList(self):
291 out, err = self.run_0install(['list', 'foo', 'bar'])
292 assert out.lower().startswith("usage:")
293 assert 'PATTERN' in out
295 out, err = self.run_0install(['list'])
296 assert not err, err
297 assert '' == out, repr(out)
299 self.testImport()
301 out, err = self.run_0install(['list'])
302 assert not err, err
303 assert 'http://example.com:8000/Hello.xml\n' == out, repr(out)
305 out, err = self.run_0install(['list', 'foo'])
306 assert not err, err
307 assert '' == out, repr(out)
309 out, err = self.run_0install(['list', 'hello'])
310 assert not err, err
311 assert 'http://example.com:8000/Hello.xml\n' == out, repr(out)
313 def testRun(self):
314 out, err = self.run_0install(['run'])
315 assert out.lower().startswith("usage:")
316 assert 'URI' in out, out
318 out, err = self.run_0install(['run', '--dry-run', 'runnable/Runnable.xml', '--help'])
319 assert not err, err
320 assert 'arg-for-runner' in out, out
321 assert '--help' in out, out
323 if __name__ == '__main__':
324 unittest.main()