|
16 | 16 | #
|
17 | 17 | import xml.etree.ElementTree as ElementTree
|
18 | 18 |
|
| 19 | +import chip.clusters as Clusters |
| 20 | +from chip.clusters import Attribute |
| 21 | +from chip.tlv import uint |
| 22 | +from conformance_support import conformance_allowed |
19 | 23 | from jinja2 import Template
|
20 | 24 | from matter_testing_support import MatterBaseTest, default_matter_test_main
|
21 | 25 | from mobly import asserts
|
22 |
| -from spec_parsing_support import build_xml_device_types, parse_single_device_type |
| 26 | +from spec_parsing_support import build_xml_clusters, build_xml_device_types, parse_single_device_type |
| 27 | +from TC_DeviceConformance import DeviceConformanceTests |
23 | 28 |
|
24 | 29 |
|
25 | 30 | class TestSpecParsingDeviceType(MatterBaseTest):
|
26 |
| - |
27 | 31 | # This just tests that the current spec can be parsed without failures
|
28 | 32 | def test_spec_device_parsing(self):
|
29 |
| - device_types, problems = build_xml_device_types() |
30 |
| - self.problems += problems |
31 |
| - for id, d in device_types.items(): |
| 33 | + for id, d in self.xml_device_types.items(): |
32 | 34 | print(str(d))
|
33 | 35 |
|
34 | 36 | def setup_class(self):
|
| 37 | + self.xml_clusters, self.xml_cluster_problems = build_xml_clusters() |
| 38 | + self.xml_device_types, self.xml_device_types_problems = build_xml_device_types() |
| 39 | + |
35 | 40 | self.device_type_id = 0xBBEF
|
36 | 41 | self.revision = 2
|
37 | 42 | self.classification_class = "simple"
|
@@ -106,6 +111,140 @@ def test_bad_scope(self):
|
106 | 111 | device_type, problems = parse_single_device_type(et)
|
107 | 112 | asserts.assert_equal(len(problems), 1, "Device with no scope did not generate a problem notice")
|
108 | 113 |
|
| 114 | + # All these tests are based on the temp sensor device type because it is very simple |
| 115 | + # it requires temperature measurement, identify and the base devices. |
| 116 | + # Right now I'm not testing for binding condition. |
| 117 | + # The test is entirely based on the descriptor cluster so that's all I'm populating here |
| 118 | + # because it makes the test less complex to write. |
| 119 | + def create_test(self, server_list: list[uint], no_descriptor: bool = False, bad_device_id: bool = False) -> DeviceConformanceTests: |
| 120 | + self.test = DeviceConformanceTests() |
| 121 | + self.test.xml_device_types = self.xml_device_types |
| 122 | + self.test.xml_clusters = self.xml_clusters |
| 123 | + |
| 124 | + if bad_device_id: |
| 125 | + known_ids = list(self.test.xml_device_types.keys()) |
| 126 | + device_type_id = [a for a in range(min(known_ids), max(known_ids)) if a not in known_ids][0] |
| 127 | + else: |
| 128 | + device_type_id = 0x0302 |
| 129 | + |
| 130 | + resp = Attribute.AsyncReadTransaction.ReadResponse({}, [], {}) |
| 131 | + if no_descriptor: |
| 132 | + resp.attributes = {1: {}} |
| 133 | + else: |
| 134 | + desc = Clusters.Descriptor |
| 135 | + server_list_attr = Clusters.Descriptor.Attributes.ServerList |
| 136 | + device_type_list_attr = Clusters.Descriptor.Attributes.DeviceTypeList |
| 137 | + device_type_list = [Clusters.Descriptor.Structs.DeviceTypeStruct(deviceType=device_type_id, revision=2)] |
| 138 | + resp.attributes = {1: {desc: {device_type_list_attr: device_type_list, server_list_attr: server_list}}} |
| 139 | + self.test.endpoints = resp.attributes |
| 140 | + |
| 141 | + def create_good_device(self, device_type_id: int) -> DeviceConformanceTests: |
| 142 | + self.test = DeviceConformanceTests() |
| 143 | + self.test.xml_device_types = self.xml_device_types |
| 144 | + self.test.xml_clusters = self.xml_clusters |
| 145 | + |
| 146 | + resp = Attribute.AsyncReadTransaction.ReadResponse({}, [], {}) |
| 147 | + desc = Clusters.Descriptor |
| 148 | + server_list_attr = Clusters.Descriptor.Attributes.ServerList |
| 149 | + device_type_list_attr = Clusters.Descriptor.Attributes.DeviceTypeList |
| 150 | + device_type_list = [Clusters.Descriptor.Structs.DeviceTypeStruct( |
| 151 | + deviceType=device_type_id, revision=self.xml_device_types[device_type_id].revision)] |
| 152 | + server_list = [k for k, v in self.xml_device_types[device_type_id].server_clusters.items( |
| 153 | + ) if conformance_allowed(v.conformance(0, [], []), False)] |
| 154 | + resp.attributes = {1: {desc: {device_type_list_attr: device_type_list, server_list_attr: server_list}}} |
| 155 | + |
| 156 | + self.test.endpoints = resp.attributes |
| 157 | + |
| 158 | + # Test with temp sensor with temp sensor, identify and descriptor |
| 159 | + def test_ts_minimal_clusters(self): |
| 160 | + self.create_test([Clusters.TemperatureMeasurement.id, Clusters.Identify.id, Clusters.Descriptor.id]) |
| 161 | + success, problems = self.test.check_device_type(fail_on_extra_clusters=True) |
| 162 | + if problems: |
| 163 | + print(problems) |
| 164 | + asserts.assert_true(success, "Failure on Temperature Sensor device type test") |
| 165 | + |
| 166 | + # Temp sensor with temp sensor, identify, descriptor, binding |
| 167 | + def test_ts_minimal_with_binding(self): |
| 168 | + self.create_test([Clusters.TemperatureMeasurement.id, Clusters.Identify.id, Clusters.Binding.id, Clusters.Descriptor.id]) |
| 169 | + success, problems = self.test.check_device_type(fail_on_extra_clusters=True) |
| 170 | + if problems: |
| 171 | + print(problems) |
| 172 | + asserts.assert_true(success, "Failure on Temperature Sensor device type test") |
| 173 | + asserts.assert_false(problems, "Found problems on Temperature sensor device type test") |
| 174 | + |
| 175 | + # Temp sensor with temp sensor, identify, descriptor, fixed label |
| 176 | + def test_ts_minimal_with_label(self): |
| 177 | + self.create_test([Clusters.TemperatureMeasurement.id, Clusters.Identify.id, Clusters.FixedLabel.id, Clusters.Descriptor.id]) |
| 178 | + success, problems = self.test.check_device_type(fail_on_extra_clusters=True) |
| 179 | + if problems: |
| 180 | + print(problems) |
| 181 | + asserts.assert_true(success, "Failure on Temperature Sensor device type test") |
| 182 | + asserts.assert_false(problems, "Found problems on Temperature sensor device type test") |
| 183 | + |
| 184 | + # Temp sensor with temp sensor, descriptor |
| 185 | + def test_ts_missing_identify(self): |
| 186 | + self.create_test([Clusters.TemperatureMeasurement.id, Clusters.Descriptor.id]) |
| 187 | + success, problems = self.test.check_device_type(fail_on_extra_clusters=True) |
| 188 | + if problems: |
| 189 | + print(problems) |
| 190 | + asserts.assert_equal(len(problems), 1, "Unexpected number of problems") |
| 191 | + asserts.assert_false(success, "Unexpected success running test that should fail") |
| 192 | + |
| 193 | + # endpoint 1 empty |
| 194 | + def test_endpoint_missing_descriptor(self): |
| 195 | + self.create_test([], no_descriptor=True) |
| 196 | + success, problems = self.test.check_device_type(fail_on_extra_clusters=True) |
| 197 | + if problems: |
| 198 | + print(problems) |
| 199 | + asserts.assert_equal(len(problems), 1, "Unexpected number of problems") |
| 200 | + asserts.assert_false(success, "Unexpected success running test that should fail") |
| 201 | + |
| 202 | + # Temp sensor with temp sensor, descriptor, identify, onoff |
| 203 | + def test_ts_extra_cluster(self): |
| 204 | + self.create_test([Clusters.TemperatureMeasurement.id, Clusters.Identify.id, Clusters.Descriptor.id, Clusters.OnOff.id]) |
| 205 | + success, problems = self.test.check_device_type(fail_on_extra_clusters=True) |
| 206 | + if problems: |
| 207 | + print(problems) |
| 208 | + asserts.assert_equal(len(problems), 1, "Unexpected number of problems") |
| 209 | + asserts.assert_false(success, "Unexpected success running test that should fail") |
| 210 | + |
| 211 | + success, problems = self.test.check_device_type(fail_on_extra_clusters=False) |
| 212 | + asserts.assert_equal(len(problems), 1, "Did not receive expected warning for extra clusters") |
| 213 | + asserts.assert_true(success, "Unexpected failure") |
| 214 | + |
| 215 | + def test_bad_device_type_id_device_type_test(self): |
| 216 | + self.create_test([], bad_device_id=True) |
| 217 | + success, problems = self.test.check_device_type(fail_on_extra_clusters=True) |
| 218 | + if problems: |
| 219 | + print(problems) |
| 220 | + asserts.assert_equal(len(problems), 1, "Unexpected number of problems") |
| 221 | + asserts.assert_false(success, "Unexpected success running test that should fail") |
| 222 | + |
| 223 | + def test_all_device_types(self): |
| 224 | + for id in self.xml_device_types.keys(): |
| 225 | + self.create_good_device(id) |
| 226 | + success, problems = self.test.check_device_type(fail_on_extra_clusters=True) |
| 227 | + if problems: |
| 228 | + print(problems) |
| 229 | + asserts.assert_false(problems, f"Unexpected problems on device type {id}") |
| 230 | + asserts.assert_true(success, f"Unexpected failure on device type {id}") |
| 231 | + |
| 232 | + def test_disallowed_cluster(self): |
| 233 | + for id, dt in self.xml_device_types.items(): |
| 234 | + expected_problems = 0 |
| 235 | + self.create_good_device(id) |
| 236 | + for cluster_id, cluster in dt.server_clusters.items(): |
| 237 | + if not conformance_allowed(cluster.conformance(0, [], []), False): |
| 238 | + self.test.endpoints[1][Clusters.Descriptor][Clusters.Descriptor.Attributes.ServerList].append(cluster_id) |
| 239 | + expected_problems += 1 |
| 240 | + if expected_problems == 0: |
| 241 | + continue |
| 242 | + success, problems = self.test.check_device_type(fail_on_extra_clusters=True) |
| 243 | + if problems: |
| 244 | + print(problems) |
| 245 | + asserts.assert_equal(len(problems), expected_problems, "Unexpected number of problems") |
| 246 | + asserts.assert_false(success, "Unexpected success running test that should fail") |
| 247 | + |
109 | 248 |
|
110 | 249 | if __name__ == "__main__":
|
111 | 250 | default_matter_test_main()
|
0 commit comments