b803d9e262e3a8a02446341b1caa81ea35c93844
[WebKit-https.git] / Tools / Scripts / webkitpy / port / ios_simulator.py
1 # Copyright (C) 2014-2017 Apple Inc. All rights reserved.
2 #
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions
5 # are met:
6 # 1.  Redistributions of source code must retain the above copyright
7 #     notice, this list of conditions and the following disclaimer.
8 # 2.  Redistributions in binary form must reproduce the above copyright
9 #     notice, this list of conditions and the following disclaimer in the
10 #     documentation and/or other materials provided with the distribution.
11 #
12 # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
13 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15 # DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
16 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
18 # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
19 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
20 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
21 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22
23 import logging
24
25 from webkitpy.common.memoized import memoized
26 from webkitpy.common.version import Version
27 from webkitpy.port.config import apple_additions
28 from webkitpy.port.ios import IOSPort
29 from webkitpy.xcode.device_type import DeviceType
30 from webkitpy.xcode.simulated_device import DeviceRequest, SimulatedDeviceManager
31
32
33 _log = logging.getLogger(__name__)
34
35
36 class IOSSimulatorPort(IOSPort):
37     port_name = "ios-simulator"
38
39     FUTURE_VERSION = 'future'
40     ARCHITECTURES = ['x86_64', 'x86']
41     DEFAULT_ARCHITECTURE = 'x86_64'
42
43     DEFAULT_DEVICE_CLASS = 'iPhone SE'
44     CUSTOM_DEVICE_CLASSES = ['iPad', 'iPhone 7']
45     SDK = apple_additions().get_sdk('iphonesimulator') if apple_additions() else 'iphonesimulator'
46
47     def __init__(self, host, port_name, **kwargs):
48         super(IOSSimulatorPort, self).__init__(host, port_name, **kwargs)
49
50         optional_device_class = self.get_option('device_class')
51         self._device_class = optional_device_class if optional_device_class else self.DEFAULT_DEVICE_CLASS
52         _log.debug('IOSSimulatorPort _device_class is %s', self._device_class)
53
54     def _device_for_worker_number_map(self):
55         return SimulatedDeviceManager.INITIALIZED_DEVICES
56
57     @staticmethod
58     def _version_from_name(name):
59         if len(name.split('-')) > 2 and name.split('-')[2].isdigit():
60             return Version.from_string(name.split('-')[2])
61         return None
62
63     @memoized
64     def ios_version(self):
65         if self.get_option('version'):
66             return Version.from_string(self.get_option('version'))
67         return IOSSimulatorPort._version_from_name(self._name) if IOSSimulatorPort._version_from_name(self._name) else self.host.platform.xcode_sdk_version('iphonesimulator')
68
69     @memoized
70     def default_child_processes(self):
71         def booted_ios_devices_filter(device):
72             if not device.platform_device.is_booted_or_booting():
73                 return False
74             return device.platform_device.device_type in DeviceType(software_variant='iOS',
75                                                                     software_version=self.ios_version())
76
77         if not self.get_option('dedicated_simulators', False):
78             num_booted_sims = len(SimulatedDeviceManager.device_by_filter(booted_ios_devices_filter, host=self.host))
79             if num_booted_sims:
80                 return num_booted_sims
81         return SimulatedDeviceManager.max_supported_simulators(self.host)
82
83     def _build_driver_flags(self):
84         archs = ['ARCHS=i386'] if self.architecture() == 'x86' else []
85         sdk = ['--sdk', self.SDK]
86         return archs + sdk
87
88     def _set_device_class(self, device_class):
89         self._device_class = device_class if device_class else self.DEFAULT_DEVICE_CLASS
90
91     def _create_devices(self, device_class):
92         self._set_device_class(device_class)
93         device_type = DeviceType.from_string(self._device_class, self.ios_version())
94
95         _log.debug('')
96         _log.debug('creating devices for {}'.format(device_type))
97
98         request = DeviceRequest(
99             device_type,
100             use_booted_simulator=not self.get_option('dedicated_simulators', False),
101             use_existing_simulator=False,
102             allow_incomplete_match=True,
103         )
104         SimulatedDeviceManager.initialize_devices([request] * self.child_processes(), self.host)
105
106     def clean_up_test_run(self):
107         super(IOSSimulatorPort, self).clean_up_test_run()
108         _log.debug("clean_up_test_run")
109
110         SimulatedDeviceManager.tear_down(self.host)
111
112     def environment_for_api_tests(self):
113         no_prefix = super(IOSSimulatorPort, self).environment_for_api_tests()
114         result = {}
115         SIMCTL_ENV_PREFIX = 'SIMCTL_CHILD_'
116         for value in no_prefix:
117             if not value.startswith(SIMCTL_ENV_PREFIX):
118                 result[SIMCTL_ENV_PREFIX + value] = no_prefix[value]
119             else:
120                 result[value] = no_prefix[value]
121         return result
122
123     def setup_environ_for_server(self, server_name=None):
124         _log.debug("setup_environ_for_server")
125         env = super(IOSSimulatorPort, self).setup_environ_for_server(server_name)
126         if server_name == self.driver_name():
127             if self.get_option('leaks'):
128                 env['MallocStackLogging'] = '1'
129                 env['__XPC_MallocStackLogging'] = '1'
130                 env['MallocScribble'] = '1'
131                 env['__XPC_MallocScribble'] = '1'
132             if self.get_option('guard_malloc'):
133                 self._append_value_colon_separated(env, 'DYLD_INSERT_LIBRARIES', '/usr/lib/libgmalloc.dylib')
134                 self._append_value_colon_separated(env, '__XPC_DYLD_INSERT_LIBRARIES', '/usr/lib/libgmalloc.dylib')
135         env['XML_CATALOG_FILES'] = ''  # work around missing /etc/catalog <rdar://problem/4292995>
136         return env
137
138     def operating_system(self):
139         return 'ios-simulator'
140
141     def check_sys_deps(self):
142         target_device_type = DeviceType(software_variant='iOS', software_version=self.ios_version())
143         for device in SimulatedDeviceManager.available_devices(self.host):
144             if device.platform_device.device_type in target_device_type:
145                 return super(IOSSimulatorPort, self).check_sys_deps()
146         _log.error('No Simulated device matching "{}" defined in Xcode iOS SDK'.format(str(target_device_type)))
147         return False
148
149     def reset_preferences(self):
150         _log.debug("reset_preferences")
151         SimulatedDeviceManager.tear_down(self.host)
152
153     def nm_command(self):
154         return self.xcrun_find('nm')
155
156     @property
157     @memoized
158     def developer_dir(self):
159         return self._executive.run_command(['xcode-select', '--print-path']).rstrip()
160
161     def logging_patterns_to_strip(self):
162         return []
163
164     def stderr_patterns_to_strip(self):
165         return []