6dd74168ef631388dbfeed4f226f1e607cc35e16
[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.ios import IOSPort
28 from webkitpy.xcode.device_type import DeviceType
29 from webkitpy.xcode.simulated_device import DeviceRequest, SimulatedDeviceManager
30
31
32 _log = logging.getLogger(__name__)
33
34
35 class IOSSimulatorPort(IOSPort):
36     port_name = "ios-simulator"
37
38     FUTURE_VERSION = 'future'
39     ARCHITECTURES = ['x86_64', 'x86']
40     DEFAULT_ARCHITECTURE = 'x86_64'
41
42     DEFAULT_DEVICE_CLASS = 'iPhone 5s'
43     CUSTOM_DEVICE_CLASSES = ['iPad', 'iPhone 7']
44     SDK = 'iphonesimulator'
45
46     def __init__(self, host, port_name, **kwargs):
47         super(IOSSimulatorPort, self).__init__(host, port_name, **kwargs)
48
49         optional_device_class = self.get_option('device_class')
50         self._device_class = optional_device_class if optional_device_class else self.DEFAULT_DEVICE_CLASS
51         _log.debug('IOSSimulatorPort _device_class is %s', self._device_class)
52
53     def _device_for_worker_number_map(self):
54         return SimulatedDeviceManager.INITIALIZED_DEVICES
55
56     @staticmethod
57     def _version_from_name(name):
58         if len(name.split('-')) > 2 and name.split('-')[2].isdigit():
59             return Version.from_string(name.split('-')[2])
60         return None
61
62     @memoized
63     def ios_version(self):
64         if self.get_option('version'):
65             return Version.from_string(self.get_option('version'))
66         return IOSSimulatorPort._version_from_name(self._name) if IOSSimulatorPort._version_from_name(self._name) else self.host.platform.xcode_sdk_version('iphonesimulator')
67
68     @memoized
69     def default_child_processes(self):
70         def booted_ios_devices_filter(device):
71             if not device.platform_device.is_booted_or_booting():
72                 return False
73             return device.platform_device.device_type in DeviceType(software_variant='iOS',
74                                                                     software_version=self.ios_version())
75
76         if not self.get_option('dedicated_simulators', False):
77             num_booted_sims = len(SimulatedDeviceManager.device_by_filter(booted_ios_devices_filter, host=self.host))
78             if num_booted_sims:
79                 return num_booted_sims
80         return SimulatedDeviceManager.max_supported_simulators(self.host)
81
82     def _build_driver_flags(self):
83         archs = ['ARCHS=i386'] if self.architecture() == 'x86' else []
84         sdk = ['--sdk', 'iphonesimulator']
85         return archs + sdk
86
87     def _set_device_class(self, device_class):
88         self._device_class = device_class if device_class else self.DEFAULT_DEVICE_CLASS
89
90     def _create_devices(self, device_class):
91         self._set_device_class(device_class)
92         device_type = DeviceType.from_string(self._device_class, self.ios_version())
93
94         _log.debug('')
95         _log.debug('creating devices for {}'.format(device_type))
96
97         request = DeviceRequest(
98             device_type,
99             use_booted_simulator=not self.get_option('dedicated_simulators', False),
100             use_existing_simulator=False,
101             allow_incomplete_match=True,
102         )
103         SimulatedDeviceManager.initialize_devices([request] * self.child_processes(), self.host)
104
105     def clean_up_test_run(self):
106         super(IOSSimulatorPort, self).clean_up_test_run()
107         _log.debug("clean_up_test_run")
108
109         SimulatedDeviceManager.tear_down(self.host)
110
111     def environment_for_api_tests(self):
112         no_prefix = super(IOSSimulatorPort, self).environment_for_api_tests()
113         result = {}
114         SIMCTL_ENV_PREFIX = 'SIMCTL_CHILD_'
115         for value in no_prefix:
116             if not value.startswith(SIMCTL_ENV_PREFIX):
117                 result[SIMCTL_ENV_PREFIX + value] = no_prefix[value]
118             else:
119                 result[value] = no_prefix[value]
120         return result
121
122     def setup_environ_for_server(self, server_name=None):
123         _log.debug("setup_environ_for_server")
124         env = super(IOSSimulatorPort, self).setup_environ_for_server(server_name)
125         if server_name == self.driver_name():
126             if self.get_option('leaks'):
127                 env['MallocStackLogging'] = '1'
128                 env['__XPC_MallocStackLogging'] = '1'
129                 env['MallocScribble'] = '1'
130                 env['__XPC_MallocScribble'] = '1'
131             if self.get_option('guard_malloc'):
132                 self._append_value_colon_separated(env, 'DYLD_INSERT_LIBRARIES', '/usr/lib/libgmalloc.dylib')
133                 self._append_value_colon_separated(env, '__XPC_DYLD_INSERT_LIBRARIES', '/usr/lib/libgmalloc.dylib')
134         env['XML_CATALOG_FILES'] = ''  # work around missing /etc/catalog <rdar://problem/4292995>
135         return env
136
137     def operating_system(self):
138         return 'ios-simulator'
139
140     def check_sys_deps(self):
141         target_device_type = DeviceType(software_variant='iOS', software_version=self.ios_version())
142         for device in SimulatedDeviceManager.available_devices(self.host):
143             if device.platform_device.device_type in target_device_type:
144                 return super(IOSSimulatorPort, self).check_sys_deps()
145         _log.error('No Simulated device matching "{}" defined in Xcode iOS SDK'.format(str(target_device_type)))
146         return False
147
148     def reset_preferences(self):
149         _log.debug("reset_preferences")
150         SimulatedDeviceManager.tear_down(self.host)
151
152     def nm_command(self):
153         return self.xcrun_find('nm')
154
155     @property
156     @memoized
157     def developer_dir(self):
158         return self._executive.run_command(['xcode-select', '--print-path']).rstrip()
159
160     def logging_patterns_to_strip(self):
161         return []
162
163     def stderr_patterns_to_strip(self):
164         return []