~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/selftest/blackbox.py

  • Committer: Martin Pool
  • Date: 2005-05-03 08:00:27 UTC
  • Revision ID: mbp@sourcefrog.net-20050503080027-908edb5b39982198
doc

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