diff --git a/.gitignore b/.gitignore index b352b0a..635a80b 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,6 @@ __pycache__/ /dist /.ra-aid .coverage +/.venv +/venv +/.idea diff --git a/ra_aid/proc/interactive.py b/ra_aid/proc/interactive.py index 365d130..a097fa9 100644 --- a/ra_aid/proc/interactive.py +++ b/ra_aid/proc/interactive.py @@ -10,6 +10,9 @@ import shutil from typing import List, Tuple +# Add macOS detection +IS_MACOS = os.uname().sysname == "Darwin" + def run_interactive_command(cmd: List[str]) -> Tuple[bytes, int]: """ Runs an interactive command with a pseudo-tty, capturing combined output. @@ -57,7 +60,10 @@ def run_interactive_command(cmd: List[str]) -> Tuple[bytes, int]: os.environ['PAGER'] = '' # Run command with script for TTY and output capture - os.system(f"script -q -c {shlex.quote(shell_cmd)} {shlex.quote(output_path)}") + if IS_MACOS: + os.system(f"script -q {shlex.quote(output_path)} {shell_cmd}") + else: + os.system(f"script -q -c {shlex.quote(shell_cmd)} {shlex.quote(output_path)}") # Read and clean the output with open(output_path, "rb") as f: diff --git a/tests/ra_aid/proc/test_interactive.py b/tests/ra_aid/proc/test_interactive.py index 1e4e916..687b45c 100644 --- a/tests/ra_aid/proc/test_interactive.py +++ b/tests/ra_aid/proc/test_interactive.py @@ -26,7 +26,7 @@ def test_stderr_capture(): # Use a command that definitely writes to stderr output, retcode = run_interactive_command(["/bin/bash", "-c", "ls /nonexistent/path"]) assert b"No such file or directory" in output - assert retcode == 2 # ls returns 2 for file not found + assert retcode != 0 # ls returns 0 upon success def test_command_not_found(): @@ -51,25 +51,28 @@ def test_interactive_command(): assert b"stderr" in output assert retcode == 0 - def test_large_output(): """Test handling of commands that produce large output.""" # Generate a large output with predictable content cmd = "for i in {1..10000}; do echo \"Line $i of test output\"; done" output, retcode = run_interactive_command(["/bin/bash", "-c", cmd]) - - # Filter out script header/footer - lines = [line for line in output.splitlines() if b"Script" not in line and line.strip()] - + + # Clean up specific artifacts (e.g., ^D) + output_cleaned = output.lstrip(b'^D') # Remove the leading ^D if present + + # Split and filter lines + lines = [line.strip() for line in output_cleaned.splitlines() if b"Script" not in line and line.strip()] + # Verify we got all 10000 lines - assert len(lines) == 10000 - + assert len(lines) == 10000, f"Expected 10000 lines, but got {len(lines)}" + # Verify content of some lines - assert lines[0] == b"Line 1 of test output" - assert lines[999] == b"Line 1000 of test output" - assert lines[-1] == b"Line 10000 of test output" - - assert retcode == 0 + assert lines[0] == b"Line 1 of test output", f"Unexpected line: {lines[0]}" + assert lines[999] == b"Line 1000 of test output", f"Unexpected line: {lines[999]}" + assert lines[-1] == b"Line 10000 of test output", f"Unexpected line: {lines[-1]}" + + # Verify return code + assert retcode == 0, f"Unexpected return code: {retcode}" def test_unicode_handling(): @@ -124,9 +127,17 @@ def test_realtime_output(): assert b"third" in lines[2] assert retcode == 0 - def test_tty_available(): """Test that commands have access to a TTY.""" + # Run the tty command output, retcode = run_interactive_command(["/bin/bash", "-c", "tty"]) - assert b"/dev/pts/" in output # Should show a PTY device + + # Clean up specific artifacts (e.g., ^D) + output_cleaned = output.lstrip(b'^D') # Remove leading ^D if present + + # Debug: Print cleaned output + print(f"Cleaned TTY Output: {output_cleaned}") + + # Check if the output contains a valid TTY path + assert b"/dev/pts/" in output_cleaned or b"/dev/ttys" in output_cleaned, f"Unexpected TTY output: {output_cleaned}" assert retcode == 0