2 from basetest
import BaseTest
, TestStores
3 import sys
, os
, tempfile
4 from StringIO
import StringIO
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__
)
14 def __init__(self
, reply
):
20 class TestInstall(BaseTest
):
21 def run_0install(self
, args
):
22 old_stdout
= sys
.stdout
23 old_stderr
= sys
.stderr
25 sys
.stdout
= StringIO()
26 sys
.stderr
= StringIO()
29 cmd
.main(args
, config
= self
.config
)
36 except AttributeError:
38 except AssertionError:
40 except Exception as ex
:
42 out
= sys
.stdout
.getvalue()
43 err
= sys
.stderr
.getvalue()
45 err
+= str(ex
.__class
__)
47 sys
.stdout
= old_stdout
48 sys
.stderr
= old_stderr
52 out
, err
= self
.run_0install([])
53 assert out
.lower().startswith("usage:")
54 assert 'add-feed' in out
55 assert '--version' in out
58 out2
, err
= self
.run_0install(['--help'])
62 out
, err
= self
.run_0install(['--version'])
63 assert 'Thomas Leonard' in out
66 out
, err
= self
.run_0install(['foobar'])
67 assert 'Unknown sub-command' in err
, err
70 out
, err
= self
.run_0install(['select'])
71 assert out
.lower().startswith("usage:")
74 out
, err
= self
.run_0install(['select', 'Local.xml'])
76 assert 'Version: 0.1' in out
78 out
, err
= self
.run_0install(['select', 'Local.xml', '--command='])
80 assert 'Version: 0.1' in out
82 local_uri
= model
.canonical_iface_uri('Local.xml')
83 out
, err
= self
.run_0install(['select', 'Local.xml'])
85 assert 'Version: 0.1' in out
87 out
, err
= self
.run_0install(['select', 'Local.xml', '--xml'])
88 sels
= selections
.Selections(qdom
.parse(StringIO(str(out
))))
89 assert sels
.selections
[local_uri
].version
== '0.1'
91 out
, err
= self
.run_0install(['select', 'selections.xml'])
93 assert 'Version: 1\n' in out
94 assert '(not cached)' in out
96 out
, err
= self
.run_0install(['select', 'runnable/RunExec.xml'])
98 assert 'Runner' in out
, out
100 def testDownload(self
):
101 out
, err
= self
.run_0install(['download'])
102 assert out
.lower().startswith("usage:")
103 assert '--show' in out
105 out
, err
= self
.run_0install(['download', 'Local.xml', '--show'])
107 assert 'Version: 0.1' in out
109 local_uri
= model
.canonical_iface_uri('Local.xml')
110 out
, err
= self
.run_0install(['download', 'Local.xml', '--xml'])
112 sels
= selections
.Selections(qdom
.parse(StringIO(str(out
))))
113 assert sels
.selections
[local_uri
].version
== '0.1'
115 out
, err
= self
.run_0install(['download', 'Local.xml', '--show', '--with-store=/foo'])
117 assert self
.config
.stores
.stores
[-1].dir == '/foo'
119 out
, err
= self
.run_0install(['download', '--offline', 'selections.xml'])
120 assert 'Would download' in err
121 self
.config
.network_use
= model
.network_full
123 self
.config
.stores
= TestStores()
124 digest
= 'sha1=3ce644dc725f1d21cfcf02562c76f375944b266a'
125 self
.config
.fetcher
.allow_download(digest
)
126 out
, err
= self
.run_0install(['download', 'Hello.xml', '--show'])
128 assert self
.config
.stores
.lookup_any([digest
]).startswith('/fake')
129 assert 'Version: 1\n' in out
131 out
, err
= self
.run_0install(['download', '--offline', 'selections.xml', '--show'])
132 assert '/fake_store' in out
133 self
.config
.network_use
= model
.network_full
135 def testDownloadSelections(self
):
136 self
.config
.stores
= TestStores()
137 digest
= 'sha1=3ce644dc725f1d21cfcf02562c76f375944b266a'
138 self
.config
.fetcher
.allow_download(digest
)
139 hello
= reader
.load_feed('Hello.xml')
140 self
.config
.fetcher
.allow_feed_download('http://example.com:8000/Hello.xml', hello
)
141 out
, err
= self
.run_0install(['download', 'selections.xml', '--show'])
143 assert self
.config
.stores
.lookup_any([digest
]).startswith('/fake')
144 assert 'Version: 1\n' in out
146 def testUpdate(self
):
147 out
, err
= self
.run_0install(['update'])
148 assert out
.lower().startswith("usage:")
149 assert '--message' in out
, out
151 # Updating a local feed with no dependencies
152 out
, err
= self
.run_0install(['update', 'Local.xml'])
154 assert 'No updates found' in out
, out
156 # Using a remote feed for the first time
157 self
.config
.stores
= TestStores()
158 binary_feed
= reader
.load_feed('Binary.xml')
159 self
.config
.fetcher
.allow_download('sha1=123')
160 self
.config
.fetcher
.allow_feed_download('http://foo/Binary.xml', binary_feed
)
161 out
, err
= self
.run_0install(['update', 'http://foo/Binary.xml'])
163 assert 'Binary.xml: new -> 1.0' in out
, out
166 self
.config
.fetcher
.allow_feed_download('http://foo/Binary.xml', binary_feed
)
167 out
, err
= self
.run_0install(['update', 'http://foo/Binary.xml'])
169 assert 'No updates found' in out
, out
171 # New binary release available.
172 new_binary_feed
= reader
.load_feed('Binary.xml')
173 new_binary_feed
.implementations
['sha1=123'].version
= model
.parse_version('1.1')
174 self
.config
.fetcher
.allow_feed_download('http://foo/Binary.xml', new_binary_feed
)
175 out
, err
= self
.run_0install(['update', 'http://foo/Binary.xml'])
177 assert 'Binary.xml: 1.0 -> 1.1' in out
, out
179 # Compiling from source for the first time.
180 source_feed
= reader
.load_feed('Source.xml')
181 compiler_feed
= reader
.load_feed('Compiler.xml')
182 self
.config
.fetcher
.allow_download('sha1=234')
183 self
.config
.fetcher
.allow_download('sha1=345')
184 self
.config
.fetcher
.allow_feed_download('http://foo/Compiler.xml', compiler_feed
)
185 self
.config
.fetcher
.allow_feed_download('http://foo/Binary.xml', binary_feed
)
186 self
.config
.fetcher
.allow_feed_download('http://foo/Source.xml', source_feed
)
187 out
, err
= self
.run_0install(['update', 'http://foo/Binary.xml', '--source'])
189 assert 'Binary.xml: new -> 1.0' in out
, out
190 assert 'Compiler.xml: new -> 1.0' in out
, out
192 # New compiler released.
193 new_compiler_feed
= reader
.load_feed('Compiler.xml')
194 new_compiler_feed
.implementations
['sha1=345'].version
= model
.parse_version('1.1')
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', source_feed
)
198 out
, err
= self
.run_0install(['update', 'http://foo/Binary.xml', '--source'])
200 assert 'Compiler.xml: 1.0 -> 1.1' in out
, out
202 # A dependency disappears.
203 new_source_feed
= reader
.load_feed('Source.xml')
204 new_source_feed
.implementations
['sha1=234'].requires
= []
205 self
.config
.fetcher
.allow_feed_download('http://foo/Compiler.xml', new_compiler_feed
)
206 self
.config
.fetcher
.allow_feed_download('http://foo/Binary.xml', binary_feed
)
207 self
.config
.fetcher
.allow_feed_download('http://foo/Source.xml', new_source_feed
)
208 out
, err
= self
.run_0install(['update', 'http://foo/Binary.xml', '--source'])
210 assert 'No longer used: http://foo/Compiler.xml' in out
, out
212 def testConfig(self
):
213 out
, err
= self
.run_0install(['config', '--help'])
214 assert out
.lower().startswith("usage:")
215 assert '--console' in out
217 out
, err
= self
.run_0install(['config'])
219 assert 'full' in out
, out
220 assert 'freshness = 0' in out
, out
221 assert 'help_with_testing = False' in out
, out
223 out
, err
= self
.run_0install(['config', 'help_with_testing'])
224 assert out
== 'False\n', out
226 file_config
= policy
.load_config(handler
.Handler())
228 old_stdout
= sys
.stdout
229 sys
.stdout
= StringIO()
231 cmd
.config
.handle(file_config
, None, [name
])
232 cmd_output
= sys
.stdout
.getvalue()
234 sys
.stdout
= old_stdout
237 assert get_value('freshness') == '30d\n'
238 assert get_value('network_use') == 'full\n'
239 assert get_value('help_with_testing') == 'False\n'
241 cmd
.config
.handle(file_config
, None, ['freshness', '5m'])
242 cmd
.config
.handle(file_config
, None, ['help_with_testing', 'True'])
243 cmd
.config
.handle(file_config
, None, ['network_use', 'minimal'])
244 assert file_config
.freshness
== 5 * 60
245 assert file_config
.network_use
== model
.network_minimal
246 assert file_config
.help_with_testing
== True
248 file_config2
= policy
.load_config(handler
.Handler())
249 assert file_config2
.freshness
== 5 * 60
250 assert file_config2
.network_use
== model
.network_minimal
251 assert file_config2
.help_with_testing
== True
253 cmd
.config
.handle(file_config
, None, ['help_with_testing', 'falsE'])
254 assert file_config
.help_with_testing
== False
256 for period
in ['1s', '2d', '3.5m', '4h', '5d']:
257 secs
= cmd
.config
.TimeInterval
.parse(period
)
258 assert cmd
.config
.TimeInterval
.format(secs
) == period
260 def testAddFeed(self
):
261 binary_iface
= self
.config
.iface_cache
.get_interface('http://foo/Binary.xml')
263 out
, err
= self
.run_0install(['list-feeds', binary_iface
.uri
])
264 assert "(no feeds)" in out
, out
267 out
, err
= self
.run_0install(['add-feed'])
268 assert out
.lower().startswith("usage:")
269 assert 'NEW-FEED' in out
271 sys
.stdin
= Reply('1')
272 assert binary_iface
.extra_feeds
== []
274 out
, err
= self
.run_0install(['add-feed', 'Source.xml'])
276 assert "Add as feed for 'http://foo/Binary.xml'" in out
, out
277 assert len(binary_iface
.extra_feeds
) == 1
279 out
, err
= self
.run_0install(['list-feeds', binary_iface
.uri
])
280 assert "Source.xml" in out
283 out
, err
= self
.run_0install(['remove-feed', 'Source.xml'])
285 assert "Remove as feed for 'http://foo/Binary.xml'" in out
, out
286 assert len(binary_iface
.extra_feeds
) == 0
288 source_feed
= reader
.load_feed('Source.xml')
289 self
.config
.fetcher
.allow_feed_download('http://foo/Source.xml', source_feed
)
290 out
, err
= self
.run_0install(['add-feed', 'http://foo/Source.xml'])
292 assert 'Downloading feed; please wait' in out
, out
293 assert len(binary_iface
.extra_feeds
) == 1
295 def testImport(self
):
296 out
, err
= self
.run_0install(['import'])
297 assert out
.lower().startswith("usage:")
300 stream
= open('6FCF121BE2390E0B.gpg')
301 gpg
.import_key(stream
)
303 sys
.stdin
= Reply('Y\n')
304 out
, err
= self
.run_0install(['import', 'Hello.xml'])
306 assert 'Trusting DE937DD411906ACF7C263B396FCF121BE2390E0B for example.com:8000' in err
, out
309 out
, err
= self
.run_0install(['list', 'foo', 'bar'])
310 assert out
.lower().startswith("usage:")
311 assert 'PATTERN' in out
313 out
, err
= self
.run_0install(['list'])
315 assert '' == out
, repr(out
)
319 out
, err
= self
.run_0install(['list'])
321 assert 'http://example.com:8000/Hello.xml\n' == out
, repr(out
)
323 out
, err
= self
.run_0install(['list', 'foo'])
325 assert '' == out
, repr(out
)
327 out
, err
= self
.run_0install(['list', 'hello'])
329 assert 'http://example.com:8000/Hello.xml\n' == out
, repr(out
)
332 out
, err
= self
.run_0install(['run'])
333 assert out
.lower().startswith("usage:")
334 assert 'URI' in out
, out
336 out
, err
= self
.run_0install(['run', '--dry-run', 'runnable/Runnable.xml', '--help'])
338 assert 'arg-for-runner' in out
, out
339 assert '--help' in out
, out
341 def testDigest(self
):
342 hw
= os
.path
.join(mydir
, 'HelloWorld.tgz')
343 out
, err
= self
.run_0install(['digest', '--algorithm=sha1', hw
])
344 assert out
== 'sha1=3ce644dc725f1d21cfcf02562c76f375944b266a\n', out
347 out
, err
= self
.run_0install(['digest', hw
])
348 assert out
== 'sha1new=290eb133e146635fe37713fd58174324a16d595f\n', out
351 out
, err
= self
.run_0install(['digest', hw
, 'HelloWorld'])
352 assert out
== 'sha1new=491678c37f77fadafbaae66b13d48d237773a68f\n', out
355 tmp
= tempfile
.mkdtemp(prefix
= '0install')
356 out
, err
= self
.run_0install(['digest', tmp
])
357 assert out
== 'sha1new=da39a3ee5e6b4b0d3255bfef95601890afd80709\n', out
362 out
, err
= self
.run_0install(['add', 'local-app'])
363 assert out
.lower().startswith("usage:")
365 out
, err
= self
.run_0install(['destroy', 'local-app', 'uri'])
366 assert out
.lower().startswith("usage:")
368 local_feed
= os
.path
.join(mydir
, 'Local.xml')
370 out
, err
= self
.run_0install(['add', 'local:app', local_feed
])
372 assert "Invalid application name 'local:app'" in err
, err
374 out
, err
= self
.run_0install(['add', 'local-app', local_feed
])
378 out
, err
= self
.run_0install(['add', 'local-app', local_feed
])
380 assert "Application 'local-app' already exists" in err
, err
382 out
, err
= self
.run_0install(['update', 'local-app'])
383 assert "No updates found. Continuing with version 0.1." in out
, out
386 out
, err
= self
.run_0install(['destroy', 'local-app'])
390 out
, err
= self
.run_0install(['destroy', 'local-app'])
392 assert "No such application 'local-app'" in err
, err
394 if __name__
== '__main__':