~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/selftest/blackbox.py

  • Committer: Martin Pool
  • Date: 2005-09-30 05:15:03 UTC
  • mto: (1185.14.2)
  • mto: This revision was merged to the branch mainline in revision 1396.
  • Revision ID: mbp@sourcefrog.net-20050930051503-9c049325215ddd1c
- fix up Branch.open_downlevel for Transport

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 os
 
31
import shutil
 
32
import sys
 
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', 'rU').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', 'rU').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
        # naughty - abstraction violations RBC 20050928  
 
231
        print "test_branch used to delete the stores, how is this meant to work ?"
 
232
        #shutil.rmtree('a/.bzr/revision-store')
 
233
        #shutil.rmtree('a/.bzr/inventory-store', ignore_errors=True)
 
234
        #shutil.rmtree('a/.bzr/text-store', ignore_errors=True)
 
235
        self.runbzr('branch a d --basis b')
 
236
 
 
237
    def test_merge(self):
 
238
        from bzrlib.branch import Branch
 
239
        
 
240
        os.mkdir('a')
 
241
        os.chdir('a')
 
242
        self.example_branch()
 
243
        os.chdir('..')
 
244
        self.runbzr('branch a b')
 
245
        os.chdir('b')
 
246
        file('goodbye', 'wt').write('quux')
 
247
        self.runbzr(['commit',  '-m',  "more u's are always good"])
 
248
 
 
249
        os.chdir('../a')
 
250
        file('hello', 'wt').write('quuux')
 
251
        # We can't merge when there are in-tree changes
 
252
        self.runbzr('merge ../b', retcode=1)
 
253
        self.runbzr(['commit', '-m', "Like an epidemic of u's"])
 
254
        self.runbzr('merge ../b')
 
255
        self.check_file_contents('goodbye', 'quux')
 
256
        # Merging a branch pulls its revision into the tree
 
257
        a = Branch.open('.')
 
258
        b = Branch.open('../b')
 
259
        a.get_revision_xml(b.last_revision())
 
260
        self.log('pending merges: %s', a.pending_merges())
 
261
        #        assert a.pending_merges() == [b.last_revision()], "Assertion %s %s" \
 
262
        #        % (a.pending_merges(), b.last_revision())
 
263
 
 
264
    def test_pull(self):
 
265
        """Pull changes from one branch to another."""
 
266
        os.mkdir('a')
 
267
        os.chdir('a')
 
268
 
 
269
        self.example_branch()
 
270
        self.runbzr('pull', retcode=1)
 
271
        self.runbzr('missing', retcode=1)
 
272
        self.runbzr('missing .')
 
273
        self.runbzr('missing')
 
274
        self.runbzr('pull')
 
275
        self.runbzr('pull /', retcode=1)
 
276
        self.runbzr('pull')
 
277
 
 
278
        os.chdir('..')
 
279
        self.runbzr('branch a b')
 
280
        os.chdir('b')
 
281
        self.runbzr('pull')
 
282
        os.mkdir('subdir')
 
283
        self.runbzr('add subdir')
 
284
        self.runbzr('commit -m blah --unchanged')
 
285
        os.chdir('../a')
 
286
        a = Branch.open('.')
 
287
        b = Branch.open('../b')
 
288
        assert a.revision_history() == b.revision_history()[:-1]
 
289
        self.runbzr('pull ../b')
 
290
        assert a.revision_history() == b.revision_history()
 
291
        self.runbzr('commit -m blah2 --unchanged')
 
292
        os.chdir('../b')
 
293
        self.runbzr('commit -m blah3 --unchanged')
 
294
        self.runbzr('pull ../a', retcode=1)
 
295
        print "DECIDE IF PULL CAN CONVERGE, blackbox.py"
 
296
        return
 
297
        os.chdir('../a')
 
298
        self.runbzr('merge ../b')
 
299
        self.runbzr('commit -m blah4 --unchanged')
 
300
        os.chdir('../b/subdir')
 
301
        self.runbzr('pull ../../a')
 
302
        assert a.revision_history()[-1] == b.revision_history()[-1]
 
303
        self.runbzr('commit -m blah5 --unchanged')
 
304
        self.runbzr('commit -m blah6 --unchanged')
 
305
        os.chdir('..')
 
306
        self.runbzr('pull ../a')
 
307
        os.chdir('../a')
 
308
        self.runbzr('commit -m blah7 --unchanged')
 
309
        self.runbzr('merge ../b')
 
310
        self.runbzr('commit -m blah8 --unchanged')
 
311
        self.runbzr('pull ../b')
 
312
        self.runbzr('pull ../b')
 
313
        
 
314
    def test_add_reports(self):
 
315
        """add command prints the names of added files."""
 
316
        b = Branch.initialize('.')
 
317
        self.build_tree(['top.txt', 'dir/', 'dir/sub.txt'])
 
318
        out = self.run_bzr_captured(['add'], retcode = 0)[0]
 
319
        # the ordering is not defined at the moment
 
320
        results = sorted(out.rstrip('\n').split('\n'))
 
321
        self.assertEquals(['added dir',
 
322
                           'added dir'+os.sep+'sub.txt',
 
323
                           'added top.txt',],
 
324
                          results)
 
325
 
 
326
    def test_unknown_command(self):
 
327
        """Handling of unknown command."""
 
328
        out, err = self.run_bzr_captured(['fluffy-badger'],
 
329
                                         retcode=1)
 
330
        self.assertEquals(out, '')
 
331
        err.index('unknown command')
 
332
        
 
333
 
 
334
 
 
335
class OldTests(ExternalBase):
 
336
    """old tests moved from ./testbzr."""
 
337
 
 
338
    def test_bzr(self):
 
339
        from os import chdir, mkdir
 
340
        from os.path import exists
 
341
 
 
342
        runbzr = self.runbzr
 
343
        capture = self.capture
 
344
        progress = self.log
 
345
 
 
346
        progress("basic branch creation")
 
347
        mkdir('branch1')
 
348
        chdir('branch1')
 
349
        runbzr('init')
 
350
 
 
351
        self.assertEquals(capture('root').rstrip(),
 
352
                          os.path.join(self.test_dir, 'branch1'))
 
353
 
 
354
        progress("status of new file")
 
355
 
 
356
        f = file('test.txt', 'wt')
 
357
        f.write('hello world!\n')
 
358
        f.close()
 
359
 
 
360
        self.assertEquals(capture('unknowns'), 'test.txt\n')
 
361
 
 
362
        out = capture("status")
 
363
        assert out == 'unknown:\n  test.txt\n'
 
364
 
 
365
        out = capture("status --all")
 
366
        assert out == "unknown:\n  test.txt\n"
 
367
 
 
368
        out = capture("status test.txt --all")
 
369
        assert out == "unknown:\n  test.txt\n"
 
370
 
 
371
        f = file('test2.txt', 'wt')
 
372
        f.write('goodbye cruel world...\n')
 
373
        f.close()
 
374
 
 
375
        out = capture("status test.txt")
 
376
        assert out == "unknown:\n  test.txt\n"
 
377
 
 
378
        out = capture("status")
 
379
        assert out == ("unknown:\n"
 
380
                       "  test.txt\n"
 
381
                       "  test2.txt\n")
 
382
 
 
383
        os.unlink('test2.txt')
 
384
 
 
385
        progress("command aliases")
 
386
        out = capture("st --all")
 
387
        assert out == ("unknown:\n"
 
388
                       "  test.txt\n")
 
389
 
 
390
        out = capture("stat")
 
391
        assert out == ("unknown:\n"
 
392
                       "  test.txt\n")
 
393
 
 
394
        progress("command help")
 
395
        runbzr("help st")
 
396
        runbzr("help")
 
397
        runbzr("help commands")
 
398
        runbzr("help slartibartfast", 1)
 
399
 
 
400
        out = capture("help ci")
 
401
        out.index('aliases: ')
 
402
 
 
403
        progress("can't rename unversioned file")
 
404
        runbzr("rename test.txt new-test.txt", 1)
 
405
 
 
406
        progress("adding a file")
 
407
 
 
408
        runbzr("add test.txt")
 
409
        assert capture("unknowns") == ''
 
410
        assert capture("status --all") == ("added:\n"
 
411
                                                "  test.txt\n")
 
412
 
 
413
        progress("rename newly-added file")
 
414
        runbzr("rename test.txt hello.txt")
 
415
        assert os.path.exists("hello.txt")
 
416
        assert not os.path.exists("test.txt")
 
417
 
 
418
        assert capture("revno") == '0\n'
 
419
 
 
420
        progress("add first revision")
 
421
        runbzr(['commit', '-m', 'add first revision'])
 
422
 
 
423
        progress("more complex renames")
 
424
        os.mkdir("sub1")
 
425
        runbzr("rename hello.txt sub1", 1)
 
426
        runbzr("rename hello.txt sub1/hello.txt", 1)
 
427
        runbzr("move hello.txt sub1", 1)
 
428
 
 
429
        runbzr("add sub1")
 
430
        runbzr("rename sub1 sub2")
 
431
        runbzr("move hello.txt sub2")
 
432
        assert capture("relpath sub2/hello.txt") == os.path.join("sub2", "hello.txt\n")
 
433
 
 
434
        assert exists("sub2")
 
435
        assert exists("sub2/hello.txt")
 
436
        assert not exists("sub1")
 
437
        assert not exists("hello.txt")
 
438
 
 
439
        runbzr(['commit', '-m', 'commit with some things moved to subdirs'])
 
440
 
 
441
        mkdir("sub1")
 
442
        runbzr('add sub1')
 
443
        runbzr('move sub2/hello.txt sub1')
 
444
        assert not exists('sub2/hello.txt')
 
445
        assert exists('sub1/hello.txt')
 
446
        runbzr('move sub2 sub1')
 
447
        assert not exists('sub2')
 
448
        assert exists('sub1/sub2')
 
449
 
 
450
        runbzr(['commit', '-m', 'rename nested subdirectories'])
 
451
 
 
452
        chdir('sub1/sub2')
 
453
        self.assertEquals(capture('root')[:-1],
 
454
                          os.path.join(self.test_dir, 'branch1'))
 
455
        runbzr('move ../hello.txt .')
 
456
        assert exists('./hello.txt')
 
457
        self.assertEquals(capture('relpath hello.txt'),
 
458
                          os.path.join('sub1', 'sub2', 'hello.txt') + '\n')
 
459
        assert capture('relpath ../../sub1/sub2/hello.txt') == os.path.join('sub1', 'sub2', 'hello.txt\n')
 
460
        runbzr(['commit', '-m', 'move to parent directory'])
 
461
        chdir('..')
 
462
        assert capture('relpath sub2/hello.txt') == os.path.join('sub1', 'sub2', 'hello.txt\n')
 
463
 
 
464
        runbzr('move sub2/hello.txt .')
 
465
        assert exists('hello.txt')
 
466
 
 
467
        f = file('hello.txt', 'wt')
 
468
        f.write('some nice new content\n')
 
469
        f.close()
 
470
 
 
471
        f = file('msg.tmp', 'wt')
 
472
        f.write('this is my new commit\n')
 
473
        f.close()
 
474
 
 
475
        runbzr('commit -F msg.tmp')
 
476
 
 
477
        assert capture('revno') == '5\n'
 
478
        runbzr('export -r 5 export-5.tmp')
 
479
        runbzr('export export.tmp')
 
480
 
 
481
        runbzr('log')
 
482
        runbzr('log -v')
 
483
        runbzr('log -v --forward')
 
484
        runbzr('log -m', retcode=1)
 
485
        log_out = capture('log -m commit')
 
486
        assert "this is my new commit" in log_out
 
487
        assert "rename nested" not in log_out
 
488
        assert 'revision-id' not in log_out
 
489
        assert 'revision-id' in capture('log --show-ids -m commit')
 
490
 
 
491
 
 
492
        progress("file with spaces in name")
 
493
        mkdir('sub directory')
 
494
        file('sub directory/file with spaces ', 'wt').write('see how this works\n')
 
495
        runbzr('add .')
 
496
        runbzr('diff')
 
497
        runbzr('commit -m add-spaces')
 
498
        runbzr('check')
 
499
 
 
500
        runbzr('log')
 
501
        runbzr('log --forward')
 
502
 
 
503
        runbzr('info')
 
504