1
from unittest import TestCase
2
from mock import Mock, patch
7
JUJUBOT_USER = {'login': 'jujubot', 'id': 7779494}
8
OTHER_USER = {'login': 'user', 'id': 1}
19
def make_fake_lp(series=False, bugs=False, project_name='juju', tags=[]):
20
"""Return a fake Lp lib object based on Mocks"""
23
self_link='https://lp/j/98765', title='one', status='Triaged')
24
task_1.bug.tags = tags
26
self_link='https://lp/j/54321', title='two', status='Triaged')
27
task_2.bug.tags = tags
28
bugs = [task_1, task_2]
31
lp = Mock(_target=None, projects={})
35
series.searchTasks.return_value = bugs
39
project.searchTasks.return_value = bugs
41
project.getSeries.return_value = series
42
lp.projects[project_name] = project
46
class CheckBlockers(TestCase):
48
def test_parse_args_check(self):
49
args = check_blockers.parse_args(['check', 'MASTER', '17'])
50
self.assertEqual('check', args.command)
51
self.assertEqual('master', args.branch)
52
self.assertEqual('17', args.pull_request)
54
def test_parse_args_check_pr_optional(self):
55
args = check_blockers.parse_args(['check', 'master'])
56
self.assertEqual('check', args.command)
57
self.assertEqual('master', args.branch)
58
self.assertIsNone(args.pull_request)
60
def test_parse_args_block_ci_testing(self):
61
args = check_blockers.parse_args(['block-ci-testing', 'FEATURE'])
62
self.assertEqual('block-ci-testing', args.command)
63
self.assertEqual('feature', args.branch)
64
self.assertIsNone(args.pull_request)
66
def test_parse_args_check_branch_optional(self):
67
args = check_blockers.parse_args(['check'])
68
self.assertEqual('check', args.command)
69
self.assertEqual('master', args.branch)
70
self.assertIsNone(args.pull_request)
72
def test_parse_args_update(self):
73
args = check_blockers.parse_args(
74
['-c', './foo.cred', 'update', 'MASTER', '1234'])
75
self.assertEqual('update', args.command)
76
self.assertEqual('master', args.branch)
77
self.assertEqual('1234', args.build)
78
self.assertEqual('./foo.cred', args.credentials_file)
80
def test_main_check(self):
82
args = check_blockers.parse_args(['check', 'master', '17'])
83
with patch('check_blockers.get_lp', autospec=True,
84
return_value='lp') as gl:
85
with patch('check_blockers.get_lp_bugs', autospec=True,
86
return_value=bugs) as glb:
87
with patch('check_blockers.get_reason', autospec=True,
88
return_value=(0, 'foo')) as gr:
89
code = check_blockers.main(['check', 'master', '17'])
90
gl.assert_called_with('check_blockers', credentials_file=None)
91
glb.assert_called_with('lp', 'master', ['blocker'])
92
gr.assert_called_with(bugs, args)
93
self.assertEqual(0, code)
95
def test_main_block_ci_testing(self):
97
args = check_blockers.parse_args(['block-ci-testing', 'feature'])
98
with patch('check_blockers.get_lp', autospec=True,
99
return_value='lp') as gl:
100
with patch('check_blockers.get_lp_bugs', autospec=True,
101
return_value=bugs) as glb:
102
with patch('check_blockers.get_reason', autospec=True,
103
return_value=(0, 'foo')) as gr:
104
code = check_blockers.main(['block-ci-testing', 'feature'])
105
gl.assert_called_with('check_blockers', credentials_file=None)
106
glb.assert_called_with('lp', 'feature', ['block-ci-testing'])
107
gr.assert_called_with(bugs, args)
108
self.assertEqual(0, code)
110
def test_main_update(self):
112
argv = ['-c', './foo.cred', 'update', '--dry-run', 'master', '1234']
113
with patch('check_blockers.get_lp', autospec=True,
114
return_value='lp') as gl:
115
with patch('check_blockers.get_lp_bugs', autospec=True,
116
return_value=bugs) as glb:
117
with patch('check_blockers.update_bugs', autospec=True,
118
return_value=[0, 'Updating']) as ub:
119
code = check_blockers.main(argv)
120
gl.assert_called_with('check_blockers', credentials_file='./foo.cred')
121
glb.assert_called_with('lp', 'master', ['blocker', 'ci'])
122
ub.assert_called_with(bugs, 'master', '1234', dry_run=True)
123
self.assertEqual(0, code)
125
def test_get_lp_bugs_with_master_branch(self):
126
lp = make_fake_lp(series=False, bugs=True, tags=['blocker'])
127
bugs = check_blockers.get_lp_bugs(lp, 'master', ['blocker'])
128
self.assertEqual(['54321', '98765'], sorted(bugs.keys()))
129
project = lp.projects['juju']
130
self.assertEqual(0, project.getSeries.call_count)
131
project.searchTasks.assert_called_with(
132
status=check_blockers.BUG_STATUSES,
133
importance=check_blockers.BUG_IMPORTANCES,
134
tags=check_blockers.BUG_TAGS, tags_combinator='All')
136
def test_get_lp_bugs_with_supported_branch(self):
137
lp = make_fake_lp(series=True, bugs=True,
138
project_name='juju-core', tags=['blocker'])
139
bugs = check_blockers.get_lp_bugs(lp, '1.20', ['blocker'])
140
self.assertEqual(['54321', '98765'], sorted(bugs.keys()))
141
project = lp.projects['juju-core']
142
project.getSeries.assert_called_with(name='1.20')
144
series.searchTasks.assert_called_with(
145
status=check_blockers.BUG_STATUSES,
146
importance=check_blockers.BUG_IMPORTANCES,
147
tags=check_blockers.BUG_TAGS, tags_combinator='All')
149
def test_get_lp_bugs_with_unsupported_branch(self):
150
lp = make_fake_lp(series=False, bugs=False)
151
bugs = check_blockers.get_lp_bugs(lp, 'foo', ['blocker'])
152
self.assertEqual({}, bugs)
153
project = lp.projects['juju']
154
project.getSeries.assert_called_with(name='foo')
155
self.assertEqual(0, project.searchTasks.call_count)
157
def test_get_lp_bugs_without_blocking_bugs(self):
158
lp = make_fake_lp(series=False, bugs=False)
159
bugs = check_blockers.get_lp_bugs(lp, 'master', ['blocker'])
160
self.assertEqual({}, bugs)
161
project = lp.projects['juju']
162
project.searchTasks.assert_called_with(
163
status=check_blockers.BUG_STATUSES,
164
importance=check_blockers.BUG_IMPORTANCES,
165
tags=check_blockers.BUG_TAGS, tags_combinator='All')
167
def test_get_lp_bugs_error(self):
168
lp = make_fake_lp(series=False, bugs=True)
169
with self.assertRaises(ValueError):
170
check_blockers.get_lp_bugs(lp, 'master', [])
172
def test_get_reason_without_blocking_bugs(self):
173
args = check_blockers.parse_args(['check', 'master', '17'])
174
with patch('check_blockers.get_json') as gj:
175
code, reason = check_blockers.get_reason({}, args)
176
self.assertEqual(0, code)
177
self.assertEqual('No blocking bugs', reason)
178
self.assertEqual(0, gj.call_count)
180
def test_get_reason_without_comments(self):
181
args = check_blockers.parse_args(['check', 'master', '17'])
182
with patch('check_blockers.get_json') as gj:
184
bugs = {'98765': {'self_link': 'https://lp/j/98765'}}
185
code, reason = check_blockers.get_reason(bugs, args)
186
self.assertEqual(1, code)
187
self.assertEqual("Does not match ['fixes-98765']", reason)
188
gj.assert_called_with((check_blockers.GH_COMMENTS.format('17')))
190
def test_get_reason_with_blockers_no_match(self):
191
args = check_blockers.parse_args(['check', 'master', '17'])
192
with patch('check_blockers.get_json') as gj:
193
gj.return_value = [{'body': '$$merge$$', 'user': OTHER_USER}]
194
bugs = {'98765': {'self_link': 'https://lp/j/98765'}}
195
code, reason = check_blockers.get_reason(bugs, args)
196
self.assertEqual(1, code)
197
self.assertEqual("Does not match ['fixes-98765']", reason)
199
def test_get_reason_with_blockers_with_match(self):
200
args = check_blockers.parse_args(['check', 'master', '17'])
201
with patch('check_blockers.get_json') as gj:
203
{'body': '$$merge$$', 'user': OTHER_USER},
204
{'body': 'la la __fixes-98765__ ha ha', 'user': OTHER_USER}]
205
bugs = {'98765': {'self_link': 'https://lp/j/98765'}}
206
code, reason = check_blockers.get_reason(bugs, args)
207
self.assertEqual(0, code)
208
self.assertEqual("Matches fixes-98765", reason)
210
def test_get_reason_with_blockers_with_jujubot_comment(self):
211
args = check_blockers.parse_args(['check', 'master', '17'])
212
with patch('check_blockers.get_json') as gj:
214
{'body': '$$merge$$', 'user': OTHER_USER},
215
{'body': 'la la $$fixes-98765$$ ha ha', 'user': JUJUBOT_USER}]
216
bugs = {'98765': {'self_link': 'https://lp/j/98765'}}
217
code, reason = check_blockers.get_reason(bugs, args)
218
self.assertEqual(1, code)
219
self.assertEqual("Does not match ['fixes-98765']", reason)
221
def test_get_reason_with_blockers_with_reply_jujubot_comment(self):
222
args = check_blockers.parse_args(['check', 'master', '17'])
223
with patch('check_blockers.get_json') as gj:
225
{'body': '$$merge$$', 'user': OTHER_USER},
226
{'body': 'Juju bot wrote $$fixes-98765$$', 'user': OTHER_USER}]
227
bugs = {'98765': {'self_link': 'https://lp/j/98765'}}
228
code, reason = check_blockers.get_reason(bugs, args)
229
self.assertEqual(1, code)
230
self.assertEqual("Does not match ['fixes-98765']", reason)
232
def test_get_reason_with_blockers_with_jfdi(self):
233
args = check_blockers.parse_args(['check', 'master', '17'])
234
with patch('check_blockers.get_json') as gj:
236
{'body': '$$merge$$', 'user': OTHER_USER},
237
{'body': 'la la __JFDI__ ha ha', 'user': OTHER_USER}]
238
bugs = {'98765': {'self_link': 'https://lp/j/98765'}}
239
code, reason = check_blockers.get_reason(bugs, args)
240
self.assertEqual(0, code)
241
self.assertEqual("Engineer says JFDI", reason)
243
def test_get_json(self):
245
response.getcode.return_value = 200
246
response.read.side_effect = ['{"result": []}']
247
with patch('check_blockers.urllib2.urlopen') as urlopen:
248
urlopen.return_value = response
249
json = check_blockers.get_json("http://api.testing/")
250
request = urlopen.call_args[0][0]
251
self.assertEqual(request.get_full_url(), "http://api.testing/")
252
self.assertEqual(request.get_header("Cache-control"),
253
"max-age=0, must-revalidate")
254
self.assertEqual(json, {"result": []})
256
def test_update_bugs(self):
257
lp = make_fake_lp(series=False, bugs=True, tags=['blocker'])
258
bugs = check_blockers.get_lp_bugs(lp, 'master', ['blocker'])
259
code, changes = check_blockers.update_bugs(
260
bugs, 'master', '1234', dry_run=False)
261
self.assertEqual(0, code)
262
self.assertIn('Updated two', changes)
263
self.assertEqual('Fix Released', bugs['54321'].status)
264
self.assertEqual(1, bugs['54321'].lp_save.call_count)
265
expected_subject = 'Fix Released in juju-core master'
267
'Juju-CI verified that this issue is %s:\n'
268
' http://reports.vapour.ws/releases/1234' % expected_subject)
269
bugs['54321'].bug.newMessage.assert_called_with(
270
subject=expected_subject, content=expected_content)
272
def test_update_bugs_skipped(self):
274
series=False, bugs=True, tags=['blocker', 'intermittent-failure'])
275
bugs = check_blockers.get_lp_bugs(lp, 'master', ['blocker'])
276
code, changes = check_blockers.update_bugs(
277
bugs, 'master', '1234', dry_run=False)
278
self.assertEqual(0, code)
279
self.assertIn('Skipping intermittent-failure', changes)
280
self.assertEqual('Triaged', bugs['54321'].status)
281
self.assertEqual(0, bugs['54321'].lp_save.call_count)
282
self.assertEqual(0, bugs['54321'].bug.newMessage.call_count)
284
def test_update_bugs_with_dry_run(self):
285
lp = make_fake_lp(series=False, bugs=True)
286
bugs = check_blockers.get_lp_bugs(lp, 'master', ['blocker'])
287
code, changes = check_blockers.update_bugs(
288
bugs, 'master', '1234', dry_run=True)
289
self.assertEqual(0, bugs['54321'].lp_save.call_count)