diff --git a/.gitignore b/.gitignore index 1b6888a7..00e8fb44 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ # Python *.pyc -venv __pycache__ .env diff --git a/requirements.in b/requirements.in index 56fd2dfa..28f04b81 100644 --- a/requirements.in +++ b/requirements.in @@ -18,3 +18,4 @@ black mypy pylint pytest +pytest-mock diff --git a/src/data_sync/common.py b/src/data_sync/common.py index a04e192f..1373ce43 100644 --- a/src/data_sync/common.py +++ b/src/data_sync/common.py @@ -19,6 +19,9 @@ def partition_time_range( Otherwise, the range is split into n pieces of the form [(start_time, start_of_month_2), (start_of_month_2, start_of_month_3),..., (start_of_month_n, end_time)]. """ + assert ( + start_time.timetz().tzinfo == end_time.timetz().tzinfo + ), "Timezones need to be the same" assert start_time < end_time, "start_time must be strictly smaller than end_time" # if there is just one month to consider diff --git a/src/fetch/payouts.py b/src/fetch/payouts.py index c76f1a03..697a2116 100644 --- a/src/fetch/payouts.py +++ b/src/fetch/payouts.py @@ -76,7 +76,6 @@ def __init__( # pylint: disable=too-many-arguments, too-many-positional-argumen service_fee: Fraction, reward_token_address: Address, ): - assert quote_reward_cow >= 0, "invalid quote_reward_cow" self.solver = solver diff --git a/tests/unit/test_common.py b/tests/unit/test_common.py new file mode 100644 index 00000000..f31740f4 --- /dev/null +++ b/tests/unit/test_common.py @@ -0,0 +1,87 @@ +import pytest +from pytest_mock import MockerFixture +import datetime +from src.data_sync.common import ( + partition_time_range, + compute_block_range, + find_block_with_timestamp, +) + +from web3 import Web3 + + +@pytest.fixture(scope="session") +def times(): + start_time = datetime.datetime.now(tz=datetime.timezone.utc) + end_time = start_time + datetime.timedelta(seconds=10) + return {"start_time": start_time, "end_time": end_time} + + +@pytest.fixture(scope="function") +def mock_node(): + return Web3() + + +def test_partition_time_range(times): + # test that if they are equal or negative the function raises an error + with pytest.raises(AssertionError): + partition_time_range( + start_time=times["start_time"], end_time=times["start_time"] + ) + + # test timezones don't match + with pytest.raises(AssertionError): + partition_time_range( + start_time=datetime.datetime.now(), end_time=times["end_time"] + ) + + with pytest.raises(AssertionError): + partition_time_range( + start_time=times["start_time"], + end_time=times["end_time"] + datetime.timedelta(seconds=-10), + ) + + # end time is not greater than a month + result = partition_time_range( + start_time=times["start_time"], end_time=times["end_time"] + ) + assert result == [(times["start_time"], times["end_time"])] + + # end time is greater than a month + result = partition_time_range( + start_time=times["start_time"], + end_time=times["end_time"] + datetime.timedelta(days=60), + ) + + assert len(result) == 3 + + +def test_compute_block_range(mocker: MockerFixture, times, mock_node): + mock_find_block = mocker.patch( + "src.data_sync.common.find_block_with_timestamp", side_effect=[200, 400] + ) + mock_get_block = mocker.patch.object( + mock_node.eth, + "get_block", + return_value={"number": 400, "timestamp": times["end_time"].timestamp()}, + ) + results = compute_block_range( + start_time=times["start_time"], end_time=times["end_time"], node=mock_node + ) + + assert mock_find_block.call_count == 2 + mock_get_block.assert_called_once() + assert results.block_from == 200 + assert results.block_to == 399 + + +def test_find_block_with_timestamp(mocker: MockerFixture, mock_node, times): + end_timestamp = times["end_time"].timestamp() + mock_get_block = mocker.patch.object( + mock_node.eth, + "get_block", + return_value={"number": 400, "timestamp": end_timestamp}, + ) + results = find_block_with_timestamp(node=mock_node, time_stamp=end_timestamp) + assert results == 400 + assert mock_get_block.call_count == 3