diff --git a/setup.py b/setup.py index 2771152..091bda1 100644 --- a/setup.py +++ b/setup.py @@ -42,17 +42,17 @@ name='eth-teser-rpc', # *IMPORTANT*: Don't manually change the version here. Use `make bump`, as described in readme version='0.1.0-alpha.0', - description="""Python TestRPC for ethereun""", + description="""Python TestRPC for ethereum""", long_description_markdown_filename='README.md', author='voith', - author_email='ethcalibur+pip@gmail.com', + author_email='voithjm1@gmail.com', url='https://github.com/voith/eth-teser-rpc', include_package_data=True, install_requires=[ "eth-utils>=1,<2", "toolz>=0.9.0,<1.0.0;implementation_name=='pypy'", "cytoolz>=0.9.0,<1.0.0;implementation_name=='cpython'", - "eth-tester[py-evm]==0.1.0b30", + "eth-tester[py-evm]==0.1.0b31", 'json-rpc>=1.10.3', 'Werkzeug>=0.11.10', 'click>=6.6', diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..9d3913b --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,8 @@ +import pytest + +from tests.utils import get_open_port + + +@pytest.fixture() +def open_port(): + return get_open_port() diff --git a/tests/core/conftest.py b/tests/core/conftest.py index e69de29..430c964 100644 --- a/tests/core/conftest.py +++ b/tests/core/conftest.py @@ -0,0 +1,112 @@ +import contextlib +import itertools +import json +import os +import pytest +import socket + +from eth_utils import ( + to_text, +) + +from eth_tester_rpc.utils.compat_threading import ( + make_server, + spawn, +) +from tests.utils import ( + wait_for_http_connection, +) + + +request_counter = itertools.count() + + +def close_http_socket(port): + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.settimeout(1) + try: + s.connect(('127.0.0.1', port)) + s.close() + except (socket.timeout, ConnectionRefusedError): + pass + + +@pytest.yield_fixture() +def rpc_server(open_port): + from eth_tester_rpc.server import get_application + + application = get_application() + + server = make_server( + '127.0.0.1', + open_port, + application, + ) + thread = spawn(server.serve_forever) + wait_for_http_connection(open_port) + + yield server + close_http_socket(open_port) + try: + server.stop() + except AttributeError: + server.shutdown() + + thread.join() + + +@pytest.fixture() +def rpc_client(rpc_server): + try: + host, port = rpc_server.address + except AttributeError: + host, port = rpc_server.server_address + + endpoint = "http://{host}:{port}".format(host=host, port=port) + + def make_request(method, params=None): + global request_counter + payload = { + "id": next(request_counter), + "jsonrpc": "2.0", + "method": method, + "params": params or [], + } + payload_data = json.dumps(payload) + + if 'TESTRPC_ASYNC_GEVENT' in os.environ: + from geventhttpclient import HTTPClient + client = HTTPClient( + host=host, + port=port, + connection_timeout=10, + network_timeout=10, + headers={ + 'Content-Type': 'application/json', + }, + ) + with contextlib.closing(client): + response = client.post('/', body=payload_data) + response_body = response.read() + + result = json.loads(to_text(response_body)) + else: + import requests + response = requests.post( + endpoint, + data=payload_data, + headers={ + 'Content-Type': 'application/json', + }, + ) + + result = response.json() + + if 'error' in result: + raise AssertionError(result['error']) + + return result['result'] + + make_request.server = rpc_server + + return make_request diff --git a/tests/core/endpoints/__init__.py b/tests/core/endpoints/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/core/endpoints/test_eth.py b/tests/core/endpoints/test_eth.py new file mode 100644 index 0000000..5bcb222 --- /dev/null +++ b/tests/core/endpoints/test_eth.py @@ -0,0 +1,43 @@ +import pytest + +from eth_tester.constants import ( + UINT256_MIN, + UINT256_MAX +) +from eth_utils import ( + is_address, + is_checksum_address, +) + + +# def test_eth_protocolVersion(w3): +# with pytest.raises(ValueError): +# w3.eth.protocolVersion +# +# +# def test_eth_syncing(w3): +# with pytest.raises(ValueError): +# w3.eth.syncing +# +# +# def test_eth_coinbase(w3): +# coinbase = w3.eth.coinbase +# assert is_checksum_address(coinbase) + + +def test_eth_account(rpc_client): + accounts = rpc_client('eth_accounts') + assert accounts + assert all( + is_address(account) + for account + in accounts + ) + + +# def test_eth_getBalance(w3): +# accounts = w3.eth.accounts +# for account in accounts: +# balance = w3.eth.getBalance(account) +# assert balance >= UINT256_MIN +# assert balance <= UINT256_MAX diff --git a/tests/core/server/__init__.py b/tests/core/server/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/core/server/test_server_running.py b/tests/core/server/test_server_running.py new file mode 100644 index 0000000..dc7e813 --- /dev/null +++ b/tests/core/server/test_server_running.py @@ -0,0 +1,31 @@ +import os +import signal + +from click.testing import CliRunner + +from eth_tester_rpc.cli import runserver +from eth_tester_rpc.rpc import RPCMethods +from eth_tester_rpc.utils.compat_threading import ( + sleep, + spawn, +) + + +def test_main_module_for_cli_server_running(open_port): + runner = CliRunner() + + port = open_port + + pid = os.getpid() + + def kill_it(): + sleep(2) + os.kill(pid, signal.SIGINT) + + spawn(kill_it) + + result = runner.invoke(runserver, ['--port', str(port)]) + assert result.exit_code == 0 + + assert str(port) in result.output + assert RPCMethods().web3_clientVersion([]) in result.output diff --git a/tests/utils.py b/tests/utils.py new file mode 100644 index 0000000..be26239 --- /dev/null +++ b/tests/utils.py @@ -0,0 +1,33 @@ + +from eth_tester_rpc.utils.compat_threading import ( # noqa: E402 + Timeout, + sleep, + socket, +) + + +def get_open_port(): + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.bind(("", 0)) + s.listen(1) + port = s.getsockname()[1] + s.close() + return int(port) + + +def wait_for_http_connection(port, timeout=5): + with Timeout(timeout) as _timeout: + while True: + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.settimeout(1) + try: + s.connect(('127.0.0.1', port)) + except (socket.timeout, ConnectionRefusedError): + sleep(0.1) + _timeout.check() + continue + else: + s.close() + break + else: + raise ValueError("Unable to establish HTTP connection")