~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to testbzr

  • Committer: Martin Pool
  • Date: 2005-04-15 01:31:21 UTC
  • Revision ID: mbp@sourcefrog.net-20050415013121-b18f1be12a735066
- Doc cleanups from Magnus Therning

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
 
OVERRIDE_PYTHON = None
50
 
 
51
 
LOGFILENAME = 'testbzr.log'
52
 
 
53
 
try:
54
 
    import shutil
55
 
    from subprocess import call, Popen, PIPE
56
 
except ImportError, e:
57
 
    sys.stderr.write("testbzr: sorry, this test suite requires modules from python2.4\n"
58
 
                     + '    ' + str(e))
59
 
    sys.exit(1)
60
 
 
61
 
 
62
 
class CommandFailed(Exception):
63
 
    pass
64
 
 
65
 
 
66
 
def formcmd(cmd):
67
 
    if isinstance(cmd, basestring):
68
 
        cmd = cmd.split()
69
 
 
70
 
    if cmd[0] == 'bzr':
71
 
        cmd[0] = BZRPATH
72
 
        if OVERRIDE_PYTHON:
73
 
            cmd.insert(0, OVERRIDE_PYTHON)
74
 
 
75
 
    logfile.write('$ %r\n' % cmd)
76
 
    
77
 
    return cmd
78
 
 
79
 
 
80
 
def runcmd(cmd, retcode=0):
81
 
    """Run one command and check the return code.
82
 
 
83
 
    Returns a tuple of (stdout,stderr) strings.
84
 
 
85
 
    If a single string is based, it is split into words.
86
 
    For commands that are not simple space-separated words, please
87
 
    pass a list instead."""
88
 
    cmd = formcmd(cmd)
89
 
    log_linenumber()
90
 
    
91
 
    actual_retcode = call(cmd, stdout=logfile, stderr=logfile)
92
 
    
93
 
    if retcode != actual_retcode:
94
 
        raise CommandFailed("test failed: %r returned %d, expected %d"
95
 
                            % (cmd, actual_retcode, retcode))
96
 
 
97
 
 
98
 
 
99
 
def backtick(cmd, retcode=0):
100
 
    cmd = formcmd(cmd)
101
 
    log_linenumber()
102
 
    child = Popen(cmd, stdout=PIPE, stderr=logfile)
103
 
    outd, errd = child.communicate()
104
 
    logfile.write(outd)
105
 
    actual_retcode = child.wait()
106
 
 
107
 
    outd = outd.replace('\r', '')
108
 
    
109
 
    if retcode != actual_retcode:
110
 
        raise CommandFailed("test failed: %r returned %d, expected %d"
111
 
                            % (cmd, actual_retcode, retcode))
112
 
 
113
 
    return outd
114
 
 
115
 
 
116
 
 
117
 
def progress(msg):
118
 
    print '* ' + msg
119
 
    logfile.write('* '+ msg + '\n')
120
 
    log_linenumber()
121
 
 
122
 
 
123
 
def cd(dirname):
124
 
    logfile.write('$ cd %s\n' % dirname)
125
 
    os.chdir(dirname)
126
 
 
127
 
 
128
 
 
129
 
def log_linenumber():
130
 
    """Log the stack frame location two things up."""
131
 
    stack = traceback.extract_stack()[-3]
132
 
    logfile.write('   at %s:%d\n' % stack[:2])
133
 
 
134
 
 
135
 
 
136
 
# prepare an empty scratch directory
137
 
if os.path.exists(TESTDIR):
138
 
    shutil.rmtree(TESTDIR)
139
 
 
140
 
start_dir = os.getcwd()
141
 
 
142
 
 
143
 
logfile = open(LOGFILENAME, 'wt', buffering=1)
144
 
 
145
 
 
146
 
try:
147
 
    from getopt import getopt
148
 
    opts, args = getopt(sys.argv[1:], 'p:')
149
 
 
150
 
    for option, value in opts:
151
 
        if option == '-p':
152
 
            OVERRIDE_PYTHON = value
153
 
            
154
 
    
155
 
    mypath = os.path.abspath(sys.argv[0])
156
 
    print '%-30s %s' % ('running tests from', mypath)
157
 
 
158
 
    global BZRPATH
159
 
 
160
 
    if args:
161
 
        BZRPATH = args[1]
162
 
    else:
163
 
        BZRPATH = os.path.join(os.path.split(mypath)[0], 'bzr')
164
 
 
165
 
    print '%-30s %s' % ('against bzr', BZRPATH)
166
 
    print '%-30s %s' % ('in directory', os.getcwd())
167
 
    print '%-30s %s' % ('with python', (OVERRIDE_PYTHON or '(default)'))
168
 
    print
169
 
    print backtick([BZRPATH, 'version'])
170
 
    
171
 
    runcmd(['mkdir', TESTDIR])
172
 
    cd(TESTDIR)
173
 
    test_root = os.getcwd()
174
 
 
175
 
    progress("introductory commands")
176
 
    runcmd("bzr version")
177
 
    runcmd("bzr --version")
178
 
    runcmd("bzr help")
179
 
    runcmd("bzr --help")
180
 
 
181
 
    progress("internal tests")
182
 
    runcmd("bzr selftest")
183
 
 
184
 
    progress("user identity")
185
 
    # this should always identify something, if only "john@localhost"
186
 
    runcmd("bzr whoami")
187
 
    runcmd("bzr whoami --email")
188
 
    assert backtick("bzr whoami --email").count('@') == 1
189
 
 
190
 
    progress("invalid commands")
191
 
    runcmd("bzr pants", retcode=1)
192
 
    runcmd("bzr --pants off", retcode=1)
193
 
    runcmd("bzr diff --message foo", retcode=1)
194
 
 
195
 
    progress("basic branch creation")
196
 
    runcmd(['mkdir', 'branch1'])
197
 
    cd('branch1')
198
 
    runcmd('bzr init')
199
 
 
200
 
    assert backtick('bzr root')[:-1] == os.path.join(test_root, 'branch1')
201
 
 
202
 
    progress("status of new file")
203
 
    
204
 
    f = file('test.txt', 'wt')
205
 
    f.write('hello world!\n')
206
 
    f.close()
207
 
 
208
 
    out = backtick("bzr unknowns")
209
 
    assert out == 'test.txt\n'
210
 
 
211
 
    out = backtick("bzr status")
212
 
    assert out == 'unknown:\n  test.txt\n'
213
 
 
214
 
    out = backtick("bzr status --all")
215
 
    assert out == "unknown:\n  test.txt\n"
216
 
 
217
 
    out = backtick("bzr status test.txt --all")
218
 
    assert out == "unknown:\n  test.txt\n"
219
 
 
220
 
    f = file('test2.txt', 'wt')
221
 
    f.write('goodbye cruel world...\n')
222
 
    f.close()
223
 
 
224
 
    out = backtick("bzr status test.txt")
225
 
    assert out == "unknown:\n  test.txt\n"
226
 
 
227
 
    out = backtick("bzr status")
228
 
    assert out == ("unknown:\n"
229
 
                   "  test.txt\n"
230
 
                   "  test2.txt\n")
231
 
 
232
 
    os.unlink('test2.txt')
233
 
 
234
 
    progress("command aliases")
235
 
    out = backtick("bzr st --all")
236
 
    assert out == ("unknown:\n"
237
 
                   "  test.txt\n")
238
 
    
239
 
    out = backtick("bzr stat")
240
 
    assert out == ("unknown:\n"
241
 
                   "  test.txt\n")
242
 
 
243
 
    progress("command help")
244
 
    runcmd("bzr help st")
245
 
    runcmd("bzr help")
246
 
    runcmd("bzr help commands")
247
 
    runcmd("bzr help slartibartfast", 1)
248
 
 
249
 
    out = backtick("bzr help ci")
250
 
    out.index('aliases: ')
251
 
 
252
 
    progress("can't rename unversioned file")
253
 
    runcmd("bzr rename test.txt new-test.txt", 1)
254
 
 
255
 
    progress("adding a file")
256
 
 
257
 
    runcmd("bzr add test.txt")
258
 
    assert backtick("bzr unknowns") == ''
259
 
    assert backtick("bzr status --all") == ("added:\n"
260
 
                                            "  test.txt\n")
261
 
 
262
 
    progress("rename newly-added file")
263
 
    runcmd("bzr rename test.txt hello.txt")
264
 
    assert os.path.exists("hello.txt")
265
 
    assert not os.path.exists("test.txt")
266
 
 
267
 
    assert backtick("bzr revno") == '0\n'
268
 
 
269
 
    progress("add first revision")
270
 
    runcmd(["bzr", "commit", "-m", 'add first revision'])
271
 
 
272
 
    progress("more complex renames")
273
 
    os.mkdir("sub1")
274
 
    runcmd("bzr rename hello.txt sub1", 1)
275
 
    runcmd("bzr rename hello.txt sub1/hello.txt", 1)
276
 
    runcmd("bzr move hello.txt sub1", 1)
277
 
 
278
 
    runcmd("bzr add sub1")
279
 
    runcmd("bzr rename sub1 sub2")
280
 
    runcmd("bzr move hello.txt sub2")
281
 
    assert backtick("bzr relpath sub2/hello.txt") == os.path.join("sub2", "hello.txt\n")
282
 
 
283
 
    assert exists("sub2")
284
 
    assert exists("sub2/hello.txt")
285
 
    assert not exists("sub1")
286
 
    assert not exists("hello.txt")
287
 
 
288
 
    runcmd(['bzr', 'commit', '-m', 'commit with some things moved to subdirs'])
289
 
 
290
 
    mkdir("sub1")
291
 
    runcmd('bzr add sub1')
292
 
    runcmd('bzr move sub2/hello.txt sub1')
293
 
    assert not exists('sub2/hello.txt')
294
 
    assert exists('sub1/hello.txt')
295
 
    runcmd('bzr move sub2 sub1')
296
 
    assert not exists('sub2')
297
 
    assert exists('sub1/sub2')
298
 
 
299
 
    runcmd(['bzr', 'commit', '-m', 'rename nested subdirectories'])
300
 
 
301
 
    cd('sub1/sub2')
302
 
    assert backtick('bzr root')[:-1] == os.path.join(test_root, 'branch1')
303
 
    runcmd('bzr move ../hello.txt .')
304
 
    assert exists('./hello.txt')
305
 
    assert backtick('bzr relpath hello.txt') == os.path.join('sub1', 'sub2', 'hello.txt\n')
306
 
    assert backtick('bzr relpath ../../sub1/sub2/hello.txt') == os.path.join('sub1', 'sub2', 'hello.txt\n')
307
 
    runcmd(['bzr', 'commit', '-m', 'move to parent directory'])
308
 
    cd('..')
309
 
    assert backtick('bzr relpath sub2/hello.txt') == os.path.join('sub1', 'sub2', 'hello.txt\n')
310
 
 
311
 
    runcmd('bzr move sub2/hello.txt .')
312
 
    assert exists('hello.txt')
313
 
 
314
 
    f = file('hello.txt', 'wt')
315
 
    f.write('some nice new content\n')
316
 
    f.close()
317
 
 
318
 
    f = file('msg.tmp', 'wt')
319
 
    f.write('this is my new commit\n')
320
 
    f.close()
321
 
 
322
 
    runcmd('bzr commit -F msg.tmp')
323
 
 
324
 
    assert backtick('bzr revno') == '5\n'
325
 
    runcmd('bzr export -r 5 export-5.tmp')
326
 
    runcmd('bzr export export.tmp')
327
 
 
328
 
    runcmd('bzr log')
329
 
    runcmd('bzr log -v')
330
 
 
331
 
 
332
 
 
333
 
    progress("file with spaces in name")
334
 
    mkdir('sub directory')
335
 
    file('sub directory/file with spaces ', 'wt').write('see how this works\n')
336
 
    runcmd('bzr add .')
337
 
    runcmd('bzr diff')
338
 
    runcmd('bzr commit -m add-spaces')
339
 
    runcmd('bzr check')
340
 
 
341
 
    runcmd('bzr log')
342
 
    runcmd('bzr log --forward')
343
 
 
344
 
    runcmd('bzr info')
345
 
 
346
 
 
347
 
 
348
 
    cd('..')
349
 
    cd('..')
350
 
 
351
 
    progress('status after remove')
352
 
    mkdir('status-after-remove')
353
 
    # see mail from William Dodé, 2005-05-25
354
 
    # $ bzr init; touch a; bzr add a; bzr commit -m "add a"
355
 
    #     * looking for changes...
356
 
    #     added a
357
 
    #     * commited r1
358
 
    #     $ bzr remove a
359
 
    #     $ bzr status
360
 
    #     bzr: local variable 'kind' referenced before assignment
361
 
    #     at /vrac/python/bazaar-ng/bzrlib/diff.py:286 in compare_trees()
362
 
    #     see ~/.bzr.log for debug information
363
 
    cd('status-after-remove')
364
 
    runcmd('bzr init')
365
 
    file('a', 'w').write('foo')
366
 
    runcmd('bzr add a')
367
 
    runcmd(['bzr', 'commit', '-m', 'add a'])
368
 
    runcmd('bzr remove a')
369
 
    runcmd('bzr status')
370
 
 
371
 
    cd('..')
372
 
 
373
 
    progress('ignore patterns')
374
 
    mkdir('ignorebranch')
375
 
    cd('ignorebranch')
376
 
    runcmd('bzr init')
377
 
    assert backtick('bzr unknowns') == ''
378
 
 
379
 
    file('foo.tmp', 'wt').write('tmp files are ignored')
380
 
    assert backtick('bzr unknowns') == ''
381
 
 
382
 
    file('foo.c', 'wt').write('int main() {}')
383
 
    assert backtick('bzr unknowns') == 'foo.c\n'
384
 
    runcmd('bzr add foo.c')
385
 
    assert backtick('bzr unknowns') == ''
386
 
 
387
 
    # 'ignore' works when creating the .bzignore file
388
 
    file('foo.blah', 'wt').write('blah')
389
 
    assert backtick('bzr unknowns') == 'foo.blah\n'
390
 
    runcmd('bzr ignore *.blah')
391
 
    assert backtick('bzr unknowns') == ''
392
 
    assert file('.bzrignore', 'rb').read() == '*.blah\n'
393
 
 
394
 
    # 'ignore' works when then .bzrignore file already exists
395
 
    file('garh', 'wt').write('garh')
396
 
    assert backtick('bzr unknowns') == 'garh\n'
397
 
    runcmd('bzr ignore garh')
398
 
    assert backtick('bzr unknowns') == ''
399
 
    assert file('.bzrignore', 'rb').read() == '*.blah\ngarh\n'
400
 
 
401
 
 
402
 
 
403
 
    progress("all tests passed!")
404
 
except Exception, e:
405
 
    sys.stderr.write('*' * 50 + '\n'
406
 
                     + 'testbzr: tests failed\n'
407
 
                     + 'see ' + LOGFILENAME + ' for more information\n'
408
 
                     + '*' * 50 + '\n')
409
 
    logfile.write('tests failed!\n')
410
 
    traceback.print_exc(None, logfile)
411
 
    logfile.close()
412
 
 
413
 
    sys.stdout.writelines(file(os.path.join(start_dir, LOGFILENAME), 'rt').readlines()[-50:])
414
 
    
415
 
    sys.exit(1)
416