~ci-train-bot/ubuntu-system-image/system-image-ubuntu-wily-proposed

« back to all changes in this revision

Viewing changes to systemimage/tests/test_scores.py

  • Committer: Barry Warsaw
  • Date: 2015-05-20 21:10:36 UTC
  • mfrom: (240.2.2 system-image)
  • Revision ID: barry@python.org-20150520211036-it6uoej3ai06fo5n
Manual train silo merge, required because of bot permission snafu

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2013-2014 Canonical Ltd.
 
1
# Copyright (C) 2013-2015 Canonical Ltd.
2
2
# Author: Barry Warsaw <barry@ubuntu.com>
3
3
 
4
4
# This program is free software: you can redistribute it and/or modify
14
14
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
15
 
16
16
__all__ = [
 
17
    'TestPhasedUpdates',
 
18
    'TestVersionDetail',
17
19
    'TestWeightedScorer',
18
20
    ]
19
21
 
22
24
 
23
25
from systemimage.candidates import get_candidates
24
26
from systemimage.scores import WeightedScorer
25
 
from systemimage.testing.helpers import get_index
 
27
from systemimage.testing.helpers import descriptions, get_index
 
28
from unittest.mock import patch
26
29
 
27
30
 
28
31
class TestWeightedScorer(unittest.TestCase):
31
34
 
32
35
    def test_choose_no_candidates(self):
33
36
        # If there are no candidates, then there is no path to upgrade.
34
 
        self.assertEqual(self.scorer.choose([]), [])
 
37
        self.assertEqual(self.scorer.choose([], 'devel'), [])
35
38
 
36
39
    def test_score_no_candidates(self):
37
40
        self.assertEqual(self.scorer.score([]), [])
38
41
 
39
42
    def test_one_path(self):
40
 
        index = get_index('index_08.json')
 
43
        index = get_index('scores.index_02.json')
41
44
        candidates = get_candidates(index, 600)
42
45
        # There's only one path.
43
46
        scores = self.scorer.score(candidates)
44
47
        # The score is 200 for the two extra bootme flags.
45
48
        self.assertEqual(scores, [200])
46
49
        # And we upgrade to the only path available.
47
 
        winner = self.scorer.choose(candidates)
 
50
        winner = self.scorer.choose(candidates, 'devel')
48
51
        # There are two images in the winning path.
49
52
        self.assertEqual(len(winner), 2)
50
53
        self.assertEqual([image.version for image in winner], [1300, 1301])
62
65
        #   a huge score making it impossible to win.
63
66
        #
64
67
        # Path B wins.
65
 
        index = get_index('index_09.json')
 
68
        index = get_index('scores.index_03.json')
66
69
        candidates = get_candidates(index, 600)
67
70
        # There are three paths.  The scores are as above.
68
71
        scores = self.scorer.score(candidates)
69
72
        self.assertEqual(scores, [300, 200, 9401])
70
 
        winner = self.scorer.choose(candidates)
 
73
        winner = self.scorer.choose(candidates, 'devel')
71
74
        self.assertEqual(len(winner), 3)
72
75
        self.assertEqual([image.version for image in winner],
73
76
                         [1200, 1201, 1304])
74
 
        descriptions = []
75
 
        for image in winner:
76
 
            # There's only one description per image so order doesn't matter.
77
 
            descriptions.extend(image.descriptions.values())
78
 
        self.assertEqual(descriptions, ['Full B', 'Delta B.1', 'Delta B.2'])
 
77
        self.assertEqual(descriptions(winner),
 
78
                         ['Full B', 'Delta B.1', 'Delta B.2'])
79
79
 
80
80
    def test_tied_candidates(self):
81
81
        # LP: #1206866 - TypeError when two candidate paths scored equal.
82
82
        #
83
 
        # index_17.json was captured from real data causing the traceback.
84
 
        index = get_index('index_17.json')
 
83
        # index_04.json was captured from real data causing the traceback.
 
84
        index = get_index('scores.index_04.json')
85
85
        candidates = get_candidates(index, 1)
86
 
        path = self.scorer.choose(candidates)
 
86
        path = self.scorer.choose(candidates, 'devel')
87
87
        self.assertEqual(len(path), 1)
88
88
        self.assertEqual(path[0].version, 1800)
 
89
 
 
90
 
 
91
class TestPhasedUpdates(unittest.TestCase):
 
92
    def setUp(self):
 
93
        self.scorer = WeightedScorer()
 
94
 
 
95
    def test_inside_phase_gets_update(self):
 
96
        # When the final image on an update path has a phase percentage higher
 
97
        # than the device percentage, the candidate path is okay.  In this
 
98
        # case, the `Full B` has phase of 50%.
 
99
        index = get_index('scores.index_05.json')
 
100
        candidates = get_candidates(index, 100)
 
101
        with patch('systemimage.scores.phased_percentage', return_value=22):
 
102
            winner = self.scorer.choose(candidates, 'devel')
 
103
            descriptions = []
 
104
            for image in winner:
 
105
                descriptions.extend(image.descriptions.values())
 
106
        self.assertEqual(descriptions, ['Full B', 'Delta B.1', 'Delta B.2'])
 
107
 
 
108
    def test_outside_phase_gets_update(self):
 
109
        # When the final image on an update path has a phase percentage lower
 
110
        # than the device percentage, the scorer falls back to the next
 
111
        # candidate path.
 
112
        index = get_index('scores.index_05.json')
 
113
        candidates = get_candidates(index, 100)
 
114
        with patch('systemimage.scores.phased_percentage', return_value=66):
 
115
            winner = self.scorer.choose(candidates, 'devel')
 
116
        self.assertEqual(descriptions(winner),
 
117
                         ['Full A', 'Delta A.1', 'Delta A.2'])
 
118
 
 
119
    def test_equal_phase_gets_update(self):
 
120
        # When the final image on an update path has a phase percentage exactly
 
121
        # equal to the device percentage, the candidate path is okay.  In this
 
122
        # case, the `Full B` has phase of 50%.
 
123
        index = get_index('scores.index_05.json')
 
124
        candidates = get_candidates(index, 100)
 
125
        with patch('systemimage.scores.phased_percentage', return_value=50):
 
126
            winner = self.scorer.choose(candidates, 'devel')
 
127
        self.assertEqual(descriptions(winner),
 
128
                         ['Full B', 'Delta B.1', 'Delta B.2'])
 
129
 
 
130
    def test_pulled_update(self):
 
131
        # When the final image on an update path has a phase percentage of
 
132
        # zero, then regardless of the device's percentage, the candidate path
 
133
        # is not okay.  In this case, the `Full B` has phase of 0%.
 
134
        index = get_index('scores.index_01.json')
 
135
        candidates = get_candidates(index, 100)
 
136
        with patch('systemimage.scores.phased_percentage', return_value=0):
 
137
            winner = self.scorer.choose(candidates, 'devel')
 
138
        self.assertEqual(descriptions(winner),
 
139
                         ['Full A', 'Delta A.1', 'Delta A.2'])
 
140
 
 
141
    def test_pulled_update_insanely_negative_randint(self):
 
142
        # When the final image on an update path has a phase percentage of
 
143
        # zero, then regardless of the device's percentage (even if randint
 
144
        # returned some insane value), the candidate path is not okay.  In this
 
145
        # case, the `Full B` has phase of 0%.
 
146
        index = get_index('scores.index_01.json')
 
147
        candidates = get_candidates(index, 100)
 
148
        with patch('systemimage.scores.phased_percentage', return_value=-100):
 
149
            winner = self.scorer.choose(candidates, 'devel')
 
150
        self.assertEqual(descriptions(winner),
 
151
                         ['Full A', 'Delta A.1', 'Delta A.2'])
 
152
 
 
153
    def test_pulled_update_insanely_positive_randint(self):
 
154
        # When the final image on an update path has a phase percentage of
 
155
        # zero, then regardless of the device's percentage (even if randint
 
156
        # returned some insane value), the candidate path is not okay.  In this
 
157
        # case, the `Full B` has phase of 0%.
 
158
        index = get_index('scores.index_01.json')
 
159
        candidates = get_candidates(index, 100)
 
160
        with patch('systemimage.scores.phased_percentage', return_value=1000):
 
161
            winner = self.scorer.choose(candidates, 'devel')
 
162
        self.assertEqual(len(winner), 0)
 
163
 
 
164
 
 
165
class TestVersionDetail(unittest.TestCase):
 
166
    def setUp(self):
 
167
        self.scorer = WeightedScorer()
 
168
 
 
169
    def test_version_detail(self):
 
170
        # The index.json file has three paths for updates, but only one is
 
171
        # selected.  The winning path lands on an image with a version_detail
 
172
        # key.
 
173
        index = get_index('scores.index_06.json')
 
174
        candidates = get_candidates(index, 600)
 
175
        scores = self.scorer.score(candidates)
 
176
        self.assertEqual(scores, [300, 200, 9401])
 
177
        winner = self.scorer.choose(candidates, 'devel')
 
178
        self.assertEqual(len(winner), 3)
 
179
        self.assertEqual([image.version for image in winner],
 
180
                         [1200, 1201, 1304])
 
181
        self.assertEqual(descriptions(winner),
 
182
                         ['Full B', 'Delta B.1', 'Delta B.2'])
 
183
        self.assertEqual(winner[-1].version_detail,
 
184
                         "ubuntu=105,raw-device=205,version=305")
 
185
 
 
186
    def test_no_version_detail(self):
 
187
        # The index.json file has three paths for updates, but only one is
 
188
        # selected.  The winning path lands on an image without a
 
189
        # version_detail key.
 
190
        index = get_index('scores.index_07.json')
 
191
        candidates = get_candidates(index, 600)
 
192
        scores = self.scorer.score(candidates)
 
193
        self.assertEqual(scores, [300, 200, 9401])
 
194
        winner = self.scorer.choose(candidates, 'devel')
 
195
        self.assertEqual(len(winner), 3)
 
196
        self.assertEqual([image.version for image in winner],
 
197
                         [1200, 1201, 1304])
 
198
        self.assertEqual(descriptions(winner),
 
199
                         ['Full B', 'Delta B.1', 'Delta B.2'])
 
200
        self.assertEqual(winner[-1].version_detail, '')