Skip to content

Commit 8560821

Browse files
aburgonov-dsrgemini-code-assist[bot]hastydsurninjamesharrow
authored
Commodity Metering: TC_COMMTR_2_1, TC_COMMTR_3_1 test scripts (project-chip#39809)
* Test Scripts for Commodity Metering initial commit * Minor change * Gemini suggestion commit for TC_SEMT_2_1 Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Gemini suggestion commit for TC_SEMT_3_1 Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Gemini suggestion commit for TC_SEMT_3_1 Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Gemini suggestion commit for TC_SEMT_3_1 Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Updated: PICS code\CI, test steps, subscription logic, common code * Attributes list is changed * Reporting intervals changed and some minor changes. * TC 2.1 is updated, enable-key is changed for CI * Excluding TC_COMMTR_TestBase.py from CI testing * rename ClusterAttributeChangeAccumulator to AttributeSubscriptionHandler Signed-off-by: Dmitry Surnin <[email protected]> * fix of AttributeSubscriptionHandler usage Signed-off-by: Dmitry Surnin <[email protected]> * Minor fix * Remove incorrect attributes * fix datatype ussage Signed-off-by: Dmitry Surnin <[email protected]> * Restyled by whitespace --------- Signed-off-by: Dmitry Surnin <[email protected]> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: Hasty Granbery <[email protected]> Co-authored-by: Dmitry Surnin <[email protected]> Co-authored-by: dsurnin <[email protected]> Co-authored-by: jamesharrow <[email protected]> Co-authored-by: Restyled.io <[email protected]>
1 parent 585ce6b commit 8560821

File tree

6 files changed

+465
-2
lines changed

6 files changed

+465
-2
lines changed

src/app/tests/suites/certification/PICS.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10416,6 +10416,23 @@ PICS:
1041610416
- label: " Does the device implement the StatusLightBrightnesss attribute?"
1041710417
id: AVSM.S.A0028
1041810418

10419+
#
10420+
# Commodity Metering Cluster
10421+
#
10422+
- label:
10423+
"Does the device implement the Commodity Metering Cluster as a server?"
10424+
id: COMMTR.S
10425+
10426+
# Server attributes
10427+
- label: "Does the device implement the MeteredQuantity attribute?"
10428+
id: COMMTR.S.A0000
10429+
10430+
- label: "Does the device implement the MeteredQuantityTimestamp attribute?"
10431+
id: COMMTR.S.A0001
10432+
10433+
- label: "Does the device implement the TariffUnit attribute?"
10434+
id: COMMTR.S.A0002
10435+
1041910436
#
1042010437
# Meter Identification
1042110438
#

src/app/tests/suites/certification/ci-pics-values

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3066,8 +3066,16 @@ AVSM.S.A0026=1
30663066
AVSM.S.A0027=1
30673067
AVSM.S.A0028=1
30683068

3069-
# Meter Identification
3069+
# Commodity Metering
3070+
#Server
3071+
COMMTR.S=1
30703072

3073+
#Attributes
3074+
COMMTR.S.A0000=1
3075+
COMMTR.S.A0001=1
3076+
COMMTR.S.A0002=1
3077+
3078+
# Meter Identification
30713079
#Server
30723080
MTRID.S=1
30733081

@@ -3079,4 +3087,4 @@ MTRID.S.A0000=1
30793087
MTRID.S.A0001=1
30803088
MTRID.S.A0002=1
30813089
MTRID.S.A0003=1
3082-
MTRID.S.A0004=1
3090+
MTRID.S.A0004=1
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
#
2+
# Copyright (c) 2025 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+
# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments
18+
# for details about the block below.
19+
#
20+
# === BEGIN CI TEST ARGUMENTS ===
21+
# test-runner-runs:
22+
# run1:
23+
# app: ${ENERGY_GATEWAY_APP}
24+
# app-args: >
25+
# --discriminator 1234
26+
# --KVS kvs1
27+
# --trace-to json:${TRACE_APP}.json
28+
# --enable-key 000102030405060708090a0b0c0d0e0f
29+
# script-args: >
30+
# --storage-path admin_storage.json
31+
# --commissioning-method on-network
32+
# --discriminator 1234
33+
# --passcode 20202021
34+
# --PICS src/app/tests/suites/certification/ci-pics-values
35+
# --hex-arg enableKey:000102030405060708090a0b0c0d0e0f
36+
# --endpoint 1
37+
# --trace-to json:${TRACE_TEST_JSON}.json
38+
# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto
39+
# factory-reset: true
40+
# quiet: true
41+
# === END CI TEST ARGUMENTS ===
42+
43+
"""Define Matter test case TC_COMMTR_2_1."""
44+
45+
import logging
46+
47+
import chip.clusters as Clusters
48+
import test_plan_support
49+
from chip.clusters import Globals
50+
from chip.clusters.Types import NullValue
51+
from chip.testing import matter_asserts
52+
from chip.testing.matter_testing import MatterBaseTest, TestStep, default_matter_test_main, has_cluster, run_if_endpoint_matches
53+
from mobly import asserts
54+
from TC_COMMTR_TestBase import CommodityMeteringTestBaseHelper
55+
56+
logger = logging.getLogger(__name__)
57+
58+
cluster = Clusters.CommodityMetering
59+
60+
61+
class TC_COMMTR_2_1(MatterBaseTest, CommodityMeteringTestBaseHelper):
62+
"""Implementation of test case TC_COMMTR_2_1."""
63+
64+
def desc_TC_COMMTR_2_1(self) -> str:
65+
"""Returns a description of this test"""
66+
67+
return "Attributes with Server as DUT"
68+
69+
def pics_TC_COMMTR_2_1(self) -> list[str]:
70+
"""This function returns a list of PICS for this test case that must be True for the test to be run"""
71+
72+
return ["COMMTR.S", "DGGEN.S", "DGGEN.S.A0008", "DGGEN.S.C00.Rsp"]
73+
74+
def steps_TC_COMMTR_2_1(self) -> list[TestStep]:
75+
76+
steps = [
77+
TestStep("1", "Commissioning, already done", test_plan_support.commission_if_required(), is_commissioning=True),
78+
TestStep("2", "TH reads TestEventTriggersEnabled attribute from General Diagnostics Cluster",
79+
"TestEventTriggersEnabled must be True"),
80+
TestStep("3", "TH reads MaximumMeteredQuantities attribute", """
81+
- DUT replies a null value or a uint16 value;
82+
- Store value as MaxMeteredQuantities."""),
83+
TestStep("4", "TH reads MeteredQuantity attribute", """
84+
- DUT replies Null or a list of MeteredQuantityStruct entries.
85+
- Verify that the list length less or equal MaxMeteredQuantities from step 3;
86+
- Verify that the TariffComponentIDs field is a list with length less or equal 128;
87+
- Verify that the Quantity field has int64 type;"""),
88+
TestStep("5", "TH reads MeteredQuantityTimestamp attribute", "DUT replies a null value or epoch-s type."),
89+
TestStep("6", "TH reads MeasurementType attribute", "DUT replies a a null value or MeasurementTypeEnum type."),
90+
TestStep("7", "TH sends TestEventTrigger command Fake Value Update Test Event", "Status code must be SUCCESS."),
91+
TestStep("8", "TH reads MeteredQuantityTimestamp attribute", "DUT replies an epoch-s value."),
92+
TestStep("9", "TH reads MeasurementType attribute", "DUT replies a MeasurementTypeEnum value."),
93+
TestStep("10", "TH reads MaximumMeteredQuantities attribute", """
94+
- DUT replies a uint16 value;
95+
- Value saved as MaxMeteredQuantities."""),
96+
TestStep("11", "TH reads MeteredQuantity attribute", """
97+
- DUT replies a list of MeteredQuantityStruct entries.
98+
- Verify that the list length less or equal MaxMeteredQuantities from step 10;
99+
- Verify that the TariffComponentIDs field is a list with length less or equal 128;
100+
- Verify that the Quantity field has int64 type;"""),
101+
TestStep("12", "TH sends TestEventTrigger command for Test Event Clear", "Status code must be SUCCESS."),
102+
]
103+
104+
return steps
105+
106+
@run_if_endpoint_matches(has_cluster(Clusters.CommodityMetering))
107+
async def test_TC_COMMTR_2_1(self):
108+
"""Implements test procedure for test case TC_COMMTR_2_1."""
109+
110+
endpoint = self.get_endpoint()
111+
112+
# If TestEventTriggers is not enabled this TC can't be checked properly.
113+
if not self.check_pics("DGGEN.S") or not self.check_pics("DGGEN.S.A0008") or not self.check_pics("DGGEN.S.C00.Rsp"):
114+
asserts.skip("PICS DGGEN.S or DGGEN.S.A0008 or DGGEN.S.C00.Rsp is not True")
115+
116+
self.step("1")
117+
# commissioning
118+
119+
self.step("2")
120+
# TH reads TestEventTriggersEnabled attribute from General Diagnostics Cluster, expected to be True
121+
await self.check_test_event_triggers_enabled()
122+
123+
self.step("3")
124+
# Read MaximumMeteredQuantities attribute, expected to be Null or uint16
125+
self.MaximumMeteredQuantities = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.MaximumMeteredQuantities)
126+
if self.MaximumMeteredQuantities is not NullValue:
127+
matter_asserts.assert_valid_uint16(self.MaximumMeteredQuantities, 'MaximumMeteredQuantities must be uint16')
128+
129+
self.step("4")
130+
# Read MeteredQuantity attribute, expected to be Null or list of MeteredQuantityStruct entries.
131+
val = await self.read_single_attribute_check_success(
132+
endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.MeteredQuantity
133+
)
134+
if val is not NullValue:
135+
# Looks like MaximumMeteredQuantities can't be Null if MeteredQuantity is not Null due to it defines the size of the list
136+
asserts.assert_not_equal(self.MaximumMeteredQuantities, NullValue, "MaximumMeteredQuantities must not be NullValue")
137+
matter_asserts.assert_list(val, "MeteredQuantity attribute must return a list",
138+
max_length=self.MaximumMeteredQuantities)
139+
matter_asserts.assert_list_element_type(
140+
val, cluster.Structs.MeteredQuantityStruct, "MeteredQuantity attribute must contain MeteredQuantityStruct elements")
141+
142+
self.step("5")
143+
# Read MeteredQuantityTimestamp attribute, expected to be Null or epoch-s
144+
val = await self.read_single_attribute_check_success(
145+
endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.MeteredQuantityTimestamp
146+
)
147+
if val is not NullValue:
148+
matter_asserts.assert_valid_uint32(val, 'MeteredQuantityTimestamp')
149+
150+
self.step("6")
151+
# Read MeasurementType attribute, expected to be Null or MeasurementTypeEnum
152+
val = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.MeasurementType)
153+
if val is not NullValue:
154+
asserts.assert_is_instance(
155+
val, Globals.Enums.MeasurementTypeEnum, "MeasurementType attribute must return a MeasurementTypeEnum")
156+
157+
self.step("7")
158+
# TH sends TestEventTrigger command Fake Value Update Test Event, expected SUCCESS
159+
await self.send_test_event_trigger_fake_value_update()
160+
161+
self.step("8")
162+
# Read MeteredQuantityTimestamp attribute, expected to be uint32
163+
val = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.MeteredQuantityTimestamp)
164+
asserts.assert_not_equal(val, NullValue, "MeteredQuantityTimestamp must not be NullValue")
165+
matter_asserts.assert_valid_uint32(val, 'MeteredQuantityTimestamp must be uint32')
166+
167+
self.step("9")
168+
# Read MeasurementType attribute, expected to be MeasurementTypeEnum
169+
val = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.MeasurementType)
170+
asserts.assert_not_equal(val, NullValue, "MeasurementType must not be NullValue")
171+
matter_asserts.assert_valid_enum(
172+
val, "MeasurementType attribute must return a MeasurementTypeEnum", cluster.Enums.MeasurementTypeEnum)
173+
174+
self.step("10")
175+
# Read MaximumMeteredQuantities attribute, expected to be uint16
176+
self.MaximumMeteredQuantities = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.MaximumMeteredQuantities)
177+
asserts.assert_not_equal(self.MaximumMeteredQuantities, NullValue, "MaximumMeteredQuantities must not be NullValue")
178+
matter_asserts.assert_valid_uint16(self.MaximumMeteredQuantities, 'MaximumMeteredQuantities must be uint16')
179+
180+
self.step("11")
181+
# Read MeteredQuantity attribute, expected to be list of MeteredQuantityStruct
182+
# Length of the list must be less than or equal to 128
183+
val = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.MeteredQuantity)
184+
185+
if val is not NullValue:
186+
matter_asserts.assert_list(val, "MeteredQuantity attribute must return a list",
187+
max_length=self.MaximumMeteredQuantities)
188+
matter_asserts.assert_list_element_type(
189+
val, cluster.Structs.MeteredQuantityStruct, "MeteredQuantity attribute must contain MeteredQuantityStruct elements")
190+
for item in val:
191+
await self.checkMeteredQuantityStruct(struct=item)
192+
193+
self.step("12")
194+
# TH sends TestEventTrigger command for Test Event Clear, expected SUCCESS
195+
await self.send_test_event_trigger_clear()
196+
197+
198+
if __name__ == "__main__":
199+
default_matter_test_main()

0 commit comments

Comments
 (0)