From 90964e55b07362e819d8dc73650864b7ed99ccec Mon Sep 17 00:00:00 2001 From: Nikhil Parasaram Date: Sun, 7 Aug 2022 08:33:27 +0100 Subject: [PATCH] Add exit code (#1662) * Add exit code * Fix tests --- mythril/interfaces/cli.py | 4 ++++ tests/cmd_line_test.py | 7 +++++-- tests/integration_tests/analysis_tests.py | 4 ++-- tests/integration_tests/test_safe_functions.py | 7 ++++--- tests/integration_tests/test_src_mapping.py | 5 +++-- tests/integration_tests/utils.py | 13 +++++++++++++ tests/integration_tests/version_test.py | 4 ++-- 7 files changed, 33 insertions(+), 11 deletions(-) create mode 100644 tests/integration_tests/utils.py diff --git a/mythril/interfaces/cli.py b/mythril/interfaces/cli.py index d2c12565..7d625f8b 100644 --- a/mythril/interfaces/cli.py +++ b/mythril/interfaces/cli.py @@ -835,6 +835,10 @@ def execute_command( "markdown": report.as_markdown(), } print(outputs[args.outform]) + if len(report.issues) > 0: + exit(1) + else: + exit(0) except DetectorNotFoundError as e: exit_with_error(args.outform, format(e)) except CriticalError as e: diff --git a/tests/cmd_line_test.py b/tests/cmd_line_test.py index 749c59be..b534947f 100644 --- a/tests/cmd_line_test.py +++ b/tests/cmd_line_test.py @@ -1,4 +1,4 @@ -from subprocess import check_output +from subprocess import check_output, CalledProcessError from tests import BaseTestCase, TESTDATA, PROJECT_DIR, TESTS_DIR from mock import patch @@ -11,7 +11,10 @@ def output_of(command): :param command: :return: """ - return check_output(command, shell=True).decode("UTF-8") + try: + return check_output(command, shell=True).decode("UTF-8") + except CalledProcessError as exc: + return exc.output.decode("UTF-8") class CommandLineToolTestCase(BaseTestCase): diff --git a/tests/integration_tests/analysis_tests.py b/tests/integration_tests/analysis_tests.py index e93fae6c..08854ff3 100644 --- a/tests/integration_tests/analysis_tests.py +++ b/tests/integration_tests/analysis_tests.py @@ -2,7 +2,7 @@ import pytest import json import sys -from subprocess import check_output +from utils import output_of from tests import PROJECT_DIR, TESTDATA MYTH = str(PROJECT_DIR / "myth") @@ -47,7 +47,7 @@ test_data = ( def test_analysis(file_name, tx_data, calldata): bytecode_file = str(TESTDATA / "inputs" / file_name) command = f"""python3 {MYTH} analyze -f {bytecode_file} -t {tx_data["TX_COUNT"]} -o jsonv2 -m {tx_data["MODULE"]} --solver-timeout 60000""" - output = json.loads(check_output(command, shell=True).decode("UTF-8")) + output = json.loads(output_of(command)) assert len(output[0]["issues"]) == tx_data["ISSUE_COUNT"] if calldata: diff --git a/tests/integration_tests/test_safe_functions.py b/tests/integration_tests/test_safe_functions.py index bc184c8e..eabfd179 100644 --- a/tests/integration_tests/test_safe_functions.py +++ b/tests/integration_tests/test_safe_functions.py @@ -2,9 +2,10 @@ import pytest import json import sys -from subprocess import check_output +from utils import output_of from tests import PROJECT_DIR, TESTDATA + MYTH = str(PROJECT_DIR / "myth") test_data = ( ("suicide.sol", [], "0.5.0"), @@ -36,7 +37,7 @@ bytes_test_data = ( def test_analysis(file_name, safe_funcs, version): file = str(TESTDATA / "input_contracts" / file_name) command = f"python3 {MYTH} safe-functions {file} --solv {version}" - output = check_output(command, shell=True).decode("UTF-8") + output = output_of(command) assert f"{len(safe_funcs)} functions are deemed safe in this contract" in output for func in safe_funcs: assert func in output @@ -46,5 +47,5 @@ def test_analysis(file_name, safe_funcs, version): def test_bytecode_analysis(file_name, safe_funcs): file = str(TESTDATA / "inputs" / file_name) command = f"python3 {MYTH} safe-functions --bin-runtime -f {file}" - output = check_output(command, shell=True).decode("UTF-8") + output = output_of(command) assert f"{len(safe_funcs)} functions are deemed safe in this contract" in output diff --git a/tests/integration_tests/test_src_mapping.py b/tests/integration_tests/test_src_mapping.py index a11dc6b5..57186ec8 100644 --- a/tests/integration_tests/test_src_mapping.py +++ b/tests/integration_tests/test_src_mapping.py @@ -2,8 +2,9 @@ import pytest import json import sys -from subprocess import check_output, STDOUT +from subprocess import STDOUT from tests import PROJECT_DIR, TESTDATA +from utils import output_of MYTH = str(PROJECT_DIR / "myth") @@ -12,5 +13,5 @@ def test_positive_solc_settings(): file_path = str(TESTDATA / "input_contracts" / "destruct_crlf.sol") command = f"python3 {MYTH} analyze {file_path} --solv 0.5.0" - output = check_output(command, shell=True, stderr=STDOUT).decode("UTF-8") + output = output_of(command, stderr=STDOUT) assert "selfdestruct(addr)" in output diff --git a/tests/integration_tests/utils.py b/tests/integration_tests/utils.py new file mode 100644 index 00000000..a4bf28b4 --- /dev/null +++ b/tests/integration_tests/utils.py @@ -0,0 +1,13 @@ +from subprocess import check_output, CalledProcessError + + +def output_of(command, stderr=None): + """ + + :param command: + :return: + """ + try: + return check_output(command, shell=True, stderr=stderr).decode("UTF-8") + except CalledProcessError as exc: + return exc.output.decode("UTF-8") diff --git a/tests/integration_tests/version_test.py b/tests/integration_tests/version_test.py index 73d316ab..a33ee8f8 100644 --- a/tests/integration_tests/version_test.py +++ b/tests/integration_tests/version_test.py @@ -2,8 +2,8 @@ import pytest import json import sys -from subprocess import check_output from tests import PROJECT_DIR, TESTDATA +from utils import output_of MYTH = str(PROJECT_DIR / "myth") test_data = ( @@ -23,7 +23,7 @@ def test_analysis(file_name, version, has_overflow): command = f"python3 {MYTH} analyze {file} --solv {version}" else: command = f"python3 {MYTH} analyze {file}" - output = check_output(command, shell=True).decode("UTF-8") + output = output_of(command) if has_overflow: assert f"SWC ID: 101" in output else: