1#!/usr/bin/python2 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 7import mock 8 9import common 10 11from autotest_lib.server import utils 12from autotest_lib.server.hosts import cros_label 13from autotest_lib.server.hosts.cros_label import BrandCodeLabel 14from autotest_lib.server.hosts.cros_label import Cr50Label 15from autotest_lib.server.hosts.cros_label import Cr50ROKeyidLabel 16from autotest_lib.server.hosts.cros_label import Cr50RWKeyidLabel 17from autotest_lib.server.hosts.cros_label import DeviceSkuLabel 18from autotest_lib.server.hosts.cros_label import AudioLoopbackDongleLabel 19from autotest_lib.server.hosts.cros_label import ChameleonConnectionLabel 20from autotest_lib.server.hosts.cros_label import ChameleonLabel 21from autotest_lib.server.hosts.cros_label import ServoTypeLabel 22from autotest_lib.server.hosts import host_info 23 24# pylint: disable=missing-docstring 25 26NON_UNI_LSB_RELEASE_OUTPUT = """ 27CHROMEOS_RELEASE_APPID={63A9F698-C1CA-4A75-95E7-6B90181B3718} 28CHROMEOS_BOARD_APPID={63A9F698-C1CA-4A75-95E7-6B90181B3718} 29CHROMEOS_CANARY_APPID={90F229CE-83E2-4FAF-8479-E368A34938B1} 30DEVICETYPE=CHROMEBOOK 31CHROMEOS_ARC_VERSION=4234098 32CHROMEOS_ARC_ANDROID_SDK_VERSION=25 33GOOGLE_RELEASE=9798.0.2017_08_02_1022 34CHROMEOS_DEVSERVER=http://shapiroc3.bld.corp.google.com:8080 35CHROMEOS_RELEASE_BOARD=pyro 36CHROMEOS_RELEASE_BUILD_NUMBER=9798 37CHROMEOS_RELEASE_BRANCH_NUMBER=0 38CHROMEOS_RELEASE_CHROME_MILESTONE=62 39CHROMEOS_RELEASE_PATCH_NUMBER=2017_08_02_1022 40CHROMEOS_RELEASE_TRACK=testimage-channel 41CHROMEOS_RELEASE_DESCRIPTION=9798.0.2017_08_02_1022 (Test Build) 42CHROMEOS_RELEASE_BUILD_TYPE=Test Build 43CHROMEOS_RELEASE_NAME=Chromium OS 44CHROMEOS_RELEASE_VERSION=9798.0.2017_08_02_1022 45CHROMEOS_AUSERVER=http://someserver.bld.corp.google.com:8080/update 46""" 47 48UNI_LSB_RELEASE_OUTPUT = """ 49CHROMEOS_RELEASE_APPID={5A3AB642-2A67-470A-8F37-37E737A53CFC} 50CHROMEOS_BOARD_APPID={5A3AB642-2A67-470A-8F37-37E737A53CFC} 51CHROMEOS_CANARY_APPID={90F229CE-83E2-4FAF-8479-E368A34938B1} 52DEVICETYPE=CHROMEBOOK 53CHROMEOS_ARC_VERSION=4340813 54CHROMEOS_ARC_ANDROID_SDK_VERSION=25 55GOOGLE_RELEASE=9953.0.2017_09_18_1334 56CHROMEOS_DEVSERVER=http://server.bld.corp.google.com:8080 57CHROMEOS_RELEASE_BOARD=coral 58CHROMEOS_RELEASE_BUILD_NUMBER=9953 59CHROMEOS_RELEASE_BRANCH_NUMBER=0 60CHROMEOS_RELEASE_CHROME_MILESTONE=63 61CHROMEOS_RELEASE_PATCH_NUMBER=2017_09_18_1334 62CHROMEOS_RELEASE_TRACK=testimage-channel 63CHROMEOS_RELEASE_DESCRIPTION=9953.0.2017_09_18_1334 (Test Build) 64CHROMEOS_RELEASE_BUILD_TYPE=Test Build 65CHROMEOS_RELEASE_NAME=Chromium OS 66CHROMEOS_RELEASE_UNIBUILD=1 67CHROMEOS_RELEASE_VERSION=9953.0.2017_09_18_1334 68CHROMEOS_AUSERVER=http://server.bld.corp.google.com:8080/update 69CHROMEOS_RELEASE_MODELS=coral astronaut blue bruce lava nasher 70""" 71 72GSCTOOL_OUTPUT_PVT = """ 73start 74target running protocol version 6 75keyids: RO 0xaa66150f, RW 0xde88588d 76offsets: backup RO at 0x40000, backup RW at 0x44000 77Current versions: 78RO 0.0.10 79RW 0.3.14 80""" 81 82GSCTOOL_OUTPUT_PREPVT = """ 83start 84target running protocol version 6 85keyids: RO 0xaa66150f, RW 0xde88588d 86offsets: backup RO at 0x40000, backup RW at 0x44000 87Current versions: 88RO 0.0.10 89RW 0.4.15 90""" 91 92GSCTOOL_OUTPUT_DEV_RO = """ 93start 94target running protocol version 6 95keyids: RO 0x3716ee6b, RW 0xde88588d 96offsets: backup RO at 0x40000, backup RW at 0x44000 97Current versions: 98RO 0.0.10 99RW 0.4.15 100""" 101 102GSCTOOL_OUTPUT_DEV_RW = """ 103start 104target running protocol version 6 105keyids: RO 0xaa66150f, RW 0xb93d6539 106offsets: backup RO at 0x40000, backup RW at 0x44000 107Current versions: 108RO 0.0.10 109RW 0.4.15 110""" 111 112 113class MockCmd(object): 114 """Simple mock command with base command and results""" 115 116 def __init__(self, cmd, exit_status, stdout): 117 self.cmd = cmd 118 self.stdout = stdout 119 self.exit_status = exit_status 120 121 122class MockAFEHost(utils.EmptyAFEHost): 123 124 def __init__(self, labels=[], attributes={}): 125 self.labels = labels 126 self.attributes = attributes 127 128 129class MockHost(object): 130 """Simple host for running mock'd host commands""" 131 132 def __init__(self, labels, *args): 133 self._afe_host = MockAFEHost(labels) 134 self.mock_cmds = {c.cmd: c for c in args} 135 info = host_info.HostInfo(labels=labels) 136 self.host_info_store = host_info.InMemoryHostInfoStore(info) 137 138 def run(self, command, **kwargs): 139 """Finds the matching result by command value""" 140 return self.mock_cmds[command] 141 142 def is_up(self, **args): 143 return True 144 145 146class MockHostWithoutAFE(MockHost): 147 148 def __init__(self, labels, *args): 149 super(MockHostWithoutAFE, self).__init__(labels, *args) 150 self._afe_host = utils.EmptyAFEHost() 151 152 153class DeviceSkuLabelTests(unittest.TestCase): 154 """Unit tests for DeviceSkuLabel""" 155 156 def test_new_label(self): 157 mosys_cmd = 'mosys platform sku' 158 host = MockHost([], MockCmd(mosys_cmd, 0, '27\n')) 159 self.assertEqual(DeviceSkuLabel().generate_labels(host), ['27']) 160 161 def test_new_label_mosys_fails(self): 162 mosys_cmd = 'mosys platform sku' 163 host = MockHost([], MockCmd(mosys_cmd, 1, '27\n')) 164 self.assertEqual(DeviceSkuLabel().generate_labels(host), []) 165 166 def test_existing_label(self): 167 host = MockHost(['device-sku:48']) 168 self.assertEqual(DeviceSkuLabel().generate_labels(host), ['48']) 169 170 def test_update_for_task(self): 171 self.assertTrue(DeviceSkuLabel().update_for_task('')) 172 self.assertTrue(DeviceSkuLabel().update_for_task('repair')) 173 self.assertTrue(DeviceSkuLabel().update_for_task('deploy')) 174 175 176class BrandCodeLabelTests(unittest.TestCase): 177 """Unit tests for DeviceSkuLabel""" 178 179 def test_new_label(self): 180 cros_config_cmd = 'cros_config / brand-code' 181 host = MockHost([], MockCmd(cros_config_cmd, 0, 'XXYZ\n')) 182 self.assertEqual(BrandCodeLabel().generate_labels(host), ['XXYZ']) 183 184 def test_new_label_cros_config_fails(self): 185 cros_config_cmd = 'cros_config / brand-code' 186 host = MockHost([], MockCmd(cros_config_cmd, 1, 'XXYZ\n')) 187 self.assertEqual(BrandCodeLabel().generate_labels(host), []) 188 189 def test_existing_label(self): 190 host = MockHost(['brand-code:ABCD']) 191 self.assertEqual(BrandCodeLabel().generate_labels(host), ['ABCD']) 192 193 194class Cr50Tests(unittest.TestCase): 195 """Unit tests for Cr50Label""" 196 197 def test_cr50_pvt(self): 198 host = MockHost([], MockCmd('gsctool -a -f', 0, GSCTOOL_OUTPUT_PVT)) 199 self.assertEqual(Cr50Label().get(host), ['cr50:pvt']) 200 201 def test_cr50_prepvt(self): 202 host = MockHost([], MockCmd('gsctool -a -f', 0, GSCTOOL_OUTPUT_PREPVT)) 203 self.assertEqual(Cr50Label().get(host), ['cr50:prepvt']) 204 205 def test_gsctool_fails(self): 206 host = MockHost([], MockCmd('gsctool -a -f', 1, '')) 207 self.assertEqual(Cr50Label().get(host), []) 208 209 210class Cr50RWKeyidTests(unittest.TestCase): 211 """Unit tests for Cr50RWKeyidLabel""" 212 213 def test_cr50_prod_rw(self): 214 host = MockHost([], MockCmd('gsctool -a -f', 0, GSCTOOL_OUTPUT_PVT)) 215 self.assertEqual(Cr50RWKeyidLabel().get(host), 216 ['cr50-rw-keyid:0xde88588d', 'cr50-rw-keyid:prod']) 217 218 def test_cr50_dev_rw(self): 219 host = MockHost([], MockCmd('gsctool -a -f', 0, GSCTOOL_OUTPUT_DEV_RW)) 220 self.assertEqual(Cr50RWKeyidLabel().get(host), 221 ['cr50-rw-keyid:0xb93d6539', 'cr50-rw-keyid:dev']) 222 223 def test_gsctool_fails(self): 224 host = MockHost([], MockCmd('gsctool -a -f', 1, '')) 225 self.assertEqual(Cr50RWKeyidLabel().get(host), []) 226 227 228class Cr50ROKeyidTests(unittest.TestCase): 229 """Unit tests for Cr50ROKeyidLabel""" 230 231 def test_cr50_prod_ro(self): 232 host = MockHost([], MockCmd('gsctool -a -f', 0, GSCTOOL_OUTPUT_PREPVT)) 233 self.assertEqual(Cr50ROKeyidLabel().get(host), 234 ['cr50-ro-keyid:0xaa66150f', 'cr50-ro-keyid:prod']) 235 236 def test_cr50_dev_ro(self): 237 host = MockHost([], MockCmd('gsctool -a -f', 0, GSCTOOL_OUTPUT_DEV_RO)) 238 self.assertEqual(Cr50ROKeyidLabel().get(host), 239 ['cr50-ro-keyid:0x3716ee6b', 'cr50-ro-keyid:dev']) 240 241 def test_gsctool_fails(self): 242 host = MockHost([], MockCmd('gsctool -a -f', 1, '')) 243 self.assertEqual(Cr50ROKeyidLabel().get(host), []) 244 245 246class HWIDLabelTests(unittest.TestCase): 247 def test_merge_hwid_label_lists_empty(self): 248 self.assertEqual(cros_label.HWIDLabel._merge_hwid_label_lists([], []), []) 249 250 def test_merge_hwid_label_lists_singleton(self): 251 self.assertEqual(cros_label.HWIDLabel._merge_hwid_label_lists([], ["4"]), 252 ["4"]) 253 self.assertEqual(cros_label.HWIDLabel._merge_hwid_label_lists(["7"], []), 254 ["7"]) 255 256 def test_merge_hwid_label_lists_override(self): 257 self.assertEqual( 258 cros_label.HWIDLabel._merge_hwid_label_lists(old=["7:a"], new=["7:b"]), 259 ["7:b"]) 260 261 def test_merge_hwid_label_lists_no_override(self): 262 self.assertEqual( 263 cros_label.HWIDLabel._merge_hwid_label_lists(old=["7a"], new=["7b"]), 264 ["7a", "7b"]) 265 266 def test_hwid_label_names(self): 267 class HWIDLabelTester(cros_label.HWIDLabel): 268 def get_all_labels(self): 269 return [], [] 270 271 item = HWIDLabelTester() 272 self.assertEqual(item._hwid_label_names(), cros_label.HWID_LABELS_FALLBACK) 273 274 275class AudioLoopbackDongleLabelTests(unittest.TestCase): 276 def test_update_for_task(self): 277 self.assertTrue(AudioLoopbackDongleLabel().update_for_task('')) 278 self.assertTrue(AudioLoopbackDongleLabel().update_for_task('repair')) 279 self.assertFalse(AudioLoopbackDongleLabel().update_for_task('deploy')) 280 281 282class ChameleonConnectionLabelTests(unittest.TestCase): 283 def test_update_for_task(self): 284 self.assertTrue(ChameleonConnectionLabel().update_for_task('')) 285 self.assertFalse(ChameleonConnectionLabel().update_for_task('repair')) 286 self.assertTrue(ChameleonConnectionLabel().update_for_task('deploy')) 287 288 289class ChameleonLabelTests(unittest.TestCase): 290 def test_update_for_task(self): 291 self.assertTrue(ChameleonLabel().update_for_task('')) 292 self.assertTrue(ChameleonLabel().update_for_task('repair')) 293 self.assertFalse(ChameleonLabel().update_for_task('deploy')) 294 295 296class ServoTypeLabelTests(unittest.TestCase): 297 """Unit tests for ServoTypeLabel""" 298 def test_update_for_task(self): 299 self.assertTrue(ServoTypeLabel().update_for_task('')) 300 self.assertFalse(ServoTypeLabel().update_for_task('repair')) 301 self.assertTrue(ServoTypeLabel().update_for_task('deploy')) 302 303 def test_generate_labels_return_value_from_labels(self): 304 host = MockHost(['servo_type:Some_interesting']) 305 servo = ServoTypeLabel() 306 self.assertEqual(servo.get(host), ['servo_type:Some_interesting']) 307 self.assertEqual(servo.generate_labels(host), ['Some_interesting']) 308 309 def test_generate_labels_from_cache_when_servo_is_none(self): 310 host = MockHost(['servo_state:Some_interesting']) 311 host.servo = None 312 servo = ServoTypeLabel() 313 self.assertEqual(servo.get(host), []) 314 self.assertEqual(servo.generate_labels(host), []) 315 316 def test_generate_labels_not_from_cache_when_servo_exist(self): 317 host = MockHost(['servo_type']) 318 host.servo = mock.Mock() 319 host.servo.get_servo_version.return_value = 'servo_v3' 320 servo = ServoTypeLabel() 321 self.assertEqual(servo.get(host), ['servo_type:servo_v3']) 322 self.assertEqual(servo.generate_labels(host), ['servo_v3']) 323 host.servo.get_servo_version.assert_called() 324 325 326if __name__ == '__main__': 327 unittest.main() 328