/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to testbzr

  • Committer: Martin Pool
  • Date: 2005-06-21 08:35:05 UTC
  • Revision ID: mbp@sourcefrog.net-20050621083505-79259fb5ed842e4f
- move more code to run external commands from testbzr to selftest

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#! /usr/bin/python
 
2
# -*- coding: utf-8 -*-
 
3
 
 
4
# Copyright (C) 2005 Canonical Ltd
 
5
 
 
6
# This program is free software; you can redistribute it and/or modify
 
7
# it under the terms of the GNU General Public License as published by
 
8
# the Free Software Foundation; either version 2 of the License, or
 
9
# (at your option) any later version.
 
10
 
 
11
# This program is distributed in the hope that it will be useful,
 
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
# GNU General Public License for more details.
 
15
 
 
16
# You should have received a copy of the GNU General Public License
 
17
# along with this program; if not, write to the Free Software
 
18
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
19
 
 
20
 
 
21
"""External black-box test for bzr.
 
22
 
 
23
This always runs bzr as an external process to try to catch bugs
 
24
related to argument processing, startup, etc.
 
25
 
 
26
usage:
 
27
 
 
28
    testbzr [-p PYTHON] [BZR]
 
29
 
 
30
By default this tests the copy of bzr found in the same directory as
 
31
testbzr, or the first one found on the $PATH.  A copy of bzr may be
 
32
given on the command line to override this, for example when applying
 
33
a new test suite to an old copy of bzr or vice versa.
 
34
 
 
35
testbzr normally invokes bzr using the same version of python as it
 
36
would normally use to run -- that is, the system default python,
 
37
unless that is older than 2.3.  The -p option allows specification of
 
38
a different Python interpreter, such as when testing that bzr still
 
39
works on python2.3.
 
40
 
 
41
This replaces the previous test.sh which was not very portable."""
 
42
 
 
43
import sys, os, traceback
 
44
from os import mkdir
 
45
from os.path import exists
 
46
 
 
47
TESTDIR = "testbzr.tmp"
 
48
 
 
49
 
 
50
# we always invoke bzr as 'python bzr' (or e.g. 'python2.3 bzr')
 
51
# partly so as to cope if the bzr binary is not marked executable
 
52
OVERRIDE_PYTHON = 'python'
 
53
 
 
54
LOGFILENAME = 'testbzr.log'
 
55
 
 
56
try:
 
57
    import shutil
 
58
    from subprocess import call, Popen, PIPE
 
59
except ImportError, e:
 
60
    sys.stderr.write("testbzr: sorry, this test suite requires modules from python2.4\n"
 
61
                     + '    ' + str(e))
 
62
    sys.exit(1)
 
63
 
 
64
 
 
65
 
 
66
 
 
67
def formcmd(cmd):
 
68
    if isinstance(cmd, basestring):
 
69
        cmd = cmd.split()
 
70
 
 
71
    if cmd[0] == 'bzr':
 
72
        cmd[0] = BZRPATH
 
73
        if OVERRIDE_PYTHON:
 
74
            cmd.insert(0, OVERRIDE_PYTHON)
 
75
 
 
76
    logfile.write('$ %r\n' % cmd)
 
77
    
 
78
    return cmd
 
79
 
 
80
 
 
81
def runcmd(cmd, retcode=0):
 
82
    """Run one command and check the return code.
 
83
 
 
84
    Returns a tuple of (stdout,stderr) strings.
 
85
 
 
86
    If a single string is based, it is split into words.
 
87
    For commands that are not simple space-separated words, please
 
88
    pass a list instead."""
 
89
    cmd = formcmd(cmd)
 
90
    log_linenumber()
 
91
    
 
92
    actual_retcode = call(cmd, stdout=logfile, stderr=logfile)
 
93
    
 
94
    if retcode != actual_retcode:
 
95
        raise CommandFailed("test failed: %r returned %d, expected %d"
 
96
                            % (cmd, actual_retcode, retcode))
 
97
 
 
98
 
 
99
 
 
100
def backtick(cmd, retcode=0):
 
101
    cmd = formcmd(cmd)
 
102
    log_linenumber()
 
103
    child = Popen(cmd, stdout=PIPE, stderr=logfile)
 
104
    outd, errd = child.communicate()
 
105
    logfile.write(outd)
 
106
    actual_retcode = child.wait()
 
107
 
 
108
    outd = outd.replace('\r', '')
 
109
    
 
110
    if retcode != actual_retcode:
 
111
        raise CommandFailed("test failed: %r returned %d, expected %d"
 
112
                            % (cmd, actual_retcode, retcode))
 
113
 
 
114
    return outd
 
115
 
 
116
 
 
117
 
 
118
def progress(msg):
 
119
    print '* ' + msg
 
120
    logfile.write('* '+ msg + '\n')
 
121
    log_linenumber()
 
122
 
 
123
 
 
124
def cd(dirname):
 
125
    logfile.write('$ cd %s\n' % dirname)
 
126
    os.chdir(dirname)
 
127
 
 
128
 
 
129
 
 
130
def log_linenumber():
 
131
    """Log the stack frame location two things up."""
 
132
    stack = traceback.extract_stack()[-3]
 
133
    logfile.write('   at %s:%d\n' % stack[:2])
 
134
 
 
135
 
 
136
 
 
137
# prepare an empty scratch directory
 
138
if os.path.exists(TESTDIR):
 
139
    shutil.rmtree(TESTDIR)
 
140
 
 
141
start_dir = os.getcwd()
 
142
 
 
143
 
 
144
logfile = open(LOGFILENAME, 'wt', buffering=1)
 
145
 
 
146
def test_plugins():
 
147
    """Run a test involving creating a plugin to load,
 
148
    and making sure it is seen properly.
 
149
    """
 
150
    mkdir('plugin_test')
 
151
    f = open(os.path.join('plugin_test', 'myplug.py'), 'wb')
 
152
    f.write("""import bzrlib, bzrlib.commands
 
153
class cmd_myplug(bzrlib.commands.Command):
 
154
    '''Just a simple test plugin.'''
 
155
    aliases = ['mplg']
 
156
    def run(self):
 
157
        print 'Hello from my plugin'
 
158
""")
 
159
    f.close()
 
160
 
 
161
    os.environ['BZRPLUGINPATH'] = os.path.abspath('plugin_test')
 
162
    help = backtick('bzr help commands')
 
163
    assert help.find('myplug') != -1
 
164
    assert help.find('Just a simple test plugin.') != -1
 
165
 
 
166
    
 
167
    assert backtick('bzr myplug') == 'Hello from my plugin\n'
 
168
    assert backtick('bzr mplg') == 'Hello from my plugin\n'
 
169
 
 
170
    f = open(os.path.join('plugin_test', 'override.py'), 'wb')
 
171
    f.write("""import bzrlib, bzrlib.commands
 
172
class cmd_commit(bzrlib.commands.cmd_commit):
 
173
    '''Commit changes into a new revision.'''
 
174
    def run(self, *args, **kwargs):
 
175
        print "I'm sorry dave, you can't do that"
 
176
 
 
177
class cmd_help(bzrlib.commands.cmd_help):
 
178
    '''Show help on a command or other topic.'''
 
179
    def run(self, *args, **kwargs):
 
180
        print "You have been overridden"
 
181
        bzrlib.commands.cmd_help.run(self, *args, **kwargs)
 
182
 
 
183
""")
 
184
    f.close()
 
185
 
 
186
    newhelp = backtick('bzr help commands')
 
187
    assert newhelp.startswith('You have been overridden\n')
 
188
    # We added a line, but the rest should work
 
189
    assert newhelp[25:] == help
 
190
 
 
191
    assert backtick('bzr commit -m test') == "I'm sorry dave, you can't do that\n"
 
192
    
 
193
    shutil.rmtree('plugin_test')
 
194
 
 
195
try:
 
196
    from getopt import getopt
 
197
    opts, args = getopt(sys.argv[1:], 'p:')
 
198
 
 
199
    for option, value in opts:
 
200
        if option == '-p':
 
201
            OVERRIDE_PYTHON = value
 
202
            
 
203
    
 
204
    mypath = os.path.abspath(sys.argv[0])
 
205
    print '%-30s %s' % ('running tests from', mypath)
 
206
 
 
207
    global BZRPATH
 
208
 
 
209
    if args:
 
210
        BZRPATH = args[0]
 
211
    else:
 
212
        BZRPATH = os.path.join(os.path.split(mypath)[0], 'bzr')
 
213
 
 
214
    print '%-30s %s' % ('against bzr', BZRPATH)
 
215
    print '%-30s %s' % ('in directory', os.getcwd())
 
216
    print '%-30s %s' % ('with python', (OVERRIDE_PYTHON or '(default)'))
 
217
    print
 
218
    print backtick('bzr version')
 
219
    
 
220
    runcmd(['mkdir', TESTDIR])
 
221
    cd(TESTDIR)
 
222
    test_root = os.getcwd()
 
223
 
 
224
    progress("introductory commands")
 
225
    runcmd("bzr version")
 
226
    runcmd("bzr --version")
 
227
    runcmd("bzr help")
 
228
    runcmd("bzr --help")
 
229
 
 
230
    progress("internal tests")
 
231
    runcmd("bzr selftest")
 
232
 
 
233
    progress("user identity")
 
234
    # this should always identify something, if only "john@localhost"
 
235
    runcmd("bzr whoami")
 
236
    runcmd("bzr whoami --email")
 
237
    assert backtick("bzr whoami --email").count('@') == 1
 
238
 
 
239
    progress("invalid commands")
 
240
    runcmd("bzr pants", retcode=1)
 
241
    runcmd("bzr --pants off", retcode=1)
 
242
    runcmd("bzr diff --message foo", retcode=1)
 
243
 
 
244
    progress("basic branch creation")
 
245
    runcmd(['mkdir', 'branch1'])
 
246
    cd('branch1')
 
247
    runcmd('bzr init')
 
248
 
 
249
    assert backtick('bzr root')[:-1] == os.path.join(test_root, 'branch1')
 
250
 
 
251
    progress("status of new file")
 
252
    
 
253
    f = file('test.txt', 'wt')
 
254
    f.write('hello world!\n')
 
255
    f.close()
 
256
 
 
257
    out = backtick("bzr unknowns")
 
258
    assert out == 'test.txt\n'
 
259
 
 
260
    out = backtick("bzr status")
 
261
    assert out == 'unknown:\n  test.txt\n'
 
262
 
 
263
    out = backtick("bzr status --all")
 
264
    assert out == "unknown:\n  test.txt\n"
 
265
 
 
266
    out = backtick("bzr status test.txt --all")
 
267
    assert out == "unknown:\n  test.txt\n"
 
268
 
 
269
    f = file('test2.txt', 'wt')
 
270
    f.write('goodbye cruel world...\n')
 
271
    f.close()
 
272
 
 
273
    out = backtick("bzr status test.txt")
 
274
    assert out == "unknown:\n  test.txt\n"
 
275
 
 
276
    out = backtick("bzr status")
 
277
    assert out == ("unknown:\n"
 
278
                   "  test.txt\n"
 
279
                   "  test2.txt\n")
 
280
 
 
281
    os.unlink('test2.txt')
 
282
 
 
283
    progress("command aliases")
 
284
    out = backtick("bzr st --all")
 
285
    assert out == ("unknown:\n"
 
286
                   "  test.txt\n")
 
287
    
 
288
    out = backtick("bzr stat")
 
289
    assert out == ("unknown:\n"
 
290
                   "  test.txt\n")
 
291
 
 
292
    progress("command help")
 
293
    runcmd("bzr help st")
 
294
    runcmd("bzr help")
 
295
    runcmd("bzr help commands")
 
296
    runcmd("bzr help slartibartfast", 1)
 
297
 
 
298
    out = backtick("bzr help ci")
 
299
    out.index('aliases: ')
 
300
 
 
301
    progress("can't rename unversioned file")
 
302
    runcmd("bzr rename test.txt new-test.txt", 1)
 
303
 
 
304
    progress("adding a file")
 
305
 
 
306
    runcmd("bzr add test.txt")
 
307
    assert backtick("bzr unknowns") == ''
 
308
    assert backtick("bzr status --all") == ("added:\n"
 
309
                                            "  test.txt\n")
 
310
 
 
311
    progress("rename newly-added file")
 
312
    runcmd("bzr rename test.txt hello.txt")
 
313
    assert os.path.exists("hello.txt")
 
314
    assert not os.path.exists("test.txt")
 
315
 
 
316
    assert backtick("bzr revno") == '0\n'
 
317
 
 
318
    progress("add first revision")
 
319
    runcmd(["bzr", "commit", "-m", 'add first revision'])
 
320
 
 
321
    progress("more complex renames")
 
322
    os.mkdir("sub1")
 
323
    runcmd("bzr rename hello.txt sub1", 1)
 
324
    runcmd("bzr rename hello.txt sub1/hello.txt", 1)
 
325
    runcmd("bzr move hello.txt sub1", 1)
 
326
 
 
327
    runcmd("bzr add sub1")
 
328
    runcmd("bzr rename sub1 sub2")
 
329
    runcmd("bzr move hello.txt sub2")
 
330
    assert backtick("bzr relpath sub2/hello.txt") == os.path.join("sub2", "hello.txt\n")
 
331
 
 
332
    assert exists("sub2")
 
333
    assert exists("sub2/hello.txt")
 
334
    assert not exists("sub1")
 
335
    assert not exists("hello.txt")
 
336
 
 
337
    runcmd(['bzr', 'commit', '-m', 'commit with some things moved to subdirs'])
 
338
 
 
339
    mkdir("sub1")
 
340
    runcmd('bzr add sub1')
 
341
    runcmd('bzr move sub2/hello.txt sub1')
 
342
    assert not exists('sub2/hello.txt')
 
343
    assert exists('sub1/hello.txt')
 
344
    runcmd('bzr move sub2 sub1')
 
345
    assert not exists('sub2')
 
346
    assert exists('sub1/sub2')
 
347
 
 
348
    runcmd(['bzr', 'commit', '-m', 'rename nested subdirectories'])
 
349
 
 
350
    cd('sub1/sub2')
 
351
    assert backtick('bzr root')[:-1] == os.path.join(test_root, 'branch1')
 
352
    runcmd('bzr move ../hello.txt .')
 
353
    assert exists('./hello.txt')
 
354
    assert backtick('bzr relpath hello.txt') == os.path.join('sub1', 'sub2', 'hello.txt\n')
 
355
    assert backtick('bzr relpath ../../sub1/sub2/hello.txt') == os.path.join('sub1', 'sub2', 'hello.txt\n')
 
356
    runcmd(['bzr', 'commit', '-m', 'move to parent directory'])
 
357
    cd('..')
 
358
    assert backtick('bzr relpath sub2/hello.txt') == os.path.join('sub1', 'sub2', 'hello.txt\n')
 
359
 
 
360
    runcmd('bzr move sub2/hello.txt .')
 
361
    assert exists('hello.txt')
 
362
 
 
363
    f = file('hello.txt', 'wt')
 
364
    f.write('some nice new content\n')
 
365
    f.close()
 
366
 
 
367
    f = file('msg.tmp', 'wt')
 
368
    f.write('this is my new commit\n')
 
369
    f.close()
 
370
 
 
371
    runcmd('bzr commit -F msg.tmp')
 
372
 
 
373
    assert backtick('bzr revno') == '5\n'
 
374
    runcmd('bzr export -r 5 export-5.tmp')
 
375
    runcmd('bzr export export.tmp')
 
376
 
 
377
    runcmd('bzr log')
 
378
    runcmd('bzr log -v')
 
379
 
 
380
 
 
381
 
 
382
    progress("file with spaces in name")
 
383
    mkdir('sub directory')
 
384
    file('sub directory/file with spaces ', 'wt').write('see how this works\n')
 
385
    runcmd('bzr add .')
 
386
    runcmd('bzr diff')
 
387
    runcmd('bzr commit -m add-spaces')
 
388
    runcmd('bzr check')
 
389
 
 
390
    runcmd('bzr log')
 
391
    runcmd('bzr log --forward')
 
392
 
 
393
    runcmd('bzr info')
 
394
 
 
395
 
 
396
    
 
397
 
 
398
 
 
399
 
 
400
    cd('..')
 
401
    cd('..')
 
402
    progress('branch')
 
403
    # Can't create a branch if it already exists
 
404
    runcmd('bzr branch branch1', retcode=1)
 
405
    # Can't create a branch if its parent doesn't exist
 
406
    runcmd('bzr branch /unlikely/to/exist', retcode=1)
 
407
    runcmd('bzr branch branch1 branch2')
 
408
 
 
409
    progress("pull")
 
410
    cd('branch1')
 
411
    runcmd('bzr pull', retcode=1)
 
412
    runcmd('bzr pull ../branch2')
 
413
    cd('.bzr')
 
414
    runcmd('bzr pull')
 
415
    runcmd('bzr commit -m empty')
 
416
    runcmd('bzr pull')
 
417
    cd('../../branch2')
 
418
    runcmd('bzr pull')
 
419
    runcmd('bzr commit -m empty')
 
420
    cd('../branch1')
 
421
    runcmd('bzr commit -m empty')
 
422
    runcmd('bzr pull', retcode=1)
 
423
    cd ('..')
 
424
 
 
425
    progress('status after remove')
 
426
    mkdir('status-after-remove')
 
427
    # see mail from William Dodé, 2005-05-25
 
428
    # $ bzr init; touch a; bzr add a; bzr commit -m "add a"
 
429
    #     * looking for changes...
 
430
    #     added a
 
431
    #     * commited r1
 
432
    #     $ bzr remove a
 
433
    #     $ bzr status
 
434
    #     bzr: local variable 'kind' referenced before assignment
 
435
    #     at /vrac/python/bazaar-ng/bzrlib/diff.py:286 in compare_trees()
 
436
    #     see ~/.bzr.log for debug information
 
437
    cd('status-after-remove')
 
438
    runcmd('bzr init')
 
439
    file('a', 'w').write('foo')
 
440
    runcmd('bzr add a')
 
441
    runcmd(['bzr', 'commit', '-m', 'add a'])
 
442
    runcmd('bzr remove a')
 
443
    runcmd('bzr status')
 
444
 
 
445
    cd('..')
 
446
 
 
447
    progress('ignore patterns')
 
448
    mkdir('ignorebranch')
 
449
    cd('ignorebranch')
 
450
    runcmd('bzr init')
 
451
    assert backtick('bzr unknowns') == ''
 
452
 
 
453
    file('foo.tmp', 'wt').write('tmp files are ignored')
 
454
    assert backtick('bzr unknowns') == ''
 
455
 
 
456
    file('foo.c', 'wt').write('int main() {}')
 
457
    assert backtick('bzr unknowns') == 'foo.c\n'
 
458
    runcmd('bzr add foo.c')
 
459
    assert backtick('bzr unknowns') == ''
 
460
 
 
461
    # 'ignore' works when creating the .bzignore file
 
462
    file('foo.blah', 'wt').write('blah')
 
463
    assert backtick('bzr unknowns') == 'foo.blah\n'
 
464
    runcmd('bzr ignore *.blah')
 
465
    assert backtick('bzr unknowns') == ''
 
466
    assert file('.bzrignore', 'rb').read() == '*.blah\n'
 
467
 
 
468
    # 'ignore' works when then .bzrignore file already exists
 
469
    file('garh', 'wt').write('garh')
 
470
    assert backtick('bzr unknowns') == 'garh\n'
 
471
    runcmd('bzr ignore garh')
 
472
    assert backtick('bzr unknowns') == ''
 
473
    assert file('.bzrignore', 'rb').read() == '*.blah\ngarh\n'
 
474
 
 
475
    cd('..')
 
476
 
 
477
 
 
478
 
 
479
 
 
480
    progress("recursive and non-recursive add")
 
481
    mkdir('no-recurse')
 
482
    cd('no-recurse')
 
483
    runcmd('bzr init')
 
484
    mkdir('foo')
 
485
    fp = os.path.join('foo', 'test.txt')
 
486
    f = file(fp, 'w')
 
487
    f.write('hello!\n')
 
488
    f.close()
 
489
    runcmd('bzr add --no-recurse foo')
 
490
    runcmd('bzr file-id foo')
 
491
    runcmd('bzr file-id ' + fp, 1)      # not versioned yet
 
492
    runcmd('bzr commit -m add-dir-only')
 
493
 
 
494
    runcmd('bzr file-id ' + fp, 1)      # still not versioned 
 
495
 
 
496
    runcmd('bzr add foo')
 
497
    runcmd('bzr file-id ' + fp)
 
498
    runcmd('bzr commit -m add-sub-file')
 
499
    
 
500
    cd('..')
 
501
 
 
502
 
 
503
 
 
504
 
 
505
    # Run any function in this 
 
506
    g = globals()
 
507
    funcs = g.keys()
 
508
    funcs.sort()
 
509
    for k in funcs:
 
510
        if k.startswith('test_') and callable(g[k]):
 
511
            progress(k[5:].replace('_', ' '))
 
512
            g[k]()
 
513
 
 
514
    progress("all tests passed!")
 
515
except Exception, e:
 
516
    sys.stderr.write('*' * 50 + '\n'
 
517
                     + 'testbzr: tests failed\n'
 
518
                     + 'see ' + LOGFILENAME + ' for more information\n'
 
519
                     + '*' * 50 + '\n')
 
520
    logfile.write('tests failed!\n')
 
521
    traceback.print_exc(None, logfile)
 
522
    logfile.close()
 
523
 
 
524
    sys.stdout.writelines(file(os.path.join(start_dir, LOGFILENAME), 'rt').readlines()[-50:])
 
525
    
 
526
    sys.exit(1)
 
527