Skip to content

Commit

Permalink
Create fixture for creating GDB session
Browse files Browse the repository at this point in the history
  • Loading branch information
lebr0nli committed May 14, 2024
1 parent 97d98d8 commit f51a82c
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 0 deletions.
106 changes: 106 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
from __future__ import annotations

import functools
import os
import subprocess
import tempfile
import time
import typing as T

import pytest

SESSION_STARTUP_TIMEOUT = 15
STARTUP_BANNER = b"GEP is running now!"
GDB_HISTORY_NAME = ".gdb_history"


class GDBSession:
def __init__(self) -> None:
self.tmpdir = tempfile.TemporaryDirectory()

self.session_name = None
self.__session_started = False

def start(self, gdb_args: list[str] | None = None, histories: list[str] = None) -> None:
if histories:
with open(os.path.join(self.tmpdir.name, GDB_HISTORY_NAME), "w") as f:
f.write("\n".join(histories))

cmd = [
"tmux",
"new-session",
"-f",
os.devnull,
"-d",
"-P",
"-F",
"#{session_name}",
"-c",
self.tmpdir.name,
"gdb",
"-q",
]
if gdb_args:
cmd.extend(gdb_args)

self.session_name = subprocess.run(cmd, capture_output=True).stdout.decode().strip()
self.__session_started = True

# wait `STARTUP_BANNER` appears in pane
now = time.time()
while time.time() - now < SESSION_STARTUP_TIMEOUT:
if STARTUP_BANNER in self.capture_pane():
break
time.sleep(1)
else:
raise TimeoutError("GDB session did not start in time")
self.clear_pane()

def stop(self) -> None:
self.tmpdir.cleanup()
if self.__session_started:
subprocess.run(["tmux", "kill-session", "-t", self.session_name])
self.__session_started = False

def check_session_started(func: T.Callable) -> T.Callable:
@functools.wraps(func)
def wrapper(self: GDBSession, *args, **kwargs):
if not self.__session_started:
raise RuntimeError("GDB session is not started")
return func(self, *args, **kwargs)

return wrapper

@check_session_started
def send_literal(self, literal: str) -> None:
subprocess.run(["tmux", "send-keys", "-l", "-t", self.session_name, literal])
time.sleep(1)

@check_session_started
def send_key(self, key: str) -> None:
subprocess.run(["tmux", "send-keys", "-t", self.session_name, key])
time.sleep(1)

@check_session_started
def clear_pane(self) -> None:
subprocess.run(["tmux", "send-keys", "-t", self.session_name, "C-l"])
time.sleep(1)
subprocess.run(["tmux", "clear-history", "-t", self.session_name])

@check_session_started
def capture_pane(self) -> bytes:
return subprocess.run(
["tmux", "capture-pane", "-p", "-t", self.session_name], capture_output=True
).stdout.rstrip(b"\n")

def __enter__(self) -> GDBSession:
return self

def __exit__(self, exc_type, exc_value, traceback) -> None:
self.stop()


@pytest.fixture
def gdb_session() -> T.Iterator[GDBSession]:
with GDBSession() as session:
yield session
32 changes: 32 additions & 0 deletions tests/test_gep.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from conftest import GDBSession


def test_autosuggestion(gdb_session: GDBSession) -> None:
gdb_session.send_literal("print 12\n")
gdb_session.clear_pane()
gdb_session.send_literal("print 34\n")
gdb_session.clear_pane()

# the autosuggestion should not be shown when no match
gdb_session.send_literal("print x")
assert b"(gdb) print x" == gdb_session.capture_pane()

# make buffer to "print "
gdb_session.send_key("BSpace")
gdb_session.send_key("BSpace")
gdb_session.send_literal(" ")
# match "print 34"
assert b"(gdb) print 34" == gdb_session.capture_pane() # TODO: there is no color
# accept the suggestion
gdb_session.send_key("Right")
assert b"(gdb) print 34" == gdb_session.capture_pane()

# make buffer to "print 1"
gdb_session.send_key("BSpace")
gdb_session.send_key("BSpace")
gdb_session.send_literal("1")
# match "print 12"
assert b"(gdb) print 12" == gdb_session.capture_pane() # TODO: there is no color
# accept the suggestion
gdb_session.send_key("Right")
assert b"(gdb) print 12" == gdb_session.capture_pane()

0 comments on commit f51a82c

Please sign in to comment.