test/pyxtest: move X11 error codes from xclient.py to proto/x11.py

The X11 core protocol error code constants (BadRequest, BadValue,
BadWindow, etc.) belong with the other protocol definitions in
proto/x11.py rather than in the client connection module.

Move the canonical definitions to proto/x11.py and re-export them from
xclient.py for backward compatibility. Update all test files to import
from proto.x11 instead.

Assisted-by: Claude:claude-opus-4-6
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2263>
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
This commit is contained in:
Peter Hutterer 2026-07-22 15:37:16 +10:00 • committed by Enrico Weigelt
commit 02b7b7a9a5
6 changed files with 64 additions and 42 deletions

View file

@ -5,6 +5,25 @@
import struct
from dataclasses import dataclass, field
# Core protocol error codes (from X.h)
BadRequest = 1
BadValue = 2
BadWindow = 3
BadPixmap = 4
BadAtom = 5
BadCursor = 6
BadFont = 7
BadMatch = 8
BadDrawable = 9
BadAccess = 10
BadAlloc = 11
BadColor = 12
BadGC = 13
BadIDChoice = 14
BadName = 15
BadLength = 16
BadImplementation = 17
# Core protocol opcodes
CreateWindow = 1
ChangeWindowAttributes = 2

View file

@ -3,8 +3,8 @@
# Tests for Present extension.
import pytest
from proto import present
from xclient import BadWindow, Extension, X11Error
from proto import present, x11
from xclient import Extension, X11Error
class TestPresentSelectInput:
@ -124,7 +124,7 @@ class TestPresentNotify:
bad_window_errors = [
r
for r in responses
if isinstance(r, X11Error) and r.error_code == BadWindow
if isinstance(r, X11Error) and r.error_code == x11.BadWindow
]
assert len(bad_window_errors) == 0, (
f"PresentPixmap returned BadWindow error(s): "

View file

@ -5,8 +5,8 @@
import struct
import pytest
from proto import randr
from xclient import BadIDChoice, BadLength, Extension, X11Error, X11Reply
from proto import randr, x11
from xclient import Extension, X11Error, X11Reply
def _get_first_output(xclient, opcode):
@ -178,8 +178,8 @@ class TestRandROutputProperty:
# server tries to allocate 4 GB, failing with BadAlloc (11)
# instead.
assert isinstance(resp, X11Error), f"Expected an error, got {resp}"
assert resp.error_code == BadLength, (
f"Expected BadLength ({BadLength}), got error code {resp.error_code} - "
assert resp.error_code == x11.BadLength, (
f"Expected BadLength ({x11.BadLength}), got error code {resp.error_code} - "
f"integer truncation not caught by length check"
)
@ -304,6 +304,6 @@ class TestRandRCreateLease:
# Without the fix: BadIDChoice (error code 14).
# With the fix: either success or some other error.
if isinstance(resp, X11Error):
assert resp.error_code != BadIDChoice, (
assert resp.error_code != x11.BadIDChoice, (
"CreateLease returned BadIDChoice - lid not byte-swapped"
)

View file

@ -5,8 +5,8 @@
import struct
import pytest
from proto import xi
from xclient import BadLength, BadValue, BadWindow, Extension, X11Error, X11Reply
from proto import x11, xi
from xclient import Extension, X11Error, X11Reply
@pytest.fixture
@ -115,8 +115,8 @@ class TestXIPassiveGrab:
)
# The fix returns BadValue (error code 2)
assert isinstance(resp, X11Error), f"Expected an error reply, got {resp}"
assert resp.error_code == BadValue, (
f"Expected BadValue ({BadValue}), got error code {resp.error_code}"
assert resp.error_code == x11.BadValue, (
f"Expected BadValue ({x11.BadValue}), got error code {resp.error_code}"
)
@ -167,8 +167,8 @@ class TestXIChangeProperty:
# server tries to allocate 4 GB, failing with BadAlloc (11)
# instead.
assert isinstance(resp, X11Error), f"Expected an error, got {resp}"
assert resp.error_code == BadLength, (
f"Expected BadLength ({BadLength}), got error code {resp.error_code} - "
assert resp.error_code == x11.BadLength, (
f"Expected BadLength ({x11.BadLength}), got error code {resp.error_code} - "
f"integer truncation not caught by length check"
)
@ -384,7 +384,7 @@ class TestXIChangeDeviceControl:
# With the fix: either a reply (success) or BadMatch (device
# doesn't support resolution control), but NOT BadValue.
if isinstance(resp, X11Error):
assert resp.error_code != BadValue, (
assert resp.error_code != x11.BadValue, (
"ChangeDeviceControl returned BadValue - "
"resolution values not byte-swapped"
)
@ -410,6 +410,6 @@ class TestXIChangeCursor:
# Without the fix: SegFault on a NULL WindowPtr
# With the fix: BadWindow
assert isinstance(resp, X11Error), f"Expected an error, got {resp}"
assert resp.error_code == BadWindow, (
assert resp.error_code == x11.BadWindow, (
"ChangeCursor didn't return BadWindow for Window 0"
)

View file

@ -7,8 +7,8 @@ import struct
import time
import pytest
from proto import xkb
from xclient import BadLength, BadMatch, BadValue, X11Error, X11Reply
from proto import x11, xkb
from xclient import X11Error, X11Reply
logger = logging.getLogger(__name__)
@ -157,7 +157,7 @@ class TestXkbSetMapOverflows:
# error code 0x25 in the resource_id. Without the fix, the
# wire pointer advances past the buffer and a later check
# returns BadLength (16).
bad_value_errors = [e for e in errors if e.error_code == BadValue]
bad_value_errors = [e for e in errors if e.error_code == x11.BadValue]
assert bad_value_errors, (
"SetMap with totalActs=0 but nonzero per-key action counts "
"was not rejected with BadValue - server is missing the "
@ -215,8 +215,8 @@ class TestXkbSetGeometry:
assert xserver.is_alive, "Server crashed - truncated sections in SetGeometry"
assert isinstance(resp, X11Error), f"Expected an error, got {resp}"
assert resp.error_code == BadLength, (
f"Expected BadLength ({BadLength}), got error code {resp.error_code} - "
assert resp.error_code == x11.BadLength, (
f"Expected BadLength ({x11.BadLength}), got error code {resp.error_code} - "
f"missing bounds check in SetGeometry section parsing"
)
@ -265,7 +265,7 @@ class TestXkbSetGeometry:
resps = xclient.flush_responses(timeout=0.5)
errors = [r for r in resps if isinstance(r, X11Error)]
bad_value_errors = [e for e in errors if e.error_code == BadValue]
bad_value_errors = [e for e in errors if e.error_code == x11.BadValue]
assert bad_value_errors, (
f"SetGeometry with {which_ndx}=200 nOutlines=1 was not rejected "
f"with BadValue - server is missing the {which_ndx} bounds check"
@ -322,7 +322,7 @@ class TestXkbSetGeometry:
# With the fix, we get BadMatch (8) from the color index check.
# Without the fix, the OOB access happens silently and the
# request succeeds (no error), so valgrind catches it.
match_errors = [e for e in errors if e.error_code == BadMatch]
match_errors = [e for e in errors if e.error_code == x11.BadMatch]
assert match_errors, (
f"SetGeometry with {which_color}ColorNdx=nColors was not rejected with "
f"BadMatch - server is missing the off-by-one check"
@ -386,7 +386,7 @@ class TestXkbSetGeometry:
# With the fix, we get BadMatch (8) from the rowUnder >= num_rows check.
# Without the fix, rowUnder == num_rows passes the '>' check and
# the OOB access happens in XkbAddGeomOverlayRow().
match_errors = [e for e in errors if e.error_code == BadMatch]
match_errors = [e for e in errors if e.error_code == x11.BadMatch]
assert match_errors, (
"SetGeometry with rowUnder=1 num_rows=1 was not rejected with "
"BadMatch - server is missing the off-by-one check"

View file

@ -78,24 +78,27 @@ class Extension(StrEnum):
XVIDEO_MC = "XVideo-MotionCompensation"
# X11 core protocol error codes (from X.h)
BadRequest = 1
BadValue = 2
BadWindow = 3
BadPixmap = 4
BadAtom = 5
BadCursor = 6
BadFont = 7
BadMatch = 8
BadDrawable = 9
BadAccess = 10
BadAlloc = 11
BadColor = 12
BadGC = 13
BadIDChoice = 14
BadName = 15
BadLength = 16
BadImplementation = 17
# X11 core protocol error codes -- canonical definitions are in proto/x11.py,
# re-exported here for backward compatibility.
from proto.x11 import ( # noqa: F401
BadAccess,
BadAlloc,
BadAtom,
BadColor,
BadCursor,
BadDrawable,
BadFont,
BadGC,
BadIDChoice,
BadImplementation,
BadLength,
BadMatch,
BadName,
BadPixmap,
BadRequest,
BadValue,
BadWindow,
)
@dataclass