| import lldb |
| from lldbsuite.test.lldbtest import * |
| from lldbsuite.test.decorators import * |
| import lldbsuite.test.lldbutil as lldbutil |
| import json |
| |
| |
| class TestSimulatorPlatformLaunching(TestBase): |
| NO_DEBUG_INFO_TESTCASE = True |
| |
| def check_load_commands(self, expected_load_command): |
| """sanity check the built binary for the expected number of load commands""" |
| load_cmds = subprocess.check_output( |
| ["otool", "-l", self.getBuildArtifact()] |
| ).decode("utf-8") |
| found = 0 |
| for line in load_cmds.split("\n"): |
| if expected_load_command in line: |
| found += 1 |
| self.assertEqual( |
| found, |
| 1, |
| "wrong number of load commands for {}".format(expected_load_command), |
| ) |
| |
| def check_debugserver(self, log, expected_platform, expected_version): |
| """scan the debugserver packet log""" |
| process_info = lldbutil.packetlog_get_process_info(log) |
| self.assertIn("ostype", process_info) |
| self.assertEqual(process_info["ostype"], expected_platform) |
| dylib_info = lldbutil.packetlog_get_dylib_info(log) |
| self.assertTrue(dylib_info) |
| aout_info = None |
| for image in dylib_info["images"]: |
| if image["pathname"].endswith("a.out"): |
| aout_info = image |
| self.assertTrue(aout_info) |
| self.assertEqual(aout_info["min_version_os_name"], expected_platform) |
| if expected_version: |
| self.assertEqual(aout_info["min_version_os_sdk"], expected_version) |
| |
| def run_with( |
| self, arch, os, vers, env, expected_load_command, expected_platform=None |
| ): |
| env_list = [env] if env else [] |
| triple = "-".join([arch, "apple", os + vers] + env_list) |
| sdk = lldbutil.get_xcode_sdk(os, env) |
| |
| if not vers: |
| vers = lldbutil.get_xcode_sdk_version(sdk) |
| |
| version_min = "" |
| if env == "simulator": |
| version_min = "-m{}-simulator-version-min={}".format(os, vers) |
| elif os == "macosx": |
| version_min = "-m{}-version-min={}".format(os, vers) |
| |
| sdk_root = lldbutil.get_xcode_sdk_root(sdk) |
| clang = lldbutil.get_xcode_clang(sdk) |
| |
| print(triple) |
| |
| self.build( |
| dictionary={ |
| "ARCH": arch, |
| "ARCH_CFLAGS": "-target {} {}".format(triple, version_min), |
| "SDKROOT": sdk_root, |
| "USE_SYSTEM_STDLIB": 1, |
| }, |
| compiler=clang, |
| ) |
| |
| self.check_load_commands(expected_load_command) |
| log = self.getBuildArtifact("packets.log") |
| self.expect("log enable gdb-remote packets -f " + log) |
| lldbutil.run_to_source_breakpoint( |
| self, "break here", lldb.SBFileSpec("hello.cpp") |
| ) |
| triple_re = "-".join([arch, "apple", os + vers + ".*"] + env_list) |
| self.expect("image list -b -t", patterns=[r"a\.out " + triple_re]) |
| self.check_debugserver(log, os + env, vers) |
| |
| if expected_platform is not None: |
| # Verify the platform name. |
| self.expect( |
| "platform status", |
| patterns=[r"Platform: " + expected_platform + "-simulator"], |
| ) |
| |
| # Launch exe in simulator and verify that `platform process list` can find the process. |
| # This separate launch is needed because the command ignores processes which are being debugged. |
| device_udid = lldbutil.get_latest_apple_simulator( |
| expected_platform, self.trace |
| ) |
| _, matched_strings = lldbutil.launch_exe_in_apple_simulator( |
| device_udid, |
| self.getBuildArtifact("a.out"), |
| exe_args=[], |
| stderr_lines_to_read=1, # in hello.cpp, the pid is printed first |
| stderr_patterns=[r"PID: (.*)"], |
| log=self.trace, |
| ) |
| |
| # Make sure we found the PID. |
| self.assertIsNotNone(matched_strings[0]) |
| pid = int(matched_strings[0]) |
| |
| # Verify that processes on the platform can be listed. |
| self.expect( |
| "platform process list", |
| patterns=[ |
| r"\d+ matching processes were found on \"%s-simulator\"" |
| % expected_platform, |
| r"%d .+ a.out" % pid, |
| ], |
| ) |
| |
| @skipIfAsan |
| @skipUnlessDarwin |
| @skipIfDarwinEmbedded |
| @apple_simulator_test("iphone") |
| def test_ios(self): |
| """Test running an iOS simulator binary""" |
| self.run_with( |
| arch=self.getArchitecture(), |
| os="ios", |
| vers="", |
| env="simulator", |
| expected_load_command="LC_BUILD_VERSION", |
| expected_platform="ios", |
| ) |
| |
| @skipIfAsan |
| @skipUnlessDarwin |
| @skipIfDarwinEmbedded |
| @apple_simulator_test("appletv") |
| def test_tvos(self): |
| """Test running an tvOS simulator binary""" |
| self.run_with( |
| arch=self.getArchitecture(), |
| os="tvos", |
| vers="", |
| env="simulator", |
| expected_load_command="LC_BUILD_VERSION", |
| ) |
| |
| @skipIfAsan |
| @skipUnlessDarwin |
| @skipIfDarwinEmbedded |
| @apple_simulator_test("watch") |
| @skipIfDarwin # rdar://problem/64552748 |
| @skipIf(archs=["arm64", "arm64e"]) |
| def test_watchos_i386(self): |
| """Test running a 32-bit watchOS simulator binary""" |
| self.run_with( |
| arch="i386", |
| os="watchos", |
| vers="", |
| env="simulator", |
| expected_load_command="LC_BUILD_VERSION", |
| ) |
| |
| @skipIfAsan |
| @skipUnlessDarwin |
| @skipIfDarwinEmbedded |
| @apple_simulator_test("watch") |
| @skipIfDarwin # rdar://problem/64552748 |
| @skipIf(archs=["i386", "x86_64"]) |
| def test_watchos_armv7k(self): |
| """Test running a 32-bit watchOS simulator binary""" |
| self.run_with( |
| arch="armv7k", |
| os="watchos", |
| vers="", |
| env="simulator", |
| expected_load_command="LC_BUILD_VERSION", |
| ) |
| |
| # |
| # Back-deployment tests. |
| # |
| # Older Mach-O versions used less expressive load commands, such |
| # as LC_VERSION_MIN_IPHONEOS that wouldn't distinguish between ios |
| # and ios-simulator. When targeting a simulator on Apple Silicon |
| # macOS, however, these legacy load commands are never generated. |
| # |
| |
| @skipUnlessDarwin |
| @skipIfDarwinEmbedded |
| @skipIf(archs=["arm64", "arm64e"]) |
| def test_lc_version_min_macosx(self): |
| """Test running a back-deploying non-simulator MacOS X binary""" |
| self.run_with( |
| arch=self.getArchitecture(), |
| os="macosx", |
| vers="10.9", |
| env="", |
| expected_load_command="LC_VERSION_MIN_MACOSX", |
| ) |
| |
| @skipIfAsan |
| @skipUnlessDarwin |
| @skipIfDarwinEmbedded |
| @apple_simulator_test("iphone") |
| @skipIf(archs=["arm64", "arm64e"]) |
| def test_lc_version_min_iphoneos(self): |
| """Test running a back-deploying iOS simulator binary |
| with a legacy iOS load command""" |
| self.run_with( |
| arch=self.getArchitecture(), |
| os="ios", |
| vers="11.0", |
| env="simulator", |
| expected_load_command="LC_VERSION_MIN_IPHONEOS", |
| ) |
| |
| @skipIfAsan |
| @skipUnlessDarwin |
| @skipIfDarwinEmbedded |
| @apple_simulator_test("iphone") |
| @skipIf(archs=["arm64", "arm64e"]) |
| def test_ios_backdeploy_x86(self): |
| """Test running a back-deploying iOS simulator binary |
| with a legacy iOS load command""" |
| self.run_with( |
| arch=self.getArchitecture(), |
| os="ios", |
| vers="13.0", |
| env="simulator", |
| expected_load_command="LC_BUILD_VERSION", |
| ) |
| |
| @skipIfAsan |
| @skipUnlessDarwin |
| @skipIfDarwinEmbedded |
| @apple_simulator_test("iphone") |
| @skipIf(archs=["i386", "x86_64"]) |
| def test_ios_backdeploy_apple_silicon(self): |
| """Test running a back-deploying iOS simulator binary""" |
| self.run_with( |
| arch=self.getArchitecture(), |
| os="ios", |
| vers="14.0", |
| env="simulator", |
| expected_load_command="LC_BUILD_VERSION", |
| ) |
| |
| @skipIfAsan |
| @skipUnlessDarwin |
| @skipIfDarwinEmbedded |
| @apple_simulator_test("appletv") |
| @skipIf(archs=["arm64", "arm64e"]) |
| def test_lc_version_min_tvos(self): |
| """Test running a back-deploying tvOS simulator binary |
| with a legacy tvOS load command""" |
| self.run_with( |
| arch=self.getArchitecture(), |
| os="tvos", |
| vers="11.0", |
| env="simulator", |
| expected_load_command="LC_VERSION_MIN_TVOS", |
| ) |
| |
| @skipIfAsan |
| @skipUnlessDarwin |
| @skipIfDarwinEmbedded |
| @apple_simulator_test("appletv") |
| @skipIf(archs=["i386", "x86_64"]) |
| def test_tvos_backdeploy_apple_silicon(self): |
| """Test running a back-deploying tvOS simulator binary""" |
| self.run_with( |
| arch=self.getArchitecture(), |
| os="tvos", |
| vers="14.0", |
| env="simulator", |
| expected_load_command="LC_BUILD_VERSION", |
| ) |
| |
| @skipIfAsan |
| @skipUnlessDarwin |
| @skipIfDarwinEmbedded |
| @apple_simulator_test("watch") |
| @skipIf(archs=["arm64", "arm64e"]) |
| @skipIfDarwin # rdar://problem/64552748 |
| def test_lc_version_min_watchos(self): |
| """Test running a back-deploying watchOS simulator binary |
| with a legacy watchOS load command""" |
| self.run_with( |
| arch="i386", |
| os="watchos", |
| vers="4.0", |
| env="simulator", |
| expected_load_command="LC_VERSION_MIN_WATCHOS", |
| ) |
| |
| @skipIfAsan |
| @skipUnlessDarwin |
| @skipIfDarwinEmbedded |
| @apple_simulator_test("watch") |
| @skipIf(archs=["arm64", "arm64e"]) |
| @skipIfDarwin # rdar://problem/64552748 |
| def test_watchos_backdeploy_apple_silicon(self): |
| """Test running a back-deploying watchOS simulator binary""" |
| self.run_with( |
| arch="armv7k", |
| os="watchos", |
| vers="4.0", |
| env="simulator", |
| expected_load_command="LC_BUILD_VERSION", |
| ) |