[Local Agent] b/282592569 Retrieve commission RPC request. functional proof: https://paste.googleplex.com/5265599176376320 Test coverage: https://paste.googleplex.com/4949417630105600 Design Doc: go/ghts:dd:matter-enhance Change-Id: I7ffe0b50f01dbdd69b025eb53948c653bd0959eb
diff --git a/local_agent/local_agent.py b/local_agent/local_agent.py index 25398d1..5400fa1 100644 --- a/local_agent/local_agent.py +++ b/local_agent/local_agent.py
@@ -50,6 +50,7 @@ '~/.config/google/local_agent_config.ini') _START_TEST_SUITE_METHOD = 'startTestSuite' _END_TEST_SUITE_METHOD = 'endTestSuite' +_COMMISSION_TO_GOOGLE_FABRIC_METHOD = 'commissionToGoogleFabric' _USER_CONFIG_ROOT_KEY = 'ServerConfig' _USER_CONFIG_AMS_HOST = 'AMS_HOST' _USER_CONFIG_AMS_PORT = 'AMS_PORT' @@ -67,6 +68,8 @@ START_TEST_SUITE = enum.auto() END_TEST_SUITE = enum.auto() DEVICE_QUERY_CONTROL = enum.auto() + COMMISSION_TO_GOOGLE_FABRIC = enum.auto() + # ======================== Module level functions ========================== # def rpc_request_type(method: str) -> RpcRequestType: @@ -82,6 +85,8 @@ return RpcRequestType.START_TEST_SUITE elif method == _END_TEST_SUITE_METHOD: return RpcRequestType.END_TEST_SUITE + elif method == _COMMISSION_TO_GOOGLE_FABRIC_METHOD: + return RpcRequestType.COMMISSION_TO_GOOGLE_FABRIC else: return RpcRequestType.DEVICE_QUERY_CONTROL # ========================================================================== # @@ -323,6 +328,10 @@ elif req_type == RpcRequestType.DEVICE_QUERY_CONTROL: resp = self._translator.dispatch_to_cmd_handler(rpc_request) + elif req_type == RpcRequestType.COMMISSION_TO_GOOGLE_FABRIC: + # TODO(b/282592569): Move commission_to_google_fabric out of translator. + resp = self._translator.commission_to_google_fabric(rpc_request) + else: raise errors.InvalidRPCError( f'Invalid RPC request type {req_type}.')
diff --git a/local_agent/tests/unit_tests/test_local_agent.py b/local_agent/tests/unit_tests/test_local_agent.py index 184685b..6d05c94 100644 --- a/local_agent/tests/unit_tests/test_local_agent.py +++ b/local_agent/tests/unit_tests/test_local_agent.py
@@ -39,9 +39,11 @@ _FAKE_RPC_RESPONSE = {'fake': 'response'} _FAKE_RPC_ID = 'fake-rpc-id' _FAKE_ERROR_MSG = 'fake-error-msg' +_FAKE_COMMISSION_ERROR_MSG = 'Unable to commission the device.' _FAKE_ARTIFACTS_DIR = 'fake-artifacts-dir' _START_TEST_SUITE = 'startTestSuite' _END_TEST_SUITE = 'endTestSuite' +_COMMISSION_TO_GOOGLE_FABRIC = 'commissionToGoogleFabric' _LOCK_DEVICE = 'setLock' _FAKE_CONTROLLER_PACKAGE = 'FAKE_CONTROLLER_PACKAGE' ############################################################################# @@ -612,6 +614,35 @@ self.assertEqual(_FAKE_RPC_RESPONSE, rpc_response) mock_dispatch.assert_called_once_with(fake_rpc_request) + @mock.patch.object( + translation_layer.TranslationLayer, 'commission_to_google_fabric') + def test_handle_rpc_request_commission_to_google_fabric_on_success(self, mock_commission): + """Verifies handle_rpc_request to commission a device to google fabric on success.""" + mock_commission.return_value = _FAKE_RPC_RESPONSE + fake_rpc_request = {'method': _COMMISSION_TO_GOOGLE_FABRIC} + + rpc_response = self.proc._handle_rpc_request(fake_rpc_request) + + self.assertEqual(_FAKE_RPC_RESPONSE, rpc_response) + mock_commission.assert_called_once_with(fake_rpc_request) + + @mock.patch.object(translation_layer.TranslationLayer, 'commission_to_google_fabric') + def test_handle_rpc_request_returns_a_commissioning_error( + self, mock_commission + ): + """Verifies handle_rpc_request returns a commissioning error.""" + mock_commission.side_effect = errors.InvalidRPCError( + _FAKE_COMMISSION_ERROR_MSG + ) + fake_rpc_request = { + 'id': _FAKE_RPC_ID, + 'method': _COMMISSION_TO_GOOGLE_FABRIC, + } + + rpc_response = self.proc._handle_rpc_request(fake_rpc_request) + + self.assertIn(_FAKE_COMMISSION_ERROR_MSG, rpc_response['error']['message']) + @mock.patch.object(local_agent, 'rpc_request_type', return_value='') def test_handle_rpc_request_invalid_rpc_type(self, mock_req_type): """Verifies handle_rpc_request on failure with invalid RPC type."""
diff --git a/local_agent/tests/unit_tests/test_translation_layer.py b/local_agent/tests/unit_tests/test_translation_layer.py index ddfa844..f292b9c 100644 --- a/local_agent/tests/unit_tests/test_translation_layer.py +++ b/local_agent/tests/unit_tests/test_translation_layer.py
@@ -28,8 +28,10 @@ _FAKE_DEVICE_TYPE = 'fake-device-type' _FAKE_DEVICE_ID = 'fake-device-id' _FAKE_CAPABILITY = 'fake-device-capability' +_FAKE_PAIRING_CODE = 'fake-pairing-code' _SET_ON = 'setOn' _SET_LOCK = 'setLock' +_COMMISSION_TO_GOOGLE_FABRIC = 'commissionToGoogleFabric' ############################################################################## @@ -218,6 +220,21 @@ self.mock_client.send_rpc_response.assert_called_once() self.assertTrue(self.translator.is_rpc_timeout(_FAKE_DEVICE_ID)) + def test_commission_to_google_fabric_on_failure(self): + """Verifies commission_to_google_fabric throws an error when pairing code not found.""" + invalid_rpc_request = rpc_request(_COMMISSION_TO_GOOGLE_FABRIC, {}) + error_msg = 'Invalid rpc command, no pairingCode in params was found.' + with self.assertRaisesRegex(agent_errors.InvalidRPCError, error_msg): + self.translator.commission_to_google_fabric(invalid_rpc_request) + + def test_commission_to_google_fabric_on_success(self): + """Verifies commission_to_google_fabric on success when pairing code is provided.""" + valid_rpc_request = rpc_request( + _COMMISSION_TO_GOOGLE_FABRIC, {'pairingCode': _FAKE_PAIRING_CODE}) + response = self.translator.commission_to_google_fabric(valid_rpc_request) + + # Id is fake and it was made by `rpc_request` wrapper. + self.assertEqual(response, {'id': 0, 'jsonrpc': '2.0', 'result': {}}) if __name__ == '__main__': unittest.main(failfast=True)
diff --git a/local_agent/translation_layer/translation_layer.py b/local_agent/translation_layer/translation_layer.py index eeb02e6..5da05fe 100644 --- a/local_agent/translation_layer/translation_layer.py +++ b/local_agent/translation_layer/translation_layer.py
@@ -280,3 +280,26 @@ 'message': err_mesg} self._ams_client.send_rpc_response(err_resp) self._timeout_rpc.add(rpc_id) + + def commission_to_google_fabric(self, rpc_request: dict[str, dict[str, str]]) -> dict[str, Any]: + """Subroutine for handling COMMISSION_TO_GOOGLE_FABRIC command. + + Args: + rpc_request: JSON-RPC request. + + Raises: + InvalidRPCError: Invalid RPC. + + Returns: + RPC response. + """ + pairing_code = rpc_request['params'].get('pairingCode') + if pairing_code is None: + raise agent_errors.InvalidRPCError( + 'Invalid rpc command, no pairingCode in params was found.') + + request_id = rpc_request['id'] + # TODO(b/282592569): Use this pairing code to commission a matter device on GHA. + logger.info(f'Completed request for {request_id}, pairingCode: {pairing_code}') + + return {'id': request_id, 'jsonrpc': '2.0', 'result': {}}