Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AEA-699 connections test coverage #1488

Merged
merged 1 commit into from
Jul 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions packages/fetchai/connections/ledger/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,19 @@ def __init__(
self._api_configs = api_configs

def api_config(self, ledger_id: str) -> Dict[str, str]:
"""Get api config"""
"""Get api config."""
config = {} # type: Dict[str, str]
if self._api_configs is not None and ledger_id in self._api_configs:
config = self._api_configs[ledger_id]
return config

async def run_async(self, func: Callable[[Any], Task], *args):
async def run_async(
self,
func: Callable[[Any], Task],
api: LedgerApi,
message: Message,
dialogue: Dialogue,
):
"""
Run a function in executor.

Expand All @@ -76,10 +82,12 @@ async def run_async(self, func: Callable[[Any], Task], *args):
:return: the return value of the function.
"""
try:
response = await self.loop.run_in_executor(self.executor, func, *args)
response = await self.loop.run_in_executor(
self.executor, func, api, message, dialogue
)
return response
except Exception as e: # pylint: disable=broad-except
return self.get_error_message(e, *args)
return self.get_error_message(e, api, message, dialogue)

def dispatch(self, envelope: Envelope) -> Task:
"""
Expand All @@ -106,7 +114,7 @@ def get_handler(self, performative: Any) -> Callable[[Any], Task]:
:param performative: the message performative.
:return: the method that will send the request.
"""
handler = getattr(self, performative.value, lambda *args, **kwargs: None)
handler = getattr(self, performative.value, None)
if handler is None:
raise Exception("Performative not recognized.")
return handler
Expand Down
9 changes: 3 additions & 6 deletions packages/fetchai/connections/ledger/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,7 @@ class LedgerConnection(Connection):
connection_id = CONNECTION_ID

def __init__(self, **kwargs):
"""
Initialize a connection to interact with a ledger APIs.

"""
"""Initialize a connection to interact with a ledger APIs."""
super().__init__(**kwargs)

self._ledger_dispatcher: Optional[LedgerApiRequestDispatcher] = None
Expand Down Expand Up @@ -84,7 +81,7 @@ async def disconnect(self) -> None:
"""Tear down the connection."""
self.connection_status.is_connected = False
for task in self.receiving_tasks:
if not task.cancelled():
if not task.cancelled(): # pragma: nocover
task.cancel()
self._ledger_dispatcher = None
self._contract_dispatcher = None
Expand Down Expand Up @@ -129,7 +126,7 @@ async def receive(self, *args, **kwargs) -> Optional["Envelope"]:
:return: the envelope received, or None.
"""
# if there are done tasks, return the result
if len(self.done_tasks) > 0:
if len(self.done_tasks) > 0: # pragma: nocover
done_task = self.done_tasks.pop()
return self._handle_done_task(done_task)

Expand Down
8 changes: 4 additions & 4 deletions packages/fetchai/connections/ledger/connection.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ license: Apache-2.0
aea_version: '>=0.5.0, <0.6.0'
fingerprint:
__init__.py: QmZvYZ5ECcWwqiNGh8qNTg735wu51HqaLxTSifUxkQ4KGj
base.py: QmZecsNSNpct1Zrs7HsJPQJN2buKJCirz6Z7nYH2FQbJFH
connection.py: QmP6kzX6pnsT44tu3bH9PC486mxcTnZ8CR6SngqxtrjHnb
contract_dispatcher.py: QmPtV5PxCP3YCtyA4EeGijqgpNwqPp3xvNZvtvk1nkhRJk
ledger_dispatcher.py: QmUk2J1FokJR6iLQYfyZbSSvR5y5g3ozYq7H6yQcv7YqmJ
base.py: QmegtTTPWhrnpHNiFpSm3TMcH9MTQLaWDvogL9dVvKPwXR
connection.py: QmTPj9CGkDtPMT7bXXDQi3i8zoRvSJvPVr6fyK2giPjmW1
contract_dispatcher.py: QmSkA75HLriYkKXd7wcFqchSkrQsP8RxHK1be5qtXTpgwz
ledger_dispatcher.py: QmaETup4DzFYVkembK2yZL6TfbNDL13fdr6i29CPubG3CN
fingerprint_ignore_patterns: []
protocols:
- fetchai/contract_api:0.1.0
Expand Down
11 changes: 6 additions & 5 deletions packages/fetchai/connections/ledger/contract_dispatcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ def __init__(self, **kwargs) -> None:

@staticmethod
def role_from_first_message(message: Message) -> BaseDialogue.Role:
"""Infer the role of the agent from an incoming/outgoing first message
"""
Infer the role of the agent from an incoming/outgoing first message.

:param message: an incoming/outgoing first message
:return: The role of the agent
Expand Down Expand Up @@ -156,7 +157,7 @@ def get_state(
)
response.counterparty = message.counterparty
dialogue.update(response)
except Exception as e: # pylint: disable=broad-except
except Exception as e: # pylint: disable=broad-except # pragma: nocover
response = self.get_error_message(e, api, message, dialogue)
return response

Expand Down Expand Up @@ -187,7 +188,7 @@ def get_deploy_transaction(
)
response.counterparty = message.counterparty
dialogue.update(response)
except Exception as e: # pylint: disable=broad-except
except Exception as e: # pylint: disable=broad-except # pragma: nocover
response = self.get_error_message(e, api, message, dialogue)
return response

Expand Down Expand Up @@ -218,7 +219,7 @@ def get_raw_transaction(
)
response.counterparty = message.counterparty
dialogue.update(response)
except Exception as e: # pylint: disable=broad-except
except Exception as e: # pylint: disable=broad-except # pragma: nocover
response = self.get_error_message(e, api, message, dialogue)
return response

Expand Down Expand Up @@ -249,6 +250,6 @@ def get_raw_message(
)
response.counterparty = message.counterparty
dialogue.update(response)
except Exception as e: # pylint: disable=broad-except
except Exception as e: # pylint: disable=broad-except # pragma: nocover
response = self.get_error_message(e, api, message, dialogue)
return response
11 changes: 6 additions & 5 deletions packages/fetchai/connections/ledger/ledger_dispatcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ def __init__(self, **kwargs) -> None:

@staticmethod
def role_from_first_message(message: Message) -> BaseDialogue.Role:
"""Infer the role of the agent from an incoming/outgoing first message
"""
Infer the role of the agent from an incoming/outgoing first message.

:param message: an incoming/outgoing first message
:return: The role of the agent
Expand Down Expand Up @@ -211,18 +212,18 @@ def get_transaction_receipt(
time.sleep(self.TIMEOUT)
transaction = api.get_transaction(message.transaction_digest.body)
attempts += 1
if not is_settled:
if not is_settled: # pragma: nocover
response = self.get_error_message(
ValueError("Transaction not settled within timeout"),
api,
message,
dialogue,
)
elif transaction_receipt is None:
elif transaction_receipt is None: # pragma: nocover
response = self.get_error_message(
ValueError("No transaction_receipt returned"), api, message, dialogue
)
elif transaction is None:
elif transaction is None: # pragma: nocover
response = self.get_error_message(
ValueError("No tx returned"), api, message, dialogue
)
Expand Down Expand Up @@ -255,7 +256,7 @@ def send_signed_transaction(
transaction_digest = api.send_signed_transaction(
message.signed_transaction.body
)
if transaction_digest is None:
if transaction_digest is None: # pragma: nocover
response = self.get_error_message(
ValueError("No transaction_digest returned"), api, message, dialogue
)
Expand Down
2 changes: 1 addition & 1 deletion packages/hashes.csv
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ fetchai/agents/weather_station,QmfD44aXS4TmcZFMASb8vDxYK6eNFsQMkSTBmTdcqzGPhc
fetchai/connections/gym,QmZNEJvgi9n5poswQrHav3fvSv5vA1nbxxkTzWENCoCdrc
fetchai/connections/http_client,QmXQrA6gA4hMEMkMQsEp1MQwDEqRw5BnnqR4gCrP5xqVD2
fetchai/connections/http_server,QmPMSyX1iaWM7mWqFtW8LnSyR9r88RzYbGtyYmopT6tshC
fetchai/connections/ledger,QmezMgaJkk9wbQ4nzURERnNJdrzkQyvV5PiieH6uGbVzc3
fetchai/connections/ledger,QmWDietq5YFkZAYpyyrmq7AFbTVN4skDWKsG4CXrc5uZ37
fetchai/connections/local,QmVcTEJxGbWbtXi2fLN5eJA6XuEAneaNd83UJPugrtb9xU
fetchai/connections/oef,QmfHVVcwUb8SqGYHs51iH5ymK5xJvxCCtShEmc9cw4FNVZ
fetchai/connections/p2p_client,QmbwCDuAB1eq6JikqeAAqpqjVhxevGNeWCLqRD67Uvqiaz
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,33 @@
# limitations under the License.
#
# ------------------------------------------------------------------------------

"""This module contains the tests of the ledger API connection for the contract APIs."""
import asyncio
from pathlib import Path
from typing import cast

import pytest

from aea.connections.base import Connection
from aea.connections.base import Connection, ConnectionStatus
from aea.crypto.ethereum import EthereumCrypto
from aea.crypto.fetchai import FetchAICrypto
from aea.crypto.wallet import CryptoStore
from aea.helpers.transaction.base import RawMessage, RawTransaction, State
from aea.identity.base import Identity
from aea.mail.base import Envelope

from packages.fetchai.connections.ledger.contract_dispatcher import ContractApiDialogues
from packages.fetchai.connections.ledger.contract_dispatcher import (
ContractApiDialogues,
ContractApiRequestDispatcher,
)
from packages.fetchai.protocols.contract_api import ContractApiMessage

from tests.conftest import ETHEREUM_ADDRESS_ONE, ROOT_DIR


@pytest.fixture()
async def ledger_apis_connection(request):
"""Create connection."""
identity = Identity("name", FetchAICrypto().address)
crypto_store = CryptoStore()
directory = Path(ROOT_DIR, "packages", "fetchai", "connections", "ledger")
Expand Down Expand Up @@ -243,3 +246,43 @@ async def test_erc1155_get_state(erc1155_contract, ledger_apis_connection):
result = response_message.state.body.get("balance", None)
expected_result = {token_id: 0}
assert result is not None and result == expected_result


@pytest.mark.asyncio
async def test_run_async():
"""Test run async error handled."""
# for pydocstyle
def _raise():
raise Exception("Expected")

contract_api_dialogues = ContractApiDialogues()
message = ContractApiMessage(
performative=ContractApiMessage.Performative.GET_RAW_TRANSACTION,
dialogue_reference=contract_api_dialogues.new_self_initiated_dialogue_reference(),
ledger_id=EthereumCrypto.identifier,
contract_id="fetchai/erc1155:0.6.0",
contract_address="test addr",
callable="get_create_batch_transaction",
kwargs=ContractApiMessage.Kwargs(
{
"deployer_address": "test_addr",
"token_ids": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
}
),
)
message.counterparty = "test"
dialogue = contract_api_dialogues.update(message)
api = None
msg = await ContractApiRequestDispatcher(ConnectionStatus()).run_async(
_raise, api, message, dialogue
)
assert msg.performative == ContractApiMessage.Performative.ERROR


@pytest.mark.asyncio
async def test_get_handler():
"""Test failed to get handler."""
with pytest.raises(Exception, match="Performative not recognized."):
ContractApiRequestDispatcher(ConnectionStatus()).get_handler(
ContractApiMessage.Performative.ERROR
)
Loading