1# Copyright 2020 The ChromiumOS Authors 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4"""Tests for check_firmware_configuration.""" 5 6import unittest 7 8from checker.common_checks.check_firmware_configuration import ( 9 FirmwareConfigurationConstraintSuite) 10 11from chromiumos.config.payload.config_bundle_pb2 import ConfigBundle 12from chromiumos.config.api.design_pb2 import Design 13from chromiumos.config.api.program_pb2 import (Program, 14 FirmwareConfigurationSegment) 15from chromiumos.config.api.hardware_topology_pb2 import HardwareTopology 16from chromiumos.config.api.topology_pb2 import HardwareFeatures, Topology 17 18# Alias a few nested classes to make creating test objects less verbose 19# pylint: disable=invalid-name 20FirmwareConfiguration = HardwareFeatures.FirmwareConfiguration 21Config = Design.Config 22# pylint: enable=invalid-name 23 24# Some tests just check no exceptions were raised, and will not call self.assert 25# methods 26# pylint: disable=no-self-use 27 28 29class CheckFirmwareConfigurationTest(unittest.TestCase): 30 """Tests for check_firmware_configuration.""" 31 32 def test_check_firmware_configuration_masks(self): 33 """Tests check_firmware_configuration_masks with valid configs.""" 34 program_config = ConfigBundle(program_list=[ 35 Program(firmware_configuration_segments=[ 36 FirmwareConfigurationSegment(name='screen', mask=0b0001), 37 FirmwareConfigurationSegment(name='form_factor', mask=0b0110), 38 ]) 39 ]) 40 41 project_config = ConfigBundle(design_list=[ 42 Design(configs=[ 43 Config( 44 hardware_topology=HardwareTopology( 45 screen=Topology( 46 type=Topology.SCREEN, 47 hardware_feature=HardwareFeatures( 48 fw_config=FirmwareConfiguration( 49 value=0b0000, 50 mask=0b0001, 51 ))), 52 form_factor=Topology( 53 type=Topology.FORM_FACTOR, 54 hardware_feature=HardwareFeatures( 55 fw_config=FirmwareConfiguration( 56 value=0b0010, 57 mask=0b0110, 58 ))), 59 )) 60 ]), 61 ]) 62 63 FirmwareConfigurationConstraintSuite().check_firmware_configuration_masks( 64 program_config=program_config, 65 project_config=project_config, 66 factory_dir=None, 67 ) 68 69 def test_check_firmware_configuration_masks_overlap(self): 70 """Tests check_firmware_configuration_masks with overlapping segments.""" 71 program_config = ConfigBundle(program_list=[ 72 Program(firmware_configuration_segments=[ 73 FirmwareConfigurationSegment(name='screen', mask=0b0011), 74 FirmwareConfigurationSegment(name='form_factor', mask=0b0110), 75 ]) 76 ]) 77 78 with self.assertRaisesRegex( 79 AssertionError, 80 'Overlap in masks screen and form_factor: 11 & 110 = 10'): 81 FirmwareConfigurationConstraintSuite().check_firmware_configuration_masks( 82 program_config=program_config, project_config=None, factory_dir=None) 83 84 def test_check_firmware_configuration_multiple_masks_in_use(self): 85 """Tests check_firmware_configuration_masks with a topology using 86 multiple fw_config fields. 87 """ 88 program_config = ConfigBundle(program_list=[ 89 Program(firmware_configuration_segments=[ 90 FirmwareConfigurationSegment(name='screen_a', mask=0b0001), 91 FirmwareConfigurationSegment(name='screen_b', mask=0b1110), 92 ]) 93 ]) 94 95 project_config = ConfigBundle(design_list=[ 96 Design(configs=[ 97 Config( 98 hardware_topology=HardwareTopology( 99 screen=Topology( 100 id="DEFAULT", 101 type=Topology.SCREEN, 102 hardware_feature=HardwareFeatures( 103 fw_config=FirmwareConfiguration( 104 value=0b0001, 105 mask=0b1111, 106 ))),)) 107 ]), 108 ]) 109 110 FirmwareConfigurationConstraintSuite().check_firmware_configuration_masks( 111 program_config=program_config, 112 project_config=project_config, 113 factory_dir=None, 114 ) 115 116 def test_check_firmware_configuration_incomplete_mask(self): 117 """Tests check_firmware_configuration_masks with an incomplete mask.""" 118 program_config = ConfigBundle(program_list=[ 119 Program(firmware_configuration_segments=[ 120 FirmwareConfigurationSegment(name='screen_a', mask=0b0001), 121 FirmwareConfigurationSegment(name='screen_b', mask=0b1110), 122 ]) 123 ]) 124 125 project_config = ConfigBundle(design_list=[ 126 Design(configs=[ 127 Config( 128 hardware_topology=HardwareTopology( 129 screen=Topology( 130 id="DEFAULT", 131 type=Topology.SCREEN, 132 hardware_feature=HardwareFeatures( 133 fw_config=FirmwareConfiguration( 134 value=0b0001, 135 mask=0b0111, 136 ))),)) 137 ]), 138 ]) 139 140 with self.assertRaisesRegex( 141 AssertionError, 'Topology SCREEN:DEFAULT with fw_config mask ' 142 '0x00000007 did not specify the complete ' 143 'fw_config field "screen_b" with mask ' 144 '0x0000000E'): 145 FirmwareConfigurationConstraintSuite().check_firmware_configuration_masks( 146 program_config=program_config, 147 project_config=project_config, 148 factory_dir=None, 149 ) 150 151 def test_check_firmware_configuration_extra_mask(self): 152 """Tests check_firmware_configuration_masks with an extra mask.""" 153 program_config = ConfigBundle(program_list=[ 154 Program(firmware_configuration_segments=[ 155 FirmwareConfigurationSegment(name='screen', mask=0b0001), 156 ]) 157 ]) 158 159 project_config = ConfigBundle(design_list=[ 160 Design(configs=[ 161 Config( 162 hardware_topology=HardwareTopology( 163 screen=Topology( 164 id="DEFAULT", 165 type=Topology.SCREEN, 166 hardware_feature=HardwareFeatures( 167 fw_config=FirmwareConfiguration( 168 value=0b0001, 169 mask=0b0111, 170 ))),)) 171 ]), 172 ]) 173 174 with self.assertRaisesRegex( 175 AssertionError, 'Topology SCREEN:DEFAULT specifies fw_mask ' 176 'that is not known 0x00000006'): 177 FirmwareConfigurationConstraintSuite().check_firmware_configuration_masks( 178 program_config=program_config, 179 project_config=project_config, 180 factory_dir=None, 181 ) 182 183 def test_check_firmware_value_collision(self): 184 """Tests check_firmware_value_collision on a valid config.""" 185 project_config = ConfigBundle(design_list=[ 186 Design(configs=[ 187 Config( 188 hardware_topology=HardwareTopology( 189 # ('screen1', SCREEN) topology uses fw value 0b0001. 190 screen=Topology( 191 id='screen1', 192 type=Topology.SCREEN, 193 description={'EN': 'First description'}, 194 hardware_feature=HardwareFeatures( 195 fw_config=FirmwareConfiguration(value=0b0001))), 196 # ('ff1', FORM_FACTOR) topology doesn't specify a fw 197 # value. 198 form_factor=Topology( 199 id='ff1', 200 type=Topology.FORM_FACTOR, 201 ), 202 )), 203 Config( 204 hardware_topology=HardwareTopology( 205 # ('screen2', SCREEN) topology is used in a different 206 # design, again using fw value 0b0001. This is valid, 207 # because the topology has the same type. 208 screen=Topology( 209 id='screen2', 210 type=Topology.SCREEN, 211 description={'EN': 'Slightly different description'}, 212 hardware_feature=HardwareFeatures( 213 fw_config=FirmwareConfiguration(value=0b0001))),),), 214 ]), 215 ]) 216 217 FirmwareConfigurationConstraintSuite( 218 ).check_firmware_configuration_value_collision( 219 program_config=None, 220 project_config=project_config, 221 factory_dir=None, 222 ) 223 224 def test_check_firmware_value_collision_invalid_config(self): 225 """Tests check_firmware_value_collision on an invalid config.""" 226 project_config = ConfigBundle(design_list=[ 227 Design(configs=[ 228 Config( 229 hardware_topology=HardwareTopology( 230 # Both ('screen1', SCREEN) and ('thermal1', THERMAL) use 231 # fw value 0b0001. 232 screen=Topology( 233 id='screen1', 234 type=Topology.SCREEN, 235 hardware_feature=HardwareFeatures( 236 fw_config=FirmwareConfiguration(value=0b0001))), 237 thermal=Topology( 238 id='thermal1', 239 type=Topology.THERMAL, 240 hardware_feature=HardwareFeatures( 241 fw_config=FirmwareConfiguration(value=0b0001))), 242 )), 243 ]), 244 ]) 245 246 with self.assertRaisesRegex( 247 AssertionError, 248 (r'Topologies \(thermal1, THERMAL\) and \(screen1, SCREEN\) both use ' 249 r'firmware value 1 but have different types')): 250 FirmwareConfigurationConstraintSuite( 251 ).check_firmware_configuration_value_collision( 252 program_config=None, 253 project_config=project_config, 254 factory_dir=None, 255 ) 256