Skip to content

Commit 8eabd12

Browse files
cecillerestyled-commitstcarmelveilleuxandy31415
authored
Cert Test proposal: warnings for common defaults (project-chip#38419)
* Cert Test proposal: warnings for common defaults Adds a test for common defaults that appear in prod devices but probably aren't intended. They can all be turned off via flags, but this will at least warn manufacturers that something is weird. * Restyled by isort * copyright header got cut off * add new test * linter * linter again * Let's use IDM * Fix app name for CI * Update src/python_testing/TestDefaultWarnings.py Co-authored-by: Tennessee Carmel-Veilleux <[email protected]> * Address review comments * whoops, changed the pixit names and forgot to change the CI --------- Co-authored-by: Restyled.io <[email protected]> Co-authored-by: Tennessee Carmel-Veilleux <[email protected]> Co-authored-by: Andrei Litvin <[email protected]>
1 parent 23817fd commit 8eabd12

File tree

4 files changed

+471
-0
lines changed

4 files changed

+471
-0
lines changed

.github/workflows/tests.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,7 @@ jobs:
549549
scripts/run_in_python_env.sh out/venv 'python3 src/python_testing/TestChoiceConformanceSupport.py'
550550
scripts/run_in_python_env.sh out/venv 'python3 src/python_testing/TestConformanceSupport.py'
551551
scripts/run_in_python_env.sh out/venv 'python3 src/python_testing/TestConformanceTest.py'
552+
scripts/run_in_python_env.sh out/venv 'python3 src/python_testing/TestDefaultWarnings.py'
552553
scripts/run_in_python_env.sh out/venv 'python3 src/python_testing/TestIdChecks.py'
553554
scripts/run_in_python_env.sh out/venv 'python3 src/python_testing/TestMatterTestingSupport.py'
554555
scripts/run_in_python_env.sh out/venv 'python3 src/python_testing/TestSpecParsingDeviceType.py'
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
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: ${CHIP_LOCK_APP}
24+
# factory-reset: true
25+
# quiet: true
26+
# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json
27+
# script-args: >
28+
# --storage-path admin_storage.json
29+
# --commissioning-method on-network
30+
# --discriminator 1234
31+
# --passcode 20202021
32+
# --bool-arg pixit_allow_test_in_product_name:True pixit_allow_test_in_vendor_name:True pixit_allow_default_vendor_id:True
33+
# --trace-to json:${TRACE_TEST_JSON}.json
34+
# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto
35+
# === END CI TEST ARGUMENTS ===
36+
37+
from typing import Optional
38+
39+
import chip.clusters as Clusters
40+
from chip.testing.basic_composition import BasicCompositionTests
41+
from chip.testing.matter_testing import (AttributePathLocation, ClusterPathLocation, MatterBaseTest, ProblemLocation, ProblemNotice,
42+
ProblemSeverity, TestStep, async_test_body, default_matter_test_main)
43+
from mobly import asserts
44+
45+
FLAG_PRODUCT_NAME = "pixit_allow_test_in_product_name"
46+
FLAG_VENDOR_NAME = "pixit_allow_test_in_vendor_name"
47+
FLAG_VENDOR_ID = "pixit_allow_default_vendor_id"
48+
FLAG_DEFAULT_CALENDAR_FORMAT = "pixit_allow_default_calendar_format"
49+
FLAG_UNIT_TESTING = "pixit_allow_unit_testing_cluster"
50+
FLAG_FAULT_INJECTION = "pixit_allow_fault_injection_cluster"
51+
FLAG_SAMPLE_MEI = "pixit_allow_sample_mei_cluster"
52+
FLAG_FIXED_LABEL = "pixit_allow_empty_fixed_label_list"
53+
54+
55+
def _problem(location: ProblemLocation, msg: str):
56+
return ProblemNotice("Default Value Checker", location, ProblemSeverity.ERROR, msg)
57+
58+
59+
def warning_wrapper(override_flag: str):
60+
def warning_wrapper_internal(body):
61+
def runner(self: MatterBaseTest):
62+
skip = self.user_params.get(override_flag, False)
63+
if not skip:
64+
problem: ProblemNotice = body(self)
65+
if problem:
66+
problem.problem += f"\nIf this is intended, you may disable this check using the {override_flag}"
67+
self.problems.append(problem)
68+
else:
69+
self.mark_current_step_skipped()
70+
return runner
71+
return warning_wrapper_internal
72+
73+
74+
class DefaultChecker(BasicCompositionTests):
75+
@warning_wrapper(FLAG_PRODUCT_NAME)
76+
def check_default_product_name(self):
77+
cluster = Clusters.BasicInformation
78+
attr = cluster.Attributes.ProductName
79+
val = self.endpoints[0][cluster][attr]
80+
if "test" in val.lower():
81+
return _problem(AttributePathLocation(0, cluster.id, attr.attribute_id), f"Product name contains test ({val})")
82+
83+
@warning_wrapper(FLAG_VENDOR_NAME)
84+
def check_default_vendor_name(self):
85+
cluster = Clusters.BasicInformation
86+
attr = cluster.Attributes.VendorName
87+
val = self.endpoints[0][cluster][attr]
88+
if "test" in val.lower():
89+
return _problem(AttributePathLocation(0, cluster.id, attr.attribute_id), f"Vendor name contains test ({val})")
90+
91+
@warning_wrapper(FLAG_VENDOR_ID)
92+
def check_default_vendor_id(self):
93+
cluster = Clusters.BasicInformation
94+
attr = cluster.Attributes.VendorID
95+
val = self.endpoints[0][cluster][attr]
96+
if val == 0x0000 or val > 0xFFF0:
97+
return _problem(AttributePathLocation(0, cluster.id, attr.attribute_id), f"Vendor is not in manufacturer code range ({val})")
98+
99+
@warning_wrapper(FLAG_DEFAULT_CALENDAR_FORMAT)
100+
def check_default_calendar_format(self):
101+
cluster = Clusters.TimeFormatLocalization
102+
attr = cluster.Attributes.ActiveCalendarType
103+
if cluster in self.endpoints[0].keys() and attr in self.endpoints[0][cluster].keys():
104+
val = self.endpoints[0][cluster][attr]
105+
if val == cluster.Enums.CalendarTypeEnum.kBuddhist:
106+
return _problem(AttributePathLocation(0, cluster.id, attr.attribute_id), "Calendar format is set to default (Buddhist)")
107+
else:
108+
self.mark_current_step_skipped()
109+
110+
def _check_testing_cluster_presence(self, cluster: Clusters.ClusterObjects.Cluster) -> Optional[ProblemNotice]:
111+
for endpoint_num, endpoint in self.endpoints.items():
112+
if cluster.id in endpoint[Clusters.Descriptor][Clusters.Descriptor.Attributes.ServerList]:
113+
return _problem(ClusterPathLocation(endpoint_num, cluster.id), f"{cluster.__name__} cluster found on device.")
114+
115+
@warning_wrapper(FLAG_UNIT_TESTING)
116+
def check_unit_testing_cluster_presence(self):
117+
return self._check_testing_cluster_presence(Clusters.UnitTesting)
118+
119+
@warning_wrapper(FLAG_FAULT_INJECTION)
120+
def check_fault_injection_cluster_presence(self):
121+
return self._check_testing_cluster_presence(Clusters.FaultInjection)
122+
123+
@warning_wrapper(FLAG_SAMPLE_MEI)
124+
def check_sample_mei_cluster_presence(self):
125+
return self._check_testing_cluster_presence(Clusters.SampleMei)
126+
127+
@warning_wrapper(FLAG_FIXED_LABEL)
128+
def check_fixed_label_cluster(self):
129+
cluster = Clusters.FixedLabel
130+
attr = cluster.Attributes.LabelList
131+
if cluster in self.endpoints[0].keys():
132+
val = self.endpoints[0][cluster][attr]
133+
if val == []:
134+
return _problem(AttributePathLocation(0, cluster.id, attr.attribute_id), "Fixed label list is empty")
135+
else:
136+
self.mark_current_step_skipped()
137+
138+
139+
class TC_DefaultChecker(MatterBaseTest, DefaultChecker):
140+
@async_test_body
141+
async def setup_class(self):
142+
super().setup_class()
143+
await self.setup_class_helper()
144+
145+
@async_test_body
146+
async def setup_test(self):
147+
super().setup_test()
148+
self.success = True
149+
150+
def steps_TC_IDM_13_1(self):
151+
steps = [TestStep(1, "TH performs a wildcard read of all attributes"),
152+
TestStep(2, f"If the {FLAG_PRODUCT_NAME} flag is not set, check for \"Test\" in the product name",
153+
"\"Test\" does not appear in the product name"),
154+
TestStep(3, f"If the {FLAG_VENDOR_NAME} flag is not set, check for \"Test\" in the vendor name",
155+
"\"Test\" does not appear in the vendor name"),
156+
TestStep(4, f"If the {FLAG_VENDOR_ID} flag is not set, check for test vendor IDs",
157+
"Product does not use a test vendor ID"),
158+
TestStep(5, f"If the {FLAG_DEFAULT_CALENDAR_FORMAT} flag is not set, and the TimeFormatLocalization cluster is present and has the ActiveCalendarType attribute, check for the default calendar format", "Calendar format is not the default"),
159+
TestStep(6, f"If the {FLAG_UNIT_TESTING} flag is not set, check for the presence of a unit testing cluster on any endpoint",
160+
"Unit testing cluster does not appear on any endpoint"),
161+
TestStep(7, f"If the {FLAG_FAULT_INJECTION} flag is not set, check for the presence of a fault injection cluster on any endpoint",
162+
"Fault injection cluster does not appear on any endpoint"),
163+
TestStep(8, f"If the {FLAG_SAMPLE_MEI} flag is not set, check for the presence of a sample mei cluster on any endpoint",
164+
"Sample MEI cluster does not appear on any endpoint"),
165+
TestStep(
166+
9, f"If the {FLAG_FIXED_LABEL} flag is not set, and the FixedLabel cluster is present on the device, ,check that the fixed label cluster list is not empty", "List is not empty"),
167+
TestStep(10, "Fail on any problems")
168+
]
169+
return steps
170+
171+
def desc_TC_IDM_13_1(self):
172+
return "[TC-IDM-13.1] Accidental defaults check - [DUT as Server]"
173+
174+
def test_TC_IDM_13_1(self):
175+
print(self.user_params)
176+
self.step(1)
177+
self.step(2)
178+
self.check_default_product_name()
179+
self.step(3)
180+
self.check_default_vendor_name()
181+
self.step(4)
182+
self.check_default_vendor_id()
183+
self.step(5)
184+
self.check_default_calendar_format()
185+
self.step(6)
186+
self.check_unit_testing_cluster_presence()
187+
self.step(7)
188+
self.check_fault_injection_cluster_presence()
189+
self.step(8)
190+
self.check_sample_mei_cluster_presence()
191+
self.step(9)
192+
self.check_fixed_label_cluster()
193+
self.step(10)
194+
195+
if self.problems:
196+
asserts.fail("One or more default values found on device")
197+
198+
199+
if __name__ == "__main__":
200+
default_matter_test_main()

0 commit comments

Comments
 (0)