run_loop 1.4.1 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,6 +5,24 @@ module RunLoop
5
5
  # @note All instruments commands are run in the context of `xcrun`.
6
6
  class Instruments
7
7
 
8
+ include RunLoop::Regex
9
+
10
+ attr_reader :xcode
11
+
12
+ def xcode
13
+ @xcode ||= RunLoop::Xcode.new
14
+ end
15
+
16
+ # @!visibility private
17
+ def to_s
18
+ "#<Instruments #{version.to_s}>"
19
+ end
20
+
21
+ # @!visibility private
22
+ def inspect
23
+ to_s
24
+ end
25
+
8
26
  # Returns an Array of instruments process ids.
9
27
  #
10
28
  # @note The `block` parameter is included for legacy API and will be
@@ -32,10 +50,17 @@ module RunLoop
32
50
  #
33
51
  # Only one instruments process can be running at any one time.
34
52
  #
35
- # @param [RunLoop::XCTools] xcode_tools The Xcode tools to use to determine
36
- # what version of Xcode is active.
37
- def kill_instruments(xcode_tools = RunLoop::XCTools.new)
38
- kill_signal = kill_signal xcode_tools
53
+ # @param [RunLoop::Xcode, RunLoop::XCTools] xcode Used to make check the
54
+ # active Xcode version.
55
+ def kill_instruments(xcode = RunLoop::Xcode.new)
56
+ if xcode.is_a?(RunLoop::XCTools)
57
+ RunLoop.deprecated('1.5.0',
58
+ %q(
59
+ RunLoop::XCTools has been replaced with RunLoop::Xcode.
60
+ Please update your sources to pass an instance of RunLoop::Xcode))
61
+ end
62
+
63
+ kill_signal = kill_signal(xcode)
39
64
  instruments_pids.each do |pid|
40
65
  terminator = RunLoop::ProcessTerminator.new(pid, kill_signal, 'instruments')
41
66
  unless terminator.kill_process
@@ -77,8 +102,144 @@ module RunLoop
77
102
  pid.to_i
78
103
  end
79
104
 
105
+ # Returns the instruments version.
106
+ # @return [RunLoop::Version] A version object.
107
+ def version
108
+ @instruments_version ||= lambda do
109
+ execute_command([]) do |_, stderr, _|
110
+ version_str = stderr.read[VERSION_REGEX, 0]
111
+ RunLoop::Version.new(version_str)
112
+ end
113
+ end.call
114
+ end
115
+
116
+ # Returns an array of Instruments.app templates.
117
+ #
118
+ # Depending on the Xcode version Instruments.app templates will either be:
119
+ #
120
+ # * A full path to the template. # Xcode 5 and Xcode > 5 betas
121
+ # * The name of a template. # Xcode >= 6 (non beta)
122
+ #
123
+ # **Maintainers!** The rules above are important and explain why we can't
124
+ # simply filter by `~= /tracetemplate/`.
125
+ #
126
+ # Templates that users have saved will always be full paths - regardless
127
+ # of the Xcode version.
128
+ #
129
+ # @return [Array<String>] Instruments.app templates.
130
+ def templates
131
+ @instruments_templates ||= lambda do
132
+ if xcode.version_gte_6?
133
+ execute_command(['-s', 'templates']) do |stdout, stderr, _|
134
+ filter_stderr_spam(stderr)
135
+ stdout.read.chomp.split("\n").map do |elm|
136
+ stripped = elm.strip.tr('"', '')
137
+ if stripped == '' || stripped == 'Known Templates:'
138
+ nil
139
+ else
140
+ stripped
141
+ end
142
+ end.compact
143
+ end
144
+ elsif xcode.version_gte_51?
145
+ execute_command(['-s', 'templates']) do |stdout, stderr, _|
146
+ err = stderr.read
147
+ if !err.nil? || err != ''
148
+ $stderr.puts stderr.read
149
+ end
150
+
151
+ stdout.read.strip.split("\n").delete_if do |path|
152
+ not path =~ /tracetemplate/
153
+ end.map { |elm| elm.strip }
154
+ end
155
+ else
156
+ raise "Xcode version '#{xcode.version}' is not supported."
157
+ end
158
+ end.call
159
+ end
160
+
161
+ # Returns an array the available physical devices.
162
+ #
163
+ # @return [Array<RunLoop::Device>] All the devices will be physical
164
+ # devices.
165
+ def physical_devices
166
+ @instruments_physical_devices ||= lambda do
167
+ execute_command(['-s', 'devices']) do |stdout, stderr, _|
168
+ filter_stderr_spam(stderr)
169
+ all = stdout.read.chomp.split("\n")
170
+ valid = all.select do |device|
171
+ device =~ DEVICE_UDID_REGEX
172
+ end
173
+ valid.map do |device|
174
+ udid = device[DEVICE_UDID_REGEX, 0]
175
+ version = device[VERSION_REGEX, 0]
176
+ name = device.split('(').first.strip
177
+ RunLoop::Device.new(name, version, udid)
178
+ end
179
+ end
180
+ end.call
181
+ end
182
+
183
+ # Returns an array of the available simulators.
184
+ #
185
+ # **Xcode 5.1**
186
+ # * iPad Retina - Simulator - iOS 7.1
187
+ #
188
+ # **Xcode 6**
189
+ # * iPad Retina (8.3 Simulator) [EA79555F-ADB4-4D75-930C-A745EAC8FA8B]
190
+ #
191
+ # **Xcode 7**
192
+ # * iPhone 6 (9.0) [3EDC9C6E-3096-48BF-BCEC-7A5CAF8AA706]
193
+ # * iPhone 6 (9.0) + Apple Watch - 38mm (2.0) [EE3C200C-69BA-4816-A087-0457C5FCEDA0]
194
+ #
195
+ # @return [Array<RunLoop::Device>] All the devices will be simulators.
196
+ def simulators
197
+ @instruments_simulators ||= lambda do
198
+ execute_command(['-s', 'devices']) do |stdout, stderr, _|
199
+ filter_stderr_spam(stderr)
200
+ lines = stdout.read.chomp.split("\n")
201
+ lines.map do |line|
202
+ stripped = line.strip
203
+ if line_is_simulator?(stripped) &&
204
+ !line_is_simulator_paired_with_watch?(stripped)
205
+
206
+ version = stripped[VERSION_REGEX, 0]
207
+
208
+ if line_is_xcode5_simulator?(stripped)
209
+ name = line
210
+ udid = line
211
+ else
212
+ name = stripped.split('(').first.strip
213
+ udid = line[CORE_SIMULATOR_UDID_REGEX, 0]
214
+ end
215
+
216
+ RunLoop::Device.new(name, version, udid)
217
+ else
218
+ nil
219
+ end
220
+ end.compact
221
+ end
222
+ end.call
223
+ end
224
+
80
225
  private
81
226
 
227
+ # @!visibility private
228
+ #
229
+ # ```
230
+ # $ ps x -o pid,command | grep -v grep | grep instruments
231
+ # 98081 sh -c xcrun instruments -w "43be3f89d9587e9468c24672777ff6241bd91124" < args >
232
+ # 98082 /Xcode/6.0.1/Xcode.app/Contents/Developer/usr/bin/instruments -w < args >
233
+ # ```
234
+ #
235
+ # When run from run-loop (via rspec), expect this:
236
+ #
237
+ # ```
238
+ # $ ps x -o pid,command | grep -v grep | grep instruments
239
+ # 98082 /Xcode/6.0.1/Xcode.app/Contents/Developer/usr/bin/instruments -w < args >
240
+ # ```
241
+ INSTRUMENTS_FIND_PIDS_CMD = 'ps x -o pid,command | grep -v grep | grep instruments'
242
+
82
243
  # @!visibility private
83
244
  # Parses the run-loop options hash into an array of arguments that can be
84
245
  # passed to `Process.spawn` to launch instruments.
@@ -109,22 +270,6 @@ module RunLoop
109
270
  array + options.fetch(:args, [])
110
271
  end
111
272
 
112
- # @!visibility private
113
- #
114
- # ```
115
- # $ ps x -o pid,command | grep -v grep | grep instruments
116
- # 98081 sh -c xcrun instruments -w "43be3f89d9587e9468c24672777ff6241bd91124" < args >
117
- # 98082 /Xcode/6.0.1/Xcode.app/Contents/Developer/usr/bin/instruments -w < args >
118
- # ```
119
- #
120
- # When run from run-loop (via rspec), expect this:
121
- #
122
- # ```
123
- # $ ps x -o pid,command | grep -v grep | grep instruments
124
- # 98082 /Xcode/6.0.1/Xcode.app/Contents/Developer/usr/bin/instruments -w < args >
125
- # ```
126
- INSTRUMENTS_FIND_PIDS_CMD = 'ps x -o pid,command | grep -v grep | grep instruments'
127
-
128
273
  # @!visibility private
129
274
  #
130
275
  # Executes `ps_cmd` to find instruments processes and returns the result.
@@ -185,12 +330,67 @@ module RunLoop
185
330
  #
186
331
  # @see https://github.com/calabash/run_loop/issues/34
187
332
  #
188
- # @param [RunLoop::XCTools] xcode_tools The Xcode tools to use to determine
333
+ # @param [RunLoop::Xcode, RunLoop::XCTools] xcode The Xcode tools to use to determine
189
334
  # what version of Xcode is active.
190
335
  # @return [String] Either 'QUIT' or 'TERM', depending on the Xcode
191
336
  # version.
192
- def kill_signal(xcode_tools = RunLoop::XCTools.new)
193
- xcode_tools.xcode_version_gte_6? ? 'QUIT' : 'TERM'
337
+ def kill_signal(xcode = RunLoop::Xcode.new)
338
+ if xcode.is_a?(RunLoop::XCTools)
339
+ RunLoop.deprecated('1.5.0',
340
+ %q(
341
+ RunLoop::XCTools has been replaced with RunLoop::Xcode.
342
+ Please update your sources to pass an instance of RunLoop::Xcode))
343
+ end
344
+ xcode.version_gte_6? ? 'QUIT' : 'TERM'
345
+ end
346
+
347
+ # @!visibility private
348
+ #
349
+ # Execute an instruments command.
350
+ # @param [Array] args An array of arguments
351
+ def execute_command(args)
352
+ Open3.popen3('xcrun', 'instruments', *args) do |_, stdout, stderr, process_status|
353
+ yield stdout, stderr, process_status
354
+ end
355
+ end
356
+
357
+ # @!visibility private
358
+ #
359
+ # Filters `instruments` spam.
360
+ def filter_stderr_spam(stderr)
361
+ # Xcode 6 GM is spamming "WebKit Threading Violations"
362
+ stderr.read.strip.split("\n").each do |line|
363
+ unless line[/WebKit Threading Violation/, 0]
364
+ $stderr.puts line
365
+ end
366
+ end
367
+ end
368
+
369
+ # @!visibility private
370
+ def line_is_simulator?(line)
371
+ line_is_core_simulator?(line) || line_is_xcode5_simulator?(line)
372
+ end
373
+
374
+ # @!visibility private
375
+ def line_is_xcode5_simulator?(line)
376
+ !line[CORE_SIMULATOR_UDID_REGEX, 0] && line[/Simulator/, 0]
377
+ end
378
+
379
+ # @!visibility private
380
+ def line_is_core_simulator?(line)
381
+ return nil if !line_has_a_version?(line)
382
+
383
+ line[CORE_SIMULATOR_UDID_REGEX, 0]
384
+ end
385
+
386
+ # @!visibility private
387
+ def line_has_a_version?(line)
388
+ line[VERSION_REGEX, 0]
389
+ end
390
+
391
+ # @!visibility private
392
+ def line_is_simulator_paired_with_watch?(line)
393
+ line[CORE_SIMULATOR_UDID_REGEX, 0] && line[/Apple Watch/, 0]
194
394
  end
195
395
  end
196
396
  end
data/lib/run_loop/ipa.rb CHANGED
@@ -35,6 +35,11 @@ module RunLoop
35
35
  "#<IPA: #{bundle_identifier}: '#{path}'>"
36
36
  end
37
37
 
38
+ # @!visibility private
39
+ def inspect
40
+ to_s
41
+ end
42
+
38
43
  # The bundle identifier of this ipa.
39
44
  # @return [String] A string representation of this ipa's CFBundleIdentifier
40
45
  # @raise [RuntimeError] If ipa does not expand into a Payload/<app name>.app
@@ -0,0 +1,117 @@
1
+ module RunLoop
2
+ class L10N
3
+
4
+ # Find the localized name for a given key_code
5
+ #
6
+ # @example
7
+ # lookup_localization_name('delete.key', 'da') => 'Slet'
8
+ #
9
+ # @param [String] key_code the localization signifier, e.g. 'delete.key'
10
+ # @param [String] localized_lang an iso language code returned by calabash ios server
11
+ #
12
+ # @return [String] the localized name
13
+ def lookup_localization_name(key_code, localized_lang)
14
+ lookup_table_dir = lang_dir(localized_lang)
15
+ return nil unless lookup_table_dir
16
+
17
+ key_name_lookup_table(lookup_table_dir)[key_code]
18
+ end
19
+
20
+ UIKIT_AXBUNDLE_PATH_CORE_SIM = 'Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/AccessibilityBundles/UIKit.axbundle/'
21
+
22
+ LANG_CODE_TO_LANG_NAME_MAP = {
23
+ 'en' => 'English',
24
+ 'nl' => 'Dutch',
25
+ 'fr' => 'French',
26
+ 'de' => 'German',
27
+ 'es' => 'Spanish',
28
+ 'it' => 'Italian',
29
+ 'jp' => 'Japanese'
30
+ }
31
+
32
+ # @!visibility private
33
+ def to_s
34
+ "#<L10N #{uikit_bundle_l10n_path}>"
35
+ end
36
+
37
+ # @!visibility private
38
+ def inspect
39
+ to_s
40
+ end
41
+
42
+ # maps the ios keyboard localization to a language directory where we can
43
+ # find a key-code -> localized-label mapping
44
+ def lang_dir(localized_lang)
45
+ l10n_path = uikit_bundle_l10n_path
46
+
47
+ ## 2 char + _ + sub localization
48
+ # en_GB.lproj
49
+ lang_dir_name = "#{localized_lang}.lproj".sub('-','_')
50
+ if File.exists?(File.join(l10n_path, lang_dir_name))
51
+ return lang_dir_name
52
+ end
53
+
54
+ # 2 char iso language code
55
+ # vi.lproj
56
+ two_char_country_code = localized_lang.split('-')[0]
57
+ lang_dir_name = "#{two_char_country_code}.lproj"
58
+ if File.exists?(File.join(l10n_path, lang_dir_name))
59
+ return lang_dir_name
60
+ end
61
+
62
+ # Full name
63
+ # e.g. Dutch.lproj
64
+ lang_dir_name = "#{LANG_CODE_TO_LANG_NAME_MAP[two_char_country_code]}.lproj"
65
+ if is_full_name?(two_char_country_code) &&
66
+ File.exists?(File.join(l10n_path, lang_dir_name))
67
+ return lang_dir_name
68
+ end
69
+ nil
70
+ end
71
+
72
+ def uikit_bundle_l10n_path
73
+ developer_dir = xcode.developer_dir
74
+ if !developer_dir
75
+ nil
76
+ else
77
+ if xcode.version_gte_6?
78
+ File.join(developer_dir, UIKIT_AXBUNDLE_PATH_CORE_SIM)
79
+ else
80
+ ['7.1', '7.0', '6.1'].map do |sdk|
81
+ path = axbundle_path_for_sdk(developer_dir, sdk)
82
+ if File.exist?(path)
83
+ path
84
+ else
85
+ nil
86
+ end
87
+ end.compact.first
88
+ end
89
+ end
90
+ end
91
+
92
+ # Xcode 5.1.1 path.
93
+ def axbundle_path_for_sdk(developer_dir, sdk)
94
+ File.join(developer_dir,
95
+ 'Platforms/iPhoneSimulator.platform/Developer/SDKs',
96
+ "iPhoneSimulator#{sdk}.sdk",
97
+ 'System/Library/AccessibilityBundles/UIKit.axbundle')
98
+ end
99
+
100
+ def is_full_name?(two_letter_country_code)
101
+ LANG_CODE_TO_LANG_NAME_MAP.has_key?(two_letter_country_code)
102
+ end
103
+
104
+ def key_name_lookup_table(lang_dir_name)
105
+ path = File.join(uikit_bundle_l10n_path, lang_dir_name, 'Accessibility.strings')
106
+ JSON.parse(`plutil -convert json #{path} -o -`)
107
+ end
108
+
109
+ # @!visibility private
110
+ attr_reader :xcode
111
+
112
+ # @!visibility private
113
+ def xcode
114
+ @xcode ||= RunLoop::Xcode.new
115
+ end
116
+ end
117
+ end
data/lib/run_loop/lipo.rb CHANGED
@@ -22,6 +22,16 @@ module RunLoop
22
22
  @plist_buddy = RunLoop::PlistBuddy.new
23
23
  end
24
24
 
25
+ # @!visibility private
26
+ def to_s
27
+ "#<Lipo #{bundle_path}>"
28
+ end
29
+
30
+ # @!visibility private
31
+ def inspect
32
+ to_s
33
+ end
34
+
25
35
  # Inspect the `CFBundleExecutable` in the app bundle path with `lipo` and
26
36
  # compare the result with the target device's instruction set.
27
37
  #
@@ -0,0 +1,19 @@
1
+ module RunLoop
2
+
3
+ # @!visibility private
4
+ module Regex
5
+
6
+ # @!visibility private
7
+ CORE_SIMULATOR_UDID_REGEX = /[A-F0-9]{8}-([A-F0-9]{4}-){3}[A-F0-9]{12}/.freeze
8
+
9
+ # @!visibility private
10
+ XCODE_511_SIMULATOR_REGEX = /(\d)\.(\d)\.?(\d)?(-64)?/.freeze
11
+
12
+ # @!visibility private
13
+ DEVICE_UDID_REGEX = /[a-f0-9]{40}/.freeze
14
+
15
+ # @!visibility private
16
+ VERSION_REGEX = /(\d\.\d(\.\d)?)/.freeze
17
+
18
+ end
19
+ end
@@ -14,40 +14,42 @@ module RunLoop
14
14
  # @todo `puts` calls need to be replaced with proper logging
15
15
  class SimControl
16
16
 
17
- # Returns an instance of XCTools.
18
- # @return [RunLoop::XCTools] The xcode tools instance that is used internally.
17
+ include RunLoop::Regex
18
+
19
+ # @deprecated 1.5.0 - replaced by #xcode
19
20
  def xctools
21
+ RunLoop.deprecated('1.5.0', 'Replaced by RunLoop::Xcode')
20
22
  @xctools ||= RunLoop::XCTools.new
21
23
  end
22
24
 
23
25
  # @!visibility private
24
- # Are we running Xcode 7 or above?
25
- #
26
- # This is a convenience method.
27
- #
28
- # @return [Boolean] `true` if the current Xcode version is >= 7.0
26
+ def xcode
27
+ @xcode ||= RunLoop::Xcode.new
28
+ end
29
+
30
+ # @!visibility private
31
+ def xcode_version
32
+ xcode.version
33
+ end
34
+
35
+ # @!visibility private
29
36
  def xcode_version_gte_7?
30
- xctools.xcode_version_gte_7?
37
+ xcode.version_gte_7?
31
38
  end
32
39
 
33
40
  # @!visibility private
34
- # Are we running Xcode 6 or above?
35
- #
36
- # This is a convenience method.
37
- #
38
- # @return [Boolean] `true` if the current Xcode version is >= 6.0
39
41
  def xcode_version_gte_6?
40
- xctools.xcode_version_gte_6?
42
+ xcode.version_gte_6?
41
43
  end
42
44
 
43
45
  # @!visibility private
44
- # Are we running Xcode 5.1 or above?
45
- #
46
- # This is a convenience method.
47
- #
48
- # @return [Boolean] `true` if the current Xcode version is >= 5.1
49
46
  def xcode_version_gte_51?
50
- xctools.xcode_version_gte_51?
47
+ xcode.version_gte_51?
48
+ end
49
+
50
+ # @!visibility private
51
+ def xcode_developer_dir
52
+ xcode.developer_dir
51
53
  end
52
54
 
53
55
  # Return an instance of PlistBuddy.
@@ -309,26 +311,22 @@ module RunLoop
309
311
  # @param [String] udid the String to check
310
312
  # @return [Boolean] Returns true iff the `udid` matches /[A-F0-9]{8}-([A-F0-9]{4}-){3}[A-F0-9]{12}/
311
313
  def sim_udid?(udid)
312
- udid.length == 36 and udid[XCODE_6_SIM_UDID_REGEX,0] != nil
314
+ udid.length == 36 and udid[CORE_SIMULATOR_UDID_REGEX,0] != nil
313
315
  end
314
316
 
315
317
  def simulators
316
- unless xcode_version_gte_51?
318
+ unless xcode_version_gte_6?
317
319
  raise RuntimeError, 'simctl is only available on Xcode >= 6'
318
320
  end
319
321
 
320
- if xcode_version_gte_6?
321
- hash = simctl_list :devices
322
- sims = []
323
- hash.each_pair do |sdk, list|
324
- list.each do |details|
325
- sims << RunLoop::Device.new(details[:name], sdk, details[:udid], details[:state])
326
- end
322
+ hash = simctl_list :devices
323
+ sims = []
324
+ hash.each_pair do |sdk, list|
325
+ list.each do |details|
326
+ sims << RunLoop::Device.new(details[:name], sdk, details[:udid], details[:state])
327
327
  end
328
- sims
329
- else
330
- raise NotImplementedError, 'the simulators method is not available yet for Xcode 5.1.1'
331
328
  end
329
+ sims
332
330
  end
333
331
 
334
332
  def accessibility_enabled?(device)
@@ -586,7 +584,7 @@ module RunLoop
586
584
  # @!visibility private
587
585
  # A regex for finding directories under ~/Library/Developer/CoreSimulator/Devices
588
586
  # and parsing the output of `simctl list sessions`.
589
- XCODE_6_SIM_UDID_REGEX = /[A-F0-9]{8}-([A-F0-9]{4}-){3}[A-F0-9]{12}/.freeze
587
+ CORE_SIMULATOR_UDID_REGEX = /[A-F0-9]{8}-([A-F0-9]{4}-){3}[A-F0-9]{12}/.freeze
590
588
 
591
589
  CORE_SIMULATOR_KEYBOARD_PROPERTIES_HASH =
592
590
  {
@@ -639,7 +637,7 @@ module RunLoop
639
637
  # Xcode.
640
638
  def sim_app_path
641
639
  @sim_app_path ||= lambda {
642
- dev_dir = xctools.xcode_developer_dir
640
+ dev_dir = xcode_developer_dir
643
641
  if xcode_version_gte_7?
644
642
  "#{dev_dir}/Applications/Simulator.app"
645
643
  elsif xcode_version_gte_6?
@@ -704,9 +702,9 @@ module RunLoop
704
702
  def existing_sim_sdk_or_device_data_dirs
705
703
  base_dir = sim_app_support_dir
706
704
  if xcode_version_gte_6?
707
- regex = XCODE_6_SIM_UDID_REGEX
705
+ regex = CORE_SIMULATOR_UDID_REGEX
708
706
  else
709
- regex = /(\d)\.(\d)\.?(\d)?(-64)?/
707
+ regex = XCODE_511_SIMULATOR_REGEX
710
708
  end
711
709
  dirs = Dir.glob("#{base_dir}/*").select { |path|
712
710
  path =~ regex
@@ -840,13 +838,12 @@ module RunLoop
840
838
  quit_sim
841
839
 
842
840
  verbose = merged_opts[:verbose]
843
- target_udid = sim_data_dir[XCODE_6_SIM_UDID_REGEX, 0]
841
+ target_udid = sim_data_dir[CORE_SIMULATOR_UDID_REGEX, 0]
844
842
 
845
843
  # Directory contains simulators not reported by instruments -s devices
846
844
  simulator_details = sim_details_keyed_with_udid[target_udid]
847
845
  if simulator_details.nil?
848
846
  if verbose
849
- xcode_version = xctools.xcode_version
850
847
  puts ["INFO: Skipping '#{target_udid}' directory because",
851
848
  "there is no corresponding simulator for active Xcode (version '#{xcode_version}')"].join("\n")
852
849
  end
@@ -930,13 +927,12 @@ module RunLoop
930
927
  quit_sim
931
928
 
932
929
  verbose = merged_opts[:verbose]
933
- target_udid = sim_data_dir[XCODE_6_SIM_UDID_REGEX, 0]
930
+ target_udid = sim_data_dir[CORE_SIMULATOR_UDID_REGEX, 0]
934
931
 
935
932
  # Directory contains simulators not reported by instruments -s devices
936
933
  simulator_details = sim_details_keyed_with_udid[target_udid]
937
934
  if simulator_details.nil?
938
935
  if verbose
939
- xcode_version = xctools.xcode_version
940
936
  puts ["INFO: Skipping '#{target_udid}' directory because",
941
937
  "there is no corresponding simulator for active Xcode (version '#{xcode_version}')"].join("\n")
942
938
  end
@@ -1014,16 +1010,17 @@ module RunLoop
1014
1010
  end
1015
1011
 
1016
1012
  hash = {}
1017
- xctools.instruments(:sims).each do |elm|
1018
- launch_name = elm[/\A.+\((\d\.\d(\.\d)? Simulator\))/, 0]
1019
- udid = elm[XCODE_6_SIM_UDID_REGEX,0]
1020
- sdk_version = elm[/(\d\.\d(\.\d)? Simulator)/, 0].split(' ').first
1021
- value =
1022
- {
1023
- :launch_name => launch_name,
1024
- :udid => udid,
1025
- :sdk_version => RunLoop::Version.new(sdk_version)
1026
- }
1013
+
1014
+ simulators.each do |device|
1015
+ launch_name = device.instruments_identifier(xcode)
1016
+ udid = device.udid
1017
+ value = {
1018
+ :launch_name => device.instruments_identifier(xcode),
1019
+ :udid => device.udid,
1020
+ :sdk_version => device.version
1021
+
1022
+ }
1023
+
1027
1024
  if primary_key == :udid
1028
1025
  key = udid
1029
1026
  else
@@ -1153,15 +1150,27 @@ module RunLoop
1153
1150
  res = {}
1154
1151
  out.split("\n").each do |line|
1155
1152
 
1156
- possible_sdk = line[/(\d\.\d(\.\d)?)/,0]
1153
+ possible_sdk = line[VERSION_REGEX,0]
1157
1154
  if possible_sdk
1158
1155
  current_sdk = possible_sdk
1159
1156
  res[current_sdk] = []
1160
1157
  next
1161
1158
  end
1162
1159
 
1163
- unavailable_skd = line[/Unavailable/, 0]
1164
- if unavailable_skd
1160
+ unavailable_sdk = line[/Unavailable/, 0]
1161
+ if unavailable_sdk
1162
+ current_sdk = nil
1163
+ next
1164
+ end
1165
+
1166
+ watch_os = line[/watchOS/, 0]
1167
+ if watch_os
1168
+ current_sdk = nil
1169
+ next
1170
+ end
1171
+
1172
+ watch = line[/Apple Watch/, 0]
1173
+ if watch
1165
1174
  current_sdk = nil
1166
1175
  next
1167
1176
  end
@@ -1169,7 +1178,7 @@ module RunLoop
1169
1178
  if current_sdk
1170
1179
  unless line[/unavailable/,0]
1171
1180
  name = line.split('(').first.strip
1172
- udid = line[XCODE_6_SIM_UDID_REGEX,0]
1181
+ udid = line[CORE_SIMULATOR_UDID_REGEX,0]
1173
1182
  state = line[/(Booted|Shutdown)/,0]
1174
1183
  res[current_sdk] << {:name => name, :udid => udid, :state => state}
1175
1184
  end
@@ -194,7 +194,12 @@ module RunLoop::Simctl
194
194
  ['launchd_sim', true],
195
195
 
196
196
  # Yes, but does not always appear.
197
- ['CoreSimulatorBridge', true]
197
+ ['CoreSimulatorBridge', true],
198
+
199
+ # Xcode 7
200
+ ['ids_simd', true],
201
+ ['com.apple.CoreSimulator.CoreSimulatorService', true],
202
+ ['com.apple.CoreSimulator.SimVerificationService', true]
198
203
  ].each do |pair|
199
204
  name = pair[0]
200
205
  send_term = pair[1]