Skip to content
This repository was archived by the owner on May 23, 2023. It is now read-only.

Commit 85c11d1

Browse files
committed
Merge pull request #321 from ethereum/clean_up_tests
Cleanup test loading
2 parents 80c5cdf + 8146f0e commit 85c11d1

20 files changed

+231
-242
lines changed

.travis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ sudo: false
44
env:
55
- TOX_ENV=py27
66
install:
7-
- pip install -r requirements.txt
8-
- pip install -r dev_requirements.txt
7+
- pip install -Ur requirements.txt
8+
- pip install -Ur dev_requirements.txt
99
script:
1010
- coverage run --source ethereum -m py.test --ignore ethereum/tests/test_vm.py --ignore
1111
ethereum/tests/test_state.py

dev_requirements.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
tox
22
coveralls
3-
pytest
4-
pytest-catchlog==1.1
5-
pytest-timeout==0.5
3+
pytest>=2.9.0
4+
pytest-catchlog==1.2.2
5+
pytest-timeout==1.0.0
66
https://github.com/ethereum/serpent/tarball/develop

ethereum/slogging.py

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,32 @@ class LogRecorder(object):
3535
"""
3636
max_capacity = 1000 * 1000 # check we are not forgotten or abused
3737

38-
def __init__(self):
38+
def __init__(self, disable_other_handlers=False, log_config=None):
3939
self._records = []
4040
log_listeners.append(self._add_log_record)
41+
self._saved_config = None
42+
if log_config:
43+
self._saved_config = get_configuration()
44+
configure(log_config)
45+
self._saved_handlers = []
46+
if disable_other_handlers:
47+
self._saved_handlers = rootLogger.handlers[:]
48+
rootLogger.handlers = []
4149

4250
def pop_records(self):
43-
# can only be called once
51+
# only returns records on the first call
4452
r = self._records[:]
45-
self._records = None
46-
log_listeners.remove(self._add_log_record)
53+
self._records = []
54+
try:
55+
log_listeners.remove(self._add_log_record)
56+
except ValueError:
57+
pass
58+
if self._saved_config:
59+
configure(**self._saved_config)
60+
self._saved_config = None
61+
if self._saved_handlers:
62+
rootLogger.handlers = self._saved_handlers[:]
63+
self._saved_handlers = []
4764
return r
4865

4966
def _add_log_record(self, msg):
@@ -59,9 +76,13 @@ def get_configuration():
5976
"""
6077
root = getLogger()
6178
name_levels = [('', logging.getLevelName(root.level))]
79+
name_levels.extend(
80+
(name, logging.getLevelName(logger.level))
81+
for name, logger
82+
in root.manager.loggerDict.items()
83+
if hasattr(logger, 'level')
84+
)
6285

63-
for name, logger in list(root.manager.loggerDict.items()):
64-
name_levels.append((name, logging.getLevelName(logger.level)))
6586
config_string = ','.join('%s:%s' % x for x in name_levels)
6687

6788
return dict(config_string=config_string, log_json=root.log_json)
@@ -222,6 +243,7 @@ def configure(config_string=None, log_json=False, log_file=None):
222243
if hasattr(logger, 'setLevel'):
223244
# Guard against `logging.PlaceHolder` instances
224245
logger.setLevel(logging.NOTSET)
246+
logger.propagate = True
225247

226248
for name_levels in config_string.split(','):
227249
name, _, level = name_levels.partition(':')

ethereum/tester.py

Lines changed: 39 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,17 @@
1313
import rlp
1414
from rlp.utils import decode_hex, encode_hex, ascii_chr
1515

16+
17+
TRACE_LVL_MAP = [
18+
':info',
19+
'eth.vm.log:trace',
20+
':info,eth.vm.log:trace,eth.vm.exit:trace',
21+
':info,eth.vm.log:trace,eth.vm.op:trace,eth.vm.stack:trace',
22+
':info,eth.vm.log:trace,eth.vm.op:trace,eth.vm.stack:trace,' +
23+
'eth.vm.storage:trace,eth.vm.memory:trace'
24+
]
25+
26+
1627
serpent = None
1728

1829
u = ethereum.utils
@@ -199,31 +210,35 @@ def _send(self, sender, to, value, evmdata='', output=None,
199210
tx = t.Transaction(sendnonce, gas_price, gas_limit, to, value, evmdata)
200211
self.last_tx = tx
201212
tx.sign(sender)
213+
recorder = None
202214
if profiling > 1:
203-
set_logging_level(3)
204-
recorder = LogRecorder()
205-
(s, o) = pb.apply_transaction(self.block, tx)
206-
if not s:
207-
raise TransactionFailed()
208-
out = {"output": o}
209-
if profiling > 0:
210-
zero_bytes = tx.data.count(ascii_chr(0))
211-
non_zero_bytes = len(tx.data) - zero_bytes
212-
intrinsic_gas_used = opcodes.GTXCOST + \
213-
opcodes.GTXDATAZERO * zero_bytes + \
214-
opcodes.GTXDATANONZERO * non_zero_bytes
215-
ntm, ng = time.time(), self.block.gas_used
216-
out["time"] = ntm - tm
217-
out["gas"] = ng - g - intrinsic_gas_used
218-
if profiling > 1:
219-
trace = recorder.pop_records()
220-
set_logging_level(0)
221-
ops = [x['op'] for x in trace if x['event'] == 'vm']
222-
opdict = {}
223-
for op in ops:
224-
opdict[op] = opdict.get(op, 0) + 1
225-
out["ops"] = opdict
226-
return out
215+
recorder = LogRecorder(disable_other_handlers=True, log_config=TRACE_LVL_MAP[3])
216+
try:
217+
(s, o) = pb.apply_transaction(self.block, tx)
218+
if not s:
219+
raise TransactionFailed()
220+
out = {"output": o}
221+
if profiling > 0:
222+
zero_bytes = tx.data.count(ascii_chr(0))
223+
non_zero_bytes = len(tx.data) - zero_bytes
224+
intrinsic_gas_used = opcodes.GTXCOST + \
225+
opcodes.GTXDATAZERO * zero_bytes + \
226+
opcodes.GTXDATANONZERO * non_zero_bytes
227+
ntm, ng = time.time(), self.block.gas_used
228+
out["time"] = ntm - tm
229+
out["gas"] = ng - g - intrinsic_gas_used
230+
if profiling > 1:
231+
trace = recorder.pop_records()
232+
ops = [x['op'] for x in trace if x['event'] == 'vm']
233+
opdict = {}
234+
for op in ops:
235+
opdict[op] = opdict.get(op, 0) + 1
236+
out["ops"] = opdict
237+
return out
238+
finally:
239+
# ensure LogRecorder has been disabled
240+
if recorder:
241+
recorder.pop_records()
227242

228243
def profile(self, *args, **kwargs):
229244
kwargs['profiling'] = True
@@ -281,41 +296,6 @@ def revert(self, data):
281296
self.block._cached_rlp = None
282297
self.block.header._cached_rlp = None
283298

284-
# logging
285-
286-
287-
def set_logging_level(lvl=0):
288-
trace_lvl_map = [
289-
':info',
290-
'eth.vm.log:trace',
291-
':info,eth.vm.log:trace,eth.vm.exit:trace',
292-
':info,eth.vm.log:trace,eth.vm.op:trace,eth.vm.stack:trace',
293-
':info,eth.vm.log:trace,eth.vm.op:trace,eth.vm.stack:trace,' +
294-
'eth.vm.storage:trace,eth.vm.memory:trace'
295-
]
296-
configure_logging(config_string=trace_lvl_map[lvl])
297-
if lvl == 0:
298-
set_level(None, 'info')
299-
print('Set logging level: %d' % lvl)
300-
301-
302-
def set_log_trace(logger_names=[]):
303-
"""
304-
sets all named loggers to level 'trace'
305-
attention: vm.op.* are only active if vm.op is active
306-
"""
307-
for name in logger_names:
308-
assert name in slogging.get_logger_names()
309-
slogging.set_level(name, 'trace')
310-
311-
312-
def enable_logging():
313-
set_logging_level(1)
314-
315-
316-
def disable_logging():
317-
set_logging_level(0)
318-
319299

320300
gas_limit = 3141592
321301
gas_price = 1

ethereum/tests/conftest.py

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,19 @@
11
import pytest
2+
23
from ethereum import slogging
34

45

56
CATCH_LOG_HANDLER_NAME = 'catch_log_handler'
67

78

8-
@pytest.mark.hookwrapper
9-
def pytest_runtest_setup(item):
10-
"""Attach pytest-catchlog's handler to `slogging`'s root logger"""
11-
yield
12-
caplog_handler = getattr(item, CATCH_LOG_HANDLER_NAME, None)
13-
if caplog_handler and caplog_handler not in slogging.rootLogger.handlers:
14-
slogging.rootLogger.addHandler(caplog_handler)
9+
# Connect catchlog's handler to slogging's root logger
10+
@pytest.hookimpl(hookwrapper=True, trylast=True)
11+
def pytest_runtest_call(item):
12+
catchlog_handler = getattr(item, CATCH_LOG_HANDLER_NAME, None)
13+
if catchlog_handler and catchlog_handler not in slogging.rootLogger.handlers:
14+
slogging.rootLogger.addHandler(catchlog_handler)
1515

16+
_ = yield
1617

17-
@pytest.mark.hookwrapper
18-
def pytest_runtest_makereport(item, call):
19-
"""Remove pytest-catchlog's handler from `slogging`'s root logger"""
20-
if call.when == 'call':
21-
caplog_handler = getattr(item, CATCH_LOG_HANDLER_NAME, None)
22-
if caplog_handler and caplog_handler in slogging.rootLogger.handlers:
23-
slogging.rootLogger.removeHandler(caplog_handler)
24-
yield
18+
if catchlog_handler and catchlog_handler in slogging.rootLogger.handlers:
19+
slogging.rootLogger.removeHandler(catchlog_handler)

ethereum/tests/test_abi.py

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,24 @@
44
import ethereum.abi as abi
55
logger = get_logger()
66

7+
78
def test_abi_encode_var_sized_array():
89
abi.encode_abi(['address[]'], [[b'\x00' * 20] * 3])
910

11+
1012
def test_abi_encode_fixed_size_array():
1113
abi.encode_abi(['uint16[2]'], [[5, 6]])
1214

15+
1316
def test_abi_encode_signed_int():
1417
assert abi.decode_abi(['int8'], abi.encode_abi(['int8'], [1]))[0] == 1
1518
assert abi.decode_abi(['int8'], abi.encode_abi(['int8'], [-1]))[0] == -1
1619

1720

18-
# SETUP TESTS IN GLOBAL NAME SPACE
19-
def gen_func(filename, testname, testdata):
20-
return lambda: do_test_state(filename, testname, testdata)
21-
22-
def do_test_state(filename, testname=None, testdata=None, limit=99999999):
23-
logger.debug('running test:%r in %r' % (testname, filename))
21+
# Will be parametrized fron json fixtures
22+
def test_state(filename, testname, testdata):
2423
testutils.check_abi_test(testutils.fixture_to_bytes(testdata))
2524

26-
fixtures = testutils.get_tests_from_file_or_dir(
27-
os.path.join(testutils.fixture_path, 'ABITests'))
2825

29-
filenames = sorted(list(fixtures.keys()))
30-
for filename in filenames:
31-
tests = fixtures[filename]
32-
for testname, testdata in list(tests.items()):
33-
func_name = 'test_%s_%s' % (filename, testname)
34-
globals()[func_name] = gen_func(filename, testname, testdata)
26+
def pytest_generate_tests(metafunc):
27+
testutils.generate_test_params('ABITests', metafunc)

ethereum/tests/test_blocks.py

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import pytest
2+
13
from ethereum import blocks, utils, db
24
from ethereum.exceptions import VerificationFailed, InvalidTransaction
35
import rlp
@@ -106,41 +108,44 @@ def run_block_test(params, config_overrides = {}):
106108
env.config = old_config
107109

108110

109-
def do_test_block(filename, testname=None, testdata=None, limit=99999999):
110-
print('\nrunning test:%r in %r' % (testname, filename))
111+
def test_block(filename, testname, testdata):
111112
run_block_test(testdata, {'HOMESTEAD_FORK_BLKNUM':0 if 'Homestead' in filename else 5 if 'TestNetwork' in filename else 1000000 })
112113

113-
excludes = [('bcWalletTest.json', u'walletReorganizeOwners'),
114-
('bl10251623GO.json', u'randomBlockTest'),
115-
('bl201507071825GO.json', u'randomBlockTest')
116-
]
117114

115+
excludes = {
116+
('bcWalletTest.json', u'walletReorganizeOwners'),
117+
('bl10251623GO.json', u'randomBlockTest'),
118+
('bl201507071825GO.json', u'randomBlockTest')
119+
}
118120

119-
if __name__ == '__main__':
121+
122+
def pytest_generate_tests(metafunc):
123+
testutils.generate_test_params(
124+
'BlockchainTests',
125+
metafunc,
126+
lambda filename, testname, _: (filename.split('/')[-1], testname) in excludes
127+
)
128+
129+
130+
def main():
120131
assert len(sys.argv) >= 2, "Please specify file or dir name"
121132
fixtures = testutils.get_tests_from_file_or_dir(sys.argv[1])
122133
if len(sys.argv) >= 3:
123134
for filename, tests in list(fixtures.items()):
124135
for testname, testdata in list(tests.items()):
125136
if testname == sys.argv[2]:
126137
print("Testing: %s %s" % (filename, testname))
127-
run_block_test(testdata, {'HOMESTEAD_FORK_BLKNUM':0 if 'Homestead' in filename else 5 if 'TestNetwork' in filename else 1000000 })
138+
run_block_test(testdata, {
139+
'HOMESTEAD_FORK_BLKNUM': 0 if 'Homestead' in filename else 5 if 'TestNetwork' in filename
140+
else 1000000})
128141
else:
129142
for filename, tests in list(fixtures.items()):
130143
for testname, testdata in list(tests.items()):
131144
if (filename.split('/')[-1], testname) not in excludes:
132145
print("Testing: %s %s" % (filename, testname))
133-
run_block_test(testdata, {'HOMESTEAD_FORK_BLKNUM':0 if 'Homestead' in filename else 5 if 'TestNetwork' in filename else 1000000 })
134-
else:
135-
fixtures = testutils.get_tests_from_file_or_dir(
136-
os.path.join(testutils.fixture_path, 'BlockchainTests'))
137-
138-
def mk_test_func(filename, testname, testdata):
139-
return lambda: do_test_block(filename, testname, testdata)
140-
141-
for filename, tests in list(fixtures.items()):
142-
for testname, testdata in list(tests.items())[:500]:
143-
func_name = 'test_%s_%s' % (filename, testname)
144-
if (filename.split('/')[-1], testname) not in excludes:
145-
# print 'making function', (filename.split('/')[-1], testname)
146-
globals()[func_name] = mk_test_func(filename, testname, testdata)
146+
run_block_test(testdata, {
147+
'HOMESTEAD_FORK_BLKNUM': 0 if 'Homestead' in filename else 5 if 'TestNetwork' in filename else 1000000})
148+
149+
150+
if __name__ == '__main__':
151+
main()

ethereum/tests/test_chain.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@
1010
from ethereum.db import EphemDB
1111
from ethereum.tests.utils import new_db
1212

13-
from ethereum.slogging import get_logger, configure_logging
13+
from ethereum.slogging import get_logger
1414
logger = get_logger()
15-
# configure_logging('eth.vm:trace,eth.vm.memory:info')
1615

1716
_db = new_db()
1817

0 commit comments

Comments
 (0)