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
, handler
, gpg
, config
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:
42 except Exception as ex
:
44 out
= sys
.stdout
.getvalue()
45 err
= sys
.stderr
.getvalue()
47 err
+= str(ex
.__class
__)
49 sys
.stdout
= old_stdout
50 sys
.stderr
= old_stderr
54 out
, err
= self
.run_0install([])
55 assert out
.lower().startswith("usage:")
56 assert 'add-feed' in out
57 assert '--version' in out
60 out2
, err
= self
.run_0install(['--help'])
64 out
, err
= self
.run_0install(['--version'])
65 assert 'Thomas Leonard' in out
68 out
, err
= self
.run_0install(['foobar'])
69 assert 'Unknown sub-command' in err
, err
72 out
, err
= self
.run_0install(['select'])
73 assert out
.lower().startswith("usage:")
76 out
, err
= self
.run_0install(['select', 'Local.xml'])
78 assert 'Version: 0.1' in out
80 out
, err
= self
.run_0install(['select', 'Local.xml', '--command='])
82 assert 'Version: 0.1' in out
84 local_uri
= model
.canonical_iface_uri('Local.xml')
85 out
, err
= self
.run_0install(['select', 'Local.xml'])
87 assert 'Version: 0.1' in out
89 out
, err
= self
.run_0install(['select', 'Local.xml', '--xml'])
90 sels
= selections
.Selections(qdom
.parse(StringIO(str(out
))))
91 assert sels
.selections
[local_uri
].version
== '0.1'
93 out
, err
= self
.run_0install(['select', 'selections.xml'])
95 assert 'Version: 1\n' in out
96 assert '(not cached)' in out
98 out
, err
= self
.run_0install(['select', 'runnable/RunExec.xml'])
100 assert 'Runner' in out
, out
102 def testDownload(self
):
103 out
, err
= self
.run_0install(['download'])
104 assert out
.lower().startswith("usage:")
105 assert '--show' in out
107 out
, err
= self
.run_0install(['download', 'Local.xml', '--show'])
109 assert 'Version: 0.1' in out
111 local_uri
= model
.canonical_iface_uri('Local.xml')
112 out
, err
= self
.run_0install(['download', 'Local.xml', '--xml'])
114 sels
= selections
.Selections(qdom
.parse(StringIO(str(out
))))
115 assert sels
.selections
[local_uri
].version
== '0.1'
117 out
, err
= self
.run_0install(['download', 'Local.xml', '--show', '--with-store=/foo'])
119 assert self
.config
.stores
.stores
[-1].dir == '/foo'
121 out
, err
= self
.run_0install(['download', '--offline', 'selections.xml'])
122 assert 'Would download' in err
123 self
.config
.network_use
= model
.network_full
125 self
.config
.stores
= TestStores()
126 digest
= 'sha1=3ce644dc725f1d21cfcf02562c76f375944b266a'
127 self
.config
.fetcher
.allow_download(digest
)
128 out
, err
= self
.run_0install(['download', 'Hello.xml', '--show'])
130 assert self
.config
.stores
.lookup_any([digest
]).startswith('/fake')
131 assert 'Version: 1\n' in out
133 out
, err
= self
.run_0install(['download', '--offline', 'selections.xml', '--show'])
134 assert '/fake_store' in out
135 self
.config
.network_use
= model
.network_full
137 def testDownloadSelections(self
):
138 self
.config
.stores
= TestStores()
139 digest
= 'sha1=3ce644dc725f1d21cfcf02562c76f375944b266a'
140 self
.config
.fetcher
.allow_download(digest
)
141 with
open('Hello.xml') as stream
: hello
= stream
.read()
142 self
.config
.fetcher
.allow_feed_download('http://example.com:8000/Hello.xml', hello
)
143 out
, err
= self
.run_0install(['download', 'selections.xml', '--show'])
145 assert self
.config
.stores
.lookup_any([digest
]).startswith('/fake')
146 assert 'Version: 1\n' in out
148 def testUpdate(self
):
149 out
, err
= self
.run_0install(['update'])
150 assert out
.lower().startswith("usage:")
151 assert '--message' in out
, out
153 # Updating a local feed with no dependencies
154 out
, err
= self
.run_0install(['update', 'Local.xml'])
156 assert 'No updates found' in out
, out
158 # Using a remote feed for the first time
159 self
.config
.stores
= TestStores()
160 with
open('Binary.xml') as stream
: binary_feed
= stream
.read()
161 self
.config
.fetcher
.allow_download('sha1=123')
162 self
.config
.fetcher
.allow_feed_download('http://foo/Binary.xml', binary_feed
)
163 out
, err
= self
.run_0install(['update', 'http://foo/Binary.xml'])
165 assert 'Binary.xml: new -> 1.0' in out
, out
168 self
.config
.fetcher
.allow_feed_download('http://foo/Binary.xml', binary_feed
)
169 out
, err
= self
.run_0install(['update', 'http://foo/Binary.xml'])
171 assert 'No updates found' in out
, out
173 # New binary release available.
174 new_binary_feed
= binary_feed
.replace("version='1.0'", "version='1.1'")
175 assert binary_feed
!= new_binary_feed
176 self
.config
.fetcher
.allow_feed_download('http://foo/Binary.xml', new_binary_feed
)
177 out
, err
= self
.run_0install(['update', 'http://foo/Binary.xml'])
179 assert 'Binary.xml: 1.0 -> 1.1' in out
, out
181 # Compiling from source for the first time.
182 with
open('Source.xml') as stream
: source_feed
= stream
.read()
183 with
open('Compiler.xml') as stream
: compiler_feed
= stream
.read()
184 self
.config
.fetcher
.allow_download('sha1=234')
185 self
.config
.fetcher
.allow_download('sha1=345')
186 self
.config
.fetcher
.allow_feed_download('http://foo/Compiler.xml', compiler_feed
)
187 self
.config
.fetcher
.allow_feed_download('http://foo/Binary.xml', binary_feed
)
188 self
.config
.fetcher
.allow_feed_download('http://foo/Source.xml', source_feed
)
189 out
, err
= self
.run_0install(['update', 'http://foo/Binary.xml', '--source'])
191 assert 'Binary.xml: new -> 1.0' in out
, out
192 assert 'Compiler.xml: new -> 1.0' in out
, out
194 # New compiler released.
195 new_compiler_feed
= compiler_feed
.replace(
196 "id='sha1=345' version='1.0'",
197 "id='sha1=345' version='1.1'")
198 assert new_compiler_feed
!= compiler_feed
199 self
.config
.fetcher
.allow_feed_download('http://foo/Compiler.xml', new_compiler_feed
)
200 self
.config
.fetcher
.allow_feed_download('http://foo/Binary.xml', binary_feed
)
201 self
.config
.fetcher
.allow_feed_download('http://foo/Source.xml', source_feed
)
202 out
, err
= self
.run_0install(['update', 'http://foo/Binary.xml', '--source'])
204 assert 'Compiler.xml: 1.0 -> 1.1' in out
, out
206 # A dependency disappears.
207 with
open('Source-missing-req.xml') as stream
: new_source_feed
= stream
.read()
208 self
.config
.fetcher
.allow_feed_download('http://foo/Compiler.xml', new_compiler_feed
)
209 self
.config
.fetcher
.allow_feed_download('http://foo/Binary.xml', binary_feed
)
210 self
.config
.fetcher
.allow_feed_download('http://foo/Source.xml', new_source_feed
)
211 out
, err
= self
.run_0install(['update', 'http://foo/Binary.xml', '--source'])
213 assert 'No longer used: http://foo/Compiler.xml' in out
, out
215 def testConfig(self
):
216 out
, err
= self
.run_0install(['config', '--help'])
217 assert out
.lower().startswith("usage:")
218 assert '--console' in out
220 out
, err
= self
.run_0install(['config'])
222 assert 'full' in out
, out
223 assert 'freshness = 0' in out
, out
224 assert 'help_with_testing = False' in out
, out
226 out
, err
= self
.run_0install(['config', 'help_with_testing'])
227 assert out
== 'False\n', out
229 file_config
= config
.load_config(handler
.Handler())
231 old_stdout
= sys
.stdout
232 sys
.stdout
= StringIO()
234 cmd
.config
.handle(file_config
, None, [name
])
235 cmd_output
= sys
.stdout
.getvalue()
237 sys
.stdout
= old_stdout
240 assert get_value('freshness') == '30d\n'
241 assert get_value('network_use') == 'full\n'
242 assert get_value('help_with_testing') == 'False\n'
244 cmd
.config
.handle(file_config
, None, ['freshness', '5m'])
245 cmd
.config
.handle(file_config
, None, ['help_with_testing', 'True'])
246 cmd
.config
.handle(file_config
, None, ['network_use', 'minimal'])
247 assert file_config
.freshness
== 5 * 60
248 assert file_config
.network_use
== model
.network_minimal
249 assert file_config
.help_with_testing
== True
251 file_config2
= config
.load_config(handler
.Handler())
252 assert file_config2
.freshness
== 5 * 60
253 assert file_config2
.network_use
== model
.network_minimal
254 assert file_config2
.help_with_testing
== True
256 cmd
.config
.handle(file_config
, None, ['help_with_testing', 'falsE'])
257 assert file_config
.help_with_testing
== False
259 for period
in ['1s', '2d', '3.5m', '4h', '5d']:
260 secs
= cmd
.config
.TimeInterval
.parse(period
)
261 assert cmd
.config
.TimeInterval
.format(secs
) == period
263 def testAddFeed(self
):
264 binary_iface
= self
.config
.iface_cache
.get_interface('http://foo/Binary.xml')
266 out
, err
= self
.run_0install(['list-feeds', binary_iface
.uri
])
267 assert "(no feeds)" in out
, out
270 out
, err
= self
.run_0install(['add-feed'])
271 assert out
.lower().startswith("usage:")
272 assert 'NEW-FEED' in out
274 sys
.stdin
= Reply('1')
275 assert binary_iface
.extra_feeds
== []
277 out
, err
= self
.run_0install(['add-feed', 'Source.xml'])
279 assert "Add as feed for 'http://foo/Binary.xml'" in out
, out
280 assert len(binary_iface
.extra_feeds
) == 1
282 out
, err
= self
.run_0install(['list-feeds', binary_iface
.uri
])
283 assert "Source.xml" in out
286 out
, err
= self
.run_0install(['remove-feed', 'Source.xml'])
288 assert "Remove as feed for 'http://foo/Binary.xml'" in out
, out
289 assert len(binary_iface
.extra_feeds
) == 0
291 with
open('Source.xml') as stream
: source_feed
= stream
.read()
292 self
.config
.fetcher
.allow_feed_download('http://foo/Source.xml', source_feed
)
293 out
, err
= self
.run_0install(['add-feed', 'http://foo/Source.xml'])
295 assert 'Downloading feed; please wait' in out
, out
296 assert len(binary_iface
.extra_feeds
) == 1
298 def testImport(self
):
299 out
, err
= self
.run_0install(['import'])
300 assert out
.lower().startswith("usage:")
303 stream
= open('6FCF121BE2390E0B.gpg')
304 gpg
.import_key(stream
)
306 sys
.stdin
= Reply('Y\n')
307 out
, err
= self
.run_0install(['import', 'Hello.xml'])
309 assert 'Trusting DE937DD411906ACF7C263B396FCF121BE2390E0B for example.com:8000' in err
, out
312 out
, err
= self
.run_0install(['list', 'foo', 'bar'])
313 assert out
.lower().startswith("usage:")
314 assert 'PATTERN' in out
316 out
, err
= self
.run_0install(['list'])
318 assert '' == out
, repr(out
)
322 out
, err
= self
.run_0install(['list'])
324 assert 'http://example.com:8000/Hello.xml\n' == out
, repr(out
)
326 out
, err
= self
.run_0install(['list', 'foo'])
328 assert '' == out
, repr(out
)
330 out
, err
= self
.run_0install(['list', 'hello'])
332 assert 'http://example.com:8000/Hello.xml\n' == out
, repr(out
)
335 out
, err
= self
.run_0install(['run'])
336 assert out
.lower().startswith("usage:")
337 assert 'URI' in out
, out
339 out
, err
= self
.run_0install(['run', '--dry-run', 'runnable/Runnable.xml', '--help'])
341 assert 'arg-for-runner' in out
, out
342 assert '--help' in out
, out
344 def testDigest(self
):
345 hw
= os
.path
.join(mydir
, 'HelloWorld.tgz')
346 out
, err
= self
.run_0install(['digest', '--algorithm=sha1', hw
])
347 assert out
== 'sha1=3ce644dc725f1d21cfcf02562c76f375944b266a\n', out
350 out
, err
= self
.run_0install(['digest', hw
])
351 assert out
== 'sha1new=290eb133e146635fe37713fd58174324a16d595f\n', out
354 out
, err
= self
.run_0install(['digest', hw
, 'HelloWorld'])
355 assert out
== 'sha1new=491678c37f77fadafbaae66b13d48d237773a68f\n', out
358 tmp
= tempfile
.mkdtemp(prefix
= '0install')
359 out
, err
= self
.run_0install(['digest', tmp
])
360 assert out
== 'sha1new=da39a3ee5e6b4b0d3255bfef95601890afd80709\n', out
365 out
, err
= self
.run_0install(['add', 'local-app'])
366 assert out
.lower().startswith("usage:")
368 out
, err
= self
.run_0install(['destroy', 'local-app', 'uri'])
369 assert out
.lower().startswith("usage:")
371 local_feed
= os
.path
.join(mydir
, 'Local.xml')
373 out
, err
= self
.run_0install(['add', 'local:app', local_feed
])
375 assert "Invalid application name 'local:app'" in err
, err
377 out
, err
= self
.run_0install(['add', 'local-app', local_feed
])
381 out
, err
= self
.run_0install(['add', 'local-app', local_feed
])
383 assert "Application 'local-app' already exists" in err
, err
385 out
, err
= self
.run_0install(['select', 'local-app'])
386 assert "Version: 0.1" in out
, out
389 out
, err
= self
.run_0install(['update', 'local-app'])
390 assert "No updates found. Continuing with version 0.1." in out
, out
394 out
, err
= self
.run_0install(['whatchanged', 'local-app', 'uri'])
395 assert out
.lower().startswith("usage:")
397 out
, err
= self
.run_0install(['whatchanged', 'local-app'])
398 assert "No previous history to compare against." in out
, out
401 app
= self
.config
.app_mgr
.lookup_app('local-app')
402 with
open(os
.path
.join(app
.path
, "selections.xml")) as stream
:
403 old_local
= stream
.read()
404 new_local
= old_local
.replace('0.1', '0.1-pre')
405 with
open(os
.path
.join(app
.path
, "selections-2012-01-01.xml"), 'w') as stream
:
406 stream
.write(new_local
)
408 out
, err
= self
.run_0install(['whatchanged', 'local-app'])
409 assert "Local.xml: 0.1-pre -> 0.1" in out
, out
412 out
, err
= self
.run_0install(['whatchanged', 'local-app', '--full'])
413 assert "--- 2012-01-01" in out
, out
416 out
, err
= self
.run_0install(['destroy', 'local-app'])
420 out
, err
= self
.run_0install(['destroy', 'local-app'])
422 assert "No such application 'local-app'" in err
, err
424 if __name__
== '__main__':