Skip to content

Commit

Permalink
[CI] Automate Test_TC_IDM_1_2.yaml (#28071)
Browse files Browse the repository at this point in the history
* [chiptool.py] Allow '*' to be used as a top level endpoint value

* [matter_yamltests] Add saveResponseAs step level keyword to save the whole response

* [matter_yamltests] Add an optional definitions parameters for the methods of pseudo clusters

* [matter_yamltests] Add WildcardResponseExtractorCluster

* [CI] Automate Test_TC_IDM_1_2.yaml
  • Loading branch information
vivien-apple authored and pull[bot] committed Jan 20, 2024
1 parent 107f258 commit 4569580
Show file tree
Hide file tree
Showing 8 changed files with 529 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,8 @@ def __maybe_add_endpoint(self, rv, request):

endpoint_argument_name = 'endpoint-id-ignored-for-group-commands'
endpoint_argument_value = request.endpoint
if endpoint_argument_value == '*':
endpoint_argument_value = 0xFFFF

if (request.is_attribute and not request.command == "writeAttribute") or request.is_event or (request.command in _ANY_COMMANDS_LIST and not request.command == "WriteById"):
endpoint_argument_name = 'endpoint-ids'
Expand Down
5 changes: 5 additions & 0 deletions scripts/py_matter_yamltests/matter_yamltests/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ def __init__(self, test: dict, config: dict, definitions: SpecDefinitions, pics_
self.wait_for = _value_or_none(test, 'wait')
self.event_number = _value_or_none(test, 'eventNumber')
self.run_if = _value_or_none(test, 'runIf')
self.save_response_as = _value_or_none(test, 'saveResponseAs')

self.is_attribute = self.__is_attribute_command()
self.is_event = self.__is_event_command()
Expand Down Expand Up @@ -695,6 +696,9 @@ def post_process_response(self, received_responses):
if not isinstance(received_responses, list):
received_responses = [received_responses]

if self._test.save_response_as:
self._runtime_config_variable_storage[self._test.save_response_as] = received_responses

if self.wait_for is not None:
self._response_cluster_wait_validation(received_responses, result)
return result
Expand Down Expand Up @@ -1112,6 +1116,7 @@ def __init__(self, test_file: str, parser_config: TestParserConfig = TestParserC
tests
)
self.timeout = config['timeout']
self.definitions = parser_config.definitions

def __apply_config_override(self, config, config_override):
for key, value in config_override.items():
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import inspect
from typing import List

from .clusters.commissioner_commands import CommissionerCommands
Expand All @@ -33,12 +34,16 @@ def supports(self, request) -> bool:
def add(self, cluster: PseudoCluster):
self.clusters.append(cluster)

async def execute(self, request):
async def execute(self, request, definitions=None):
status = {'error': 'FAILURE'}

command = self.__get_command(request)
if command:
status = await command(request)
if 'definitions' in inspect.signature(command).parameters:
status = await command(request, definitions)
else:
status = await command(request)

# If the command does not returns an error, it is considered a success.
if status is None:
status = {}
Expand Down
2 changes: 1 addition & 1 deletion scripts/py_matter_yamltests/matter_yamltests/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ async def _run(self, parser: TestParser, config: TestRunnerConfig):

start = time.time()
if config.pseudo_clusters.supports(request):
responses, logs = await config.pseudo_clusters.execute(request)
responses, logs = await config.pseudo_clusters.execute(request, parser.definitions)
else:
encoded_request = config.adapter.encode(request)
encoded_response = await self.execute(encoded_request)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ def __check_test_step(self, config: dict, content):
'PICS': str,
'arguments': dict,
'response': (dict, list, str), # Can be a variable
'saveResponseAs': str,
'minInterval': int,
'maxInterval': int,
'timeout': int,
Expand Down
1 change: 1 addition & 0 deletions scripts/tests/chiptest/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ def _GetInDevelopmentTests() -> Set[str]:
"Test_TC_SMCO_2_4.yaml", # chip-repl does not support timeout (07/20/2023)
"Test_TC_SMCO_2_5.yaml", # chip-repl does not support timeout (07/20/2023)
"Test_TC_SMCO_2_6.yaml", # chip-repl does not support timeout (07/20/2023)
"Test_TC_IDM_1_2.yaml", # chip-repl does not support AnyCommands (19/07/2023)
}


Expand Down
128 changes: 128 additions & 0 deletions scripts/tests/yaml/extensions/wildcard_response_extractor_cluster.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#
# Copyright (c) 2023 Project CHIP Authors
#
# 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.


from matter_yamltests.pseudo_clusters.pseudo_cluster import PseudoCluster

_VALUE_ARGUMENT_NAME = 'Value'
_CLUSTERS_ARGUMENT_NAME = 'Clusters'


class wildcard_response_extractor_cluster(PseudoCluster):
name = 'WildcardResponseExtractorCluster'

async def GetDefaultEndPointForClusters(self, request, definitions):
entries = self.__get_argument(request, _VALUE_ARGUMENT_NAME)
clusters = self.__get_argument(request, _CLUSTERS_ARGUMENT_NAME)
if entries is None or clusters is None:
return {'error': 'INVALID_ARGUMENT'}

results = {}

for cluster in clusters:
cluster_id = definitions.get_cluster_id_by_name(cluster)
results[cluster] = None

for entry in entries:
server_list = entry.get('value')
if cluster_id in server_list:
results[cluster] = entry.get('endpoint')
break

return {'value': results}

async def GetUnsupportedCluster(self, request):
entries = self.__get_argument(request, _VALUE_ARGUMENT_NAME)
if entries is None:
return {'error': 'INVALID_ARGUMENT'}

cluster_ids = []
for entry in entries:
server_list = entry.get('value')
for cluster_id in server_list:
if cluster_id not in cluster_ids:
cluster_ids.append(cluster_id)

unsupported_cluster = None
for cluster_code in range(0xFFFFFFFF):
if cluster_code not in cluster_ids:
unsupported_cluster = f'{cluster_code:#0{10}x}'
break

return {'value': {'UnsupportedCluster': unsupported_cluster}}

async def GetUnsupportedCommand(self, request):
entries = self.__get_argument(request, _VALUE_ARGUMENT_NAME)
if entries is None:
return {'error': 'INVALID_ARGUMENT'}

command_ids = []
for entry in entries:
commands_list = entry.get('value')
for command_id in commands_list:
if command_id not in command_ids:
command_ids.append(command_id)

unsupported_command = None
for command_code in range(0xFFFFFFFF):
if command_code not in command_ids:
unsupported_command = f'{command_code:#0{10}x}'
break

return {'value': {'UnsupportedCommand': unsupported_command}}

async def GetUnsupportedEndPoint(self, request):
entries = self.__get_argument(request, _VALUE_ARGUMENT_NAME)
if entries is None:
return {'error': 'INVALID_ARGUMENT'}

endpoint_ids = []
for entry in entries:
parts_list = entry.get('value')
for endpoint_id in parts_list:
if endpoint_id not in endpoint_ids:
endpoint_ids.append(endpoint_id)

# Add the endpoint id of the response if needed.
endpoint_id = entry.get('endpoint')
if endpoint_id not in endpoint_ids:
endpoint_ids.append(endpoint_id)

unsupported_endpoint = None
for endpoint_code in range(0xFFFF):
if endpoint_code not in endpoint_ids:
unsupported_endpoint = endpoint_code
break

return {'value': {'UnsupportedEndPoint': unsupported_endpoint}}

def __get_argument(self, request, argument_name):
arguments = request.arguments.get('values')
if arguments is None:
return None

if not type(arguments) is list:
return None

for argument in arguments:
name = argument.get('name')
value = argument.get('value')
if name is None or value is None:
return None

if name == argument_name:
return value

return None
Loading

0 comments on commit 4569580

Please sign in to comment.