Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
{
"BLOB_SCHEDULE": sample_blob_schedule(initial_epoch=1, interval=1),
},
emit=False,
)
@with_presets([MINIMAL], reason="too slow")
def test_light_client_data_collection(spec, state):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
{
"BLOB_SCHEDULE": sample_blob_schedule(),
},
emit=False,
)
@with_presets([MINIMAL], reason="too slow")
def test_light_client_sync(spec, state):
Expand Down Expand Up @@ -294,7 +293,6 @@ def test_light_client_sync(spec, state):
{
"BLOB_SCHEDULE": sample_blob_schedule(),
},
emit=False,
)
@with_presets([MINIMAL], reason="too slow")
def test_supply_sync_committee_from_past_update(spec, state):
Expand Down Expand Up @@ -334,7 +332,6 @@ def test_supply_sync_committee_from_past_update(spec, state):
{
"BLOB_SCHEDULE": sample_blob_schedule(),
},
emit=False,
)
@with_presets([MINIMAL], reason="too slow")
def test_advance_finality_without_sync_committee(spec, state):
Expand Down Expand Up @@ -428,7 +425,6 @@ def test_advance_finality_without_sync_committee(spec, state):
{
"BLOB_SCHEDULE": sample_blob_schedule(),
},
emit=False,
)
@with_presets([MINIMAL], reason="too slow")
def test_light_client_sync_no_force_update(spec, state):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ def setup_test(spec, state):
{
"BLOB_SCHEDULE": sample_blob_schedule(),
},
emit=False,
)
def test_process_light_client_update_not_timeout(spec, state):
genesis_block, store = setup_test(spec, state)
Expand Down Expand Up @@ -75,7 +74,6 @@ def test_process_light_client_update_not_timeout(spec, state):
{
"BLOB_SCHEDULE": sample_blob_schedule(),
},
emit=False,
)
@with_presets([MINIMAL], reason="too slow")
def test_process_light_client_update_at_period_boundary(spec, state):
Expand Down Expand Up @@ -116,7 +114,6 @@ def test_process_light_client_update_at_period_boundary(spec, state):
{
"BLOB_SCHEDULE": sample_blob_schedule(),
},
emit=False,
)
@with_presets([MINIMAL], reason="too slow")
def test_process_light_client_update_timeout(spec, state):
Expand Down Expand Up @@ -157,7 +154,6 @@ def test_process_light_client_update_timeout(spec, state):
{
"BLOB_SCHEDULE": sample_blob_schedule(),
},
emit=False,
)
@with_presets([MINIMAL], reason="too slow")
def test_process_light_client_update_finality_updated(spec, state):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ def test_config_override_matching_fork_epochs(spec, state):
"ALTAIR_FORK_VERSION": "0x11111111",
"BELLATRIX_FORK_EPOCH": 4,
},
emit=False,
)
@with_state
@with_matching_spec_config(emitted_fork=BELLATRIX)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
"CAPELLA_FORK_EPOCH": 1 * 8, # SyncCommitteePeriod 1
"DENEB_FORK_EPOCH": 2 * 8, # SyncCommitteePeriod 2
},
emit=False,
)
@with_state
@with_matching_spec_config(emitted_fork=DENEB)
Expand All @@ -40,7 +39,6 @@ def test_capella_deneb_reorg_aligned(spec, phases, state):
"CAPELLA_FORK_EPOCH": 1 * 8 + 4, # SyncCommitteePeriod 1 (+ 4 epochs)
"DENEB_FORK_EPOCH": 3 * 8 + 4, # SyncCommitteePeriod 3 (+ 4 epochs)
},
emit=False,
)
@with_state
@with_matching_spec_config(emitted_fork=DENEB)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
{
"CAPELLA_FORK_EPOCH": 3, # Test setup advances to epoch 2
},
emit=False,
)
@with_state
@with_matching_spec_config(emitted_fork=CAPELLA)
Expand All @@ -41,7 +40,6 @@ def test_capella_fork(spec, phases, state):
"CAPELLA_FORK_EPOCH": 3, # Test setup advances to epoch 2
"DENEB_FORK_EPOCH": 4,
},
emit=False,
)
@with_state
@with_matching_spec_config(emitted_fork=DENEB)
Expand All @@ -58,7 +56,6 @@ def test_capella_deneb_fork(spec, phases, state):
"DENEB_FORK_EPOCH": 4,
"ELECTRA_FORK_EPOCH": 5,
},
emit=False,
)
@with_state
@with_matching_spec_config(emitted_fork=ELECTRA)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
"DENEB_FORK_EPOCH": 1 * 8, # SyncCommitteePeriod 1
"ELECTRA_FORK_EPOCH": 2 * 8, # SyncCommitteePeriod 2
},
emit=False,
)
@with_state
@with_matching_spec_config(emitted_fork=ELECTRA)
Expand All @@ -40,7 +39,6 @@ def test_deneb_electra_reorg_aligned(spec, phases, state):
"DENEB_FORK_EPOCH": 1 * 8 + 4, # SyncCommitteePeriod 1 (+ 4 epochs)
"ELECTRA_FORK_EPOCH": 3 * 8 + 4, # SyncCommitteePeriod 3 (+ 4 epochs)
},
emit=False,
)
@with_state
@with_matching_spec_config(emitted_fork=ELECTRA)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
{
"DENEB_FORK_EPOCH": 3, # Test setup advances to epoch 2
},
emit=False,
)
@with_state
@with_matching_spec_config(emitted_fork=DENEB)
Expand All @@ -40,7 +39,6 @@ def test_deneb_fork(spec, phases, state):
"DENEB_FORK_EPOCH": 3, # Test setup advances to epoch 2
"ELECTRA_FORK_EPOCH": 4,
},
emit=False,
)
@with_state
@with_matching_spec_config(emitted_fork=ELECTRA)
Expand Down
42 changes: 35 additions & 7 deletions tests/core/pyspec/eth2spec/test/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from lru import LRU

from eth2spec.utils import bls
from tests.infra.yield_generator import vector_test

from .exceptions import SkippedTest
from .helpers.constants import (
Expand Down Expand Up @@ -40,7 +41,6 @@
SpecForks,
)
from .utils import (
vector_test,
with_meta_tags,
)

Expand Down Expand Up @@ -325,7 +325,7 @@ def spec_test(fn):
# A test may apply BLS overrides such as @always_bls,
# but if it yields data (n.b. @always_bls yields the bls setting), it should be wrapped by this decorator.
# This is why @always_bls has its own bls switch, since the override is beyond the reach of the outer switch.
return vector_test()(bls_switch(fn))
return vector_test(bls_switch(fn))


# shorthand for decorating @spec_test @with_state @single_phase
Expand All @@ -334,7 +334,7 @@ def spec_state_test(fn):


def spec_configured_state_test(conf):
overrides = with_config_overrides(conf)
overrides = _with_config_overrides_emit(conf)

def decorator(fn):
return spec_test(overrides(with_state(single_phase(fn))))
Expand Down Expand Up @@ -369,7 +369,7 @@ def with_matching_spec_config(emitted_fork=None):
def decorator(fn):
def wrapper(*args, spec: Spec, **kw):
overrides = config_fork_epoch_overrides(spec, kw["state"])
deco = with_config_overrides(overrides, emitted_fork)
deco = _with_config_overrides_emit(overrides, emitted_fork)
return deco(fn)(*args, spec=spec, **kw)

return wrapper
Expand Down Expand Up @@ -711,7 +711,36 @@ def spec_with_config_overrides(spec, config_overrides):
return spec, output_config


def with_config_overrides(config_overrides, emitted_fork=None, emit=True):
def with_config_overrides(config_overrides):
"""
WARNING: the spec_test decorator must wrap this, to ensure the decorated test actually runs.

This is a decorator that applies a dict of config value overrides to the spec during execution.
"""

def decorator(fn):
def wrapper(*args, spec: Spec, **kw):
# Apply config overrides to spec
spec, _ = spec_with_config_overrides(get_copy_of_spec(spec), config_overrides)

# Apply config overrides to additional phases, if present
if "phases" in kw:
phases = {}
for fork in kw["phases"]:
phases[fork], _ = spec_with_config_overrides(
get_copy_of_spec(kw["phases"][fork]), config_overrides
)
kw["phases"] = phases

# Run the function
return fn(*args, spec=spec, **kw)

return wrapper

return decorator


def _with_config_overrides_emit(config_overrides, emitted_fork=None):
"""
WARNING: the spec_test decorator must wrap this, to ensure the decorated test actually runs.
This decorator forces the test to yield, and pytest doesn't run generator tests, and instead silently passes it.
Expand Down Expand Up @@ -739,8 +768,7 @@ def wrapper(*args, spec: Spec, **kw):
kw["phases"] = phases

# Emit requested spec (with overrides)
if emit:
yield "config", "cfg", output_config
yield "config", "cfg", output_config

# Run the function
out = fn(*args, spec=spec, **kw)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
{
"ELECTRA_FORK_EPOCH": 3, # Test setup advances to epoch 2
},
emit=False,
)
@with_state
@with_matching_spec_config(emitted_fork=ELECTRA)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
{"EPOCH": 300, "MAX_BLOBS_PER_BLOCK": 300},
],
},
emit=False,
)
def test_compute_fork_digest(spec):
test_cases = [
Expand Down
3 changes: 2 additions & 1 deletion tests/core/pyspec/eth2spec/test/utils/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from tests.infra.yield_generator import vector_test

from .utils import (
vector_test,
with_meta_tags,
)

Expand Down
76 changes: 0 additions & 76 deletions tests/core/pyspec/eth2spec/test/utils/utils.py
Original file line number Diff line number Diff line change
@@ -1,81 +1,5 @@
from typing import Any

from eth2spec.utils.ssz.ssz_impl import serialize
from eth2spec.utils.ssz.ssz_typing import View


def vector_test(description: str = None):
"""
vector_test decorator: Allow a caller to pass "generator_mode=True" to make the test yield data,
but behave like a normal test (ignoring the yield, but fully processing) a test when not in "generator_mode"
This should always be the most outer decorator around functions that yield data.
This is to deal with silent iteration through yielding function when in a pytest
context (i.e. not in generator mode).
:param description: Optional description for the test to add to the metadata.
:return: Decorator.
"""

def runner(fn):
# this wraps the function, to yield type-annotated entries of data.
# Valid types are:
# - "meta": all key-values with this type can be collected by the generator, to put somewhere together.
# - "cfg": spec config dictionary
# - "ssz": raw SSZ bytes
# - "data": a python structure to be encoded by the user.
def entry(*args, **kw):
def generator_mode():
if description is not None:
# description can be explicit
yield "description", "meta", description

# transform the yielded data, and add type annotations
for data in fn(*args, **kw):
# if not 2 items, then it is assumed to be already formatted with a type:
# e.g. ("bls_setting", "meta", 1)
if len(data) != 2:
yield data
continue
# Try to infer the type, but keep it as-is if it's not a SSZ type or bytes.
(key, value) = data
if value is None:
continue
if isinstance(value, View):
yield key, "ssz", serialize(value)
elif isinstance(value, bytes):
yield key, "ssz", value
elif isinstance(value, list) and all(
[isinstance(el, View | bytes) for el in value]
):
for i, el in enumerate(value):
if isinstance(el, View):
yield f"{key}_{i}", "ssz", serialize(el)
elif isinstance(el, bytes):
yield f"{key}_{i}", "ssz", el
yield f"{key}_count", "meta", len(value)
else:
# Not a ssz value.
# The data will now just be yielded as any python data,
# something that should be encodable by the generator runner.
yield key, "data", value

# check generator mode, may be None/else.
# "pop" removes it, so it is not passed to the inner function.
if kw.pop("generator_mode", False) is True:
# return the yielding function as a generator object.
# Don't yield in this function itself, that would make pytest skip over it.
return generator_mode()
else:
# Just complete the function, ignore all yielded data,
# we are not using it (or processing it, i.e. nearly zero efficiency loss)
# Pytest does not support yielded data in the outer function, so we need to wrap it like this.
for _ in fn(*args, **kw):
continue
return None

return entry

return runner


def with_meta_tags(tags: dict[str, Any]):
"""
Expand Down
Loading