Skip to content

Commit 2a827a1

Browse files
authored
Merge branch 'master' into feature/app-install-flow-public
2 parents 1a8f583 + 70744ed commit 2a827a1

File tree

10 files changed

+105
-58
lines changed

10 files changed

+105
-58
lines changed

docs/testing/python.md

+65-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ Python tests located in src/python_testing
1919

2020
## Writing Python tests
2121

22+
- Defining arguments in the test script
23+
- In order to streamline the configuration and execution of tests, it is
24+
essential to define arguments at the top of the test script. This
25+
section should include various parameters and their respective values,
26+
which will guide the test runner on how to execute the tests.
2227
- All test classes inherit from MatterBaseTest in
2328
[matter_testing_support.py](https://github.com/project-chip/connectedhomeip/blob/master/src/python_testing/matter_testing_support.py)
2429
- support for commissioning using the python controller
@@ -36,11 +41,17 @@ Python tests located in src/python_testing
3641
- Use Mobly assertions for failing tests
3742
- self.step() along with a steps\_ function to mark test plan steps for cert
3843
tests
39-
-
4044

4145
### A simple test
4246

4347
```
48+
# test-runner-runs: run1
49+
# test-runner-run/run1/app: ${ALL_CLUSTERS_APP}
50+
# test-runner-run/run1/factoryreset: True
51+
# test-runner-run/run1/quiet: True
52+
# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json
53+
# test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto
54+
4455
class TC_MYTEST_1_1(MatterBaseTest):
4556
4657
@async_test_body
@@ -74,6 +85,59 @@ The default_matter_test_main() function is used to run the test on the command
7485
line. These two lines should appear verbatim at the bottom of every python test
7586
file.
7687

88+
## Defining the test arguments
89+
90+
Below is the format:
91+
92+
```
93+
# test-runner-runs: <run_identifier>
94+
# test-runner-run/<run_identifier>/app: ${TYPE_OF_APP}
95+
# test-runner-run/<run_identifier>/factoryreset: <True|False>
96+
# test-runner-run/<run_identifier>/quiet: <True|False>
97+
# test-runner-run/<run_identifier>/app-args: <app_arguments>
98+
# test-runner-run/<run_identifier>/script-args: <script_arguments>
99+
```
100+
101+
### Description of Parameters
102+
103+
- test-runner-runs: Specifies the identifier for the run. This can be any
104+
unique identifier.
105+
106+
- Example: run1
107+
108+
- test-runner-run/<run_identifier>/app: Indicates the application to be used
109+
in the test. Different app types as needed could be referenced from section
110+
[name: Generate an argument environment file ] of the file
111+
[.github/workflows/tests.yaml](https://github.com/project-chip/connectedhomeip/blob/master/.github/workflows/tests.yaml)
112+
113+
- Example: \${TYPE_OF_APP}
114+
115+
- test-runner-run/<run_identifier>/factoryreset: Determines whether a factory
116+
reset should be performed before the test.
117+
118+
- Example: True
119+
120+
- test-runner-run/<run_identifier>/quiet: Sets the verbosity level of the test
121+
run. When set to True, the test run will be quieter.
122+
123+
- Example: True
124+
125+
- test-runner-run/<run_identifier>/app-args: Specifies the arguments to be
126+
passed to the application during the test.
127+
128+
- Example: --discriminator 1234 --KVS kvs1 --trace-to
129+
json:\${TRACE_APP}.json
130+
131+
- test-runner-run/<run_identifier>/script-args: Specifies the arguments to be
132+
passed to the test script.
133+
- Example: --storage-path admin_storage.json --commissioning-method
134+
on-network --discriminator 1234 --passcode 20202021 --trace-to
135+
json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto
136+
137+
This structured format ensures that all necessary configurations are clearly
138+
defined and easily understood, allowing for consistent and reliable test
139+
execution.
140+
77141
## Cluster Codegen
78142

79143
- [Objects.py](https://github.com/project-chip/connectedhomeip/blob/master/src/controller/python/chip/clusters/Objects.py)

examples/platform/linux/Options.cpp

+10-11
Original file line numberDiff line numberDiff line change
@@ -352,27 +352,28 @@ bool HandleOption(const char * aProgram, OptionSet * aOptions, int aIdentifier,
352352
break;
353353

354354
case kDeviceOption_Version:
355-
LinuxDeviceOptions::GetInstance().payload.version = static_cast<uint8_t>(atoi(aValue));
355+
LinuxDeviceOptions::GetInstance().payload.version = static_cast<uint8_t>(strtoul(aValue, nullptr, 0));
356356
break;
357357

358358
case kDeviceOption_VendorID:
359-
LinuxDeviceOptions::GetInstance().payload.vendorID = static_cast<uint16_t>(atoi(aValue));
359+
LinuxDeviceOptions::GetInstance().payload.vendorID = static_cast<uint16_t>(strtoul(aValue, nullptr, 0));
360360
break;
361361

362362
case kDeviceOption_ProductID:
363-
LinuxDeviceOptions::GetInstance().payload.productID = static_cast<uint16_t>(atoi(aValue));
363+
LinuxDeviceOptions::GetInstance().payload.productID = static_cast<uint16_t>(strtoul(aValue, nullptr, 0));
364364
break;
365365

366366
case kDeviceOption_CustomFlow:
367-
LinuxDeviceOptions::GetInstance().payload.commissioningFlow = static_cast<CommissioningFlow>(atoi(aValue));
367+
LinuxDeviceOptions::GetInstance().payload.commissioningFlow = static_cast<CommissioningFlow>(strtoul(aValue, nullptr, 0));
368368
break;
369369

370370
case kDeviceOption_Capabilities:
371-
LinuxDeviceOptions::GetInstance().payload.rendezvousInformation.Emplace().SetRaw(static_cast<uint8_t>(atoi(aValue)));
371+
LinuxDeviceOptions::GetInstance().payload.rendezvousInformation.Emplace().SetRaw(
372+
static_cast<uint8_t>(strtoul(aValue, nullptr, 0)));
372373
break;
373374

374375
case kDeviceOption_Discriminator: {
375-
uint16_t value = static_cast<uint16_t>(atoi(aValue));
376+
uint16_t value = static_cast<uint16_t>(strtoul(aValue, nullptr, 0));
376377
if (value >= 4096)
377378
{
378379
PrintArgError("%s: invalid value specified for discriminator: %s\n", aProgram, aValue);
@@ -386,7 +387,7 @@ bool HandleOption(const char * aProgram, OptionSet * aOptions, int aIdentifier,
386387
}
387388

388389
case kDeviceOption_Passcode:
389-
LinuxDeviceOptions::GetInstance().payload.setUpPINCode = static_cast<uint32_t>(atoi(aValue));
390+
LinuxDeviceOptions::GetInstance().payload.setUpPINCode = static_cast<uint32_t>(strtoul(aValue, nullptr, 0));
390391
break;
391392

392393
case kDeviceOption_Spake2pSaltBase64: {
@@ -476,11 +477,9 @@ bool HandleOption(const char * aProgram, OptionSet * aOptions, int aIdentifier,
476477
case kDeviceOption_SecuredCommissionerPort:
477478
LinuxDeviceOptions::GetInstance().securedCommissionerPort = static_cast<uint16_t>(atoi(aValue));
478479
break;
479-
case kCommissionerOption_FabricID: {
480-
char * eptr;
481-
LinuxDeviceOptions::GetInstance().commissionerFabricId = (chip::FabricId) strtoull(aValue, &eptr, 0);
480+
case kCommissionerOption_FabricID:
481+
LinuxDeviceOptions::GetInstance().commissionerFabricId = static_cast<chip::FabricId>(strtoull(aValue, nullptr, 0));
482482
break;
483-
}
484483
#endif
485484

486485
case kDeviceOption_Command:

scripts/py_matter_yamltests/matter_yamltests/hooks.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ def stop(self, duration: int):
104104
"""
105105
pass
106106

107-
def test_start(self, filename: str, name: str, count: int):
107+
def test_start(self, filename: str, name: str, count: int, steps: list[str] = []):
108108
"""
109109
This method is called when the runner starts running a single test.
110110
@@ -118,6 +118,9 @@ def test_start(self, filename: str, name: str, count: int):
118118
119119
count: int
120120
The number of steps from the test that will be run.
121+
122+
steps: list[str]
123+
The computed test step names
121124
"""
122125
pass
123126

scripts/tests/chiptest/__init__.py

-33
Original file line numberDiff line numberDiff line change
@@ -226,50 +226,17 @@ def _GetChipReplUnsupportedTests() -> Set[str]:
226226
return {
227227
"Test_AddNewFabricFromExistingFabric.yaml", # chip-repl does not support GetCommissionerRootCertificate and IssueNocChain command
228228
"Test_TC_OPCREDS_3_7.yaml", # chip-repl does not support GetCommissionerRootCertificate and IssueNocChain command
229-
"TestEqualities.yaml", # chip-repl does not support pseudo-cluster commands that return a value
230229
"TestExampleCluster.yaml", # chip-repl does not load custom pseudo clusters
231230
"TestAttributesById.yaml", # chip-repl does not support AnyCommands (06/06/2023)
232231
"TestCommandsById.yaml", # chip-repl does not support AnyCommands (06/06/2023)
233232
"TestEventsById.yaml", # chip-repl does not support AnyCommands (06/06/2023)
234233
"TestReadNoneSubscribeNone.yaml", # chip-repl does not support AnyCommands (07/27/2023)
235-
"Test_TC_DRLK_2_8.yaml", # Test fails only in chip-repl: Refer--> https://github.com/project-chip/connectedhomeip/pull/27011#issuecomment-1593339855
236-
"Test_TC_ACE_1_6.yaml", # Test fails only in chip-repl: Refer--> https://github.com/project-chip/connectedhomeip/pull/27910#issuecomment-1632485584
237234
"Test_TC_IDM_1_2.yaml", # chip-repl does not support AnyCommands (19/07/2023)
238-
"TestGroupKeyManagementCluster.yaml", # chip-repl does not support EqualityCommands (2023-08-04)
239235
"TestIcdManagementCluster.yaml", # TODO(#30430): add ICD registration support in chip-repl
240236
"Test_TC_ICDM_3_4.yaml", # chip-repl does not support ICD registration
241-
"Test_TC_S_2_2.yaml", # chip-repl does not support EqualityCommands pseudo-cluster
242-
"Test_TC_MOD_3_1.yaml", # chip-repl does not support EqualityCommands pseudo-cluster
243-
"Test_TC_MOD_3_2.yaml", # chip-repl does not support EqualityCommands pseudo-cluster
244-
"Test_TC_MOD_3_3.yaml", # chip-repl does not support EqualityCommands pseudo-cluster
245-
"Test_TC_MOD_3_4.yaml", # chip-repl does not support EqualityCommands pseudo-cluster
246-
"Test_TC_BRBINFO_2_1.yaml", # chip-repl does not support EqualityCommands pseudo-cluster
247-
"Test_TC_DGGEN_2_1.yaml", # chip-repl does not support EqualityCommands pseudo-cluster
248-
"Test_TC_DGGEN_2_3.yaml", # chip-repl does not support EqualityCommands pseudo-cluster
249-
"Test_TC_LWM_3_1.yaml", # chip-repl does not support EqualityCommands pseudo-cluster
250-
"Test_TC_LWM_3_2.yaml", # chip-repl does not support EqualityCommands pseudo-cluster
251-
"Test_TC_LWM_3_3.yaml", # chip-repl does not support EqualityCommands pseudo-cluster
252-
"Test_TC_OTCCM_3_1.yaml", # chip-repl does not support EqualityCommands pseudo-cluster
253-
"Test_TC_OTCCM_3_2.yaml", # chip-repl does not support EqualityCommands pseudo-cluster
254-
"Test_TC_OTCCM_3_3.yaml", # chip-repl does not support EqualityCommands pseudo-cluster
255-
"Test_TC_G_2_4.yaml", # chip-repl does not support EqualityCommands pseudo-cluster
256-
"Test_TC_RVCRUNM_3_1.yaml", # chip-repl does not support EqualityCommands pseudo-cluster
257-
"Test_TC_RVCCLEANM_3_1.yaml", # chip-repl does not support EqualityCommands pseudo-cluster
258-
"Test_TC_TCCM_3_1.yaml", # chip-repl does not support EqualityCommands pseudo-cluster
259-
"Test_TC_TCCM_3_2.yaml", # chip-repl does not support EqualityCommands pseudo-cluster
260-
"Test_TC_TCCM_3_3.yaml", # chip-repl does not support EqualityCommands pseudo-cluster
261-
"Test_TC_TCTL_2_1.yaml", # chip-repl does not support EqualityCommands pseudo-cluster
262237
# chip-repl and chip-tool disagree on what the YAML here should look like: https://github.com/project-chip/connectedhomeip/issues/29110
263238
"TestClusterMultiFabric.yaml",
264-
"Test_TC_ACL_2_5.yaml", # chip-repl does not support LastReceivedEventNumber : https://github.com/project-chip/connectedhomeip/issues/28884
265-
"Test_TC_ACL_2_6.yaml", # chip-repl does not support LastReceivedEventNumber : https://github.com/project-chip/connectedhomeip/issues/28884
266-
"Test_TC_RVCCLEANM_3_3.yaml", # chip-repl does not support EqualityCommands pseudo-cluster
267-
"Test_TC_BINFO_2_1.yaml", # chip-repl does not support EqualityCommands pseudo-cluster
268239
"TestDiagnosticLogs.yaml", # chip-repl does not implement a BDXTransferServerDelegate
269-
"Test_TC_EEVSEM_2_1.yaml", # chip-repl does not support EqualityCommands pseudo-cluster
270-
"Test_TC_EEVSEM_3_1.yaml", # chip-repl does not support EqualityCommands pseudo-cluster
271-
"Test_TC_EEVSEM_3_2.yaml", # chip-repl does not support EqualityCommands pseudo-cluster
272-
"Test_TC_EEVSEM_3_3.yaml", # chip-repl does not support EqualityCommands pseudo-cluster
273240
"TestDiagnosticLogsDownloadCommand.yaml", # chip-repl does not implement the bdx download command
274241
}
275242

scripts/tests/chipyaml/tests_logger.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ def start(self, count: int):
161161
def stop(self, duration: int):
162162
print(self.__strings.stop.format(runned=self.__runned, skipped=self.__skipped, duration=duration))
163163

164-
def test_start(self, filename: str, name: str, count: int):
164+
def test_start(self, filename: str, name: str, count: int, steps: list[str] = []):
165165
print(self.__strings.test_start.format(name=click.style(name, bold=True), count=click.style(count, bold=True)))
166166

167167
if self.__use_test_harness_log_format:

scripts/tests/run_python_test.py

+4
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,10 @@ def main(app: str, factoryreset: bool, factoryreset_app_only: bool, app_args: st
110110
)
111111
]
112112

113+
if not runs:
114+
raise Exception(
115+
"No valid runs were found. Make sure you add runs to your file, see https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md document for reference/example.")
116+
113117
for run in runs:
114118
print(f"Executing {run.py_script_path.split('/')[-1]} {run.run}")
115119
main_impl(run.app, run.factoryreset, run.factoryreset_app_only, run.app_args,

src/controller/python/chip/yaml/runner.py

+10-8
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,11 @@
3131
from chip.exceptions import ChipStackError
3232
from chip.yaml.data_model_lookup import DataModelLookup
3333
from chip.yaml.errors import ActionCreationError, UnexpectedActionCreationError
34-
from matter_yamltests.pseudo_clusters.clusters.delay_commands import DelayCommands
35-
from matter_yamltests.pseudo_clusters.clusters.log_commands import LogCommands
36-
from matter_yamltests.pseudo_clusters.clusters.system_commands import SystemCommands
37-
from matter_yamltests.pseudo_clusters.pseudo_clusters import PseudoClusters
34+
from matter_yamltests.pseudo_clusters.pseudo_clusters import get_default_pseudo_clusters
3835

3936
from .data_model_lookup import PreDefinedDataModelLookup
4037

41-
_PSEUDO_CLUSTERS = PseudoClusters([DelayCommands(), LogCommands(), SystemCommands()])
38+
_PSEUDO_CLUSTERS = get_default_pseudo_clusters()
4239
logger = logging.getLogger('YamlParser')
4340

4441

@@ -129,8 +126,8 @@ def __init__(self, test_step):
129126
raise ActionCreationError(f'Default cluster {test_step.cluster} {test_step.command}, not supported')
130127

131128
async def run_action(self, dev_ctrl: ChipDeviceController) -> _ActionResult:
132-
_ = await _PSEUDO_CLUSTERS.execute(self._test_step)
133-
return _ActionResult(status=_ActionStatus.SUCCESS, response=None)
129+
response = await _PSEUDO_CLUSTERS.execute(self._test_step)
130+
return _ActionResult(status=_ActionStatus.SUCCESS, response=response[0])
134131

135132

136133
class InvokeAction(BaseAction):
@@ -884,8 +881,12 @@ def decode(self, result: _ActionResult):
884881
response = result.response
885882

886883
decoded_response = {}
884+
if isinstance(response, dict):
885+
return response
886+
887887
if isinstance(response, chip.interaction_model.InteractionModelError):
888888
decoded_response['error'] = stringcase.snakecase(response.status.name).upper()
889+
decoded_response['clusterError'] = response.clusterStatus
889890
return decoded_response
890891

891892
if isinstance(response, chip.interaction_model.Status):
@@ -939,12 +940,13 @@ def decode(self, result: _ActionResult):
939940
cluster_id = event.Header.ClusterId
940941
cluster_name = self._test_spec_definition.get_cluster_name(cluster_id)
941942
event_id = event.Header.EventId
943+
event_number = event.Header.EventNumber
942944
event_name = self._test_spec_definition.get_event_name(cluster_id, event_id)
943945
event_definition = self._test_spec_definition.get_event_by_name(cluster_name, event_name)
944946
is_fabric_scoped = bool(event_definition.is_fabric_sensitive)
945947
decoded_event = Converter.from_data_model_to_test_definition(
946948
self._test_spec_definition, cluster_name, event_definition.fields, event.Data, is_fabric_scoped)
947-
decoded_response.append({'value': decoded_event})
949+
decoded_response.append({'value': decoded_event, 'eventNumber': event_number})
948950
return decoded_response
949951

950952
if isinstance(response, ChipStackError):

src/python_testing/hello_external_runner.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def start(self, count: int):
5959
def stop(self, duration: int):
6060
self.stop_called = True
6161

62-
def test_start(self, filename: str, name: str, count: int):
62+
def test_start(self, filename: str, name: str, count: int, steps: list[str] = []):
6363
self.test_start_called = True
6464

6565
def test_stop(self, exception: Exception, duration: int):

src/python_testing/hello_test.py

+7
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@
1515
# limitations under the License.
1616
#
1717

18+
# test-runner-runs: run1
19+
# test-runner-run/run1/app: ${TYPE_OF_APP}
20+
# test-runner-run/run1/factoryreset: True
21+
# test-runner-run/run1/quiet: True
22+
# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json
23+
# test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto
24+
1825
import logging
1926

2027
import chip.clusters as Clusters

src/python_testing/matter_testing_support.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ def start(self, count: int):
274274
def stop(self, duration: int):
275275
logging.info(f'Finished test set, ran for {duration}ms')
276276

277-
def test_start(self, filename: str, name: str, count: int):
277+
def test_start(self, filename: str, name: str, count: int, steps: list[str] = []):
278278
logging.info(f'Starting test from {filename}: {name} - {count} steps')
279279

280280
def test_stop(self, exception: Exception, duration: int):
@@ -740,7 +740,8 @@ def setup_test(self):
740740
num_steps = 1 if steps is None else len(steps)
741741
filename = inspect.getfile(self.__class__)
742742
desc = self.get_test_desc(test_name)
743-
self.runner_hook.test_start(filename=filename, name=desc, count=num_steps)
743+
steps_descriptions = [] if steps is None else [step.description for step in steps]
744+
self.runner_hook.test_start(filename=filename, name=desc, count=num_steps, steps=steps_descriptions)
744745
# If we don't have defined steps, we're going to start the one and only step now
745746
# if there are steps defined by the test, rely on the test calling the step() function
746747
# to indicates how it is proceeding

0 commit comments

Comments
 (0)