Skip to content

Commit 06a28f5

Browse files
committed
Add check for unpopulated ARLs
1 parent 7f21c79 commit 06a28f5

File tree

2 files changed

+74
-1
lines changed

2 files changed

+74
-1
lines changed

src/python_testing/TestConformanceTest.py

+50-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from typing import Any
1919

2020
import chip.clusters as Clusters
21+
from basic_composition_support import arls_populated
2122
from conformance_support import ConformanceDecision
2223
from global_attribute_ids import GlobalAttributeIds
2324
from matter_testing_support import MatterBaseTest, async_test_body, default_matter_test_main
@@ -191,7 +192,7 @@ def _create_minimal_dt(self, device_type_id: int) -> dict[int, dict[int, Any]]:
191192
endpoint_tlv[Clusters.Descriptor.id] = attrs
192193
return endpoint_tlv
193194

194-
def add_macl(self, root_endpoint: dict[int, dict[int, Any]]):
195+
def add_macl(self, root_endpoint: dict[int, dict[int, Any]], populate_arl: bool = False, populate_commissioning_arl: bool = False):
195196
ac = Clusters.AccessControl
196197
root_endpoint[ac.id][ac.Attributes.FeatureMap.attribute_id] = ac.Bitmaps.Feature.kManagedDevice
197198
root_endpoint[ac.id][ac.Attributes.Arl.attribute_id] = []
@@ -202,6 +203,14 @@ def add_macl(self, root_endpoint: dict[int, dict[int, Any]]):
202203
root_endpoint[ac.id][ac.Attributes.GeneratedCommandList.attribute_id].append(
203204
ac.Commands.ReviewFabricRestrictionsResponse.command_id)
204205

206+
generic_restriction = ac.Structs.AccessRestrictionStruct(
207+
type=ac.Enums.AccessRestrictionTypeEnum.kAttributeAccessForbidden, id=1)
208+
entry = ac.Structs.CommissioningAccessRestrictionEntryStruct(endpoint=1, cluster=2, restrictions=generic_restriction)
209+
if populate_arl:
210+
root_endpoint[ac.id][ac.Attributes.Arl.attribute_id] = [entry]
211+
if populate_commissioning_arl:
212+
root_endpoint[ac.id][ac.Attributes.CommissioningARL.attribute_id] = [entry]
213+
205214
@async_test_body
206215
async def test_macl_handling(self):
207216
nim_id = self._get_device_type_id('network infrastructure manager')
@@ -231,6 +240,46 @@ async def test_macl_handling(self):
231240

232241
# TODO: what happens if there is a NIM and a non-NIM endpoint?
233242

243+
@async_test_body
244+
async def test_macl_restrictions(self):
245+
246+
nim_id = self._get_device_type_id('network infrastructure manager')
247+
root_node_id = self._get_device_type_id('root node')
248+
on_off_id = self._get_device_type_id('On/Off Light')
249+
250+
root = self._create_minimal_dt(device_type_id=root_node_id)
251+
nim = self._create_minimal_dt(device_type_id=nim_id)
252+
self.endpoints_tlv = {0: root, 1: nim}
253+
254+
# device with no macl
255+
have_arl, have_carl = arls_populated(self.endpoints_tlv)
256+
asserts.assert_false(have_arl, "Unexpected ARL found")
257+
asserts.assert_false(have_carl, "Unexpected CommissioningARL found")
258+
259+
# device with unpopulated macl
260+
self.add_macl(root)
261+
have_arl, have_carl = arls_populated(self.endpoints_tlv)
262+
asserts.assert_false(have_arl, "Unexpected ARL found")
263+
asserts.assert_false(have_carl, "Unexpected CommissioningARL found")
264+
265+
# device with populated ARL
266+
self.add_macl(root, populate_arl=True)
267+
have_arl, have_carl = arls_populated(self.endpoints_tlv)
268+
asserts.assert_true(have_arl, "Did not find expected ARL")
269+
asserts.assert_false(have_carl, "Unexpected CommissioningARL found")
270+
271+
# device with populated commissioning ARL
272+
self.add_macl(root, populate_commissioning_arl=True)
273+
have_arl, have_carl = arls_populated(self.endpoints_tlv)
274+
asserts.assert_false(have_arl, "Unexpected ARL found")
275+
asserts.assert_true(have_carl, "Did not find expected Commissioning ARL")
276+
277+
# device with both
278+
self.add_macl(root, populate_arl=True, populate_commissioning_arl=True)
279+
have_arl, have_carl = arls_populated(self.endpoints_tlv)
280+
asserts.assert_true(have_arl, "Did not find expected ARL")
281+
asserts.assert_true(have_carl, "Did not find expected Commissioning ARL")
282+
234283

235284
if __name__ == "__main__":
236285
default_matter_test_main()

src/python_testing/basic_composition_support.py

+24
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,30 @@
2626
from pprint import pformat, pprint
2727
from typing import Any, Optional
2828

29+
import chip.clusters as Clusters
2930
import chip.clusters.ClusterObjects
3031
import chip.tlv
3132
from chip.clusters.Attribute import ValueDecodeFailure
3233
from mobly import asserts
3334

3435

36+
def arls_populated(tlv_data: dict[int, Any]) -> tuple[bool, bool]:
37+
""" Returns a tuple indicating if the ARL and CommissioningARL are populated.
38+
Requires a wildcard read of the device TLV.
39+
"""
40+
# ACL is always on endpoint 0
41+
if 0 not in tlv_data or Clusters.AccessControl.id not in tlv_data[0]:
42+
return (False, False)
43+
# Both attributes are mandatory for this feature, so if one doesn't exist, neither should the other.
44+
if Clusters.AccessControl.Attributes.Arl.attribute_id not in tlv_data[0][Clusters.AccessControl.id][Clusters.AccessControl.Attributes.AttributeList.attribute_id]:
45+
return (False, False)
46+
47+
have_arl = tlv_data[0][Clusters.AccessControl.id][Clusters.AccessControl.Attributes.Arl.attribute_id]
48+
have_carl = tlv_data[0][Clusters.AccessControl.id][Clusters.AccessControl.Attributes.CommissioningARL.attribute_id]
49+
50+
return (have_arl, have_carl)
51+
52+
3553
def MatterTlvToJson(tlv_data: dict[int, Any]) -> dict[str, Any]:
3654
"""Given TLV data for a specific cluster instance, convert to the Matter JSON format."""
3755

@@ -167,6 +185,12 @@ async def setup_class_helper(self, allow_pase: bool = True):
167185
logging.info("Start of actual tests")
168186
logging.info("###########################################################")
169187

188+
have_arl, have_carl = arls_populated(self.endpoints_tlv)
189+
asserts.assert_false(
190+
have_arl, "ARL cannot be populated for this test - Please follow manufacturer-specific steps to remove the access restrictions and re-run this test")
191+
asserts.assert_false(
192+
have_carl, "CommissioningARL cannot be populated for this test - Please follow manufacturer-specific steps to remove the access restrictions and re-run this test")
193+
170194
def get_test_name(self) -> str:
171195
"""Return the function name of the caller. Used to create logging entries."""
172196
return sys._getframe().f_back.f_code.co_name

0 commit comments

Comments
 (0)