17
17
# along with this program; if not, write to the Free Software
18
18
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
print 'please use "bzr selftest" instead'
21
"""External black-box test for bzr.
23
This always runs bzr as an external process to try to catch bugs
24
related to argument processing, startup, etc.
28
testbzr [-p PYTHON] [BZR]
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.
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
41
This replaces the previous test.sh which was not very portable."""
43
import sys, os, traceback
45
from os.path import exists
47
TESTDIR = "testbzr.tmp"
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'
54
LOGFILENAME = 'testbzr.log'
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"
65
class CommandFailed(Exception):
70
if isinstance(cmd, basestring):
76
cmd.insert(0, OVERRIDE_PYTHON)
78
logfile.write('$ %r\n' % cmd)
83
def runcmd(cmd, retcode=0):
84
"""Run one command and check the return code.
86
Returns a tuple of (stdout,stderr) strings.
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."""
94
actual_retcode = call(cmd, stdout=logfile, stderr=logfile)
96
if retcode != actual_retcode:
97
raise CommandFailed("test failed: %r returned %d, expected %d"
98
% (cmd, actual_retcode, retcode))
102
def backtick(cmd, retcode=0):
105
child = Popen(cmd, stdout=PIPE, stderr=logfile)
106
outd, errd = child.communicate()
108
actual_retcode = child.wait()
110
outd = outd.replace('\r', '')
112
if retcode != actual_retcode:
113
raise CommandFailed("test failed: %r returned %d, expected %d"
114
% (cmd, actual_retcode, retcode))
122
logfile.write('* '+ msg + '\n')
127
logfile.write('$ cd %s\n' % dirname)
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])
139
# prepare an empty scratch directory
140
if os.path.exists(TESTDIR):
141
shutil.rmtree(TESTDIR)
143
start_dir = os.getcwd()
146
logfile = open(LOGFILENAME, 'wt', buffering=1)
150
from getopt import getopt
151
opts, args = getopt(sys.argv[1:], 'p:')
153
for option, value in opts:
155
OVERRIDE_PYTHON = value
158
mypath = os.path.abspath(sys.argv[0])
159
print '%-30s %s' % ('running tests from', mypath)
166
BZRPATH = os.path.join(os.path.split(mypath)[0], 'bzr')
168
print '%-30s %s' % ('against bzr', BZRPATH)
169
print '%-30s %s' % ('in directory', os.getcwd())
170
print '%-30s %s' % ('with python', (OVERRIDE_PYTHON or '(default)'))
172
print backtick('bzr version')
174
runcmd(['mkdir', TESTDIR])
176
test_root = os.getcwd()
178
progress("introductory commands")
179
runcmd("bzr version")
180
runcmd("bzr --version")
184
progress("internal tests")
185
runcmd("bzr selftest")
187
progress("user identity")
188
# this should always identify something, if only "john@localhost"
190
runcmd("bzr whoami --email")
191
assert backtick("bzr whoami --email").count('@') == 1
193
progress("invalid commands")
194
runcmd("bzr pants", retcode=1)
195
runcmd("bzr --pants off", retcode=1)
196
runcmd("bzr diff --message foo", retcode=1)
198
progress("basic branch creation")
199
runcmd(['mkdir', 'branch1'])
203
assert backtick('bzr root')[:-1] == os.path.join(test_root, 'branch1')
205
progress("status of new file")
207
f = file('test.txt', 'wt')
208
f.write('hello world!\n')
211
out = backtick("bzr unknowns")
212
assert out == 'test.txt\n'
214
out = backtick("bzr status")
215
assert out == 'unknown:\n test.txt\n'
217
out = backtick("bzr status --all")
218
assert out == "unknown:\n test.txt\n"
220
out = backtick("bzr status test.txt --all")
221
assert out == "unknown:\n test.txt\n"
223
f = file('test2.txt', 'wt')
224
f.write('goodbye cruel world...\n')
227
out = backtick("bzr status test.txt")
228
assert out == "unknown:\n test.txt\n"
230
out = backtick("bzr status")
231
assert out == ("unknown:\n"
235
os.unlink('test2.txt')
237
progress("command aliases")
238
out = backtick("bzr st --all")
239
assert out == ("unknown:\n"
242
out = backtick("bzr stat")
243
assert out == ("unknown:\n"
246
progress("command help")
247
runcmd("bzr help st")
249
runcmd("bzr help commands")
250
runcmd("bzr help slartibartfast", 1)
252
out = backtick("bzr help ci")
253
out.index('aliases: ')
255
progress("can't rename unversioned file")
256
runcmd("bzr rename test.txt new-test.txt", 1)
258
progress("adding a file")
260
runcmd("bzr add test.txt")
261
assert backtick("bzr unknowns") == ''
262
assert backtick("bzr status --all") == ("added:\n"
265
progress("rename newly-added file")
266
runcmd("bzr rename test.txt hello.txt")
267
assert os.path.exists("hello.txt")
268
assert not os.path.exists("test.txt")
270
assert backtick("bzr revno") == '0\n'
272
progress("add first revision")
273
runcmd(["bzr", "commit", "-m", 'add first revision'])
275
progress("more complex renames")
277
runcmd("bzr rename hello.txt sub1", 1)
278
runcmd("bzr rename hello.txt sub1/hello.txt", 1)
279
runcmd("bzr move hello.txt sub1", 1)
281
runcmd("bzr add sub1")
282
runcmd("bzr rename sub1 sub2")
283
runcmd("bzr move hello.txt sub2")
284
assert backtick("bzr relpath sub2/hello.txt") == os.path.join("sub2", "hello.txt\n")
286
assert exists("sub2")
287
assert exists("sub2/hello.txt")
288
assert not exists("sub1")
289
assert not exists("hello.txt")
291
runcmd(['bzr', 'commit', '-m', 'commit with some things moved to subdirs'])
294
runcmd('bzr add sub1')
295
runcmd('bzr move sub2/hello.txt sub1')
296
assert not exists('sub2/hello.txt')
297
assert exists('sub1/hello.txt')
298
runcmd('bzr move sub2 sub1')
299
assert not exists('sub2')
300
assert exists('sub1/sub2')
302
runcmd(['bzr', 'commit', '-m', 'rename nested subdirectories'])
305
assert backtick('bzr root')[:-1] == os.path.join(test_root, 'branch1')
306
runcmd('bzr move ../hello.txt .')
307
assert exists('./hello.txt')
308
assert backtick('bzr relpath hello.txt') == os.path.join('sub1', 'sub2', 'hello.txt\n')
309
assert backtick('bzr relpath ../../sub1/sub2/hello.txt') == os.path.join('sub1', 'sub2', 'hello.txt\n')
310
runcmd(['bzr', 'commit', '-m', 'move to parent directory'])
312
assert backtick('bzr relpath sub2/hello.txt') == os.path.join('sub1', 'sub2', 'hello.txt\n')
314
runcmd('bzr move sub2/hello.txt .')
315
assert exists('hello.txt')
317
f = file('hello.txt', 'wt')
318
f.write('some nice new content\n')
321
f = file('msg.tmp', 'wt')
322
f.write('this is my new commit\n')
325
runcmd('bzr commit -F msg.tmp')
327
assert backtick('bzr revno') == '5\n'
328
runcmd('bzr export -r 5 export-5.tmp')
329
runcmd('bzr export export.tmp')
336
progress("file with spaces in name")
337
mkdir('sub directory')
338
file('sub directory/file with spaces ', 'wt').write('see how this works\n')
341
runcmd('bzr commit -m add-spaces')
345
runcmd('bzr log --forward')
357
# Can't create a branch if it already exists
358
runcmd('bzr branch branch1', retcode=1)
359
# Can't create a branch if its parent doesn't exist
360
runcmd('bzr branch /unlikely/to/exist', retcode=1)
361
runcmd('bzr branch branch1 branch2')
365
runcmd('bzr pull', retcode=1)
366
runcmd('bzr pull ../branch2')
369
runcmd('bzr commit -m empty')
373
runcmd('bzr commit -m empty')
375
runcmd('bzr commit -m empty')
376
runcmd('bzr pull', retcode=1)
379
progress('status after remove')
380
mkdir('status-after-remove')
381
# see mail from William Dodé, 2005-05-25
382
# $ bzr init; touch a; bzr add a; bzr commit -m "add a"
383
# * looking for changes...
388
# bzr: local variable 'kind' referenced before assignment
389
# at /vrac/python/bazaar-ng/bzrlib/diff.py:286 in compare_trees()
390
# see ~/.bzr.log for debug information
391
cd('status-after-remove')
393
file('a', 'w').write('foo')
395
runcmd(['bzr', 'commit', '-m', 'add a'])
396
runcmd('bzr remove a')
401
progress('ignore patterns')
402
mkdir('ignorebranch')
405
assert backtick('bzr unknowns') == ''
407
file('foo.tmp', 'wt').write('tmp files are ignored')
408
assert backtick('bzr unknowns') == ''
410
file('foo.c', 'wt').write('int main() {}')
411
assert backtick('bzr unknowns') == 'foo.c\n'
412
runcmd('bzr add foo.c')
413
assert backtick('bzr unknowns') == ''
415
# 'ignore' works when creating the .bzignore file
416
file('foo.blah', 'wt').write('blah')
417
assert backtick('bzr unknowns') == 'foo.blah\n'
418
runcmd('bzr ignore *.blah')
419
assert backtick('bzr unknowns') == ''
420
assert file('.bzrignore', 'rb').read() == '*.blah\n'
422
# 'ignore' works when then .bzrignore file already exists
423
file('garh', 'wt').write('garh')
424
assert backtick('bzr unknowns') == 'garh\n'
425
runcmd('bzr ignore garh')
426
assert backtick('bzr unknowns') == ''
427
assert file('.bzrignore', 'rb').read() == '*.blah\ngarh\n'
434
progress("recursive and non-recursive add")
439
fp = os.path.join('foo', 'test.txt')
443
runcmd('bzr add --no-recurse foo')
444
runcmd('bzr file-id foo')
445
runcmd('bzr file-id ' + fp, 1) # not versioned yet
446
runcmd('bzr commit -m add-dir-only')
448
runcmd('bzr file-id ' + fp, 1) # still not versioned
450
runcmd('bzr add foo')
451
runcmd('bzr file-id ' + fp)
452
runcmd('bzr commit -m add-sub-file')
459
progress("all tests passed!")
461
sys.stderr.write('*' * 50 + '\n'
462
+ 'testbzr: tests failed\n'
463
+ 'see ' + LOGFILENAME + ' for more information\n'
465
logfile.write('tests failed!\n')
466
traceback.print_exc(None, logfile)
469
sys.stdout.writelines(file(os.path.join(start_dir, LOGFILENAME), 'rt').readlines()[-50:])