Skip to content

Commit

Permalink
[matter_yamltests] Add saveDataVersionAs supports (#27324)
Browse files Browse the repository at this point in the history
  • Loading branch information
vivien-apple authored and pull[bot] committed Aug 7, 2023
1 parent ee04a06 commit 9129923
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -234,10 +234,36 @@ def __get_command_name(self, request):
return command_name, command_specifier

def __get_arguments(self, request):
# chip-tool expects a json encoded string that contains both mandatory and optional arguments for the target command.
#
# Those arguments are either top level properties of the request object or under the 'arguments' property.
#
# Usually if an argument is used by multiple commands (e.g: 'endpoint', 'min-interval', 'commissioner-name') it is represented as
# a top level property of the request.
# Otherwise if the argument is a command specific argument, it can be retrieved as a member of the 'arguments' property.
#
# As an example, the following test step:
#
# - label: "Send Test Add Arguments Command"
# nodeId: 0x12344321
# endpoint: 1
# cluster: Unit Testing
# command: TestAddArguments
# identity: beta
# arguments:
# values:
# - name: arg1
# value: 3
# - name: arg2
# value: 4
#
# Will be translated to:
# destination-id": "0x12344321", "endpoint-id-ignored-for-group-commands": "1", "arg1":"3", "arg2":"17", "commissioner-name": "beta"
arguments = ''
arguments = self.__maybe_add_destination(arguments, request)
arguments = self.__maybe_add_endpoint(arguments, request)
arguments = self.__maybe_add_command_arguments(arguments, request)
arguments = self.__maybe_add_data_version(arguments, request)
arguments = self.__maybe_add(
arguments, request.min_interval, "min-interval")
arguments = self.__maybe_add(
Expand Down Expand Up @@ -304,6 +330,25 @@ def __maybe_add_command_arguments(self, rv, request):

return rv

def __maybe_add_data_version(self, rv, request):
if request.data_version is None:
return rv

value = ''
if type(request.data_version) is list:
for index, version in enumerate(request.data_version):
value += str(version)
if index != len(request.data_version) - 1:
value += ','
else:
value = request.data_version

if rv:
rv += ', '
rv += f'"data-version":"{value}"'

return rv

def __get_argument_name(self, request, entry):
cluster_name = request.cluster
command_name = request.command
Expand Down
28 changes: 21 additions & 7 deletions scripts/py_matter_yamltests/matter_yamltests/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,8 @@ def __init__(self, test: dict, config: dict, definitions: SpecDefinitions, pics_
self.max_interval = _value_or_none(test, 'maxInterval')
self.timed_interaction_timeout_ms = _value_or_none(
test, 'timedInteractionTimeoutMs')
self.data_version = _value_or_none(
test, 'dataVersion')
self.busy_wait_ms = _value_or_none(test, 'busyWaitMs')
self.wait_for = _value_or_none(test, 'wait')
self.event_number = _value_or_none(test, 'eventNumber')
Expand Down Expand Up @@ -412,7 +414,8 @@ def _convert_single_value_to_values(self, container):
# members of the 'values' array which is what is used for other tests.
value = {}

known_keys_to_copy = ['value', 'constraints', 'saveAs']
known_keys_to_copy = ['value', 'constraints',
'saveAs', 'saveDataVersionAs']
known_keys_to_allow = ['error', 'clusterError']

for key, item in list(container.items()):
Expand Down Expand Up @@ -473,6 +476,8 @@ def _update_with_definition(self, container: dict, mapping_type):
item_value, mapping)
elif key == 'saveAs' and type(item_value) is str and item_value not in self._parsing_config_variable_storage:
self._parsing_config_variable_storage[item_value] = None
elif key == 'saveDataVersionAs' and type(item_value) is str and item_value not in self._parsing_config_variable_storage:
self._parsing_config_variable_storage[item_value] = None
elif key == 'constraints':
for constraint, constraint_value in item_value.items():
# Only apply update_value_with_definition to constraints that have a value that depends on
Expand Down Expand Up @@ -563,6 +568,8 @@ def __init__(self, test: _TestStepWithPlaceholders, step_index: int, runtime_con
if test.is_pics_enabled:
self._update_placeholder_values(self.arguments)
self._update_placeholder_values(self.responses)
self._test.data_version = self._config_variable_substitution(
self._test.data_version)
self._test.node_id = self._config_variable_substitution(
self._test.node_id)
self._test.run_if = self._config_variable_substitution(
Expand Down Expand Up @@ -654,6 +661,10 @@ def max_interval(self):
def timed_interaction_timeout_ms(self):
return self._test.timed_interaction_timeout_ms

@property
def data_version(self):
return self._test.data_version

@property
def busy_wait_ms(self):
return self._test.busy_wait_ms
Expand Down Expand Up @@ -702,7 +713,10 @@ def post_process_response(self, received_responses):
expected_response, received_response, result)
self._response_constraints_validation(
expected_response, received_response, result)
self._maybe_save_as(expected_response, received_response, result)
self._maybe_save_as('saveAs', 'value',
expected_response, received_response, result)
self._maybe_save_as('saveDataVersionAs', 'dataVersion',
expected_response, received_response, result)

# An empty response array in a test step (responses: []) implies that the test step does expect a response
# but without any associated value.
Expand Down Expand Up @@ -936,17 +950,17 @@ def _response_constraints_validation(self, expected_response, received_response,
e.update_context(expected_response, self.step_index)
result.error(check_type, error_failure, e)

def _maybe_save_as(self, expected_response, received_response, result):
def _maybe_save_as(self, key: str, default_target: str, expected_response, received_response, result):
check_type = PostProcessCheckType.SAVE_AS_VARIABLE
error_success = 'The test save the value "{value}" as {name}.'
error_name_does_not_exist = 'The test expects a value named "{name}" but it does not exists in the response."'

for value in expected_response['values']:
if 'saveAs' not in value:
if key not in value:
continue

received_value = received_response.get('value')
if not self.is_attribute and not self.is_event:
received_value = received_response.get(default_target)
if not self.is_attribute and not self.is_event and not (self.command in ANY_COMMANDS_LIST):
expected_name = value.get('name')
if received_value is None or expected_name not in received_value:
result.error(check_type, error_name_does_not_exist.format(
Expand All @@ -956,7 +970,7 @@ def _maybe_save_as(self, expected_response, received_response, result):
received_value = received_value.get(
expected_name) if received_value else None

save_as = value.get('saveAs')
save_as = value.get(key)
self._runtime_config_variable_storage[save_as] = received_value
result.success(check_type, error_success.format(
value=received_value, name=save_as))
Expand Down
4 changes: 3 additions & 1 deletion scripts/py_matter_yamltests/matter_yamltests/yaml_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ def __check_test_step(self, content):
'minInterval': int,
'maxInterval': int,
'timedInteractionTimeoutMs': int,
'dataVersion': (list, int, str), # Can be a variable
'busyWaitMs': int,
'wait': str,
}
Expand Down Expand Up @@ -166,7 +167,8 @@ def __check_test_step_response_value(self, content, allow_name_key=False):
'error': str,
'clusterError': int,
'constraints': dict,
'saveAs': str
'saveAs': str,
'saveDataVersionAs': str,
}

if allow_name_key:
Expand Down

0 comments on commit 9129923

Please sign in to comment.