File size: 7,596 Bytes
3d7ae13
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# algoforge_prime/core/safe_executor.py
# WARNING: THIS IS A SIMULATED SAFE EXECUTOR. DO NOT USE FOR REAL UNTRUSTED CODE.
# A real implementation would require robust sandboxing (Docker, nsjail, Firecracker, WASM, etc.)
# This simulation is purely for demonstrating the application flow.

import time
import random
import traceback

class ExecutionResult:
    def __init__(self, success: bool, output: str = None, error: str = None, execution_time: float = 0.0, passed_tests: int = 0, total_tests: int = 0):
        self.success = success          # True if code ran without crashing (not necessarily if tests passed)
        self.output = output            # Stdout from the execution
        self.error = error              # Stderr or exception message
        self.execution_time = execution_time
        self.passed_tests = passed_tests  # Number of 'assert' statements that passed
        self.total_tests = total_tests    # Total 'assert' statements found and attempted

    def __str__(self):
        if self.success:
            test_summary = f"Tests: {self.passed_tests}/{self.total_tests} passed. " if self.total_tests > 0 else ""
            return f"Execution OK. {test_summary}Time: {self.execution_time:.4f}s. Output: {str(self.output)[:200]}"
        else:
            return f"Execution FAILED. Error: {str(self.error)[:300]}. Time: {self.execution_time:.4f}s"

def execute_python_code_with_tests(code_string: str, tests_string: str, timeout_seconds: int = 5) -> ExecutionResult:
    """
    SIMULATES sandboxed execution of Python code against a set of assert-based tests.
    In a real system, this function would be a complex interface to a secure sandbox.
    """
    print(f"SIMULATOR: Attempting to 'execute' code with tests. Timeout: {timeout_seconds}s")
    start_time = time.time()

    if not code_string.strip():
        return ExecutionResult(success=False, error="No code provided to execute.", execution_time=time.time() - start_time)

    # Basic simulation:
    # 1. Check for obvious syntax issues (very naive)
    if "def " not in code_string and "class " not in code_string and not any(op in code_string for op in ["=", "+", "-", "*", "/"]):
         # If it doesn't look like defining something or doing operations, maybe it's just a malformed snippet
        if len(code_string) < 50 and "print" not in code_string : # very arbitrary
            return ExecutionResult(success=False, error="Simulated: Code appears incomplete or malformed for execution.", execution_time=time.time()-start_time)


    # 2. Simulate test parsing and execution
    test_lines = [line.strip() for line in tests_string.splitlines() if line.strip().startswith("assert")]
    total_tests = len(test_lines)
    passed_tests = 0
    simulated_stdout = []
    simulated_stderr = None

    if total_tests == 0 and tests_string.strip(): # If tests were provided but no asserts found
        simulated_stderr = "Simulated: Test string provided, but no 'assert' statements found."
        # We can still "run" the code itself without asserts
    
    # Simulate code "running"
    try:
        if "loop forever" in code_string.lower() or "while True:" in code_string and "break" not in code_string: # Timeout simulation
            time.sleep(timeout_seconds + 0.1) # Exceed timeout
            raise TimeoutError("Simulated: Code execution timed out.")
        
        # Simulate print statements
        if "print('hello world')" in code_string:
            simulated_stdout.append("hello world")
        if "print(1+1)" in code_string:
            simulated_stdout.append("2")

        # Simulate errors
        if "1/0" in code_string or "zerodivisionerror" in code_string:
            raise ZeroDivisionError("Simulated: division by zero")
        if "undefined_variable" in code_string:
            raise NameError("Simulated: name 'undefined_variable' is not defined")

        # Simulate test passing/failing (very naively)
        if total_tests > 0:
            for i, test_line in enumerate(test_lines):
                # This is extremely basic and not real evaluation.
                # A real system would execute each assert in the context of the provided code.
                if "==" in test_line:
                    if "True" in test_line or "120" in test_line or "correct" in test_line.lower(): # Naive pass conditions
                        if random.random() > 0.1: # 90% chance of passing "good" tests
                            passed_tests += 1
                            simulated_stdout.append(f"Simulated Test {i+1} ({test_line[:30]}...): PASSED")
                        else:
                            simulated_stdout.append(f"Simulated Test {i+1} ({test_line[:30]}...): FAILED (Random Sim)")
                            if not simulated_stderr: simulated_stderr = f"Simulated: Assertion failed on test {i+1}"
                    elif "False" in test_line or "wrong" in test_line.lower(): # Naive fail conditions
                         if random.random() > 0.1: # 90% chance of failing "bad" tests
                            simulated_stdout.append(f"Simulated Test {i+1} ({test_line[:30]}...): FAILED (Expected by Sim)")
                            if not simulated_stderr: simulated_stderr = f"Simulated: Assertion failed on test {i+1} (Expected by Sim)"
                         else: # 10% chance of unexpectedly passing
                            passed_tests +=1
                            simulated_stdout.append(f"Simulated Test {i+1} ({test_line[:30]}...): PASSED (Unexpected by Sim)")
                    else: # Other asserts
                        if random.random() > 0.5: # 50/50
                            passed_tests += 1
                            simulated_stdout.append(f"Simulated Test {i+1} ({test_line[:30]}...): PASSED (Random Sim)")
                        else:
                            simulated_stdout.append(f"Simulated Test {i+1} ({test_line[:30]}...): FAILED (Random Sim)")
                            if not simulated_stderr: simulated_stderr = f"Simulated: Assertion failed on test {i+1} (Random Sim)"
                else: # Non-equality asserts, just pass some randomly
                    if random.random() > 0.3: passed_tests +=1
        
        # If no explicit error, but not all tests passed
        if total_tests > 0 and passed_tests < total_tests and not simulated_stderr:
            simulated_stderr = f"Simulated: {total_tests - passed_tests} out of {total_tests} assertions failed."

        execution_time = time.time() - start_time
        if execution_time > timeout_seconds: # Check after simulated work
            raise TimeoutError("Simulated: Code execution exceeded timeout.")

        return ExecutionResult(
            success=True if not simulated_stderr or (total_tests > 0 and passed_tests == total_tests) else False, # Success if no errors or all tests pass
            output="\n".join(simulated_stdout) if simulated_stdout else None,
            error=simulated_stderr,
            execution_time=execution_time,
            passed_tests=passed_tests,
            total_tests=total_tests
        )

    except Exception as e:
        execution_time = time.time() - start_time
        tb_str = traceback.format_exc()
        print(f"SIMULATOR EXCEPTION: {e}\n{tb_str}")
        return ExecutionResult(
            success=False,
            error=f"Simulated Exception: {type(e).__name__} - {str(e)}",
            execution_time=execution_time,
            passed_tests=passed_tests, # Could be some if error happened mid-tests
            total_tests=total_tests
        )