Skip to content

Commit

Permalink
run tests in parallel locally with makefile
Browse files Browse the repository at this point in the history
  • Loading branch information
0xalpharush committed Mar 28, 2023
1 parent 91798e1 commit 0d3115f
Show file tree
Hide file tree
Showing 20 changed files with 1,287 additions and 1,195 deletions.
2 changes: 0 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ jobs:
- name: Install dependencies
run: |
pip install ".[test]"
solc-select install 0.8.0
solc-select use 0.8.0
- name: Setup node
uses: actions/setup-node@v3
Expand Down
87 changes: 87 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
SHELL := /bin/bash

PY_MODULE := slither

ALL_PY_SRCS := $(shell find $(PY_MODULE) -name '*.py') \
$(shell find test -name '*.py')

# Optionally overriden by the user, if they're using a virtual environment manager.
VENV ?= env

# On Windows, venv scripts/shims are under `Scripts` instead of `bin`.
VENV_BIN := $(VENV)/bin
ifeq ($(OS),Windows_NT)
VENV_BIN := $(VENV)/Scripts
endif

# Optionally overridden by the user in the `release` target.
BUMP_ARGS :=

# Optionally overridden by the user in the `test` target.
TESTS :=

# Optionally overridden by the user/CI, to limit the installation to a specific
# subset of development dependencies.
SLITHER_EXTRA := dev

# If the user selects a specific test pattern to run, set `pytest` to fail fast
# and only run tests that match the pattern.
# Otherwise, run all tests and enable coverage assertions, since we expect
# complete test coverage.
ifneq ($(TESTS),)
TEST_ARGS := -x -k $(TESTS)
COV_ARGS :=
else
TEST_ARGS := -n auto
COV_ARGS := --cov-append # --fail-under 100
endif

.PHONY: all
all:
@echo "Run my targets individually!"

.PHONY: dev
dev: $(VENV)/pyvenv.cfg

.PHONY: run
run: $(VENV)/pyvenv.cfg
@. $(VENV_BIN)/activate && slither $(ARGS)

$(VENV)/pyvenv.cfg: pyproject.toml
# Create our Python 3 virtual environment
python3 -m venv env
$(VENV_BIN)/python -m pip install --upgrade pip
$(VENV_BIN)/python -m pip install -e .[$(SLITHER_EXTRA)]

.PHONY: lint
lint: $(VENV)/pyvenv.cfg
. $(VENV_BIN)/activate && \
black --check $(ALL_PY_SRCS) && \
pylint $(ALL_PY_SRCS)
# ruff $(ALL_PY_SRCS) && \
# mypy $(PY_MODULE) &&

.PHONY: reformat
reformat:
. $(VENV_BIN)/activate && \
black $(PY_MODULE)

.PHONY: test tests
test tests: $(VENV)/pyvenv.cfg
. $(VENV_BIN)/activate && \
pytest --cov=$(PY_MODULE) $(T) $(TEST_ARGS) && \
python -m coverage report -m $(COV_ARGS)

.PHONY: doc
doc: $(VENV)/pyvenv.cfg
. $(VENV_BIN)/activate && \
PDOC_ALLOW_EXEC=1 pdoc -o html slither '!slither.tools'

.PHONY: package
package: $(VENV)/pyvenv.cfg
. $(VENV_BIN)/activate && \
python3 -m build

.PHONY: edit
edit:
$(EDITOR) $(ALL_PY_SRCS)
2 changes: 2 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
# "crytic-compile>=0.3.0",
"crytic-compile@git+https://github.com/crytic/crytic-compile.git@master#egg=crytic-compile",
"web3>=6.0.0",
"solc-select@git+https://github.com/crytic/solc-select.git@query-artifact-path#egg=solc-select",
],
extras_require={
"lint": [
Expand All @@ -31,6 +32,7 @@
"deepdiff",
"numpy",
"coverage[toml]",
"filelock",
],
"doc": [
"pdoc",
Expand Down
27 changes: 27 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import pytest
from filelock import FileLock
from solc_select import solc_select

@pytest.fixture(scope="session")
def solc_versions_installed():
"""List of solc versions available in the test environment."""
return []

@pytest.fixture(scope="session", autouse=True)
def register_solc_versions_installed(solc_versions_installed):
solc_versions_installed.extend(solc_select.installed_versions())

@pytest.fixture(scope="session")
def use_solc_version(request, solc_versions_installed):
def _use_solc_version(version):
print(version)
if version not in solc_versions_installed:
print("Installing solc version", version)
solc_select.install_artifacts([version])
artifact_path = solc_select.artifact_path(version)
lock = FileLock(artifact_path)
try:
yield artifact_path
finally:
lock.release()
return _use_solc_version
12 changes: 6 additions & 6 deletions tests/e2e/compilation/test_resolution.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ def test_node_modules() -> None:
_run_all_detectors(slither)


def test_contract_name_collisions() -> None:
solc_select.switch_global_version("0.8.0", always_install=True)
def test_contract_name_collision(use_solc_version) -> None:
solc_path = next(use_solc_version("0.8.0"))
standard_json = SolcStandardJson()
standard_json.add_source_file(
Path(TEST_DATA_DIR, "test_contract_name_collisions", "a.sol").as_posix()
Expand All @@ -34,13 +34,13 @@ def test_contract_name_collisions() -> None:
Path(TEST_DATA_DIR, "test_contract_name_collisions", "b.sol").as_posix()
)

compilation = CryticCompile(standard_json)
compilation = CryticCompile(standard_json, solc=solc_path)
slither = Slither(compilation)

_run_all_detectors(slither)


def test_cycle() -> None:
solc_select.switch_global_version("0.8.0", always_install=True)
slither = Slither(Path(TEST_DATA_DIR, "test_cyclic_import", "a.sol").as_posix())
def test_cycle(use_solc_version) -> None:
solc_path = next(use_solc_version("0.8.0"))
slither = Slither(Path(TEST_DATA_DIR, "test_cyclic_import", "a.sol").as_posix(), solc=solc_path)
_run_all_detectors(slither)
6 changes: 4 additions & 2 deletions tests/tools/read-storage/test_read_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,9 @@ def deploy_contract(w3, ganache, contract_bin, contract_abi) -> Contract:

# pylint: disable=too-many-locals
@pytest.mark.usefixtures("web3", "ganache")
def test_read_storage(web3, ganache) -> None:
def test_read_storage(web3, ganache, use_solc_version) -> None:
solc_path = next(use_solc_version(version="0.8.10"))

assert web3.is_connected()
bin_path = Path(TEST_DATA_DIR, "StorageLayout.bin").as_posix()
abi_path = Path(TEST_DATA_DIR, "StorageLayout.abi").as_posix()
Expand All @@ -100,7 +102,7 @@ def test_read_storage(web3, ganache) -> None:
contract.functions.store().transact({"from": ganache.eth_address})
address = contract.address

sl = Slither(Path(TEST_DATA_DIR, "storage_layout-0.8.10.sol").as_posix())
sl = Slither(Path(TEST_DATA_DIR, "storage_layout-0.8.10.sol").as_posix(), solc=solc_path)
contracts = sl.contracts

srs = SlitherReadStorage(contracts, 100)
Expand Down
6 changes: 3 additions & 3 deletions tests/unit/core/test_arithmetic.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data" / "arithmetic_usage"


def test_arithmetic_usage() -> None:
solc_select.switch_global_version("0.8.15", always_install=True)
slither = Slither(Path(TEST_DATA_DIR, "test.sol").as_posix())
def test_arithmetic_usage(use_solc_version) -> None:
solc_path = next(use_solc_version("0.8.15"))
slither = Slither(Path(TEST_DATA_DIR, "test.sol").as_posix(), solc=solc_path)

assert {
f.source_mapping.content_hash for f in unchecked_arithemtic_usage(slither.contracts[0])
Expand Down
18 changes: 9 additions & 9 deletions tests/unit/core/test_code_comments.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
CUSTOM_COMMENTS_TEST_DATA_DIR = Path(TEST_DATA_DIR, "custom_comments")


def test_upgradeable_comments() -> None:
solc_select.switch_global_version("0.8.10", always_install=True)
slither = Slither(Path(CUSTOM_COMMENTS_TEST_DATA_DIR, "upgrade.sol").as_posix())
def test_upgradeable_comments(use_solc_version) -> None:
solc_path = next(use_solc_version("0.8.10"))
slither = Slither(Path(CUSTOM_COMMENTS_TEST_DATA_DIR, "upgrade.sol").as_posix(), solc=solc_path)
compilation_unit = slither.compilation_units[0]
proxy = compilation_unit.get_contract_from_name("Proxy")[0]

Expand All @@ -27,11 +27,11 @@ def test_upgradeable_comments() -> None:
assert v1.upgradeable_version == "version_1"


def test_contract_comments() -> None:
def test_contract_comments(use_solc_version) -> None:
comments = " @title Test Contract\n @dev Test comment"

solc_select.switch_global_version("0.8.10", always_install=True)
slither = Slither(Path(CUSTOM_COMMENTS_TEST_DATA_DIR, "contract_comment.sol").as_posix())
solc_path = next(use_solc_version("0.8.10"))
slither = Slither(Path(CUSTOM_COMMENTS_TEST_DATA_DIR, "contract_comment.sol").as_posix(), solc=solc_path)
compilation_unit = slither.compilation_units[0]
contract = compilation_unit.get_contract_from_name("A")[0]

Expand All @@ -40,19 +40,19 @@ def test_contract_comments() -> None:
# Old solc versions have a different parsing of comments
# the initial space (after *) is also not kept on every line
comments = "@title Test Contract\n@dev Test comment"
solc_select.switch_global_version("0.5.16", always_install=True)
slither = Slither(Path(CUSTOM_COMMENTS_TEST_DATA_DIR, "contract_comment.sol").as_posix())
solc_path = next(use_solc_version("0.5.16"))
slither = Slither(Path(CUSTOM_COMMENTS_TEST_DATA_DIR, "contract_comment.sol").as_posix(), solc=solc_path)
compilation_unit = slither.compilation_units[0]
contract = compilation_unit.get_contract_from_name("A")[0]

assert contract.comments == comments

# Test with legacy AST
comments = "@title Test Contract\n@dev Test comment"
solc_select.switch_global_version("0.5.16", always_install=True)
slither = Slither(
Path(CUSTOM_COMMENTS_TEST_DATA_DIR, "contract_comment.sol").as_posix(),
solc_force_legacy_json=True,
solc=solc_path,
)
compilation_unit = slither.compilation_units[0]
contract = compilation_unit.get_contract_from_name("A")[0]
Expand Down
15 changes: 9 additions & 6 deletions tests/unit/core/test_constant_folding.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@
CONSTANT_FOLDING_TEST_ROOT = Path(TEST_DATA_DIR, "constant_folding")


def test_constant_folding_unary():
def test_constant_folding_unary(use_solc_version):
solc_path = next(use_solc_version("0.8.0"))
file = Path(CONSTANT_FOLDING_TEST_ROOT, "constant_folding_unary.sol").as_posix()
Slither(file)
Slither(file, solc=solc_path)


def test_constant_folding_rational():
s = Slither(Path(CONSTANT_FOLDING_TEST_ROOT, "constant_folding_rational.sol").as_posix())
def test_constant_folding_rational(use_solc_version):
solc_path = next(use_solc_version("0.8.0"))
s = Slither(Path(CONSTANT_FOLDING_TEST_ROOT, "constant_folding_rational.sol").as_posix(), solc=solc_path)
contract = s.get_contract_from_name("C")[0]

variable_a = contract.get_state_variable_from_name("a")
Expand Down Expand Up @@ -50,8 +52,9 @@ def test_constant_folding_rational():
assert str(ConstantFolding(variable_g.expression, "int64").result()) == "-7"


def test_constant_folding_binary_expressions():
sl = Slither(Path(CONSTANT_FOLDING_TEST_ROOT, "constant_folding_binop.sol").as_posix())
def test_constant_folding_binary_expressions(use_solc_version):
solc_path = next(use_solc_version("0.8.0"))
sl = Slither(Path(CONSTANT_FOLDING_TEST_ROOT, "constant_folding_binop.sol").as_posix(), solc=solc_path)
contract = sl.get_contract_from_name("BinOp")[0]

variable_a = contract.get_state_variable_from_name("a")
Expand Down
17 changes: 9 additions & 8 deletions tests/unit/core/test_contract_declaration.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,26 @@
CONTRACT_DECL_TEST_ROOT = Path(TEST_DATA_DIR, "contract_declaration")


def test_abstract_contract() -> None:
solc_select.switch_global_version("0.8.0", always_install=True)
slither = Slither(Path(CONTRACT_DECL_TEST_ROOT, "abstract.sol").as_posix())
def test_abstract_contract(use_solc_version) -> None:
solc_path = next(use_solc_version("0.8.0"))
slither = Slither(Path(CONTRACT_DECL_TEST_ROOT, "abstract.sol").as_posix(), solc=solc_path)
assert not slither.contracts[0].is_fully_implemented

solc_select.switch_global_version("0.5.0", always_install=True)
slither = Slither(Path(CONTRACT_DECL_TEST_ROOT, "implicit_abstract.sol").as_posix())
solc_path = next(use_solc_version("0.5.0"))
slither = Slither(Path(CONTRACT_DECL_TEST_ROOT, "implicit_abstract.sol").as_posix(), solc=solc_path)
assert not slither.contracts[0].is_fully_implemented

slither = Slither(
Path(CONTRACT_DECL_TEST_ROOT, "implicit_abstract.sol").as_posix(),
solc_force_legacy_json=True,
solc=solc_path
)
assert not slither.contracts[0].is_fully_implemented


def test_private_variable() -> None:
solc_select.switch_global_version("0.8.15", always_install=True)
slither = Slither(Path(CONTRACT_DECL_TEST_ROOT, "private_variable.sol").as_posix())
def test_private_variable(use_solc_version) -> None:
solc_path = next(use_solc_version("0.8.15"))
slither = Slither(Path(CONTRACT_DECL_TEST_ROOT, "private_variable.sol").as_posix(), solc=solc_path)
contract_c = slither.get_contract_from_name("C")[0]
f = contract_c.functions[0]
var_read = f.variables_read[0]
Expand Down
24 changes: 12 additions & 12 deletions tests/unit/core/test_function_declaration.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@
FUNC_DELC_TEST_ROOT = Path(TEST_DATA_DIR, "function_declaration")


def test_functions():
def test_functions(use_solc_version):
# pylint: disable=too-many-statements
solc_select.switch_global_version("0.6.12", always_install=True)
solc_path = next(use_solc_version("0.6.12"))
file = Path(FUNC_DELC_TEST_ROOT, "test_function.sol").as_posix()
slither = Slither(file)
slither = Slither(file, solc=solc_path)
functions = slither.get_contract_from_name("TestFunction")[0].available_functions_as_dict()

f = functions["external_payable(uint256)"]
Expand Down Expand Up @@ -248,10 +248,10 @@ def test_functions():
assert f.return_type[0] == ElementaryType("bool")


def test_function_can_send_eth():
solc_select.switch_global_version("0.6.12", always_install=True)
def test_function_can_send_eth(use_solc_version):
solc_path = next(use_solc_version("0.6.12"))
file = Path(FUNC_DELC_TEST_ROOT, "test_function.sol").as_posix()
slither = Slither(file)
slither = Slither(file, solc=solc_path)
compilation_unit = slither.compilation_units[0]
functions = compilation_unit.get_contract_from_name("TestFunctionCanSendEth")[
0
Expand All @@ -273,10 +273,10 @@ def test_function_can_send_eth():
assert functions["highlevel_call_via_external()"].can_send_eth() is False


def test_reentrant():
solc_select.switch_global_version("0.8.10", always_install=True)
def test_reentrant(use_solc_version):
solc_path = next(use_solc_version("0.8.10"))
file = Path(FUNC_DELC_TEST_ROOT, "test_function_reentrant.sol").as_posix()
slither = Slither(file)
slither = Slither(file, solc=solc_path)
compilation_unit = slither.compilation_units[0]
functions = compilation_unit.get_contract_from_name("TestReentrant")[
0
Expand All @@ -290,10 +290,10 @@ def test_reentrant():
assert functions["internal_and_reentrant()"].is_reentrant


def test_public_variable() -> None:
solc_select.switch_global_version("0.6.12", always_install=True)
def test_public_variable(use_solc_version) -> None:
solc_path = next(use_solc_version("0.6.12"))
file = Path(FUNC_DELC_TEST_ROOT, "test_function.sol").as_posix()
slither = Slither(file)
slither = Slither(file, solc=solc_path)
contracts = slither.get_contract_from_name("TestFunction")
assert len(contracts) == 1
contract = contracts[0]
Expand Down
Loading

0 comments on commit 0d3115f

Please sign in to comment.