Skip to content

Commit

Permalink
Add support for default pseudo cluster for chip-repl based yamltests (p…
Browse files Browse the repository at this point in the history
…roject-chip#24669)

* Add support for default pseudo cluster

* Address PR comment

* Address PR comment
  • Loading branch information
tehampson authored and David Lechner committed Mar 22, 2023
1 parent 025b413 commit ca52feb
Showing 1 changed file with 45 additions and 1 deletion.
46 changes: 45 additions & 1 deletion src/controller/python/chip/yaml/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,16 @@
import stringcase
from chip import ChipDeviceCtrl
from chip.clusters.Attribute import AttributeStatus, SubscriptionTransaction, TypedAttributePath, ValueDecodeFailure
from chip.exceptions import ChipStackError
from chip.yaml.errors import ParsingError, UnexpectedParsingError
from matter_yamltests.pseudo_clusters.clusters.delay_commands import DelayCommands
from matter_yamltests.pseudo_clusters.clusters.log_commands import LogCommands
from matter_yamltests.pseudo_clusters.clusters.system_commands import SystemCommands
from matter_yamltests.pseudo_clusters.pseudo_clusters import PseudoClusters

from .data_model_lookup import *

_PSEUDO_CLUSTERS = PseudoClusters([DelayCommands(), LogCommands(), SystemCommands()])
logger = logging.getLogger('YamlParser')


Expand Down Expand Up @@ -96,6 +102,18 @@ def run_action(self, dev_ctrl: ChipDeviceCtrl) -> _ActionResult:
pass


class DefaultPseudoCluster(BaseAction):
def __init__(self, test_step):
super().__init__(test_step)
self._test_step = test_step
if not _PSEUDO_CLUSTERS.supports(test_step):
raise ParsingError(f'Default cluster {test_step.cluster} {test_step.command}, not supported')

def run_action(self, dev_ctrl: ChipDeviceCtrl) -> _ActionResult:
resp = asyncio.run(_PSEUDO_CLUSTERS.execute(self._test_step))
return _ActionResult(status=_ActionStatus.SUCCESS, response=None)


class InvokeAction(BaseAction):
'''Single invoke action to be executed.'''

Expand Down Expand Up @@ -213,6 +231,13 @@ def run_action(self, dev_ctrl: ChipDeviceCtrl) -> _ActionResult:
fabricFiltered=self._fabric_filtered))
except chip.interaction_model.InteractionModelError as error:
return _ActionResult(status=_ActionStatus.ERROR, response=error)
except ChipStackError as error:
_CHIP_TIMEOUT_ERROR = 50
if error.err == _CHIP_TIMEOUT_ERROR:
return _ActionResult(status=_ActionStatus.ERROR, response=error)
# For now it is unsure if all ChipStackError are supposed to be intentional.
# As a result we simply re-raise the error.
raise error

return self.parse_raw_response(raw_resp)

Expand Down Expand Up @@ -253,8 +278,13 @@ def __init__(self, test_step):
args = test_step.arguments['values']
request_data_as_dict = Converter.convert_list_of_name_value_pair_to_dict(args)

# There's a chance the commissionee may have rebooted before this call here as part of a
# test flow or is just starting out fresh outright. Unless expireExistingSession is
# explicitly set, the default behaviour it to make sure we're not re-using any cached CASE
# sessions that will now be stale and mismatched with the peer, causing subsequent
# interactions to fail.
self._expire_existing_session = request_data_as_dict.get('expireExistingSession', True)
self._node_id = request_data_as_dict['nodeId']
self._expire_existing_session = request_data_as_dict.get('expireExistingSession', False)
if 'timeout' in request_data_as_dict:
# Timeout is provided in seconds we need to conver to milliseconds.
self._timeout_ms = request_data_as_dict['timeout'] * 1000
Expand Down Expand Up @@ -579,6 +609,12 @@ def _commissioner_command_action_factory(self, test_step):
except ParsingError:
return None

def _default_pseudo_cluster(self, test_step):
try:
return DefaultPseudoCluster(test_step)
except ParsingError:
return None

def encode(self, request) -> BaseAction:
action = None
cluster = request.cluster.replace(' ', '').replace('/', '')
Expand All @@ -605,6 +641,10 @@ def encode(self, request) -> BaseAction:
else:
action = self._invoke_action_factory(request, cluster)

if action is None:
# Now we try to create a default pseudo cluster.
action = self._default_pseudo_cluster(request)

if action is None:
logger.warn(f"Failed to parse {request.label}")
return action
Expand All @@ -628,6 +668,10 @@ def decode(self, result: _ActionResult):
decoded_response['error'] = stringcase.snakecase(response.name).upper()
return decoded_response

if isinstance(response, ChipStackError):
decoded_response['error'] = 'FAILURE'
return decoded_response

cluster_name = self._test_spec_definition.get_cluster_name(response.cluster_id)
if cluster_name is None:
raise Exception("Cannot find cluster name for id 0x%0X / %d" % (response.cluster_id, response.cluster_id))
Expand Down

0 comments on commit ca52feb

Please sign in to comment.