webkitpy: Refactor simulator code (Part 2)
[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.new_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         if self.get_option('child_processes', self.default_child_processes()) > SimulatedDeviceManager.max_supported_simulators(self.host):
54             _log.warn('The specified number of Simulated devices to be used is greater than the number supported by this machine.')
55
56     def _device_for_worker_number_map(self):
57         return SimulatedDeviceManager.INITIALIZED_DEVICES
58
59     @staticmethod
60     def _version_from_name(name):
61         if len(name.split('-')) > 2 and name.split('-')[2].isdigit():
62             return Version.from_string(name.split('-')[2])
63         return None
64
65     @memoized
66     def ios_version(self):
67         if self.get_option('version'):
68             return Version.from_string(self.get_option('version'))
69         return IOSSimulatorPort._version_from_name(self._name) if IOSSimulatorPort._version_from_name(self._name) else self.host.platform.xcode_sdk_version('iphonesimulator')
70
71     @memoized
72     def default_child_processes(self):
73         def booted_ios_devices_filter(device):
74             if not device.platform_device.is_booted_or_booting():
75                 return False
76             return device.platform_device.device_type in DeviceType(software_variant='iOS',
77                                                                     software_version=self.ios_version())
78
79         if self.get_option('dedicated_simulators', False):
80             num_booted_sims = len(SimulatedDeviceManager.device_by_filter(booted_ios_devices_filter, host=self.host))
81             if num_booted_sims:
82                 return num_booted_sims
83         return SimulatedDeviceManager.max_supported_simulators(self.host)
84
85     def _build_driver_flags(self):
86         archs = ['ARCHS=i386'] if self.architecture() == 'x86' else []
87         sdk = ['--sdk', 'iphonesimulator']
88         return archs + sdk
89
90     def _set_device_class(self, device_class):
91         self._device_class = device_class if device_class else self.DEFAULT_DEVICE_CLASS
92
93     def _create_devices(self, device_class):
94         self._set_device_class(device_class)
95         device_type = DeviceType.from_string(self._device_class, self.ios_version())
96
97         _log.debug('')
98         _log.debug('creating devices for {}'.format(device_type))
99
100         request = DeviceRequest(
101             device_type,
102             use_booted_simulator=not self.get_option('dedicated_simulators', False),
103             use_existing_simulator=False,
104             allow_incomplete_match=True,
105         )
106         SimulatedDeviceManager.initialize_devices([request] * self.child_processes(), self.host)
107
108     def clean_up_test_run(self):
109         super(IOSSimulatorPort, self).clean_up_test_run()
110         _log.debug("clean_up_test_run")
111
112         SimulatedDeviceManager.tear_down(self.host)
113
114     def setup_environ_for_server(self, server_name=None):
115         _log.debug("setup_environ_for_server")
116         env = super(IOSSimulatorPort, self).setup_environ_for_server(server_name)
117         if server_name == self.driver_name():
118             if self.get_option('leaks'):
119                 env['MallocStackLogging'] = '1'
120                 env['__XPC_MallocStackLogging'] = '1'
121                 env['MallocScribble'] = '1'
122                 env['__XPC_MallocScribble'] = '1'
123             if self.get_option('guard_malloc'):
124                 self._append_value_colon_separated(env, 'DYLD_INSERT_LIBRARIES', '/usr/lib/libgmalloc.dylib')
125                 self._append_value_colon_separated(env, '__XPC_DYLD_INSERT_LIBRARIES', '/usr/lib/libgmalloc.dylib')
126         env['XML_CATALOG_FILES'] = ''  # work around missing /etc/catalog <rdar://problem/4292995>
127         return env
128
129     def operating_system(self):
130         return 'ios-simulator'
131
132     def check_sys_deps(self, needs_http):
133         target_device_type = DeviceType(software_variant='iOS', software_version=self.ios_version())
134         for device in SimulatedDeviceManager.available_devices(self.host):
135             if device.platform_device.device_type in target_device_type:
136                 return super(IOSSimulatorPort, self).check_sys_deps(needs_http)
137         _log.error('No Simulated device matching "{}" defined in Xcode iOS SDK'.format(str(target_device_type)))
138         return False
139
140     def reset_preferences(self):
141         _log.debug("reset_preferences")
142         SimulatedDeviceManager.tear_down(self.host)
143
144     def nm_command(self):
145         return self.xcrun_find('nm')
146
147     @property
148     @memoized
149     def developer_dir(self):
150         return self._executive.run_command(['xcode-select', '--print-path']).rstrip()
151
152     def logging_patterns_to_strip(self):
153         return []
154
155     def stderr_patterns_to_strip(self):
156         return []