diff --git a/ct-app/core/components/parameters.py b/ct-app/core/components/parameters.py index f7b31b94..82963f8c 100644 --- a/ct-app/core/components/parameters.py +++ b/ct-app/core/components/parameters.py @@ -55,28 +55,19 @@ def from_env(self, *prefixes: list[str]): else: subparams = type(self)() - for key, value in EnvironmentUtils.envvarWithPrefix(prefix).items(): - k = key.replace(prefix, "").lower() + self._parse_env_vars(prefix, subparams) - # convert snake case to camel case - k = k.replace("_", " ").title().replace(" ", "") - k = k[0].lower() + k[1:] - - try: - value = float(value) - except ValueError: - pass - - try: - integer = int(value) - if integer == value: - value = integer - except ValueError: - pass + setattr(self, subparams_name, subparams) - setattr(subparams, k, value) + def _parse_env_vars(self, prefix, subparams): + for key, value in EnvironmentUtils.envvarWithPrefix(prefix).items(): + k = self._format_key(key, prefix) + value = self._convert(value) + setattr(subparams, k, value) - setattr(self, subparams_name, subparams) + def _format_key(self, key, prefix): + k = key.replace(prefix, "").lower() + return k.replace("_", " ").title().replace(" ", "").lower() def _convert(self, value: str): try: diff --git a/ct-app/core/components/utils.py b/ct-app/core/components/utils.py index 6eb7bdab..444af9d2 100644 --- a/ct-app/core/components/utils.py +++ b/ct-app/core/components/utils.py @@ -1,5 +1,5 @@ import csv -from os import environ, path +from os import path import random import time from datetime import datetime, timedelta @@ -19,21 +19,6 @@ class Utils(Base): - @classmethod - def envvar(cls, var_name: str, default: Any = None, type: type = str): - if var_name in environ: - return type(environ[var_name]) - else: - return default - - @classmethod - def envvarWithPrefix(cls, prefix: str, type=str) -> dict[str, Any]: - var_dict = { - key: type(v) for key, v in environ.items() if key.startswith(prefix) - } - - return dict(sorted(var_dict.items())) - @classmethod def nodesAddresses( cls, address_prefix: str, keyenv: str diff --git a/ct-app/core/node.py b/ct-app/core/node.py index 61fa0f0d..9c72534e 100644 --- a/ct-app/core/node.py +++ b/ct-app/core/node.py @@ -337,6 +337,7 @@ async def retrieve_peers(self): params=["peer_id", "peer_address", "reported_version"], quality=0.5 ) + print("Results: ", results) peers = { Peer(item["peer_id"], item["peer_address"], item["reported_version"]) for item in results diff --git a/ct-app/test/components/test_decorators.py b/ct-app/test/components/test_decorators.py index d2aa12ab..d704c429 100644 --- a/ct-app/test/components/test_decorators.py +++ b/ct-app/test/components/test_decorators.py @@ -71,35 +71,15 @@ async def test_flagguard(foo_class: FooClass): @pytest.mark.asyncio async def test_formalin(foo_class: FooClass): - # reset instance counter - foo_class.counter = 0 - # # # # # # # # # # # # # # # # # # # # - - # should run only once - foo_class.params.flags.fooclass.foo_formalin_func = 0 - - foo_class.started = True - asyncio.create_task(foo_class.foo_formalin_func()) - await asyncio.sleep(1) - foo_class.started = False - await asyncio.sleep(0.5) - - - assert foo_class.counter == 1 # counter increased only once - - # reset flag cache and instance counter - foo_class.counter = 0 - # # # # # # # # # # # # # # # # # # # # - - # should run twice (every 0.5s in 1.1s) - foo_class.params.flags.fooclass.foo_formalin_func = 0.5 - - foo_class.started = True - asyncio.create_task(foo_class.foo_formalin_func()) - await asyncio.sleep(1.3) - foo_class.started = False - await asyncio.sleep(0.5) - - assert foo_class.counter == 2 # counter increased twice - - + async def setup_test(run_time: float, sleep_time: float, expected_count: int): + foo_class.params.flags.fooclass.foo_formalin_func = sleep_time + foo_class.started = True + asyncio.create_task(foo_class.foo_formalin_func()) + await asyncio.sleep(run_time) + foo_class.started = False + await asyncio.sleep(0.5) + assert foo_class.counter == expected_count + foo_class.counter = 0 + + setup_test(1, 0, 1) + setup_test(1.3, 0.5, 2) \ No newline at end of file diff --git a/ct-app/test/components/test_utils.py b/ct-app/test/components/test_utils.py index 08b6b881..14fc2545 100644 --- a/ct-app/test/components/test_utils.py +++ b/ct-app/test/components/test_utils.py @@ -157,8 +157,12 @@ def test_exclude(): assert item.address in blacklist -def test_rewardProbability(): - pytest.skip("Not implemented") +def test_rewardProbability(peers: list[Peer]): + Utils.rewardProbability(peers) + + splits = [peer.reward_probability for peer in peers] + assert sum(splits) == pytest.approx(1.0) + assert all(splits) def test_stringArrayToGCP(): diff --git a/ct-app/test/conftest.py b/ct-app/test/conftest.py index 422d9acb..0d2df347 100644 --- a/ct-app/test/conftest.py +++ b/ct-app/test/conftest.py @@ -91,11 +91,7 @@ def peers_raw() -> list[dict]: {"peer_id": "id_0", "peer_address": "address_0", "reported_version": "2.0.0"}, {"peer_id": "id_1", "peer_address": "address_1", "reported_version": "1.7.0"}, {"peer_id": "id_2", "peer_address": "address_2", "reported_version": "1.0.3"}, - { - "peer_id": "id_3", - "peer_address": "address_3", - "reported_version": "1.0.0-rc.3", - }, + {"peer_id": "id_3", "peer_address": "address_3", "reported_version": "1.0.0-rc.3"}, {"peer_id": "id_4", "peer_address": "address_4", "reported_version": "1.0.0"}, ] @@ -128,15 +124,46 @@ def addresses() -> list[dict]: @pytest.fixture -def nodes() -> list[Node]: - return [ +async def nodes(mocker: MockerFixture, + peers: list[Peer], + addresses: list[dict], + peers_raw: list[dict], + channels: NodeChannelsResponse, +) -> list[Node]: + nodes = [ Node("localhost:9000", "random_key"), Node("localhost:9001", "random_key"), Node("localhost:9002", "random_key"), Node("localhost:9003", "random_key"), Node("localhost:9004", "random_key"), ] + for idx, node in enumerate(nodes): + mocker.patch.object(node.peers, "get", return_value=peers[:idx] + peers[idx+1:]) + mocker.patch.object(node.api, "get_address", return_value=addresses[idx]) + mocker.patch.object(node.api, "all_channels", return_value=channels) + mocker.patch.object( + node.api, "channel_balance", side_effect=SideEffect().channel_balance + ) + mocker.patch.object( + node.api, "send_message", side_effect=SideEffect().send_message_success + ) + mocker.patch.object( + node.api, "messages_pop_all", side_effect=SideEffect().inbox_messages + ) + mocker.patch.object(node.api, "balances", side_effect=SideEffect().node_balance) + mocker.patch.object(node.api, "peers", return_value=peers_raw[:idx] + peers_raw[idx+1:]) + + mocker.patch.object(node.api, "healthyz", return_value=True) + mocker.patch.object(node.api, "startedz", return_value=True) + mocker.patch.object(node.api, "ticket_price", return_value=0.01) + + setattr(node.params, "distribution", Parameters()) + setattr(node.params.distribution, "delay_between_two_messages", 0.001) + + await node._retrieve_address() + + return nodes @pytest.fixture def channels(peers: list[Peer]) -> NodeChannelsResponse: @@ -169,41 +196,11 @@ def channels(peers: list[Peer]) -> NodeChannelsResponse: @pytest.fixture -async def core( - mocker: MockerFixture, - nodes: list[Node], - peers: list[Peer], - addresses: list[dict], - channels: NodeChannelsResponse, -) -> Core: +async def core(mocker: MockerFixture, nodes: list[Node]) -> Core: core = Core() - core.nodes = nodes - - for idx, node in enumerate(core.nodes): - mocker.patch.object(node.peers, "get", return_value=peers) - mocker.patch.object(node.api, "get_address", return_value=addresses[idx]) - mocker.patch.object(node.api, "all_channels", return_value=channels) - mocker.patch.object( - node.api, "channel_balance", side_effect=SideEffect().channel_balance - ) - - mocker.patch.object( - node.api, "send_message", side_effect=SideEffect().send_message_success - ) - mocker.patch.object( - node.api, "messages_pop_all", side_effect=SideEffect().inbox_messages - ) - - setattr(node.params, "distribution", Parameters()) - setattr(node.params.distribution, "delay_between_two_messages", 0.001) - mocker.patch.object(DBUtils, "peerIDToInt", return_value=0) - mocker.patch.object(core.api, "healthyz", return_value=True) - mocker.patch.object(core.api, "startedz", return_value=True) - mocker.patch.object(core.api, "ticket_price", return_value=0.01) - params = Parameters() with open("./test/test_config.yaml", "r") as file: params.parse(yaml.safe_load(file)) @@ -211,9 +208,6 @@ async def core( core.post_init(nodes, params) - for idx, node in enumerate(core.nodes): - await node._retrieve_address() - await core._retrieve_address() return core @@ -221,6 +215,7 @@ async def core( @pytest.fixture async def node( + nodes: list[Node], mocker: MockerFixture, peers_raw: list[dict], channels: NodeChannelsResponse, diff --git a/ct-app/test/test_core.py b/ct-app/test/test_core.py index 97ea05bd..3ffb61d8 100644 --- a/ct-app/test/test_core.py +++ b/ct-app/test/test_core.py @@ -1,5 +1,6 @@ -from core.model.address import Address import pytest + +from core.model.address import Address from core.model.peer import Peer from core.model.subgraph_type import SubgraphType @@ -20,7 +21,7 @@ async def test__retrieve_address(core: Core, addresses: list[dict]): @pytest.mark.asyncio -async def test_healthcheck(core: Core): +async def test_core_healthcheck(core: Core): await core.healthcheck() assert await core.connected.get() @@ -63,11 +64,6 @@ async def test_apply_economic_model(core: Core): pytest.skip("Not implemented") -@pytest.mark.asyncio -async def test_prepare_distribution(core: Core): - pytest.skip("Not implemented") - - @pytest.mark.asyncio async def test_get_fundings(core: Core): pytest.skip("Not implemented") diff --git a/ct-app/test/test_node.py b/ct-app/test/test_node.py index 6f49a7f6..130a9233 100644 --- a/ct-app/test/test_node.py +++ b/ct-app/test/test_node.py @@ -1,9 +1,7 @@ import asyncio import time from random import randint, random - import pytest -from core.model.address import Address from hoprd_sdk.models import NodeChannelsResponse from .conftest import Node, Peer @@ -12,12 +10,14 @@ @pytest.mark.asyncio async def test__retrieve_address(node: Node, addresses: dict): await node._retrieve_address() + address = await node.address.get() - assert (await node.address.get()) == Address(addresses[0]["hopr"], addresses[0]["native"]) + assert address.address in [addr["native"] for addr in addresses] + assert address.id in [addr["hopr"] for addr in addresses] @pytest.mark.asyncio -async def test_healthcheck(node: Node): +async def test_node_healthcheck(node: Node): await node.healthcheck() assert await node.connected.get() @@ -62,9 +62,8 @@ async def test_fund_channels(node: Node): @pytest.mark.asyncio async def test_retrieve_peers(node: Node, peers: list[Peer]): - assert await node.peers.get() == set() - assert await node.peer_history.get() == dict() - + await node.peers.set(set()) + await node.peer_history.set(dict()) await node.retrieve_peers() assert len(await node.peers.get()) == len(peers) - 1