~launchpad-pqm/launchpad/devel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
# Copyright 2010 Canonical Ltd.  This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).

"""Tests for BugJobs."""

__metaclass__ = type

import unittest

from zope.interface import implements

from storm.store import Store

from lazr.delegates import delegates

from canonical.testing.layers import LaunchpadZopelessLayer
from lp.bugs.interfaces.bugtask import BugTaskStatus
from lp.registry.interfaces.distributionsourcepackage import (
    IDistributionSourcePackage)
from lp.testing import TestCaseWithFactory
from lp.testing.factory import LaunchpadObjectFactory


class BugUpdateHeat(TestCaseWithFactory):

    layer = LaunchpadZopelessLayer

    def test_updateHeat_calls_recalculateBugHeatCache(self):
        # This requires some instrumentation. The updateHeat() method is
        # called by many methods that may be involved in setting up a bug
        # target.
        class TestTarget:
            implements(IDistributionSourcePackage)
            delegates(IDistributionSourcePackage, context='target')

            def __init__(self, target):
                self.target = target
                self.called = False

            def recalculateBugHeatCache(self):
                self.called = True

        self.target = TestTarget(
            self.factory.makeDistributionSourcePackage(with_db=True))
        self.bugtask = self.factory.makeBugTask(target=self.target)
        self.bugtask.bug.updateHeat()
        self.assertTrue(self.target.called)


class MaxHeatByTargetBase:
    """Base class for testing a bug target's max_bug_heat attribute."""

    layer = LaunchpadZopelessLayer

    factory = LaunchpadObjectFactory()

    # The target to test.
    target = None

    # Does the target have a set method?
    delegates_setter = False

    def test_target_max_bug_heat_default(self):
        self.assertEqual(self.target.max_bug_heat, None)

    def test_set_target_max_bug_heat(self):
        if self.delegates_setter:
            self.assertRaises(
                NotImplementedError, self.target.setMaxBugHeat, 1000)
        else:
            self.target.setMaxBugHeat(1000)
            self.assertEqual(self.target.max_bug_heat, 1000)


class ProjectMaxHeatByTargetTest(MaxHeatByTargetBase, unittest.TestCase):
    """Ensure a project has a max_bug_heat value that can be set."""

    def setUp(self):
        self.target = self.factory.makeProduct()


class DistributionMaxHeatByTargetTest(MaxHeatByTargetBase, unittest.TestCase):
    """Ensure a distribution has a max_bug_heat value that can be set."""

    def setUp(self):
        self.target = self.factory.makeDistribution()


class DistributionSourcePackageMaxHeatByTargetTest(
    MaxHeatByTargetBase, unittest.TestCase):
    """Ensure distro source package has max_bug_heat value that can be set."""

    def setUp(self):
        self.target = self.factory.makeDistributionSourcePackage()


class DistributionSourcePackageNullBugHeatCacheTest(TestCaseWithFactory):
    """Ensure distro source package cache values start at None."""

    layer = LaunchpadZopelessLayer

    def setUp(self):
        TestCaseWithFactory.setUp(self)
        self.target = self.factory.makeDistributionSourcePackage()

    def test_null_max_bug_heat(self):
        self.assertEqual(None, self.target.max_bug_heat)

    def test_null_total_bug_heat(self):
        self.assertEqual(None, self.target.total_bug_heat)

    def test_null_bug_count(self):
        self.assertEqual(None, self.target.bug_count)


class DistributionSourcePackageZeroRecalculateBugHeatCacheTest(
    TestCaseWithFactory):
    """Ensure distro source package cache values become zero properly."""

    layer = LaunchpadZopelessLayer

    def setUp(self):
        TestCaseWithFactory.setUp(self)
        self.target = self.factory.makeDistributionSourcePackage()
        self.target.recalculateBugHeatCache()

    def test_zero_max_bug_heat(self):
        self.assertEqual(0, self.target.max_bug_heat)

    def test_zero_total_bug_heat(self):
        self.assertEqual(0, self.target.total_bug_heat)

    def test_zero_bug_count(self):
        self.assertEqual(0, self.target.bug_count)


class DistributionSourcePackageMultipleBugsRecalculateBugHeatCacheTest(
    TestCaseWithFactory):
    """Ensure distro source package cache values are set properly."""

    layer = LaunchpadZopelessLayer

    def setUp(self):
        TestCaseWithFactory.setUp(self)
        self.target = self.factory.makeDistributionSourcePackage(with_db=True)
        self.bugtask1 = self.factory.makeBugTask(target=self.target)
        self.bugtask2 = self.factory.makeBugTask(target=self.target)
        self.bugtask3 = self.factory.makeBugTask(target=self.target)
        self.bugtask4 = self.factory.makeBugTask(target=self.target)
        # A closed bug is not include in DSP bug heat calculations.
        self.bugtask3.transitionToStatus(
            BugTaskStatus.FIXRELEASED, self.target.distribution.owner)
        # A duplicate bug is not include in DSP bug heat calculations.
        self.bugtask4.bug.markAsDuplicate(self.bugtask1.bug)
        # Bug heat gets calculated by complicated rules in a db
        # stored procedure. We will override them here to avoid
        # testing inconsitencies if those values are calculated
        # differently in the future.
        # target.recalculateBugHeatCache() should be called
        # automatically by bug.setHeat().
        bug1 = self.bugtask1.bug
        bug2 = self.bugtask2.bug
        bug3 = self.bugtask3.bug
        bug1.setHeat(7)
        bug2.setHeat(19)
        bug3.setHeat(11)
        Store.of(bug1).flush()
        self.max_heat = max(bug1.heat, bug2.heat)
        self.total_heat = sum([bug1.heat, bug2.heat])

    def test_max_bug_heat(self):
        self.assertEqual(self.max_heat, self.target.max_bug_heat)

    def test_total_bug_heat(self):
        self.assertEqual(self.total_heat, self.target.total_bug_heat)
        self.failUnless(
            self.target.total_bug_heat > self.target.max_bug_heat,
            "Total bug heat should be more than the max bug heat, "
            "since we know that multiple bugs have nonzero heat.")

    def test_bug_count(self):
        self.assertEqual(2, self.target.bug_count)


class SourcePackageMaxHeatByTargetTest(
    MaxHeatByTargetBase, unittest.TestCase):
    """Ensure a source package has a max_bug_heat value that can be set."""

    def setUp(self):
        self.target = self.factory.makeSourcePackage()
        self.delegates_setter = True


class ProductSeriesMaxHeatByTargetTest(
    MaxHeatByTargetBase, unittest.TestCase):
    """Ensure a product series has a max_bug_heat value that can be set."""

    def setUp(self):
        self.target = self.factory.makeProductSeries()
        self.delegates_setter = True


class DistroSeriesMaxHeatByTargetTest(
    MaxHeatByTargetBase, unittest.TestCase):
    """Ensure a distro series has a max_bug_heat value that can be set."""

    def setUp(self):
        self.target = self.factory.makeDistroSeries()
        self.delegates_setter = True


class ProjectGroupMaxHeatByTargetTest(
    MaxHeatByTargetBase, unittest.TestCase):
    """Ensure a project group has a max_bug_heat value that can be set."""

    def setUp(self):
        self.target = self.factory.makeProject()