From 719107cf425a7c29fb07a55f898c446d8c84568a Mon Sep 17 00:00:00 2001 From: Yixin Wang Date: Mon, 25 Aug 2025 10:43:50 -0700 Subject: [PATCH] Test Mock GPU sends expected packets --- lldb/test/API/gpu/mock/packets/Makefile | 2 + .../mock/packets/TestPacketsMockGpuPlugin.py | 159 ++++++++++++++++++ .../test/API/gpu/mock/packets/hello_world.cpp | 20 +++ 3 files changed, 181 insertions(+) create mode 100644 lldb/test/API/gpu/mock/packets/Makefile create mode 100644 lldb/test/API/gpu/mock/packets/TestPacketsMockGpuPlugin.py create mode 100644 lldb/test/API/gpu/mock/packets/hello_world.cpp diff --git a/lldb/test/API/gpu/mock/packets/Makefile b/lldb/test/API/gpu/mock/packets/Makefile new file mode 100644 index 0000000000000..245068df72a69 --- /dev/null +++ b/lldb/test/API/gpu/mock/packets/Makefile @@ -0,0 +1,2 @@ +CXX_SOURCES := hello_world.cpp +include Makefile.rules diff --git a/lldb/test/API/gpu/mock/packets/TestPacketsMockGpuPlugin.py b/lldb/test/API/gpu/mock/packets/TestPacketsMockGpuPlugin.py new file mode 100644 index 0000000000000..ebb0ab2436391 --- /dev/null +++ b/lldb/test/API/gpu/mock/packets/TestPacketsMockGpuPlugin.py @@ -0,0 +1,159 @@ +""" +Packets tests for the Mock GPU Plugin. +""" + +import json + +import gdbremote_testcase +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * + +# Breakpoint identifiers (corresponds to LLDBServerPluginMockGPU.cpp) +BREAKPOINT_ID_INITIALIZE = 1 +BREAKPOINT_ID_SHLIB_LOAD = 2 +BREAKPOINT_ID_THIRD_STOP = 3 + + +class PacketsMockGpuTestCase(gdbremote_testcase.GdbRemoteTestCaseBase): + + def setUp(self): + super(PacketsMockGpuTestCase, self).setUp() + self.build() + + def _make_breakpoint_packet( + self, identifier, function_name, symbol_names, symbol_values + ): + data = { + "breakpoint": { + "addr_info": None, + "identifier": identifier, + "name_info": {"function_name": function_name, "shlib": "a.out"}, + "symbol_names": symbol_names, + }, + "plugin_name": "mock-gpu", + "symbol_values": symbol_values, + } + # GDB Remote Protocol escaping: } becomes }] + return json.dumps(data, separators=(",", ":")).replace("}", "}]") + + def test_ordered_gpu_plugin_packet_sequence(self): + """Test the full ordered packet exchange for the Mock GPU Plugin.""" + + _procs = self.prep_debug_monitor_and_inferior() + self.assertIsNotNone(_procs) + + # Define the expected sequence of packets and their content checks + packet_sequence = [ + { + "send": "jGPUPluginInitialize", + "payload": None, + "expect_regex": r"^\$(\[.*\])#[0-9a-fA-F]{2}$", + "content_checks": [ + '"breakpoints":', + '"plugin_name":"mock-gpu"', + f'"identifier":{BREAKPOINT_ID_INITIALIZE}', + '"function_name":"gpu_initialize"', + '"shlib":"a.out"', + '"symbol_names":["gpu_shlib_load"]', + ], + }, + { + "send": "jGPUPluginBreakpointHit", + "payload": self._make_breakpoint_packet( + BREAKPOINT_ID_INITIALIZE, + "gpu_initialize", + ["gpu_shlib_load"], + [{"name": "gpu_shlib_load", "value": 4198710}], + ), + "expect_regex": r"^\$(.*)#[0-9a-fA-F]{2}$", + "content_checks": [ + '"breakpoints":', + f'"identifier":{BREAKPOINT_ID_SHLIB_LOAD}', + '"load_address":', + '"connect_info":', + '"connect_url":', + "localhost:", + '"load_libraries":false', + '"plugin_name":"mock-gpu"', + '"disable_bp":true', + ], + }, + { + "send": "jGPUPluginBreakpointHit", + "payload": self._make_breakpoint_packet( + BREAKPOINT_ID_SHLIB_LOAD, + "gpu_shlib_load", + ["gpu_third_stop"], + [{"name": "gpu_third_stop", "value": 4210736}], + ), + "expect_regex": r"^\$(.*)#[0-9a-fA-F]{2}$", + "content_checks": [ + '"load_libraries":true', + '"plugin_name":"mock-gpu"', + '"disable_bp":false', + ], + }, + { + "send": "jGPUPluginBreakpointHit", + "payload": self._make_breakpoint_packet( + BREAKPOINT_ID_THIRD_STOP, "gpu_third_stop", [], [] + ), + "expect_regex": r"^\$(.*)#[0-9a-fA-F]{2}$", + "content_checks": [ + '"load_libraries":true', + '"plugin_name":"mock-gpu"', + '"disable_bp":false', + ], + }, + { + "send": "jGPUPluginBreakpointHit", + "payload": self._make_breakpoint_packet( + BREAKPOINT_ID_SHLIB_LOAD, + "gpu_shlib_load", + ["gpu_third_stop"], + [{"name": "g_shlib_list", "value": 4210736}], + ), + "expect_regex": r"^\$(.*)#[0-9a-fA-F]{2}$", + "content_checks": [ + '"load_libraries":true', + '"plugin_name":"mock-gpu"', + '"disable_bp":false', + ], + }, + ] + + for idx, pkt in enumerate(packet_sequence): + print(f"PACKET {pkt['send']}") + print(f"PAYLOAD {pkt['payload']}") + + raw = ( + f"${pkt['send']}" + if pkt["payload"] is None + else f"${pkt['send']}:{pkt['payload']}" + ) + checksum = sum(ord(c) for c in raw[1:]) % 256 + packet_str = f"{raw}#{checksum:02x}" + + self.test_sequence.add_log_lines( + [ + f"read packet: {packet_str}", + { + "direction": "send", + "regex": pkt["expect_regex"], + "capture": {1: f"response_{idx}"}, + }, + ], + True, + ) + + context = self.expect_gdbremote_sequence() + self.assertIsNotNone(context) + response = context.get(f"response_{idx}") + self.assertIsNotNone(response) + + for check in pkt["content_checks"]: + self.assertIn( + check, + response, + f"Packet {idx} missing '{check}' in response: {response}", + ) diff --git a/lldb/test/API/gpu/mock/packets/hello_world.cpp b/lldb/test/API/gpu/mock/packets/hello_world.cpp new file mode 100644 index 0000000000000..248b2f3f18c7b --- /dev/null +++ b/lldb/test/API/gpu/mock/packets/hello_world.cpp @@ -0,0 +1,20 @@ +#include + +struct ShlibInfo { + const char *path; + ShlibInfo *next; +}; + +ShlibInfo g_shlib_list = {"/tmp/a.out", nullptr}; + +int gpu_initialize() { return puts(__FUNCTION__); } +int gpu_shlib_load() { return puts(__FUNCTION__); } +int gpu_third_stop() { return puts(__FUNCTION__); } + +int main(int argc, const char **argv) { + gpu_initialize(); + gpu_shlib_load(); + gpu_third_stop(); + gpu_shlib_load(); + return 0; // BREAKPOINT +}