xref: /llvm-project/lldb/test/API/functionalities/gdb_remote_client/TestPlatformClient.py (revision 2238dcc39358353cac21df75c3c3286ab20b8f53)
1import lldb
2import binascii
3import os
4import time
5from lldbsuite.test.lldbtest import *
6from lldbsuite.test.decorators import *
7from lldbsuite.test.gdbclientutils import *
8from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase
9
10
11def hexlify(string):
12    return binascii.hexlify(string.encode()).decode()
13
14
15class TestPlatformClient(GDBRemoteTestBase):
16    def test_process_list_with_all_users(self):
17        """Test connecting to a remote linux platform"""
18
19        class MyResponder(MockGDBServerResponder):
20            def __init__(self):
21                MockGDBServerResponder.__init__(self)
22                self.currentQsProc = 0
23                self.all_users = False
24
25            def qfProcessInfo(self, packet):
26                if "all_users:1" in packet:
27                    self.all_users = True
28                    name = hexlify("/a/test_process")
29                    args = "-".join(
30                        map(
31                            hexlify,
32                            ["/system/bin/sh", "-c", "/data/local/tmp/lldb-server"],
33                        )
34                    )
35                    return (
36                        "pid:10;ppid:1;uid:2;gid:3;euid:4;egid:5;name:"
37                        + name
38                        + ";args:"
39                        + args
40                        + ";"
41                    )
42                else:
43                    self.all_users = False
44                    return "E04"
45
46            def qsProcessInfo(self):
47                if self.all_users:
48                    if self.currentQsProc == 0:
49                        self.currentQsProc = 1
50                        name = hexlify("/b/another_test_process")
51                        # This intentionally has a badly encoded argument
52                        args = "X".join(map(hexlify, ["/system/bin/ls", "--help"]))
53                        return (
54                            "pid:11;ppid:2;uid:3;gid:4;euid:5;egid:6;name:"
55                            + name
56                            + ";args:"
57                            + args
58                            + ";"
59                        )
60                    elif self.currentQsProc == 1:
61                        self.currentQsProc = 0
62                        return "E04"
63                else:
64                    return "E04"
65
66        self.server.responder = MyResponder()
67
68        try:
69            self.runCmd("platform select remote-linux")
70            self.runCmd("platform connect " + self.server.get_connect_url())
71            self.assertTrue(self.dbg.GetSelectedPlatform().IsConnected())
72            self.expect(
73                "platform process list -x",
74                substrs=[
75                    "2 matching processes were found",
76                    "test_process",
77                    "another_test_process",
78                ],
79            )
80            self.expect(
81                "platform process list -xv",
82                substrs=[
83                    "PID    PARENT USER       GROUP      EFF USER   EFF GROUP  TRIPLE                         ARGUMENTS",
84                    "10     1      2          3          4          5                                         /system/bin/sh -c /data/local/tmp/lldb-server",
85                    "11     2      3          4          5          6",
86                ],
87            )
88            self.expect(
89                "platform process list -xv", substrs=["/system/bin/ls"], matching=False
90            )
91            self.expect(
92                "platform process list",
93                error=True,
94                substrs=[
95                    'error: no processes were found on the "remote-linux" platform'
96                ],
97            )
98        finally:
99            self.dbg.GetSelectedPlatform().DisconnectRemote()
100
101    class TimeoutResponder(MockGDBServerResponder):
102        """A mock server, which takes a very long time to compute the working
103        directory."""
104
105        def __init__(self):
106            MockGDBServerResponder.__init__(self)
107
108        def qGetWorkingDir(self):
109            time.sleep(10)
110            return hexlify("/foo/bar")
111
112    def test_no_timeout(self):
113        """Test that we honor the timeout setting. With a large enough timeout,
114        we should get the CWD successfully."""
115
116        self.server.responder = TestPlatformClient.TimeoutResponder()
117        self.runCmd("settings set plugin.process.gdb-remote.packet-timeout 30")
118        plat = lldb.SBPlatform("remote-linux")
119        try:
120            self.assertSuccess(
121                plat.ConnectRemote(
122                    lldb.SBPlatformConnectOptions(self.server.get_connect_url())
123                )
124            )
125            self.assertEqual(plat.GetWorkingDirectory(), "/foo/bar")
126        finally:
127            plat.DisconnectRemote()
128
129    def test_timeout(self):
130        """Test that we honor the timeout setting. With a small timeout, CWD
131        retrieval should fail."""
132
133        self.server.responder = TestPlatformClient.TimeoutResponder()
134        self.runCmd("settings set plugin.process.gdb-remote.packet-timeout 3")
135        plat = lldb.SBPlatform("remote-linux")
136        try:
137            self.assertSuccess(
138                plat.ConnectRemote(
139                    lldb.SBPlatformConnectOptions(self.server.get_connect_url())
140                )
141            )
142            self.assertIsNone(plat.GetWorkingDirectory())
143        finally:
144            plat.DisconnectRemote()
145