19
19
"""Black-box tests for bzr.
21
21
These check that it behaves properly when it's invoked through the regular
22
command-line interface. This doesn't actually run a new interpreter but
23
rather starts again from the run_bzr function.
22
command-line interface.
24
This always reinvokes bzr through a new Python interpreter, which is a
25
bit inefficient but arguably tests in a way more representative of how
26
it's normally invoked.
27
from cStringIO import StringIO
31
from bzrlib.selftest import TestCaseInTempDir, BzrTestBase
33
32
from bzrlib.branch import Branch
34
from bzrlib.clone import copy_branch
35
from bzrlib.errors import BzrCommandError
36
from bzrlib.osutils import has_symlinks
37
from bzrlib.selftest import TestCaseInTempDir, BzrTestBase
38
from bzrlib.selftest.HTTPTestUtil import TestCaseWithWebserver
33
from bzrlib.commands import run_bzr
41
36
class ExternalBase(TestCaseInTempDir):
43
def runbzr(self, args, retcode=0, backtick=False):
37
def runbzr(self, args, retcode=0,backtick=False):
44
38
if isinstance(args, basestring):
45
39
args = args.split()
48
return self.run_bzr_captured(args, retcode=retcode)[0]
42
return self.backtick(['python', self.BZRPATH,] + args,
50
return self.run_bzr_captured(args, retcode=retcode)
45
return self.runcmd(['python', self.BZRPATH,] + args,
53
49
class TestCommands(ExternalBase):
105
89
self.runbzr("add hello.txt")
106
90
self.runbzr("commit -m added")
108
def test_empty_commit_message(self):
110
file('foo.c', 'wt').write('int main() {}')
111
self.runbzr(['add', 'foo.c'])
112
self.runbzr(["commit", "-m", ""] , retcode=1)
114
92
def test_ignore_patterns(self):
115
93
from bzrlib.branch import Branch
117
b = Branch.initialize('.')
95
b = Branch('.', init=True)
118
96
self.assertEquals(list(b.unknowns()), [])
120
98
file('foo.tmp', 'wt').write('tmp files are ignored')
121
99
self.assertEquals(list(b.unknowns()), [])
122
assert self.capture('unknowns') == ''
100
assert self.backtick('bzr unknowns') == ''
124
102
file('foo.c', 'wt').write('int main() {}')
125
103
self.assertEquals(list(b.unknowns()), ['foo.c'])
126
assert self.capture('unknowns') == 'foo.c\n'
104
assert self.backtick('bzr unknowns') == 'foo.c\n'
128
106
self.runbzr(['add', 'foo.c'])
129
assert self.capture('unknowns') == ''
107
assert self.backtick('bzr unknowns') == ''
131
109
# 'ignore' works when creating the .bzignore file
132
110
file('foo.blah', 'wt').write('blah')
133
111
self.assertEquals(list(b.unknowns()), ['foo.blah'])
134
112
self.runbzr('ignore *.blah')
135
113
self.assertEquals(list(b.unknowns()), [])
136
assert file('.bzrignore', 'rU').read() == '*.blah\n'
114
assert file('.bzrignore', 'rb').read() == '*.blah\n'
138
116
# 'ignore' works when then .bzrignore file already exists
139
117
file('garh', 'wt').write('garh')
140
118
self.assertEquals(list(b.unknowns()), ['garh'])
141
assert self.capture('unknowns') == 'garh\n'
119
assert self.backtick('bzr unknowns') == 'garh\n'
142
120
self.runbzr('ignore garh')
143
121
self.assertEquals(list(b.unknowns()), [])
144
assert file('.bzrignore', 'rU').read() == '*.blah\ngarh\n'
122
assert file('.bzrignore', 'rb').read() == '*.blah\ngarh\n'
146
124
def test_revert(self):
147
126
self.runbzr('init')
149
128
file('hello', 'wt').write('foo')
168
147
os.rmdir('revertdir')
169
148
self.runbzr('revert')
171
os.symlink('/unlikely/to/exist', 'symlink')
172
self.runbzr('add symlink')
173
self.runbzr('commit -m f')
175
self.runbzr('revert')
176
self.failUnlessExists('symlink')
178
os.symlink('a-different-path', 'symlink')
179
self.runbzr('revert')
180
self.assertEqual('/unlikely/to/exist',
181
os.readlink('symlink'))
183
file('hello', 'wt').write('xyz')
184
self.runbzr('commit -m xyz hello')
185
self.runbzr('revert -r 1 hello')
186
self.check_file_contents('hello', 'foo')
187
self.runbzr('revert hello')
188
self.check_file_contents('hello', 'xyz')
189
os.chdir('revertdir')
190
self.runbzr('revert')
194
def test_mv_modes(self):
150
def skipped_test_mv_modes(self):
195
151
"""Test two modes of operation for mv"""
196
152
from bzrlib.branch import Branch
197
b = Branch.initialize('.')
153
b = Branch('.', init=True)
198
154
self.build_tree(['a', 'c', 'subdir/'])
199
self.run_bzr_captured(['add', self.test_dir])
200
self.run_bzr_captured(['mv', 'a', 'b'])
201
self.run_bzr_captured(['mv', 'b', 'subdir'])
202
self.run_bzr_captured(['mv', 'subdir/b', 'a'])
203
self.run_bzr_captured(['mv', 'a', 'c', 'subdir'])
204
self.run_bzr_captured(['mv', 'subdir/a', 'subdir/newa'])
155
self.run_bzr('mv', 'a', 'b')
156
self.run_bzr('mv', 'b', 'subdir')
157
self.run_bzr('mv', 'subdir/b', 'a')
158
self.run_bzr('mv', 'a', 'b', 'subdir')
159
self.run_bzr('mv', 'subdir/a', 'subdir/newa')
206
161
def test_main_version(self):
207
162
"""Check output from version command and master option is reasonable"""
227
182
test.runbzr('add goodbye')
228
183
test.runbzr('commit -m setup goodbye')
230
def test_export(self):
233
self.example_branch()
234
self.runbzr('export ../latest')
235
self.assertEqual(file('../latest/goodbye', 'rt').read(), 'baz')
236
self.runbzr('export ../first -r 1')
237
assert not os.path.exists('../first/goodbye')
238
self.assertEqual(file('../first/hello', 'rt').read(), 'foo')
239
self.runbzr('export ../first.gz -r 1')
240
self.assertEqual(file('../first.gz/hello', 'rt').read(), 'foo')
241
self.runbzr('export ../first.bz2 -r 1')
242
self.assertEqual(file('../first.bz2/hello', 'rt').read(), 'foo')
243
self.runbzr('export ../first.tar -r 1')
244
assert os.path.isfile('../first.tar')
245
from tarfile import TarFile
246
tf = TarFile('../first.tar')
247
assert 'first/hello' in tf.getnames(), tf.getnames()
248
self.assertEqual(tf.extractfile('first/hello').read(), 'foo')
249
self.runbzr('export ../first.tar.gz -r 1')
250
assert os.path.isfile('../first.tar.gz')
251
self.runbzr('export ../first.tbz2 -r 1')
252
assert os.path.isfile('../first.tbz2')
253
self.runbzr('export ../first.tar.bz2 -r 1')
254
assert os.path.isfile('../first.tar.bz2')
255
self.runbzr('export ../first.tar.tbz2 -r 1')
256
assert os.path.isfile('../first.tar.tbz2')
257
from bz2 import BZ2File
258
tf = TarFile('../first.tar.tbz2',
259
fileobj=BZ2File('../first.tar.tbz2', 'r'))
260
assert 'first.tar/hello' in tf.getnames(), tf.getnames()
261
self.assertEqual(tf.extractfile('first.tar/hello').read(), 'foo')
262
self.runbzr('export ../first2.tar -r 1 --root pizza')
263
tf = TarFile('../first2.tar')
264
assert 'pizza/hello' in tf.getnames(), tf.getnames()
267
self.example_branch()
268
file('hello', 'wt').write('hello world!')
269
self.runbzr('commit -m fixing hello')
270
output = self.runbzr('diff -r 2..3', backtick=1)
271
self.assert_('\n+hello world!' in output)
272
output = self.runbzr('diff -r last:3..last:1', backtick=1)
273
self.assert_('\n+baz' in output)
275
def test_diff_branches(self):
276
self.build_tree(['branch1/', 'branch1/file', 'branch2/'])
277
branch = Branch.initialize('branch1')
279
branch.commit('add file')
280
copy_branch(branch, 'branch2')
281
print >> open('branch2/file', 'w'), 'new content'
282
branch2 = Branch.open('branch2')
283
branch2.commit('update file')
284
# should open branch1 and diff against branch2,
285
output = self.run_bzr_captured(['diff', '-r', 'branch:branch2', 'branch1'])
286
self.assertEquals(("=== modified file 'file'\n"
291
"+contents of branch1/file\n"
294
def test_branch(self):
295
"""Branch from one branch to another."""
298
self.example_branch()
300
self.runbzr('branch a b')
301
self.runbzr('branch a c -r 1')
303
self.runbzr('commit -m foo --unchanged')
305
# naughty - abstraction violations RBC 20050928
306
print "test_branch used to delete the stores, how is this meant to work ?"
307
#shutil.rmtree('a/.bzr/revision-store')
308
#shutil.rmtree('a/.bzr/inventory-store', ignore_errors=True)
309
#shutil.rmtree('a/.bzr/text-store', ignore_errors=True)
310
self.runbzr('branch a d --basis b')
185
def test_revert(self):
186
self.example_branch()
187
file('hello', 'wt').write('bar')
188
file('goodbye', 'wt').write('qux')
189
self.runbzr('revert hello')
190
self.check_file_contents('hello', 'foo')
191
self.check_file_contents('goodbye', 'qux')
192
self.runbzr('revert')
193
self.check_file_contents('goodbye', 'baz')
312
195
def test_merge(self):
313
196
from bzrlib.branch import Branch
317
202
self.example_branch()
319
204
self.runbzr('branch a b')
329
214
self.runbzr('merge ../b')
330
215
self.check_file_contents('goodbye', 'quux')
331
216
# Merging a branch pulls its revision into the tree
333
b = Branch.open('../b')
334
a.get_revision_xml(b.last_revision())
219
a.get_revision_xml(b.last_patch())
335
221
self.log('pending merges: %s', a.pending_merges())
336
# assert a.pending_merges() == [b.last_revision()], "Assertion %s %s" \
222
# assert a.pending_merges() == [b.last_patch()], "Assertion %s %s" \
337
223
# % (a.pending_merges(), b.last_patch())
339
def test_merge_with_missing_file(self):
340
"""Merge handles missing file conflicts"""
344
print >> file('sub/a.txt', 'wb'), "hello"
345
print >> file('b.txt', 'wb'), "hello"
346
print >> file('sub/c.txt', 'wb'), "hello"
349
self.runbzr(('commit', '-m', 'added a'))
350
self.runbzr('branch . ../b')
351
print >> file('sub/a.txt', 'ab'), "there"
352
print >> file('b.txt', 'ab'), "there"
353
print >> file('sub/c.txt', 'ab'), "there"
354
self.runbzr(('commit', '-m', 'Added there'))
355
os.unlink('sub/a.txt')
356
os.unlink('sub/c.txt')
359
self.runbzr(('commit', '-m', 'Removed a.txt'))
361
print >> file('sub/a.txt', 'ab'), "something"
362
print >> file('b.txt', 'ab'), "something"
363
print >> file('sub/c.txt', 'ab'), "something"
364
self.runbzr(('commit', '-m', 'Modified a.txt'))
365
self.runbzr('merge ../a/')
366
assert os.path.exists('sub/a.txt.THIS')
367
assert os.path.exists('sub/a.txt.BASE')
369
self.runbzr('merge ../b/')
370
assert os.path.exists('sub/a.txt.OTHER')
371
assert os.path.exists('sub/a.txt.BASE')
374
"""Pull changes from one branch to another."""
378
self.example_branch()
379
self.runbzr('pull', retcode=1)
380
self.runbzr('missing', retcode=1)
381
self.runbzr('missing .')
382
self.runbzr('missing')
384
self.runbzr('pull /', retcode=1)
388
self.runbzr('branch a b')
392
self.runbzr('add subdir')
393
self.runbzr('commit -m blah --unchanged')
396
b = Branch.open('../b')
397
assert a.revision_history() == b.revision_history()[:-1]
398
self.runbzr('pull ../b')
399
assert a.revision_history() == b.revision_history()
400
self.runbzr('commit -m blah2 --unchanged')
402
self.runbzr('commit -m blah3 --unchanged')
403
self.runbzr('pull ../a', retcode=1)
404
print "DECIDE IF PULL CAN CONVERGE, blackbox.py"
407
self.runbzr('merge ../b')
408
self.runbzr('commit -m blah4 --unchanged')
409
os.chdir('../b/subdir')
410
self.runbzr('pull ../../a')
411
assert a.revision_history()[-1] == b.revision_history()[-1]
412
self.runbzr('commit -m blah5 --unchanged')
413
self.runbzr('commit -m blah6 --unchanged')
415
self.runbzr('pull ../a')
417
self.runbzr('commit -m blah7 --unchanged')
418
self.runbzr('merge ../b')
419
self.runbzr('commit -m blah8 --unchanged')
420
self.runbzr('pull ../b')
421
self.runbzr('pull ../b')
423
def test_locations(self):
424
"""Using and remembering different locations"""
428
self.runbzr('commit -m unchanged --unchanged')
429
self.runbzr('pull', retcode=1)
430
self.runbzr('merge', retcode=1)
431
self.runbzr('branch . ../b')
434
self.runbzr('branch . ../c')
435
self.runbzr('pull ../c')
438
self.runbzr('pull ../b')
440
self.runbzr('pull ../c')
441
self.runbzr('branch ../c ../d')
442
shutil.rmtree('../c')
447
self.runbzr('pull', retcode=1)
448
self.runbzr('pull ../a --remember')
451
226
def test_add_reports(self):
452
227
"""add command prints the names of added files."""
453
b = Branch.initialize('.')
228
b = Branch('.', init=True)
454
229
self.build_tree(['top.txt', 'dir/', 'dir/sub.txt'])
455
out = self.run_bzr_captured(['add'], retcode = 0)[0]
231
from cStringIO import StringIO
234
ret = self.apply_redirected(None, out, None,
237
self.assertEquals(ret, 0)
456
239
# the ordering is not defined at the moment
457
results = sorted(out.rstrip('\n').split('\n'))
240
results = sorted(out.getvalue().rstrip('\n').split('\n'))
458
241
self.assertEquals(['added dir',
459
'added dir'+os.sep+'sub.txt',
460
243
'added top.txt',],
463
def test_add_quiet_is(self):
464
"""add -q does not print the names of added files."""
465
b = Branch.initialize('.')
466
self.build_tree(['top.txt', 'dir/', 'dir/sub.txt'])
467
out = self.run_bzr_captured(['add', '-q'], retcode = 0)[0]
468
# the ordering is not defined at the moment
469
results = sorted(out.rstrip('\n').split('\n'))
470
self.assertEquals([''], results)
472
def test_unknown_command(self):
473
"""Handling of unknown command."""
474
out, err = self.run_bzr_captured(['fluffy-badger'],
476
self.assertEquals(out, '')
477
err.index('unknown command')
479
def test_conflicts(self):
480
"""Handling of merge conflicts"""
483
file('hello', 'wb').write("hi world")
484
file('answer', 'wb').write("42")
487
self.runbzr('commit -m base')
488
self.runbzr('branch . ../other')
489
self.runbzr('branch . ../this')
491
file('hello', 'wb').write("Hello.")
492
file('answer', 'wb').write("Is anyone there?")
493
self.runbzr('commit -m other')
495
file('hello', 'wb').write("Hello, world")
496
self.runbzr('mv answer question')
497
file('question', 'wb').write("What do you get when you multiply six"
499
self.runbzr('commit -m this')
500
self.runbzr('merge ../other')
501
result = self.runbzr('conflicts', backtick=1)
502
self.assertEquals(result, "hello\nquestion\n")
503
result = self.runbzr('status', backtick=1)
504
assert "conflicts:\n hello\n question\n" in result, result
505
self.runbzr('resolve hello')
506
result = self.runbzr('conflicts', backtick=1)
507
self.assertEquals(result, "question\n")
508
self.runbzr('commit -m conflicts', retcode=1)
509
self.runbzr('resolve --all')
510
result = self.runbzr('conflicts', backtick=1)
511
self.runbzr('commit -m conflicts')
512
self.assertEquals(result, "")
514
def listdir_sorted(dir):
520
247
class OldTests(ExternalBase):
521
248
"""old tests moved from ./testbzr."""
695
os.symlink("NOWHERE1", "link1")
697
assert self.capture('unknowns') == ''
698
runbzr(['commit', '-m', '1: added symlink link1'])
702
assert self.capture('unknowns') == ''
703
os.symlink("NOWHERE2", "d1/link2")
704
assert self.capture('unknowns') == 'd1/link2\n'
705
# is d1/link2 found when adding d1
707
assert self.capture('unknowns') == ''
708
os.symlink("NOWHERE3", "d1/link3")
709
assert self.capture('unknowns') == 'd1/link3\n'
710
runbzr(['commit', '-m', '2: added dir, symlink'])
712
runbzr('rename d1 d2')
713
runbzr('move d2/link2 .')
714
runbzr('move link1 d2')
715
assert os.readlink("./link2") == "NOWHERE2"
716
assert os.readlink("d2/link1") == "NOWHERE1"
717
runbzr('add d2/link3')
719
runbzr(['commit', '-m', '3: rename of dir, move symlinks, add link3'])
722
os.symlink("TARGET 2", "link2")
723
os.unlink("d2/link1")
724
os.symlink("TARGET 1", "d2/link1")
726
assert self.capture("relpath d2/link1") == "d2/link1\n"
727
runbzr(['commit', '-m', '4: retarget of two links'])
729
runbzr('remove d2/link1')
730
assert self.capture('unknowns') == 'd2/link1\n'
731
runbzr(['commit', '-m', '5: remove d2/link1'])
732
# try with the rm alias
733
runbzr('add d2/link1')
734
runbzr(['commit', '-m', '6: add d2/link1'])
735
runbzr('rm d2/link1')
736
assert self.capture('unknowns') == 'd2/link1\n'
737
runbzr(['commit', '-m', '7: remove d2/link1'])
741
runbzr('rename d2/link3 d1/link3new')
742
assert self.capture('unknowns') == 'd2/link1\n'
743
runbzr(['commit', '-m', '8: remove d2/link1, move/rename link3'])
747
runbzr(['export', '-r', '1', 'exp1.tmp'])
749
assert listdir_sorted(".") == [ "link1" ]
750
assert os.readlink("link1") == "NOWHERE1"
753
runbzr(['export', '-r', '2', 'exp2.tmp'])
755
assert listdir_sorted(".") == [ "d1", "link1" ]
758
runbzr(['export', '-r', '3', 'exp3.tmp'])
760
assert listdir_sorted(".") == [ "d2", "link2" ]
761
assert listdir_sorted("d2") == [ "link1", "link3" ]
762
assert os.readlink("d2/link1") == "NOWHERE1"
763
assert os.readlink("link2") == "NOWHERE2"
766
runbzr(['export', '-r', '4', 'exp4.tmp'])
768
assert listdir_sorted(".") == [ "d2", "link2" ]
769
assert os.readlink("d2/link1") == "TARGET 1"
770
assert os.readlink("link2") == "TARGET 2"
771
assert listdir_sorted("d2") == [ "link1", "link3" ]
774
runbzr(['export', '-r', '5', 'exp5.tmp'])
776
assert listdir_sorted(".") == [ "d2", "link2" ]
777
assert os.path.islink("link2")
778
assert listdir_sorted("d2")== [ "link3" ]
781
runbzr(['export', '-r', '8', 'exp6.tmp'])
783
self.assertEqual(listdir_sorted("."), [ "d1", "d2", "link2"])
784
assert listdir_sorted("d1") == [ "link3new" ]
785
assert listdir_sorted("d2") == []
786
assert os.readlink("d1/link3new") == "NOWHERE3"
789
progress("skipping symlink tests")
792
class HttpTests(TestCaseWithWebserver):
793
"""Test bzr ui commands against remote branches."""
795
def test_branch(self):
797
branch = Branch.initialize('from')
798
branch.commit('empty commit for nonsense', allow_pointless=True)
799
url = self.get_remote_url('from')
800
self.run_bzr('branch', url, 'to')
801
branch = Branch.open('to')
802
self.assertEqual(1, len(branch.revision_history()))