27
29
"""Set up data for the tests."""
28
30
super(BugResolverTests, self).setUp()
31
self.now = datetime.utcnow()
29
32
self.proposal = Thing()
30
33
self.plugin = BugResolver()
34
self.plugin.config = {
35
"set_milestone": "False",
36
"default_milestone": None}
37
self.milestone_untargeted_a = Thing(name="a", date_targeted=None)
38
self.milestone_past = Thing(
40
date_targeted=self.now - timedelta(weeks=2))
41
self.milestone_future = Thing(
43
date_targeted=self.now + timedelta(weeks=2))
44
self.milestone_far_future = Thing(
46
date_targeted=self.now + timedelta(weeks=6))
47
self.milestone_untargeted_b = Thing(name="b", date_targeted=None)
48
self.milestone_untargeted_c = Thing(name="c", date_targeted=None)
49
self.milestone_with_bug = Thing(
51
date_targeted=self.now - timedelta(weeks=3),
52
bug=Thing(id=12345), bug_target_name="foo_project")
31
53
self.series = [Thing(name='trunk'),
32
54
Thing(name='stable')]
33
55
self.projects = [Thing(name='target',
40
62
self.targets[0] = self.projects[0]
41
63
self.bugs = {'0': Thing(
42
64
bug_tasks=[Thing(target=self.targets[0], status=u'In Progress',
43
lp_save=self.lp_save),
65
lp_save=self.lp_save, milestone=None,
67
bug_target_name=self.targets[0].name),
44
68
Thing(target=self.targets[2], status=u'Incomplete',
45
lp_save=self.lp_save)]),
69
lp_save=self.lp_save, milestone=None,
71
bug_target_name=self.targets[2].name)]),
47
73
bug_tasks=[Thing(target=self.targets[1], status=u'Confirmed',
48
lp_save=self.lp_save)])}
75
milestone=self.milestone_with_bug,
77
bug_target_name=self.targets[2].name)])}
78
# Insert out of order to make sure they sort correctly.
80
self.milestone_far_future, self.milestone_with_bug,
81
self.milestone_past, self.milestone_future]
82
self.milestones_extended = [
83
self.milestone_untargeted_c, self.milestone_untargeted_b,
84
self.milestone_untargeted_a]
85
self.milestones_extended.extend(self.milestones)
86
self.projects[0].active_milestones = self.milestones
87
self.projects[1].active_milestones = self.milestones_extended
50
89
def getSeries(self, name=None):
51
90
"""Faux getSeries for testing."""
71
110
self.assertEqual(self.bugs['0'].bug_tasks[1].status, u'Incomplete')
72
111
self.assertEqual(self.bugs['1'].bug_tasks[0].status, u'Confirmed')
113
def test_run_with_set_milestone(self):
115
Test plug-in with the set_milestone config setting = true. Will
116
auto-resolve milestone using algorithm in find_target_milestone
117
and set. Test that bug0/task0 and bug1/task0 get the correct
118
milestone set. bug0/task1 is incomplete so should not be touched.
120
target = Thing(fixed_bugs=self.bugs.keys(),
121
lp_branch=Thing(project=self.projects[0],
122
bzr_identity='lp:target'),
123
config=Thing(set_milestone="true"))
124
launchpad = Thing(bugs=self.bugs)
125
command = Thing(launchpad=launchpad)
126
self.plugin.run(command=command, target=target, source=None,
127
proposal=self.proposal)
128
self.assertEqual(self.bugs['0'].bug_tasks[0].milestone,
129
self.milestone_future)
130
self.assertEqual(self.bugs['1'].bug_tasks[0].milestone,
131
self.milestone_with_bug)
132
self.assertIsNone(self.bugs['0'].bug_tasks[1].milestone)
74
134
def test_run_with_no_bugs(self):
75
135
"""Test that bug resolution for no bugs does nothing."""
76
136
target = Thing(fixed_bugs=None,
109
169
self.assertEqual(self.bugs['0'].bug_tasks[0].status, u'In Progress')
110
170
self.assertEqual(self.bugs['0'].bug_tasks[1].status, u'Incomplete')
111
171
self.assertEqual(self.bugs['1'].bug_tasks[0].status, u'Confirmed')
173
def test__find_target_milestone_older(self):
174
"""Dates before all milestones return the oldest milestone."""
175
milestone = self.plugin._find_target_milestone(
177
self.milestone_past.date_targeted - timedelta(weeks=1))
178
self.assertEqual(milestone, self.milestone_past)
180
def test__find_target_milestone_between(self):
181
"""Test that dates between milestones return the closest newest."""
182
milestone = self.plugin._find_target_milestone(
184
self.milestone_past.date_targeted + timedelta(weeks=1))
185
self.assertTrue(self.now < self.milestone_future.date_targeted)
186
self.assertTrue(self.now > self.milestone_past.date_targeted)
187
self.assertEqual(milestone, self.milestone_future)
189
def test__find_target_milestone_newer(self):
190
"""Test that dates after all milestones return the newest."""
191
milestone = self.plugin._find_target_milestone(
193
self.milestone_far_future.date_targeted + timedelta(weeks=1))
194
self.assertEqual(milestone, self.milestone_far_future)
196
def test__find_target_milestone_lexical_sort_past_dates(self):
197
"""Dates after milestones return the least sorted no-expected-date."""
198
milestone = self.plugin._find_target_milestone(
200
self.milestone_far_future.date_targeted + timedelta(weeks=1))
201
self.assertEqual(milestone, self.milestone_untargeted_a)
203
def test__find_target_milestone_with_default(self):
204
"""Test that specifying a default gets a specific milestone."""
205
self.plugin.config["default_milestone"] = "c"
206
milestone = self.plugin._find_target_milestone(
208
self.milestone_far_future.date_targeted + timedelta(weeks=1))
209
self.assertEqual(milestone, self.milestone_untargeted_c)
211
def test__find_milestone_positive(self):
212
"""Given a project, the list of milestones is returned."""
213
milestones = self.plugin._find_milestones(self.projects[1])
214
self.assertEqual(len(milestones), 7)
216
def test__find_milestone_negative(self):
217
"""Given a project with no milestones, _find_milestone handles it"""
218
milestones = self.plugin._find_milestones(Thing(active_milestones=[]))
219
self.assertEqual(len(milestones), 0)
221
def test__find_milestone_specific_negative(self):
222
"""Find a secific milestone that isn't there, check for log"""
223
self.plugin.logger.warning = MagicMock()
224
self.plugin.config["default_milestone"] = "FOO"
225
milestones = self.plugin._find_milestones(self.projects[0])
226
self.assertEqual(len(milestones), 0)
227
self.assertEqual(self.plugin.logger.warning.call_count, 1)
229
def test__find_milestone_no_dates(self):
230
"""Find a specific milestones without a targeted date"""
231
self.plugin.config["default_milestone"] = "b"
232
milestones = self.plugin._find_milestones(self.projects[1])
233
self.assertEqual(len(milestones), 1)
234
self.assertEqual(milestones[0], self.milestone_untargeted_b)
236
def test__get_and_parse_config_set_milestone_true_upper(self):
237
"""Test config parsing - set_milestone: True."""
238
config = self.plugin._get_and_parse_config(
239
Thing(config=Thing(set_milestone="True")))
240
self.assertEqual(config["set_milestone"], True)
242
def test__get_and_parse_config_set_milestone_one(self):
243
"""Test config parsing - set_milestone: 1."""
244
config = self.plugin._get_and_parse_config(
245
Thing(config=Thing(set_milestone="1")))
246
self.assertEqual(config["set_milestone"], True)
248
def test__get_and_parse_config_set_milestone_true_lower(self):
249
"""Test config parsing - set_milestone: true."""
250
config = self.plugin._get_and_parse_config(
251
Thing(config=Thing(set_milestone="true")))
252
self.assertEqual(config["set_milestone"], True)
254
def test__get_and_parse_config_default_milestone_A(self):
255
"""Test config parsing - default_milestone: A."""
256
config = self.plugin._get_and_parse_config(
257
Thing(config=Thing(default_milestone="A")))
258
self.assertEqual(config["default_milestone"], "A")
260
def test__get_and_parse_config_default_milestone_none(self):
261
"""Test config parsing - default_milestone: ."""
262
config = self.plugin._get_and_parse_config(
263
Thing(config=Thing(default_milestone="")))
264
self.assertEqual(config["default_milestone"], None)
266
def test__get_and_parse_config_default_milestone_default(self):
267
"""Test config parsing - defaults."""
268
config = self.plugin._get_and_parse_config(
269
Thing(config=Thing()))
270
self.assertEqual(config["set_milestone"], False)
271
self.assertEqual(config["default_milestone"], None)
273
def test__set_milestone_on_task_config_not_set(self):
274
"""config option not set, no-op"""
275
self.plugin.logger.info = MagicMock()
276
self.plugin.logger.warning = MagicMock()
277
self.plugin.config = {
278
"set_milestone": False, "default_milestone": None}
279
self.plugin._set_milestone_on_task(
280
self.projects[0], self.bugs['0'].bug_tasks[0])
281
self.assertEqual(self.bugs['0'].bug_tasks[0].milestone, None)
282
self.assertEqual(self.plugin.logger.info.call_count, 0)
283
self.assertEqual(self.plugin.logger.warning.call_count, 0)
285
def test__set_milestone_on_task_milestone_already_set(self):
286
"""milestone is already set, should leave task untouched"""
287
self.plugin.logger.info = MagicMock()
288
self.plugin.config = {"set_milestone": True, "default_milestone": "past"}
289
self.plugin._set_milestone_on_task(
290
self.projects[0], self.bugs['1'].bug_tasks[0])
292
self.bugs['1'].bug_tasks[0].milestone, self.milestone_with_bug)
293
self.assertIn("already has milestone",
294
self.plugin.logger.info.call_args[0][0])
296
def test__set_milestone_on_task_config_set(self):
297
"""config option set, milestone is being set, action logged"""
298
self.plugin.logger.info = MagicMock()
299
self.plugin.config = {"set_milestone": True, "default_milestone": None}
300
self.plugin._set_milestone_on_task(
301
self.projects[0], self.bugs['0'].bug_tasks[0])
303
self.bugs['0'].bug_tasks[0].milestone, self.milestone_future)
304
self.assertEqual(self.plugin.logger.info.call_count, 1)