~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/selftest/blackbox.py

and the tutorial patch came back, the very next day

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
import sys
 
30
import os
 
31
 
 
32
from bzrlib.selftest import TestCaseInTempDir, BzrTestBase
 
33
from bzrlib.branch import Branch
 
34
from bzrlib.commands import run_bzr
 
35
 
 
36
 
 
37
class ExternalBase(TestCaseInTempDir):
 
38
    def runbzr(self, args, retcode=0,backtick=False):
 
39
        if isinstance(args, basestring):
 
40
            args = args.split()
 
41
 
 
42
        if backtick:
 
43
            return self.backtick(['python', self.BZRPATH,] + args,
 
44
                           retcode=retcode)
 
45
        else:
 
46
            return self.runcmd(['python', self.BZRPATH,] + args,
 
47
                           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
        whoami = self.runbzr("whoami",backtick=True)
 
77
        whoami_email = self.runbzr("whoami --email",backtick=True)
 
78
        self.assertTrue(whoami.startswith('Branch Identity <branch@identi.ty>'))
 
79
        self.assertTrue(whoami_email.startswith('branch@identi.ty'))
 
80
 
 
81
    def test_invalid_commands(self):
 
82
        self.runbzr("pants", retcode=1)
 
83
        self.runbzr("--pants off", retcode=1)
 
84
        self.runbzr("diff --message foo", retcode=1)
 
85
 
 
86
    def test_empty_commit(self):
 
87
        self.runbzr("init")
 
88
        self.build_tree(['hello.txt'])
 
89
        self.runbzr("commit -m empty", retcode=1)
 
90
        self.runbzr("add hello.txt")
 
91
        self.runbzr("commit -m added")
 
92
 
 
93
    def test_ignore_patterns(self):
 
94
        from bzrlib.branch import Branch
 
95
        
 
96
        b = Branch('.', init=True)
 
97
        self.assertEquals(list(b.unknowns()), [])
 
98
 
 
99
        file('foo.tmp', 'wt').write('tmp files are ignored')
 
100
        self.assertEquals(list(b.unknowns()), [])
 
101
        assert self.backtick('bzr unknowns') == ''
 
102
 
 
103
        file('foo.c', 'wt').write('int main() {}')
 
104
        self.assertEquals(list(b.unknowns()), ['foo.c'])
 
105
        assert self.backtick('bzr unknowns') == 'foo.c\n'
 
106
 
 
107
        self.runbzr(['add', 'foo.c'])
 
108
        assert self.backtick('bzr unknowns') == ''
 
109
 
 
110
        # 'ignore' works when creating the .bzignore file
 
111
        file('foo.blah', 'wt').write('blah')
 
112
        self.assertEquals(list(b.unknowns()), ['foo.blah'])
 
113
        self.runbzr('ignore *.blah')
 
114
        self.assertEquals(list(b.unknowns()), [])
 
115
        assert file('.bzrignore', 'rb').read() == '*.blah\n'
 
116
 
 
117
        # 'ignore' works when then .bzrignore file already exists
 
118
        file('garh', 'wt').write('garh')
 
119
        self.assertEquals(list(b.unknowns()), ['garh'])
 
120
        assert self.backtick('bzr unknowns') == 'garh\n'
 
121
        self.runbzr('ignore garh')
 
122
        self.assertEquals(list(b.unknowns()), [])
 
123
        assert file('.bzrignore', 'rb').read() == '*.blah\ngarh\n'
 
124
 
 
125
    def test_revert(self):
 
126
        self.runbzr('init')
 
127
 
 
128
        file('hello', 'wt').write('foo')
 
129
        self.runbzr('add hello')
 
130
        self.runbzr('commit -m setup hello')
 
131
 
 
132
        file('goodbye', 'wt').write('baz')
 
133
        self.runbzr('add goodbye')
 
134
        self.runbzr('commit -m setup goodbye')
 
135
        
 
136
        file('hello', 'wt').write('bar')
 
137
        file('goodbye', 'wt').write('qux')
 
138
        self.runbzr('revert hello')
 
139
        self.check_file_contents('hello', 'foo')
 
140
        self.check_file_contents('goodbye', 'qux')
 
141
        self.runbzr('revert')
 
142
        self.check_file_contents('goodbye', 'baz')
 
143
 
 
144
        os.mkdir('revertdir')
 
145
        self.runbzr('add revertdir')
 
146
        self.runbzr('commit -m f')
 
147
        os.rmdir('revertdir')
 
148
        self.runbzr('revert')
 
149
 
 
150
    def test_mv_modes(self):
 
151
        """Test two modes of operation for mv"""
 
152
        from bzrlib.branch import Branch
 
153
        b = Branch('.', init=True)
 
154
        self.build_tree(['a', 'c', 'subdir/'])
 
155
        self.run_bzr('add', self.test_dir)
 
156
        self.run_bzr('mv', 'a', 'b')
 
157
        self.run_bzr('mv', 'b', 'subdir')
 
158
        self.run_bzr('mv', 'subdir/b', 'a')
 
159
        self.run_bzr('mv', 'a', 'c', 'subdir')
 
160
        self.run_bzr('mv', 'subdir/a', 'subdir/newa')
 
161
 
 
162
 
 
163
    def test_main_version(self):
 
164
        """Check output from version command and master option is reasonable"""
 
165
        # output is intentionally passed through to stdout so that we
 
166
        # can see the version being tested
 
167
        output = self.runbzr('version', backtick=1)
 
168
        self.log('bzr version output:')
 
169
        self.log(output)
 
170
        self.assert_(output.startswith('bzr (bazaar-ng) '))
 
171
        self.assertNotEqual(output.index('Canonical'), -1)
 
172
        # make sure --version is consistent
 
173
        tmp_output = self.runbzr('--version', backtick=1)
 
174
        self.log('bzr --version output:')
 
175
        self.log(tmp_output)
 
176
        self.assertEquals(output, tmp_output)
 
177
 
 
178
    def example_branch(test):
 
179
        test.runbzr('init')
 
180
        file('hello', 'wt').write('foo')
 
181
        test.runbzr('add hello')
 
182
        test.runbzr('commit -m setup hello')
 
183
        file('goodbye', 'wt').write('baz')
 
184
        test.runbzr('add goodbye')
 
185
        test.runbzr('commit -m setup goodbye')
 
186
 
 
187
    def test_revert(self):
 
188
        self.example_branch()
 
189
        file('hello', 'wt').write('bar')
 
190
        file('goodbye', 'wt').write('qux')
 
191
        self.runbzr('revert hello')
 
192
        self.check_file_contents('hello', 'foo')
 
193
        self.check_file_contents('goodbye', 'qux')
 
194
        self.runbzr('revert')
 
195
        self.check_file_contents('goodbye', 'baz')
 
196
 
 
197
    def test_merge(self):
 
198
        from bzrlib.branch import Branch
 
199
        
 
200
        os.mkdir('a')
 
201
        os.chdir('a')
 
202
        self.example_branch()
 
203
        os.chdir('..')
 
204
        self.runbzr('branch a b')
 
205
        os.chdir('b')
 
206
        file('goodbye', 'wt').write('quux')
 
207
        self.runbzr(['commit',  '-m',  "more u's are always good"])
 
208
 
 
209
        os.chdir('../a')
 
210
        file('hello', 'wt').write('quuux')
 
211
        # We can't merge when there are in-tree changes
 
212
        self.runbzr('merge ../b', retcode=1)
 
213
        self.runbzr(['commit', '-m', "Like an epidemic of u's"])
 
214
        self.runbzr('merge ../b')
 
215
        self.check_file_contents('goodbye', 'quux')
 
216
        # Merging a branch pulls its revision into the tree
 
217
        a = Branch('.')
 
218
        b = Branch('../b')
 
219
        a.get_revision_xml(b.last_patch())
 
220
        self.log('pending merges: %s', a.pending_merges())
 
221
        #        assert a.pending_merges() == [b.last_patch()], "Assertion %s %s" \
 
222
        #        % (a.pending_merges(), b.last_patch())
 
223
 
 
224
    def test_pull(self):
 
225
        """Pull changes from one branch to another."""
 
226
        os.mkdir('a')
 
227
        os.chdir('a')
 
228
 
 
229
        self.example_branch()
 
230
        os.chdir('..')
 
231
        self.runbzr('branch a b')
 
232
        os.chdir('b')
 
233
        self.runbzr('commit -m blah --unchanged')
 
234
        os.chdir('../a')
 
235
        a = Branch('.')
 
236
        b = Branch('../b')
 
237
        assert a.revision_history() == b.revision_history()[:-1]
 
238
        self.runbzr('pull ../b')
 
239
        assert a.revision_history() == b.revision_history()
 
240
        self.runbzr('commit -m blah2 --unchanged')
 
241
        os.chdir('../b')
 
242
        self.runbzr('commit -m blah3 --unchanged')
 
243
        self.runbzr('pull ../a', retcode=1)
 
244
        os.chdir('../a')
 
245
        self.runbzr('merge ../b')
 
246
        self.runbzr('commit -m blah4 --unchanged')
 
247
        os.chdir('../b')
 
248
        self.runbzr('pull ../a')
 
249
        assert a.revision_history()[-1] == b.revision_history()[-1]
 
250
        
 
251
 
 
252
    def test_add_reports(self):
 
253
        """add command prints the names of added files."""
 
254
        b = Branch('.', init=True)
 
255
        self.build_tree(['top.txt', 'dir/', 'dir/sub.txt'])
 
256
 
 
257
        from cStringIO import StringIO
 
258
        out = StringIO()
 
259
 
 
260
        ret = self.apply_redirected(None, out, None,
 
261
                                    run_bzr,
 
262
                                    ['add'])
 
263
        self.assertEquals(ret, 0)
 
264
 
 
265
        # the ordering is not defined at the moment
 
266
        results = sorted(out.getvalue().rstrip('\n').split('\n'))
 
267
        self.assertEquals(['added dir',
 
268
                           'added dir/sub.txt',
 
269
                           'added top.txt',],
 
270
                          results)
 
271
 
 
272
 
 
273
class OldTests(ExternalBase):
 
274
    """old tests moved from ./testbzr."""
 
275
 
 
276
    def test_bzr(self):
 
277
        from os import chdir, mkdir
 
278
        from os.path import exists
 
279
 
 
280
        runbzr = self.runbzr
 
281
        backtick = self.backtick
 
282
        progress = self.log
 
283
 
 
284
        progress("basic branch creation")
 
285
        mkdir('branch1')
 
286
        chdir('branch1')
 
287
        runbzr('init')
 
288
 
 
289
        self.assertEquals(backtick('bzr root').rstrip(),
 
290
                          os.path.join(self.test_dir, 'branch1'))
 
291
 
 
292
        progress("status of new file")
 
293
 
 
294
        f = file('test.txt', 'wt')
 
295
        f.write('hello world!\n')
 
296
        f.close()
 
297
 
 
298
        out = backtick("bzr unknowns")
 
299
        self.assertEquals(out, 'test.txt\n')
 
300
 
 
301
        out = backtick("bzr status")
 
302
        assert out == 'unknown:\n  test.txt\n'
 
303
 
 
304
        out = backtick("bzr status --all")
 
305
        assert out == "unknown:\n  test.txt\n"
 
306
 
 
307
        out = backtick("bzr status test.txt --all")
 
308
        assert out == "unknown:\n  test.txt\n"
 
309
 
 
310
        f = file('test2.txt', 'wt')
 
311
        f.write('goodbye cruel world...\n')
 
312
        f.close()
 
313
 
 
314
        out = backtick("bzr status test.txt")
 
315
        assert out == "unknown:\n  test.txt\n"
 
316
 
 
317
        out = backtick("bzr status")
 
318
        assert out == ("unknown:\n"
 
319
                       "  test.txt\n"
 
320
                       "  test2.txt\n")
 
321
 
 
322
        os.unlink('test2.txt')
 
323
 
 
324
        progress("command aliases")
 
325
        out = backtick("bzr st --all")
 
326
        assert out == ("unknown:\n"
 
327
                       "  test.txt\n")
 
328
 
 
329
        out = backtick("bzr stat")
 
330
        assert out == ("unknown:\n"
 
331
                       "  test.txt\n")
 
332
 
 
333
        progress("command help")
 
334
        runbzr("help st")
 
335
        runbzr("help")
 
336
        runbzr("help commands")
 
337
        runbzr("help slartibartfast", 1)
 
338
 
 
339
        out = backtick("bzr help ci")
 
340
        out.index('aliases: ')
 
341
 
 
342
        progress("can't rename unversioned file")
 
343
        runbzr("rename test.txt new-test.txt", 1)
 
344
 
 
345
        progress("adding a file")
 
346
 
 
347
        runbzr("add test.txt")
 
348
        assert backtick("bzr unknowns") == ''
 
349
        assert backtick("bzr status --all") == ("added:\n"
 
350
                                                "  test.txt\n")
 
351
 
 
352
        progress("rename newly-added file")
 
353
        runbzr("rename test.txt hello.txt")
 
354
        assert os.path.exists("hello.txt")
 
355
        assert not os.path.exists("test.txt")
 
356
 
 
357
        assert backtick("bzr revno") == '0\n'
 
358
 
 
359
        progress("add first revision")
 
360
        runbzr(['commit', '-m', 'add first revision'])
 
361
 
 
362
        progress("more complex renames")
 
363
        os.mkdir("sub1")
 
364
        runbzr("rename hello.txt sub1", 1)
 
365
        runbzr("rename hello.txt sub1/hello.txt", 1)
 
366
        runbzr("move hello.txt sub1", 1)
 
367
 
 
368
        runbzr("add sub1")
 
369
        runbzr("rename sub1 sub2")
 
370
        runbzr("move hello.txt sub2")
 
371
        assert backtick("bzr relpath sub2/hello.txt") == os.path.join("sub2", "hello.txt\n")
 
372
 
 
373
        assert exists("sub2")
 
374
        assert exists("sub2/hello.txt")
 
375
        assert not exists("sub1")
 
376
        assert not exists("hello.txt")
 
377
 
 
378
        runbzr(['commit', '-m', 'commit with some things moved to subdirs'])
 
379
 
 
380
        mkdir("sub1")
 
381
        runbzr('add sub1')
 
382
        runbzr('move sub2/hello.txt sub1')
 
383
        assert not exists('sub2/hello.txt')
 
384
        assert exists('sub1/hello.txt')
 
385
        runbzr('move sub2 sub1')
 
386
        assert not exists('sub2')
 
387
        assert exists('sub1/sub2')
 
388
 
 
389
        runbzr(['commit', '-m', 'rename nested subdirectories'])
 
390
 
 
391
        chdir('sub1/sub2')
 
392
        self.assertEquals(backtick('bzr root')[:-1],
 
393
                          os.path.join(self.test_dir, 'branch1'))
 
394
        runbzr('move ../hello.txt .')
 
395
        assert exists('./hello.txt')
 
396
        assert backtick('bzr relpath hello.txt') == os.path.join('sub1', 'sub2', 'hello.txt\n')
 
397
        assert backtick('bzr relpath ../../sub1/sub2/hello.txt') == os.path.join('sub1', 'sub2', 'hello.txt\n')
 
398
        runbzr(['commit', '-m', 'move to parent directory'])
 
399
        chdir('..')
 
400
        assert backtick('bzr relpath sub2/hello.txt') == os.path.join('sub1', 'sub2', 'hello.txt\n')
 
401
 
 
402
        runbzr('move sub2/hello.txt .')
 
403
        assert exists('hello.txt')
 
404
 
 
405
        f = file('hello.txt', 'wt')
 
406
        f.write('some nice new content\n')
 
407
        f.close()
 
408
 
 
409
        f = file('msg.tmp', 'wt')
 
410
        f.write('this is my new commit\n')
 
411
        f.close()
 
412
 
 
413
        runbzr('commit -F msg.tmp')
 
414
 
 
415
        assert backtick('bzr revno') == '5\n'
 
416
        runbzr('export -r 5 export-5.tmp')
 
417
        runbzr('export export.tmp')
 
418
 
 
419
        runbzr('log')
 
420
        runbzr('log -v')
 
421
        runbzr('log -v --forward')
 
422
        runbzr('log -m', retcode=1)
 
423
        log_out = backtick('bzr log -m commit')
 
424
        assert "this is my new commit" in log_out
 
425
        assert "rename nested" not in log_out
 
426
        assert 'revision-id' not in log_out
 
427
        assert 'revision-id' in backtick('bzr log --show-ids -m commit')
 
428
 
 
429
 
 
430
        progress("file with spaces in name")
 
431
        mkdir('sub directory')
 
432
        file('sub directory/file with spaces ', 'wt').write('see how this works\n')
 
433
        runbzr('add .')
 
434
        runbzr('diff')
 
435
        runbzr('commit -m add-spaces')
 
436
        runbzr('check')
 
437
 
 
438
        runbzr('log')
 
439
        runbzr('log --forward')
 
440
 
 
441
        runbzr('info')
 
442