import os
import time
import undetected_chromedriver as uc

# Get the directory of the current script
script_dir = os.path.dirname(os.path.abspath(__file__))

# Construct the relative path to the chromedriver
chromedriver_path = os.path.join(script_dir, "chromedriver-win64", "chromedriver.exe")

options = uc.ChromeOptions()
options.binary_location = chromedriver_path
print("wde")
with uc.Chrome(use_subprocess=True, options=options) as driver:
    print("wde")
    driver.get("https://lmarena.ai/")
    print("wde")
    # create an instance of ChromeOptions for undetected_chromedriver
    # initialize the undetected Chrome driver with specified options
    time.sleep(10)
import time

options = uc.ChromeOptions()
options.binary_location = (
    r"C:\Programming\Test\IP_Test\chromedriver-win64\chromedriver.exe"
)
print("wde")
with uc.Chrome(use_subprocess=True, options=options) as driver:
    print("wde")
    driver.get("https://lmarena.ai/")
    print("wde")
    # create an instance of ChromeOptions for undetected_chromedriver
    # initialize the undetected Chrome driver with specified options
    time.sleep(10)

Instruction: (venv) PS C:\Programming\Test\IP_Test> & c:/Programming/Test/IP_Test/venv/Scripts/python.exe c:/Programming/Test/IP_Test/test_site.py wde Traceback (most recent call last):   File "c:\Programming\Test\IP_Test\test_site.py", line 9, in <module>     with uc.Chrome(use_subprocess=True, options=options) as driver:          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^   File "C:\Programming\Test\IP_Test\venv\Lib\site-packages\undetected_chromedriver\__init__.py", line 466, in __init__     super(Chrome, self).__init__(   File "C:\Programming\Test\IP_Test\venv\Lib\site-packages\selenium\webdriver\chrome\webdriver.py", line 45, in __init__     super().__init__(   File "C:\Programming\Test\IP_Test\venv\Lib\site-packages\selenium\webdriver\chromium\webdriver.py", line 66, in __init__     super().__init__(command_executor=executor, options=options)   File "C:\Programming\Test\IP_Test\venv\Lib\site-packages\selenium\webdriver\remote\webdriver.py", line 238, in __init__     self.start_session(capabilities)   File "C:\Programming\Test\IP_Test\venv\Lib\site-packages\undetected_chromedriver\__init__.py", line 724, in start_session     super(selenium.webdriver.chrome.webdriver.WebDriver, self).start_session(   File "C:\Programming\Test\IP_Test\venv\Lib\site-packages\selenium\webdriver\remote\webdriver.py", line 325, in start_session     response = self.execute(Command.NEW_SESSION, caps)["value"]                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^   File "C:\Programming\Test\IP_Test\venv\Lib\site-packages\selenium\webdriver\remote\webdriver.py", line 380, in execute     self.error_handler.check_response(response)   File "C:\Programming\Test\IP_Test\venv\Lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 229, in check_response     raise exception_class(message, screen, stacktrace) selenium.common.exceptions.SessionNotCreatedException: Message: session not created: cannot connect to chrome at 127.0.0.1:50974 from chrome not reachable Stacktrace:         GetHandleVerifier [0x00425093+25075]         (No symbol) [0x003AE124]         (No symbol) [0x0028BCD9]         (No symbol) [0x002807CC]         (No symbol) [0x002C06F6]         (No symbol) [0x002B71EF]         (No symbol) [0x002B7037]         (No symbol) [0x002FB44F]         (No symbol) [0x002FAC1A]         (No symbol) [0x002F1C16]         (No symbol) [0x002C3F3C]         (No symbol) [0x002C4ECD]         GetHandleVerifier [0x00712523+3094147]         GetHandleVerifier [0x00725754+3172532]         GetHandleVerifier [0x0071DF32+3141778]         GetHandleVerifier [0x004C2100+668256]         (No symbol) [0x003B6C4D]         (No symbol) [0x003B3DF8]         (No symbol) [0x003B3F95]         (No symbol) [0x003A6C80]         BaseThreadInitThunk [0x76F9FCC9+25]         RtlGetAppContainerNamedObjectPath [0x7729809E+286]         RtlGetAppContainerNamedObjectPath [0x7729806E+238]  Exception ignored in: <function Chrome.__del__ at 0x0000028810223BA0> Traceback (most recent call last):   File "C:\Programming\Test\IP_Test\venv\Lib\site-packages\undetected_chromedriver\__init__.py", line 843, in __del__   File "C:\Programming\Test\IP_Test\venv\Lib\site-packages\undetected_chromedriver\__init__.py", line 798, in quit OSError: [WinError 6] Неверный дескриптор

import pytest
import os
import sys
import re
import importlib.util
from unittest.mock import patch, MagicMock
import inspect

@pytest.fixture
def mock_uc_chrome():
    """Mock for undetected_chromedriver.Chrome to avoid actual browser operations."""
    # Create a more complete mock that can be used in context managers
    chrome_mock = MagicMock()
    driver_mock = MagicMock()
    chrome_mock.return_value.__enter__.return_value = driver_mock
    chrome_mock.return_value.__exit__.return_value = None

    # Create a mock module with Chrome class
    uc_module_mock = MagicMock()
    uc_module_mock.Chrome = chrome_mock
    uc_module_mock.ChromeOptions = MagicMock

    with patch.dict('sys.modules', {'undetected_chromedriver': uc_module_mock}):
        yield chrome_mock

def test_import_undetected_chromedriver(implementation):
    """Test that undetected_chromedriver is properly imported."""
    impl_name, module = implementation
    source_code = inspect.getsource(module)
    assert "import undetected_chromedriver" in source_code or "import undetected_chromedriver as uc" in source_code, \
        f"Implementation {impl_name} should import undetected_chromedriver"

def test_chrome_initialization_params(implementation):
    """Test that Chrome is initialized with the correct parameters."""
    impl_name, module = implementation
    source_code = inspect.getsource(module)

    # More comprehensive patterns to capture different initialization styles
    chrome_init_patterns = [
        # Match explicit driver_executable_path parameter
        r"uc\.Chrome\(.*?driver_executable_path\s*=\s*.*?(chromedriver|path).*?\)",
        # Match explicit executable_path parameter
        r"uc\.Chrome\(.*?executable_path\s*=\s*.*?(chromedriver|path).*?\)",
        # Match any Chrome initialization that includes chromedriver path
        r"uc\.Chrome\(.*?[\"'](.*chromedriver.*)[\"'].*?\)",
        # Match any variable that contains chromedriver in its name passed to Chrome
        r"chromedriver_path.*?\n.*?uc\.Chrome\(.*?=[^=]*?chromedriver_path.*?\)",
        # Match a variable with "driver" in its name being passed to Chrome
        r"(driver.*?path|chrome_driver_path).*?\n.*?uc\.Chrome\(.*?=.*?(driver.*?path|chrome_driver_path)",
        # Match Chrome initialization with any path parameter
        r"uc\.Chrome\(.*?(executable_path|driver_executable_path|driver_path)\s*="
    ]

    # At least one of the patterns should match
    has_proper_init = any(re.search(pattern, source_code, re.DOTALL) for pattern in chrome_init_patterns)

    assert has_proper_init, \
        f"Implementation {impl_name} should properly initialize Chrome with chromedriver path"

def test_binary_location_setting(implementation):
    """Test that binary_location is properly used or not incorrectly set to chromedriver path."""
    impl_name, module = implementation
    source_code = inspect.getsource(module)

    # First, check if there are any active binary_location settings
    binary_location_pattern = r"options\.binary_location\s*=\s*"

    # Check for binary_location usage that isn't commented out
    lines = source_code.split('\n')
    incorrect_setting_lines = []

    for i, line in enumerate(lines):
        line_stripped = line.strip()

        # Skip empty lines or commented lines
        if not line_stripped or line_stripped.startswith('#') or line_stripped.startswith('//'):
            continue

        # Check if binary_location is being set to a chromedriver path
        if re.search(binary_location_pattern, line) and "chromedriver" in line:
            incorrect_setting_lines.append((i+1, line))

    assert len(incorrect_setting_lines) == 0, \
        f"Implementation {impl_name} incorrectly sets binary_location to chromedriver path on lines: {incorrect_setting_lines}. " \
        f"binary_location should point to the Chrome browser executable, not chromedriver."

def test_use_subprocess_parameter(implementation):
    """Test that the Chrome is initialized with use_subprocess=True."""
    impl_name, module = implementation
    source_code = inspect.getsource(module)

    assert "use_subprocess=True" in source_code, \
        f"Implementation {impl_name} should include use_subprocess=True parameter"

def test_exception_handling(implementation):
    """Test that exception handling is implemented."""
    impl_name, module = implementation
    source_code = inspect.getsource(module)

    # Check for try-except blocks using a regex pattern that's more specific
    try_except_pattern = r"try\s*:.*?except.*?:"
    has_error_handling = bool(re.search(try_except_pattern, source_code, re.DOTALL))

    # Handle both "except Exception as e:" and "except:" patterns
    if not has_error_handling:
        # Check line by line for both patterns
        lines = source_code.split('\n')
        has_try = False
        has_except = False

        for line in lines:
            line_stripped = line.strip()
            if line_stripped.startswith('try:'):
                has_try = True
            elif has_try and (line_stripped.startswith('except') or 'except ' in line_stripped):
                has_except = True
                break

        has_error_handling = has_try and has_except

    assert has_error_handling, \
        f"Implementation {impl_name} should include error handling with try-except blocks for better reliability"

def test_correct_structure_flow(implementation):
    """Test the overall structure and flow of the implementation."""
    impl_name, module = implementation
    source_code = inspect.getsource(module)

    # Check for essential elements in the structure
    has_options = re.search(r'options\s*=\s*(uc|undetected_chromedriver)\.ChromeOptions\(\)', source_code)
    has_chrome_init = re.search(r'(uc|undetected_chromedriver)\.Chrome\(', source_code)
    has_get_url = re.search(r'\.get\(["\']https?://.*?["\']\)', source_code)

    assert has_options, f"Implementation {impl_name} should create ChromeOptions"
    assert has_chrome_init, f"Implementation {impl_name} should initialize Chrome"
    assert has_get_url, f"Implementation {impl_name} should navigate to a URL with driver.get()"

def test_chrome_initialization_flow(implementation):
    """Test that the Chrome initialization and URL navigation follows correct order."""
    impl_name, module = implementation
    source_code = inspect.getsource(module)

    # This test is more suitable for structured code analysis rather than line-by-line
    # Instead of line numbers, check for initialization before navigation in code blocks

    # Extract all code blocks (context manager blocks or regular function blocks)
    code_blocks = re.findall(r'with\s+(uc|undetected_chromedriver)\.Chrome\(.*?\).*?as\s+driver:.*?driver\.get\(',
                             source_code, re.DOTALL)

    # If we don't find specific context manager blocks, look for any initialization followed by get
    if not code_blocks:
        # Check if Chrome is initialized first, then navigation occurs
        chrome_pos = source_code.find('.Chrome(')
        nav_pos = source_code.find('.get(')

        if chrome_pos >= 0 and nav_pos >= 0:
            assert chrome_pos < nav_pos, \
                f"Implementation {impl_name} should initialize Chrome before navigating to a URL"
        else:
            pytest.skip(f"Implementation {impl_name} structure couldn't be clearly determined for init/navigation flow")
    else:
        # If we found context manager blocks, they're already verifying correct order
        assert True

def test_chrome_options_configuration(implementation):
    """Test that Chrome options are properly configured."""
    impl_name, module = implementation
    source_code = inspect.getsource(module)

    # Check for Chrome options creation
    has_options_creation = re.search(r'options\s*=\s*(uc|undetected_chromedriver)\.ChromeOptions\(\)', source_code)

    assert has_options_creation, \
        f"Implementation {impl_name} should create a ChromeOptions object"

def test_context_manager_usage(implementation):
    """Test that the implementation uses a context manager (with statement) for Chrome."""
    impl_name, module = implementation
    source_code = inspect.getsource(module)

    # Look for context manager pattern with better pattern matching
    with_pattern = r'with\s+(uc|undetected_chromedriver)\.Chrome\('
    has_context_manager = bool(re.search(with_pattern, source_code))

    assert has_context_manager, \
        f"Implementation {impl_name} should use context manager (with statement) for proper resource management"

def test_no_redundant_code(implementation):
    """Test that the implementation doesn't have obviously redundant or duplicate code sections."""
    impl_name, module = implementation
    source_code = inspect.getsource(module)

    # Count Chrome initializations
    chrome_inits = re.findall(r'(uc|undetected_chromedriver)\.Chrome\(', source_code)

    # This is a soft test - flag if there are more than 2 initializations
    if len(chrome_inits) > 2:
        pytest.mark.xfail(reason=f"Implementation {impl_name} may contain redundant Chrome initialization code")

def test_proper_imports(implementation):
    """Test that necessary imports are included."""
    impl_name, module = implementation
    source_code = inspect.getsource(module)

    # Check for essential imports with more flexible pattern matching
    has_uc_import = re.search(r'import\s+undetected_chromedriver(\s+as\s+uc)?', source_code)
    has_os_import = re.search(r'import\s+os', source_code)

    assert has_uc_import, \
        f"Implementation {impl_name} must import undetected_chromedriver"

    # OS import is recommended but not strictly required
    if not has_os_import:
        pytest.mark.xfail(reason=f"Implementation {impl_name} is missing recommended 'import os' for path handling")

def test_code_readability(implementation):
    """Test code readability with comments and structure."""
    impl_name, module = implementation
    source_code = inspect.getsource(module)

    # Check for comments with a more flexible pattern
    has_comments = bool(re.search(r'#.*\w+', source_code))  # Comments with actual text

    assert has_comments, \
        f"Implementation {impl_name} should include descriptive comments for better code readability"

def find_callable_functions(module):
    """Helper function to find all callable functions in a module."""
    return [func for name, func in inspect.getmembers(module)
            if inspect.isfunction(func) and name != 'test_func']

def test_browser_automation_behavior(implementation, mock_uc_chrome):
    """Test that the module executes browser automation correctly with end-to-end validation."""
    impl_name, module = implementation

    # Skip if the module has an error (not fail)
    if hasattr(module, '__error__'):
        pytest.fail(f"Module {impl_name} has an error: {module.__error__}")
        return

    # Use the mock to track what happens when the module is executed
    call_counts = {
        'chrome_init': 0,
        'driver_get': 0,
        'urls_visited': [],
        'options_set': {},
        'exceptions': []
    }

    # Configure the mock to record behavior
    def mock_chrome_init(*args, **kwargs):
        call_counts['chrome_init'] += 1

        # Record the options used if they exist
        if 'options' in kwargs:
            call_counts['options_set']['options'] = kwargs['options']

        # Record if driver_executable_path was used
        if 'driver_executable_path' in kwargs:
            call_counts['options_set']['driver_executable_path'] = kwargs['driver_executable_path']
        elif 'executable_path' in kwargs:
            call_counts['options_set']['executable_path'] = kwargs['executable_path']

        # Record if use_subprocess was set
        if 'use_subprocess' in kwargs:
            call_counts['options_set']['use_subprocess'] = kwargs['use_subprocess']

        return mock_uc_chrome.return_value

    def mock_driver_get(url):
        call_counts['driver_get'] += 1
        call_counts['urls_visited'].append(url)

    # Set up the mock behaviors
    mock_uc_chrome.side_effect = mock_chrome_init
    driver_mock = mock_uc_chrome.return_value.__enter__.return_value
    driver_mock.get.side_effect = mock_driver_get

    # Patch print to capture debug prints
    printed_outputs = []
    def mock_print(*args, **kwargs):
        printed_outputs.append(" ".join(str(arg) for arg in args))

    # Create a mock module with the correct structure
    mock_module = MagicMock()
    mock_module.Chrome = mock_uc_chrome
    mock_module.ChromeOptions = lambda: MagicMock()

    # Try to execute the module in a controlled environment
    try:
        with patch('builtins.print', side_effect=mock_print), \
             patch.dict('sys.modules', {'undetected_chromedriver': mock_module}):

            # Execute the module code
            module_path = getattr(module, '__file__', None)
            if not module_path or not os.path.exists(module_path):
                pytest.skip(f"Could not find source file for {impl_name}")
                return

            with open(module_path, 'r') as f:
                source_code = f.read()

            # Import time and add it to execution environment
            import time

            # Create a safe execution environment
            exec_globals = {
                '__name__': '__main__',
                '__file__': module_path,
                'os': os,
                'sys': sys,
                'time': time,  # Add time module here
                're': re,
            }

            # Execute the module code
            try:
                exec(source_code, exec_globals)
            except Exception as e:
                call_counts['exceptions'].append(str(e))

    except Exception as exec_error:
        pytest.fail(f"Error executing {impl_name}: {str(exec_error)}")
        return

    # Now assert the expected behavior
    assert call_counts['chrome_init'] > 0, f"Module {impl_name} should instantiate Chrome"
    assert call_counts['driver_get'] > 0, f"Module {impl_name} should call driver.get()"
    assert 'https://lmarena.ai/' in call_counts['urls_visited'], f"Module {impl_name} should navigate to https://lmarena.ai/"

    # Check that the Chrome was properly configured
    if 'driver_executable_path' in call_counts['options_set']:
        assert 'chromedriver' in call_counts['options_set']['driver_executable_path'].lower(), \
            f"Module {impl_name} should specify chromedriver path"
    elif 'executable_path' in call_counts['options_set']:
        assert 'chromedriver' in call_counts['options_set']['executable_path'].lower(), \
            f"Module {impl_name} should specify chromedriver path"

    # Check use_subprocess setting
    assert 'use_subprocess' in call_counts['options_set'] and call_counts['options_set']['use_subprocess'], \
        f"Module {impl_name} should set use_subprocess=True"

    # If there were exceptions, check if they were properly handled
    if call_counts['exceptions']:
        # Check if error was caught and handled
        error_handled = any("Error initializing Chrome" in output for output in printed_outputs)
        assert error_handled, f"Module {impl_name} should handle exceptions: {call_counts['exceptions'][0]}"

    # Additional checks for code quality
    assert "wde" in printed_outputs, f"Module {impl_name} should print debug statements"

    # Check for duplicate code execution (since original has duplicate blocks)
    if call_counts['chrome_init'] > 1:
        pytest.mark.xfail(reason=f"Module {impl_name} contains duplicate Chrome initialization code")

    # Check if the module properly completes
    assert call_counts['driver_get'] >= call_counts['chrome_init'], \
        f"Module {impl_name} should navigate after initializing Chrome"

import pytest
import os
import sys
import json
from typing import Dict, List, Optional, Any

# Import from local test_utils.py in the same directory
from test_utils import TestUtils, TestResultsManager

# Load all implementations in the current sandbox
implementations = TestUtils.load_all_implementations()
test_results = TestResultsManager()

@pytest.fixture(scope="session")
def sandbox_dir():
    """Fixture to provide the sandbox directory path."""
    return os.path.dirname(os.path.abspath(__file__))

@pytest.fixture(scope="session")
def sandbox_name():
    """Fixture to provide the sandbox name."""
    return os.path.basename(os.path.dirname(os.path.abspath(__file__)))

@pytest.fixture(scope="session")
def all_implementations():
    """Fixture to provide all implementations as a dictionary."""
    return implementations

@pytest.fixture(params=list(implementations.items()))
def implementation(request):
    """Fixture to provide each implementation to tests one at a time."""
    return request.param

@pytest.fixture(scope="session")
def results_manager():
    """Fixture to provide access to the test results manager."""
    return test_results

# Hook for collecting test results
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
    """Pytest hook to collect test results."""
    # Execute all other hooks to obtain the report object
    outcome = yield
    rep = outcome.get_result()

    # We're only interested in the call outcome
    if rep.when == "call":
        if hasattr(item, "callspec") and "implementation" in item.callspec.params:
            # Get implementation name and module
            impl_name, _ = item.callspec.params["implementation"]

            # Get test name
            test_name = item.nodeid.split("::")[-1]

            # Record result
            if rep.passed:
                test_results.record_result(impl_name, test_name, True)
            elif rep.failed:
                error_msg = str(rep.longrepr) if rep.longrepr else "Test failed"
                test_results.record_result(impl_name, test_name, False, error_msg)
            elif rep.skipped:
                skip_reason = rep.longrepr[2] if rep.longrepr else "Test skipped"
                test_results.record_skip(impl_name, test_name, skip_reason)

# Hook to save results at the end of testing
@pytest.hookimpl(trylast=True)
def pytest_sessionfinish(session, exitstatus):
    """Save test results at the end of the test session."""
    test_results.save_results()

import os
import sys
import glob
import re
import importlib.util
import traceback
import types
from typing import Dict, List, Optional, Any, Tuple

class TestUtils:
    @staticmethod
    def discover_implementation_files(directory: str = None) -> List[str]:
        """Find all implementation files in the current sandbox directory."""
        if directory is None:
            directory = os.path.dirname(os.path.abspath(__file__))

        patterns = [
            r'modified_code\d+\.py',
            r'new_code\d+\.py',
            # r'original_code\.py',
            r'implementation\d*\.py'
        ]

        pattern = re.compile('|'.join(f'({p})' for p in patterns))
        implementations = []

        for file_path in glob.glob(os.path.join(directory, '*.py')):
            if pattern.search(os.path.basename(file_path)):
                implementations.append(file_path)

        # Sort files numerically
        def sort_key(path):
            filename = os.path.basename(path)
            match = re.search(r'(\d+)', filename)
            return int(match.group(1)) if match else 0

        return sorted(implementations, key=sort_key)

    @staticmethod
    def create_mock_module(file_path: str, module_name: str, error_info: str) -> types.ModuleType:
        """Create a mock module that contains error information but can still be tested."""
        # Create a new module object
        mock_module = types.ModuleType(module_name)

        # Add basic attributes
        mock_module.__file__ = file_path
        mock_module.__name__ = module_name
        mock_module.__display_name__ = module_name
        mock_module.__error__ = error_info

        # Add a dummy function that can be detected by test functions
        def dummy_function(*args, **kwargs):
            return f"Error in module: {error_info}"

        setattr(mock_module, "implementation_error", dummy_function)

        return mock_module

    @staticmethod
    def load_module(file_path: str, module_name: Optional[str] = None) -> Any:
        """
        Safely load a module from a file path with proper error handling.
        If the module has errors, return a mock module that can still be tested.
        """
        if module_name is None:
            module_name = os.path.basename(file_path).replace('.py', '')

        # Create a unique module name to avoid conflicts
        sandbox_id = os.path.basename(os.path.dirname(file_path))
        unique_module_name = f"{sandbox_id}_{module_name}"

        try:
            # First, try to read the file to check for syntax errors
            with open(file_path, 'r') as f:
                source_code = f.read()

            # Check for syntax errors by compiling the code
            try:
                compiled = compile(source_code, file_path, 'exec')
            except SyntaxError as e:
                error_msg = f"Syntax error: {str(e)}"
                print(f"Syntax error in {file_path}: {e}")
                print(f"  Line {e.lineno}, column {e.offset}: {e.text}")
                return TestUtils.create_mock_module(file_path, unique_module_name, error_msg)

            # Create the module spec
            spec = importlib.util.spec_from_file_location(unique_module_name, file_path)
            if spec is None or spec.loader is None:
                error_msg = f"Could not create spec for {file_path}"
                print(f"Error: {error_msg}")
                return TestUtils.create_mock_module(file_path, unique_module_name, error_msg)

            # Create the module object
            module = importlib.util.module_from_spec(spec)
            sys.modules[unique_module_name] = module

            # Special handling for execution errors
            try:
                # Execute the module code in a safe way
                spec.loader.exec_module(module)
                # Store the original name for reference
                module.__display_name__ = module_name
                return module
            except Exception as e:
                error_msg = f"Runtime error: {str(e)}"
                traceback_str = traceback.format_exc()
                print(f"Error executing module {file_path}: {e}")
                print(traceback_str)

                # Create a partial module that contains what we loaded before the error
                mock_module = TestUtils.create_mock_module(file_path, unique_module_name, error_msg)

                # Copy any attributes that might have been defined before the error
                for attr_name in dir(module):
                    if not attr_name.startswith('__'):
                        try:
                            setattr(mock_module, attr_name, getattr(module, attr_name))
                        except Exception:
                            pass  # Skip attributes that can't be copied

                return mock_module

        except FileNotFoundError as e:
            error_msg = f"File not found: {str(e)}"
            print(f"Error: {error_msg}")
            return TestUtils.create_mock_module(file_path, unique_module_name, error_msg)
        except Exception as e:
            error_msg = f"Unexpected error: {str(e)}"
            print(f"Error loading module {file_path}: {e}")
            return TestUtils.create_mock_module(file_path, unique_module_name, error_msg)

    @classmethod
    def load_all_implementations(cls, directory: str = None) -> Dict[str, Any]:
        """Load all implementation files in the directory, including those with errors."""
        if directory is None:
            directory = os.path.dirname(os.path.abspath(__file__))

        implementations = {}

        implementation_files = cls.discover_implementation_files(directory)
        if not implementation_files:
            print("WARNING: No implementation files found. Check your file naming patterns.")

        for file_path in implementation_files:
            module_name = os.path.basename(file_path).replace('.py', '')
            module = cls.load_module(file_path, module_name)

            # Always add the module, even if it has errors
            implementations[module_name] = module

            if hasattr(module, '__error__'):
                print(f"Loaded with errors: {module_name} - {module.__error__}")
            else:
                print(f"Successfully loaded: {module_name}")

        return implementations

class TestResultsManager:
    def __init__(self):
        self.results = {}
        self.sandbox_name = os.path.basename(os.path.dirname(os.path.abspath(__file__)))

    def record_result(self, impl_name: str, test_name: str, passed: bool,
                     error_msg: Optional[str] = None) -> None:
        """Record a test result for an implementation."""
        if impl_name not in self.results:
            self.results[impl_name] = {"passed": 0, "failed": 0, "skipped": 0, "errors": []}

        if passed:
            self.results[impl_name]["passed"] += 1
        else:
            self.results[impl_name]["failed"] += 1
            if error_msg:
                self.results[impl_name]["errors"].append({
                    "test": test_name,
                    "error": error_msg
                })

    def record_skip(self, impl_name: str, test_name: str,
                   reason: Optional[str] = None) -> None:
        """Record a skipped test for an implementation."""
        if impl_name not in self.results:
            self.results[impl_name] = {"passed": 0, "failed": 0, "skipped": 0, "errors": []}

        self.results[impl_name]["skipped"] += 1
        if reason:
            self.results[impl_name]["errors"].append({
                "test": test_name,
                "error": f"SKIPPED: {reason}"
            })

    def get_winner(self) -> Tuple[Optional[int], Dict]:
        """Determine the winner based on test results."""
        winner = None
        max_passed = -1

        for impl_name, results in self.results.items():
            if impl_name == "original_code":
                continue  # Skip original code when determining winner

            if results["passed"] > max_passed:
                max_passed = results["passed"]
                winner = impl_name
            # Break ties by looking at failure count
            elif results["passed"] == max_passed and winner is not None:
                if results["failed"] < self.results[winner]["failed"]:
                    winner = impl_name

        # Convert winner to numeric index if possible
        winner_index = -1
        if winner and re.match(r'modified_code\d+', winner):
            try:
                winner_index = int(re.search(r'(\d+)', winner).group(1))
            except (AttributeError, ValueError):
                pass

        return winner_index, self.results

    def save_results(self, filename: str = "test_results.json") -> None:
        """Save test results to a JSON file."""
        import json

        winner_index, results = self.get_winner()

        # Check if all tests were skipped
        all_skipped = all(
            stats["skipped"] == stats["passed"] + stats["failed"] + stats["skipped"]
            for impl_name, stats in results.items()
            if impl_name != "original_code"
        )

        output = {
            "winner": winner_index,
            "all_skipped": all_skipped,
            "results": {
                name: {
                    "passed": stats["passed"],
                    "failed": stats["failed"],
                    "skipped": stats["skipped"],
                    "total": stats["passed"] + stats["failed"] + stats["skipped"]
                }
                for name, stats in results.items()
                if not name.startswith("_")  # Skip internal items
            }
        }

        with open(filename, "w") as f:
            json.dump(output, f, indent=2)

        print(f"Test results saved to {filename}")

        return output


import pandas as pd

class Stock:
	def __init__(self, filename, name):
		self.filename = filename
		try:
			self.data = pd.read_csv(self.filename,index_col=0,parse_dates=True)
		except Exception as e:
			print(f"Unable to read file {self.filename}")
			raise e
		self.data.index.name = 'time'
		self.name = name
		self.attrs = {}

	def get_attr(self, key):
		try:
			return self.attrs[key]
		except KeyError:
			return None

	def set_attr(self, key, value):
		self.attrs[key] = value

	def get(self, i):
		return self.data.iloc[i]

	def get_range(self, s, t):
		return self.data.iloc[s:t+1]

	def __len__(self):
		return len(self.data)

class Transaction:
	def __init__(self, num, price):
		self.num = num
		self.price = price
		self.date = None

	def set_date(self, date):
		self.date = date

class Trade:
	def __init__(self, stock, long=True, num=0, price=0.0):
		self.stock = stock
		self.num = 0
		self.profit = 0
		self.closed = False
		self.long = long

		self.opens = []
		self.closes = []

		if num != 0:
			self.open(num, price)

	def close(self, num, price):
		if num > self.num:
			raise ValueError(f"ERR: Trying to close {num} of {self.stock.name} but only {self.num} available")
		self.num -= num
		self.closes.append(Transaction(num, price))

		if self.long:
			self.profit = self.get_num_closed() * (self.get_avg_close_price() - self.get_avg_open_price())
		else:
			self.profit = self.get_num_closed() * (self.get_avg_open_price() - self.get_avg_close_price())

		if self.num == 0:
			self.closed = True

	def open(self, num, price):
		self.num += num

		self.opens.append(Transaction(num, price))

	def get_equity(self, i):
		current_price = self.stock.get(i)["close"]
		if self.long:
			return self.num * current_price
		else:
			# For short trades, equity could reflect the potential cost to close the position
			return self.num * (self.get_avg_open_price() - current_price)

	def set_date(self, date):
		[transaction.set_date(date) for transaction in self.opens if transaction.date is None]
		[transaction.set_date(date) for transaction in self.closes if transaction.date is None]

	def get_avg_open_price(self):
		total_price = sum(transaction.price * transaction.num for transaction in self.opens)
		total_num = sum(transaction.num for transaction in self.opens)
		return total_price / total_num if total_num else 0

	def get_avg_close_price(self):
		total_price = sum(transaction.price * transaction.num for transaction in self.closes)
		total_num = sum(transaction.num for transaction in self.closes)
		return total_price / total_num if total_num else 0

	def get_num_opened(self):
		return sum(transaction.num for transaction in self.opens)

	def get_num_closed(self):
		return sum(transaction.num for transaction in self.closes)

class Strategy:
	def __init__(self):
		self.stocks = []
		self.starting_money = 100000.0
		self.money = self.starting_money
		self.closed_trades = []
		self.open_trades = []
		self.attrs = {}
		self.analyzers = []

	def get_attr(self, key):
		return self.attrs[key]

	def set_attr(self, key, value):
		self.attrs[key] = value

	def add_analyzer(self, analyzer):
		analyzer.strategy = self
		self.analyzers.append(analyzer)

	def has_open_trade(self, stock):
		for trade in self.open_trades:
			if stock is trade.stock:
				return True
		return False

	def get_open_trade(self, stock):
		for trade in self.open_trades:
			if trade.stock is stock:
				return trade
		raise ValueError("No open trade on stock "+str(stock.name))

	def open_trade(self, stock, num, price):
		if self.money < num*price:
			raise ValueError("Insufficient funds: have $"+str(self.money)+" available and trying to open "+str(num)+" of "+str(stock.name)+" at $"+str(price)+" on "+str(stock.get(self.get_attr("i")).name))

		if self.has_open_trade(stock):
			trade = self.get_open_trade(stock)
			trade.open(num, price)
			trade.set_date(stock.get(self.get_attr("i")).name)
		else:
			self.open_trades.append(Trade(stock, True, num, price))
			self.open_trades[-1].set_date(stock.get(self.get_attr("i")).name)

		self.money -= num*price

	def sell(self, stock, num, price):
		if self.has_open_trade(stock):
			trade = self.get_open_trade(stock)
			trade.close(num, price)
			if trade.closed:
				self.open_trades.remove(trade)
				self.closed_trades.append(trade)
			trade.set_date(stock.get(self.get_attr("i")).name)
		else:
			raise ValueError("No position to close in "+str(stock.name))

		self.money += num*price

	def get_equity(self, i):
		res = self.money
		for trade in self.open_trades:
			res += trade.get_equity(i)
		return res

	def next(self, i):
		pass

class Computer:
	def __init__(self):
		self.stocks = []
		self.strategies = []

	def add_stock(self, stock):
		if type(stock) is not Stock:
			exit("ERR: called 'add_stock' on type: "+str(type(stock)))
		self.stocks.append(stock)

	def add_strategy(self, strategy):
		if not isinstance(strategy, Strategy):
			exit("ERR: called 'add_strategy' on type: "+str(type(strategy)))
		self.strategies.append(strategy)

	def run(self):
		# put stocks in strategies
		for strategy in self.strategies:
			j = 1
			for stock in self.stocks:
				strategy.stocks = [stock]
				print(f"stock #{j}/{len(self.stocks)}")
				j += 1

				# run every day on the strategies
				for i in range(len(stock)):
					strategy.set_attr("i", i)
					strategy.next(i)

					for analyzer in strategy.analyzers:
						analyzer.next(i)

					# close any open trades on the end of the last day
					if i == len(stock)-1:
						for strat in self.strategies:
							while len(strat.open_trades) > 0:
								trade = strat.open_trades[0]
								strat.sell(trade.stock, trade.num, trade.stock.get(i)["close"])

		# get rid of strategies
		for strategy in self.strategies:
			strategy.stocks = []

Instruction: I want to update the `run()` method to include inter-candlestick variation. This is to simulate a real-world scenario, where the last candlestick in a stock is in-progress. For every "day" (or candlestick), there should be a configurable number of "samples" taken on the last candlestick, where the high, low, close, and volume vary as time goes on. The `strategy.next(i)` should be called for each sample. The actual dataframe on the stock should be modified during sampling, but after "completing" the candle it should match the original (completed) values and shouldn't change

import pytest
import pandas as pd
import numpy as np
import inspect
import sys
from unittest.mock import patch, MagicMock, call, ANY

@pytest.fixture
def sample_stock_data():
    """Create sample stock data for testing"""
    data = {
        'open': [100, 102, 104, 106, 108],
        'high': [105, 107, 109, 111, 113],
        'low': [95, 97, 99, 101, 103],
        'close': [102, 104, 106, 108, 110],
        'volume': [1000, 1100, 1200, 1300, 1400]
    }
    index = pd.date_range(start='2023-01-01', periods=5, freq='D')
    return pd.DataFrame(data, index=index)

@pytest.fixture
def mock_stock(sample_stock_data):
    """Create a mock Stock with proper structure to avoid exit() calls"""
    class MockStock:
        def __init__(self, data):
            self.data = data.copy()
            self.name = "TestStock"
            self.attrs = {}

        def get(self, i):
            return self.data.iloc[i]

        def __len__(self):
            return len(self.data)

        def get_attr(self, key):
            return self.attrs.get(key)

        def set_attr(self, key, value):
            self.attrs[key] = value

    return MockStock(sample_stock_data)

@pytest.fixture
def mock_strategy():
    """Create a basic mock Strategy object"""
    class MockStrategy:
        def __init__(self):
            self.stocks = []
            self.open_trades = []
            self.closed_trades = []
            self.attrs = {}
            self.analyzers = []
            self.money = 100000.0

        def next(self, i):
            pass

        def set_attr(self, key, value):
            self.attrs[key] = value

    return MockStrategy()

def has_required_class(module, class_name):
    """Check if the module has the required class"""
    return hasattr(module, class_name) and inspect.isclass(getattr(module, class_name))

def test_run_method_exists(implementation):
    """Test that the run method exists in Computer class"""
    impl_name, module = implementation

    # Skip test if Computer class doesn't exist
    if not has_required_class(module, 'Computer'):
        pytest.skip(f"Implementation {impl_name} doesn't have Computer class")

    computer_class = module.Computer
    assert hasattr(computer_class, 'run'), f"Implementation {impl_name} doesn't have a run method"

def test_samples_configuration(implementation):
    """Test that the implementation allows configuration of samples per candle"""
    impl_name, module = implementation

    # Skip test if Computer class doesn't exist
    if not has_required_class(module, 'Computer'):
        pytest.skip(f"Implementation {impl_name} doesn't have Computer class")

    computer = module.Computer()

    # Check if there's a dedicated method to set samples
    has_samples_config = hasattr(computer, 'set_samples_per_candle')

    # Or check if there's a samples parameter in run method
    if not has_samples_config:
        sig = inspect.signature(computer.run)
        has_samples_config = 'num_samples' in sig.parameters

    # Or check if there's a samples attribute that can be set
    if not has_samples_config:
        has_samples_config = hasattr(computer, 'samples_per_candle')

    assert has_samples_config, f"Implementation {impl_name} doesn't allow configuration of samples per candle"

@patch('sys.exit')
def test_run_with_samples(mock_exit, implementation, mock_stock, mock_strategy):
    """Test that the run method processes samples in the last candle"""
    impl_name, module = implementation

    # Skip test if Computer class doesn't exist
    if not has_required_class(module, 'Computer'):
        pytest.skip(f"Implementation {impl_name} doesn't have Computer class")

    # Create a real Computer instance
    computer = module.Computer()

    # Make sure computer has the needed attributes
    if not hasattr(computer, 'stocks'):
        computer.stocks = []
    if not hasattr(computer, 'strategies'):
        computer.strategies = []

    # Patch the add_stock method to accept our mock stock
    with patch.object(computer, 'add_stock', return_value=None) as mock_add_stock, \
         patch.object(computer, 'add_strategy', return_value=None) as mock_add_strategy:

        # Ensure our stock and strategy are used in tests
        mock_add_stock.side_effect = lambda x: computer.stocks.append(x)
        mock_add_strategy.side_effect = lambda x: computer.strategies.append(x)

        # Add mock stock and strategy to computer
        computer.add_stock(mock_stock)
        computer.add_strategy(mock_strategy)

        # Set up spy on strategy's next method
        original_next = mock_strategy.next
        mock_strategy.next = MagicMock(wraps=original_next)
        mock_strategy.stocks = [mock_stock]

        # Set number of samples if method exists
        expected_samples = 3
        if hasattr(computer, 'set_samples_per_candle'):
            computer.set_samples_per_candle(expected_samples)
            # Run with patched sys.exit to prevent crashes
            computer.run()
        else:
            # Check if run method accepts num_samples parameter
            sig = inspect.signature(computer.run)
            if 'num_samples' in sig.parameters:
                # Call run with explicit num_samples
                computer.run(num_samples=expected_samples)
            else:
                # Just run with default samples
                computer.run()
                # Assuming most implementations would use at least 2 samples
                expected_samples = 2

        # Verify that strategy.next was called - either on patched strategy or internally
        # in the implementation. We're just making sure the test doesn't crash at this point.
        assert not mock_exit.called, f"Implementation {impl_name} called sys.exit during run"

@patch('sys.exit')
def test_data_variation_during_samples(mock_exit, implementation):
    """Test that the data actually varies during different samples"""
    impl_name, module = implementation

    # Skip test if required classes don't exist
    if not has_required_class(module, 'Computer') or not has_required_class(module, 'Stock'):
        pytest.skip(f"Implementation {impl_name} doesn't have required classes")

    # Create test data for a single candle
    test_data = pd.DataFrame({
        'open': [100],
        'high': [110],
        'low': [90],
        'close': [105],
        'volume': [1000]
    }, index=pd.DatetimeIndex(['2023-01-01'], name='time'))

    # Create a real Stock with our test data
    with patch('pandas.read_csv', return_value=test_data.copy()):
        stock = module.Stock('dummy.csv', 'TestStock')

    # Create a spy strategy that records candle values during processing
    class SpyStrategy:
        def __init__(self):
            self.recorded_values = []
            self.stocks = []
            self.analyzers = []
            self.open_trades = []
            self.closed_trades = []
            self.attrs = {}
            self.money = 100000.0

        def next(self, i):
            # Record the current values of the candle
            candle = self.stocks[0].get(i)
            self.recorded_values.append({
                'close': candle['close'],
                'high': candle['high'],
                'low': candle['low'],
                'volume': candle['volume']
            })

        def set_attr(self, key, value):
            self.attrs[key] = value

    spy_strategy = SpyStrategy()

    # Create computer and patch methods to prevent exit() calls
    computer = module.Computer()

    # Ensure computer has necessary attributes
    if not hasattr(computer, 'stocks'):
        computer.stocks = []
    if not hasattr(computer, 'strategies'):
        computer.strategies = []

    with patch.object(computer, 'add_stock', return_value=None) as mock_add_stock, \
         patch.object(computer, 'add_strategy', return_value=None) as mock_add_strategy:

        # Ensure our stock and strategy are added properly
        mock_add_stock.side_effect = lambda x: computer.stocks.append(x)
        mock_add_strategy.side_effect = lambda x: computer.strategies.append(x)

        computer.add_stock(stock)
        computer.add_strategy(spy_strategy)
        spy_strategy.stocks = [stock]

        # Run with samples
        if hasattr(computer, 'set_samples_per_candle'):
            computer.set_samples_per_candle(3)
            computer.run()
        elif 'num_samples' in inspect.signature(computer.run).parameters:
            computer.run(num_samples=3)
        else:
            computer.run()

    # Check if values vary during samples or if we have only one sample
    if len(spy_strategy.recorded_values) > 1:
        # Check if there's variation in at least one of the values
        has_variation = False
        for key in ['close', 'high', 'low', 'volume']:
            values = [record[key] for record in spy_strategy.recorded_values]
            if len(set(values)) > 1:
                has_variation = True
                break

        assert has_variation, f"Implementation {impl_name} doesn't show variation in candle data during samples"

@patch('sys.exit')
def test_last_sample_matches_original(mock_exit, implementation):
    """Test that the last sample matches or approximates the original candle data"""
    impl_name, module = implementation

    # Skip test if required classes don't exist
    if not has_required_class(module, 'Computer') or not has_required_class(module, 'Stock'):
        pytest.skip(f"Implementation {impl_name} doesn't have required classes")

    # Create test data for a single candle
    test_data = pd.DataFrame({
        'open': [100],
        'high': [110],
        'low': [90],
        'close': [105],
        'volume': [1000]
    }, index=pd.DatetimeIndex(['2023-01-01'], name='time'))

    # Create a real Stock with our test data
    with patch('pandas.read_csv', return_value=test_data.copy()):
        stock = module.Stock('dummy.csv', 'TestStock')

    # Store original values before any modifications
    original_values = {
        'close': stock.data.iloc[0]['close'],
        'high': stock.data.iloc[0]['high'],
        'low': stock.data.iloc[0]['low'],
        'volume': stock.data.iloc[0]['volume']
    }

    # Create a spy strategy that records values
    class SpyStrategy:
        def __init__(self):
            self.recorded_values = []
            self.stocks = []
            self.analyzers = []
            self.open_trades = []
            self.closed_trades = []
            self.attrs = {}
            self.money = 100000.0

        def next(self, i):
            candle = self.stocks[0].get(i)
            self.recorded_values.append({
                'close': candle['close'],
                'high': candle['high'],
                'low': candle['low'],
                'volume': candle['volume']
            })

        def set_attr(self, key, value):
            self.attrs[key] = value

    spy_strategy = SpyStrategy()

    # Create computer and patch methods to prevent exit() calls
    computer = module.Computer()

    # Ensure computer has necessary attributes
    if not hasattr(computer, 'stocks'):
        computer.stocks = []
    if not hasattr(computer, 'strategies'):
        computer.strategies = []

    with patch.object(computer, 'add_stock', return_value=None) as mock_add_stock, \
         patch.object(computer, 'add_strategy', return_value=None) as mock_add_strategy:

        # Ensure our stock and strategy are added properly
        mock_add_stock.side_effect = lambda x: computer.stocks.append(x)
        mock_add_strategy.side_effect = lambda x: computer.strategies.append(x)

        computer.add_stock(stock)
        computer.add_strategy(spy_strategy)
        spy_strategy.stocks = [stock]

        # Run with samples
        samples = 3
        if hasattr(computer, 'set_samples_per_candle'):
            computer.set_samples_per_candle(samples)
            computer.run()
        elif 'num_samples' in inspect.signature(computer.run).parameters:
            computer.run(num_samples=samples)
        else:
            computer.run()

    # Check if the candle data was restored after processing
    # Using a tolerance because some implementations might have rounding errors
    current_values = {
        'close': stock.data.iloc[0]['close'],
        'high': stock.data.iloc[0]['high'],
        'low': stock.data.iloc[0]['low'],
        'volume': stock.data.iloc[0]['volume']
    }

    # Some implementations may not restore to exact original but should be close
    tolerance = 1e-6
    for key in ['close', 'high', 'low', 'volume']:
        assert abs(current_values[key] - original_values[key]) < tolerance, \
            f"Implementation {impl_name}: Final {key} value wasn't restored to original"

@patch('sys.exit')
def test_trades_during_samples(mock_exit, implementation):
    """Test that trades can be executed during samples"""
    impl_name, module = implementation

    # Skip test if required classes don't exist
    if not has_required_class(module, 'Computer') or not has_required_class(module, 'Stock') or not has_required_class(module, 'Strategy'):
        pytest.skip(f"Implementation {impl_name} doesn't have required classes")

    # Create test data for two candles
    test_data = pd.DataFrame({
        'open': [100, 105],
        'high': [110, 115],
        'low': [90, 95],
        'close': [105, 110],
        'volume': [1000, 1100]
    }, index=pd.DatetimeIndex(['2023-01-01', '2023-01-02'], name='time'))

    # Create a real Stock with our test data
    with patch('pandas.read_csv', return_value=test_data.copy()):
        stock = module.Stock('dummy.csv', 'TestStock')

    # Create a strategy class that will track trade activity
    class TestTradeStrategy(module.Strategy):
        def __init__(self):
            super().__init__()
            self.trade_actions = []
            self.last_close = None
            self.sample_count = 0

        def next(self, i):
            # On the last candle
            if i == len(self.stocks[0]) - 1:
                current_close = self.stocks[0].get(i)['close']

                # Detect new sample
                if self.last_close is not None and abs(current_close - self.last_close) > 1e-10:
                    self.sample_count += 1

                self.last_close

import pytest
import os
import sys
import json
from typing import Dict, List, Optional, Any

# Import from local test_utils.py in the same directory
from test_utils import TestUtils, TestResultsManager

# Load all implementations in the current sandbox
implementations = TestUtils.load_all_implementations()
test_results = TestResultsManager()

@pytest.fixture(scope="session")
def sandbox_dir():
    """Fixture to provide the sandbox directory path."""
    return os.path.dirname(os.path.abspath(__file__))

@pytest.fixture(scope="session")
def sandbox_name():
    """Fixture to provide the sandbox name."""
    return os.path.basename(os.path.dirname(os.path.abspath(__file__)))

@pytest.fixture(scope="session")
def all_implementations():
    """Fixture to provide all implementations as a dictionary."""
    return implementations

@pytest.fixture(params=list(implementations.items()))
def implementation(request):
    """Fixture to provide each implementation to tests one at a time."""
    return request.param

@pytest.fixture(scope="session")
def results_manager():
    """Fixture to provide access to the test results manager."""
    return test_results

# Hook for collecting test results
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
    """Pytest hook to collect test results."""
    # Execute all other hooks to obtain the report object
    outcome = yield
    rep = outcome.get_result()

    # We're only interested in the call outcome
    if rep.when == "call":
        if hasattr(item, "callspec") and "implementation" in item.callspec.params:
            # Get implementation name and module
            impl_name, _ = item.callspec.params["implementation"]

            # Get test name
            test_name = item.nodeid.split("::")[-1]

            # Record result
            if rep.passed:
                test_results.record_result(impl_name, test_name, True)
            elif rep.failed:
                error_msg = str(rep.longrepr) if rep.longrepr else "Test failed"
                test_results.record_result(impl_name, test_name, False, error_msg)
            elif rep.skipped:
                skip_reason = rep.longrepr[2] if rep.longrepr else "Test skipped"
                test_results.record_skip(impl_name, test_name, skip_reason)

# Hook to save results at the end of testing
@pytest.hookimpl(trylast=True)
def pytest_sessionfinish(session, exitstatus):
    """Save test results at the end of the test session."""
    test_results.save_results()

import os
import sys
import glob
import re
import importlib.util
import traceback
import types
from typing import Dict, List, Optional, Any, Tuple

class TestUtils:
    @staticmethod
    def discover_implementation_files(directory: str = None) -> List[str]:
        """Find all implementation files in the current sandbox directory."""
        if directory is None:
            directory = os.path.dirname(os.path.abspath(__file__))

        patterns = [
            r'modified_code\d+\.py',
            r'new_code\d+\.py',
            # r'original_code\.py',
            r'implementation\d*\.py'
        ]

        pattern = re.compile('|'.join(f'({p})' for p in patterns))
        implementations = []

        for file_path in glob.glob(os.path.join(directory, '*.py')):
            if pattern.search(os.path.basename(file_path)):
                implementations.append(file_path)

        # Sort files numerically
        def sort_key(path):
            filename = os.path.basename(path)
            match = re.search(r'(\d+)', filename)
            return int(match.group(1)) if match else 0

        return sorted(implementations, key=sort_key)

    @staticmethod
    def create_mock_module(file_path: str, module_name: str, error_info: str) -> types.ModuleType:
        """Create a mock module that contains error information but can still be tested."""
        # Create a new module object
        mock_module = types.ModuleType(module_name)

        # Add basic attributes
        mock_module.__file__ = file_path
        mock_module.__name__ = module_name
        mock_module.__display_name__ = module_name
        mock_module.__error__ = error_info

        # Add a dummy function that can be detected by test functions
        def dummy_function(*args, **kwargs):
            return f"Error in module: {error_info}"

        setattr(mock_module, "implementation_error", dummy_function)

        return mock_module

    @staticmethod
    def load_module(file_path: str, module_name: Optional[str] = None) -> Any:
        """
        Safely load a module from a file path with proper error handling.
        If the module has errors, return a mock module that can still be tested.
        """
        if module_name is None:
            module_name = os.path.basename(file_path).replace('.py', '')

        # Create a unique module name to avoid conflicts
        sandbox_id = os.path.basename(os.path.dirname(file_path))
        unique_module_name = f"{sandbox_id}_{module_name}"

        try:
            # First, try to read the file to check for syntax errors
            with open(file_path, 'r') as f:
                source_code = f.read()

            # Check for syntax errors by compiling the code
            try:
                compiled = compile(source_code, file_path, 'exec')
            except SyntaxError as e:
                error_msg = f"Syntax error: {str(e)}"
                print(f"Syntax error in {file_path}: {e}")
                print(f"  Line {e.lineno}, column {e.offset}: {e.text}")
                return TestUtils.create_mock_module(file_path, unique_module_name, error_msg)

            # Create the module spec
            spec = importlib.util.spec_from_file_location(unique_module_name, file_path)
            if spec is None or spec.loader is None:
                error_msg = f"Could not create spec for {file_path}"
                print(f"Error: {error_msg}")
                return TestUtils.create_mock_module(file_path, unique_module_name, error_msg)

            # Create the module object
            module = importlib.util.module_from_spec(spec)
            sys.modules[unique_module_name] = module

            # Special handling for execution errors
            try:
                # Execute the module code in a safe way
                spec.loader.exec_module(module)
                # Store the original name for reference
                module.__display_name__ = module_name
                return module
            except Exception as e:
                error_msg = f"Runtime error: {str(e)}"
                traceback_str = traceback.format_exc()
                print(f"Error executing module {file_path}: {e}")
                print(traceback_str)

                # Create a partial module that contains what we loaded before the error
                mock_module = TestUtils.create_mock_module(file_path, unique_module_name, error_msg)

                # Copy any attributes that might have been defined before the error
                for attr_name in dir(module):
                    if not attr_name.startswith('__'):
                        try:
                            setattr(mock_module, attr_name, getattr(module, attr_name))
                        except Exception:
                            pass  # Skip attributes that can't be copied

                return mock_module

        except FileNotFoundError as e:
            error_msg = f"File not found: {str(e)}"
            print(f"Error: {error_msg}")
            return TestUtils.create_mock_module(file_path, unique_module_name, error_msg)
        except Exception as e:
            error_msg = f"Unexpected error: {str(e)}"
            print(f"Error loading module {file_path}: {e}")
            return TestUtils.create_mock_module(file_path, unique_module_name, error_msg)

    @classmethod
    def load_all_implementations(cls, directory: str = None) -> Dict[str, Any]:
        """Load all implementation files in the directory, including those with errors."""
        if directory is None:
            directory = os.path.dirname(os.path.abspath(__file__))

        implementations = {}

        implementation_files = cls.discover_implementation_files(directory)
        if not implementation_files:
            print("WARNING: No implementation files found. Check your file naming patterns.")

        for file_path in implementation_files:
            module_name = os.path.basename(file_path).replace('.py', '')
            module = cls.load_module(file_path, module_name)

            # Always add the module, even if it has errors
            implementations[module_name] = module

            if hasattr(module, '__error__'):
                print(f"Loaded with errors: {module_name} - {module.__error__}")
            else:
                print(f"Successfully loaded: {module_name}")

        return implementations

class TestResultsManager:
    def __init__(self):
        self.results = {}
        self.sandbox_name = os.path.basename(os.path.dirname(os.path.abspath(__file__)))

    def record_result(self, impl_name: str, test_name: str, passed: bool,
                     error_msg: Optional[str] = None) -> None:
        """Record a test result for an implementation."""
        if impl_name not in self.results:
            self.results[impl_name] = {"passed": 0, "failed": 0, "skipped": 0, "errors": []}

        if passed:
            self.results[impl_name]["passed"] += 1
        else:
            self.results[impl_name]["failed"] += 1
            if error_msg:
                self.results[impl_name]["errors"].append({
                    "test": test_name,
                    "error": error_msg
                })

    def record_skip(self, impl_name: str, test_name: str,
                   reason: Optional[str] = None) -> None:
        """Record a skipped test for an implementation."""
        if impl_name not in self.results:
            self.results[impl_name] = {"passed": 0, "failed": 0, "skipped": 0, "errors": []}

        self.results[impl_name]["skipped"] += 1
        if reason:
            self.results[impl_name]["errors"].append({
                "test": test_name,
                "error": f"SKIPPED: {reason}"
            })

    def get_winner(self) -> Tuple[Optional[int], Dict]:
        """Determine the winner based on test results."""
        winner = None
        max_passed = -1

        for impl_name, results in self.results.items():
            if impl_name == "original_code":
                continue  # Skip original code when determining winner

            if results["passed"] > max_passed:
                max_passed = results["passed"]
                winner = impl_name
            # Break ties by looking at failure count
            elif results["passed"] == max_passed and winner is not None:
                if results["failed"] < self.results[winner]["failed"]:
                    winner = impl_name

        # Convert winner to numeric index if possible
        winner_index = -1
        if winner and re.match(r'modified_code\d+', winner):
            try:
                winner_index = int(re.search(r'(\d+)', winner).group(1))
            except (AttributeError, ValueError):
                pass

        return winner_index, self.results

    def save_results(self, filename: str = "test_results.json") -> None:
        """Save test results to a JSON file."""
        import json

        winner_index, results = self.get_winner()

        # Check if all tests were skipped
        all_skipped = all(
            stats["skipped"] == stats["passed"] + stats["failed"] + stats["skipped"]
            for impl_name, stats in results.items()
            if impl_name != "original_code"
        )

        output = {
            "winner": winner_index,
            "all_skipped": all_skipped,
            "results": {
                name: {
                    "passed": stats["passed"],
                    "failed": stats["failed"],
                    "skipped": stats["skipped"],
                    "total": stats["passed"] + stats["failed"] + stats["skipped"]
                }
                for name, stats in results.items()
                if not name.startswith("_")  # Skip internal items
            }
        }

        with open(filename, "w") as f:
            json.dump(output, f, indent=2)

        print(f"Test results saved to {filename}")

        return output


import requests

def registerKey(key: str, user: str):
    print(f'chave: {key}\nnome: {user}')
    try:
        response = requests.get(f'http://127.0.0.1:5000/register/{key}/{user}')

        if response.status_code == 200 and response.get('valid'):
            return True

        response = response.json()

        if response['valid']:
            return True

        return False

    except requests.RequestException as e:
        print(f"Erro de conexão: {e}")
        return False

Instruction: do a post request

import pytest
import unittest.mock
import requests
import inspect
import importlib
import sys
import os
from typing import Dict, Any

def test_implementation_has_register_key_function(implementation):
    """Test that the implementation has the registerKey function."""
    impl_name, module = implementation

    # Check if registerKey function is defined in the implementation
    assert hasattr(module, 'registerKey'), f"Implementation {impl_name} should have a registerKey function"
    assert callable(getattr(module, 'registerKey')), f"registerKey in {impl_name} should be callable"

    # Check function signature
    sig = inspect.signature(module.registerKey)
    assert len(sig.parameters) == 2, f"registerKey should take 2 parameters (key, user) in {impl_name}"

def test_implementation_does_post_request(implementation, monkeypatch):
    """Test that the implementation does a POST request instead of GET."""
    impl_name, module = implementation

    # Skip if implementation doesn't have registerKey
    if not hasattr(module, 'registerKey'):
        pytest.skip(f"Implementation {impl_name} doesn't have registerKey function")

    # Create a mock response
    mock_response = unittest.mock.Mock()
    mock_response.status_code = 200
    mock_response.json.return_value = {"valid": True}

    # Mock the POST request
    post_mock = unittest.mock.Mock(return_value=mock_response)
    # Mock the GET request (to ensure it's not used)
    get_mock = unittest.mock.Mock(return_value=mock_response)

    monkeypatch.setattr(requests, 'post', post_mock)
    monkeypatch.setattr(requests, 'get', get_mock)

    # Call the implementation
    result = module.registerKey("test-key", "test-user")

    # Verify POST was called (not GET)
    post_mock.assert_called_once()
    get_mock.assert_not_called()

    # Check correct result was returned
    assert result is True

def test_implementation_passes_json_data(implementation, monkeypatch):
    """Test that the implementation passes data as JSON in the POST request."""
    impl_name, module = implementation

    # Skip if implementation doesn't have registerKey
    if not hasattr(module, 'registerKey'):
        pytest.skip(f"Implementation {impl_name} doesn't have registerKey function")

    # Create a mock response
    mock_response = unittest.mock.Mock()
    mock_response.status_code = 200
    mock_response.json.return_value = {"valid": True}

    # Mock the POST request
    post_mock = unittest.mock.Mock(return_value=mock_response)
    monkeypatch.setattr(requests, 'post', post_mock)

    # Call the implementation
    module.registerKey("test-key", "test-user")

    # Verify POST was called with the correct JSON data
    post_mock.assert_called_once()
    args, kwargs = post_mock.call_args
    assert 'json' in kwargs, "POST request should include json parameter"
    assert 'key' in kwargs['json'], "JSON data should include 'key'"
    assert 'user' in kwargs['json'], "JSON data should include 'user'"
    assert kwargs['json']['key'] == "test-key", "Key value should match input parameter"
    assert kwargs['json']['user'] == "test-user", "User value should match input parameter"

def test_implementation_endpoint_format(implementation, monkeypatch):
    """Test that the implementation uses the correct endpoint format."""
    impl_name, module = implementation

    # Skip if implementation doesn't have registerKey
    if not hasattr(module, 'registerKey'):
        pytest.skip(f"Implementation {impl_name} doesn't have registerKey function")

    # Create a mock response
    mock_response = unittest.mock.Mock()
    mock_response.status_code = 200
    mock_response.json.return_value = {"valid": True}

    # Mock the POST request
    post_mock = unittest.mock.Mock(return_value=mock_response)
    monkeypatch.setattr(requests, 'post', post_mock)

    # Call the implementation
    module.registerKey("test-key", "test-user")

    # Verify POST was called with the correct endpoint
    post_mock.assert_called_once()
    args, kwargs = post_mock.call_args
    assert args[0] == 'http://127.0.0.1:5000/register', "Endpoint should be 'http://127.0.0.1:5000/register'"

import pytest
import os
import sys
import json
from typing import Dict, List, Optional, Any

# Import from local test_utils.py in the same directory
from test_utils import TestUtils, TestResultsManager

# Load all implementations in the current sandbox
implementations = TestUtils.load_all_implementations()
test_results = TestResultsManager()

@pytest.fixture(scope="session")
def sandbox_dir():
    """Fixture to provide the sandbox directory path."""
    return os.path.dirname(os.path.abspath(__file__))

@pytest.fixture(scope="session")
def sandbox_name():
    """Fixture to provide the sandbox name."""
    return os.path.basename(os.path.dirname(os.path.abspath(__file__)))

@pytest.fixture(scope="session")
def all_implementations():
    """Fixture to provide all implementations as a dictionary."""
    return implementations

@pytest.fixture(params=list(implementations.items()))
def implementation(request):
    """Fixture to provide each implementation to tests one at a time."""
    return request.param

@pytest.fixture(scope="session")
def results_manager():
    """Fixture to provide access to the test results manager."""
    return test_results

# Hook for collecting test results
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
    """Pytest hook to collect test results."""
    # Execute all other hooks to obtain the report object
    outcome = yield
    rep = outcome.get_result()

    # We're only interested in the call outcome
    if rep.when == "call":
        if hasattr(item, "callspec") and "implementation" in item.callspec.params:
            # Get implementation name and module
            impl_name, _ = item.callspec.params["implementation"]

            # Get test name
            test_name = item.nodeid.split("::")[-1]

            # Record result
            if rep.passed:
                test_results.record_result(impl_name, test_name, True)
            elif rep.failed:
                error_msg = str(rep.longrepr) if rep.longrepr else "Test failed"
                test_results.record_result(impl_name, test_name, False, error_msg)
            elif rep.skipped:
                skip_reason = rep.longrepr[2] if rep.longrepr else "Test skipped"
                test_results.record_skip(impl_name, test_name, skip_reason)

# Hook to save results at the end of testing
@pytest.hookimpl(trylast=True)
def pytest_sessionfinish(session, exitstatus):
    """Save test results at the end of the test session."""
    test_results.save_results()

import os
import sys
import glob
import re
import importlib.util
import traceback
import types
from typing import Dict, List, Optional, Any, Tuple

class TestUtils:
    @staticmethod
    def discover_implementation_files(directory: str = None) -> List[str]:
        """Find all implementation files in the current sandbox directory."""
        if directory is None:
            directory = os.path.dirname(os.path.abspath(__file__))

        patterns = [
            r'modified_code\d+\.py',
            r'new_code\d+\.py',
            # r'original_code\.py',
            r'implementation\d*\.py'
        ]

        pattern = re.compile('|'.join(f'({p})' for p in patterns))
        implementations = []

        for file_path in glob.glob(os.path.join(directory, '*.py')):
            if pattern.search(os.path.basename(file_path)):
                implementations.append(file_path)

        # Sort files numerically
        def sort_key(path):
            filename = os.path.basename(path)
            match = re.search(r'(\d+)', filename)
            return int(match.group(1)) if match else 0

        return sorted(implementations, key=sort_key)

    @staticmethod
    def create_mock_module(file_path: str, module_name: str, error_info: str) -> types.ModuleType:
        """Create a mock module that contains error information but can still be tested."""
        # Create a new module object
        mock_module = types.ModuleType(module_name)

        # Add basic attributes
        mock_module.__file__ = file_path
        mock_module.__name__ = module_name
        mock_module.__display_name__ = module_name
        mock_module.__error__ = error_info

        # Add a dummy function that can be detected by test functions
        def dummy_function(*args, **kwargs):
            return f"Error in module: {error_info}"

        setattr(mock_module, "implementation_error", dummy_function)

        return mock_module

    @staticmethod
    def load_module(file_path: str, module_name: Optional[str] = None) -> Any:
        """
        Safely load a module from a file path with proper error handling.
        If the module has errors, return a mock module that can still be tested.
        """
        if module_name is None:
            module_name = os.path.basename(file_path).replace('.py', '')

        # Create a unique module name to avoid conflicts
        sandbox_id = os.path.basename(os.path.dirname(file_path))
        unique_module_name = f"{sandbox_id}_{module_name}"

        try:
            # First, try to read the file to check for syntax errors
            with open(file_path, 'r') as f:
                source_code = f.read()

            # Check for syntax errors by compiling the code
            try:
                compiled = compile(source_code, file_path, 'exec')
            except SyntaxError as e:
                error_msg = f"Syntax error: {str(e)}"
                print(f"Syntax error in {file_path}: {e}")
                print(f"  Line {e.lineno}, column {e.offset}: {e.text}")
                return TestUtils.create_mock_module(file_path, unique_module_name, error_msg)

            # Create the module spec
            spec = importlib.util.spec_from_file_location(unique_module_name, file_path)
            if spec is None or spec.loader is None:
                error_msg = f"Could not create spec for {file_path}"
                print(f"Error: {error_msg}")
                return TestUtils.create_mock_module(file_path, unique_module_name, error_msg)

            # Create the module object
            module = importlib.util.module_from_spec(spec)
            sys.modules[unique_module_name] = module

            # Special handling for execution errors
            try:
                # Execute the module code in a safe way
                spec.loader.exec_module(module)
                # Store the original name for reference
                module.__display_name__ = module_name
                return module
            except Exception as e:
                error_msg = f"Runtime error: {str(e)}"
                traceback_str = traceback.format_exc()
                print(f"Error executing module {file_path}: {e}")
                print(traceback_str)

                # Create a partial module that contains what we loaded before the error
                mock_module = TestUtils.create_mock_module(file_path, unique_module_name, error_msg)

                # Copy any attributes that might have been defined before the error
                for attr_name in dir(module):
                    if not attr_name.startswith('__'):
                        try:
                            setattr(mock_module, attr_name, getattr(module, attr_name))
                        except Exception:
                            pass  # Skip attributes that can't be copied

                return mock_module

        except FileNotFoundError as e:
            error_msg = f"File not found: {str(e)}"
            print(f"Error: {error_msg}")
            return TestUtils.create_mock_module(file_path, unique_module_name, error_msg)
        except Exception as e:
            error_msg = f"Unexpected error: {str(e)}"
            print(f"Error loading module {file_path}: {e}")
            return TestUtils.create_mock_module(file_path, unique_module_name, error_msg)

    @classmethod
    def load_all_implementations(cls, directory: str = None) -> Dict[str, Any]:
        """Load all implementation files in the directory, including those with errors."""
        if directory is None:
            directory = os.path.dirname(os.path.abspath(__file__))

        implementations = {}

        implementation_files = cls.discover_implementation_files(directory)
        if not implementation_files:
            print("WARNING: No implementation files found. Check your file naming patterns.")

        for file_path in implementation_files:
            module_name = os.path.basename(file_path).replace('.py', '')
            module = cls.load_module(file_path, module_name)

            # Always add the module, even if it has errors
            implementations[module_name] = module

            if hasattr(module, '__error__'):
                print(f"Loaded with errors: {module_name} - {module.__error__}")
            else:
                print(f"Successfully loaded: {module_name}")

        return implementations

class TestResultsManager:
    def __init__(self):
        self.results = {}
        self.sandbox_name = os.path.basename(os.path.dirname(os.path.abspath(__file__)))

    def record_result(self, impl_name: str, test_name: str, passed: bool,
                     error_msg: Optional[str] = None) -> None:
        """Record a test result for an implementation."""
        if impl_name not in self.results:
            self.results[impl_name] = {"passed": 0, "failed": 0, "skipped": 0, "errors": []}

        if passed:
            self.results[impl_name]["passed"] += 1
        else:
            self.results[impl_name]["failed"] += 1
            if error_msg:
                self.results[impl_name]["errors"].append({
                    "test": test_name,
                    "error": error_msg
                })

    def record_skip(self, impl_name: str, test_name: str,
                   reason: Optional[str] = None) -> None:
        """Record a skipped test for an implementation."""
        if impl_name not in self.results:
            self.results[impl_name] = {"passed": 0, "failed": 0, "skipped": 0, "errors": []}

        self.results[impl_name]["skipped"] += 1
        if reason:
            self.results[impl_name]["errors"].append({
                "test": test_name,
                "error": f"SKIPPED: {reason}"
            })

    def get_winner(self) -> Tuple[Optional[int], Dict]:
        """Determine the winner based on test results."""
        winner = None
        max_passed = -1

        for impl_name, results in self.results.items():
            if impl_name == "original_code":
                continue  # Skip original code when determining winner

            if results["passed"] > max_passed:
                max_passed = results["passed"]
                winner = impl_name
            # Break ties by looking at failure count
            elif results["passed"] == max_passed and winner is not None:
                if results["failed"] < self.results[winner]["failed"]:
                    winner = impl_name

        # Convert winner to numeric index if possible
        winner_index = -1
        if winner and re.match(r'modified_code\d+', winner):
            try:
                winner_index = int(re.search(r'(\d+)', winner).group(1))
            except (AttributeError, ValueError):
                pass

        return winner_index, self.results

    def save_results(self, filename: str = "test_results.json") -> None:
        """Save test results to a JSON file."""
        import json

        winner_index, results = self.get_winner()

        # Check if all tests were skipped
        all_skipped = all(
            stats["skipped"] == stats["passed"] + stats["failed"] + stats["skipped"]
            for impl_name, stats in results.items()
            if impl_name != "original_code"
        )

        output = {
            "winner": winner_index,
            "all_skipped": all_skipped,
            "results": {
                name: {
                    "passed": stats["passed"],
                    "failed": stats["failed"],
                    "skipped": stats["skipped"],
                    "total": stats["passed"] + stats["failed"] + stats["skipped"]
                }
                for name, stats in results.items()
                if not name.startswith("_")  # Skip internal items
            }
        }

        with open(filename, "w") as f:
            json.dump(output, f, indent=2)

        print(f"Test results saved to {filename}")

        return output