/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-12-22 16:28:47 UTC
  • mto: This revision was merged to the branch mainline in revision 4922.
  • Revision ID: john@arbash-meinel.com-20091222162847-tvnsc69to4l4uf5r
Implement a permute_for_extension helper.

Use it for all of the 'simple' extension permutations.
It basically permutes all tests in the current module, by setting TestCase.module.
Which works well for most of our extension tests. Some had more advanced
handling of permutations (extra permutations, custom vars, etc.)

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