[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/ASSERT-KTH/Vecogen/main/python_modules/testing/test_function.py [Back]  [Original]

import os
import subprocess
import json

def execute_command_with_timeout(command, timeout):
    """
    Executes a shell command with a specified timeout.
    
    Parameters:
    - command: list or str, the command to execute.
    - timeout: int or float, the timeout duration in seconds.
    
    Returns:
    - stdout: str, the standard output from the command.
    - stderr: str, the standard error from the command.
    - returncode: int, the return code from the command execution.
    
    Raises:
    - subprocess.TimeoutExpired: if the command execution exceeds the timeout.
    - subprocess.CalledProcessError: if the command exits with a non-zero status.
    - Exception: for any other exceptions that occur.
    """
    try:
        # Execute the command with the specified timeout
        result = subprocess.run(
            command,
            check=True,                # Raises CalledProcessError if return code is non-zero
            capture_output=True,       # Captures stdout and stderr
            text=True,                 # Returns output as text strings
            stdin=subprocess.DEVNULL,  # Prevents the subprocess from waiting for input
            timeout=timeout            # Timeout for the command execution
        )
        # Return the output and return code
        return result.stdout, result.stderr, result.returncode

    except subprocess.TimeoutExpired as e:
        print(f"Command '{e.cmd}' timed out after {timeout} seconds.")
        # Re-raise the exception if you want the calling code to handle it
        raise

    except subprocess.CalledProcessError as e:
        print(f"Command '{e.cmd}' exited with non-zero status {e.returncode}.")
        print(f"Standard Error Output:\n{e.stderr}")
        # Re-raise the exception if you want the calling code to handle it
        raise

    except Exception as e:
        print(f"An unexpected error occurred: {e}")
        # Re-raise the exception if you want the calling code to handle it
        raise

def test_generated_code(path_file, path_test, test_file_name, output_path, debug):
    """ Function that tests a generated file
    Args:
        path_file: The path to the generated file
        path_test: The path to the test file
        test_file_name: The name of the test executable
        output_path: The directory where the executable and output will be placed
        debug: Boolean flag for printing debug information
    Returns:
        passed: The number of tests that passed
        total: The total number of tests
        tests_output: The output from the tests, typically a summary dictionary
    """

    # If debugging is true then print information that the file will be tested
    if debug:
        print(f"Testing the file {path_file}\n      using the test file {path_test}")

    # Normalize paths
    path_file = os.path.normpath(path_file)
    path_test = os.path.normpath(path_test)

    # Create the output directory if it does not exist
    if not os.path.exists(output_path):
        os.makedirs(output_path)

    path_to_executable = os.path.normpath(os.path.join(output_path, test_file_name))

    # Compile the file and the test cases
    command = [
        "gcc",
        path_file,
        path_test,
        "-o",
        path_to_executable
    ]

    try:
        # Use the execute_command_with_timeout function
        stdout, stderr, returncode = execute_command_with_timeout(command, timeout=120)
        if debug:
            print("Compilation output:", stdout)
    except subprocess.TimeoutExpired as e:
        print("Compilation timed out!")
        return 0, 0, {"summary": {"passed": 0, "failed": 0, "total": 0, "information": f"Compilation timed out: {str(e)}"}}
    except subprocess.CalledProcessError as e:
        print("Compilation failed!")
        print(e.stderr)
        return 0, 0, {"summary": {"passed": 0, "failed": 0, "total": 0, "information": f"Compilation failed: {e.stderr}"}}
    except Exception as e:
        print(f"An unexpected error occurred during compilation: {e}")
        return 0, 0, {"summary": {"passed": 0, "failed": 0, "total": 0, "information": f"Compilation error: {str(e)}"}}

    # Run the test cases
    command = [path_to_executable, f"{path_to_executable}.json"]
    try:
        # Use the execute_command_with_timeout function
        stdout, stderr, returncode = execute_command_with_timeout(command, timeout=1200)
        if stderr:
            print("Test execution failed!")
            print(stderr)
    except subprocess.TimeoutExpired as e:
        return 0, 0, {"summary": {"passed": 0, "failed": 0, "total": 0, "information": f"Test execution timed out: {str(e)}"}}
    except subprocess.CalledProcessError as e:
        return 0, 0, {"summary": {"passed": 0, "failed": 0, "total": 0, "information": f"Test execution failed: {e.stderr}"}}
    except OSError as e:
        print(f"Error: The test cases could not be run. {str(e)}")
        return 0, 0, {"summary": {"passed": 0, "failed": 0, "total": 0, "information": f"Execution error: {str(e)}"}}
    except Exception as e:
        print(f"An unexpected error occurred during test execution: {e}")
        return 0, 0, {"summary": {"passed": 0, "failed": 0, "total": 0, "information": f"Execution error: {str(e)}"}}

    # Verify the JSON file existence
    json_file_path = path_to_executable + ".json"
    if not os.path.exists(json_file_path):
        print(f"Error: The output JSON file '{json_file_path}' was not created.")
        return 0, 0, {"summary": {"passed": 0, "failed": 0, "total": 0, "information": "Output JSON file missing."}}

    # Read the output JSON file
    try:
        with open(json_file_path, "r", encoding="utf-8") as file:
            tests_output = json.load(file)
            test_information = tests_output[-1]['summary']
            passed = test_information['passed']
            total = test_information['total']
    except (json.JSONDecodeError, KeyError, IndexError) as e:
        print(f"Error reading JSON file: {str(e)}")
        return 0, 0, {"summary": {"passed": 0, "failed": 0, "total": 0, "information": "Invalid JSON format."}}

    # Clean up
    try:
        os.remove(path_to_executable)
        os.remove(json_file_path)
    except OSError as e:
        print(f"Error during cleanup: {str(e)}")

    return passed, total, tests_output

Web Proxy Viewer  |  New URL  |  Original Page