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
10def hexlify(string):
11    return binascii.hexlify(string.encode()).decode()
12
13class TestPlatformClient(GDBRemoteTestBase):
14
15    mydir = TestBase.compute_mydir(__file__)
16
17    def test_process_list_with_all_users(self):
18        """Test connecting to a remote linux platform"""
19
20        class MyResponder(MockGDBServerResponder):
21            def __init__(self):
22                MockGDBServerResponder.__init__(self)
23                self.currentQsProc = 0
24                self.all_users = False
25
26            def qfProcessInfo(self, packet):
27                if "all_users:1" in packet:
28                    self.all_users = True
29                    name = hexlify("/a/test_process")
30                    args = "-".join(map(hexlify,
31                                        ["/system/bin/sh", "-c", "/data/local/tmp/lldb-server"]))
32                    return "pid:10;ppid:1;uid:2;gid:3;euid:4;egid:5;name:" + name + ";args:" + args + ";"
33                else:
34                    self.all_users = False
35                    return "E04"
36
37            def qsProcessInfo(self):
38                if self.all_users:
39                    if self.currentQsProc == 0:
40                        self.currentQsProc = 1
41                        name = hexlify("/b/another_test_process")
42                        # This intentionally has a badly encoded argument
43                        args = "X".join(map(hexlify,
44                                            ["/system/bin/ls", "--help"]))
45                        return "pid:11;ppid:2;uid:3;gid:4;euid:5;egid:6;name:" + name + ";args:" + args + ";"
46                    elif self.currentQsProc == 1:
47                        self.currentQsProc = 0
48                        return "E04"
49                else:
50                    return "E04"
51
52        self.server.responder = MyResponder()
53
54        try:
55            self.runCmd("platform select remote-linux")
56            self.runCmd("platform connect " + self.server.get_connect_url())
57            self.assertTrue(self.dbg.GetSelectedPlatform().IsConnected())
58            self.expect("platform process list -x",
59                        substrs=["2 matching processes were found", "test_process", "another_test_process"])
60            self.expect("platform process list -xv",
61                        substrs=[
62                            "PID    PARENT USER       GROUP      EFF USER   EFF GROUP  TRIPLE                         ARGUMENTS",
63                            "10     1      2          3          4          5                                         /system/bin/sh -c /data/local/tmp/lldb-server",
64                            "11     2      3          4          5          6"])
65            self.expect("platform process list -xv", substrs=["/system/bin/ls"], matching=False)
66            self.expect("platform process list",
67                        error=True,
68                        substrs=["error: no processes were found on the \"remote-linux\" platform"])
69        finally:
70            self.dbg.GetSelectedPlatform().DisconnectRemote()
71
72    class TimeoutResponder(MockGDBServerResponder):
73        """A mock server, which takes a very long time to compute the working
74        directory."""
75        def __init__(self):
76            MockGDBServerResponder.__init__(self)
77
78        def qGetWorkingDir(self):
79            time.sleep(10)
80            return hexlify("/foo/bar")
81
82    def test_no_timeout(self):
83        """Test that we honor the timeout setting. With a large enough timeout,
84        we should get the CWD successfully."""
85
86        self.server.responder = TestPlatformClient.TimeoutResponder()
87        self.runCmd("settings set plugin.process.gdb-remote.packet-timeout 30")
88        plat = lldb.SBPlatform("remote-linux")
89        try:
90            self.assertSuccess(plat.ConnectRemote(lldb.SBPlatformConnectOptions(
91                self.server.get_connect_url())))
92            self.assertEqual(plat.GetWorkingDirectory(), "/foo/bar")
93        finally:
94            plat.DisconnectRemote()
95
96    def test_timeout(self):
97        """Test that we honor the timeout setting. With a small timeout, CWD
98        retrieval should fail."""
99
100        self.server.responder = TestPlatformClient.TimeoutResponder()
101        self.runCmd("settings set plugin.process.gdb-remote.packet-timeout 3")
102        plat = lldb.SBPlatform("remote-linux")
103        try:
104            self.assertSuccess(plat.ConnectRemote(lldb.SBPlatformConnectOptions(
105                self.server.get_connect_url())))
106            self.assertIsNone(plat.GetWorkingDirectory())
107        finally:
108            plat.DisconnectRemote()
109