~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to testbzr

  • Committer: Martin Pool
  • Date: 2005-04-28 07:24:55 UTC
  • Revision ID: mbp@sourcefrog.net-20050428072453-7b99afa993a1e549
todo

Show diffs side-by-side

added added

removed removed

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