xref: /llvm-project/lldb/packages/Python/lldbsuite/test/lldbgdbclient.py (revision 2238dcc39358353cac21df75c3c3286ab20b8f53)
133c0f93fSPavel Labathimport os
233c0f93fSPavel Labathimport os.path
333c0f93fSPavel Labathimport lldb
433c0f93fSPavel Labathfrom lldbsuite.test.lldbtest import *
533c0f93fSPavel Labathfrom lldbsuite.test.gdbclientutils import *
633c0f93fSPavel Labath
7*2238dcc3SJonas Devlieghere
833c0f93fSPavel Labathclass GDBRemoteTestBase(TestBase):
933c0f93fSPavel Labath    """
1033c0f93fSPavel Labath    Base class for GDB client tests.
1133c0f93fSPavel Labath
1233c0f93fSPavel Labath    This class will setup and start a mock GDB server for the test to use.
1333c0f93fSPavel Labath    It also provides assertPacketLogContains, which simplifies the checking
1433c0f93fSPavel Labath    of packets sent by the client.
1533c0f93fSPavel Labath    """
1633c0f93fSPavel Labath
1733c0f93fSPavel Labath    NO_DEBUG_INFO_TESTCASE = True
1833c0f93fSPavel Labath    server = None
1933c0f93fSPavel Labath    server_socket_class = TCPServerSocket
2033c0f93fSPavel Labath
2133c0f93fSPavel Labath    def setUp(self):
2233c0f93fSPavel Labath        TestBase.setUp(self)
237c8ae65fSPavel Labath        self.server = MockGDBServer(self.server_socket_class())
2433c0f93fSPavel Labath        self.server.start()
2533c0f93fSPavel Labath
2633c0f93fSPavel Labath    def tearDown(self):
2733c0f93fSPavel Labath        # TestBase.tearDown will kill the process, but we need to kill it early
2833c0f93fSPavel Labath        # so its client connection closes and we can stop the server before
2933c0f93fSPavel Labath        # finally calling the base tearDown.
3033c0f93fSPavel Labath        if self.process() is not None:
3133c0f93fSPavel Labath            self.process().Kill()
3233c0f93fSPavel Labath        self.server.stop()
3333c0f93fSPavel Labath        TestBase.tearDown(self)
3433c0f93fSPavel Labath
3533c0f93fSPavel Labath    def createTarget(self, yaml_path):
3633c0f93fSPavel Labath        """
3733c0f93fSPavel Labath        Create a target by auto-generating the object based on the given yaml
3833c0f93fSPavel Labath        instructions.
3933c0f93fSPavel Labath
4033c0f93fSPavel Labath        This will track the generated object so it can be automatically removed
4133c0f93fSPavel Labath        during tearDown.
4233c0f93fSPavel Labath        """
4333c0f93fSPavel Labath        yaml_base, ext = os.path.splitext(yaml_path)
4433c0f93fSPavel Labath        obj_path = self.getBuildArtifact(yaml_base)
4533c0f93fSPavel Labath        self.yaml2obj(yaml_path, obj_path)
4633c0f93fSPavel Labath        return self.dbg.CreateTarget(obj_path)
4733c0f93fSPavel Labath
4833c0f93fSPavel Labath    def connect(self, target):
4933c0f93fSPavel Labath        """
5033c0f93fSPavel Labath        Create a process by connecting to the mock GDB server.
5133c0f93fSPavel Labath
5233c0f93fSPavel Labath        Includes assertions that the process was successfully created.
5333c0f93fSPavel Labath        """
5433c0f93fSPavel Labath        listener = self.dbg.GetListener()
5533c0f93fSPavel Labath        error = lldb.SBError()
56*2238dcc3SJonas Devlieghere        process = target.ConnectRemote(
57*2238dcc3SJonas Devlieghere            listener, self.server.get_connect_url(), "gdb-remote", error
58*2238dcc3SJonas Devlieghere        )
5933c0f93fSPavel Labath        self.assertTrue(error.Success(), error.description)
6033c0f93fSPavel Labath        self.assertTrue(process, PROCESS_IS_VALID)
6133c0f93fSPavel Labath        return process
6233c0f93fSPavel Labath
638ccfcab3SPavel Labath    def assertPacketLogContains(self, packets, log=None):
6433c0f93fSPavel Labath        """
6533c0f93fSPavel Labath        Assert that the mock server's packet log contains the given packets.
6633c0f93fSPavel Labath
6733c0f93fSPavel Labath        The packet log includes all packets sent by the client and received
6833c0f93fSPavel Labath        by the server.  This fuction makes it easy to verify that the client
6933c0f93fSPavel Labath        sent the expected packets to the server.
7033c0f93fSPavel Labath
7133c0f93fSPavel Labath        The check does not require that the packets be consecutive, but does
7233c0f93fSPavel Labath        require that they are ordered in the log as they ordered in the arg.
7333c0f93fSPavel Labath        """
748ccfcab3SPavel Labath        if log is None:
758ccfcab3SPavel Labath            log = self.server.responder.packetLog
7633c0f93fSPavel Labath        i = 0
7733c0f93fSPavel Labath        j = 0
7833c0f93fSPavel Labath
7933c0f93fSPavel Labath        while i < len(packets) and j < len(log):
8033c0f93fSPavel Labath            if log[j] == packets[i]:
8133c0f93fSPavel Labath                i += 1
8233c0f93fSPavel Labath            j += 1
8333c0f93fSPavel Labath        if i < len(packets):
84*2238dcc3SJonas Devlieghere            self.fail(
85*2238dcc3SJonas Devlieghere                "Did not receive: %s\nLast 10 packets:\n\t%s"
86*2238dcc3SJonas Devlieghere                % (packets[i], "\n\t".join(log))
87*2238dcc3SJonas Devlieghere            )
8833c0f93fSPavel Labath
8933c0f93fSPavel Labath
9033c0f93fSPavel Labathclass GDBPlatformClientTestBase(GDBRemoteTestBase):
9133c0f93fSPavel Labath    """
9233c0f93fSPavel Labath    Base class for platform server clients.
9333c0f93fSPavel Labath
9433c0f93fSPavel Labath    This class extends GDBRemoteTestBase by automatically connecting
9533c0f93fSPavel Labath    via "platform connect" in the setUp() method.
9633c0f93fSPavel Labath    """
9733c0f93fSPavel Labath
9833c0f93fSPavel Labath    def setUp(self):
9933c0f93fSPavel Labath        super().setUp()
10033c0f93fSPavel Labath        self.runCmd("platform select remote-gdb-server")
10133c0f93fSPavel Labath        self.runCmd("platform connect " + self.server.get_connect_url())
10233c0f93fSPavel Labath        self.assertTrue(self.dbg.GetSelectedPlatform().IsConnected())
10333c0f93fSPavel Labath
10433c0f93fSPavel Labath    def tearDown(self):
10533c0f93fSPavel Labath        self.dbg.GetSelectedPlatform().DisconnectRemote()
10633c0f93fSPavel Labath        super().tearDown()
107