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"""Constraint checks related to topologies.""" 5 6import pathlib 7 8from checker import constraint_suite 9from common import proto_utils 10 11from chromiumos.config.payload import config_bundle_pb2 12from chromiumos.config.api import topology_pb2 13 14 15class TopologyConstraintSuite(constraint_suite.ConstraintSuite): 16 """Constraint checks related to program and project ids.""" 17 18 __error_message_template = ''' 19Two different messages found for id and type ({id}, {type}) 20 21First message: 22{first_message} 23 24Second message: 25 26{second_message} 27''' 28 29 def check_topologies_consistent( 30 self, 31 program_config: config_bundle_pb2.ConfigBundle, 32 project_config: config_bundle_pb2.ConfigBundle, 33 factory_dir: pathlib.Path, 34 ): 35 """Checks all topologies in a project are consistent. 36 37 Consistency is defined as: For a given Topology id and type, the entire 38 Topology message is equal, where two messages are equal iff their binary 39 serializations are equal. 40 41 For example: 42 43 { 44 { 45 "id": "part1", 46 "type": "SCREEN", 47 "description": { 48 "EN": "The first type of screen" 49 } 50 }, 51 { 52 "id": "part1", 53 "type": "SCREEN", 54 "description": { 55 "EN": "The second type of screen" 56 } 57 } 58 } 59 60 is inconsistent because a given id and type ("part1" and "SCREEN") are used 61 in different messages (descriptions are different.) 62 """ 63 # program_config and factory_dir not used. 64 del program_config, factory_dir 65 66 # Map from (Topology.id, Topology.type) -> Topology. 67 topology_map = {} 68 69 for design in project_config.design_list: 70 for config in design.configs: 71 for topology in proto_utils.get_all_fields(config.hardware_topology): 72 key = (topology.id, topology.type) 73 prev_topology = topology_map.get(key) 74 if prev_topology: 75 # Consider two messages equal iff their serialized form is the same. 76 # Include a human-readable error message as well. 77 self.assertEqual( 78 prev_topology.SerializeToString(deterministic=True), 79 topology.SerializeToString(deterministic=True), 80 msg=self.__error_message_template.format( 81 id=key[0], 82 type=topology_pb2.Topology.Type.Name(key[1]), 83 first_message=prev_topology, 84 second_message=topology, 85 )) 86 else: 87 topology_map[key] = topology 88