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