~bzr-pqm/bzr/bzr.dev

292 by Martin Pool
- start adding a pure-python blackbox test suite
1
#! /usr/bin/python
561 by Martin Pool
- add failing test for problem with stat after remove,
2
# -*- coding: utf-8 -*-
292 by Martin Pool
- start adding a pure-python blackbox test suite
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
507 by Martin Pool
- new -p option for testbzr to use a different version of python
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
292 by Martin Pool
- start adding a pure-python blackbox test suite
41
This replaces the previous test.sh which was not very portable."""
42
296 by Martin Pool
- better reports from testbzr when it fails
43
import sys, os, traceback
339 by Martin Pool
many more diffs
44
from os import mkdir
45
from os.path import exists
292 by Martin Pool
- start adding a pure-python blackbox test suite
46
335 by Martin Pool
- add new failing test for command parsing
47
TESTDIR = "testbzr.tmp"
48
624 by Martin Pool
- make sure bzr is always explicitly invoked through
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'
507 by Martin Pool
- new -p option for testbzr to use a different version of python
53
335 by Martin Pool
- add new failing test for command parsing
54
LOGFILENAME = 'testbzr.log'
55
292 by Martin Pool
- start adding a pure-python blackbox test suite
56
try:
57
    import shutil
301 by Martin Pool
- provide for catching output from shell commands
58
    from subprocess import call, Popen, PIPE
292 by Martin Pool
- start adding a pure-python blackbox test suite
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
296 by Martin Pool
- better reports from testbzr when it fails
65
class CommandFailed(Exception):
66
    pass
67
68
302 by Martin Pool
testbzr: new backtick() helper
69
def formcmd(cmd):
70
    if isinstance(cmd, basestring):
71
        cmd = cmd.split()
72
398 by Martin Pool
- testbzr finds the right version of bzr to test
73
    if cmd[0] == 'bzr':
74
        cmd[0] = BZRPATH
507 by Martin Pool
- new -p option for testbzr to use a different version of python
75
        if OVERRIDE_PYTHON:
76
            cmd.insert(0, OVERRIDE_PYTHON)
398 by Martin Pool
- testbzr finds the right version of bzr to test
77
507 by Martin Pool
- new -p option for testbzr to use a different version of python
78
    logfile.write('$ %r\n' % cmd)
79
    
302 by Martin Pool
testbzr: new backtick() helper
80
    return cmd
81
82
83
def runcmd(cmd, retcode=0):
300 by Martin Pool
- more tests
84
    """Run one command and check the return code.
292 by Martin Pool
- start adding a pure-python blackbox test suite
85
301 by Martin Pool
- provide for catching output from shell commands
86
    Returns a tuple of (stdout,stderr) strings.
87
292 by Martin Pool
- start adding a pure-python blackbox test suite
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."""
302 by Martin Pool
testbzr: new backtick() helper
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)
301 by Martin Pool
- provide for catching output from shell commands
106
    outd, errd = child.communicate()
302 by Martin Pool
testbzr: new backtick() helper
107
    logfile.write(outd)
301 by Martin Pool
- provide for catching output from shell commands
108
    actual_retcode = child.wait()
307 by Martin Pool
testbzr: clean up crlf handling
109
110
    outd = outd.replace('\r', '')
301 by Martin Pool
- provide for catching output from shell commands
111
    
298 by Martin Pool
- test some commands known to fail
112
    if retcode != actual_retcode:
113
        raise CommandFailed("test failed: %r returned %d, expected %d"
114
                            % (cmd, actual_retcode, retcode))
292 by Martin Pool
- start adding a pure-python blackbox test suite
115
302 by Martin Pool
testbzr: new backtick() helper
116
    return outd
117
301 by Martin Pool
- provide for catching output from shell commands
118
292 by Martin Pool
- start adding a pure-python blackbox test suite
119
120
def progress(msg):
121
    print '* ' + msg
122
    logfile.write('* '+ msg + '\n')
297 by Martin Pool
- fix intentional testcase failure
123
    log_linenumber()
124
125
299 by Martin Pool
testbzr:
126
def cd(dirname):
127
    logfile.write('$ cd %s\n' % dirname)
128
    os.chdir(dirname)
129
130
300 by Martin Pool
- more tests
131
297 by Martin Pool
- fix intentional testcase failure
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
340 by Martin Pool
- more testcase fixes
138
292 by Martin Pool
- start adding a pure-python blackbox test suite
139
# prepare an empty scratch directory
140
if os.path.exists(TESTDIR):
141
    shutil.rmtree(TESTDIR)
142
513 by Martin Pool
- show some log output if the tests fail
143
start_dir = os.getcwd()
144
292 by Martin Pool
- start adding a pure-python blackbox test suite
145
335 by Martin Pool
- add new failing test for command parsing
146
logfile = open(LOGFILENAME, 'wt', buffering=1)
292 by Martin Pool
- start adding a pure-python blackbox test suite
147
641 by Martin Pool
- improved external-command patch from john
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')
292 by Martin Pool
- start adding a pure-python blackbox test suite
196
300 by Martin Pool
- more tests
197
try:
507 by Martin Pool
- new -p option for testbzr to use a different version of python
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
    
398 by Martin Pool
- testbzr finds the right version of bzr to test
206
    mypath = os.path.abspath(sys.argv[0])
413 by Martin Pool
- more indicators at top of test output
207
    print '%-30s %s' % ('running tests from', mypath)
398 by Martin Pool
- testbzr finds the right version of bzr to test
208
209
    global BZRPATH
210
507 by Martin Pool
- new -p option for testbzr to use a different version of python
211
    if args:
623 by Martin Pool
- fix invocation of testbzr when giving explicit bzr location
212
        BZRPATH = args[0]
398 by Martin Pool
- testbzr finds the right version of bzr to test
213
    else:
214
        BZRPATH = os.path.join(os.path.split(mypath)[0], 'bzr')
215
413 by Martin Pool
- more indicators at top of test output
216
    print '%-30s %s' % ('against bzr', BZRPATH)
217
    print '%-30s %s' % ('in directory', os.getcwd())
507 by Martin Pool
- new -p option for testbzr to use a different version of python
218
    print '%-30s %s' % ('with python', (OVERRIDE_PYTHON or '(default)'))
398 by Martin Pool
- testbzr finds the right version of bzr to test
219
    print
624 by Martin Pool
- make sure bzr is always explicitly invoked through
220
    print backtick('bzr version')
398 by Martin Pool
- testbzr finds the right version of bzr to test
221
    
300 by Martin Pool
- more tests
222
    runcmd(['mkdir', TESTDIR])
299 by Martin Pool
testbzr:
223
    cd(TESTDIR)
456 by Martin Pool
- tests for bzr root
224
    test_root = os.getcwd()
296 by Martin Pool
- better reports from testbzr when it fails
225
300 by Martin Pool
- more tests
226
    progress("introductory commands")
296 by Martin Pool
- better reports from testbzr when it fails
227
    runcmd("bzr version")
335 by Martin Pool
- add new failing test for command parsing
228
    runcmd("bzr --version")
296 by Martin Pool
- better reports from testbzr when it fails
229
    runcmd("bzr help")
297 by Martin Pool
- fix intentional testcase failure
230
    runcmd("bzr --help")
231
399 by Martin Pool
- testbzr also runs selftests
232
    progress("internal tests")
233
    runcmd("bzr selftest")
234
300 by Martin Pool
- more tests
235
    progress("user identity")
297 by Martin Pool
- fix intentional testcase failure
236
    # this should always identify something, if only "john@localhost"
237
    runcmd("bzr whoami")
298 by Martin Pool
- test some commands known to fail
238
    runcmd("bzr whoami --email")
302 by Martin Pool
testbzr: new backtick() helper
239
    assert backtick("bzr whoami --email").count('@') == 1
298 by Martin Pool
- test some commands known to fail
240
300 by Martin Pool
- more tests
241
    progress("invalid commands")
298 by Martin Pool
- test some commands known to fail
242
    runcmd("bzr pants", retcode=1)
243
    runcmd("bzr --pants off", retcode=1)
382 by Martin Pool
- test previous commit
244
    runcmd("bzr diff --message foo", retcode=1)
296 by Martin Pool
- better reports from testbzr when it fails
245
300 by Martin Pool
- more tests
246
    progress("basic branch creation")
247
    runcmd(['mkdir', 'branch1'])
248
    cd('branch1')
249
    runcmd('bzr init')
303 by Martin Pool
- more tests for unknown file
250
456 by Martin Pool
- tests for bzr root
251
    assert backtick('bzr root')[:-1] == os.path.join(test_root, 'branch1')
252
303 by Martin Pool
- more tests for unknown file
253
    progress("status of new file")
300 by Martin Pool
- more tests
254
    
255
    f = file('test.txt', 'wt')
256
    f.write('hello world!\n')
257
    f.close()
258
307 by Martin Pool
testbzr: clean up crlf handling
259
    out = backtick("bzr unknowns")
260
    assert out == 'test.txt\n'
303 by Martin Pool
- more tests for unknown file
261
307 by Martin Pool
testbzr: clean up crlf handling
262
    out = backtick("bzr status")
477 by Martin Pool
- fix header for listing of unknown files
263
    assert out == 'unknown:\n  test.txt\n'
303 by Martin Pool
- more tests for unknown file
264
307 by Martin Pool
testbzr: clean up crlf handling
265
    out = backtick("bzr status --all")
477 by Martin Pool
- fix header for listing of unknown files
266
    assert out == "unknown:\n  test.txt\n"
304 by Martin Pool
testbzr: test adding a file
267
404 by Martin Pool
- bzr status now optionally takes filenames to check
268
    out = backtick("bzr status test.txt --all")
477 by Martin Pool
- fix header for listing of unknown files
269
    assert out == "unknown:\n  test.txt\n"
404 by Martin Pool
- bzr status now optionally takes filenames to check
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")
480 by Martin Pool
- more status form test fixes
276
    assert out == "unknown:\n  test.txt\n"
404 by Martin Pool
- bzr status now optionally takes filenames to check
277
278
    out = backtick("bzr status")
480 by Martin Pool
- more status form test fixes
279
    assert out == ("unknown:\n"
280
                   "  test.txt\n"
281
                   "  test2.txt\n")
404 by Martin Pool
- bzr status now optionally takes filenames to check
282
283
    os.unlink('test2.txt')
284
350 by Martin Pool
- refactor command aliases into command classes
285
    progress("command aliases")
286
    out = backtick("bzr st --all")
482 by Martin Pool
- more status form test fixes
287
    assert out == ("unknown:\n"
288
                   "  test.txt\n")
289
    
350 by Martin Pool
- refactor command aliases into command classes
290
    out = backtick("bzr stat")
482 by Martin Pool
- more status form test fixes
291
    assert out == ("unknown:\n"
292
                   "  test.txt\n")
350 by Martin Pool
- refactor command aliases into command classes
293
294
    progress("command help")
295
    runcmd("bzr help st")
296
    runcmd("bzr help")
297
    runcmd("bzr help commands")
352 by Martin Pool
- Show aliases in command help
298
    runcmd("bzr help slartibartfast", 1)
299
300
    out = backtick("bzr help ci")
301
    out.index('aliases: ')
350 by Martin Pool
- refactor command aliases into command classes
302
305 by Martin Pool
testbzr: test renames
303
    progress("can't rename unversioned file")
304
    runcmd("bzr rename test.txt new-test.txt", 1)
305
304 by Martin Pool
testbzr: test adding a file
306
    progress("adding a file")
307
308
    runcmd("bzr add test.txt")
309
    assert backtick("bzr unknowns") == ''
482 by Martin Pool
- more status form test fixes
310
    assert backtick("bzr status --all") == ("added:\n"
311
                                            "  test.txt\n")
300 by Martin Pool
- more tests
312
305 by Martin Pool
testbzr: test renames
313
    progress("rename newly-added file")
314
    runcmd("bzr rename test.txt hello.txt")
306 by Martin Pool
testbzr: test renames
315
    assert os.path.exists("hello.txt")
316
    assert not os.path.exists("test.txt")
305 by Martin Pool
testbzr: test renames
317
308 by Martin Pool
fix test suite
318
    assert backtick("bzr revno") == '0\n'
307 by Martin Pool
testbzr: clean up crlf handling
319
339 by Martin Pool
many more diffs
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")
560 by Martin Pool
- fix testbzr for win32
332
    assert backtick("bzr relpath sub2/hello.txt") == os.path.join("sub2", "hello.txt\n")
339 by Martin Pool
many more diffs
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')
456 by Martin Pool
- tests for bzr root
353
    assert backtick('bzr root')[:-1] == os.path.join(test_root, 'branch1')
339 by Martin Pool
many more diffs
354
    runcmd('bzr move ../hello.txt .')
340 by Martin Pool
- more testcase fixes
355
    assert exists('./hello.txt')
560 by Martin Pool
- fix testbzr for win32
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')
339 by Martin Pool
many more diffs
358
    runcmd(['bzr', 'commit', '-m', 'move to parent directory'])
359
    cd('..')
560 by Martin Pool
- fix testbzr for win32
360
    assert backtick('bzr relpath sub2/hello.txt') == os.path.join('sub1', 'sub2', 'hello.txt\n')
340 by Martin Pool
- more testcase fixes
361
362
    runcmd('bzr move sub2/hello.txt .')
363
    assert exists('hello.txt')
389 by Martin Pool
- new commit --file option!
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')
394 by Martin Pool
- Fix argument handling in export command
374
375
    assert backtick('bzr revno') == '5\n'
376
    runcmd('bzr export -r 5 export-5.tmp')
377
    runcmd('bzr export export.tmp')
461 by Martin Pool
- remove compare_inventories() in favor of compare_trees()
378
379
    runcmd('bzr log')
380
    runcmd('bzr log -v')
511 by Martin Pool
- add tests for files and directories with spaces in name
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
545 by Martin Pool
- --forward option for log
392
    runcmd('bzr log')
393
    runcmd('bzr log --forward')
394
541 by Martin Pool
- add lazy test for 'bzr info'
395
    runcmd('bzr info')
561 by Martin Pool
- add failing test for problem with stat after remove,
396
397
595 by Martin Pool
- tests for add --no-recurse
398
    
399
400
561 by Martin Pool
- add failing test for problem with stat after remove,
401
402
    cd('..')
403
    cd('..')
628 by Martin Pool
- merge aaron's updated merge/pull code
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 ('..')
561 by Martin Pool
- add failing test for problem with stat after remove,
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
410 by Martin Pool
- Fix ignore command and add tests
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
499 by Martin Pool
- new bzr ignore test cases from ddaa
463
    # 'ignore' works when creating the .bzignore file
410 by Martin Pool
- Fix ignore command and add tests
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') == ''
499 by Martin Pool
- new bzr ignore test cases from ddaa
468
    assert file('.bzrignore', 'rb').read() == '*.blah\n'
410 by Martin Pool
- Fix ignore command and add tests
469
499 by Martin Pool
- new bzr ignore test cases from ddaa
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'
300 by Martin Pool
- more tests
476
595 by Martin Pool
- tests for add --no-recurse
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
511 by Martin Pool
- add tests for files and directories with spaces in name
505
506
641 by Martin Pool
- improved external-command patch from john
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
296 by Martin Pool
- better reports from testbzr when it fails
516
    progress("all tests passed!")
517
except Exception, e:
518
    sys.stderr.write('*' * 50 + '\n'
519
                     + 'testbzr: tests failed\n'
335 by Martin Pool
- add new failing test for command parsing
520
                     + 'see ' + LOGFILENAME + ' for more information\n'
296 by Martin Pool
- better reports from testbzr when it fails
521
                     + '*' * 50 + '\n')
522
    logfile.write('tests failed!\n')
523
    traceback.print_exc(None, logfile)
513 by Martin Pool
- show some log output if the tests fail
524
    logfile.close()
525
526
    sys.stdout.writelines(file(os.path.join(start_dir, LOGFILENAME), 'rt').readlines()[-50:])
527
    
296 by Martin Pool
- better reports from testbzr when it fails
528
    sys.exit(1)
513 by Martin Pool
- show some log output if the tests fail
529