Skip to content

Commit 240d59d

Browse files
committed
Python testing: id range check functions
1 parent 320f83e commit 240d59d

File tree

2 files changed

+323
-0
lines changed

2 files changed

+323
-0
lines changed

src/python_testing/TestIdChecks.py

+230
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
#
2+
# Copyright (c) 2024 Project CHIP Authors
3+
# All rights reserved.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
#
17+
18+
from global_attribute_ids import *
19+
from matter_testing_support import MatterBaseTest, default_matter_test_main
20+
from mobly import asserts
21+
22+
23+
class TestIdChecks(MatterBaseTest):
24+
def test_device_type_ids(self):
25+
standard_good = [0x0000_0000, 0x0000_BFFF]
26+
standard_bad = [0x0000_C000]
27+
28+
manufacturer_good = [0x0001_0000, 0x0001_BFFF, 0xFFF0_0000, 0xFFF0_BFFF]
29+
manufacturer_bad = [0x0001_C000, 0xFFF0_C000]
30+
31+
test_good = [0xFFF1_0000, 0xFFF1_BFFF, 0xFFF4_0000, 0xFFF4_BFFF]
32+
test_bad = [0xFFF1_C000, 0xFFF4_C000]
33+
34+
prefix_bad = [0xFFF5_0000, 0xFFF5_BFFFF, 0xFFF5_C000]
35+
36+
def check_standard(id):
37+
msg = f"Incorrect device type range assessment, expecting standard {id:08x}"
38+
asserts.assert_true(standard_device_type_range(id), msg)
39+
asserts.assert_false(manufacturer_device_type_range(id), msg)
40+
asserts.assert_false(test_device_type_range(id), msg)
41+
asserts.assert_true(valid_device_type_range(id, allow_test=True), msg)
42+
asserts.assert_true(valid_device_type_range(id, allow_test=False), msg)
43+
44+
def check_manufacturer(id):
45+
msg = f"Incorrect device type range assessment, expecting manufacturer {id:08x}"
46+
asserts.assert_false(standard_device_type_range(id), msg)
47+
asserts.assert_true(manufacturer_device_type_range(id), msg)
48+
asserts.assert_false(test_device_type_range(id), msg)
49+
asserts.assert_true(valid_device_type_range(id, allow_test=True), msg)
50+
asserts.assert_true(valid_device_type_range(id, allow_test=False), msg)
51+
52+
def check_test(id):
53+
msg = f"Incorrect device type range assessment, expecting test {id:08x}"
54+
asserts.assert_false(standard_device_type_range(id), msg)
55+
asserts.assert_false(manufacturer_device_type_range(id), msg)
56+
asserts.assert_true(test_device_type_range(id), msg)
57+
asserts.assert_true(valid_device_type_range(id, allow_test=True), msg)
58+
asserts.assert_false(valid_device_type_range(id, allow_test=False), msg)
59+
60+
def check_all_bad(id):
61+
msg = f"Incorrect device type range assessment, expecting invalid {id:08x}"
62+
asserts.assert_false(standard_device_type_range(id), msg)
63+
asserts.assert_false(manufacturer_device_type_range(id), msg)
64+
asserts.assert_false(valid_device_type_range(id, allow_test=True), msg)
65+
asserts.assert_false(valid_device_type_range(id, allow_test=False), msg)
66+
67+
for id in standard_good:
68+
check_standard(id)
69+
70+
for id in standard_bad:
71+
check_all_bad(id)
72+
73+
for id in manufacturer_good:
74+
check_manufacturer(id)
75+
76+
for id in manufacturer_bad:
77+
check_all_bad(id)
78+
79+
for id in test_good:
80+
check_test(id)
81+
82+
for id in test_bad:
83+
check_all_bad(id)
84+
85+
for id in prefix_bad:
86+
check_all_bad(id)
87+
88+
def test_cluster_ids(self):
89+
standard_good = [0x0000_0000, 0x0000_7FFF]
90+
standard_bad = [0x0000_8000]
91+
92+
manufacturer_good = [0x0001_FC00, 0x0001_FFFE, 0xFFF0_FC00, 0xFFF0_FFFE]
93+
manufacturer_bad = [0x0001_0000, 0x0001_7FFF, 0x0001_FFFF, 0xFFF0_0000, 0xFFF0_7FFF, 0xFFF0_FFFF]
94+
95+
test_good = [0xFFF1_FC00, 0xFFF1_FFFE, 0xFFF4_FC00, 0xFFF4_FFFE]
96+
test_bad = [0xFFF1_0000, 0xFFF1_7FFF, 0xFFF1_FFFF, 0xFFF4_0000, 0xFFF4_7FFF, 0xFFF4_FFFF]
97+
98+
prefix_bad = [0xFFF5_0000, 0xFFF5_FC00, 0xFFF5_FFFF]
99+
100+
def check_standard(id):
101+
msg = f"Incorrect cluster range assessment, expecting standard {id:08x}"
102+
asserts.assert_true(standard_cluster_range(id), msg)
103+
asserts.assert_false(manufacturer_cluster_range(id), msg)
104+
asserts.assert_false(test_cluster_range(id), msg)
105+
asserts.assert_true(valid_cluster_range(id, allow_test=True), msg)
106+
asserts.assert_true(valid_cluster_range(id, allow_test=False), msg)
107+
108+
def check_manufacturer(id):
109+
msg = f"Incorrect cluster range assessment, expecting manufacturer {id:08x}"
110+
asserts.assert_false(standard_cluster_range(id), msg)
111+
asserts.assert_true(manufacturer_cluster_range(id), msg)
112+
asserts.assert_false(test_cluster_range(id), msg)
113+
asserts.assert_true(valid_cluster_range(id, allow_test=True), msg)
114+
asserts.assert_true(valid_cluster_range(id, allow_test=False), msg)
115+
116+
def check_test(id):
117+
msg = f"Incorrect cluster range assessment, expecting test {id:08x}"
118+
asserts.assert_false(standard_cluster_range(id), msg)
119+
asserts.assert_false(manufacturer_cluster_range(id), msg)
120+
asserts.assert_true(test_cluster_range(id), msg)
121+
asserts.assert_true(valid_cluster_range(id, allow_test=True), msg)
122+
asserts.assert_false(valid_cluster_range(id, allow_test=False), msg)
123+
124+
def check_all_bad(id):
125+
msg = f"Incorrect cluster range assessment, expecting invalid {id:08x}"
126+
asserts.assert_false(standard_cluster_range(id), msg)
127+
asserts.assert_false(manufacturer_cluster_range(id), msg)
128+
asserts.assert_false(test_cluster_range(id), msg)
129+
asserts.assert_false(valid_cluster_range(id, allow_test=True), msg)
130+
asserts.assert_false(valid_cluster_range(id, allow_test=False), msg)
131+
132+
for id in standard_good:
133+
check_standard(id)
134+
135+
for id in standard_bad:
136+
check_all_bad(id)
137+
138+
for id in manufacturer_good:
139+
check_manufacturer(id)
140+
141+
for id in manufacturer_bad:
142+
check_all_bad(id)
143+
144+
for id in test_good:
145+
check_test(id)
146+
147+
for id in test_bad:
148+
check_all_bad(id)
149+
150+
for id in prefix_bad:
151+
check_all_bad(id)
152+
153+
def test_attribute_ids(self):
154+
standard_global_good = [0x0000_F000, 0x0000_FFFE]
155+
standard_global_bad = [0x0000_FFFF]
156+
standard_non_global_good = [0x0000_0000, 0x0000_4FFF]
157+
standard_non_global_bad = [0x0000_5000]
158+
manufacturer_good = [0x0001_0000, 0x0001_4FFF, 0xFFF0_0000, 0xFFF0_4FFF]
159+
manufacturer_bad = [0x0001_5000, 0x0001_F000, 0x0001_FFFFF, 0xFFF0_5000, 0xFFF0_F000, 0xFFF0_FFFF]
160+
test_good = [0xFFF1_0000, 0xFFF1_4FFF, 0xFFF4_0000, 0xFFF4_4FFF]
161+
test_bad = [0xFFF1_5000, 0xFFF1_F000, 0xFFF1_FFFFF, 0xFFF4_5000, 0xFFF4_F000, 0xFFF4_FFFF]
162+
prefix_bad = [0xFFF5_0000, 0xFFF5_4FFF, 0xFFF5_5000, 0xFFF5_F000, 0xFFF5_FFFF]
163+
164+
def check_standard_global(id):
165+
msg = f"Incorrect attribute range assessment, expecting standard global {id:08x}"
166+
asserts.assert_true(standard_global_attribute_range(id), msg)
167+
asserts.assert_false(standard_non_global_attribute_range(id), msg)
168+
asserts.assert_false(manufacturer_attribute_range(id), msg)
169+
asserts.assert_false(test_attribute_range(id), msg)
170+
asserts.assert_true(valid_attribute_range(id, allow_test=True), msg)
171+
asserts.assert_true(valid_attribute_range(id, allow_test=False), msg)
172+
173+
def check_standard_non_global(id):
174+
msg = f"Incorrect attribute range assessment, expecting standard non-global {id:08x}"
175+
asserts.assert_false(standard_global_attribute_range(id), msg)
176+
asserts.assert_true(standard_non_global_attribute_range(id), msg)
177+
asserts.assert_false(manufacturer_attribute_range(id), msg)
178+
asserts.assert_false(test_attribute_range(id), msg)
179+
asserts.assert_true(valid_attribute_range(id, allow_test=True), msg)
180+
asserts.assert_true(valid_attribute_range(id, allow_test=False), msg)
181+
182+
def check_manufacturer(id):
183+
msg = f"Incorrect attribute range assessment, expecting manufacturer {id:08x}"
184+
asserts.assert_false(standard_global_attribute_range(id), msg)
185+
asserts.assert_false(standard_non_global_attribute_range(id), msg)
186+
asserts.assert_true(manufacturer_attribute_range(id), msg)
187+
asserts.assert_false(test_attribute_range(id), msg)
188+
asserts.assert_true(valid_attribute_range(id, allow_test=True), msg)
189+
asserts.assert_true(valid_attribute_range(id, allow_test=False), msg)
190+
191+
def check_test(id):
192+
msg = f"Incorrect attribute range assessment, expecting test {id:08x}"
193+
asserts.assert_false(standard_global_attribute_range(id), msg)
194+
asserts.assert_false(standard_non_global_attribute_range(id), msg)
195+
asserts.assert_false(manufacturer_attribute_range(id), msg)
196+
asserts.assert_true(test_attribute_range(id), msg)
197+
asserts.assert_true(valid_attribute_range(id, allow_test=True), msg)
198+
asserts.assert_false(valid_attribute_range(id, allow_test=False), msg)
199+
200+
def check_all_bad(id):
201+
msg = f"Incorrect attribute range assessment, expecting invalid {id:08x}"
202+
asserts.assert_false(standard_global_attribute_range(id), msg)
203+
asserts.assert_false(standard_non_global_attribute_range(id), msg)
204+
asserts.assert_false(manufacturer_attribute_range(id), msg)
205+
asserts.assert_false(test_attribute_range(id), msg)
206+
asserts.assert_false(valid_attribute_range(id, allow_test=True), msg)
207+
asserts.assert_false(valid_attribute_range(id, allow_test=False), msg)
208+
209+
for id in standard_global_good:
210+
check_standard_global(id)
211+
for id in standard_global_bad:
212+
check_all_bad(id)
213+
for id in standard_non_global_good:
214+
check_standard_non_global(id)
215+
for id in standard_non_global_bad:
216+
check_all_bad(id)
217+
for id in manufacturer_good:
218+
check_manufacturer(id)
219+
for id in manufacturer_bad:
220+
check_all_bad(id)
221+
for id in test_good:
222+
check_test(id)
223+
for id in test_bad:
224+
check_all_bad(id)
225+
for id in prefix_bad:
226+
check_all_bad(id)
227+
228+
229+
if __name__ == "__main__":
230+
default_matter_test_main()

src/python_testing/global_attribute_ids.py

+93
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
# This file should be removed once we have a good way to get this from the codegen or XML
1919

20+
from dataclasses import dataclass
2021
from enum import IntEnum
2122

2223

@@ -38,3 +39,95 @@ def to_name(self) -> str:
3839
return "FeatureMap"
3940
if self == GlobalAttributeIds.CLUSTER_REVISION_ID:
4041
return "ClusterRevision"
42+
43+
44+
@dataclass
45+
class IdRange:
46+
min: int
47+
max: int
48+
49+
def _contains(self, id: int):
50+
return id in range(self.min, self.max+1)
51+
52+
53+
@dataclass
54+
class PrefixIdRange(IdRange):
55+
def contains(self, id: int):
56+
return super()._contains(id >> 16)
57+
58+
59+
class SuffixIdRange(IdRange):
60+
def contains(self, id: int):
61+
return super()._contains(id & 0xFFFF)
62+
63+
64+
STANDARD_PREFIX = PrefixIdRange(0x0000, 0x0000)
65+
MANUFACTURER_PREFIX = PrefixIdRange(0x0001, 0xFFF0)
66+
TEST_PREFIX = PrefixIdRange(0xFFF1, 0xFFF4)
67+
68+
DEVICE_TYPE_ID_RANGE_SUFFIX = SuffixIdRange(0x0000, 0xBFFF)
69+
CLUSTER_ID_STANDARD_RANGE_SUFFIX = SuffixIdRange(0x0000, 0x7FFF)
70+
CLUSTER_ID_MANUFACTURER_RANGE_SUFFIX = SuffixIdRange(0xFC00, 0xFFFE)
71+
ATTRIBUTE_ID_GLOBAL_RANGE_SUFFIX = SuffixIdRange(0xF000, 0xFFFE)
72+
ATTRIBUTE_ID_NON_GLOBAL_RANGE_SUFFIX = SuffixIdRange(0x0000, 0x4FFF)
73+
74+
75+
def standard_device_type_range(id: int):
76+
return STANDARD_PREFIX.contains(id) and DEVICE_TYPE_ID_RANGE_SUFFIX.contains(id)
77+
78+
79+
def manufacturer_device_type_range(id: int):
80+
return MANUFACTURER_PREFIX.contains(id) and DEVICE_TYPE_ID_RANGE_SUFFIX.contains(id)
81+
82+
83+
def test_device_type_range(id: int):
84+
return TEST_PREFIX.contains(id) and DEVICE_TYPE_ID_RANGE_SUFFIX.contains(id)
85+
86+
87+
def valid_device_type_range(id: int, allow_test: bool = False):
88+
ret = manufacturer_device_type_range(id) or standard_device_type_range(id)
89+
if allow_test:
90+
ret = ret or test_device_type_range(id)
91+
return ret
92+
93+
94+
def standard_cluster_range(id: int):
95+
return STANDARD_PREFIX.contains(id) and CLUSTER_ID_STANDARD_RANGE_SUFFIX.contains(id)
96+
97+
98+
def manufacturer_cluster_range(id: int):
99+
return MANUFACTURER_PREFIX.contains(id) and CLUSTER_ID_MANUFACTURER_RANGE_SUFFIX.contains(id)
100+
101+
102+
def test_cluster_range(id: int):
103+
return TEST_PREFIX.contains(id) and CLUSTER_ID_MANUFACTURER_RANGE_SUFFIX.contains(id)
104+
105+
106+
def valid_cluster_range(id: int, allow_test: bool = False):
107+
ret = standard_cluster_range(id) or manufacturer_cluster_range(id)
108+
if allow_test:
109+
ret = ret or test_cluster_range(id)
110+
return ret
111+
112+
113+
def standard_non_global_attribute_range(id: int):
114+
return STANDARD_PREFIX.contains(id) and ATTRIBUTE_ID_NON_GLOBAL_RANGE_SUFFIX.contains(id)
115+
116+
117+
def standard_global_attribute_range(id: str):
118+
return STANDARD_PREFIX.contains(id) and ATTRIBUTE_ID_GLOBAL_RANGE_SUFFIX.contains(id)
119+
120+
121+
def manufacturer_attribute_range(id: str):
122+
return MANUFACTURER_PREFIX.contains(id) and ATTRIBUTE_ID_NON_GLOBAL_RANGE_SUFFIX.contains(id)
123+
124+
125+
def test_attribute_range(id: str):
126+
return TEST_PREFIX.contains(id) and ATTRIBUTE_ID_NON_GLOBAL_RANGE_SUFFIX.contains(id)
127+
128+
129+
def valid_attribute_range(id: str, allow_test: bool = False):
130+
ret = standard_global_attribute_range(id) or standard_non_global_attribute_range(id) or manufacturer_attribute_range(id)
131+
if allow_test:
132+
ret = ret or test_attribute_range(id)
133+
return ret

0 commit comments

Comments
 (0)