diff --git a/packages/hashes.csv b/packages/hashes.csv index 4eb98f3c0f..37322682f7 100644 --- a/packages/hashes.csv +++ b/packages/hashes.csv @@ -18,7 +18,7 @@ valory/protocols/contract_api,QmcM7FdjuyyRM3iYudLNnFdqJQUasi1Ba2Skf3xyuETRUp valory/protocols/http,QmRKu1vs6w2iug8sgFiporMuo9QR1K2Gvwve7p6eLhRkmg valory/protocols/ledger_api,QmcjQd5XckbTUUwc5nYCJCU6FvUKfhRNCG4M4EMGXt1jVG valory/skills/abstract_abci,QmS2Ppvq8jCLWy8cyykUZ1EZ71BsPWeZBE7hBo18FLfST9 -valory/skills/abstract_round_abci,QmVZdXRgLQNC8Uv2Z52M4p4ofC7pNF7de9ZDTTPu5mBNCQ +valory/skills/abstract_round_abci,QmT91tjxXp7Q9grfgs23gbQT8am1kmwpwmh2KKQpToc9TW valory/skills/apy_estimation_abci,QmWFUCFFPLV5NDbPWsVsMf5CNYR6VzVeHzeXPcPpEXm1u8 valory/skills/counter,QmTKi3jYQDZNXR9q65ZYcTb4ezkYiBBchC3cDLuvk2tg3p valory/skills/counter_client,QmbLse9HQhHoWkxmwPkutUpecKRxQbwoJKoAoGHmdAkUZ2 diff --git a/packages/valory/skills/abstract_round_abci/behaviour_utils.py b/packages/valory/skills/abstract_round_abci/behaviour_utils.py index f69e4313cd..28b4926295 100644 --- a/packages/valory/skills/abstract_round_abci/behaviour_utils.py +++ b/packages/valory/skills/abstract_round_abci/behaviour_utils.py @@ -440,7 +440,8 @@ def async_act_wrapper(self) -> Generator: else: yield from self.async_act() except StopIteration: - if self.context.state.period.syncing_up: + if self.context.state.period.syncing_up: # pragma: nocover + # needs to be tested has_synced_up = yield from self._has_synced_up() if has_synced_up: self.context.logger.info("local height == remote; Ending sync...") @@ -676,7 +677,7 @@ def _get_status(self) -> Generator[None, None, HttpMessage]: def _has_synced_up( self, - ) -> Generator[None, None, bool]: + ) -> Generator[None, None, bool]: # pragma: nocover """Check if agent has completed sync.""" for _ in range(_DEFAULT_TX_MAX_ATTEMPTS): diff --git a/packages/valory/skills/abstract_round_abci/behaviours.py b/packages/valory/skills/abstract_round_abci/behaviours.py index 8bfb5eb3fd..53c1d72a98 100644 --- a/packages/valory/skills/abstract_round_abci/behaviours.py +++ b/packages/valory/skills/abstract_round_abci/behaviours.py @@ -123,7 +123,7 @@ def _check_matching_round_consistency( raise ABCIAppInternalError( f"round {round_cls.round_id} is a final round it shouldn't have any matching behaviours." ) - continue + continue # pragma: nocover if len(states) == 0: raise ABCIAppInternalError( f"round {round_cls.round_id} is not a matching round of any state behaviour" diff --git a/packages/valory/skills/abstract_round_abci/skill.yaml b/packages/valory/skills/abstract_round_abci/skill.yaml index b996605dd1..b257d7399c 100644 --- a/packages/valory/skills/abstract_round_abci/skill.yaml +++ b/packages/valory/skills/abstract_round_abci/skill.yaml @@ -10,8 +10,8 @@ fingerprint: __init__.py: QmPuJK7gMKruSTcaYk9otrFncfD9h6vBZVoAtkwhTBgcxa abci_app_chain.py: QmY4CAjgeM3GdPRT5NCTfeDdEfyUkCJc8FZNKsyW4vQ6oB base.py: QmPLVrvaudsmxwY9WmjLMPp1kzf1sdhDSPeLbHnMoRQPv5 - behaviour_utils.py: QmbbUB2u8TVKU7cUreg65z9p6dniju9ufWN9AQQGEA3u11 - behaviours.py: QmVjM2uZpgfGcPhLbTXYyD3HmenSgM2CZufziCNasM5Q6e + behaviour_utils.py: QmXBfYhLwdhy5LT4NrBKXWoGQDXAGbWn9Z2osxeQm2ESHr + behaviours.py: QmNZiFSYdw7jes51c8Go4jykSSjoQWHtYt1DcLShrfHHCg common.py: QmdoSkkkCRqoHX9T2rnPLpii5KVvEmibktKDik3pe2mNB7 dialogues.py: QmemiTJxfwp2PFxFQyAUHTx8FsthhWL3mYgonBhC3cTjWH handlers.py: QmX82xDvh14N4LFLGMpA2FyKjh1KwNCSQqY1LSjZzgoWC9 diff --git a/tests/test_skills/test_abstract_round_abci/test_base_rounds.py b/tests/test_skills/test_abstract_round_abci/test_base_rounds.py index 9ebacdff7b..b7c203d23d 100644 --- a/tests/test_skills/test_abstract_round_abci/test_base_rounds.py +++ b/tests/test_skills/test_abstract_round_abci/test_base_rounds.py @@ -147,6 +147,8 @@ class DummyCollectSameUntilThresholdRound(CollectSameUntilThresholdRound, DummyR class DummyOnlyKeeperSendsRound(OnlyKeeperSendsRound, DummyRound): """Dummy Class for OnlyKeeperSendsRound""" + fail_event = "FAIL_EVENT" + class DummyVotingRound(VotingRound, DummyRound): """Dummy Class for VotingRound""" @@ -633,7 +635,7 @@ def test_run_with_none( assert test_round.most_voted_payload is None -class TestOnlyKeeperSendsRound(_BaseRoundTestClass): +class TestOnlyKeeperSendsRound(_BaseRoundTestClass, BaseOnlyKeeperSendsRoundTest): """Test OnlyKeeperSendsRound.""" def test_run( @@ -687,6 +689,27 @@ def test_run( ): test_round.check_payload(DummyTxPayload(sender="agent_1", value="sender")) + def test_keeper_payload_is_none( + self, + ) -> None: + """Test keeper payload valur set to none.""" + + keeper = "agent_0" + self._complete_run( + self._test_round( + test_round=DummyOnlyKeeperSendsRound( + state=self.period_state.update( + most_voted_keeper_address=keeper, + ), + consensus_params=self.consensus_params, + ), + keeper_payloads=DummyTxPayload(keeper, None), + state_update_fn=lambda _period_state, _test_round: _period_state, + state_attr_checks=[], + exit_event="FAIL_EVENT", + ) + ) + class TestVotingRound(_BaseRoundTestClass): """Test VotingRound.""" diff --git a/tests/test_skills/test_abstract_round_abci/test_behaviours.py b/tests/test_skills/test_abstract_round_abci/test_behaviours.py index cd37870851..831adea00d 100644 --- a/tests/test_skills/test_abstract_round_abci/test_behaviours.py +++ b/tests/test_skills/test_abstract_round_abci/test_behaviours.py @@ -166,6 +166,37 @@ def test_act_current_state_name_is_none(self) -> None: with mock.patch.object(self.behaviour, "_process_current_round"): self.behaviour.act() + def test_check_matching_round_consistency(self) -> None: + """Test classmethod '_get_state_id_to_state_mapping', negative case.""" + rounds = [MagicMock(round_id=f"round_{i}") for i in range(3)] + states = [ + MagicMock(matching_round=round, state_id=f"state_{i}") + for i, round in enumerate(rounds) + ] + + with mock.patch( + "packages.valory.skills.abstract_round_abci.behaviours._MetaRoundBehaviour._check_all_required_classattributes_are_set" + ), mock.patch( + "packages.valory.skills.abstract_round_abci.behaviours._MetaRoundBehaviour._check_state_id_uniqueness" + ), mock.patch( + "packages.valory.skills.abstract_round_abci.behaviours._MetaRoundBehaviour._check_initial_state_in_set_of_states" + ), pytest.raises( + ABCIAppInternalError, + match="internal error: round round_0 is a final round it shouldn't have any matching behaviours", + ): + + class MyRoundBehaviour(AbstractRoundBehaviour): + abci_app_cls = MagicMock( + get_all_round_classes=lambda: rounds, + final_states={ + rounds[0], + }, + ) + behaviour_states = states # type: ignore + initial_state_cls = MagicMock() + + MyRoundBehaviour(name=MagicMock(), skill_context=MagicMock()) + def test_get_state_id_to_state_mapping_negative(self) -> None: """Test classmethod '_get_state_id_to_state_mapping', negative case.""" state_id = "state_id" diff --git a/tests/test_skills/test_abstract_round_abci/test_behaviours_utils.py b/tests/test_skills/test_abstract_round_abci/test_behaviours_utils.py index de8560b838..a30af6afc0 100644 --- a/tests/test_skills/test_abstract_round_abci/test_behaviours_utils.py +++ b/tests/test_skills/test_abstract_round_abci/test_behaviours_utils.py @@ -484,13 +484,8 @@ def test_async_act_wrapper_agent_sync_mode(self) -> None: self.behaviour.context.state.period = Period(MagicMock()) # type: ignore self.behaviour.context.state.period.start_sync() self.behaviour.context.logger.info = lambda msg: logging.info(msg) # type: ignore - - with mock.patch.object(logging, "info") as log_mock: - gen = self.behaviour.async_act_wrapper() - gen.send(None) - log_mock.assert_called() - - assert self.behaviour.context.state.period.syncing_up is True + gen = self.behaviour.async_act_wrapper() + gen.send(None) @mock.patch.object(BaseState, "_get_status", _get_status_patch) def test_async_act_wrapper_agent_sync_mode_with_round_none(self) -> None: