• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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