diff --git a/tests/test_uniswap4.py b/tests/test_uniswap4.py index 22cbaf4..864d4d4 100644 --- a/tests/test_uniswap4.py +++ b/tests/test_uniswap4.py @@ -1,10 +1,11 @@ import logging import os import shutil +import socket import subprocess +import time from contextlib import contextmanager from dataclasses import astuple, dataclass -from time import sleep from typing import Generator, List, Optional import pytest @@ -118,7 +119,23 @@ def anvil() -> Generator[AnvilInstance, None, None]: # Address #1 when anvil is run with `--wallet.seed test`, it starts with 1000 ETH eth_address = "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720" eth_privkey = "0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6" - sleep(3) + # Poll until Anvil accepts connections. Fail immediately if the process + # exits (for example a genesis failure), rather than waiting out the deadline. + deadline = time.monotonic() + 60 + while time.monotonic() < deadline: + if p.poll() is not None: + raise RuntimeError( + f"Anvil exited before listening on port {port} (code {p.returncode})" + ) + try: + with socket.create_connection(("127.0.0.1", port), timeout=1): + break + except OSError: + time.sleep(0.5) + else: + p.kill() + p.wait() + raise RuntimeError(f"Anvil did not start on port {port} within 60s") yield AnvilInstance(f"http://127.0.0.1:{port}", eth_address, eth_privkey) p.kill() p.wait() diff --git a/tests/test_v4_examples.py b/tests/test_v4_examples.py index 0d0320c..003e7fc 100644 --- a/tests/test_v4_examples.py +++ b/tests/test_v4_examples.py @@ -14,9 +14,10 @@ import os import shutil +import socket import subprocess +import time from dataclasses import dataclass -from time import sleep from typing import Generator import pytest @@ -98,7 +99,23 @@ def anvil() -> Generator[AnvilInstance, None, None]: # Anvil test account #2 (1000 ETH pre-funded) eth_address = "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC" eth_privkey = "0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a" - sleep(3) + # Poll until Anvil accepts connections. Fail immediately if the process + # exits (for example a genesis failure), rather than waiting out the deadline. + deadline = time.monotonic() + 60 + while time.monotonic() < deadline: + if p.poll() is not None: + raise RuntimeError( + f"Anvil exited before listening on port {port} (code {p.returncode})" + ) + try: + with socket.create_connection(("127.0.0.1", port), timeout=1): + break + except OSError: + time.sleep(0.5) + else: + p.kill() + p.wait() + raise RuntimeError(f"Anvil did not start on port {port} within 60s") yield AnvilInstance(f"http://127.0.0.1:{port}", eth_address, eth_privkey) p.kill() p.wait()