1#!/usr/bin/python
2# Copyright 2017 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6import unittest
7
8import common
9
10from autotest_lib.server import utils
11from autotest_lib.server.hosts.cros_label import BoardLabel
12from autotest_lib.server.hosts.cros_label import ModelLabel
13from autotest_lib.server.hosts.cros_label import SparseCoverageLabel
14
15# pylint: disable=missing-docstring
16
17NON_UNI_LSB_RELEASE_OUTPUT = """
18CHROMEOS_RELEASE_APPID={63A9F698-C1CA-4A75-95E7-6B90181B3718}
19CHROMEOS_BOARD_APPID={63A9F698-C1CA-4A75-95E7-6B90181B3718}
20CHROMEOS_CANARY_APPID={90F229CE-83E2-4FAF-8479-E368A34938B1}
21DEVICETYPE=CHROMEBOOK
22CHROMEOS_ARC_VERSION=4234098
23CHROMEOS_ARC_ANDROID_SDK_VERSION=25
24GOOGLE_RELEASE=9798.0.2017_08_02_1022
25CHROMEOS_DEVSERVER=http://shapiroc3.bld.corp.google.com:8080
26CHROMEOS_RELEASE_BOARD=pyro
27CHROMEOS_RELEASE_BUILD_NUMBER=9798
28CHROMEOS_RELEASE_BRANCH_NUMBER=0
29CHROMEOS_RELEASE_CHROME_MILESTONE=62
30CHROMEOS_RELEASE_PATCH_NUMBER=2017_08_02_1022
31CHROMEOS_RELEASE_TRACK=testimage-channel
32CHROMEOS_RELEASE_DESCRIPTION=9798.0.2017_08_02_1022 (Test Build)
33CHROMEOS_RELEASE_BUILD_TYPE=Test Build
34CHROMEOS_RELEASE_NAME=Chromium OS
35CHROMEOS_RELEASE_VERSION=9798.0.2017_08_02_1022
36CHROMEOS_AUSERVER=http://someserver.bld.corp.google.com:8080/update
37"""
38
39UNI_LSB_RELEASE_OUTPUT = """
40CHROMEOS_RELEASE_APPID={5A3AB642-2A67-470A-8F37-37E737A53CFC}
41CHROMEOS_BOARD_APPID={5A3AB642-2A67-470A-8F37-37E737A53CFC}
42CHROMEOS_CANARY_APPID={90F229CE-83E2-4FAF-8479-E368A34938B1}
43DEVICETYPE=CHROMEBOOK
44CHROMEOS_ARC_VERSION=4340813
45CHROMEOS_ARC_ANDROID_SDK_VERSION=25
46GOOGLE_RELEASE=9953.0.2017_09_18_1334
47CHROMEOS_DEVSERVER=http://server.bld.corp.google.com:8080
48CHROMEOS_RELEASE_BOARD=coral
49CHROMEOS_RELEASE_BUILD_NUMBER=9953
50CHROMEOS_RELEASE_BRANCH_NUMBER=0
51CHROMEOS_RELEASE_CHROME_MILESTONE=63
52CHROMEOS_RELEASE_PATCH_NUMBER=2017_09_18_1334
53CHROMEOS_RELEASE_TRACK=testimage-channel
54CHROMEOS_RELEASE_DESCRIPTION=9953.0.2017_09_18_1334 (Test Build)
55CHROMEOS_RELEASE_BUILD_TYPE=Test Build
56CHROMEOS_RELEASE_NAME=Chromium OS
57CHROMEOS_RELEASE_UNIBUILD=1
58CHROMEOS_RELEASE_VERSION=9953.0.2017_09_18_1334
59CHROMEOS_AUSERVER=http://server.bld.corp.google.com:8080/update
60CHROMEOS_RELEASE_MODELS=coral astronaut blue bruce lava nasher
61"""
62
63
64class MockCmd(object):
65    """Simple mock command with base command and results"""
66
67    def __init__(self, cmd, exit_status, stdout):
68        self.cmd = cmd
69        self.stdout = stdout
70        self.exit_status = exit_status
71
72
73class MockAFEHost(utils.EmptyAFEHost):
74
75    def __init__(self, labels=[], attributes={}):
76        self.labels = labels
77        self.attributes = attributes
78
79
80class MockHost(object):
81    """Simple host for running mock'd host commands"""
82
83    def __init__(self, labels, *args):
84        self._afe_host = MockAFEHost(labels)
85        self.mock_cmds = {c.cmd: c for c in args}
86
87    def run(self, command, **kwargs):
88        """Finds the matching result by command value"""
89        return self.mock_cmds[command]
90
91
92class ModelLabelTests(unittest.TestCase):
93    """Unit tests for ModelLabel"""
94
95    def test_cros_config_succeeds(self):
96        cat_lsb_release_output = """
97CHROMEOS_RELEASE_BOARD=pyro
98CHROMEOS_RELEASE_UNIBUILD=1
99"""
100        host = MockHost([],
101                        MockCmd('cros_config / test-label', 0, 'coral\n'),
102                        MockCmd('cat /etc/lsb-release', 0,
103                                cat_lsb_release_output))
104        self.assertEqual(ModelLabel().generate_labels(host), ['coral'])
105
106    def test_cros_config_fails_mosys_succeeds(self):
107        cat_lsb_release_output = """
108CHROMEOS_RELEASE_BOARD=pyro
109CHROMEOS_RELEASE_UNIBUILD=1
110"""
111        host = MockHost([],
112                        MockCmd('cros_config / test-label', 1, ''),
113                        MockCmd('mosys platform model', 0, 'coral\n'),
114                        MockCmd('cat /etc/lsb-release', 0,
115                                cat_lsb_release_output))
116        self.assertEqual(ModelLabel().generate_labels(host), ['coral'])
117
118    def test_cros_config_fails_mosys_fails(self):
119        cat_lsb_release_output = """
120CHROMEOS_RELEASE_BOARD=pyro
121CHROMEOS_RELEASE_UNIBUILD=1
122"""
123        host = MockHost([],
124                        MockCmd('cros_config / test-label', 1, ''),
125                        MockCmd('mosys platform model', 1, ''),
126                        MockCmd('cat /etc/lsb-release', 0,
127                                cat_lsb_release_output))
128        self.assertEqual(ModelLabel().generate_labels(host), ['pyro'])
129
130    def test_cros_config_only_used_for_unibuilds(self):
131        cat_lsb_release_output = """
132CHROMEOS_RELEASE_BOARD=pyro
133"""
134        host = MockHost([],
135                        MockCmd('cat /etc/lsb-release', 0,
136                                cat_lsb_release_output))
137        self.assertEqual(ModelLabel().generate_labels(host), ['pyro'])
138
139    def test_existing_label(self):
140        host = MockHost(['model:existing'])
141        self.assertEqual(ModelLabel().generate_labels(host), ['existing'])
142
143
144class BoardLabelTests(unittest.TestCase):
145    """Unit tests for BoardLabel"""
146
147    def test_new_label(self):
148        cat_cmd = 'cat /etc/lsb-release'
149        host = MockHost([], MockCmd(cat_cmd, 0, NON_UNI_LSB_RELEASE_OUTPUT))
150        self.assertEqual(BoardLabel().generate_labels(host), ['pyro'])
151
152    def test_existing_label(self):
153        host = MockHost(['board:existing'])
154        self.assertEqual(BoardLabel().generate_labels(host), ['existing'])
155
156
157SPARSE_COVERAGE_TEMPLATE = """
158CHROMEOS_RELEASE_APPID={{01906EA2-3EB2-41F1-8F62-F0B7120EFD2E}}
159CHROMEOS_BOARD_APPID={{01906EA2-3EB2-41F1-8F62-F0B7120EFD2E}}
160CHROMEOS_CANARY_APPID={{90F229CE-83E2-4FAF-8479-E368A34938B1}}
161DEVICETYPE=CHROMEBOOK
162CHROMEOS_ARC_VERSION=4473730
163CHROMEOS_ARC_ANDROID_SDK_VERSION=25
164GOOGLE_RELEASE={build}.{branch}.{patch}
165CHROMEOS_DEVSERVER=
166CHROMEOS_RELEASE_BUILDER_PATH=eve-{builder}/R64-{build}.{branch}.{patch}
167CHROMEOS_RELEASE_BUILD_NUMBER={build}
168CHROMEOS_RELEASE_BRANCH_NUMBER={branch}
169CHROMEOS_RELEASE_CHROME_MILESTONE=64
170CHROMEOS_RELEASE_PATCH_NUMBER={patch}
171CHROMEOS_RELEASE_TRACK=testimage-channel
172CHROMEOS_RELEASE_DESCRIPTION={build}.{branch}.{patch} (Official Build) dev-channel eve test
173CHROMEOS_RELEASE_BUILD_TYPE=Official Build
174CHROMEOS_RELEASE_NAME=Chrome OS
175CHROMEOS_RELEASE_BOARD=eve
176CHROMEOS_RELEASE_VERSION={build}.{branch}.{patch}
177CHROMEOS_AUSERVER=https://tools.google.com/service/update2
178"""
179
180
181def _cat_output(builder, build, branch, patch):
182    return SPARSE_COVERAGE_TEMPLATE.format(
183        builder=builder, build=build, branch=branch, patch=patch)
184
185
186class SparseCoverageLabelTests(unittest.TestCase):
187    """Unit tests for SparseCoverageLabel"""
188
189    _mock_data = [
190        # Master canary build - sparse.
191        (('release', '60000', '0', '0'), {2, 3, 5}),
192        (('release', '60001', '0', '0'), {}),
193        (('release', '60002', '0', '0'), {2}),
194        (('release', '60003', '0', '0'), {3}),
195        (('release', '60004', '0', '0'), {2}),
196        (('release', '60005', '0', '0'), {5}),
197        (('release', '60006', '0', '0'), {2, 3}),
198        # Branch canary build - not sparse.
199        (('release', '60000', '1', '0'), {2, 3, 5}),
200        (('release', '60001', '1', '0'), {2, 3, 5}),
201        (('release', '60002', '1', '0'), {2, 3, 5}),
202        (('release', '60003', '1', '0'), {2, 3, 5}),
203        (('release', '60004', '1', '0'), {2, 3, 5}),
204        (('release', '60005', '1', '0'), {2, 3, 5}),
205        (('release', '60006', '1', '0'), {2, 3, 5}),
206        # A CQ/PFQ like build - not sparse.
207        (('release', '60000', '0', '0-rc4'), {2, 3, 5}),
208        (('release', '60001', '0', '0-rc4'), {2, 3, 5}),
209        (('release', '60002', '0', '0-rc4'), {2, 3, 5}),
210        (('release', '60003', '0', '0-rc4'), {2, 3, 5}),
211        (('release', '60004', '0', '0-rc4'), {2, 3, 5}),
212        (('release', '60005', '0', '0-rc4'), {2, 3, 5}),
213        (('release', '60006', '0', '0-rc4'), {2, 3, 5}),
214        # Not a release build - not sparse.
215        (('chrome-pfq', '60000', '0', '0'), {2, 3, 5}),
216        (('chrome-pfq', '60001', '0', '0'), {2, 3, 5}),
217        (('chrome-pfq', '60002', '0', '0'), {2, 3, 5}),
218        (('chrome-pfq', '60003', '0', '0'), {2, 3, 5}),
219        (('chrome-pfq', '60004', '0', '0'), {2, 3, 5}),
220        (('chrome-pfq', '60005', '0', '0'), {2, 3, 5}),
221        (('chrome-pfq', '60006', '0', '0'), {2, 3, 5}),
222    ]
223
224    def test_coverage_label(self):
225        cat_cmd = 'cat /etc/lsb-release'
226        for release, short_labels in self._mock_data:
227            host = MockHost([], MockCmd(cat_cmd, 0, _cat_output(*release)))
228            expected_labels = set(
229                'sparse_coverage_%d' % l for l in short_labels)
230            generated_labels = set(SparseCoverageLabel().generate_labels(host))
231            self.assertEqual(expected_labels, generated_labels)
232
233
234if __name__ == '__main__':
235    unittest.main()
236