Skip to content

Commit

Permalink
Add TC_ECOINFO_2_1.py test implementation (project-chip#34564)
Browse files Browse the repository at this point in the history
* Add TC_ECOINFO_2_1.py test implementation

* Quick fix

* Restyled by autopep8

* Fix lint and minor test plan update

* add default_matter_test_main

* Address PR comments

* Restyled by autopep8

---------

Co-authored-by: Restyled.io <[email protected]>
  • Loading branch information
2 people authored and j-ororke committed Jul 31, 2024
1 parent 2796358 commit 85b86e4
Showing 1 changed file with 190 additions and 0 deletions.
190 changes: 190 additions & 0 deletions src/python_testing/TC_ECOINFO_2_1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
#
# Copyright (c) 2024 Project CHIP Authors
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

import chip.clusters as Clusters
from chip.clusters.Types import NullValue
from chip.interaction_model import Status
from chip.tlv import uint
from matter_testing_support import MatterBaseTest, TestStep, async_test_body, default_matter_test_main, type_matches
from mobly import asserts


class TC_ECOINFO_2_1(MatterBaseTest):

def _validate_device_directory(self, is_removed_on_null, device_directory):
num_of_devices = len(device_directory)
if is_removed_on_null:
asserts.assert_less_equal(num_of_devices, 256, "Too many device entries")
for device in device_directory:
# TODO do fabric index check first
if device.deviceName is not None:
asserts.assert_true(type_matches(device.deviceName, str), "DeviceName should be a string")
asserts.assert_less_equal(len(device.deviceName), 64, "DeviceName should be <= 64")
asserts.assert_true(type_matches(device.deviceNameLastEdit, uint), "DeviceNameLastEdit should be a uint")
asserts.assert_greater(device.deviceNameLastEdit, 0, "DeviceNameLastEdit must be greater than 0")
else:
asserts.assert_true(device.deviceNameLastEdit is None,
"DeviceNameLastEdit should not be provided when there is no DeviceName")

asserts.assert_true(type_matches(device.bridgedEndpoint, uint), "BridgedEndpoint should be a uint")
asserts.assert_greater_equal(device.bridgedEndpoint, 0, "BridgedEndpoint >= 0")
asserts.assert_less_equal(device.bridgedEndpoint, 0xffff_ffff,
"BridgedEndpoint less than or equal to Invalid Endpoint value")

asserts.assert_true(type_matches(device.originalEndpoint, uint), "OriginalEndpoint should be a uint")
asserts.assert_greater_equal(device.originalEndpoint, 0, "OriginalEndpoint >= 0")
asserts.assert_less(device.originalEndpoint, 0xffff_ffff,
"OriginalEndpoint less than or equal to Invalid Endpoint value")

asserts.assert_true(type_matches(device.deviceTypes, list), "DeviceTypes should be a list")
asserts.assert_greater_equal(len(device.deviceTypes), 1, "DeviceTypes list must contains at least one entry")
for device_type in device.deviceTypes:
asserts.assert_true(type_matches(device_type.deviceType, uint), "DeviceType should be a uint")
# TODO what other validation can we do here to device_type.deviceType
asserts.assert_true(type_matches(device_type.revision, uint), "device type's revision should be a uint")
asserts.assert_greater_equal(device_type.revision, 1, "device type's revision must >= 1")

asserts.assert_true(type_matches(device.uniqueLocationIDs, list), "UniqueLocationIds should be a list")
num_of_unique_location_ids = len(device.uniqueLocationIDs)
asserts.assert_less_equal(num_of_unique_location_ids, 64, "UniqueLocationIds list should be <= 64")
for location_id in device.uniqueLocationIDs:
asserts.assert_true(type_matches(location_id, str), "UniqueLocationId should be a string")
location_id_string_length = len(location_id)
asserts.assert_greater_equal(location_id_string_length, 1,
"UniqueLocationId must contain at least one character")
asserts.assert_less_equal(location_id_string_length, 64, "UniqueLocationId should be <= 64")

asserts.assert_true(type_matches(device.uniqueLocationIDsLastEdit, uint),
"UniqueLocationIdsLastEdit should be a uint")
if num_of_unique_location_ids:
asserts.assert_greater(device.uniqueLocationIDsLastEdit, 0, "UniqueLocationIdsLastEdit must be non-zero")
else:
asserts.assert_equal(num_of_devices, 0, "Device was removed, there should be no devices in DeviceDirectory")

def _validate_location_directory(self, is_removed_on_null, location_directory):
num_of_locations = len(location_directory)
if is_removed_on_null:
asserts.assert_less_equal(num_of_locations, 64, "Too many location entries")
for location in location_directory:
asserts.assert_true(type_matches(location.uniqueLocationID, str), "UniqueLocationId should be a string")
location_id_string_length = len(location.uniqueLocationID)
asserts.assert_greater_equal(location_id_string_length, 1,
"UniqueLocationId must contain at least one character")
asserts.assert_less_equal(location_id_string_length, 64, "UniqueLocationId should be <= 64")

asserts.assert_true(type_matches(location.locationDescriptor.locationName, str),
"LocationName should be a string")
asserts.assert_less_equal(len(location.locationDescriptor.locationName), 64, "LocationName should be <= 64")

if location.locationDescriptor.floorNumber is not NullValue:
asserts.assert_true(type_matches(location.locationDescriptor.floorNumber, int),
"FloorNumber should be an int")
# TODO check in range of int16.

if location.locationDescriptor.areaType is not NullValue:
# TODO check areaType is valid.
pass

asserts.assert_true(type_matches(location.locationDescriptorLastEdit, uint),
"UniqueLocationIdsLastEdit should be a uint")
asserts.assert_greater(location.locationDescriptorLastEdit, 0, "LocationDescriptorLastEdit must be non-zero")

else:
asserts.assert_equal(num_of_locations, 0, "Device was removed, there should be no location in LocationDirectory")

def steps_TC_ECOINFO_2_1(self) -> list[TestStep]:
steps = [TestStep(1, "Identify endpoints with Ecosystem Information Cluster", is_commissioning=True),
TestStep(2, "Reading RemovedOn Attribute"),
TestStep(3, "Reading DeviceDirectory Attribute"),
TestStep(4, "Reading LocationDirectory Attribute"),
TestStep(5, "Try Writing to RemovedOn Attribute"),
TestStep(6, "Try Writing to DeviceDirectory Attribute"),
TestStep(7, "Try Writing to LocationDirectory Attribute"),
TestStep(8, "Repeating steps 2 to 7 for each endpoint identified in step 1")]
return steps

@async_test_body
async def test_TC_ECOINFO_2_1(self):
dev_ctrl = self.default_controller
dut_node_id = self.dut_node_id

self.print_step(0, "Commissioning, already done")

self.step(1)
endpoint_wild_card_read = await dev_ctrl.ReadAttribute(dut_node_id, [(Clusters.EcosystemInformation.Attributes.ClusterRevision)])
list_of_endpoints = list(endpoint_wild_card_read.keys())

for idx, cluster_endpoint in enumerate(list_of_endpoints):
if idx == 0:
self.step(2)
removed_on = await self.read_single_attribute(
dev_ctrl,
dut_node_id,
endpoint=cluster_endpoint,
attribute=Clusters.EcosystemInformation.Attributes.RemovedOn)

is_removed_on_null = removed_on is NullValue
if not is_removed_on_null:
asserts.assert_true(type_matches(removed_on, uint))
asserts.assert_greater(removed_on, 0, "RemovedOn must be greater than 0", "RemovedOn should be a uint")

if idx == 0:
self.step(3)
device_directory = await self.read_single_attribute(
dev_ctrl,
dut_node_id,
endpoint=cluster_endpoint,
attribute=Clusters.EcosystemInformation.Attributes.DeviceDirectory,
fabricFiltered=False)

self._validate_device_directory(is_removed_on_null, device_directory)

if idx == 0:
self.step(4)
location_directory = await self.read_single_attribute(
dev_ctrl,
dut_node_id,
endpoint=cluster_endpoint,
attribute=Clusters.EcosystemInformation.Attributes.LocationDirectory,
fabricFiltered=False)

self._validate_location_directory(is_removed_on_null, location_directory)

if idx == 0:
self.step(5)
result = await dev_ctrl.WriteAttribute(dut_node_id, [(cluster_endpoint, Clusters.EcosystemInformation.Attributes.RemovedOn(2))])
asserts.assert_equal(len(result), 1, "Expecting only one result from trying to write to RemovedOn Attribute")
asserts.assert_equal(result[0].Status, Status.UnsupportedWrite, "Expecting Status of UnsupportedWrite")

if idx == 0:
self.step(6)
result = await dev_ctrl.WriteAttribute(dut_node_id, [(cluster_endpoint, Clusters.EcosystemInformation.Attributes.DeviceDirectory([]))])
asserts.assert_equal(len(result), 1, "Expecting only one result from trying to write to DeviceDirectory Attribute")
asserts.assert_equal(result[0].Status, Status.UnsupportedWrite, "Expecting Status of UnsupportedWrite")

if idx == 0:
self.step(7)
result = await dev_ctrl.WriteAttribute(dut_node_id, [(cluster_endpoint, Clusters.EcosystemInformation.Attributes.DeviceDirectory([]))])
asserts.assert_equal(len(result), 1, "Expecting only one result from trying to write to LocationDirectory Attribute")
asserts.assert_equal(result[0].Status, Status.UnsupportedWrite, "Expecting Status of UnsupportedWrite")

if idx == 0:
self.step(8)


if __name__ == "__main__":
default_matter_test_main()

0 comments on commit 85b86e4

Please sign in to comment.