xref: /llvm-project/lldb/test/API/commands/platform/sdk/TestPlatformSDK.py (revision 0fc578664809d9f808d24a91e50a68d6bfa22118)
1import lldb
2
3from lldbsuite.test.decorators import *
4from lldbsuite.test.lldbtest import *
5from lldbsuite.test import lldbutil
6from lldbgdbserverutils import get_debugserver_exe
7
8import os
9import platform
10import shutil
11import time
12import socket
13
14
15class PlatformSDKTestCase(TestBase):
16    NO_DEBUG_INFO_TESTCASE = True
17
18    # The port used by debugserver.
19    PORT = 54637
20
21    # The number of attempts.
22    ATTEMPTS = 10
23
24    # Time given to the binary to launch and to debugserver to attach to it for
25    # every attempt. We'll wait a maximum of 10 times 2 seconds while the
26    # inferior will wait 10 times 10 seconds.
27    TIMEOUT = 2
28
29    def no_debugserver(self):
30        if get_debugserver_exe() is None:
31            return "no debugserver"
32        return None
33
34    def port_not_available(self):
35        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
36        if s.connect_ex(("127.0.0.1", self.PORT)) == 0:
37            return "{} not available".format(self.PORT)
38        return None
39
40    @no_debug_info_test
41    @skipUnlessDarwin
42    @skipTestIfFn(no_debugserver)
43    @skipTestIfFn(port_not_available)
44    @skipIfRemote
45    def test_macos_sdk(self):
46        self.build()
47
48        exe = self.getBuildArtifact("a.out")
49        token = self.getBuildArtifact("token")
50
51        # Remove the old token.
52        try:
53            os.remove(token)
54        except:
55            pass
56
57        # Create a fake 'SDK' directory.
58        test_home = os.path.join(self.getBuildDir(), "fake_home.noindex")
59        test_home = os.path.realpath(test_home)
60        macos_version = platform.mac_ver()[0]
61        sdk_dir = os.path.join(
62            test_home,
63            "Library",
64            "Developer",
65            "Xcode",
66            "macOS DeviceSupport",
67            macos_version,
68        )
69        symbols_dir = os.path.join(sdk_dir, "Symbols")
70        lldbutil.mkdir_p(symbols_dir)
71
72        # Save the current home directory and restore it afterwards.
73        old_home = os.getenv("HOME")
74
75        def cleanup():
76            if not old_home:
77                del os.environ["HOME"]
78            else:
79                os.environ["HOME"] = old_home
80
81        self.addTearDownHook(cleanup)
82        os.environ["HOME"] = test_home
83
84        # Launch our test binary.
85        inferior = self.spawnSubprocess(exe, [token])
86        pid = inferior.pid
87
88        # Wait for the binary to launch.
89        lldbutil.wait_for_file_on_target(self, token)
90
91        # Move the binary into the 'SDK'.
92        rel_exe_path = os.path.relpath(os.path.realpath(exe), "/")
93        exe_sdk_path = os.path.join(symbols_dir, rel_exe_path)
94        lldbutil.mkdir_p(os.path.dirname(exe_sdk_path))
95        shutil.move(exe, exe_sdk_path)
96
97        # Attach to it with debugserver.
98        debugserver = get_debugserver_exe()
99        debugserver_args = ["localhost:{}".format(self.PORT), "--attach={}".format(pid)]
100        self.spawnSubprocess(debugserver, debugserver_args)
101
102        # Select the platform.
103        self.expect("platform select remote-macosx", substrs=[sdk_dir])
104
105        # Connect to debugserver
106        interpreter = self.dbg.GetCommandInterpreter()
107        connected = False
108        for i in range(self.ATTEMPTS):
109            result = lldb.SBCommandReturnObject()
110            interpreter.HandleCommand("gdb-remote {}".format(self.PORT), result)
111            connected = result.Succeeded()
112            if connected:
113                break
114            time.sleep(self.TIMEOUT)
115
116        self.assertTrue(connected, "could not connect to debugserver")
117
118        # Make sure the image was loaded from the 'SDK'.
119        self.expect("image list", substrs=[exe_sdk_path])
120