~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_log.py

  • Committer: Martin Pool
  • Date: 2006-06-05 18:00:36 UTC
  • mto: This revision was merged to the branch mainline in revision 1752.
  • Revision ID: mbp@sourcefrog.net-20060605180036-04f5d0cea94ed999
clean up test kipple

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2005 by Canonical Ltd
 
2
# -*- coding: utf-8 -*-
 
3
# vim: encoding=utf-8
 
4
 
 
5
# This program is free software; you can redistribute it and/or modify
 
6
# it under the terms of the GNU General Public License as published by
 
7
# the Free Software Foundation; either version 2 of the License, or
 
8
# (at your option) any later version.
 
9
 
 
10
# This program is distributed in the hope that it will be useful,
 
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
# GNU General Public License for more details.
 
14
 
 
15
# You should have received a copy of the GNU General Public License
 
16
# along with this program; if not, write to the Free Software
 
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
 
 
19
import os
 
20
from cStringIO import StringIO
 
21
 
 
22
from bzrlib.tests import BzrTestBase, TestCaseWithTransport
 
23
from bzrlib.log import LogFormatter, show_log, LongLogFormatter, ShortLogFormatter
 
24
from bzrlib.branch import Branch
 
25
from bzrlib.errors import InvalidRevisionNumber
 
26
 
 
27
class _LogEntry(object):
 
28
    # should probably move into bzrlib.log?
 
29
    pass
 
30
 
 
31
 
 
32
class LogCatcher(LogFormatter):
 
33
    """Pull log messages into list rather than displaying them.
 
34
 
 
35
    For ease of testing we save log messages here rather than actually
 
36
    formatting them, so that we can precisely check the result without
 
37
    being too dependent on the exact formatting.
 
38
 
 
39
    We should also test the LogFormatter.
 
40
    """
 
41
    def __init__(self):
 
42
        super(LogCatcher, self).__init__(to_file=None)
 
43
        self.logs = []
 
44
        
 
45
        
 
46
    def show(self, revno, rev, delta):
 
47
        le = _LogEntry()
 
48
        le.revno = revno
 
49
        le.rev = rev
 
50
        le.delta = delta
 
51
        self.logs.append(le)
 
52
 
 
53
 
 
54
class SimpleLogTest(TestCaseWithTransport):
 
55
 
 
56
    def checkDelta(self, delta, **kw):
 
57
        """Check the filenames touched by a delta are as expected."""
 
58
        for n in 'added', 'removed', 'renamed', 'modified', 'unchanged':
 
59
            expected = kw.get(n, [])
 
60
 
 
61
            # tests are written with unix paths; fix them up for windows
 
62
            #if os.sep != '/':
 
63
            #    expected = [x.replace('/', os.sep) for x in expected]
 
64
 
 
65
            # strip out only the path components
 
66
            got = [x[0] for x in getattr(delta, n)]
 
67
            self.assertEquals(expected, got)
 
68
 
 
69
    def test_cur_revno(self):
 
70
        wt = self.make_branch_and_tree('.')
 
71
        b = wt.branch
 
72
 
 
73
        lf = LogCatcher()
 
74
        wt.commit('empty commit')
 
75
        show_log(b, lf, verbose=True, start_revision=1, end_revision=1)
 
76
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
 
77
                          start_revision=2, end_revision=1) 
 
78
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
 
79
                          start_revision=1, end_revision=2) 
 
80
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
 
81
                          start_revision=0, end_revision=2) 
 
82
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
 
83
                          start_revision=1, end_revision=0) 
 
84
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
 
85
                          start_revision=-1, end_revision=1) 
 
86
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
 
87
                          start_revision=1, end_revision=-1) 
 
88
 
 
89
    def test_cur_revno(self):
 
90
        wt = self.make_branch_and_tree('.')
 
91
        b = wt.branch
 
92
 
 
93
        lf = LogCatcher()
 
94
        wt.commit('empty commit')
 
95
        show_log(b, lf, verbose=True, start_revision=1, end_revision=1)
 
96
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
 
97
                          start_revision=2, end_revision=1) 
 
98
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
 
99
                          start_revision=1, end_revision=2) 
 
100
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
 
101
                          start_revision=0, end_revision=2) 
 
102
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
 
103
                          start_revision=1, end_revision=0) 
 
104
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
 
105
                          start_revision=-1, end_revision=1) 
 
106
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
 
107
                          start_revision=1, end_revision=-1) 
 
108
 
 
109
    def test_simple_log(self):
 
110
        eq = self.assertEquals
 
111
        
 
112
        wt = self.make_branch_and_tree('.')
 
113
        b = wt.branch
 
114
 
 
115
        lf = LogCatcher()
 
116
        show_log(b, lf)
 
117
        # no entries yet
 
118
        eq(lf.logs, [])
 
119
 
 
120
        wt.commit('empty commit')
 
121
        lf = LogCatcher()
 
122
        show_log(b, lf, verbose=True)
 
123
        eq(len(lf.logs), 1)
 
124
        eq(lf.logs[0].revno, 1)
 
125
        eq(lf.logs[0].rev.message, 'empty commit')
 
126
        d = lf.logs[0].delta
 
127
        self.log('log delta: %r' % d)
 
128
        self.checkDelta(d)
 
129
 
 
130
        self.build_tree(['hello'])
 
131
        wt.add('hello')
 
132
        wt.commit('add one file')
 
133
 
 
134
        lf = StringIO()
 
135
        # log using regular thing
 
136
        show_log(b, LongLogFormatter(lf))
 
137
        lf.seek(0)
 
138
        for l in lf.readlines():
 
139
            self.log(l)
 
140
 
 
141
        # get log as data structure
 
142
        lf = LogCatcher()
 
143
        show_log(b, lf, verbose=True)
 
144
        eq(len(lf.logs), 2)
 
145
        self.log('log entries:')
 
146
        for logentry in lf.logs:
 
147
            self.log('%4d %s' % (logentry.revno, logentry.rev.message))
 
148
        
 
149
        # first one is most recent
 
150
        logentry = lf.logs[0]
 
151
        eq(logentry.revno, 2)
 
152
        eq(logentry.rev.message, 'add one file')
 
153
        d = logentry.delta
 
154
        self.log('log 2 delta: %r' % d)
 
155
        # self.checkDelta(d, added=['hello'])
 
156
        
 
157
        # commit a log message with control characters
 
158
        msg = "All 8-bit chars: " +  ''.join([unichr(x) for x in range(256)])
 
159
        self.log("original commit message: %r", msg)
 
160
        wt.commit(msg)
 
161
        lf = LogCatcher()
 
162
        show_log(b, lf, verbose=True)
 
163
        committed_msg = lf.logs[0].rev.message
 
164
        self.log("escaped commit message: %r", committed_msg)
 
165
        self.assert_(msg != committed_msg)
 
166
        self.assert_(len(committed_msg) > len(msg))
 
167
 
 
168
        # Check that log message with only XML-valid characters isn't
 
169
        # escaped.  As ElementTree apparently does some kind of
 
170
        # newline conversion, neither LF (\x0A) nor CR (\x0D) are
 
171
        # included in the test commit message, even though they are
 
172
        # valid XML 1.0 characters.
 
173
        msg = "\x09" + ''.join([unichr(x) for x in range(0x20, 256)])
 
174
        self.log("original commit message: %r", msg)
 
175
        wt.commit(msg)
 
176
        lf = LogCatcher()
 
177
        show_log(b, lf, verbose=True)
 
178
        committed_msg = lf.logs[0].rev.message
 
179
        self.log("escaped commit message: %r", committed_msg)
 
180
        self.assert_(msg == committed_msg)
 
181
 
 
182
    def test_trailing_newlines(self):
 
183
        wt = self.make_branch_and_tree('.')
 
184
        b = wt.branch
 
185
        b.nick='test'
 
186
        open('a', 'wb').write('hello moto\n')
 
187
        wt.add('a')
 
188
        wt.commit('simple log message', rev_id='a1'
 
189
                , timestamp=1132586655.459960938, timezone=-6*3600
 
190
                , committer='Joe Foo <joe@foo.com>')
 
191
        open('b', 'wb').write('goodbye\n')
 
192
        wt.add('b')
 
193
        wt.commit('multiline\nlog\nmessage\n', rev_id='a2'
 
194
                , timestamp=1132586842.411175966, timezone=-6*3600
 
195
                , committer='Joe Foo <joe@foo.com>')
 
196
 
 
197
        open('c', 'wb').write('just another manic monday\n')
 
198
        wt.add('c')
 
199
        wt.commit('single line with trailing newline\n', rev_id='a3'
 
200
                , timestamp=1132587176.835228920, timezone=-6*3600
 
201
                , committer = 'Joe Foo <joe@foo.com>')
 
202
 
 
203
        sio = StringIO()
 
204
        lf = ShortLogFormatter(to_file=sio)
 
205
        show_log(b, lf)
 
206
        self.assertEquals(sio.getvalue(), """\
 
207
    3 Joe Foo\t2005-11-21
 
208
      single line with trailing newline
 
209
 
 
210
    2 Joe Foo\t2005-11-21
 
211
      multiline
 
212
      log
 
213
      message
 
214
 
 
215
    1 Joe Foo\t2005-11-21
 
216
      simple log message
 
217
 
 
218
""")
 
219
 
 
220
        sio = StringIO()
 
221
        lf = LongLogFormatter(to_file=sio)
 
222
        show_log(b, lf)
 
223
        self.assertEquals(sio.getvalue(), """\
 
224
------------------------------------------------------------
 
225
revno: 3
 
226
committer: Joe Foo <joe@foo.com>
 
227
branch nick: test
 
228
timestamp: Mon 2005-11-21 09:32:56 -0600
 
229
message:
 
230
  single line with trailing newline
 
231
------------------------------------------------------------
 
232
revno: 2
 
233
committer: Joe Foo <joe@foo.com>
 
234
branch nick: test
 
235
timestamp: Mon 2005-11-21 09:27:22 -0600
 
236
message:
 
237
  multiline
 
238
  log
 
239
  message
 
240
------------------------------------------------------------
 
241
revno: 1
 
242
committer: Joe Foo <joe@foo.com>
 
243
branch nick: test
 
244
timestamp: Mon 2005-11-21 09:24:15 -0600
 
245
message:
 
246
  simple log message
 
247
""")
 
248
        
 
249
    def test_verbose_log(self):
 
250
        """Verbose log includes changed files
 
251
        
 
252
        bug #4676
 
253
        """
 
254
        wt = self.make_branch_and_tree('.')
 
255
        b = wt.branch
 
256
        self.build_tree(['a'])
 
257
        wt.add('a')
 
258
        # XXX: why does a longer nick show up?
 
259
        b.nick = 'test_verbose_log'
 
260
        wt.commit(message='add a', 
 
261
                  timestamp=1132711707, 
 
262
                  timezone=36000,
 
263
                  committer='Lorem Ipsum <test@example.com>')
 
264
        logfile = file('out.tmp', 'w+')
 
265
        formatter = LongLogFormatter(to_file=logfile)
 
266
        show_log(b, formatter, verbose=True)
 
267
        logfile.flush()
 
268
        logfile.seek(0)
 
269
        log_contents = logfile.read()
 
270
        self.assertEqualDiff(log_contents, '''\
 
271
------------------------------------------------------------
 
272
revno: 1
 
273
committer: Lorem Ipsum <test@example.com>
 
274
branch nick: test_verbose_log
 
275
timestamp: Wed 2005-11-23 12:08:27 +1000
 
276
message:
 
277
  add a
 
278
added:
 
279
  a
 
280
''')
 
281