| # 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. |
| """Constraint checks related to topologies.""" |
| |
| import pathlib |
| |
| from checker import constraint_suite |
| from common import proto_utils |
| |
| from chromiumos.config.payload import config_bundle_pb2 |
| from chromiumos.config.api import topology_pb2 |
| |
| |
| class TopologyConstraintSuite(constraint_suite.ConstraintSuite): |
| """Constraint checks related to program and project ids.""" |
| |
| __error_message_template = ''' |
| Two different messages found for id and type ({id}, {type}) |
| |
| First message: |
| {first_message} |
| |
| Second message: |
| |
| {second_message} |
| ''' |
| |
| def check_topologies_consistent( |
| self, |
| program_config: config_bundle_pb2.ConfigBundle, |
| project_config: config_bundle_pb2.ConfigBundle, |
| factory_dir: pathlib.Path, |
| ): |
| """Checks all topologies in a project are consistent. |
| |
| Consistency is defined as: For a given Topology id and type, the entire |
| Topology message is equal, where two messages are equal iff their binary |
| serializations are equal. |
| |
| For example: |
| |
| { |
| { |
| "id": "part1", |
| "type": "SCREEN", |
| "description": { |
| "EN": "The first type of screen" |
| } |
| }, |
| { |
| "id": "part1", |
| "type": "SCREEN", |
| "description": { |
| "EN": "The second type of screen" |
| } |
| } |
| } |
| |
| is inconsistent because a given id and type ("part1" and "SCREEN") are used |
| in different messages (descriptions are different.) |
| """ |
| # program_config and factory_dir not used. |
| del program_config, factory_dir |
| |
| # Map from (Topology.id, Topology.type) -> Topology. |
| topology_map = {} |
| |
| for design in project_config.design_list: |
| for config in design.configs: |
| for topology in proto_utils.get_all_fields(config.hardware_topology): |
| key = (topology.id, topology.type) |
| prev_topology = topology_map.get(key) |
| if prev_topology: |
| # Consider two messages equal iff their serialized form is the same. |
| # Include a human-readable error message as well. |
| self.assertEqual( |
| prev_topology.SerializeToString(deterministic=True), |
| topology.SerializeToString(deterministic=True), |
| msg=self.__error_message_template.format( |
| id=key[0], |
| type=topology_pb2.Topology.Type.Name(key[1]), |
| first_message=prev_topology, |
| second_message=topology, |
| )) |
| else: |
| topology_map[key] = topology |