From fac704270a2ecf8101cc5b85281936f766ff22f4 Mon Sep 17 00:00:00 2001 From: bohendo Date: Fri, 16 Feb 2024 17:26:11 -0500 Subject: [PATCH] log output if tests fail before mutating --- slither/tools/mutator/__main__.py | 7 ++++--- .../tools/mutator/utils/testing_generated_mutant.py | 12 +++++++++--- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index 38d54bbd1..f02b84f53 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -163,7 +163,7 @@ def main() -> (None): # pylint: disable=too-many-statements,too-many-branches,t contract_names: Optional[List[str]] = args.contract_names comprehensive_flag: Optional[bool] = args.comprehensive - logger.info(blue(f"Starting Mutation Campaign in '{args.codebase}")) + logger.info(blue(f"Starting mutation campaign in {args.codebase}")) if paths_to_ignore: paths_to_ignore_list = paths_to_ignore.strip("][").split(",") @@ -200,8 +200,9 @@ def main() -> (None): # pylint: disable=too-many-statements,too-many-branches,t # run and time tests, abort if they're broken start_time = time.time() - if not run_test_cmd(test_command, None, None): # no timeout or target_file during the first run - logger.error(red("Test suite fails before mutation, aborting")) + # no timeout or target_file during the first run, but be verbose on failure + if not run_test_cmd(test_command, None, None, True): + logger.error(red("Test suite fails with mutations, aborting")) return elapsed_time = round(time.time() - start_time) diff --git a/slither/tools/mutator/utils/testing_generated_mutant.py b/slither/tools/mutator/utils/testing_generated_mutant.py index bc1562681..09094df08 100644 --- a/slither/tools/mutator/utils/testing_generated_mutant.py +++ b/slither/tools/mutator/utils/testing_generated_mutant.py @@ -21,7 +21,7 @@ def compile_generated_mutant(file_path: str, mappings: str) -> bool: return False -def run_test_cmd(cmd: str, timeout: int | None, target_file: str | None) -> bool: +def run_test_cmd(cmd: str, timeout: int | None, target_file: str | None, verbose: bool) -> bool: """ function to run codebase tests returns: boolean whether the tests passed or not @@ -64,7 +64,13 @@ def run_test_cmd(cmd: str, timeout: int | None, target_file: str | None) -> bool # if result is 0 then it is an uncaught mutant because tests didn't fail if result: code = result.returncode - return code == 0 + if code == 0: + return True + + # If tests fail in verbose-mode, print both stdout and stderr for easier debugging + if verbose: + logger.info(yellow(result.stdout.decode('utf-8'))) + logger.info(red(result.stderr.decode('utf-8'))) return False @@ -92,7 +98,7 @@ def test_patch( # pylint: disable=too-many-arguments with open(file, "w", encoding="utf-8") as filepath: filepath.write(replaced_content) if compile_generated_mutant(file, mappings): - if run_test_cmd(command, timeout, file): + if run_test_cmd(command, timeout, file, False): create_mutant_file(file, generator_name) logger.info( red(