1#!/usr/bin/python3 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 7from unittest import mock 8 9import common 10 11from autotest_lib.server import utils 12from autotest_lib.server.hosts.cros_label import BrandCodeLabel 13from autotest_lib.server.hosts.cros_label import Cr50Label 14from autotest_lib.server.hosts.cros_label import Cr50ROKeyidLabel 15from autotest_lib.server.hosts.cros_label import Cr50RWKeyidLabel 16from autotest_lib.server.hosts.cros_label import DeviceSkuLabel 17from autotest_lib.server.hosts.cros_label import AudioConfigLabel 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 AudioConfigLabelTests(unittest.TestCase): 247 """Unit tests for AudioConfigLabel""" 248 249 HAS_NC_BOARD_INI_OUTPUT = """ 250 [hotword] 251 pause_at_suspend=1 252 [processing] 253 nc_supported=1 254 hw_echo_ref_disabled=1 255 """ 256 257 NO_NC_BOARD_INI_OUTPUT = """ 258 [hotword] 259 pause_at_suspend=1 260 [processing] 261 hw_echo_ref_disabled=1 262 """ 263 264 DISABLED_NC_BOARD_INI_OUTPUT = """ 265 [hotword] 266 pause_at_suspend=1 267 [processing] 268 hw_echo_ref_disabled=1 269 nc_supported=0 270 """ 271 272 def test_has_noise_cancellation_label_enabled(self): 273 cros_config_cmd = 'cros_config / name' 274 cras_config_cmd = 'cat /etc/cras/HAS_NC/board.ini' 275 host = MockHost([], MockCmd(cros_config_cmd, 0, 'HAS_NC\n'), 276 MockCmd(cras_config_cmd, 0, 277 self.HAS_NC_BOARD_INI_OUTPUT)) 278 self.assertEqual(AudioConfigLabel().get(host), 279 ['audio:has_noise_cancellation']) 280 281 def test_has_noise_cancellation_label_not_exists(self): 282 cros_config_cmd = 'cros_config / name' 283 cras_config_cmd = 'cat /etc/cras/NO_NC/board.ini' 284 host = MockHost([], MockCmd(cros_config_cmd, 0, 'NO_NC\n'), 285 MockCmd(cras_config_cmd, 0, 286 self.NO_NC_BOARD_INI_OUTPUT)) 287 self.assertEqual(AudioConfigLabel().get(host), []) 288 289 def test_has_noise_cancellation_label_disabled(self): 290 cros_config_cmd = 'cros_config / name' 291 cras_config_cmd = 'cat /etc/cras/DISABLED_NC/board.ini' 292 host = MockHost([], MockCmd(cros_config_cmd, 0, 'DISABLED_NC\n'), 293 MockCmd(cras_config_cmd, 0, 294 self.DISABLED_NC_BOARD_INI_OUTPUT)) 295 self.assertEqual(AudioConfigLabel().get(host), []) 296 297 def test_has_noise_cancellation_label_fails_cros_config(self): 298 cros_config_cmd = 'cros_config / name' 299 cras_config_cmd = 'cat /etc/cras/HAS_NC/board.ini' 300 host = MockHost([], MockCmd(cros_config_cmd, 1, 'HAS_NC\n'), 301 MockCmd(cras_config_cmd, 0, 302 self.HAS_NC_BOARD_INI_OUTPUT)) 303 self.assertEqual(AudioConfigLabel().get(host), []) 304 305 def test_has_noise_cancellation_label_fails_cras_config(self): 306 cros_config_cmd = 'cros_config / name' 307 cras_config_cmd = 'cat /etc/cras/HAS_NC/board.ini' 308 host = MockHost([], MockCmd(cros_config_cmd, 0, 'HAS_NC\n'), 309 MockCmd(cras_config_cmd, 1, 310 self.HAS_NC_BOARD_INI_OUTPUT)) 311 self.assertEqual(AudioConfigLabel().get(host), []) 312 313 314class AudioLoopbackDongleLabelTests(unittest.TestCase): 315 def test_update_for_task(self): 316 self.assertTrue(AudioLoopbackDongleLabel().update_for_task('')) 317 self.assertTrue(AudioLoopbackDongleLabel().update_for_task('repair')) 318 self.assertFalse(AudioLoopbackDongleLabel().update_for_task('deploy')) 319 320 321class ChameleonConnectionLabelTests(unittest.TestCase): 322 def test_update_for_task(self): 323 self.assertTrue(ChameleonConnectionLabel().update_for_task('')) 324 self.assertFalse(ChameleonConnectionLabel().update_for_task('repair')) 325 self.assertTrue(ChameleonConnectionLabel().update_for_task('deploy')) 326 327 328class ChameleonLabelTests(unittest.TestCase): 329 def test_update_for_task(self): 330 self.assertTrue(ChameleonLabel().update_for_task('')) 331 self.assertTrue(ChameleonLabel().update_for_task('repair')) 332 self.assertFalse(ChameleonLabel().update_for_task('deploy')) 333 334 335class ServoTypeLabelTests(unittest.TestCase): 336 """Unit tests for ServoTypeLabel""" 337 def test_update_for_task(self): 338 self.assertTrue(ServoTypeLabel().update_for_task('')) 339 self.assertFalse(ServoTypeLabel().update_for_task('repair')) 340 self.assertTrue(ServoTypeLabel().update_for_task('deploy')) 341 342 def test_generate_labels_return_value_from_labels(self): 343 host = MockHost(['servo_type:Some_interesting']) 344 servo = ServoTypeLabel() 345 self.assertEqual(servo.get(host), ['servo_type:Some_interesting']) 346 self.assertEqual(servo.generate_labels(host), ['Some_interesting']) 347 348 def test_generate_labels_from_cache_when_servo_is_none(self): 349 host = MockHost(['servo_state:Some_interesting']) 350 host.servo = None 351 servo = ServoTypeLabel() 352 self.assertEqual(servo.get(host), []) 353 self.assertEqual(servo.generate_labels(host), []) 354 355 def test_generate_labels_not_from_cache_when_servo_exist(self): 356 host = MockHost(['servo_type']) 357 host.servo = mock.Mock() 358 host.servo.get_servo_version.return_value = 'servo_v3' 359 servo = ServoTypeLabel() 360 self.assertEqual(servo.get(host), ['servo_type:servo_v3']) 361 self.assertEqual(servo.generate_labels(host), ['servo_v3']) 362 host.servo.get_servo_version.assert_called() 363 364 365if __name__ == '__main__': 366 unittest.main() 367