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_ids.""" 5 6import unittest 7 8from checker.common_checks.check_ids import IdConstraintSuite 9 10from chromiumos.config.payload.config_bundle_pb2 import ConfigBundle 11from chromiumos.config.api.design_pb2 import Design 12from chromiumos.config.api.design_id_pb2 import DesignId 13from chromiumos.config.api.design_config_id_pb2 import DesignConfigId 14from chromiumos.config.api.program_pb2 import (DesignConfigIdSegment, Program) 15from chromiumos.config.api.program_id_pb2 import ProgramId 16 17# Alias a few nested classes to make creating test objects less verbose 18# pylint: disable=invalid-name 19Config = Design.Config 20# pylint: enable=invalid-name 21 22# Some tests just check no exceptions were raised, and will not call self.assert 23# methods 24# pylint: disable=no-self-use 25 26 27class CheckIdsTest(unittest.TestCase): 28 """Tests for check_ids.""" 29 30 def test_check_ids_consistent(self): 31 """Tests check_ids_consistent with valid configs.""" 32 program_config = ConfigBundle( 33 program_list=[Program(id=ProgramId(value='testprogram1'))]) 34 35 project_config = ConfigBundle(design_list=[ 36 Design(program_id=ProgramId(value='testprogram1')), 37 Design(program_id=ProgramId(value='testprogram1')), 38 ]) 39 40 IdConstraintSuite().check_ids_consistent( 41 program_config=program_config, 42 project_config=project_config, 43 factory_dir=None, 44 ) 45 46 def test_check_ids_consistent_violated(self): 47 """Tests check_ids_consistent with invalid configs.""" 48 program_config = ConfigBundle( 49 program_list=[Program(id=ProgramId(value='testprogram1'))]) 50 51 project_config = ConfigBundle(design_list=[ 52 Design(program_id=ProgramId(value='testprogram1')), 53 Design(program_id=ProgramId(value='testprogram2')), 54 ]) 55 56 with self.assertRaises(AssertionError): 57 IdConstraintSuite().check_ids_consistent( 58 program_config=program_config, 59 project_config=project_config, 60 factory_dir=None, 61 ) 62 63 def test_check_design_config_id_segments(self): 64 """Test check_design_config_id_segments with valid configs.""" 65 program_config = ConfigBundle(program_list=[ 66 Program(design_config_id_segments=[ 67 DesignConfigIdSegment( 68 design_id=DesignId(value='a'), 69 min_id=11, 70 max_id=20, 71 ), 72 DesignConfigIdSegment( 73 design_id=DesignId(value='b'), 74 min_id=21, 75 max_id=30, 76 ), 77 ]) 78 ]) 79 80 project_config = ConfigBundle(design_list=[ 81 Design( 82 id=DesignId(value='a'), 83 configs=[ 84 Config(id=DesignConfigId(value='a:11')), 85 Config(id=DesignConfigId(value='a:15')), 86 Config(id=DesignConfigId(value='a:20')), 87 ]), 88 Design( 89 id=DesignId(value='b'), 90 configs=[ 91 Config(id=DesignConfigId(value='b:25')), 92 # Unprovisioned ids are exempt from the check. 93 Config(id=DesignConfigId(value='b:2147483647')), 94 ]), 95 # Design 'c' doesn't have a segment. 96 Design( 97 id=DesignId(value='c'), 98 configs=[ 99 Config(id=DesignConfigId(value='c:40')), 100 ]), 101 ]) 102 103 IdConstraintSuite().check_design_config_id_segments( 104 program_config=program_config, 105 project_config=project_config, 106 factory_dir=None, 107 ) 108 109 def test_check_design_config_id_segments_violated(self): 110 """Test check_design_config_id_segments with ids out of range.""" 111 program_config = ConfigBundle(program_list=[ 112 Program(design_config_id_segments=[ 113 DesignConfigIdSegment( 114 design_id=DesignId(value='a'), 115 min_id=11, 116 max_id=20, 117 ), 118 ]) 119 ]) 120 121 # Test ids on the lower boundary. 122 for id_num in (9, 10): 123 project_config = ConfigBundle(design_list=[ 124 Design( 125 id=DesignId(value='a'), 126 configs=[ 127 Config(id=DesignConfigId(value='a:{}'.format(id_num))), 128 ]), 129 ]) 130 131 with self.assertRaisesRegex( 132 AssertionError, 133 'DesignConfigId must be >= 11, got {}'.format(id_num)): 134 IdConstraintSuite().check_design_config_id_segments( 135 program_config=program_config, 136 project_config=project_config, 137 factory_dir=None, 138 ) 139 140 # Test ids on the upper boundary. 141 for id_num in (21, 22): 142 project_config = ConfigBundle(design_list=[ 143 Design( 144 id=DesignId(value='a'), 145 configs=[ 146 Config(id=DesignConfigId(value='a:{}'.format(id_num))), 147 ]), 148 ]) 149 150 with self.assertRaisesRegex( 151 AssertionError, 152 'DesignConfigId must be <= 20, got {}'.format(id_num)): 153 IdConstraintSuite().check_design_config_id_segments( 154 program_config=program_config, 155 project_config=project_config, 156 factory_dir=None, 157 ) 158 159 def test_check_design_config_id_segments_overlap(self): 160 """Test check_design_config_id_segments_overlap with valid configs.""" 161 program_config = ConfigBundle(program_list=[ 162 Program(design_config_id_segments=[ 163 DesignConfigIdSegment( 164 design_id=DesignId(value='a'), 165 min_id=11, 166 max_id=20, 167 ), 168 DesignConfigIdSegment( 169 design_id=DesignId(value='b'), 170 min_id=21, 171 max_id=30, 172 ), 173 DesignConfigIdSegment( 174 design_id=DesignId(value='c'), 175 min_id=41, 176 max_id=50, 177 ), 178 ]) 179 ]) 180 181 IdConstraintSuite().check_design_config_id_segments_overlap( 182 program_config=program_config, project_config=None, factory_dir=None) 183 184 def test_check_design_config_id_segments_overlap_violated(self): 185 """Test check_design_config_id_segments_overlap with overlapping segments.""" 186 program_config = ConfigBundle(program_list=[ 187 Program(design_config_id_segments=[ 188 DesignConfigIdSegment( 189 design_id=DesignId(value='a'), 190 min_id=11, 191 max_id=20, 192 ), 193 DesignConfigIdSegment( 194 design_id=DesignId(value='b'), 195 min_id=20, 196 max_id=30, 197 ), 198 DesignConfigIdSegment( 199 design_id=DesignId(value='c'), 200 min_id=31, 201 max_id=40, 202 ), 203 ]) 204 ]) 205 206 with self.assertRaisesRegex( 207 AssertionError, 'Segments {} and {} overlap'.format( 208 program_config.program_list[0].design_config_id_segments[0], 209 program_config.program_list[0].design_config_id_segments[1], 210 )): 211 IdConstraintSuite().check_design_config_id_segments_overlap( 212 program_config=program_config, project_config=None, factory_dir=None) 213 214 # Segments are declared in a different order. 215 program_config = ConfigBundle(program_list=[ 216 Program(design_config_id_segments=[ 217 DesignConfigIdSegment( 218 design_id=DesignId(value='a'), 219 min_id=31, 220 max_id=40, 221 ), 222 DesignConfigIdSegment( 223 design_id=DesignId(value='b'), 224 min_id=20, 225 max_id=30, 226 ), 227 DesignConfigIdSegment( 228 design_id=DesignId(value='c'), 229 min_id=11, 230 max_id=20, 231 ), 232 ]) 233 ]) 234 235 with self.assertRaisesRegex( 236 AssertionError, 'Segments {} and {} overlap'.format( 237 program_config.program_list[0].design_config_id_segments[2], 238 program_config.program_list[0].design_config_id_segments[1], 239 )): 240 IdConstraintSuite().check_design_config_id_segments_overlap( 241 program_config=program_config, project_config=None, factory_dir=None) 242 243 # Two segments have the same min_id. 244 program_config = ConfigBundle(program_list=[ 245 Program(design_config_id_segments=[ 246 DesignConfigIdSegment( 247 design_id=DesignId(value='b'), 248 min_id=20, 249 max_id=30, 250 ), 251 DesignConfigIdSegment( 252 design_id=DesignId(value='a'), 253 min_id=20, 254 max_id=25, 255 ), 256 ]) 257 ]) 258 259 with self.assertRaisesRegex( 260 AssertionError, 'Segments {} and {} overlap'.format( 261 program_config.program_list[0].design_config_id_segments[0], 262 program_config.program_list[0].design_config_id_segments[1], 263 )): 264 IdConstraintSuite().check_design_config_id_segments_overlap( 265 program_config=program_config, project_config=None, factory_dir=None) 266 267 def test_check_design_config_ids_unique(self): 268 """Tests check_design_config_ids_unique with valid configs.""" 269 project_config = ConfigBundle(design_list=[ 270 Design(configs=[ 271 Config(id=DesignConfigId(value='a')), 272 Config(id=DesignConfigId(value='b')), 273 ]), 274 Design(configs=[Config(id=DesignConfigId(value='c'))]), 275 ]) 276 277 IdConstraintSuite().check_design_config_ids_unique( 278 program_config=None, 279 project_config=project_config, 280 factory_dir=None, 281 ) 282 283 def test_check_design_config_ids_unique_violated(self): 284 """Tests check_design_config_ids_unique with valid configs.""" 285 project_config = ConfigBundle(design_list=[ 286 Design(configs=[ 287 Config(id=DesignConfigId(value='a')), 288 Config(id=DesignConfigId(value='b')), 289 ]), 290 Design(configs=[Config(id=DesignConfigId(value='a'))]), 291 ]) 292 293 with self.assertRaisesRegex(AssertionError, 294 "Found multiple configs with id 'a'"): 295 IdConstraintSuite().check_design_config_ids_unique( 296 program_config=None, 297 project_config=project_config, 298 factory_dir=None, 299 ) 300