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
7 changes: 3 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -234,11 +234,10 @@ gen_list:
gen_%: MAYBE_VERBOSE := $(if $(filter true,$(verbose)),--verbose)
gen_%: MAYBE_MODCHECK := $(if $(filter true,$(modcheck)),--modcheck)
gen_%: MAYBE_THREADS := $(if $(threads),--threads=$(threads))
gen_%: MAYBE_TESTS := $(if $(k),--case-list $(subst ${COMMA}, ,$(k)))
gen_%: MAYBE_FORKS := $(if $(fork),--fork-list $(subst ${COMMA}, ,$(fork)))
gen_%: MAYBE_PRESETS := $(if $(preset),--preset-list $(subst ${COMMA}, ,$(preset)))
gen_%: MAYBE_TESTS := $(if $(k),--cases $(subst ${COMMA}, ,$(k)))
gen_%: MAYBE_FORKS := $(if $(fork),--forks $(subst ${COMMA}, ,$(fork)))
gen_%: MAYBE_PRESETS := $(if $(preset),--presets $(subst ${COMMA}, ,$(preset)))
gen_%: pyspec
@mkdir -p $(TEST_VECTOR_DIR)
@$(PYTHON_VENV) $(GENERATOR_DIR)/$*/main.py \
--output $(TEST_VECTOR_DIR) \
$(MAYBE_VERBOSE) \
Expand Down
64 changes: 64 additions & 0 deletions tests/core/pyspec/eth2spec/gen_helpers/gen_base/args.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import argparse
import os
import pathlib


def parse_arguments(generator_name):
parser = argparse.ArgumentParser(
prog="gen-" + generator_name,
description=f"Generate YAML test suite files for {generator_name}.",
)
parser.add_argument(
"-o",
"--output-dir",
dest="output_dir",
required=True,
type=pathlib.Path,
help="Directory into which the generated YAML files will be dumped.",
)
parser.add_argument(
"--presets",
dest="presets",
nargs="*",
type=str,
default=[],
required=False,
help="Specify presets to run with. Allows all if no preset names are specified.",
)
parser.add_argument(
"--forks",
dest="forks",
nargs="*",
type=str,
default=[],
required=False,
help="Specify forks to run with. Allows all if no fork names are specified.",
)
parser.add_argument(
"--cases",
dest="cases",
nargs="*",
type=str,
default=[],
required=False,
help="Specify test cases to run with. Allows all if no test case names are specified.",
)
parser.add_argument(
"--modcheck",
action="store_true",
default=False,
help="Check generator modules, do not run any tests.",
)
parser.add_argument(
"--verbose",
action="store_true",
default=False,
help="Print more information to the console.",
)
parser.add_argument(
"--threads",
type=int,
default=os.cpu_count(),
help="Generate tests with N threads. Defaults to core count.",
)
return parser.parse_args()
75 changes: 75 additions & 0 deletions tests/core/pyspec/eth2spec/gen_helpers/gen_base/dumper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
from eth2spec.test import context
from eth_utils import encode_hex
from ruamel.yaml import YAML
from snappy import compress

from .gen_typing import TestCase


def get_default_yaml():
yaml = YAML(pure=True)
yaml.default_flow_style = None

def _represent_none(self, _):
return self.represent_scalar("tag:yaml.org,2002:null", "null")

def _represent_str(self, data):
if data.startswith("0x"):
# Without this, a zero-byte hex string is represented without quotes.
return self.represent_scalar("tag:yaml.org,2002:str", data, style="'")
return self.represent_str(data)

yaml.representer.add_representer(type(None), _represent_none)
yaml.representer.add_representer(str, _represent_str)

return yaml


def get_cfg_yaml():
# Spec config is using a YAML subset
cfg_yaml = YAML(pure=True)
cfg_yaml.default_flow_style = False # Emit separate line for each key

def cfg_represent_bytes(self, data):
return self.represent_int(encode_hex(data))

cfg_yaml.representer.add_representer(bytes, cfg_represent_bytes)

def cfg_represent_quoted_str(self, data):
return self.represent_scalar("tag:yaml.org,2002:str", data, style="'")

cfg_yaml.representer.add_representer(context.quoted_str, cfg_represent_quoted_str)
return cfg_yaml


class Dumper:
"""Helper for dumping test case outputs (cfg, data, meta, ssz)."""

def __init__(self, default_yaml: YAML = None, cfg_yaml: YAML = None):
self.default_yaml = default_yaml or get_default_yaml()
self.cfg_yaml = cfg_yaml or get_cfg_yaml()

def dump_meta(self, test_case: TestCase, meta: dict) -> None:
if not meta:
return
self._dump_yaml(test_case, "meta", meta, self.default_yaml)

def dump_cfg(self, test_case: TestCase, name: str, data: any) -> None:
self._dump_yaml(test_case, name, data, self.cfg_yaml)

def dump_data(self, test_case: TestCase, name: str, data: any) -> None:
self._dump_yaml(test_case, name, data, self.default_yaml)

def dump_ssz(self, test_case: TestCase, name: str, data: bytes) -> None:
"""Compress and write SSZ data for test case."""
path = test_case.dir / f"{name}.ssz_snappy"
path.parent.mkdir(parents=True, exist_ok=True)
with path.open("wb") as f:
f.write(compress(data))

def _dump_yaml(self, test_case: TestCase, name: str, data: any, yaml_encoder: YAML) -> None:
"""Helper to write YAML files for test case."""
path = test_case.dir / f"{name}.yaml"
path.parent.mkdir(parents=True, exist_ok=True)
with path.open("w") as f:
yaml_encoder.dump(data, f)
Loading