~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/selftest/blackbox.py

  • Committer: Aaron Bentley
  • Date: 2005-09-29 04:59:47 UTC
  • mto: (1393.1.21) (1185.14.1)
  • mto: This revision was merged to the branch mainline in revision 1396.
  • Revision ID: aaron.bentley@utoronto.ca-20050929045947-ff08a7f6578f9657
Conflict handling where OTHER is deleted

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2005 by Canonical Ltd
 
2
# -*- coding: utf-8 -*-
 
3
 
 
4
# This program is free software; you can redistribute it and/or modify
 
5
# it under the terms of the GNU General Public License as published by
 
6
# the Free Software Foundation; either version 2 of the License, or
 
7
# (at your option) any later version.
 
8
 
 
9
# This program is distributed in the hope that it will be useful,
 
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
# GNU General Public License for more details.
 
13
 
 
14
# You should have received a copy of the GNU General Public License
 
15
# along with this program; if not, write to the Free Software
 
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
17
 
 
18
 
 
19
"""Black-box tests for bzr.
 
20
 
 
21
These check that it behaves properly when it's invoked through the regular
 
22
command-line interface.
 
23
 
 
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
"""
 
28
 
 
29
from cStringIO import StringIO
 
30
import sys
 
31
import os
 
32
import shutil
 
33
 
 
34
from bzrlib.selftest import TestCaseInTempDir, BzrTestBase
 
35
from bzrlib.branch import Branch
 
36
 
 
37
 
 
38
class ExternalBase(TestCaseInTempDir):
 
39
 
 
40
    def runbzr(self, args, retcode=0, backtick=False):
 
41
        if isinstance(args, basestring):
 
42
            args = args.split()
 
43
 
 
44
        if backtick:
 
45
            return self.run_bzr_captured(args, retcode=retcode)[0]
 
46
        else:
 
47
            return self.run_bzr_captured(args, retcode=retcode)
 
48
 
 
49
 
 
50
class TestCommands(ExternalBase):
 
51
 
 
52
    def test_help_commands(self):
 
53
        self.runbzr('--help')
 
54
        self.runbzr('help')
 
55
        self.runbzr('help commands')
 
56
        self.runbzr('help help')
 
57
        self.runbzr('commit -h')
 
58
 
 
59
    def test_init_branch(self):
 
60
        self.runbzr(['init'])
 
61
 
 
62
    def test_whoami(self):
 
63
        # this should always identify something, if only "john@localhost"
 
64
        self.runbzr("whoami")
 
65
        self.runbzr("whoami --email")
 
66
 
 
67
        self.assertEquals(self.runbzr("whoami --email",
 
68
                                      backtick=True).count('@'), 1)
 
69
        
 
70
    def test_whoami_branch(self):
 
71
        """branch specific user identity works."""
 
72
        self.runbzr('init')
 
73
        f = file('.bzr/email', 'wt')
 
74
        f.write('Branch Identity <branch@identi.ty>')
 
75
        f.close()
 
76
        bzr_email = os.environ.get('BZREMAIL')
 
77
        if bzr_email is not None:
 
78
            del os.environ['BZREMAIL']
 
79
        whoami = self.runbzr("whoami",backtick=True)
 
80
        whoami_email = self.runbzr("whoami --email",backtick=True)
 
81
        self.assertTrue(whoami.startswith('Branch Identity <branch@identi.ty>'))
 
82
        self.assertTrue(whoami_email.startswith('branch@identi.ty'))
 
83
        # Verify that the environment variable overrides the value 
 
84
        # in the file
 
85
        os.environ['BZREMAIL'] = 'Different ID <other@environ.ment>'
 
86
        whoami = self.runbzr("whoami",backtick=True)
 
87
        whoami_email = self.runbzr("whoami --email",backtick=True)
 
88
        self.assertTrue(whoami.startswith('Different ID <other@environ.ment>'))
 
89
        self.assertTrue(whoami_email.startswith('other@environ.ment'))
 
90
        if bzr_email is not None:
 
91
            os.environ['BZREMAIL'] = bzr_email
 
92
 
 
93
    def test_invalid_commands(self):
 
94
        self.runbzr("pants", retcode=1)
 
95
        self.runbzr("--pants off", retcode=1)
 
96
        self.runbzr("diff --message foo", retcode=1)
 
97
 
 
98
    def test_empty_commit(self):
 
99
        self.runbzr("init")
 
100
        self.build_tree(['hello.txt'])
 
101
        self.runbzr("commit -m empty", retcode=1)
 
102
        self.runbzr("add hello.txt")
 
103
        self.runbzr("commit -m added")
 
104
 
 
105
    def test_ignore_patterns(self):
 
106
        from bzrlib.branch import Branch
 
107
        
 
108
        b = Branch.initialize('.')
 
109
        self.assertEquals(list(b.unknowns()), [])
 
110
 
 
111
        file('foo.tmp', 'wt').write('tmp files are ignored')
 
112
        self.assertEquals(list(b.unknowns()), [])
 
113
        assert self.capture('unknowns') == ''
 
114
 
 
115
        file('foo.c', 'wt').write('int main() {}')
 
116
        self.assertEquals(list(b.unknowns()), ['foo.c'])
 
117
        assert self.capture('unknowns') == 'foo.c\n'
 
118
 
 
119
        self.runbzr(['add', 'foo.c'])
 
120
        assert self.capture('unknowns') == ''
 
121
 
 
122
        # 'ignore' works when creating the .bzignore file
 
123
        file('foo.blah', 'wt').write('blah')
 
124
        self.assertEquals(list(b.unknowns()), ['foo.blah'])
 
125
        self.runbzr('ignore *.blah')
 
126
        self.assertEquals(list(b.unknowns()), [])
 
127
        assert file('.bzrignore', 'rb').read() == '*.blah\n'
 
128
 
 
129
        # 'ignore' works when then .bzrignore file already exists
 
130
        file('garh', 'wt').write('garh')
 
131
        self.assertEquals(list(b.unknowns()), ['garh'])
 
132
        assert self.capture('unknowns') == 'garh\n'
 
133
        self.runbzr('ignore garh')
 
134
        self.assertEquals(list(b.unknowns()), [])
 
135
        assert file('.bzrignore', 'rb').read() == '*.blah\ngarh\n'
 
136
 
 
137
    def test_revert(self):
 
138
        self.runbzr('init')
 
139
 
 
140
        file('hello', 'wt').write('foo')
 
141
        self.runbzr('add hello')
 
142
        self.runbzr('commit -m setup hello')
 
143
 
 
144
        file('goodbye', 'wt').write('baz')
 
145
        self.runbzr('add goodbye')
 
146
        self.runbzr('commit -m setup goodbye')
 
147
        
 
148
        file('hello', 'wt').write('bar')
 
149
        file('goodbye', 'wt').write('qux')
 
150
        self.runbzr('revert hello')
 
151
        self.check_file_contents('hello', 'foo')
 
152
        self.check_file_contents('goodbye', 'qux')
 
153
        self.runbzr('revert')
 
154
        self.check_file_contents('goodbye', 'baz')
 
155
 
 
156
        os.mkdir('revertdir')
 
157
        self.runbzr('add revertdir')
 
158
        self.runbzr('commit -m f')
 
159
        os.rmdir('revertdir')
 
160
        self.runbzr('revert')
 
161
 
 
162
        file('hello', 'wt').write('xyz')
 
163
        self.runbzr('commit -m xyz hello')
 
164
        self.runbzr('revert -r 1 hello')
 
165
        self.check_file_contents('hello', 'foo')
 
166
        self.runbzr('revert hello')
 
167
        self.check_file_contents('hello', 'xyz')
 
168
        os.chdir('revertdir')
 
169
        self.runbzr('revert')
 
170
        os.chdir('..')
 
171
 
 
172
 
 
173
    def test_mv_modes(self):
 
174
        """Test two modes of operation for mv"""
 
175
        from bzrlib.branch import Branch
 
176
        b = Branch.initialize('.')
 
177
        self.build_tree(['a', 'c', 'subdir/'])
 
178
        self.run_bzr_captured(['add', self.test_dir])
 
179
        self.run_bzr_captured(['mv', 'a', 'b'])
 
180
        self.run_bzr_captured(['mv', 'b', 'subdir'])
 
181
        self.run_bzr_captured(['mv', 'subdir/b', 'a'])
 
182
        self.run_bzr_captured(['mv', 'a', 'c', 'subdir'])
 
183
        self.run_bzr_captured(['mv', 'subdir/a', 'subdir/newa'])
 
184
 
 
185
 
 
186
    def test_main_version(self):
 
187
        """Check output from version command and master option is reasonable"""
 
188
        # output is intentionally passed through to stdout so that we
 
189
        # can see the version being tested
 
190
        output = self.runbzr('version', backtick=1)
 
191
        self.log('bzr version output:')
 
192
        self.log(output)
 
193
        self.assert_(output.startswith('bzr (bazaar-ng) '))
 
194
        self.assertNotEqual(output.index('Canonical'), -1)
 
195
        # make sure --version is consistent
 
196
        tmp_output = self.runbzr('--version', backtick=1)
 
197
        self.log('bzr --version output:')
 
198
        self.log(tmp_output)
 
199
        self.assertEquals(output, tmp_output)
 
200
 
 
201
    def example_branch(test):
 
202
        test.runbzr('init')
 
203
        file('hello', 'wt').write('foo')
 
204
        test.runbzr('add hello')
 
205
        test.runbzr('commit -m setup hello')
 
206
        file('goodbye', 'wt').write('baz')
 
207
        test.runbzr('add goodbye')
 
208
        test.runbzr('commit -m setup goodbye')
 
209
 
 
210
    def test_diff(self):
 
211
        self.example_branch()
 
212
        file('hello', 'wt').write('hello world!')
 
213
        self.runbzr('commit -m fixing hello')
 
214
        output = self.runbzr('diff -r 2..3', backtick=1)
 
215
        self.assert_('\n+hello world!' in output)
 
216
        output = self.runbzr('diff -r last:3..last:1', backtick=1)
 
217
        self.assert_('\n+baz' in output)
 
218
 
 
219
    def test_branch(self):
 
220
        """Branch from one branch to another."""
 
221
        os.mkdir('a')
 
222
        os.chdir('a')
 
223
        self.example_branch()
 
224
        os.chdir('..')
 
225
        self.runbzr('branch a b')
 
226
        self.runbzr('branch a c -r 1')
 
227
        os.chdir('b')
 
228
        self.runbzr('commit -m foo --unchanged')
 
229
        os.chdir('..')
 
230
        shutil.rmtree('a/.bzr/revision-store')
 
231
        shutil.rmtree('a/.bzr/inventory-store')
 
232
        shutil.rmtree('a/.bzr/text-store')
 
233
        self.runbzr('branch a d --basis b')
 
234
 
 
235
    def test_merge(self):
 
236
        from bzrlib.branch import Branch
 
237
        
 
238
        os.mkdir('a')
 
239
        os.chdir('a')
 
240
        self.example_branch()
 
241
        os.chdir('..')
 
242
        self.runbzr('branch a b')
 
243
        os.chdir('b')
 
244
        file('goodbye', 'wt').write('quux')
 
245
        self.runbzr(['commit',  '-m',  "more u's are always good"])
 
246
 
 
247
        os.chdir('../a')
 
248
        file('hello', 'wt').write('quuux')
 
249
        # We can't merge when there are in-tree changes
 
250
        self.runbzr('merge ../b', retcode=1)
 
251
        self.runbzr(['commit', '-m', "Like an epidemic of u's"])
 
252
        self.runbzr('merge ../b')
 
253
        self.check_file_contents('goodbye', 'quux')
 
254
        # Merging a branch pulls its revision into the tree
 
255
        a = Branch.open('.')
 
256
        b = Branch.open('../b')
 
257
        a.get_revision_xml(b.last_patch())
 
258
        self.log('pending merges: %s', a.pending_merges())
 
259
        #        assert a.pending_merges() == [b.last_patch()], "Assertion %s %s" \
 
260
        #        % (a.pending_merges(), b.last_patch())
 
261
 
 
262
    def test_merge_with_missing_file(self):
 
263
        """Merge handles missing file conflicts"""
 
264
        os.mkdir('a')
 
265
        os.chdir('a')
 
266
        os.mkdir('sub')
 
267
        print >> file('sub/a.txt', 'wb'), "hello"
 
268
        self.runbzr('init')
 
269
        self.runbzr('add')
 
270
        self.runbzr(('commit', '-m', 'added a'))
 
271
        self.runbzr('branch . ../b')
 
272
        print >> file('sub/a.txt', 'ab'), "there"
 
273
        self.runbzr(('commit', '-m', 'Added there'))
 
274
        os.unlink('sub/a.txt')
 
275
        os.rmdir('sub')
 
276
        self.runbzr(('commit', '-m', 'Removed a.txt'))
 
277
        os.chdir('../b')
 
278
        print >> file('sub/a.txt', 'ab'), "something"
 
279
        self.runbzr(('commit', '-m', 'Modified a.txt'))
 
280
        self.runbzr('merge ../a/')
 
281
        assert os.path.exists('sub/a.txt.THIS')
 
282
        assert os.path.exists('sub/a.txt.BASE')
 
283
 
 
284
    def test_pull(self):
 
285
        """Pull changes from one branch to another."""
 
286
        os.mkdir('a')
 
287
        os.chdir('a')
 
288
 
 
289
        self.example_branch()
 
290
        self.runbzr('pull', retcode=1)
 
291
        self.runbzr('missing', retcode=1)
 
292
        self.runbzr('missing .')
 
293
        self.runbzr('missing')
 
294
        self.runbzr('pull')
 
295
        self.runbzr('pull /', retcode=1)
 
296
        self.runbzr('pull')
 
297
 
 
298
        os.chdir('..')
 
299
        self.runbzr('branch a b')
 
300
        os.chdir('b')
 
301
        self.runbzr('pull')
 
302
        os.mkdir('subdir')
 
303
        self.runbzr('add subdir')
 
304
        self.runbzr('commit -m blah --unchanged')
 
305
        os.chdir('../a')
 
306
        a = Branch.open('.')
 
307
        b = Branch.open('../b')
 
308
        assert a.revision_history() == b.revision_history()[:-1]
 
309
        self.runbzr('pull ../b')
 
310
        assert a.revision_history() == b.revision_history()
 
311
        self.runbzr('commit -m blah2 --unchanged')
 
312
        os.chdir('../b')
 
313
        self.runbzr('commit -m blah3 --unchanged')
 
314
        self.runbzr('pull ../a', retcode=1)
 
315
        os.chdir('../a')
 
316
        self.runbzr('merge ../b')
 
317
        self.runbzr('commit -m blah4 --unchanged')
 
318
        os.chdir('../b/subdir')
 
319
        self.runbzr('pull ../../a')
 
320
        assert a.revision_history()[-1] == b.revision_history()[-1]
 
321
        self.runbzr('commit -m blah5 --unchanged')
 
322
        self.runbzr('commit -m blah6 --unchanged')
 
323
        os.chdir('..')
 
324
        self.runbzr('pull ../a')
 
325
        os.chdir('../a')
 
326
        self.runbzr('commit -m blah7 --unchanged')
 
327
        self.runbzr('merge ../b')
 
328
        self.runbzr('commit -m blah8 --unchanged')
 
329
        self.runbzr('pull ../b')
 
330
        self.runbzr('pull ../b')
 
331
        
 
332
    def test_add_reports(self):
 
333
        """add command prints the names of added files."""
 
334
        b = Branch.initialize('.')
 
335
        self.build_tree(['top.txt', 'dir/', 'dir/sub.txt'])
 
336
        out = self.run_bzr_captured(['add'], retcode = 0)[0]
 
337
        # the ordering is not defined at the moment
 
338
        results = sorted(out.rstrip('\n').split('\n'))
 
339
        self.assertEquals(['added dir',
 
340
                           'added dir/sub.txt',
 
341
                           'added top.txt',],
 
342
                          results)
 
343
 
 
344
    def test_unknown_command(self):
 
345
        """Handling of unknown command."""
 
346
        out, err = self.run_bzr_captured(['fluffy-badger'],
 
347
                                         retcode=1)
 
348
        self.assertEquals(out, '')
 
349
        err.index('unknown command')
 
350
        
 
351
 
 
352
 
 
353
class OldTests(ExternalBase):
 
354
    """old tests moved from ./testbzr."""
 
355
 
 
356
    def test_bzr(self):
 
357
        from os import chdir, mkdir
 
358
        from os.path import exists
 
359
 
 
360
        runbzr = self.runbzr
 
361
        capture = self.capture
 
362
        progress = self.log
 
363
 
 
364
        progress("basic branch creation")
 
365
        mkdir('branch1')
 
366
        chdir('branch1')
 
367
        runbzr('init')
 
368
 
 
369
        self.assertEquals(capture('root').rstrip(),
 
370
                          os.path.join(self.test_dir, 'branch1'))
 
371
 
 
372
        progress("status of new file")
 
373
 
 
374
        f = file('test.txt', 'wt')
 
375
        f.write('hello world!\n')
 
376
        f.close()
 
377
 
 
378
        self.assertEquals(capture('unknowns'), 'test.txt\n')
 
379
 
 
380
        out = capture("status")
 
381
        assert out == 'unknown:\n  test.txt\n'
 
382
 
 
383
        out = capture("status --all")
 
384
        assert out == "unknown:\n  test.txt\n"
 
385
 
 
386
        out = capture("status test.txt --all")
 
387
        assert out == "unknown:\n  test.txt\n"
 
388
 
 
389
        f = file('test2.txt', 'wt')
 
390
        f.write('goodbye cruel world...\n')
 
391
        f.close()
 
392
 
 
393
        out = capture("status test.txt")
 
394
        assert out == "unknown:\n  test.txt\n"
 
395
 
 
396
        out = capture("status")
 
397
        assert out == ("unknown:\n"
 
398
                       "  test.txt\n"
 
399
                       "  test2.txt\n")
 
400
 
 
401
        os.unlink('test2.txt')
 
402
 
 
403
        progress("command aliases")
 
404
        out = capture("st --all")
 
405
        assert out == ("unknown:\n"
 
406
                       "  test.txt\n")
 
407
 
 
408
        out = capture("stat")
 
409
        assert out == ("unknown:\n"
 
410
                       "  test.txt\n")
 
411
 
 
412
        progress("command help")
 
413
        runbzr("help st")
 
414
        runbzr("help")
 
415
        runbzr("help commands")
 
416
        runbzr("help slartibartfast", 1)
 
417
 
 
418
        out = capture("help ci")
 
419
        out.index('aliases: ')
 
420
 
 
421
        progress("can't rename unversioned file")
 
422
        runbzr("rename test.txt new-test.txt", 1)
 
423
 
 
424
        progress("adding a file")
 
425
 
 
426
        runbzr("add test.txt")
 
427
        assert capture("unknowns") == ''
 
428
        assert capture("status --all") == ("added:\n"
 
429
                                                "  test.txt\n")
 
430
 
 
431
        progress("rename newly-added file")
 
432
        runbzr("rename test.txt hello.txt")
 
433
        assert os.path.exists("hello.txt")
 
434
        assert not os.path.exists("test.txt")
 
435
 
 
436
        assert capture("revno") == '0\n'
 
437
 
 
438
        progress("add first revision")
 
439
        runbzr(['commit', '-m', 'add first revision'])
 
440
 
 
441
        progress("more complex renames")
 
442
        os.mkdir("sub1")
 
443
        runbzr("rename hello.txt sub1", 1)
 
444
        runbzr("rename hello.txt sub1/hello.txt", 1)
 
445
        runbzr("move hello.txt sub1", 1)
 
446
 
 
447
        runbzr("add sub1")
 
448
        runbzr("rename sub1 sub2")
 
449
        runbzr("move hello.txt sub2")
 
450
        assert capture("relpath sub2/hello.txt") == os.path.join("sub2", "hello.txt\n")
 
451
 
 
452
        assert exists("sub2")
 
453
        assert exists("sub2/hello.txt")
 
454
        assert not exists("sub1")
 
455
        assert not exists("hello.txt")
 
456
 
 
457
        runbzr(['commit', '-m', 'commit with some things moved to subdirs'])
 
458
 
 
459
        mkdir("sub1")
 
460
        runbzr('add sub1')
 
461
        runbzr('move sub2/hello.txt sub1')
 
462
        assert not exists('sub2/hello.txt')
 
463
        assert exists('sub1/hello.txt')
 
464
        runbzr('move sub2 sub1')
 
465
        assert not exists('sub2')
 
466
        assert exists('sub1/sub2')
 
467
 
 
468
        runbzr(['commit', '-m', 'rename nested subdirectories'])
 
469
 
 
470
        chdir('sub1/sub2')
 
471
        self.assertEquals(capture('root')[:-1],
 
472
                          os.path.join(self.test_dir, 'branch1'))
 
473
        runbzr('move ../hello.txt .')
 
474
        assert exists('./hello.txt')
 
475
        self.assertEquals(capture('relpath hello.txt'),
 
476
                          os.path.join('sub1', 'sub2', 'hello.txt') + '\n')
 
477
        assert capture('relpath ../../sub1/sub2/hello.txt') == os.path.join('sub1', 'sub2', 'hello.txt\n')
 
478
        runbzr(['commit', '-m', 'move to parent directory'])
 
479
        chdir('..')
 
480
        assert capture('relpath sub2/hello.txt') == os.path.join('sub1', 'sub2', 'hello.txt\n')
 
481
 
 
482
        runbzr('move sub2/hello.txt .')
 
483
        assert exists('hello.txt')
 
484
 
 
485
        f = file('hello.txt', 'wt')
 
486
        f.write('some nice new content\n')
 
487
        f.close()
 
488
 
 
489
        f = file('msg.tmp', 'wt')
 
490
        f.write('this is my new commit\n')
 
491
        f.close()
 
492
 
 
493
        runbzr('commit -F msg.tmp')
 
494
 
 
495
        assert capture('revno') == '5\n'
 
496
        runbzr('export -r 5 export-5.tmp')
 
497
        runbzr('export export.tmp')
 
498
 
 
499
        runbzr('log')
 
500
        runbzr('log -v')
 
501
        runbzr('log -v --forward')
 
502
        runbzr('log -m', retcode=1)
 
503
        log_out = capture('log -m commit')
 
504
        assert "this is my new commit" in log_out
 
505
        assert "rename nested" not in log_out
 
506
        assert 'revision-id' not in log_out
 
507
        assert 'revision-id' in capture('log --show-ids -m commit')
 
508
 
 
509
 
 
510
        progress("file with spaces in name")
 
511
        mkdir('sub directory')
 
512
        file('sub directory/file with spaces ', 'wt').write('see how this works\n')
 
513
        runbzr('add .')
 
514
        runbzr('diff')
 
515
        runbzr('commit -m add-spaces')
 
516
        runbzr('check')
 
517
 
 
518
        runbzr('log')
 
519
        runbzr('log --forward')
 
520
 
 
521
        runbzr('info')
 
522