mirror of https://github.com/pwndbg/pwndbg
Fix terminal width to 80 columns in tests (#2444)
* Fix terminal width to 80 columns in tests Set a `PWNDBG_IN_TEST`environment variable when running gdb in tests. Use the dimensions in `LINES` and `COLUMNS` when looking up the window size when that envvar is set. This makes context output always be 80 columns wide which allows to compare to hardcoded output. * Use `width` and `height` parameters for cmd window size They are updated to the correct values when switching between tui and cli mode. So it's unnecessary to parse `info win`. * Remove workarounds for terminal size in DEVELOPING * Don't bother updating the env of the debuggee
This commit is contained in:
parent
5553a93a3e
commit
6892a09c5a
|
@ -51,19 +51,6 @@ We have four types of tests: `gdb-tests`,`qemu-tests`, `unit-tests`, and Linux k
|
||||||
|
|
||||||
To run these tests, run [`./tests.sh`](./tests.sh). You can filter the tests to run by providing an argument to the script, such as `./tests.sh heap`, which will only run tests that contain "heap" in the name. You can also drop into the PDB debugger when a test fails with `./tests.sh --pdb`.
|
To run these tests, run [`./tests.sh`](./tests.sh). You can filter the tests to run by providing an argument to the script, such as `./tests.sh heap`, which will only run tests that contain "heap" in the name. You can also drop into the PDB debugger when a test fails with `./tests.sh --pdb`.
|
||||||
|
|
||||||
Some of the tests rely on output that depends on a certain width/height of the terminal, so you will likely see many test failures when simply running `./tests.sh`. To run the tests in the expected environment, you can use:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
docker compose run --build -T ubuntu24.04 ./tests.sh
|
|
||||||
# The `-T` disables the use of a pseudo-TTY
|
|
||||||
```
|
|
||||||
|
|
||||||
If you want rapidly iterate on tests (waiting for the container to rebuild and all the test source code files to compile can take a while), you can pipe `cat` on both ends to disable the PTY and get the correct terminal width/height for the tests.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cat | ./tests.sh | cat
|
|
||||||
```
|
|
||||||
|
|
||||||
To invoke cross-architecture tests, use `./qemu-tests.sh`, and to run unit tests, use `./unit-tests.sh`
|
To invoke cross-architecture tests, use `./qemu-tests.sh`, and to run unit tests, use `./unit-tests.sh`
|
||||||
|
|
||||||
## Writing Tests
|
## Writing Tests
|
||||||
|
|
|
@ -6,6 +6,7 @@ from typing import Any
|
||||||
from typing import Generator
|
from typing import Generator
|
||||||
from typing import List
|
from typing import List
|
||||||
from typing import Literal
|
from typing import Literal
|
||||||
|
from typing import Optional
|
||||||
from typing import Sequence
|
from typing import Sequence
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
from typing import TypeVar
|
from typing import TypeVar
|
||||||
|
@ -1254,38 +1255,22 @@ class GDB(pwndbg.dbg_mod.Debugger):
|
||||||
return f"%#{2 * pwndbg.gdblib.arch.ptrsize}x" % address
|
return f"%#{2 * pwndbg.gdblib.arch.ptrsize}x" % address
|
||||||
|
|
||||||
@override
|
@override
|
||||||
def get_cmd_window_size(self) -> Tuple[int, int]:
|
def get_cmd_window_size(self) -> Tuple[Optional[int], Optional[int]]:
|
||||||
"""Get the size of the command window in TUI mode which could be different than the terminal window width \
|
"""Get the size of the command window.
|
||||||
with horizontal split "tui new-layout hsrc { -horizontal src 1 cmd 1 } 1".
|
|
||||||
|
|
||||||
Possible output of "info win" in TUI mode:
|
GDB keeps these parameters up to date with the actual window size
|
||||||
(gdb) info win
|
of the command output. This is the full terminal size in CLI mode
|
||||||
Name Lines Columns Focus
|
or the size of the cmd window in TUI mode.
|
||||||
src 77 104 (has focus)
|
|
||||||
cmd 77 105
|
|
||||||
|
|
||||||
Output of "info win" in non-TUI mode:
|
When the window size is set to be unlimited (0), the parameter
|
||||||
(gdb) info win
|
is None.
|
||||||
The TUI is not active."""
|
"""
|
||||||
try:
|
width = gdb.parameter("width")
|
||||||
info_out = gdb.execute("info win", to_string=True).split()
|
height = gdb.parameter("height")
|
||||||
except gdb.error:
|
return (
|
||||||
# Return None if the command is not compiled into GDB
|
height if height is None else int(height),
|
||||||
# (gdb.error: Undefined info command: "win". Try "help info")
|
width if width is None else int(width),
|
||||||
return None, None
|
)
|
||||||
if "cmd" not in info_out:
|
|
||||||
# if TUI is not enabled, info win will output "The TUI is not active."
|
|
||||||
return None, None
|
|
||||||
# parse cmd window size from the output of "info win"
|
|
||||||
cmd_win_index = info_out.index("cmd")
|
|
||||||
if len(info_out) <= cmd_win_index + 2:
|
|
||||||
return None, None
|
|
||||||
elif (
|
|
||||||
not info_out[cmd_win_index + 1].isdigit() and not info_out[cmd_win_index + 2].isdigit()
|
|
||||||
):
|
|
||||||
return None, None
|
|
||||||
else:
|
|
||||||
return int(info_out[cmd_win_index + 1]), int(info_out[cmd_win_index + 2])
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
def set_python_diagnostics(self, enabled: bool) -> None:
|
def set_python_diagnostics(self, enabled: bool) -> None:
|
||||||
|
|
|
@ -73,6 +73,8 @@ def get_window_size(target=sys.stdin):
|
||||||
rows, cols = get_cmd_window_size()
|
rows, cols = get_cmd_window_size()
|
||||||
if rows is not None and cols is not None:
|
if rows is not None and cols is not None:
|
||||||
return rows, cols
|
return rows, cols
|
||||||
|
elif os.environ.get("PWNDBG_IN_TEST") is not None:
|
||||||
|
return fallback
|
||||||
try:
|
try:
|
||||||
# get terminal size and force ret buffer len of 4 bytes for safe unpacking by passing equally long arg
|
# get terminal size and force ret buffer len of 4 bytes for safe unpacking by passing equally long arg
|
||||||
rows, cols = struct.unpack("hh", fcntl.ioctl(target.fileno(), termios.TIOCGWINSZ, b"1234"))
|
rows, cols = struct.unpack("hh", fcntl.ioctl(target.fileno(), termios.TIOCGWINSZ, b"1234"))
|
||||||
|
|
|
@ -4,6 +4,8 @@ This file should consist of global test fixtures.
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
import gdb
|
import gdb
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
@ -17,8 +19,11 @@ def start_binary():
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _start_binary(path, *args):
|
def _start_binary(path, *args):
|
||||||
|
os.environ["PWNDBG_IN_TEST"] = "1"
|
||||||
gdb.execute("file " + path)
|
gdb.execute("file " + path)
|
||||||
gdb.execute("set exception-verbose on")
|
gdb.execute("set exception-verbose on")
|
||||||
|
gdb.execute("set width 80")
|
||||||
|
os.environ["COLUMNS"] = "80"
|
||||||
gdb.execute("starti " + " ".join(args))
|
gdb.execute("starti " + " ".join(args))
|
||||||
|
|
||||||
global _start_binary_called
|
global _start_binary_called
|
||||||
|
|
Loading…
Reference in New Issue