Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CBMC proof-running GitHub Action #137

Merged
merged 1 commit into from
Mar 3, 2023
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
13 changes: 13 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,16 @@ jobs:
with:
config: .github/memory_statistics_config.json
check_against: docs/doxygen/include/size_table.md
proof_ci:
runs-on: cbmc_ubuntu-latest_64-core
steps:
- name: Set up CBMC runner
uses: FreeRTOS/CI-CD-Github-Actions/set_up_cbmc_runner@main
with:
cbmc_version: "5.73.0"
cadical_tag: "latest"
kissat_tag: "latest"
- name: Run CBMC
uses: FreeRTOS/CI-CD-Github-Actions/run_cbmc@main
with:
proofs_dir: test/cbmc/proofs
74 changes: 74 additions & 0 deletions test/cbmc/proofs/lib/print_tool_versions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#!/usr/bin/env python3
#
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0


import logging
import pathlib
import shutil
import subprocess


_TOOLS = [
"cadical",
"cbmc",
"cbmc-viewer",
"cbmc-starter-kit-update",
"kissat",
"litani",
]


def _format_versions(table):
lines = [
"<table>",
'<tr><td colspan="2" style="font-weight: bold">Tool Versions</td></tr>',
]
for tool, version in table.items():
if version:
v_str = f'<code><pre style="margin: 0">{version}</pre></code>'
else:
v_str = '<em>not found</em>'
lines.append(
f'<tr><td style="font-weight: bold; padding-right: 1em; '
f'text-align: right;">{tool}:</td>'
f'<td>{v_str}</td></tr>')
lines.append("</table>")
return "\n".join(lines)


def _get_tool_versions():
ret = {}
for tool in _TOOLS:
err = f"Could not determine version of {tool}: "
ret[tool] = None
if not shutil.which(tool):
logging.error("%s'%s' not found on $PATH", err, tool)
continue
cmd = [tool, "--version"]
proc = subprocess.Popen(cmd, text=True, stdout=subprocess.PIPE)
try:
out, _ = proc.communicate(timeout=10)
except subprocess.TimeoutExpired:
logging.error("%s'%s --version' timed out", err, tool)
continue
if proc.returncode:
logging.error(
"%s'%s --version' returned %s", err, tool, str(proc.returncode))
continue
ret[tool] = out.strip()
return ret


def main():
exe_name = pathlib.Path(__file__).name
logging.basicConfig(format=f"{exe_name}: %(message)s")

table = _get_tool_versions()
out = _format_versions(table)
print(out)


if __name__ == "__main__":
main()
50 changes: 37 additions & 13 deletions test/cbmc/proofs/lib/summarize.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import argparse
import json
import logging
import os
import sys


DESCRIPTION = """Print 2 tables in GitHub-flavored Markdown that summarize
Expand Down Expand Up @@ -89,8 +91,9 @@ def _get_status_and_proof_summaries(run_dict):
count_statuses[status_pretty_name] += 1
except KeyError:
count_statuses[status_pretty_name] = 1
proof = proof_pipeline["name"]
proofs.append([proof, status_pretty_name])
if proof_pipeline["name"] == "print_tool_versions":
continue
proofs.append([proof_pipeline["name"], status_pretty_name])
statuses = [["Status", "Count"]]
for status, count in count_statuses.items():
statuses.append([status, str(count)])
Expand All @@ -102,18 +105,39 @@ def print_proof_results(out_file):
Print 2 strings that summarize the proof results.
When printing, each string will render as a GitHub flavored Markdown table.
"""
print("## Summary of CBMC proof results")
try:
with open(out_file, encoding='utf-8') as run_json:
run_dict = json.load(run_json)
summaries = _get_status_and_proof_summaries(
run_dict)
for summary in summaries:
print(_get_rendered_table(summary))
except Exception as ex: # pylint: disable=broad-except
logging.critical("Could not print results. Exception: %s", str(ex))
output = "## Summary of CBMC proof results\n\n"
with open(out_file, encoding='utf-8') as run_json:
run_dict = json.load(run_json)
status_table, proof_table = _get_status_and_proof_summaries(run_dict)
for summary in (status_table, proof_table):
output += _get_rendered_table(summary)

print(output)
sys.stdout.flush()

github_summary_file = os.getenv("GITHUB_STEP_SUMMARY")
if github_summary_file:
with open(github_summary_file, "a") as handle:
print(output, file=handle)
handle.flush()
else:
logging.warning(
"$GITHUB_STEP_SUMMARY not set, not writing summary file")

msg = (
"Click the 'Summary' button to view a Markdown table "
"summarizing all proof results")
if run_dict["status"] != "success":
logging.error("Not all proofs passed.")
logging.error(msg)
sys.exit(1)
logging.info(msg)


if __name__ == '__main__':
args = get_args()
print_proof_results(args.run_file)
logging.basicConfig(format="%(levelname)s: %(message)s")
try:
print_proof_results(args.run_file)
except Exception as ex: # pylint: disable=broad-except
logging.critical("Could not print results. Exception: %s", str(ex))
18 changes: 0 additions & 18 deletions test/cbmc/proofs/run-cbmc-proofs.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,22 +334,6 @@ async def configure_proof_dirs( # pylint: disable=too-many-arguments
queue.task_done()


def add_tool_version_job():
cmd = [
"litani", "add-job",
"--command", "cbmc-starter-kit-print-tool-versions .",
"--description", "printing out tool versions",
"--phony-outputs", str(uuid.uuid4()),
"--pipeline-name", "print_tool_versions",
"--ci-stage", "report",
"--tags", "front-page-text",
]
proc = subprocess.run(cmd)
if proc.returncode:
logging.critical("Could not add tool version printing job")
sys.exit(1)


async def main(): # pylint: disable=too-many-locals
args = get_args()
set_up_logging(args.verbose)
Expand Down Expand Up @@ -419,8 +403,6 @@ async def main(): # pylint: disable=too-many-locals

await proof_queue.join()

add_tool_version_job()

print_counter(counter)
print("", file=sys.stderr)

Expand Down