/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_msgeditor.py

  • Committer: John Arbash Meinel
  • Date: 2009-06-18 18:18:36 UTC
  • mto: This revision was merged to the branch mainline in revision 4461.
  • Revision ID: john@arbash-meinel.com-20090618181836-biodfkat9a8eyzjz
The new add_inventory_by_delta is returning a CHKInventory when mapping from NULL
Which is completely valid, but 'broke' one of the tests.
So to fix it, changed the test to use CHKInventories on both sides, and add an __eq__
member. The nice thing is that CHKInventory.__eq__ is fairly cheap, since it only
has to check the root keys.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2005 Canonical Ltd
 
2
#
 
3
# This program is free software; you can redistribute it and/or modify
 
4
# it under the terms of the GNU General Public License as published by
 
5
# the Free Software Foundation; either version 2 of the License, or
 
6
# (at your option) any later version.
 
7
#
 
8
# This program is distributed in the hope that it will be useful,
 
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
# GNU General Public License for more details.
 
12
#
 
13
# You should have received a copy of the GNU General Public License
 
14
# along with this program; if not, write to the Free Software
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
 
 
17
"""Test commit message editor.
 
18
"""
 
19
 
 
20
import os
 
21
import sys
 
22
 
 
23
from bzrlib import (
 
24
    commit,
 
25
    errors,
 
26
    msgeditor,
 
27
    osutils,
 
28
    tests,
 
29
    trace,
 
30
    )
 
31
from bzrlib.branch import Branch
 
32
from bzrlib.config import ensure_config_dir_exists, config_filename
 
33
from bzrlib.msgeditor import (
 
34
    make_commit_message_template_encoded,
 
35
    edit_commit_message_encoded
 
36
)
 
37
from bzrlib.tests import (
 
38
    TestCaseWithTransport,
 
39
    TestNotApplicable,
 
40
    TestSkipped,
 
41
    multiply_tests,
 
42
    probe_bad_non_ascii,
 
43
    split_suite_by_re,
 
44
    )
 
45
from bzrlib.tests.EncodingAdapter import encoding_scenarios
 
46
from bzrlib.trace import mutter
 
47
 
 
48
 
 
49
def load_tests(standard_tests, module, loader):
 
50
    """Parameterize the test for tempfile creation with different encodings."""
 
51
    to_adapt, result = split_suite_by_re(standard_tests,
 
52
        "test__create_temp_file_with_commit_template_in_unicode_dir")
 
53
    return multiply_tests(to_adapt, encoding_scenarios, result)
 
54
 
 
55
 
 
56
class MsgEditorTest(TestCaseWithTransport):
 
57
 
 
58
    def make_uncommitted_tree(self):
 
59
        """Build a branch with uncommitted unicode named changes in the cwd."""
 
60
        working_tree = self.make_branch_and_tree('.')
 
61
        b = working_tree.branch
 
62
        filename = u'hell\u00d8'
 
63
        try:
 
64
            self.build_tree_contents([(filename, 'contents of hello')])
 
65
        except UnicodeEncodeError:
 
66
            raise TestSkipped("can't build unicode working tree in "
 
67
                "filesystem encoding %s" % sys.getfilesystemencoding())
 
68
        working_tree.add(filename)
 
69
        return working_tree
 
70
 
 
71
    def test_commit_template(self):
 
72
        """Test building a commit message template"""
 
73
        working_tree = self.make_uncommitted_tree()
 
74
        template = msgeditor.make_commit_message_template(working_tree,
 
75
                                                                 None)
 
76
        self.assertEqualDiff(template,
 
77
u"""\
 
78
added:
 
79
  hell\u00d8
 
80
""")
 
81
 
 
82
    def make_multiple_pending_tree(self):
 
83
        from bzrlib import config
 
84
        config.GlobalConfig().set_user_option('email',
 
85
                                              'Bilbo Baggins <bb@hobbit.net>')
 
86
        tree = self.make_branch_and_tree('a')
 
87
        tree.commit('Initial checkin.', timestamp=1230912900, timezone=0)
 
88
        tree2 = tree.bzrdir.clone('b').open_workingtree()
 
89
        tree.commit('Minor tweak.', timestamp=1231977840, timezone=0)
 
90
        tree2.commit('Feature X work.', timestamp=1233186240, timezone=0)
 
91
        tree3 = tree2.bzrdir.clone('c').open_workingtree()
 
92
        tree2.commit('Feature X finished.', timestamp=1233187680, timezone=0)
 
93
        tree3.commit('Feature Y, based on initial X work.',
 
94
                     timestamp=1233285960, timezone=0)
 
95
        tree.merge_from_branch(tree2.branch)
 
96
        tree.merge_from_branch(tree3.branch)
 
97
        return tree
 
98
 
 
99
    def test_commit_template_pending_merges(self):
 
100
        """Test building a commit message template when there are pending
 
101
        merges.  The commit message should show all pending merge revisions,
 
102
        as does 'status -v', not only the merge tips.
 
103
        """
 
104
        working_tree = self.make_multiple_pending_tree()
 
105
        template = msgeditor.make_commit_message_template(working_tree, None)
 
106
        self.assertEqualDiff(template,
 
107
u"""\
 
108
pending merges:
 
109
  Bilbo Baggins 2009-01-29 Feature X finished.
 
110
    Bilbo Baggins 2009-01-28 Feature X work.
 
111
  Bilbo Baggins 2009-01-30 Feature Y, based on initial X work.
 
112
""")
 
113
 
 
114
    def test_commit_template_encoded(self):
 
115
        """Test building a commit message template"""
 
116
        working_tree = self.make_uncommitted_tree()
 
117
        template = make_commit_message_template_encoded(working_tree,
 
118
                                                        None,
 
119
                                                        output_encoding='utf8')
 
120
        self.assertEqualDiff(template,
 
121
u"""\
 
122
added:
 
123
  hell\u00d8
 
124
""".encode("utf8"))
 
125
 
 
126
 
 
127
    def test_commit_template_and_diff(self):
 
128
        """Test building a commit message template"""
 
129
        working_tree = self.make_uncommitted_tree()
 
130
        template = make_commit_message_template_encoded(working_tree,
 
131
                                                        None,
 
132
                                                        diff=True,
 
133
                                                        output_encoding='utf8')
 
134
 
 
135
        self.assertTrue("""\
 
136
@@ -0,0 +1,1 @@
 
137
+contents of hello
 
138
""" in template)
 
139
        self.assertTrue(u"""\
 
140
added:
 
141
  hell\u00d8
 
142
""".encode('utf8') in template)
 
143
 
 
144
    def make_do_nothing_editor(self):
 
145
        if sys.platform == "win32":
 
146
            f = file('fed.bat', 'w')
 
147
            f.write('@rem dummy fed')
 
148
            f.close()
 
149
            return 'fed.bat'
 
150
        else:
 
151
            f = file('fed.sh', 'wb')
 
152
            f.write('#!/bin/sh\n')
 
153
            f.close()
 
154
            os.chmod('fed.sh', 0755)
 
155
            return './fed.sh'
 
156
 
 
157
    def test_run_editor(self):
 
158
        os.environ['BZR_EDITOR'] = self.make_do_nothing_editor()
 
159
        self.assertEqual(True, msgeditor._run_editor(''),
 
160
                         'Unable to run dummy fake editor')
 
161
 
 
162
    def make_fake_editor(self, message='test message from fed\\n'):
 
163
        """Set up environment so that an editor will be a known script.
 
164
 
 
165
        Sets up BZR_EDITOR so that if an editor is spawned it will run a
 
166
        script that just adds a known message to the start of the file.
 
167
        """
 
168
        f = file('fed.py', 'wb')
 
169
        f.write('#!%s\n' % sys.executable)
 
170
        f.write("""\
 
171
# coding=utf-8
 
172
import sys
 
173
if len(sys.argv) == 2:
 
174
    fn = sys.argv[1]
 
175
    f = file(fn, 'rb')
 
176
    s = f.read()
 
177
    f.close()
 
178
    f = file(fn, 'wb')
 
179
    f.write('%s')
 
180
    f.write(s)
 
181
    f.close()
 
182
""" % (message, ))
 
183
        f.close()
 
184
        if sys.platform == "win32":
 
185
            # [win32] make batch file and set BZR_EDITOR
 
186
            f = file('fed.bat', 'w')
 
187
            f.write("""\
 
188
@echo off
 
189
"%s" fed.py %%1
 
190
""" % sys.executable)
 
191
            f.close()
 
192
            os.environ['BZR_EDITOR'] = 'fed.bat'
 
193
        else:
 
194
            # [non-win32] make python script executable and set BZR_EDITOR
 
195
            os.chmod('fed.py', 0755)
 
196
            os.environ['BZR_EDITOR'] = './fed.py'
 
197
 
 
198
    def test_edit_commit_message(self):
 
199
        working_tree = self.make_uncommitted_tree()
 
200
        self.make_fake_editor()
 
201
 
 
202
        mutter('edit_commit_message without infotext')
 
203
        self.assertEqual('test message from fed\n',
 
204
                         msgeditor.edit_commit_message(''))
 
205
 
 
206
        mutter('edit_commit_message with ascii string infotext')
 
207
        self.assertEqual('test message from fed\n',
 
208
                         msgeditor.edit_commit_message('spam'))
 
209
 
 
210
        mutter('edit_commit_message with unicode infotext')
 
211
        self.assertEqual('test message from fed\n',
 
212
                         msgeditor.edit_commit_message(u'\u1234'))
 
213
 
 
214
        tmpl = edit_commit_message_encoded(u'\u1234'.encode("utf8"))
 
215
        self.assertEqual('test message from fed\n', tmpl)
 
216
 
 
217
    def test_start_message(self):
 
218
        self.make_uncommitted_tree()
 
219
        self.make_fake_editor()
 
220
        self.assertEqual('test message from fed\nstart message\n',
 
221
                         msgeditor.edit_commit_message('',
 
222
                                              start_message='start message\n'))
 
223
        self.assertEqual('test message from fed\n',
 
224
                         msgeditor.edit_commit_message('',
 
225
                                              start_message=''))
 
226
 
 
227
    def test_deleted_commit_message(self):
 
228
        working_tree = self.make_uncommitted_tree()
 
229
 
 
230
        if sys.platform == 'win32':
 
231
            os.environ['BZR_EDITOR'] = 'cmd.exe /c del'
 
232
        else:
 
233
            os.environ['BZR_EDITOR'] = 'rm'
 
234
 
 
235
        self.assertRaises((IOError, OSError), msgeditor.edit_commit_message, '')
 
236
 
 
237
    def test__get_editor(self):
 
238
        # Test that _get_editor can return a decent list of items
 
239
        bzr_editor = os.environ.get('BZR_EDITOR')
 
240
        visual = os.environ.get('VISUAL')
 
241
        editor = os.environ.get('EDITOR')
 
242
        try:
 
243
            os.environ['BZR_EDITOR'] = 'bzr_editor'
 
244
            os.environ['VISUAL'] = 'visual'
 
245
            os.environ['EDITOR'] = 'editor'
 
246
 
 
247
            ensure_config_dir_exists()
 
248
            f = open(config_filename(), 'wb')
 
249
            f.write('editor = config_editor\n')
 
250
            f.close()
 
251
 
 
252
            editors = list(msgeditor._get_editor())
 
253
            editors = [editor for (editor, cfg_src) in editors]
 
254
 
 
255
            self.assertEqual(['bzr_editor', 'config_editor', 'visual',
 
256
                              'editor'], editors[:4])
 
257
 
 
258
            if sys.platform == 'win32':
 
259
                self.assertEqual(['wordpad.exe', 'notepad.exe'], editors[4:])
 
260
            else:
 
261
                self.assertEqual(['/usr/bin/editor', 'vi', 'pico', 'nano',
 
262
                                  'joe'], editors[4:])
 
263
 
 
264
        finally:
 
265
            # Restore the environment
 
266
            if bzr_editor is None:
 
267
                del os.environ['BZR_EDITOR']
 
268
            else:
 
269
                os.environ['BZR_EDITOR'] = bzr_editor
 
270
            if visual is None:
 
271
                del os.environ['VISUAL']
 
272
            else:
 
273
                os.environ['VISUAL'] = visual
 
274
            if editor is None:
 
275
                del os.environ['EDITOR']
 
276
            else:
 
277
                os.environ['EDITOR'] = editor
 
278
 
 
279
    def test__run_editor_EACCES(self):
 
280
        """If running a configured editor raises EACESS, the user is warned."""
 
281
        os.environ['BZR_EDITOR'] = 'eacces.py'
 
282
        f = file('eacces.py', 'wb')
 
283
        f.write('# Not a real editor')
 
284
        f.close()
 
285
        # Make the fake editor unreadable (and unexecutable)
 
286
        os.chmod('eacces.py', 0)
 
287
        # Set $EDITOR so that _run_editor will terminate before trying real
 
288
        # editors.
 
289
        os.environ['EDITOR'] = self.make_do_nothing_editor()
 
290
        # Call _run_editor, capturing mutter.warning calls.
 
291
        warnings = []
 
292
        def warning(*args):
 
293
            warnings.append(args[0] % args[1:])
 
294
        _warning = trace.warning
 
295
        trace.warning = warning
 
296
        try:
 
297
            msgeditor._run_editor('')
 
298
        finally:
 
299
            trace.warning = _warning
 
300
        self.assertStartsWith(warnings[0], 'Could not start editor "eacces.py"')
 
301
 
 
302
    def test__create_temp_file_with_commit_template(self):
 
303
        # check that commit template written properly
 
304
        # and has platform native line-endings (CRLF on win32)
 
305
        create_file = msgeditor._create_temp_file_with_commit_template
 
306
        msgfilename, hasinfo = create_file('infotext','----','start message')
 
307
        self.assertNotEqual(None, msgfilename)
 
308
        self.assertTrue(hasinfo)
 
309
        expected = os.linesep.join(['start message',
 
310
                                    '',
 
311
                                    '',
 
312
                                    '----',
 
313
                                    '',
 
314
                                    'infotext'])
 
315
        self.assertFileEqual(expected, msgfilename)
 
316
 
 
317
    def test__create_temp_file_with_commit_template_in_unicode_dir(self):
 
318
        self.requireFeature(tests.UnicodeFilenameFeature)
 
319
        if hasattr(self, 'info'):
 
320
            os.mkdir(self.info['directory'])
 
321
            os.chdir(self.info['directory'])
 
322
            msgeditor._create_temp_file_with_commit_template('infotext')
 
323
        else:
 
324
            raise TestNotApplicable('Test run elsewhere with non-ascii data.')
 
325
 
 
326
    def test__create_temp_file_with_empty_commit_template(self):
 
327
        # empty file
 
328
        create_file = msgeditor._create_temp_file_with_commit_template
 
329
        msgfilename, hasinfo = create_file('')
 
330
        self.assertNotEqual(None, msgfilename)
 
331
        self.assertFalse(hasinfo)
 
332
        self.assertFileEqual('', msgfilename)
 
333
 
 
334
    def test_unsupported_encoding_commit_message(self):
 
335
        old_env = osutils.set_or_unset_env('LANG', 'C')
 
336
        try:
 
337
            # LANG env variable has no effect on Windows
 
338
            # but some characters anyway cannot be represented
 
339
            # in default user encoding
 
340
            char = probe_bad_non_ascii(osutils.get_user_encoding())
 
341
            if char is None:
 
342
                raise TestSkipped('Cannot find suitable non-ascii character '
 
343
                    'for user_encoding (%s)' % osutils.get_user_encoding())
 
344
 
 
345
            self.make_fake_editor(message=char)
 
346
 
 
347
            working_tree = self.make_uncommitted_tree()
 
348
            self.assertRaises(errors.BadCommitMessageEncoding,
 
349
                              msgeditor.edit_commit_message, '')
 
350
        finally:
 
351
            osutils.set_or_unset_env('LANG', old_env)
 
352
 
 
353
    def test_generate_commit_message_template_no_hooks(self):
 
354
        commit_obj = commit.Commit()
 
355
        self.assertIs(None,
 
356
            msgeditor.generate_commit_message_template(commit_obj))
 
357
 
 
358
    def test_generate_commit_message_template_hook(self):
 
359
        def restoreDefaults():
 
360
            msgeditor.hooks['commit_message_template'] = []
 
361
        self.addCleanup(restoreDefaults)
 
362
        msgeditor.hooks.install_named_hook("commit_message_template",
 
363
                lambda commit_obj, msg: "save me some typing\n", None)
 
364
        commit_obj = commit.Commit()
 
365
        self.assertEquals("save me some typing\n",
 
366
            msgeditor.generate_commit_message_template(commit_obj))