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 mock 7import unittest 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 BoardLabel 14from autotest_lib.server.hosts.cros_label import BluetoothLabel 15from autotest_lib.server.hosts.cros_label import BrandCodeLabel 16from autotest_lib.server.hosts.cros_label import Cr50Label 17from autotest_lib.server.hosts.cros_label import Cr50ROKeyidLabel 18from autotest_lib.server.hosts.cros_label import Cr50RWKeyidLabel 19from autotest_lib.server.hosts.cros_label import Cr50ROVersionLabel 20from autotest_lib.server.hosts.cros_label import Cr50RWVersionLabel 21from autotest_lib.server.hosts.cros_label import DeviceSkuLabel 22from autotest_lib.server.hosts.cros_label import ModelLabel 23from autotest_lib.server.hosts.cros_label import AudioLoopbackDongleLabel 24from autotest_lib.server.hosts.cros_label import ChameleonConnectionLabel 25from autotest_lib.server.hosts.cros_label import ChameleonLabel 26from autotest_lib.server.hosts.cros_label import ChameleonPeripheralsLabel 27from autotest_lib.server.hosts.cros_label import ServoLabel 28from autotest_lib.server.hosts import host_info 29 30# pylint: disable=missing-docstring 31 32NON_UNI_LSB_RELEASE_OUTPUT = """ 33CHROMEOS_RELEASE_APPID={63A9F698-C1CA-4A75-95E7-6B90181B3718} 34CHROMEOS_BOARD_APPID={63A9F698-C1CA-4A75-95E7-6B90181B3718} 35CHROMEOS_CANARY_APPID={90F229CE-83E2-4FAF-8479-E368A34938B1} 36DEVICETYPE=CHROMEBOOK 37CHROMEOS_ARC_VERSION=4234098 38CHROMEOS_ARC_ANDROID_SDK_VERSION=25 39GOOGLE_RELEASE=9798.0.2017_08_02_1022 40CHROMEOS_DEVSERVER=http://shapiroc3.bld.corp.google.com:8080 41CHROMEOS_RELEASE_BOARD=pyro 42CHROMEOS_RELEASE_BUILD_NUMBER=9798 43CHROMEOS_RELEASE_BRANCH_NUMBER=0 44CHROMEOS_RELEASE_CHROME_MILESTONE=62 45CHROMEOS_RELEASE_PATCH_NUMBER=2017_08_02_1022 46CHROMEOS_RELEASE_TRACK=testimage-channel 47CHROMEOS_RELEASE_DESCRIPTION=9798.0.2017_08_02_1022 (Test Build) 48CHROMEOS_RELEASE_BUILD_TYPE=Test Build 49CHROMEOS_RELEASE_NAME=Chromium OS 50CHROMEOS_RELEASE_VERSION=9798.0.2017_08_02_1022 51CHROMEOS_AUSERVER=http://someserver.bld.corp.google.com:8080/update 52""" 53 54UNI_LSB_RELEASE_OUTPUT = """ 55CHROMEOS_RELEASE_APPID={5A3AB642-2A67-470A-8F37-37E737A53CFC} 56CHROMEOS_BOARD_APPID={5A3AB642-2A67-470A-8F37-37E737A53CFC} 57CHROMEOS_CANARY_APPID={90F229CE-83E2-4FAF-8479-E368A34938B1} 58DEVICETYPE=CHROMEBOOK 59CHROMEOS_ARC_VERSION=4340813 60CHROMEOS_ARC_ANDROID_SDK_VERSION=25 61GOOGLE_RELEASE=9953.0.2017_09_18_1334 62CHROMEOS_DEVSERVER=http://server.bld.corp.google.com:8080 63CHROMEOS_RELEASE_BOARD=coral 64CHROMEOS_RELEASE_BUILD_NUMBER=9953 65CHROMEOS_RELEASE_BRANCH_NUMBER=0 66CHROMEOS_RELEASE_CHROME_MILESTONE=63 67CHROMEOS_RELEASE_PATCH_NUMBER=2017_09_18_1334 68CHROMEOS_RELEASE_TRACK=testimage-channel 69CHROMEOS_RELEASE_DESCRIPTION=9953.0.2017_09_18_1334 (Test Build) 70CHROMEOS_RELEASE_BUILD_TYPE=Test Build 71CHROMEOS_RELEASE_NAME=Chromium OS 72CHROMEOS_RELEASE_UNIBUILD=1 73CHROMEOS_RELEASE_VERSION=9953.0.2017_09_18_1334 74CHROMEOS_AUSERVER=http://server.bld.corp.google.com:8080/update 75CHROMEOS_RELEASE_MODELS=coral astronaut blue bruce lava nasher 76""" 77 78GSCTOOL_OUTPUT_PVT = """ 79start 80target running protocol version 6 81keyids: RO 0xaa66150f, RW 0xde88588d 82offsets: backup RO at 0x40000, backup RW at 0x44000 83Current versions: 84RO 0.0.10 85RW 0.3.14 86""" 87 88GSCTOOL_OUTPUT_PREPVT = """ 89start 90target running protocol version 6 91keyids: RO 0xaa66150f, RW 0xde88588d 92offsets: backup RO at 0x40000, backup RW at 0x44000 93Current versions: 94RO 0.0.10 95RW 0.4.15 96""" 97 98GSCTOOL_OUTPUT_DEV_RO = """ 99start 100target running protocol version 6 101keyids: RO 0x3716ee6b, RW 0xde88588d 102offsets: backup RO at 0x40000, backup RW at 0x44000 103Current versions: 104RO 0.0.10 105RW 0.4.15 106""" 107 108GSCTOOL_OUTPUT_DEV_RW = """ 109start 110target running protocol version 6 111keyids: RO 0xaa66150f, RW 0xb93d6539 112offsets: backup RO at 0x40000, backup RW at 0x44000 113Current versions: 114RO 0.0.10 115RW 0.4.15 116""" 117 118 119class MockCmd(object): 120 """Simple mock command with base command and results""" 121 122 def __init__(self, cmd, exit_status, stdout): 123 self.cmd = cmd 124 self.stdout = stdout 125 self.exit_status = exit_status 126 127 128class MockAFEHost(utils.EmptyAFEHost): 129 130 def __init__(self, labels=[], attributes={}): 131 self.labels = labels 132 self.attributes = attributes 133 134 135class MockHost(object): 136 """Simple host for running mock'd host commands""" 137 138 def __init__(self, labels, *args): 139 self._afe_host = MockAFEHost(labels) 140 self.mock_cmds = {c.cmd: c for c in args} 141 info = host_info.HostInfo(labels=labels) 142 self.host_info_store = host_info.InMemoryHostInfoStore(info) 143 144 def run(self, command, **kwargs): 145 """Finds the matching result by command value""" 146 return self.mock_cmds[command] 147 148 149class MockHostWithoutAFE(MockHost): 150 151 def __init__(self, labels, *args): 152 super(MockHostWithoutAFE, self).__init__(labels, *args) 153 self._afe_host = utils.EmptyAFEHost() 154 155 156class ModelLabelTests(unittest.TestCase): 157 """Unit tests for ModelLabel""" 158 159 def test_cros_config_succeeds(self): 160 cat_lsb_release_output = """ 161CHROMEOS_RELEASE_BOARD=pyro 162CHROMEOS_RELEASE_UNIBUILD=1 163""" 164 host = MockHost([], 165 MockCmd('cros_config / test-label', 0, 'coral\n'), 166 MockCmd('cat /etc/lsb-release', 0, 167 cat_lsb_release_output)) 168 self.assertEqual(ModelLabel().generate_labels(host), ['coral']) 169 170 def test_cros_config_fails_mosys_succeeds(self): 171 cat_lsb_release_output = """ 172CHROMEOS_RELEASE_BOARD=pyro 173CHROMEOS_RELEASE_UNIBUILD=1 174""" 175 host = MockHost([], 176 MockCmd('cros_config / test-label', 1, ''), 177 MockCmd('mosys platform model', 0, 'coral\n'), 178 MockCmd('cat /etc/lsb-release', 0, 179 cat_lsb_release_output)) 180 self.assertEqual(ModelLabel().generate_labels(host), ['coral']) 181 182 def test_cros_config_fails_mosys_fails(self): 183 cat_lsb_release_output = """ 184CHROMEOS_RELEASE_BOARD=pyro 185CHROMEOS_RELEASE_UNIBUILD=1 186""" 187 host = MockHost([], 188 MockCmd('cros_config / test-label', 1, ''), 189 MockCmd('mosys platform model', 1, ''), 190 MockCmd('cat /etc/lsb-release', 0, 191 cat_lsb_release_output)) 192 self.assertEqual(ModelLabel().generate_labels(host), ['pyro']) 193 194 def test_cros_config_only_used_for_unibuilds(self): 195 cat_lsb_release_output = """ 196CHROMEOS_RELEASE_BOARD=pyro 197""" 198 host = MockHost([], 199 MockCmd('cat /etc/lsb-release', 0, 200 cat_lsb_release_output)) 201 self.assertEqual(ModelLabel().generate_labels(host), ['pyro']) 202 203 def test_existing_label(self): 204 host = MockHost(['model:existing']) 205 self.assertEqual(ModelLabel().generate_labels(host), ['existing']) 206 207 def test_existing_label_in_host_info_store(self): 208 host = MockHostWithoutAFE(['model:existing']) 209 self.assertEqual(ModelLabel().generate_labels(host), ['existing']) 210 211 212class BoardLabelTests(unittest.TestCase): 213 """Unit tests for BoardLabel""" 214 215 def test_new_label(self): 216 cat_cmd = 'cat /etc/lsb-release' 217 host = MockHost([], MockCmd(cat_cmd, 0, NON_UNI_LSB_RELEASE_OUTPUT)) 218 self.assertEqual(BoardLabel().generate_labels(host), ['pyro']) 219 220 def test_existing_label(self): 221 host = MockHost(['board:existing']) 222 self.assertEqual(BoardLabel().generate_labels(host), ['existing']) 223 224 def test_existing_label_in_host_info_store(self): 225 host = MockHostWithoutAFE(['board:existing']) 226 self.assertEqual(BoardLabel().generate_labels(host), ['existing']) 227 228 229class DeviceSkuLabelTests(unittest.TestCase): 230 """Unit tests for DeviceSkuLabel""" 231 232 def test_new_label(self): 233 mosys_cmd = 'mosys platform sku' 234 host = MockHost([], MockCmd(mosys_cmd, 0, '27\n')) 235 self.assertEqual(DeviceSkuLabel().generate_labels(host), ['27']) 236 237 def test_new_label_mosys_fails(self): 238 mosys_cmd = 'mosys platform sku' 239 host = MockHost([], MockCmd(mosys_cmd, 1, '27\n')) 240 self.assertEqual(DeviceSkuLabel().generate_labels(host), []) 241 242 def test_existing_label(self): 243 host = MockHost(['device-sku:48']) 244 self.assertEqual(DeviceSkuLabel().generate_labels(host), ['48']) 245 246 def test_update_for_task(self): 247 self.assertTrue(DeviceSkuLabel().update_for_task('')) 248 self.assertFalse(DeviceSkuLabel().update_for_task('repair')) 249 self.assertTrue(DeviceSkuLabel().update_for_task('deploy')) 250 251 252class BrandCodeLabelTests(unittest.TestCase): 253 """Unit tests for DeviceSkuLabel""" 254 255 def test_new_label(self): 256 cros_config_cmd = 'cros_config / brand-code' 257 host = MockHost([], MockCmd(cros_config_cmd, 0, 'XXYZ\n')) 258 self.assertEqual(BrandCodeLabel().generate_labels(host), ['XXYZ']) 259 260 def test_new_label_cros_config_fails(self): 261 cros_config_cmd = 'cros_config / brand-code' 262 host = MockHost([], MockCmd(cros_config_cmd, 1, 'XXYZ\n')) 263 self.assertEqual(BrandCodeLabel().generate_labels(host), []) 264 265 def test_existing_label(self): 266 host = MockHost(['brand-code:ABCD']) 267 self.assertEqual(BrandCodeLabel().generate_labels(host), ['ABCD']) 268 269 270class BluetoothLabelTests(unittest.TestCase): 271 """Unit tests for BluetoothLabel""" 272 273 def test_new_label(self): 274 test_cmd = 'test -d /sys/class/bluetooth/hci0' 275 host = MockHost([], MockCmd(test_cmd, 0, '')) 276 self.assertEqual(BluetoothLabel().exists(host), True) 277 278 def test_existing_label(self): 279 host = MockHostWithoutAFE(['bluetooth']) 280 self.assertEqual(BoardLabel().exists(host), True) 281 282 283class Cr50Tests(unittest.TestCase): 284 """Unit tests for Cr50Label""" 285 286 def test_cr50_pvt(self): 287 host = MockHost([], 288 MockCmd('gsctool -a -f', 0, GSCTOOL_OUTPUT_PVT)) 289 self.assertEqual(Cr50Label().get(host), ['cr50:pvt']) 290 291 def test_cr50_prepvt(self): 292 host = MockHost([], 293 MockCmd('gsctool -a -f', 0, GSCTOOL_OUTPUT_PREPVT)) 294 self.assertEqual(Cr50Label().get(host), ['cr50:prepvt']) 295 296 def test_gsctool_fails(self): 297 host = MockHost([], 298 MockCmd('gsctool -a -f', 1, '')) 299 self.assertEqual(Cr50Label().get(host), []) 300 301 302class Cr50RWKeyidTests(unittest.TestCase): 303 """Unit tests for Cr50RWKeyidLabel""" 304 305 def test_cr50_prod_rw(self): 306 host = MockHost([], 307 MockCmd('gsctool -a -f', 0, GSCTOOL_OUTPUT_PVT)) 308 self.assertEqual(Cr50RWKeyidLabel().get(host), 309 ['cr50-rw-keyid:0xde88588d', 'cr50-rw-keyid:prod']) 310 311 def test_cr50_dev_rw(self): 312 host = MockHost([], 313 MockCmd('gsctool -a -f', 0, GSCTOOL_OUTPUT_DEV_RW)) 314 self.assertEqual(Cr50RWKeyidLabel().get(host), 315 ['cr50-rw-keyid:0xb93d6539', 'cr50-rw-keyid:dev']) 316 317 def test_gsctool_fails(self): 318 host = MockHost([], 319 MockCmd('gsctool -a -f', 1, '')) 320 self.assertEqual(Cr50RWKeyidLabel().get(host), []) 321 322 323class Cr50ROKeyidTests(unittest.TestCase): 324 """Unit tests for Cr50ROKeyidLabel""" 325 326 def test_cr50_prod_ro(self): 327 host = MockHost([], 328 MockCmd('gsctool -a -f', 0, GSCTOOL_OUTPUT_PREPVT)) 329 self.assertEqual(Cr50ROKeyidLabel().get(host), 330 ['cr50-ro-keyid:0xaa66150f', 'cr50-ro-keyid:prod']) 331 332 def test_cr50_dev_ro(self): 333 host = MockHost([], 334 MockCmd('gsctool -a -f', 0, GSCTOOL_OUTPUT_DEV_RO)) 335 self.assertEqual(Cr50ROKeyidLabel().get(host), 336 ['cr50-ro-keyid:0x3716ee6b', 'cr50-ro-keyid:dev']) 337 338 def test_gsctool_fails(self): 339 host = MockHost([], 340 MockCmd('gsctool -a -f', 1, '')) 341 self.assertEqual(Cr50ROKeyidLabel().get(host), []) 342 343 344class Cr50RWVersionTests(unittest.TestCase): 345 """Unit tests for Cr50RWVersionLabel""" 346 347 def test_cr50_prod_rw(self): 348 host = MockHost([], 349 MockCmd('gsctool -a -f', 0, GSCTOOL_OUTPUT_PVT)) 350 self.assertEqual(Cr50RWVersionLabel().get(host), 351 ['cr50-rw-version:0.3.14']) 352 353 def test_cr50_dev_rw(self): 354 host = MockHost([], 355 MockCmd('gsctool -a -f', 0, GSCTOOL_OUTPUT_PREPVT)) 356 self.assertEqual(Cr50RWVersionLabel().get(host), 357 ['cr50-rw-version:0.4.15']) 358 359 def test_gsctool_fails(self): 360 host = MockHost([], 361 MockCmd('gsctool -a -f', 1, '')) 362 self.assertEqual(Cr50RWVersionLabel().get(host), []) 363 364 365class Cr50ROVersionTests(unittest.TestCase): 366 """Unit tests for Cr50ROVersionLabel""" 367 368 def test_cr50_prod_ro(self): 369 host = MockHost([], 370 MockCmd('gsctool -a -f', 0, GSCTOOL_OUTPUT_PREPVT)) 371 self.assertEqual(Cr50ROVersionLabel().get(host), 372 ['cr50-ro-version:0.0.10']) 373 374 def test_gsctool_fails(self): 375 host = MockHost([], 376 MockCmd('gsctool -a -f', 1, '')) 377 self.assertEqual(Cr50ROVersionLabel().get(host), []) 378 379 380class HWIDLabelTests(unittest.TestCase): 381 def test_merge_hwid_label_lists_empty(self): 382 self.assertEqual(cros_label.HWIDLabel._merge_hwid_label_lists([], []), []) 383 384 def test_merge_hwid_label_lists_singleton(self): 385 self.assertEqual(cros_label.HWIDLabel._merge_hwid_label_lists([], ["4"]), 386 ["4"]) 387 self.assertEqual(cros_label.HWIDLabel._merge_hwid_label_lists(["7"], []), 388 ["7"]) 389 390 def test_merge_hwid_label_lists_override(self): 391 self.assertEqual( 392 cros_label.HWIDLabel._merge_hwid_label_lists(old=["7:a"], new=["7:b"]), 393 ["7:b"]) 394 395 def test_merge_hwid_label_lists_no_override(self): 396 self.assertEqual( 397 cros_label.HWIDLabel._merge_hwid_label_lists(old=["7a"], new=["7b"]), 398 ["7a", "7b"]) 399 400 def test_hwid_label_names(self): 401 class HWIDLabelTester(cros_label.HWIDLabel): 402 def get_all_labels(self): 403 return [], [] 404 405 item = HWIDLabelTester() 406 self.assertEqual(item._hwid_label_names(), cros_label.HWID_LABELS_FALLBACK) 407 408 409class ServoLabelTests(unittest.TestCase): 410 """Unit tests for ServoLabel""" 411 412 def test_servo_working_and_in_cache(self): 413 host = MockHost(['servo_state:WORKING']) 414 servo = ServoLabel() 415 self.assertEqual(servo.get(host), ['servo', 'servo_state:WORKING']) 416 self.assertEqual(servo.exists(host), True) 417 418 def test_servo_working_and_in_cache_but_not_connected(self): 419 host = MockHost(['servo_state:NOT_CONNECTED']) 420 servo = ServoLabel() 421 self.assertEqual(servo.get(host), ['servo_state:BROKEN']) 422 self.assertEqual(servo.exists(host), False) 423 424 def test_servo_not_in_cache_and_not_working(self): 425 host = MockHostWithoutAFE(['not_servo_state:WORKING']) 426 servo = ServoLabel() 427 self.assertEqual(servo.get(host), ['servo_state:BROKEN']) 428 self.assertEqual(servo.exists(host), False) 429 430 @mock.patch('autotest_lib.server.hosts.servo_host.get_servo_args_for_host') 431 @mock.patch('autotest_lib.server.hosts.servo_host.servo_host_is_up') 432 def test_servo_not_in_cache_but_working(self, 433 servo_host_is_up, 434 get_servo_args_for_host): 435 get_servo_args_for_host.return_value = {"servo_host": "some_servo_host_name"} 436 servo_host_is_up.return_value = True 437 host = MockHostWithoutAFE(['not_servo_state:WORKING']) 438 439 servo = ServoLabel() 440 self.assertEqual(servo.get(host), ['servo', 'servo_state:WORKING']) 441 self.assertEqual(servo.exists(host), True) 442 get_servo_args_for_host.assert_called() 443 servo_host_is_up.assert_called() 444 servo_host_is_up.assert_called_with('some_servo_host_name') 445 446 def test_get_all_labels_lists_of_generating_labels(self): 447 servo = ServoLabel() 448 prefix_labels, full_labels = servo.get_all_labels() 449 self.assertEqual(prefix_labels, set(['servo_state'])) 450 self.assertEqual(full_labels, set(['servo'])) 451 452 def test_update_for_task(self): 453 self.assertTrue(ServoLabel().update_for_task('')) 454 self.assertTrue(ServoLabel().update_for_task('repair')) 455 self.assertFalse(ServoLabel().update_for_task('deploy')) 456 457 458class AudioLoopbackDongleLabelTests(unittest.TestCase): 459 def test_update_for_task(self): 460 self.assertTrue(AudioLoopbackDongleLabel().update_for_task('')) 461 self.assertTrue(AudioLoopbackDongleLabel().update_for_task('repair')) 462 self.assertFalse(AudioLoopbackDongleLabel().update_for_task('deploy')) 463 464 465class ChameleonConnectionLabelTests(unittest.TestCase): 466 def test_update_for_task(self): 467 self.assertTrue(ChameleonConnectionLabel().update_for_task('')) 468 self.assertFalse(ChameleonConnectionLabel().update_for_task('repair')) 469 self.assertTrue(ChameleonConnectionLabel().update_for_task('deploy')) 470 471 472class ChameleonLabelTests(unittest.TestCase): 473 def test_update_for_task(self): 474 self.assertTrue(ChameleonLabel().update_for_task('')) 475 self.assertTrue(ChameleonLabel().update_for_task('repair')) 476 self.assertFalse(ChameleonLabel().update_for_task('deploy')) 477 478 479class ChameleonPeripheralsLabelTests(unittest.TestCase): 480 def test_update_for_task(self): 481 self.assertTrue(ChameleonPeripheralsLabel().update_for_task('')) 482 self.assertFalse(ChameleonPeripheralsLabel().update_for_task('repair')) 483 self.assertTrue(ChameleonPeripheralsLabel().update_for_task('deploy')) 484 485 486if __name__ == '__main__': 487 unittest.main() 488