1
# Copyright (C) 2005, 2006 by Canonical Ltd
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16
"""Test cases for pqm submit."""
21
config as _mod_config,
25
from bzrlib.plugins.pqm import pqm_submit
26
from bzrlib.tests import TestCaseWithMemoryTransport, TestCaseWithTransport
30
From: "J. Random Hacker" <jrandom@example.com>
31
Subject: commit message
32
To: PQM <pqm@example.com>
33
User-Agent: Bazaar \(.*\)
35
-----BEGIN PSEUDO-SIGNED CONTENT-----
36
star-merge .*/public/ http://example.com/submit
37
-----END PSEUDO-SIGNED CONTENT-----
41
class PQMSubmissionTests(TestCaseWithMemoryTransport):
43
def test_no_source_branch(self):
45
errors.NoMergeSource, pqm_submit.PQMSubmission,
48
def test_newlines_in_message(self):
49
source_branch = self.make_branch('source')
50
self.assertRaises(pqm_submit.BadCommitMessage,
51
pqm_submit.PQMSubmission,
52
source_branch=source_branch,
53
public_location='public-branch',
54
submit_location='submit-branch',
57
def test_check_tree_clean(self):
58
tree = self.make_branch_and_memory_tree('source')
59
submission = pqm_submit.PQMSubmission(
60
source_branch=tree.branch,
61
public_location=tree.branch.base,
62
submit_location='submit-branch',
63
message='not much to say',
66
submission.check_tree()
68
def test_check_tree_no_tree(self):
69
branch = self.make_branch('source')
70
submission = pqm_submit.PQMSubmission(
72
public_location=branch.base,
73
submit_location='submit-branch',
74
message='not much to say',
77
submission.check_tree()
79
def test_check_tree_dirty(self):
80
tree = self.make_branch_and_memory_tree('source')
85
submission = pqm_submit.PQMSubmission(
86
source_branch=tree.branch,
87
public_location=tree.branch.base,
88
submit_location='submit-branch',
89
message='not much to say',
92
self.assertRaises(errors.UncommittedChanges, submission.check_tree)
96
def test_check_public_branch(self):
97
tree = self.make_branch_and_memory_tree('source')
98
source_branch = tree.branch
99
public_branch = self.make_branch('public')
101
# Commit something to the source branch
104
tree.commit('message')
107
# Now the public branch is out of date:
108
submission = pqm_submit.PQMSubmission(
109
source_branch=source_branch,
110
public_location=public_branch.base,
111
submit_location='submit-branch',
112
message='merge message')
113
self.assertRaises(errors.PublicBranchOutOfDate,
114
submission.check_public_branch)
116
# If we bring the public branch up to date, everything is fine.
117
public_branch.pull(source_branch)
118
submission.check_public_branch()
120
def test_check_public_branch_missing(self):
121
source_branch = self.make_branch('source')
122
submission = pqm_submit.PQMSubmission(
123
source_branch=source_branch,
124
public_location=self.get_transport().abspath('public'),
125
submit_location='submit-branch',
126
message='merge message')
127
self.assertRaises(errors.NotBranchError,
128
submission.check_public_branch)
130
def test_to_lines(self):
131
source_branch = self.make_branch('source')
132
submission = pqm_submit.PQMSubmission(
133
source_branch=source_branch,
134
public_location='public-branch',
135
submit_location='submit-branch',
136
message='commit message')
137
lines = submission.to_lines()
138
self.assertEqual(['star-merge public-branch submit-branch\n'], lines)
140
def test_to_signed(self):
141
source_branch = self.make_branch('source')
142
submission = pqm_submit.PQMSubmission(
143
source_branch=source_branch,
144
public_location='public-branch',
145
submit_location='submit-branch',
146
message='commit message')
147
old_strategy = gpg.GPGStrategy
148
gpg.GPGStrategy = gpg.LoopbackGPGStrategy
150
signed = submission.to_signed()
152
gpg.GPGStrategy = old_strategy
153
self.assertEqual('-----BEGIN PSEUDO-SIGNED CONTENT-----\n'
154
'star-merge public-branch submit-branch\n'
155
'-----END PSEUDO-SIGNED CONTENT-----\n', signed)
157
def test_to_email(self):
158
source_branch = self.make_branch('source')
159
submission = pqm_submit.PQMSubmission(
160
source_branch=source_branch,
161
public_location='public-branch',
162
submit_location='submit-branch',
163
message='commit message')
164
message = submission.to_email('from@example.com', 'to@example.com',
166
self.assertEqual('from@example.com', message.get('From'))
167
self.assertEqual('to@example.com', message.get('To'))
168
self.assertEqual('commit message', message.get('Subject'))
170
def test_to_unicode_email(self):
171
"""Subject has to be raw UTF-8 not email encoded."""
172
source_branch = self.make_branch('source')
173
submission = pqm_submit.PQMSubmission(
174
source_branch=source_branch,
175
public_location='public-branch',
176
submit_location='submit-branch',
177
message=u'Commit m\xe5ss\xb5ge')
178
message = submission.to_email('from@example.com', 'to@example.com',
180
self.assertEqual('from@example.com', message.get('From'))
181
self.assertEqual('to@example.com', message.get('To'))
182
self.assertEqual('Commit m\xc3\xa5ss\xc2\xb5ge',
183
message.get('Subject'))
185
def test_submit_branch_public_location(self):
186
source_branch = self.make_branch('source')
187
public_branch = self.make_branch('public')
188
submit_branch = self.make_branch('submit')
189
submit_public_branch = self.make_branch('submit_public')
190
submit_branch.set_public_branch(submit_public_branch.base)
191
source_branch.set_submit_branch(submit_branch.base)
192
submission = pqm_submit.PQMSubmission(
193
source_branch=source_branch,
194
public_location='public',
195
message=u'Commit m\xe5ss\xb5ge')
196
self.assertEqual(submit_public_branch.base, submission.submit_location)
199
class PQMSubmissionLocationsTests(TestCaseWithTransport):
201
def test_find_public_branch(self):
202
source_branch = self.make_branch('source')
203
source_branch.set_public_branch('http://example.com/public')
204
# Also set the deprecated public_repository config item to
205
# show that public_branch is used in preference to it.
206
source_branch.get_config().set_user_option(
207
'public_repository', 'bad-value')
209
submission = pqm_submit.PQMSubmission(
210
source_branch=source_branch,
211
submit_location='submit-branch',
212
message='commit message')
213
self.assertEqual('http://example.com/public',
214
submission.public_location)
216
def test_find_public_branch_from_repo(self):
217
# Test that public_location can be inferred from the obsolete
218
# "public_repository" config option.
219
source_repo = self.make_repository('repo', shared=True)
220
source_branch = self.make_bzrdir('repo/source').create_branch()
222
config = _mod_config.LocationConfig(
223
source_repo.bzrdir.root_transport.base)
224
config.set_user_option(
225
'public_repository', 'http://example.com/repo',
226
store=_mod_config.STORE_LOCATION_NORECURSE)
228
submission = pqm_submit.PQMSubmission(
229
source_branch=source_branch,
230
submit_location='submit-branch',
231
message='commit message')
232
self.assertEqual('http://example.com/repo/source',
233
submission.public_location)
235
def test_find_public_branch_missing(self):
236
source_branch = self.make_branch('source')
238
errors.BzrCommandError, pqm_submit.PQMSubmission,
239
source_branch=source_branch,
240
submit_location='submit-branch',
241
message='commit message')
243
def test_find_submit_branch(self):
244
source_branch = self.make_branch('source')
245
source_branch.set_submit_branch('http://example.com/submit')
247
submission = pqm_submit.PQMSubmission(
248
source_branch=source_branch,
249
public_location='public-branch',
250
message='commit message')
251
self.assertEqual('http://example.com/submit',
252
submission.submit_location)
254
def test_find_submit_branch_from_pqm_branch(self):
255
# Test that submit_branch can be picked up from the obsolete
256
# pqm_branch config option.
257
source_branch = self.make_branch('source')
258
source_branch.get_config().set_user_option(
259
'pqm_branch', 'http://example.com/submit')
260
# pqm_branch is used in preference to the submit_branch:
261
source_branch.set_submit_branch('bad-value')
263
submission = pqm_submit.PQMSubmission(
264
source_branch=source_branch,
265
public_location='public-branch',
266
message='commit message')
267
self.assertEqual('http://example.com/submit',
268
submission.submit_location)
270
def test_find_submit_branch_missing(self):
271
source_branch = self.make_branch('source')
273
errors.NoSubmitBranch, pqm_submit.PQMSubmission,
274
source_branch=source_branch,
275
public_location='public-branch',
276
message='commit message')
278
def run_bzr_fakemail(self, *args, **kwargs):
279
# Run with fake smtplib and gpg stubs in place:
281
def sendmail(self, from_, to, message):
282
sendmail_calls.append((self, from_, to, message))
284
def connect(self, host='localhost', port=0):
285
connect_calls.append((self, host, port))
288
def has_extn(self, extn):
292
old_sendmail = smtplib.SMTP.sendmail
293
smtplib.SMTP.sendmail = sendmail
294
old_connect = smtplib.SMTP.connect
295
smtplib.SMTP.connect = connect
296
old_ehlo = smtplib.SMTP.ehlo
297
smtplib.SMTP.ehlo = ehlo
298
old_has_extn = smtplib.SMTP.has_extn
299
smtplib.SMTP.has_extn = has_extn
300
old_starttls = smtplib.SMTP.starttls
301
smtplib.SMTP.starttls = starttls
302
old_strategy = gpg.GPGStrategy
303
gpg.GPGStrategy = gpg.LoopbackGPGStrategy
305
result = self.run_bzr(*args, **kwargs)
307
smtplib.SMTP.sendmail = old_sendmail
308
smtplib.SMTP.connect = old_connect
309
smtplib.SMTP.ehlo = old_ehlo
310
smtplib.SMTP.has_extn = old_has_extn
311
smtplib.SMTP.starttls = old_starttls
312
gpg.GPGStrategy = old_strategy
314
return result + (connect_calls, sendmail_calls)
316
def test_pqm_submit(self):
317
source_branch = self.make_branch('source')
318
public_branch = self.make_branch('public')
319
source_branch.set_public_branch(public_branch.base)
320
source_branch.set_submit_branch('http://example.com/submit')
321
config = source_branch.get_config()
322
config.set_user_option('pqm_email', 'PQM <pqm@example.com>')
323
config.set_user_option(
324
'email', 'J. Random Hacker <jrandom@example.com>')
326
out, err, connect_calls, sendmail_calls = \
327
self.run_bzr_fakemail(['pqm-submit', '-m', 'commit message',
329
self.assertEqual('', out)
330
self.assertEqual(1, len(connect_calls))
331
call = connect_calls[0]
332
self.assertEqual(('localhost', 0), call[1:3])
333
self.assertEqual(1, len(sendmail_calls))
334
call = sendmail_calls[0]
335
self.assertEqual(('jrandom@example.com', ['pqm@example.com']),
337
self.assertContainsRe(call[3], EMAIL)
339
def test_dirty_pqm_submit(self):
340
source_tree = self.make_branch_and_tree('source')
341
self.build_tree(['source/foo'])
342
source_tree.add(['foo'])
344
public_branch = self.make_branch('public')
345
source_tree.branch.set_public_branch(public_branch.base)
346
source_tree.branch.set_submit_branch('http://example.com/submit')
347
config = source_tree.branch.get_config()
348
config.set_user_option('pqm_email', 'PQM <pqm@example.com>')
349
config.set_user_option(
350
'email', 'J. Random Hacker <jrandom@example.com>')
352
out, err, connect_calls, sendmail_calls = \
353
self.run_bzr_fakemail(['pqm-submit', '-m', 'commit message',
356
self.assertContainsRe(err,
357
r'Working tree ".*/source/" has uncommitted changes\.')
359
def test_submit_subdir_of_branch(self):
360
source_branch = self.make_branch('source')
361
source_branch.set_submit_branch('http://example.com/submit')
362
config = source_branch.get_config()
363
out, err, connect_calls, sendmail_calls = \
364
self.run_bzr_fakemail(['pqm-submit', '-m', 'commit message',
367
self.assertContainsRe(err, 'bzr: ERROR: No working tree was found')
369
def test_submit_branch(self):
370
"""Test that --submit-branch overrides local config."""
371
source_branch = self.make_branch('source')
372
public_branch = self.make_branch('public')
373
source_branch.set_public_branch(public_branch.base)
374
source_branch.set_submit_branch('http://a/very/different/branch')
375
config = source_branch.get_config()
376
config.set_user_option('pqm_email', 'PQM <pqm@example.com>')
377
config.set_user_option(
378
'email', 'J. Random Hacker <jrandom@example.com>')
380
(out, err, connect_calls,
381
sendmail_calls) = self.run_bzr_fakemail(
382
['pqm-submit', '-m', 'commit message',
383
'--submit-branch', 'http://example.com/submit',
386
self.assertEqual('', out)
387
self.assertEqual(1, len(connect_calls))
388
call = connect_calls[0]
389
self.assertEqual(('localhost', 0), call[1:3])
390
self.assertEqual(1, len(sendmail_calls))
391
call = sendmail_calls[0]
392
self.assertEqual(('jrandom@example.com', ['pqm@example.com']),
394
self.assertContainsRe(call[3], EMAIL)