# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. """Tests for check_ids.""" import unittest from checker.common_checks.check_ids import IdConstraintSuite from chromiumos.config.payload.config_bundle_pb2 import ConfigBundle from chromiumos.config.api.design_pb2 import Design from chromiumos.config.api.design_id_pb2 import DesignId from chromiumos.config.api.design_config_id_pb2 import DesignConfigId from chromiumos.config.api.program_pb2 import (DesignConfigIdSegment, Program) from chromiumos.config.api.program_id_pb2 import ProgramId # Alias a few nested classes to make creating test objects less verbose # pylint: disable=invalid-name Config = Design.Config # pylint: enable=invalid-name # Some tests just check no exceptions were raised, and will not call self.assert # methods # pylint: disable=no-self-use class CheckIdsTest(unittest.TestCase): """Tests for check_ids.""" def test_check_ids_consistent(self): """Tests check_ids_consistent with valid configs.""" program_config = ConfigBundle( program_list=[Program(id=ProgramId(value='testprogram1'))]) project_config = ConfigBundle(design_list=[ Design(program_id=ProgramId(value='testprogram1')), Design(program_id=ProgramId(value='testprogram1')), ]) IdConstraintSuite().check_ids_consistent( program_config=program_config, project_config=project_config, factory_dir=None, ) def test_check_ids_consistent_violated(self): """Tests check_ids_consistent with invalid configs.""" program_config = ConfigBundle( program_list=[Program(id=ProgramId(value='testprogram1'))]) project_config = ConfigBundle(design_list=[ Design(program_id=ProgramId(value='testprogram1')), Design(program_id=ProgramId(value='testprogram2')), ]) with self.assertRaises(AssertionError): IdConstraintSuite().check_ids_consistent( program_config=program_config, project_config=project_config, factory_dir=None, ) def test_check_design_config_id_segments(self): """Test check_design_config_id_segments with valid configs.""" program_config = ConfigBundle(program_list=[ Program(design_config_id_segments=[ DesignConfigIdSegment( design_id=DesignId(value='a'), min_id=11, max_id=20, ), DesignConfigIdSegment( design_id=DesignId(value='b'), min_id=21, max_id=30, ), ]) ]) project_config = ConfigBundle(design_list=[ Design( id=DesignId(value='a'), configs=[ Config(id=DesignConfigId(value='a:11')), Config(id=DesignConfigId(value='a:15')), Config(id=DesignConfigId(value='a:20')), ]), Design( id=DesignId(value='b'), configs=[ Config(id=DesignConfigId(value='b:25')), # Unprovisioned ids are exempt from the check. Config(id=DesignConfigId(value='b:2147483647')), ]), # Design 'c' doesn't have a segment. Design( id=DesignId(value='c'), configs=[ Config(id=DesignConfigId(value='c:40')), ]), ]) IdConstraintSuite().check_design_config_id_segments( program_config=program_config, project_config=project_config, factory_dir=None, ) def test_check_design_config_id_segments_violated(self): """Test check_design_config_id_segments with ids out of range.""" program_config = ConfigBundle(program_list=[ Program(design_config_id_segments=[ DesignConfigIdSegment( design_id=DesignId(value='a'), min_id=11, max_id=20, ), ]) ]) # Test ids on the lower boundary. for id_num in (9, 10): project_config = ConfigBundle(design_list=[ Design( id=DesignId(value='a'), configs=[ Config(id=DesignConfigId(value='a:{}'.format(id_num))), ]), ]) with self.assertRaisesRegex( AssertionError, 'DesignConfigId must be >= 11, got {}'.format(id_num)): IdConstraintSuite().check_design_config_id_segments( program_config=program_config, project_config=project_config, factory_dir=None, ) # Test ids on the upper boundary. for id_num in (21, 22): project_config = ConfigBundle(design_list=[ Design( id=DesignId(value='a'), configs=[ Config(id=DesignConfigId(value='a:{}'.format(id_num))), ]), ]) with self.assertRaisesRegex( AssertionError, 'DesignConfigId must be <= 20, got {}'.format(id_num)): IdConstraintSuite().check_design_config_id_segments( program_config=program_config, project_config=project_config, factory_dir=None, ) def test_check_design_config_id_segments_overlap(self): """Test check_design_config_id_segments_overlap with valid configs.""" program_config = ConfigBundle(program_list=[ Program(design_config_id_segments=[ DesignConfigIdSegment( design_id=DesignId(value='a'), min_id=11, max_id=20, ), DesignConfigIdSegment( design_id=DesignId(value='b'), min_id=21, max_id=30, ), DesignConfigIdSegment( design_id=DesignId(value='c'), min_id=41, max_id=50, ), ]) ]) IdConstraintSuite().check_design_config_id_segments_overlap( program_config=program_config, project_config=None, factory_dir=None) def test_check_design_config_id_segments_overlap_violated(self): """Test check_design_config_id_segments_overlap with overlapping segments.""" program_config = ConfigBundle(program_list=[ Program(design_config_id_segments=[ DesignConfigIdSegment( design_id=DesignId(value='a'), min_id=11, max_id=20, ), DesignConfigIdSegment( design_id=DesignId(value='b'), min_id=20, max_id=30, ), DesignConfigIdSegment( design_id=DesignId(value='c'), min_id=31, max_id=40, ), ]) ]) with self.assertRaisesRegex( AssertionError, 'Segments {} and {} overlap'.format( program_config.program_list[0].design_config_id_segments[0], program_config.program_list[0].design_config_id_segments[1], )): IdConstraintSuite().check_design_config_id_segments_overlap( program_config=program_config, project_config=None, factory_dir=None) # Segments are declared in a different order. program_config = ConfigBundle(program_list=[ Program(design_config_id_segments=[ DesignConfigIdSegment( design_id=DesignId(value='a'), min_id=31, max_id=40, ), DesignConfigIdSegment( design_id=DesignId(value='b'), min_id=20, max_id=30, ), DesignConfigIdSegment( design_id=DesignId(value='c'), min_id=11, max_id=20, ), ]) ]) with self.assertRaisesRegex( AssertionError, 'Segments {} and {} overlap'.format( program_config.program_list[0].design_config_id_segments[2], program_config.program_list[0].design_config_id_segments[1], )): IdConstraintSuite().check_design_config_id_segments_overlap( program_config=program_config, project_config=None, factory_dir=None) # Two segments have the same min_id. program_config = ConfigBundle(program_list=[ Program(design_config_id_segments=[ DesignConfigIdSegment( design_id=DesignId(value='b'), min_id=20, max_id=30, ), DesignConfigIdSegment( design_id=DesignId(value='a'), min_id=20, max_id=25, ), ]) ]) with self.assertRaisesRegex( AssertionError, 'Segments {} and {} overlap'.format( program_config.program_list[0].design_config_id_segments[0], program_config.program_list[0].design_config_id_segments[1], )): IdConstraintSuite().check_design_config_id_segments_overlap( program_config=program_config, project_config=None, factory_dir=None) def test_check_design_config_ids_unique(self): """Tests check_design_config_ids_unique with valid configs.""" project_config = ConfigBundle(design_list=[ Design(configs=[ Config(id=DesignConfigId(value='a')), Config(id=DesignConfigId(value='b')), ]), Design(configs=[Config(id=DesignConfigId(value='c'))]), ]) IdConstraintSuite().check_design_config_ids_unique( program_config=None, project_config=project_config, factory_dir=None, ) def test_check_design_config_ids_unique_violated(self): """Tests check_design_config_ids_unique with valid configs.""" project_config = ConfigBundle(design_list=[ Design(configs=[ Config(id=DesignConfigId(value='a')), Config(id=DesignConfigId(value='b')), ]), Design(configs=[Config(id=DesignConfigId(value='a'))]), ]) with self.assertRaisesRegex(AssertionError, "Found multiple configs with id 'a'"): IdConstraintSuite().check_design_config_ids_unique( program_config=None, project_config=project_config, factory_dir=None, )