Skip to content

Commit

Permalink
Merge pull request #328 from Ravleen-Solulab/Test-decision
Browse files Browse the repository at this point in the history
Test/decision_maker
  • Loading branch information
Adamantios authored and OjusWiZard committed Nov 15, 2024
2 parents f077310 + ea766ab commit 92dcb78
Show file tree
Hide file tree
Showing 26 changed files with 3,181 additions and 601 deletions.
12 changes: 6 additions & 6 deletions packages/packages.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@
"contract/valory/staking_token/0.1.0": "bafybeiep4r6qyilbfgzdvx6t7zvpgaioxqktmxm7puwtnbpb2ftlib43gy",
"contract/valory/relayer/0.1.0": "bafybeicawmds6czx7db2lcktvexwrp245jpekgulndtos5s5zdid3ilvq4",
"skill/valory/market_manager_abci/0.1.0": "bafybeicia7itulcrxlwbmhfzxppgo5i33tb2nmcycwizftw7gps4dareka",
"skill/valory/decision_maker_abci/0.1.0": "bafybeiaizbnlz46lba6tcwmajpo2z37cpxuobeqmlgdqbdxnt65jr6rely",
"skill/valory/trader_abci/0.1.0": "bafybeido4dpfcvpyrobs2veoliuwaz2ltuzvo2gqfbsqxgd5tdr7zllyru",
"skill/valory/tx_settlement_multiplexer_abci/0.1.0": "bafybeieszb6lxyy5gt4m4f75fjicuzf3ewsxgxcc5dh4l2tjjau7wcrgxe",
"skill/valory/decision_maker_abci/0.1.0": "bafybeia5qzqac2g444myog3tlwagthcknmanqunnytbjfsuk2msep2rnna",
"skill/valory/trader_abci/0.1.0": "bafybeigz6mm7xzhe334iuyy6nw4tdymxfjp6fp37firbzznxg7mowtvcoe",
"skill/valory/tx_settlement_multiplexer_abci/0.1.0": "bafybeigt42cdisy2z53u5pqq3qmjk5bb32cm5oegftptv56m7yq5dbdoyi",
"skill/valory/staking_abci/0.1.0": "bafybeictd5pxhscuhqntvctb7l5lfjausxt2m22rg5mkaiuj4cwwcxpvne",
"skill/valory/check_stop_trading_abci/0.1.0": "bafybeifmi64g4ki6zwbcncb35ovhd4sllw4xrszrkturpeqdhgf5bkiini",
"agent/valory/trader/0.1.0": "bafybeifaw3dk5uklcgj5iftcdhj4p2ymkidoli3uxibq4olddd3eboey7e",
"service/valory/trader/0.1.0": "bafybeiaqqlwqjiofrezpnk4hq6doiccbquzgmd6pcgtfx7akmfhhvyoipi",
"service/valory/trader_pearl/0.1.0": "bafybeidzv544ive2oozjk2szmengrcszea7ai54qts7ehdjdkwevwtwfba"
"agent/valory/trader/0.1.0": "bafybeidcn54f67yhqaa7aycsmurm4tvmx2dj2e2zir6keft3ubxchcu6hu",
"service/valory/trader/0.1.0": "bafybeig6jsofnzrst72r3qannxrpbrbfd7c4nvdcvacsplcx7gnyroqeuu",
"service/valory/trader_pearl/0.1.0": "bafybeica7obylkk3hu7xfkq73da5mtdw7q732v6kzwrlh4owoc3czjtcua"
},
"third_party": {
"protocol/open_aea/signing/1.0.0": "bafybeihv62fim3wl2bayavfcg3u5e5cxu3b7brtu4cn5xoxd6lqwachasi",
Expand Down
6 changes: 3 additions & 3 deletions packages/valory/agents/trader/aea-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ skills:
- valory/reset_pause_abci:0.1.0:bafybeigrdlxed3xlsnxtjhnsbl3cojruihxcqx4jxhgivkd5i2fkjncgba
- valory/termination_abci:0.1.0:bafybeib5l7jhew5ic6iq24dd23nidcoimzqkrk556gqywhoziatj33zvwm
- valory/transaction_settlement_abci:0.1.0:bafybeic7q7recyka272udwcupblwbkc3jkodgp74fvcdxb7urametg5dae
- valory/tx_settlement_multiplexer_abci:0.1.0:bafybeieszb6lxyy5gt4m4f75fjicuzf3ewsxgxcc5dh4l2tjjau7wcrgxe
- valory/tx_settlement_multiplexer_abci:0.1.0:bafybeigt42cdisy2z53u5pqq3qmjk5bb32cm5oegftptv56m7yq5dbdoyi
- valory/market_manager_abci:0.1.0:bafybeicia7itulcrxlwbmhfzxppgo5i33tb2nmcycwizftw7gps4dareka
- valory/decision_maker_abci:0.1.0:bafybeiaizbnlz46lba6tcwmajpo2z37cpxuobeqmlgdqbdxnt65jr6rely
- valory/trader_abci:0.1.0:bafybeido4dpfcvpyrobs2veoliuwaz2ltuzvo2gqfbsqxgd5tdr7zllyru
- valory/decision_maker_abci:0.1.0:bafybeia5qzqac2g444myog3tlwagthcknmanqunnytbjfsuk2msep2rnna
- valory/trader_abci:0.1.0:bafybeigz6mm7xzhe334iuyy6nw4tdymxfjp6fp37firbzznxg7mowtvcoe
- valory/staking_abci:0.1.0:bafybeictd5pxhscuhqntvctb7l5lfjausxt2m22rg5mkaiuj4cwwcxpvne
- valory/check_stop_trading_abci:0.1.0:bafybeifmi64g4ki6zwbcncb35ovhd4sllw4xrszrkturpeqdhgf5bkiini
- valory/mech_interact_abci:0.1.0:bafybeid6m3i5ofq7vuogqapdnoshhq7mswmudhvfcr2craw25fdwtoe3lm
Expand Down
2 changes: 1 addition & 1 deletion packages/valory/services/trader/service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ license: Apache-2.0
fingerprint:
README.md: bafybeigtuothskwyvrhfosps2bu6suauycolj67dpuxqvnicdrdu7yhtvq
fingerprint_ignore_patterns: []
agent: valory/trader:0.1.0:bafybeifaw3dk5uklcgj5iftcdhj4p2ymkidoli3uxibq4olddd3eboey7e
agent: valory/trader:0.1.0:bafybeidcn54f67yhqaa7aycsmurm4tvmx2dj2e2zir6keft3ubxchcu6hu
number_of_agents: 4
deployment:
agent:
Expand Down
4 changes: 2 additions & 2 deletions packages/valory/services/trader_pearl/service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ license: Apache-2.0
fingerprint:
README.md: bafybeibg7bdqpioh4lmvknw3ygnllfku32oca4eq5pqtvdrdsgw6buko7e
fingerprint_ignore_patterns: []
agent: valory/trader:0.1.0:bafybeifaw3dk5uklcgj5iftcdhj4p2ymkidoli3uxibq4olddd3eboey7e
agent: valory/trader:0.1.0:bafybeidcn54f67yhqaa7aycsmurm4tvmx2dj2e2zir6keft3ubxchcu6hu
number_of_agents: 1
deployment:
agent:
Expand Down Expand Up @@ -126,7 +126,7 @@ type: connection
config:
ledger_apis:
ethereum:
address: http://host.docker.internal:8545
address: ${GNOSIS_LEDGER_RPC:str:http://host.docker.internal:8545}
chain_id: 100
default_gas_price_strategy: eip1559
poa_chain: false
Expand Down
16 changes: 16 additions & 0 deletions packages/valory/skills/decision_maker_abci/skill.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,24 @@ fingerprint:
tests/behaviours/dummy_strategy/dummy_strategy.py: bafybeig5e3xfr7gxsakfj4stbxqcwdiljl7klvgahkuwe3obzxgkg3qt2e
tests/behaviours/test_base.py: bafybeif6pglmr7pvojylatfzaxtlk65igx6a2omyrbxfihnnft6o7p75p4
tests/conftest.py: bafybeidy5hw56kw5mxudnfbhvogofn6k4rqb4ux2bd45baedrrhmgyrude
tests/states/test_base.py: bafybeigiuctxda3npkbvx7nsq4jvqpckvbzgqlj76hdpk2ntc52ppc4vnm
tests/states/test_bet_placement.py: bafybeibvc37n2cluep4tasvgmvwxwne2deais6ptirducpogk67v4gj4ga
tests/states/test_blacklising.py: bafybeihm2ex6l7fhorgi3mjj2epztu2r7bqbg56unpgpzfzymghshchqzy
tests/states/test_check_benchmarking.py: bafybeifwpi5f4fhreqptfxdsnyv3nptkqytkwbukfuqkrjo4eww7cv3sxy
tests/states/test_claim_subscription.py: bafybeiclkxjhceb3ehgmg6klt4uywew5drk5b3w6no7mwxetpubxqrejfy
tests/states/test_decision_receive.py: bafybeifj7rwqyzfcvnqqhbo25pl2jppgjqnqldadwku5wl2tpskfj2zwxq
tests/states/test_decision_request.py: bafybeigqbakm2olkwvcngertjplhnmu6on6tp6hxn7lxygi2gf5a5eurbe
tests/states/test_final_states.py: bafybeiftfd3ovaqpfe7t5ry7maiziavk74wl66d6zo6ikhgodznormd2nm
tests/states/test_handle_failed_tx.py: bafybeibuepj6fko7ba3bef6nybzetilni2iwgkxd5xeazqskadbad3l2zq
tests/states/test_order_subscription.py: bafybeiag37uk5mitjm4yadcpr67icfmmzeucdlgvqoct4y4jeyhnebyyoi
tests/states/test_randomness.py: bafybeib3eqjv6mhlprzda7d4viddn5alrfqteq6juyg3ccejseoywcsbey
tests/states/test_redeem.py: bafybeiezdnfrxukb2xpwffrr357g2anmdkwy7wo3nphvlggipq5xrdzr7a
tests/states/test_sampling.py: bafybeibyglipxdl6f25qfxf36v2n3kckrpmwyuqcenfeqzhjujpwon6o2u
tests/states/test_tool_selection.py: bafybeib7js3dj7647t33o5ybfqftwytxktwrvhbri5yuyymg6znj6y7xxa
tests/test_dialogues.py: bafybeibulo64tgfrq4e5qbcqnmifrlehkqciwuavublints353zaj2mlpa
tests/test_handlers.py: bafybeihpkgtjjm3uegpup6zkznpoaxqpu6kmp3ujiggrzbe73p5fzlq7im
tests/test_payloads.py: bafybeifc2os3orozmsxbrcfp4c4vrweojo6g4ebxinr5ilescraw6qm6sa
tests/test_rounds.py: bafybeigifftusd4ew42tyvyrr55o2uehhcik2gdq3atkpjwwlqdeskedty
utils/__init__.py: bafybeiazrfg3kwfdl5q45azwz6b6mobqxngxpf4hazmrnkhinpk4qhbbf4
utils/nevermined.py: bafybeigallaqxhqopznhjhefr6bukh4ojkz5vdtqyzod5dksshrf24fjgi
utils/scaling.py: bafybeialr3z4zogp4k3l2bzcjfi4igvxzjexmlpgze2bai2ufc3plaow4y
Expand Down
252 changes: 252 additions & 0 deletions packages/valory/skills/decision_maker_abci/tests/states/test_base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
# -*- coding: utf-8 -*-
# ------------------------------------------------------------------------------
#
# Copyright 2023-2024 Valory AG
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# ------------------------------------------------------------------------------

"""This package contains the tests for Decision Maker"""

import json
from unittest.mock import MagicMock, patch

import pytest

from packages.valory.skills.decision_maker_abci.policy import (
AccuracyInfo,
EGreedyPolicy,
)
from packages.valory.skills.decision_maker_abci.states.base import (
Event,
SynchronizedData,
TxPreparationRound,
)


class MechMetadata:
"""The class for test of Mech Data"""

def __init__(self, request_id: str, data: str) -> None:
"""Initialize MechMetadata with request ID and data."""
self.request_id = request_id
self.data = data


@pytest.fixture
def mocked_db() -> MagicMock:
"""Fixture to mock the database."""
return MagicMock()


@pytest.fixture
def sync_data(mocked_db: MagicMock) -> SynchronizedData:
"""Fixture for SynchronizedData."""
return SynchronizedData(db=mocked_db)


def test_sampled_bet_index(sync_data: SynchronizedData, mocked_db: MagicMock) -> None:
"""Test the sampled_bet_index property."""
mocked_db.get_strict.return_value = "5"
assert sync_data.sampled_bet_index == 5
mocked_db.get_strict.assert_called_once_with("sampled_bet_index")


def test_is_mech_price_set(sync_data: SynchronizedData, mocked_db: MagicMock) -> None:
"""Test the is_mech_price_set property."""
mocked_db.get.return_value = True
assert sync_data.is_mech_price_set is True
mocked_db.get.assert_called_once_with("mech_price", False)


def test_available_mech_tools(
sync_data: SynchronizedData, mocked_db: MagicMock
) -> None:
"""Test the available_mech_tools property."""
mocked_db.get_strict.return_value = '["tool1", "tool2"]'
assert sync_data.available_mech_tools == ["tool1", "tool2"]
mocked_db.get_strict.assert_called_once_with("available_mech_tools")


def test_is_policy_set(sync_data: SynchronizedData, mocked_db: MagicMock) -> None:
"""Test the is_policy_set property."""
mocked_db.get.return_value = True
assert sync_data.is_policy_set is True
mocked_db.get.assert_called_once_with("policy", False)


def test_has_tool_selection_run(
sync_data: SynchronizedData, mocked_db: MagicMock
) -> None:
"""Test the has_tool_selection_run property."""
mocked_db.get.return_value = "tool1"
assert sync_data.has_tool_selection_run is True
mocked_db.get.assert_called_once_with("mech_tool", None)


def test_mech_tool(sync_data: SynchronizedData, mocked_db: MagicMock) -> None:
"""Test the mech_tool property."""
mocked_db.get_strict.return_value = "tool1"
assert sync_data.mech_tool == "tool1"
mocked_db.get_strict.assert_called_once_with("mech_tool")


def test_utilized_tools(sync_data: SynchronizedData, mocked_db: MagicMock) -> None:
"""Test the utilized_tools property."""
mocked_db.get_strict.return_value = '{"tx1": "tool1"}'
assert sync_data.utilized_tools == {"tx1": "tool1"}
mocked_db.get_strict.assert_called_once_with("utilized_tools")


def test_redeemed_condition_ids(
sync_data: SynchronizedData, mocked_db: MagicMock
) -> None:
"""Test the redeemed_condition_ids property."""
mocked_db.get.return_value = '["cond1", "cond2"]'
assert sync_data.redeemed_condition_ids == {"cond1", "cond2"}
mocked_db.get.assert_called_once_with("redeemed_condition_ids", None)


def test_payout_so_far(sync_data: SynchronizedData, mocked_db: MagicMock) -> None:
"""Test the payout_so_far property."""
mocked_db.get.return_value = "100"
assert sync_data.payout_so_far == 100
mocked_db.get.assert_called_once_with("payout_so_far", None)


def test_vote(sync_data: SynchronizedData, mocked_db: MagicMock) -> None:
"""Test the vote property."""
mocked_db.get_strict.return_value = "1"
assert sync_data.vote == 1
mocked_db.get_strict.assert_called_once_with("vote")


def test_confidence(sync_data: SynchronizedData, mocked_db: MagicMock) -> None:
"""Test the confidence property."""
mocked_db.get_strict.return_value = "0.9"
assert sync_data.confidence == 0.9
mocked_db.get_strict.assert_called_once_with("confidence")


def test_bet_amount(sync_data: SynchronizedData, mocked_db: MagicMock) -> None:
"""Test the bet_amount property."""
mocked_db.get_strict.return_value = "50"
assert sync_data.bet_amount == 50
mocked_db.get_strict.assert_called_once_with("bet_amount")


def test_is_profitable(sync_data: SynchronizedData, mocked_db: MagicMock) -> None:
"""Test the is_profitable property."""
mocked_db.get_strict.return_value = True
assert sync_data.is_profitable is True
mocked_db.get_strict.assert_called_once_with("is_profitable")


def test_tx_submitter(sync_data: SynchronizedData, mocked_db: MagicMock) -> None:
"""Test the tx_submitter property."""
mocked_db.get_strict.return_value = "submitter1"
assert sync_data.tx_submitter == "submitter1"
mocked_db.get_strict.assert_called_once_with("tx_submitter")


@patch("packages.valory.skills.decision_maker_abci.policy.EGreedyPolicy.deserialize")
def test_policy_property(
mock_deserialize: MagicMock, sync_data: SynchronizedData, mocked_db: MagicMock
) -> None:
"""Test for policy property"""
mock_policy_serialized = "serialized_policy_string"
mocked_db.get_strict.return_value = mock_policy_serialized

expected_policy = EGreedyPolicy(eps=0.1)
mock_deserialize.return_value = expected_policy

result = sync_data.policy

mocked_db.get_strict.assert_called_once_with("policy")
mock_deserialize.assert_called_once_with(mock_policy_serialized)
assert result == expected_policy


def test_mech_requests(sync_data: SynchronizedData, mocked_db: MagicMock) -> None:
"""Test the mech_requests property."""
mocked_db.get.return_value = '[{"request_id": "1", "data": "request_data"}]'
requests = json.loads(mocked_db.get.return_value)

mech_requests = [
MechMetadata(request_id=item["request_id"], data=item["data"])
for item in requests
]

assert len(mech_requests) == 1
assert isinstance(mech_requests[0], MechMetadata)
assert mech_requests[0].request_id == "1"


def test_weighted_accuracy(sync_data: SynchronizedData, mocked_db: MagicMock) -> None:
"""Test the weighted_accuracy property."""
selected_mech_tool = "tool1"
policy_db_name = "policy"
policy_mock = EGreedyPolicy(
eps=0.1, accuracy_store={selected_mech_tool: AccuracyInfo(requests=1)}
).serialize()
mocked_db.get_strict = lambda name: (
policy_mock if name == policy_db_name else selected_mech_tool
)
policy = EGreedyPolicy.deserialize(policy_mock)
assert selected_mech_tool in policy.weighted_accuracy
assert sync_data.weighted_accuracy == policy.weighted_accuracy[selected_mech_tool]


def test_mech_responses(sync_data: SynchronizedData, mocked_db: MagicMock) -> None:
"""Test the mech_responses property."""

# Mock the response with empty dictionaries to avoid field mismatches
mocked_db.get.return_value = "[{}, {}]"

# Access the mech_responses property
responses = sync_data.mech_responses

# Validate the responses length
assert len(responses) == 2

# Test when db.get() returns None
mocked_db.get.return_value = None
responses = sync_data.mech_responses
assert responses == []

# Test when db.get() returns an empty list
mocked_db.get.return_value = "[]"
responses = sync_data.mech_responses
assert responses == []


def test_end_block(mocked_db: MagicMock) -> None:
"""Test the end_block logic in TxPreparationRound."""
mocked_sync_data = MagicMock(spec=SynchronizedData)
mock_context = MagicMock()
round_instance = TxPreparationRound(
synchronized_data=mocked_sync_data, context=mock_context
)

with patch.object(
TxPreparationRound, "end_block", return_value=(mocked_sync_data, Event.DONE)
):
result = round_instance.end_block()
assert result == (mocked_sync_data, Event.DONE)

with patch.object(
TxPreparationRound, "end_block", return_value=(mocked_sync_data, Event.NONE)
):
result = round_instance.end_block()
assert result == (mocked_sync_data, Event.NONE)
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
# ------------------------------------------------------------------------------
#
# Copyright 2023-2024 Valory AG
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# ------------------------------------------------------------------------------

"""This package contains the tests for Decision Maker"""

from typing import Any, Dict

import pytest

from packages.valory.skills.decision_maker_abci.states.base import Event
from packages.valory.skills.decision_maker_abci.states.bet_placement import (
BetPlacementRound,
)


@pytest.fixture
def bet_placement_round() -> BetPlacementRound:
"""Fixture to set up a BetPlacementRound instance for testing."""
synchronized_data: Dict[str, Any] = {} # Added type annotation
context: Dict[str, Any] = {} # Added type annotation
return BetPlacementRound(synchronized_data, context)


def test_initial_event(bet_placement_round: BetPlacementRound) -> None:
"""Test that the initial event is set correctly."""
assert bet_placement_round.none_event == Event.INSUFFICIENT_BALANCE
Loading

0 comments on commit 92dcb78

Please sign in to comment.