From 7f7dbdd06680fc87aa5efe138eb66181ac2f19c0 Mon Sep 17 00:00:00 2001 From: Piper Merriam Date: Thu, 29 Dec 2016 11:41:33 -0700 Subject: [PATCH 1/2] add testing module --- docs/web3.testing.rst | 55 +++++++++++++++++++ setup.py | 2 +- tests/testing-module/test_testing_mine.py | 22 ++++++++ .../test_testing_snapshot_and_revert.py | 47 ++++++++++++++++ .../testing-module/test_testing_timeTravel.py | 9 +++ tox.ini | 1 + web3/main.py | 2 + web3/testing.py | 30 ++++++++++ 8 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 docs/web3.testing.rst create mode 100644 tests/testing-module/test_testing_mine.py create mode 100644 tests/testing-module/test_testing_snapshot_and_revert.py create mode 100644 tests/testing-module/test_testing_timeTravel.py create mode 100644 web3/testing.py diff --git a/docs/web3.testing.rst b/docs/web3.testing.rst new file mode 100644 index 0000000..7d81338 --- /dev/null +++ b/docs/web3.testing.rst @@ -0,0 +1,55 @@ +Testing API +=========== + +.. py:module:: web3.testing +.. py:currentmodule:: web3.testing + +.. py:class:: Testing + +The ``web3.testing`` object exposes methods to interact with non-standard RPC +APIs that are only available under the python ``eth-testrpc`` package. + + +Methods +------- + +The following methods are available on the ``web3.testing`` namespace. + + +.. py:method:: Testing.timeTravel(timestamp) + + * Delegates to ``testing_timeTravel`` RPC Method + + Advances the test blockchain one block setting the new block's timestamp to + the provided integer timestamp. + + +.. py:method:: Testing.mine(num_blocks=1) + + * Delegates to ``evm_mine`` RPC Method + + Mines ``num_blocks`` new blocks. + + +.. py:method:: Testing.snapshot() + + * Delegates to ``evm_snapshot`` RPC Method + + Takes a snapshot of the current EVM state and returns an integer that can + be used with the ``revert`` method to restore the EVM to this state. + + +.. py:method:: Testing.revert(snapshot_idx=None) + + * Delegates to ``evm_revert`` RPC Method + + If no ``snapshot_idx`` is provided this will revert the EVM to the most + recent snapshot. Otherwise reverts the EVM to the snapshot indicated by + the provided ``snapshot_idx`` + + +.. py:method:: Testing.reset() + + * Delegates to ``evm_reset`` RPC Method + + Reset the EVM back to the genesis state. diff --git a/setup.py b/setup.py index 4a91bd6..cd35663 100644 --- a/setup.py +++ b/setup.py @@ -33,7 +33,7 @@ setup( "pylru>=1.0.9", ], extras_require={ - 'Tester': ["eth-testrpc>=0.9.0"], + 'Tester': ["eth-testrpc>=0.9.2"], }, py_modules=['web3'], license="MIT", diff --git a/tests/testing-module/test_testing_mine.py b/tests/testing-module/test_testing_mine.py new file mode 100644 index 0000000..4a22524 --- /dev/null +++ b/tests/testing-module/test_testing_mine.py @@ -0,0 +1,22 @@ +def test_testing_mine_single_block(web3): + web3.testing.mine() + + before_mining_block = web3.eth.getBlock("latest") + + web3.testing.mine() + + after_mining_block = web3.eth.getBlock("latest") + + assert after_mining_block['number'] - before_mining_block['number'] == 1 + + +def test_testing_mine_multiple_blocks(web3): + web3.testing.mine() + + before_mining_block = web3.eth.getBlock("latest") + + web3.testing.mine(5) + + after_mining_block = web3.eth.getBlock("latest") + + assert after_mining_block['number'] - before_mining_block['number'] == 5 diff --git a/tests/testing-module/test_testing_snapshot_and_revert.py b/tests/testing-module/test_testing_snapshot_and_revert.py new file mode 100644 index 0000000..f17e244 --- /dev/null +++ b/tests/testing-module/test_testing_snapshot_and_revert.py @@ -0,0 +1,47 @@ +def test_snapshot_revert_to_latest_snapshot(web3): + web3.testing.mine(5) + + block_before_snapshot = web3.eth.getBlock("latest") + + snapshot_idx = web3.testing.snapshot() + + block_after_snapshot = web3.eth.getBlock("latest") + + web3.testing.mine(3) + + block_after_mining = web3.eth.getBlock("latest") + + web3.testing.revert() + + block_after_revert = web3.eth.getBlock("latest") + + assert block_after_mining['number'] > block_before_snapshot['number'] + assert block_before_snapshot['hash'] == block_after_snapshot['hash'] + assert block_after_snapshot['hash'] == block_after_revert['hash'] + + +def test_snapshot_revert_to_specific(web3): + web3.testing.mine(5) + + block_before_snapshot = web3.eth.getBlock("latest") + + snapshot_idx = web3.testing.snapshot() + + block_after_snapshot = web3.eth.getBlock("latest") + + web3.testing.mine() + web3.testing.snapshot() + web3.testing.mine() + web3.testing.snapshot() + web3.testing.mine() + web3.testing.snapshot() + + block_after_mining = web3.eth.getBlock("latest") + + web3.testing.revert(snapshot_idx) + + block_after_revert = web3.eth.getBlock("latest") + + assert block_after_mining['number'] > block_before_snapshot['number'] + assert block_before_snapshot['hash'] == block_after_snapshot['hash'] + assert block_after_snapshot['hash'] == block_after_revert['hash'] diff --git a/tests/testing-module/test_testing_timeTravel.py b/tests/testing-module/test_testing_timeTravel.py new file mode 100644 index 0000000..50628fe --- /dev/null +++ b/tests/testing-module/test_testing_timeTravel.py @@ -0,0 +1,9 @@ +def test_time_traveling(web3): + current_block_time = web3.eth.getBlock("pending")['timestamp'] + + time_travel_to = current_block_time + 12345 + + web3.testing.timeTravel(time_travel_to) + + latest_block_time = web3.eth.getBlock("pending")['timestamp'] + assert latest_block_time >= time_travel_to diff --git a/tox.ini b/tox.ini index 19d844c..e22a0de 100644 --- a/tox.ini +++ b/tox.ini @@ -24,6 +24,7 @@ commands= db: py.test {posargs:tests/db-module} managers: py.test {posargs:tests/managers} personal: py.test {posargs:tests/personal-module} + testing: py.test {posargs:tests/testing-module} utilities: py.test {posargs:tests/utilities} deps = -r{toxinidir}/requirements-dev.txt diff --git a/web3/main.py b/web3/main.py index 3fd5617..af3db14 100644 --- a/web3/main.py +++ b/web3/main.py @@ -9,6 +9,7 @@ from web3.personal import Personal from web3.shh import Shh from web3.txpool import TxPool from web3.version import Version +from web3.testing import Testing from web3.iban import Iban @@ -100,6 +101,7 @@ class Web3(object): self.txpool = TxPool(self) self.miner = Miner(self) self.admin = Admin(self) + self.testing = Testing(self) def setProvider(self, provider): self._requestManager.setProvider(provider) diff --git a/web3/testing.py b/web3/testing.py new file mode 100644 index 0000000..456cb4e --- /dev/null +++ b/web3/testing.py @@ -0,0 +1,30 @@ +from web3.utils.encoding import ( + to_decimal, +) +from web3.utils.functional import ( + apply_formatters_to_return, +) + + +class Testing(object): + def __init__(self, web3): + self.web3 = web3 + + def timeTravel(self, timestamp): + return self.web3._requestManager.request_blocking("testing_timeTravel", [timestamp]) + + def mine(self, num_blocks=1): + return self.web3._requestManager.request_blocking("evm_mine", [num_blocks]) + + @apply_formatters_to_return(to_decimal) + def snapshot(self): + return self.web3._requestManager.request_blocking("evm_snapshot", []) + + def reset(self): + return self.web3._requestManager.request_blocking("evm_reset", []) + + def revert(self, snapshot_idx=None): + if snapshot_idx is None: + return self.web3._requestManager.request_blocking("evm_revert", []) + else: + return self.web3._requestManager.request_blocking("evm_revert", [snapshot_idx]) From e298a8164eb5141a4760ed68e4bfab42b0ecb704 Mon Sep 17 00:00:00 2001 From: Piper Merriam Date: Thu, 29 Dec 2016 11:51:05 -0700 Subject: [PATCH 2/2] latest testrpc --- requirements-dev.txt | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 08fd0ed..3666418 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,7 +1,7 @@ pytest>=2.8.2 pytest-pythonpath>=0.3 tox>=1.8.0 -eth-testrpc>=0.9.0 +eth-testrpc>=0.9.3 py-geth>=1.4.0 ethereum>=1.5.2 secp256k1>=0.13.1 diff --git a/setup.py b/setup.py index cd35663..e36d8bb 100644 --- a/setup.py +++ b/setup.py @@ -33,7 +33,7 @@ setup( "pylru>=1.0.9", ], extras_require={ - 'Tester': ["eth-testrpc>=0.9.2"], + 'Tester': ["eth-testrpc>=0.9.3"], }, py_modules=['web3'], license="MIT",