Skip to content

Commit 1060bfe

Browse files
ehildenbrv-auditor
andauthored
Separate functional specifications into own CI job (#2504)
* kevm-pyk/test_prove: separate out functional proofs an rewrite proofs * Makefile, .github/test-pr: split out functional tests into own test-suite * kevm-pyk/test_prove: use _test_prove helper for test_prove_dss too * kevm-pyk/test-prove: organize * kevm-pyk/test_prove: correct path for vat-spec.k * kevm-pyk/test_prove: simplify how test_prove_dss uses _test_prove * kevm-pyk/test_prove: enable --direct-subproof-rules for test_prove_dss * kevm-pyk/test_prove: remove unused test parameter setting * Set Version: 1.0.624 * kevm-pyk/test_prove: run functional specs in parallel per-file * .github/test-pr: rename step name in job * .github/test-pr: decrease rules proof timeouts --------- Co-authored-by: devops <[email protected]>
1 parent 9d3c329 commit 1060bfe

File tree

6 files changed

+151
-110
lines changed

6 files changed

+151
-110
lines changed

.github/workflows/test-pr.yml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,15 +111,20 @@ jobs:
111111
matrix:
112112
include:
113113
- name: 'Rules (booster)'
114-
test-suite: 'test-prove-pyk'
114+
test-suite: 'test-prove-rules'
115115
test-args:
116-
timeout: 150
116+
timeout: 100
117117
parallel: 6
118118
- name: 'Rules (booster-dev)'
119-
test-suite: 'test-prove-pyk'
119+
test-suite: 'test-prove-rules'
120120
test-args: '--use-booster-dev'
121121
timeout: 45
122122
parallel: 8
123+
- name: 'Functional'
124+
test-suite: 'test-prove-functional'
125+
test-args:
126+
timeout: 45
127+
parallel: 3
123128
- name: 'Optimizations'
124129
test-suite: 'test-prove-optimizations'
125130
test-args:
@@ -146,7 +151,7 @@ jobs:
146151
run: docker exec -u github-user kevm-ci-haskell-${{ matrix.test-suite }}-${{ github.sha }} /bin/bash -c 'make poetry'
147152
- name: 'Build distribution'
148153
run: docker exec -u github-user kevm-ci-haskell-${{ matrix.test-suite }}-${{ github.sha }} /bin/bash -c 'CXX=clang++-14 poetry -C kevm-pyk run kdist --verbose build -j`nproc` evm-semantics.plugin evm-semantics.haskell'
149-
- name: 'Prove Haskell'
154+
- name: 'Run proofs'
150155
run: docker exec -u github-user kevm-ci-haskell-${{ matrix.test-suite }}-${{ github.sha }} /bin/bash -c "make ${{ matrix.test-suite }} PYTEST_ARGS='-vv ${{ matrix.test-args }}' PYTEST_PARALLEL=${{ matrix.parallel }}"
151156
- name: 'Tear down Docker'
152157
if: always()

Makefile

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ kevm-pyk: poetry-env
2727
# Tests
2828
# -----
2929

30-
test: test-integration test-conformance test-prove test-prove-pyk test-prove-kprove test-prove-dss test-interactive
30+
test: test-integration test-conformance test-prove test-interactive
3131

3232

3333
# Conformance Tests
@@ -50,10 +50,13 @@ test-rest-bchain: poetry
5050

5151
# Proof Tests
5252

53-
test-prove: test-prove-pyk test-prove-optimizations test-prove-dss
53+
test-prove: test-prove-rules test-prove-functional test-prove-optimizations test-prove-dss
5454

55-
test-prove-pyk: poetry
56-
$(MAKE) -C kevm-pyk/ test-integration PYTEST_ARGS+="-k test_pyk_prove"
55+
test-prove-rules: poetry
56+
$(MAKE) -C kevm-pyk/ test-integration PYTEST_ARGS+="-k test_prove_rules"
57+
58+
test-prove-functional: poetry
59+
$(MAKE) -C kevm-pyk/ test-integration PYTEST_ARGS+="-k test_prove_functional"
5760

5861
test-prove-optimizations: poetry
5962
$(MAKE) -C kevm-pyk/ test-integration PYTEST_ARGS+="-k test_prove_optimizations"

kevm-pyk/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
44

55
[tool.poetry]
66
name = "kevm-pyk"
7-
version = "1.0.623"
7+
version = "1.0.624"
88
description = ""
99
authors = [
1010
"Runtime Verification, Inc. <[email protected]>",

kevm-pyk/src/kevm_pyk/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@
55
if TYPE_CHECKING:
66
from typing import Final
77

8-
VERSION: Final = '1.0.623'
8+
VERSION: Final = '1.0.624'

kevm-pyk/src/tests/integration/test_prove.py

Lines changed: 132 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import logging
44
import sys
5-
from pathlib import Path
65
from typing import TYPE_CHECKING, NamedTuple
76

87
import pytest
@@ -24,6 +23,7 @@
2423

2524
if TYPE_CHECKING:
2625
from collections.abc import Callable
26+
from pathlib import Path
2727
from typing import Final
2828

2929
from pyk.utils import BugReport
@@ -52,18 +52,17 @@ def spec_files(dir_name: str, glob: str) -> tuple[Path, ...]:
5252

5353

5454
BENCHMARK_TESTS: Final = spec_files('benchmarks', '*-spec.k')
55-
FUNCTIONAL_TESTS: Final = spec_files('functional', '*-spec.k')
5655
ERC20_TESTS: Final = spec_files('erc20', '*/*-spec.k')
5756
EXAMPLES_TESTS: Final = spec_files('examples', '*-spec.k') + spec_files('examples', '*-spec.md')
5857
MCD_TESTS: Final = spec_files('mcd', '*-spec.k')
5958
VAT_TESTS: Final = spec_files('mcd', 'vat*-spec.k')
6059
NON_VAT_MCD_TESTS: Final = tuple(test for test in MCD_TESTS if test not in VAT_TESTS)
6160
KONTROL_TESTS: Final = spec_files('kontrol', '*-spec.k')
61+
FUNCTIONAL_TESTS: Final = spec_files('functional', '*-spec.k')
6262

63-
ALL_TESTS: Final = sum(
63+
RULE_TESTS: Final = sum(
6464
[
6565
BENCHMARK_TESTS,
66-
FUNCTIONAL_TESTS,
6766
ERC20_TESTS,
6867
EXAMPLES_TESTS,
6968
NON_VAT_MCD_TESTS,
@@ -72,6 +71,11 @@ def spec_files(dir_name: str, glob: str) -> tuple[Path, ...]:
7271
(),
7372
)
7473

74+
ALL_TESTS: Final = sum(
75+
[RULE_TESTS, FUNCTIONAL_TESTS, VAT_TESTS],
76+
(),
77+
)
78+
7579

7680
def exclude_list(exclude_file: Path) -> list[Path]:
7781
res = [REPO_ROOT / test_path for test_path in exclude_file.read_text().splitlines()]
@@ -171,6 +175,72 @@ def _target_for_spec(spec_file: Path) -> Target:
171175
return Target(main_file, main_module_name)
172176

173177

178+
def _test_prove(
179+
spec_file: Path,
180+
kompiled_target_for: Callable[[Path], Path],
181+
tmp_path: Path,
182+
caplog: LogCaptureFixture,
183+
no_use_booster: bool,
184+
use_booster_dev: bool,
185+
bug_report: BugReport | None,
186+
spec_name: str | None,
187+
workers: int | None = None,
188+
direct_subproof_rules: bool = False,
189+
) -> None:
190+
caplog.set_level(logging.INFO)
191+
192+
if use_booster_dev and spec_file in FAILING_BOOSTER_DEV_TESTS:
193+
pytest.skip()
194+
195+
if spec_name is not None and str(spec_file).find(spec_name) < 0:
196+
pytest.skip()
197+
198+
# Given
199+
log_file = tmp_path / 'log.txt'
200+
use_directory = tmp_path / 'kprove'
201+
use_directory.mkdir()
202+
203+
# When
204+
try:
205+
definition_dir = kompiled_target_for(spec_file)
206+
name = str(spec_file.relative_to(SPEC_DIR))
207+
break_on_calls = name in TEST_PARAMS and TEST_PARAMS[name].break_on_calls
208+
break_on_basic_blocks = name in TEST_PARAMS and TEST_PARAMS[name].break_on_basic_blocks
209+
if workers is None:
210+
workers = 1 if name not in TEST_PARAMS else TEST_PARAMS[name].workers
211+
options = ProveOptions(
212+
{
213+
'spec_file': spec_file,
214+
'definition_dir': definition_dir,
215+
'includes': [str(include_dir) for include_dir in config.INCLUDE_DIRS],
216+
'save_directory': use_directory,
217+
'md_selector': 'foo', # TODO Ignored flag, this is to avoid KeyError
218+
'use_booster': not no_use_booster,
219+
'use_booster_dev': use_booster_dev,
220+
'bug_report': bug_report,
221+
'break_on_calls': break_on_calls,
222+
'break_on_basic_blocks': break_on_basic_blocks,
223+
'workers': workers,
224+
'direct_subproof_rules': direct_subproof_rules,
225+
}
226+
)
227+
exec_prove(options=options)
228+
if name in TEST_PARAMS:
229+
params = TEST_PARAMS[name]
230+
if params.leaf_number is not None and params.main_claim_id is not None:
231+
apr_proof = APRProof.read_proof_data(
232+
proof_dir=use_directory,
233+
id=params.main_claim_id,
234+
)
235+
expected_leaf_number = params.leaf_number
236+
actual_leaf_number = leaf_number(apr_proof)
237+
assert expected_leaf_number == actual_leaf_number
238+
except BaseException:
239+
raise
240+
finally:
241+
log_file.write_text(caplog.text)
242+
243+
174244
@pytest.mark.parametrize(
175245
'spec_file',
176246
ALL_TESTS,
@@ -223,10 +293,6 @@ def __init__(
223293

224294

225295
TEST_PARAMS: dict[str, TParams] = {
226-
'mcd/vat-slip-pass-rough-spec.k': TParams(
227-
main_claim_id='VAT-SLIP-PASS-ROUGH-SPEC.Vat.slip.pass.rough',
228-
leaf_number=1,
229-
),
230296
'functional/lemmas-spec.k': TParams(workers=8),
231297
'examples/sum-to-n-foundry-spec.k': TParams(break_on_basic_blocks=True),
232298
}
@@ -243,10 +309,10 @@ def leaf_number(proof: APRProof) -> int:
243309

244310
@pytest.mark.parametrize(
245311
'spec_file',
246-
ALL_TESTS,
247-
ids=[str(spec_file.relative_to(SPEC_DIR)) for spec_file in ALL_TESTS],
312+
RULE_TESTS,
313+
ids=[str(spec_file.relative_to(SPEC_DIR)) for spec_file in RULE_TESTS],
248314
)
249-
def test_pyk_prove(
315+
def test_prove_rules(
250316
spec_file: Path,
251317
kompiled_target_for: Callable[[Path], Path],
252318
tmp_path: Path,
@@ -256,56 +322,65 @@ def test_pyk_prove(
256322
bug_report: BugReport | None,
257323
spec_name: str | None,
258324
) -> None:
259-
caplog.set_level(logging.INFO)
325+
_test_prove(
326+
spec_file,
327+
kompiled_target_for,
328+
tmp_path,
329+
caplog,
330+
no_use_booster,
331+
use_booster_dev,
332+
bug_report=bug_report,
333+
spec_name=spec_name,
334+
)
260335

261-
if use_booster_dev and spec_file in FAILING_BOOSTER_DEV_TESTS:
262-
pytest.skip()
263336

264-
if spec_name is not None and str(spec_file).find(spec_name) < 0:
265-
pytest.skip()
337+
@pytest.mark.parametrize(
338+
'spec_file',
339+
FUNCTIONAL_TESTS,
340+
ids=[str(spec_file.relative_to(SPEC_DIR)) for spec_file in FUNCTIONAL_TESTS],
341+
)
342+
def test_prove_functional(
343+
spec_file: Path,
344+
kompiled_target_for: Callable[[Path], Path],
345+
tmp_path: Path,
346+
caplog: LogCaptureFixture,
347+
no_use_booster: bool,
348+
use_booster_dev: bool,
349+
bug_report: BugReport | None,
350+
spec_name: str | None,
351+
) -> None:
352+
_test_prove(
353+
spec_file,
354+
kompiled_target_for,
355+
tmp_path,
356+
caplog,
357+
no_use_booster,
358+
use_booster_dev,
359+
bug_report=bug_report,
360+
spec_name=spec_name,
361+
workers=8,
362+
)
266363

267-
# Given
268-
log_file = tmp_path / 'log.txt'
269-
use_directory = tmp_path / 'kprove'
270-
use_directory.mkdir()
271364

272-
# When
273-
try:
274-
definition_dir = kompiled_target_for(spec_file)
275-
name = str(spec_file.relative_to(SPEC_DIR))
276-
break_on_calls = name in TEST_PARAMS and TEST_PARAMS[name].break_on_calls
277-
break_on_basic_blocks = name in TEST_PARAMS and TEST_PARAMS[name].break_on_basic_blocks
278-
workers = 1 if name not in TEST_PARAMS else TEST_PARAMS[name].workers
279-
options = ProveOptions(
280-
{
281-
'spec_file': spec_file,
282-
'definition_dir': definition_dir,
283-
'includes': [str(include_dir) for include_dir in config.INCLUDE_DIRS],
284-
'save_directory': use_directory,
285-
'md_selector': 'foo', # TODO Ignored flag, this is to avoid KeyError
286-
'use_booster': not no_use_booster,
287-
'use_booster_dev': use_booster_dev,
288-
'bug_report': bug_report,
289-
'break_on_calls': break_on_calls,
290-
'break_on_basic_blocks': break_on_basic_blocks,
291-
'workers': workers,
292-
}
293-
)
294-
exec_prove(options=options)
295-
if name in TEST_PARAMS:
296-
params = TEST_PARAMS[name]
297-
if params.leaf_number is not None and params.main_claim_id is not None:
298-
apr_proof = APRProof.read_proof_data(
299-
proof_dir=use_directory,
300-
id=params.main_claim_id,
301-
)
302-
expected_leaf_number = params.leaf_number
303-
actual_leaf_number = leaf_number(apr_proof)
304-
assert expected_leaf_number == actual_leaf_number
305-
except BaseException:
306-
raise
307-
finally:
308-
log_file.write_text(caplog.text)
365+
def test_prove_dss(
366+
kompiled_target_for: Callable[[Path], Path],
367+
tmp_path: Path,
368+
caplog: LogCaptureFixture,
369+
bug_report: BugReport | None,
370+
) -> None:
371+
spec_file = REPO_ROOT / 'tests/specs/mcd/vat-spec.k'
372+
_test_prove(
373+
spec_file,
374+
kompiled_target_for,
375+
tmp_path,
376+
caplog,
377+
False,
378+
False,
379+
bug_report=bug_report,
380+
spec_name=None,
381+
workers=8,
382+
direct_subproof_rules=True,
383+
)
309384

310385

311386
def test_prove_optimizations(
@@ -355,45 +430,3 @@ def _get_optimization_proofs() -> list[APRProof]:
355430
proof_display = '\n'.join(' ' + line for line in proof_show.show(proof))
356431
_LOGGER.info(f'Proof {proof.id}:\n{proof_display}')
357432
assert proof.passed
358-
359-
360-
def test_prove_dss(
361-
kompiled_target_for: Callable[[Path], Path],
362-
tmp_path: Path,
363-
caplog: LogCaptureFixture,
364-
bug_report: BugReport | None,
365-
spec_name: str | None,
366-
) -> None:
367-
spec_file = Path('../tests/specs/mcd/vat-spec.k')
368-
caplog.set_level(logging.INFO)
369-
370-
if spec_name is not None and str(spec_file).find(spec_name) < 0:
371-
pytest.skip()
372-
373-
# Given
374-
log_file = tmp_path / 'log.txt'
375-
use_directory = tmp_path / 'kprove'
376-
use_directory.mkdir()
377-
378-
# When
379-
try:
380-
definition_dir = kompiled_target_for(spec_file)
381-
options = ProveOptions(
382-
{
383-
'spec_file': spec_file,
384-
'definition_dir': definition_dir,
385-
'includes': [str(include_dir) for include_dir in config.INCLUDE_DIRS],
386-
'save_directory': use_directory,
387-
'md_selector': 'foo', # TODO Ignored flag, this is to avoid KeyError
388-
'use_booster': True,
389-
'bug_report': bug_report,
390-
'break_on_calls': False,
391-
'workers': 8,
392-
'direct_subproof_rules': True,
393-
}
394-
)
395-
exec_prove(options=options)
396-
except BaseException:
397-
raise
398-
finally:
399-
log_file.write_text(caplog.text)

package/version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.0.623
1+
1.0.624

0 commit comments

Comments
 (0)