2 from basetest
import BaseTest
, TestStores
3 import sys
, os
, tempfile
4 if sys
.version_info
[0] > 2:
5 from io
import StringIO
, BytesIO
7 from StringIO
import StringIO
11 sys
.path
.insert(0, '..')
12 from zeroinstall
import cmd
13 from zeroinstall
.injector
import model
, selections
, qdom
, reader
, handler
, gpg
, config
15 mydir
= os
.path
.dirname(__file__
)
18 def __init__(self
, reply
):
24 class TestInstall(BaseTest
):
25 def run_0install(self
, args
):
26 old_stdout
= sys
.stdout
27 old_stderr
= sys
.stderr
29 sys
.stdout
= StringIO()
30 sys
.stderr
= StringIO()
33 cmd
.main(args
, config
= self
.config
)
40 except AttributeError:
42 except AssertionError:
46 except Exception as ex2
:
49 out
= sys
.stdout
.getvalue()
50 err
= sys
.stderr
.getvalue()
52 err
+= str(ex
.__class
__)
54 sys
.stdout
= old_stdout
55 sys
.stderr
= old_stderr
59 out
, err
= self
.run_0install([])
60 assert out
.lower().startswith("usage:")
61 assert 'add-feed' in out
62 assert '--version' in out
65 out2
, err
= self
.run_0install(['--help'])
69 out
, err
= self
.run_0install(['--version'])
70 assert 'Thomas Leonard' in out
73 out
, err
= self
.run_0install(['foobar'])
74 assert 'Unknown sub-command' in err
, err
77 out
, err
= self
.run_0install(['select'])
78 assert out
.lower().startswith("usage:")
81 out
, err
= self
.run_0install(['select', 'Local.xml'])
83 assert 'Version: 0.1' in out
85 out
, err
= self
.run_0install(['select', 'Local.xml', '--command='])
87 assert 'Version: 0.1' in out
89 local_uri
= model
.canonical_iface_uri('Local.xml')
90 out
, err
= self
.run_0install(['select', 'Local.xml'])
92 assert 'Version: 0.1' in out
94 out
, err
= self
.run_0install(['select', 'Local.xml', '--xml'])
95 sels
= selections
.Selections(qdom
.parse(BytesIO(str(out
).encode('utf-8'))))
96 assert sels
.selections
[local_uri
].version
== '0.1'
98 out
, err
= self
.run_0install(['select', 'selections.xml'])
100 assert 'Version: 1\n' in out
101 assert '(not cached)' in out
103 out
, err
= self
.run_0install(['select', 'runnable/RunExec.xml'])
105 assert 'Runner' in out
, out
107 def testDownload(self
):
108 out
, err
= self
.run_0install(['download'])
109 assert out
.lower().startswith("usage:")
110 assert '--show' in out
112 out
, err
= self
.run_0install(['download', 'Local.xml', '--show'])
114 assert 'Version: 0.1' in out
116 local_uri
= model
.canonical_iface_uri('Local.xml')
117 out
, err
= self
.run_0install(['download', 'Local.xml', '--xml'])
119 sels
= selections
.Selections(qdom
.parse(BytesIO(str(out
).encode('utf-8'))))
120 assert sels
.selections
[local_uri
].version
== '0.1'
122 out
, err
= self
.run_0install(['download', 'Local.xml', '--show', '--with-store=/foo'])
124 assert self
.config
.stores
.stores
[-1].dir == '/foo'
126 out
, err
= self
.run_0install(['download', '--offline', 'selections.xml'])
127 assert 'Would download' in err
128 self
.config
.network_use
= model
.network_full
130 self
.config
.stores
= TestStores()
131 digest
= 'sha1=3ce644dc725f1d21cfcf02562c76f375944b266a'
132 self
.config
.fetcher
.allow_download(digest
)
133 out
, err
= self
.run_0install(['download', 'Hello.xml', '--show'])
135 assert self
.config
.stores
.lookup_any([digest
]).startswith('/fake')
136 assert 'Version: 1\n' in out
138 out
, err
= self
.run_0install(['download', '--offline', 'selections.xml', '--show'])
139 assert '/fake_store' in out
140 self
.config
.network_use
= model
.network_full
142 def testDownloadSelections(self
):
143 self
.config
.stores
= TestStores()
144 digest
= 'sha1=3ce644dc725f1d21cfcf02562c76f375944b266a'
145 self
.config
.fetcher
.allow_download(digest
)
146 with
open('Hello.xml') as stream
: hello
= stream
.read()
147 self
.config
.fetcher
.allow_feed_download('http://example.com:8000/Hello.xml', hello
)
148 out
, err
= self
.run_0install(['download', 'selections.xml', '--show'])
150 assert self
.config
.stores
.lookup_any([digest
]).startswith('/fake')
151 assert 'Version: 1\n' in out
153 def testUpdate(self
):
154 out
, err
= self
.run_0install(['update'])
155 assert out
.lower().startswith("usage:")
156 assert '--message' in out
, out
158 # Updating a local feed with no dependencies
159 out
, err
= self
.run_0install(['update', 'Local.xml'])
161 assert 'No updates found' in out
, out
163 # Using a remote feed for the first time
164 self
.config
.stores
= TestStores()
165 with
open('Binary.xml') as stream
: binary_feed
= stream
.read()
166 self
.config
.fetcher
.allow_download('sha1=123')
167 self
.config
.fetcher
.allow_feed_download('http://foo/Binary.xml', binary_feed
)
168 out
, err
= self
.run_0install(['update', 'http://foo/Binary.xml'])
170 assert 'Binary.xml: new -> 1.0' in out
, out
173 self
.config
.fetcher
.allow_feed_download('http://foo/Binary.xml', binary_feed
)
174 out
, err
= self
.run_0install(['update', 'http://foo/Binary.xml'])
176 assert 'No updates found' in out
, out
178 # New binary release available.
179 new_binary_feed
= binary_feed
.replace("version='1.0'", "version='1.1'")
180 assert binary_feed
!= new_binary_feed
181 self
.config
.fetcher
.allow_feed_download('http://foo/Binary.xml', new_binary_feed
)
182 out
, err
= self
.run_0install(['update', 'http://foo/Binary.xml'])
184 assert 'Binary.xml: 1.0 -> 1.1' in out
, out
186 # Compiling from source for the first time.
187 with
open('Source.xml') as stream
: source_feed
= stream
.read()
188 with
open('Compiler.xml') as stream
: compiler_feed
= stream
.read()
189 self
.config
.fetcher
.allow_download('sha1=234')
190 self
.config
.fetcher
.allow_download('sha1=345')
191 self
.config
.fetcher
.allow_feed_download('http://foo/Compiler.xml', compiler_feed
)
192 self
.config
.fetcher
.allow_feed_download('http://foo/Binary.xml', binary_feed
)
193 self
.config
.fetcher
.allow_feed_download('http://foo/Source.xml', source_feed
)
194 out
, err
= self
.run_0install(['update', 'http://foo/Binary.xml', '--source'])
196 assert 'Binary.xml: new -> 1.0' in out
, out
197 assert 'Compiler.xml: new -> 1.0' in out
, out
199 # New compiler released.
200 new_compiler_feed
= compiler_feed
.replace(
201 "id='sha1=345' version='1.0'",
202 "id='sha1=345' version='1.1'")
203 assert new_compiler_feed
!= compiler_feed
204 self
.config
.fetcher
.allow_feed_download('http://foo/Compiler.xml', new_compiler_feed
)
205 self
.config
.fetcher
.allow_feed_download('http://foo/Binary.xml', binary_feed
)
206 self
.config
.fetcher
.allow_feed_download('http://foo/Source.xml', source_feed
)
207 out
, err
= self
.run_0install(['update', 'http://foo/Binary.xml', '--source'])
209 assert 'Compiler.xml: 1.0 -> 1.1' in out
, out
211 # A dependency disappears.
212 with
open('Source-missing-req.xml') as stream
: new_source_feed
= stream
.read()
213 self
.config
.fetcher
.allow_feed_download('http://foo/Compiler.xml', new_compiler_feed
)
214 self
.config
.fetcher
.allow_feed_download('http://foo/Binary.xml', binary_feed
)
215 self
.config
.fetcher
.allow_feed_download('http://foo/Source.xml', new_source_feed
)
216 out
, err
= self
.run_0install(['update', 'http://foo/Binary.xml', '--source'])
218 assert 'No longer used: http://foo/Compiler.xml' in out
, out
220 def testConfig(self
):
221 out
, err
= self
.run_0install(['config', '--help'])
222 assert out
.lower().startswith("usage:")
223 assert '--console' in out
225 out
, err
= self
.run_0install(['config'])
227 assert 'full' in out
, out
228 assert 'freshness = 0' in out
, out
229 assert 'help_with_testing = False' in out
, out
231 out
, err
= self
.run_0install(['config', 'help_with_testing'])
232 assert out
== 'False\n', out
234 file_config
= config
.load_config(handler
.Handler())
236 old_stdout
= sys
.stdout
237 sys
.stdout
= StringIO()
239 cmd
.config
.handle(file_config
, None, [name
])
240 cmd_output
= sys
.stdout
.getvalue()
242 sys
.stdout
= old_stdout
245 assert get_value('freshness') == '30d\n'
246 assert get_value('network_use') == 'full\n'
247 assert get_value('help_with_testing') == 'False\n'
249 cmd
.config
.handle(file_config
, None, ['freshness', '5m'])
250 cmd
.config
.handle(file_config
, None, ['help_with_testing', 'True'])
251 cmd
.config
.handle(file_config
, None, ['network_use', 'minimal'])
252 assert file_config
.freshness
== 5 * 60
253 assert file_config
.network_use
== model
.network_minimal
254 assert file_config
.help_with_testing
== True
256 file_config2
= config
.load_config(handler
.Handler())
257 assert file_config2
.freshness
== 5 * 60
258 assert file_config2
.network_use
== model
.network_minimal
259 assert file_config2
.help_with_testing
== True
261 cmd
.config
.handle(file_config
, None, ['help_with_testing', 'falsE'])
262 assert file_config
.help_with_testing
== False
264 for period
in ['1s', '2d', '3.5m', '4h', '5d']:
265 secs
= cmd
.config
.TimeInterval
.parse(period
)
266 assert cmd
.config
.TimeInterval
.format(secs
) == period
268 def testAddFeed(self
):
269 binary_iface
= self
.config
.iface_cache
.get_interface('http://foo/Binary.xml')
271 out
, err
= self
.run_0install(['list-feeds', binary_iface
.uri
])
272 assert "(no feeds)" in out
, out
275 out
, err
= self
.run_0install(['add-feed'])
276 assert out
.lower().startswith("usage:")
277 assert 'NEW-FEED' in out
279 sys
.stdin
= Reply('1')
280 assert binary_iface
.extra_feeds
== []
282 out
, err
= self
.run_0install(['add-feed', 'Source.xml'])
284 assert "Add as feed for 'http://foo/Binary.xml'" in out
, out
285 assert len(binary_iface
.extra_feeds
) == 1
287 out
, err
= self
.run_0install(['list-feeds', binary_iface
.uri
])
288 assert "Source.xml" in out
291 out
, err
= self
.run_0install(['remove-feed', 'Source.xml'])
293 assert "Remove as feed for 'http://foo/Binary.xml'" in out
, out
294 assert len(binary_iface
.extra_feeds
) == 0
296 with
open('Source.xml') as stream
: source_feed
= stream
.read()
297 self
.config
.fetcher
.allow_feed_download('http://foo/Source.xml', source_feed
)
298 out
, err
= self
.run_0install(['add-feed', 'http://foo/Source.xml'])
300 assert 'Downloading feed; please wait' in out
, out
301 assert len(binary_iface
.extra_feeds
) == 1
303 def testImport(self
):
304 out
, err
= self
.run_0install(['import'])
305 assert out
.lower().startswith("usage:")
308 stream
= open('6FCF121BE2390E0B.gpg')
309 gpg
.import_key(stream
)
311 sys
.stdin
= Reply('Y\n')
312 out
, err
= self
.run_0install(['import', 'Hello.xml'])
314 assert 'Trusting DE937DD411906ACF7C263B396FCF121BE2390E0B for example.com:8000' in err
, out
317 out
, err
= self
.run_0install(['list', 'foo', 'bar'])
318 assert out
.lower().startswith("usage:")
319 assert 'PATTERN' in out
321 out
, err
= self
.run_0install(['list'])
323 assert '' == out
, repr(out
)
327 out
, err
= self
.run_0install(['list'])
329 assert 'http://example.com:8000/Hello.xml\n' == out
, repr(out
)
331 out
, err
= self
.run_0install(['list', 'foo'])
333 assert '' == out
, repr(out
)
335 out
, err
= self
.run_0install(['list', 'hello'])
337 assert 'http://example.com:8000/Hello.xml\n' == out
, repr(out
)
340 out
, err
= self
.run_0install(['run'])
341 assert out
.lower().startswith("usage:")
342 assert 'URI' in out
, out
344 out
, err
= self
.run_0install(['run', '--dry-run', 'runnable/Runnable.xml', '--help'])
346 assert 'arg-for-runner' in out
, out
347 assert '--help' in out
, out
349 def testDigest(self
):
350 hw
= os
.path
.join(mydir
, 'HelloWorld.tgz')
351 out
, err
= self
.run_0install(['digest', '--algorithm=sha1', hw
])
352 assert out
== 'sha1=3ce644dc725f1d21cfcf02562c76f375944b266a\n', out
355 out
, err
= self
.run_0install(['digest', hw
])
356 assert out
== 'sha1new=290eb133e146635fe37713fd58174324a16d595f\n', out
359 out
, err
= self
.run_0install(['digest', hw
, 'HelloWorld'])
360 assert out
== 'sha1new=491678c37f77fadafbaae66b13d48d237773a68f\n', out
363 tmp
= tempfile
.mkdtemp(prefix
= '0install')
364 out
, err
= self
.run_0install(['digest', tmp
])
365 assert out
== 'sha1new=da39a3ee5e6b4b0d3255bfef95601890afd80709\n', out
370 out
, err
= self
.run_0install(['add', 'local-app'])
371 assert out
.lower().startswith("usage:")
373 out
, err
= self
.run_0install(['destroy', 'local-app', 'uri'])
374 assert out
.lower().startswith("usage:")
376 local_feed
= os
.path
.join(mydir
, 'Local.xml')
378 out
, err
= self
.run_0install(['add', 'local:app', local_feed
])
380 assert "Invalid application name 'local:app'" in err
, err
382 out
, err
= self
.run_0install(['add', 'local-app', local_feed
])
386 out
, err
= self
.run_0install(['add', 'local-app', local_feed
])
388 assert "Application 'local-app' already exists" in err
, err
390 out
, err
= self
.run_0install(['select', 'local-app'])
391 assert "Version: 0.1" in out
, out
394 out
, err
= self
.run_0install(['update', 'local-app'])
395 assert "No updates found. Continuing with version 0.1." in out
, out
399 out
, err
= self
.run_0install(['whatchanged', 'local-app', 'uri'])
400 assert out
.lower().startswith("usage:")
402 out
, err
= self
.run_0install(['whatchanged', 'local-app'])
403 assert "No previous history to compare against." in out
, out
406 app
= self
.config
.app_mgr
.lookup_app('local-app')
407 with
open(os
.path
.join(app
.path
, "selections.xml")) as stream
:
408 old_local
= stream
.read()
409 new_local
= old_local
.replace('0.1', '0.1-pre')
410 with
open(os
.path
.join(app
.path
, "selections-2012-01-01.xml"), 'w') as stream
:
411 stream
.write(new_local
)
413 out
, err
= self
.run_0install(['whatchanged', 'local-app'])
414 assert "Local.xml: 0.1-pre -> 0.1" in out
, out
417 out
, err
= self
.run_0install(['whatchanged', 'local-app', '--full'])
418 assert "--- 2012-01-01" in out
, out
421 out
, err
= self
.run_0install(['destroy', 'local-app'])
425 out
, err
= self
.run_0install(['destroy', 'local-app'])
427 assert "No such application 'local-app'" in err
, err
429 if __name__
== '__main__':