run_loop 2.0.10.pre1 → 2.1.0.pre1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/run_loop/core.rb +280 -355
- data/lib/run_loop/core_simulator.rb +3 -7
- data/lib/run_loop/detect_aut/detect.rb +72 -0
- data/lib/run_loop/device.rb +111 -5
- data/lib/run_loop/environment.rb +5 -0
- data/lib/run_loop/instruments.rb +10 -38
- data/lib/run_loop/l10n.rb +1 -25
- data/lib/run_loop/logging.rb +1 -1
- data/lib/run_loop/sim_control.rb +2 -4
- data/lib/run_loop/version.rb +1 -1
- data/lib/run_loop/xcode.rb +2 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7ea9c17ad6325b7381a689e16ea30c98b34e2765
|
4
|
+
data.tar.gz: a1f044d25c196213e310f2f70f096f35bb558c65
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 49f63b7057fb4448850252365b840843b05a4ac39f81db367dd32a52d0b23dc0cdcb67c8de22e4838f02bfb81ef7f2bf3c189da4d4953a008f1812b6bd108326
|
7
|
+
data.tar.gz: 30aed60ffb8069e15260ea81f02fa8a2261a59e473fcd4beaeacfcec940030671c6eb730423d088f73864cfc66daf18972df60a0cfc671013ed61e7f3b8f293f
|
data/lib/run_loop/core.rb
CHANGED
@@ -57,179 +57,24 @@ module RunLoop
|
|
57
57
|
SCRIPTS[key]
|
58
58
|
end
|
59
59
|
|
60
|
-
def self.detect_connected_device
|
61
|
-
begin
|
62
|
-
Timeout::timeout(1, RunLoop::TimeoutError) do
|
63
|
-
return `#{File.join(scripts_path, 'udidetect')}`.chomp
|
64
|
-
end
|
65
|
-
rescue RunLoop::TimeoutError => _
|
66
|
-
`killall udidetect &> /dev/null`
|
67
|
-
end
|
68
|
-
nil
|
69
|
-
end
|
70
|
-
|
71
|
-
# @deprecated 1.5.2 No public replacement.
|
72
|
-
#
|
73
|
-
# Raise an error if the application binary is not compatible with the
|
74
|
-
# target simulator.
|
75
|
-
#
|
76
|
-
# @note This method is implemented for CoreSimulator environments only;
|
77
|
-
# for Xcode < 6.0 this method does nothing.
|
78
|
-
#
|
79
|
-
# @param [Hash] launch_options These options need to contain the app bundle
|
80
|
-
# path and a udid that corresponds to a simulator name or simulator udid.
|
81
|
-
# In practical terms: call this after merging the original launch
|
82
|
-
# options with those options that are discovered.
|
83
|
-
#
|
84
|
-
# @param [RunLoop::SimControl] sim_control A simulator control object.
|
85
|
-
# @raise [RuntimeError] Raises an error if the `launch_options[:udid]`
|
86
|
-
# cannot be used to find a simulator.
|
87
|
-
# @raise [RunLoop::IncompatibleArchitecture] Raises an error if the
|
88
|
-
# application binary is not compatible with the target simulator.
|
89
|
-
def self.expect_compatible_simulator_architecture(launch_options, sim_control)
|
90
|
-
RunLoop.deprecated('1.5.2', 'No public replacement.')
|
91
|
-
logger = launch_options[:logger]
|
92
|
-
if sim_control.xcode_version_gte_6?
|
93
|
-
sim_identifier = launch_options[:udid]
|
94
|
-
simulator = sim_control.simulators.find do |simulator|
|
95
|
-
[simulator.instruments_identifier(sim_control.xcode),
|
96
|
-
simulator.udid].include?(sim_identifier)
|
97
|
-
end
|
98
|
-
|
99
|
-
if simulator.nil?
|
100
|
-
raise "Could not find simulator with identifier '#{sim_identifier}'"
|
101
|
-
end
|
102
|
-
|
103
|
-
lipo = RunLoop::Lipo.new(launch_options[:bundle_dir_or_bundle_id])
|
104
|
-
lipo.expect_compatible_arch(simulator)
|
105
|
-
RunLoop::Logging.log_debug(logger, "Simulator instruction set '#{simulator.instruction_set}' is compatible with #{lipo.info}")
|
106
|
-
true
|
107
|
-
else
|
108
|
-
RunLoop::Logging.log_debug(logger, "Xcode #{sim_control.xcode_version} detected; skipping simulator architecture check.")
|
109
|
-
false
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
# Raise an error if the application binary is not compatible with the
|
114
|
-
# target simulator.
|
115
|
-
#
|
116
|
-
# @note This method is implemented for CoreSimulator environments only;
|
117
|
-
# for Xcode < 6.0 this method does nothing.
|
118
|
-
#
|
119
|
-
# @param [RunLoop::Device] device The device to install on.
|
120
|
-
# @param [RunLoop::App] app The app to install.
|
121
|
-
# @param [RunLoop::Xcode] xcode The active Xcode.
|
122
|
-
#
|
123
|
-
# @raise [RunLoop::IncompatibleArchitecture] Raises an error if the
|
124
|
-
# application binary is not compatible with the target simulator.
|
125
|
-
def self.expect_simulator_compatible_arch(device, app, xcode)
|
126
|
-
if !xcode.version_gte_6?
|
127
|
-
RunLoop.log_warn("Checking for compatible arches is only available in CoreSimulator environments")
|
128
|
-
return
|
129
|
-
end
|
130
|
-
|
131
|
-
lipo = RunLoop::Lipo.new(app.path)
|
132
|
-
lipo.expect_compatible_arch(device)
|
133
|
-
|
134
|
-
RunLoop.log_debug("Simulator instruction set '#{device.instruction_set}' is compatible with '#{lipo.info}'")
|
135
|
-
end
|
136
|
-
|
137
|
-
# Prepares the simulator for running.
|
138
|
-
#
|
139
|
-
# 1. enabling accessibility and software keyboard
|
140
|
-
# 2. installing / uninstalling apps
|
141
|
-
def self.prepare_simulator(launch_options, sim_control)
|
142
|
-
|
143
|
-
xcode = sim_control.xcode
|
144
|
-
|
145
|
-
# Respect option passed from Calabash
|
146
|
-
if launch_options[:relaunch_simulator]
|
147
|
-
sim_control.quit_sim
|
148
|
-
end
|
149
|
-
|
150
|
-
if !xcode.version_gte_6?
|
151
|
-
# Xcode 5.1.1
|
152
|
-
|
153
|
-
# Will quit the simulator!
|
154
|
-
sim_control.enable_accessibility_on_sims({:verbose => false})
|
155
|
-
else
|
156
|
-
|
157
|
-
# CoreSimulator
|
158
|
-
|
159
|
-
app_bundle_path = launch_options[:bundle_dir_or_bundle_id]
|
160
|
-
app = RunLoop::App.new(app_bundle_path)
|
161
|
-
|
162
|
-
unless app.valid?
|
163
|
-
if !File.exist?(app.path)
|
164
|
-
message = "App '#{app_bundle_path}' does not exist."
|
165
|
-
else
|
166
|
-
message = "App '#{app_bundle_path}' is not a valid .app bundle"
|
167
|
-
end
|
168
|
-
raise RuntimeError, message
|
169
|
-
end
|
170
|
-
|
171
|
-
udid = launch_options[:udid]
|
172
|
-
|
173
|
-
device = sim_control.simulators.find do |sim|
|
174
|
-
sim.udid == udid || sim.instruments_identifier(xcode) == udid
|
175
|
-
end
|
176
|
-
|
177
|
-
if device.nil?
|
178
|
-
raise RuntimeError,
|
179
|
-
"Could not find simulator with name or UDID that matches: '#{udid}'"
|
180
|
-
end
|
181
|
-
|
182
|
-
# Validate the architecture.
|
183
|
-
self.expect_simulator_compatible_arch(device, app, xcode)
|
184
|
-
|
185
|
-
# Quits the simulator.
|
186
|
-
core_sim = RunLoop::CoreSimulator.new(device, app)
|
187
|
-
|
188
|
-
# :reset is a legacy variable; has been replaced with :reset_app_sandbox
|
189
|
-
if launch_options[:reset] || launch_options[:reset_app_sandbox]
|
190
|
-
core_sim.reset_app_sandbox
|
191
|
-
end
|
192
|
-
|
193
|
-
# Will quit the simulator if it is running.
|
194
|
-
# @todo fix accessibility_enabled? so we don't have to quit the sim
|
195
|
-
# SimControl#accessibility_enabled? is always false during Core#prepare_simulator
|
196
|
-
# https://github.com/calabash/run_loop/issues/167
|
197
|
-
sim_control.ensure_accessibility(device)
|
198
|
-
|
199
|
-
# Will quit the simulator if it is running.
|
200
|
-
# @todo fix software_keyboard_enabled? so we don't have to quit the sim
|
201
|
-
# SimControl#software_keyboard_enabled? is always false during Core#prepare_simulator
|
202
|
-
# https://github.com/calabash/run_loop/issues/168
|
203
|
-
sim_control.ensure_software_keyboard(device)
|
204
|
-
|
205
|
-
# Launches the simulator if the app is not installed.
|
206
|
-
core_sim.install
|
207
|
-
|
208
|
-
# If CoreSimulator has already launched the simulator, it will not
|
209
|
-
# launching it again.
|
210
|
-
core_sim.launch_simulator
|
211
|
-
end
|
212
|
-
end
|
213
|
-
|
214
60
|
def self.run_with_options(options)
|
215
61
|
before = Time.now
|
216
62
|
|
217
63
|
self.prepare(options)
|
218
64
|
|
219
65
|
logger = options[:logger]
|
220
|
-
sim_control
|
66
|
+
sim_control = options[:sim_control] || options[:simctl] || RunLoop::SimControl.new
|
67
|
+
xcode = options[:xcode] || RunLoop::Xcode.new
|
68
|
+
instruments = options[:instruments] || RunLoop::Instruments.new
|
221
69
|
|
222
|
-
|
70
|
+
# Find the Device under test, the App under test, UIA strategy, and reset options
|
71
|
+
device = RunLoop::Device.detect_device(options, xcode, sim_control, instruments)
|
72
|
+
app_details = RunLoop::DetectAUT.detect_app_under_test(options)
|
73
|
+
uia_strategy = self.detect_uia_strategy(options, device, xcode)
|
74
|
+
reset_options = self.detect_reset_options(options)
|
223
75
|
|
224
|
-
instruments = RunLoop::Instruments.new
|
225
76
|
instruments.kill_instruments(xcode)
|
226
77
|
|
227
|
-
device_target = options[:udid] || options[:device_target] || detect_connected_device || 'simulator'
|
228
|
-
if device_target && device_target.to_s.downcase == 'device'
|
229
|
-
device_target = detect_connected_device
|
230
|
-
end
|
231
|
-
|
232
|
-
log_file = options[:log_path]
|
233
78
|
timeout = options[:timeout] || 30
|
234
79
|
|
235
80
|
results_dir = options[:results_dir] || RunLoop::DotDir.make_results_dir
|
@@ -253,8 +98,6 @@ module RunLoop
|
|
253
98
|
repl_path = File.join(results_dir, 'repl-cmd.pipe')
|
254
99
|
FileUtils.rm_f(repl_path)
|
255
100
|
|
256
|
-
uia_strategy = options[:uia_strategy]
|
257
|
-
|
258
101
|
if uia_strategy == :host
|
259
102
|
create_uia_pipe(repl_path)
|
260
103
|
else
|
@@ -271,39 +114,33 @@ module RunLoop
|
|
271
114
|
file.puts code
|
272
115
|
end
|
273
116
|
|
274
|
-
udid = options[:udid]
|
275
|
-
bundle_dir_or_bundle_id = options[:bundle_dir_or_bundle_id]
|
276
|
-
|
277
|
-
if !(udid && bundle_dir_or_bundle_id)
|
278
|
-
# Compute udid and bundle_dir / bundle_id from options and target depending on Xcode version
|
279
|
-
udid, bundle_dir_or_bundle_id = self.udid_and_bundle_for_launcher(device_target, options, sim_control)
|
280
|
-
end
|
281
|
-
|
282
117
|
args = options.fetch(:args, [])
|
283
118
|
|
284
|
-
log_file
|
119
|
+
log_file = options[:log_path] || File.join(results_dir, 'run_loop.out')
|
285
120
|
|
286
121
|
discovered_options =
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
122
|
+
{
|
123
|
+
:udid => device.udid,
|
124
|
+
:device => device,
|
125
|
+
:results_dir_trace => results_dir_trace,
|
126
|
+
:bundle_id => app_details[:bundle_id],
|
127
|
+
:app => app_details[:app] || app_details[:bundle_id],
|
128
|
+
:results_dir => results_dir,
|
129
|
+
:script => script,
|
130
|
+
:log_file => log_file,
|
131
|
+
:args => args
|
132
|
+
}
|
296
133
|
merged_options = options.merge(discovered_options)
|
297
134
|
|
298
|
-
if
|
299
|
-
self.prepare_simulator(
|
135
|
+
if device.simulator?
|
136
|
+
self.prepare_simulator(app_details[:app], device, xcode, sim_control, reset_options)
|
300
137
|
end
|
301
138
|
|
302
139
|
self.log_run_loop_options(merged_options, xcode)
|
303
140
|
|
304
141
|
automation_template = automation_template(instruments)
|
305
142
|
|
306
|
-
RunLoop::Logging.log_header(logger, "Starting on #{
|
143
|
+
RunLoop::Logging.log_header(logger, "Starting on #{device.name} App: #{app_details[:bundle_id]}")
|
307
144
|
|
308
145
|
pid = instruments.spawn(automation_template, merged_options, log_file)
|
309
146
|
|
@@ -311,14 +148,16 @@ module RunLoop
|
|
311
148
|
f.write pid
|
312
149
|
end
|
313
150
|
|
314
|
-
run_loop = {
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
151
|
+
run_loop = {
|
152
|
+
:pid => pid,
|
153
|
+
:index => 1,
|
154
|
+
:uia_strategy => uia_strategy,
|
155
|
+
:udid => device.udid,
|
156
|
+
:app => app_details[:bundle_id],
|
157
|
+
:repl_path => repl_path,
|
158
|
+
:log_file => log_file,
|
159
|
+
:results_dir => results_dir
|
160
|
+
}
|
322
161
|
|
323
162
|
uia_timeout = options[:uia_timeout] || RunLoop::Environment.uia_timeout || 10
|
324
163
|
|
@@ -326,8 +165,10 @@ module RunLoop
|
|
326
165
|
|
327
166
|
before_instruments_launch = Time.now
|
328
167
|
|
329
|
-
|
330
|
-
|
168
|
+
fifo_retry_on = [
|
169
|
+
RunLoop::Fifo::NoReaderConfiguredError,
|
170
|
+
RunLoop::Fifo::WriteTimedOut
|
171
|
+
]
|
331
172
|
|
332
173
|
begin
|
333
174
|
|
@@ -364,9 +205,9 @@ module RunLoop
|
|
364
205
|
|
365
206
|
Logfile: #{log_file}
|
366
207
|
|
367
|
-
#{File.read(log_file)}
|
208
|
+
#{File.read(log_file)}
|
368
209
|
|
369
|
-
)
|
210
|
+
)
|
370
211
|
raise RunLoop::TimeoutError, message
|
371
212
|
end
|
372
213
|
|
@@ -375,8 +216,11 @@ Logfile: #{log_file}
|
|
375
216
|
dylib_path = self.dylib_path_from_options(merged_options)
|
376
217
|
|
377
218
|
if dylib_path
|
378
|
-
|
379
|
-
|
219
|
+
if device.physical_device?
|
220
|
+
raise RuntimeError, "Injecting a dylib is not supported when targeting a device"
|
221
|
+
end
|
222
|
+
|
223
|
+
app = app_details[:app]
|
380
224
|
lldb = RunLoop::DylibInjector.new(app.executable_name, dylib_path)
|
381
225
|
lldb.retriable_inject_dylib
|
382
226
|
end
|
@@ -395,7 +239,7 @@ Logfile: #{log_file}
|
|
395
239
|
def self.include_calabash_script?(options)
|
396
240
|
|
397
241
|
if (options[:include_calabash_script] == false) || options[:dismiss_immediate_dialogs]
|
398
|
-
|
242
|
+
return false
|
399
243
|
end
|
400
244
|
if Core.script_for_key(:run_loop_basic) == options[:script]
|
401
245
|
return options[:include_calabash_script]
|
@@ -403,164 +247,71 @@ Logfile: #{log_file}
|
|
403
247
|
true
|
404
248
|
end
|
405
249
|
|
406
|
-
#
|
407
|
-
#
|
408
|
-
#
|
409
|
-
#
|
410
|
-
#
|
411
|
-
#
|
412
|
-
#
|
413
|
-
|
250
|
+
# Extracts the value of :inject_dylib from options Hash.
|
251
|
+
# @param options [Hash] arguments passed to {RunLoop.run}
|
252
|
+
# @return [String, nil] If the options contains :inject_dylibs and it is a
|
253
|
+
# path to a dylib that exists, return the path. Otherwise return nil or
|
254
|
+
# raise an error.
|
255
|
+
# @raise [RuntimeError] If :inject_dylib points to a path that does not exist.
|
256
|
+
# @raise [ArgumentError] If :inject_dylib is not a String.
|
257
|
+
def self.dylib_path_from_options(options)
|
258
|
+
inject_dylib = options.fetch(:inject_dylib, nil)
|
259
|
+
return nil if inject_dylib.nil?
|
260
|
+
unless inject_dylib.is_a? String
|
261
|
+
raise ArgumentError, "Expected :inject_dylib to be a path to a dylib, but found '#{inject_dylib}'"
|
262
|
+
end
|
263
|
+
dylib_path = File.expand_path(inject_dylib)
|
264
|
+
unless File.exist?(dylib_path)
|
265
|
+
raise "Cannot load dylib. The file '#{dylib_path}' does not exist."
|
266
|
+
end
|
267
|
+
dylib_path
|
268
|
+
end
|
269
|
+
|
270
|
+
# Returns the a default simulator to target. This default needs to be one
|
271
|
+
# that installed by default in the current Xcode version.
|
414
272
|
#
|
415
|
-
#
|
273
|
+
# For historical reasons, the most recent non-64b SDK should be used.
|
416
274
|
#
|
417
|
-
# @
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
sim.udid == value,
|
438
|
-
sim.name == value
|
439
|
-
].any?
|
440
|
-
end
|
441
|
-
!simulator.nil?
|
275
|
+
# @param [RunLoop::Xcode] xcode Used to detect the current xcode
|
276
|
+
# version.
|
277
|
+
def self.default_simulator(xcode=RunLoop::Xcode.new)
|
278
|
+
|
279
|
+
if xcode.version_gte_73?
|
280
|
+
"iPhone 6s (9.3)"
|
281
|
+
elsif xcode.version_gte_72?
|
282
|
+
"iPhone 6s (9.2)"
|
283
|
+
elsif xcode.version_gte_71?
|
284
|
+
"iPhone 6s (9.1)"
|
285
|
+
elsif xcode.version_gte_7?
|
286
|
+
"iPhone 5s (9.0)"
|
287
|
+
elsif xcode.version_gte_64?
|
288
|
+
"iPhone 5s (8.4 Simulator)"
|
289
|
+
elsif xcode.version_gte_63?
|
290
|
+
"iPhone 5s (8.3 Simulator)"
|
291
|
+
elsif xcode.version_gte_62?
|
292
|
+
"iPhone 5s (8.2 Simulator)"
|
293
|
+
elsif xcode.version_gte_61?
|
294
|
+
"iPhone 5s (8.1 Simulator)"
|
442
295
|
else
|
443
|
-
|
296
|
+
"iPhone 5s (8.0 Simulator)"
|
444
297
|
end
|
445
298
|
end
|
446
299
|
|
447
300
|
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
raise ArgumentError, "Expected :inject_dylib to be a path to a dylib, but found '#{inject_dylib}'"
|
460
|
-
end
|
461
|
-
dylib_path = File.expand_path(inject_dylib)
|
462
|
-
unless File.exist?(dylib_path)
|
463
|
-
raise "Cannot load dylib. The file '#{dylib_path}' does not exist."
|
464
|
-
end
|
465
|
-
dylib_path
|
466
|
-
end
|
467
|
-
|
468
|
-
# Returns the a default simulator to target. This default needs to be one
|
469
|
-
# that installed by default in the current Xcode version.
|
470
|
-
#
|
471
|
-
# For historical reasons, the most recent non-64b SDK should be used.
|
472
|
-
#
|
473
|
-
# @param [RunLoop::Xcode] xcode Used to detect the current xcode
|
474
|
-
# version.
|
475
|
-
def self.default_simulator(xcode=RunLoop::Xcode.new)
|
476
|
-
|
477
|
-
if xcode.version_gte_73?
|
478
|
-
"iPhone 6s (9.3)"
|
479
|
-
elsif xcode.version_gte_72?
|
480
|
-
"iPhone 6s (9.2)"
|
481
|
-
elsif xcode.version_gte_71?
|
482
|
-
"iPhone 6s (9.1)"
|
483
|
-
elsif xcode.version_gte_7?
|
484
|
-
"iPhone 5s (9.0)"
|
485
|
-
elsif xcode.version_gte_64?
|
486
|
-
"iPhone 5s (8.4 Simulator)"
|
487
|
-
elsif xcode.version_gte_63?
|
488
|
-
"iPhone 5s (8.3 Simulator)"
|
489
|
-
elsif xcode.version_gte_62?
|
490
|
-
"iPhone 5s (8.2 Simulator)"
|
491
|
-
elsif xcode.version_gte_61?
|
492
|
-
"iPhone 5s (8.1 Simulator)"
|
493
|
-
elsif xcode.version_gte_6?
|
494
|
-
"iPhone 5s (8.0 Simulator)"
|
495
|
-
else
|
496
|
-
"iPhone Retina (4-inch) - Simulator - iOS 7.1"
|
497
|
-
end
|
498
|
-
end
|
499
|
-
|
500
|
-
def self.udid_and_bundle_for_launcher(device_target, options, sim_control=RunLoop::SimControl.new)
|
501
|
-
xcode = sim_control.xcode
|
502
|
-
|
503
|
-
bundle_dir_or_bundle_id = options[:app] || RunLoop::Environment.bundle_id || RunLoop::Environment.path_to_app_bundle
|
504
|
-
|
505
|
-
unless bundle_dir_or_bundle_id
|
506
|
-
raise 'key :app or environment variable APP_BUNDLE_PATH, BUNDLE_ID or APP must be specified as path to app bundle (simulator) or bundle id (device)'
|
507
|
-
end
|
508
|
-
|
509
|
-
udid = nil
|
510
|
-
|
511
|
-
if xcode.version_gte_51?
|
512
|
-
if device_target.nil? || device_target.empty? || device_target == 'simulator'
|
513
|
-
device_target = self.default_simulator(xcode)
|
514
|
-
end
|
515
|
-
udid = device_target
|
516
|
-
|
517
|
-
unless self.simulator_target?(options)
|
518
|
-
bundle_dir_or_bundle_id = options[:bundle_id] if options[:bundle_id]
|
519
|
-
end
|
520
|
-
else
|
521
|
-
#TODO: this can be removed - Xcode < 5.1.1 not supported.
|
522
|
-
if device_target == 'simulator'
|
523
|
-
|
524
|
-
unless File.exist?(bundle_dir_or_bundle_id)
|
525
|
-
raise "Unable to find app in directory #{bundle_dir_or_bundle_id} when trying to launch simulator"
|
526
|
-
end
|
527
|
-
|
528
|
-
|
529
|
-
device = options[:device] || :iphone
|
530
|
-
device = device && device.to_sym
|
531
|
-
|
532
|
-
plistbuddy='/usr/libexec/PlistBuddy'
|
533
|
-
plistfile="#{bundle_dir_or_bundle_id}/Info.plist"
|
534
|
-
if device == :iphone
|
535
|
-
uidevicefamily=1
|
536
|
-
else
|
537
|
-
uidevicefamily=2
|
538
|
-
end
|
539
|
-
system("#{plistbuddy} -c 'Delete :UIDeviceFamily' '#{plistfile}'")
|
540
|
-
system("#{plistbuddy} -c 'Add :UIDeviceFamily array' '#{plistfile}'")
|
541
|
-
system("#{plistbuddy} -c 'Add :UIDeviceFamily:0 integer #{uidevicefamily}' '#{plistfile}'")
|
542
|
-
else
|
543
|
-
udid = device_target
|
544
|
-
bundle_dir_or_bundle_id = options[:bundle_id] if options[:bundle_id]
|
545
|
-
end
|
546
|
-
end
|
547
|
-
return udid, bundle_dir_or_bundle_id
|
548
|
-
end
|
549
|
-
|
550
|
-
def self.create_uia_pipe(repl_path)
|
551
|
-
begin
|
552
|
-
Timeout::timeout(5, RunLoop::TimeoutError) do
|
553
|
-
loop do
|
554
|
-
begin
|
555
|
-
FileUtils.rm_f(repl_path)
|
556
|
-
return repl_path if system(%Q[mkfifo "#{repl_path}"])
|
557
|
-
rescue Errno::EINTR => e
|
558
|
-
#retry
|
559
|
-
sleep(0.1)
|
301
|
+
def self.create_uia_pipe(repl_path)
|
302
|
+
begin
|
303
|
+
Timeout::timeout(5, RunLoop::TimeoutError) do
|
304
|
+
loop do
|
305
|
+
begin
|
306
|
+
FileUtils.rm_f(repl_path)
|
307
|
+
return repl_path if system(%Q[mkfifo "#{repl_path}"])
|
308
|
+
rescue Errno::EINTR => e
|
309
|
+
#retry
|
310
|
+
sleep(0.1)
|
311
|
+
end
|
560
312
|
end
|
561
313
|
end
|
562
|
-
|
563
|
-
rescue RunLoop::TimeoutError => _
|
314
|
+
rescue RunLoop::TimeoutError => _
|
564
315
|
raise RunLoop::TimeoutError, 'Unable to create pipe (mkfifo failed)'
|
565
316
|
end
|
566
317
|
end
|
@@ -581,7 +332,7 @@ Logfile: #{log_file}
|
|
581
332
|
RunLoop::Fifo.write(repl_path, cmd_str)
|
582
333
|
write_succeeded = validate_index_written(run_loop, index, logger)
|
583
334
|
rescue RunLoop::Fifo::NoReaderConfiguredError,
|
584
|
-
|
335
|
+
RunLoop::Fifo::WriteTimedOut => e
|
585
336
|
RunLoop::Logging.log_debug(logger, "Error while writing command (retry count #{i}). #{e}")
|
586
337
|
end
|
587
338
|
break if write_succeeded
|
@@ -744,13 +495,91 @@ Logfile: #{log_file}
|
|
744
495
|
end
|
745
496
|
|
746
497
|
message = ['Expected instruments to report an Automation tracetemplate.',
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
498
|
+
'Please report this as bug: https://github.com/calabash/run_loop/issues',
|
499
|
+
"In the bug report, include the output of:\n",
|
500
|
+
'$ xcrun xcodebuild -version',
|
501
|
+
"$ xcrun instruments -s templates\n"]
|
751
502
|
raise message.join("\n")
|
752
503
|
end
|
753
504
|
|
505
|
+
# @deprecated 2.1.0
|
506
|
+
# Replaced with Device.detect_physical_device_on_usb
|
507
|
+
def self.detect_connected_device
|
508
|
+
begin
|
509
|
+
Timeout::timeout(1, RunLoop::TimeoutError) do
|
510
|
+
return `#{File.join(scripts_path, 'udidetect')}`.chomp
|
511
|
+
end
|
512
|
+
rescue RunLoop::TimeoutError => _
|
513
|
+
`killall udidetect &> /dev/null`
|
514
|
+
end
|
515
|
+
nil
|
516
|
+
end
|
517
|
+
|
518
|
+
# @deprecated 2.1.0
|
519
|
+
# @!visibility private
|
520
|
+
# Are we targeting a simulator?
|
521
|
+
#
|
522
|
+
# @note The behavior of this method is different than the corresponding
|
523
|
+
# method in Calabash::Cucumber::Launcher method. If
|
524
|
+
# `:device_target => {nil | ''}`, then the calabash-ios method returns
|
525
|
+
# _false_. I am basing run-loop's behavior off the behavior in
|
526
|
+
# `self.udid_and_bundle_for_launcher`
|
527
|
+
#
|
528
|
+
# @see {Core::RunLoop.udid_and_bundle_for_launcher}
|
529
|
+
#
|
530
|
+
# @todo sim_control argument is no longer necessary and can be removed.
|
531
|
+
def self.simulator_target?(run_options, sim_control=nil)
|
532
|
+
# TODO Enable deprecation warning
|
533
|
+
# RunLoop.deprecated("2.1.0", "No replacement")
|
534
|
+
value = run_options[:device_target]
|
535
|
+
|
536
|
+
# Match the behavior of udid_and_bundle_for_launcher.
|
537
|
+
return true if value.nil? or value == ''
|
538
|
+
|
539
|
+
# 5.1 <= Xcode < 7.0
|
540
|
+
return true if value.downcase.include?('simulator')
|
541
|
+
|
542
|
+
# Not a physical device.
|
543
|
+
return false if value[DEVICE_UDID_REGEX, 0] != nil
|
544
|
+
|
545
|
+
# Check for named simulators and Xcode >= 7.0 simulators.
|
546
|
+
sim_control = run_options[:sim_control] || RunLoop::SimControl.new
|
547
|
+
xcode = sim_control.xcode
|
548
|
+
simulator = sim_control.simulators.find do |sim|
|
549
|
+
[
|
550
|
+
sim.instruments_identifier(xcode) == value,
|
551
|
+
sim.udid == value,
|
552
|
+
sim.name == value
|
553
|
+
].any?
|
554
|
+
end
|
555
|
+
!simulator.nil?
|
556
|
+
end
|
557
|
+
|
558
|
+
# @!visibility private
|
559
|
+
# @deprecated 2.1.0
|
560
|
+
#
|
561
|
+
# Do not call this method.
|
562
|
+
def self.udid_and_bundle_for_launcher(device_target, options, sim_control=RunLoop::SimControl.new)
|
563
|
+
RunLoop.deprecated("2.1.0", "No replacement")
|
564
|
+
xcode = sim_control.xcode
|
565
|
+
|
566
|
+
bundle_dir_or_bundle_id = options[:app] || RunLoop::Environment.bundle_id || RunLoop::Environment.path_to_app_bundle
|
567
|
+
|
568
|
+
unless bundle_dir_or_bundle_id
|
569
|
+
raise 'key :app or environment variable APP_BUNDLE_PATH, BUNDLE_ID or APP must be specified as path to app bundle (simulator) or bundle id (device)'
|
570
|
+
end
|
571
|
+
|
572
|
+
if device_target.nil? || device_target.empty? || device_target == 'simulator'
|
573
|
+
device_target = self.default_simulator(xcode)
|
574
|
+
end
|
575
|
+
udid = device_target
|
576
|
+
|
577
|
+
unless self.simulator_target?(options)
|
578
|
+
bundle_dir_or_bundle_id = options[:bundle_id] if options[:bundle_id]
|
579
|
+
end
|
580
|
+
return udid, bundle_dir_or_bundle_id
|
581
|
+
end
|
582
|
+
|
754
583
|
# @deprecated 1.0.5
|
755
584
|
def self.ensure_instruments_not_running!
|
756
585
|
RunLoop::Instruments.new.kill_instruments
|
@@ -794,10 +623,106 @@ Logfile: #{log_file}
|
|
794
623
|
|
795
624
|
private
|
796
625
|
|
626
|
+
# @!visibility private
|
627
|
+
#
|
628
|
+
# @param [Hash] options The launch options passed to .run_with_options
|
797
629
|
def self.prepare(run_options)
|
798
630
|
RunLoop::DotDir.rotate_result_directories
|
799
631
|
RunLoop::Instruments.rotate_cache_directories
|
800
632
|
true
|
801
633
|
end
|
634
|
+
|
635
|
+
# @!visibility private
|
636
|
+
#
|
637
|
+
# @param [RunLoop::Device] device The device under test.
|
638
|
+
# @param [RunLoop::Xcode] xcode The active Xcode
|
639
|
+
def self.default_uia_strategy(device, xcode)
|
640
|
+
if xcode.version_gte_7?
|
641
|
+
:host
|
642
|
+
elsif device.physical_device? && device.version >= RunLoop::Version.new("8.0")
|
643
|
+
:host
|
644
|
+
else
|
645
|
+
:preferences
|
646
|
+
end
|
647
|
+
end
|
648
|
+
|
649
|
+
# @!visibility private
|
650
|
+
#
|
651
|
+
# @param [Hash] options The launch options passed to .run_with_options
|
652
|
+
# @param [RunLoop::Device] device The device under test.
|
653
|
+
# @param [RunLoop::Xcode] xcode The active Xcode.
|
654
|
+
def self.detect_uia_strategy(options, device, xcode)
|
655
|
+
strategy = options[:uia_strategy] || self.default_uia_strategy(device, xcode)
|
656
|
+
|
657
|
+
if ![:host, :preferences, :shared_element].include?(strategy)
|
658
|
+
raise ArgumentError,
|
659
|
+
"Invalid strategy: expected '#{strategy}' to be :host, :preferences, or :shared_element"
|
660
|
+
end
|
661
|
+
strategy
|
662
|
+
end
|
663
|
+
|
664
|
+
# @!visibility private
|
665
|
+
#
|
666
|
+
# @param [Hash] options The launch options passed to .run_with_options
|
667
|
+
def self.detect_reset_options(options)
|
668
|
+
return options[:reset] if options.has_key?(:reset)
|
669
|
+
|
670
|
+
return options[:reset_app_sandbox] if options.has_key?(:reset_app_sandbox)
|
671
|
+
|
672
|
+
RunLoop::Environment.reset_between_scenarios?
|
673
|
+
end
|
674
|
+
|
675
|
+
# Prepares the simulator for running.
|
676
|
+
#
|
677
|
+
# 1. enabling accessibility and software keyboard
|
678
|
+
# 2. installing / uninstalling apps
|
679
|
+
def self.prepare_simulator(app, device, xcode, simctl, reset_options)
|
680
|
+
|
681
|
+
# Validate the architecture.
|
682
|
+
self.expect_simulator_compatible_arch(device, app)
|
683
|
+
|
684
|
+
# Quits the simulator.
|
685
|
+
core_sim = RunLoop::CoreSimulator.new(device, app, :xcode => xcode)
|
686
|
+
|
687
|
+
# Calabash 0.x can only reset the app sandbox (true/false).
|
688
|
+
# Calabash 2.x has advanced reset options.
|
689
|
+
if reset_options
|
690
|
+
core_sim.reset_app_sandbox
|
691
|
+
end
|
692
|
+
|
693
|
+
# Will quit the simulator if it is running.
|
694
|
+
# @todo fix accessibility_enabled? so we don't have to quit the sim
|
695
|
+
# SimControl#accessibility_enabled? is always false during Core#prepare_simulator
|
696
|
+
# https://github.com/calabash/run_loop/issues/167
|
697
|
+
simctl.ensure_accessibility(device)
|
698
|
+
|
699
|
+
# Will quit the simulator if it is running.
|
700
|
+
# @todo fix software_keyboard_enabled? so we don't have to quit the sim
|
701
|
+
# SimControl#software_keyboard_enabled? is always false during Core#prepare_simulator
|
702
|
+
# https://github.com/calabash/run_loop/issues/168
|
703
|
+
simctl.ensure_software_keyboard(device)
|
704
|
+
|
705
|
+
# Launches the simulator if the app is not installed.
|
706
|
+
core_sim.install
|
707
|
+
|
708
|
+
# If CoreSimulator has already launched the simulator, it will not launch it again.
|
709
|
+
core_sim.launch_simulator
|
710
|
+
end
|
711
|
+
|
712
|
+
# @!visibility private
|
713
|
+
# Raise an error if the application binary is not compatible with the
|
714
|
+
# target simulator.
|
715
|
+
#
|
716
|
+
# @param [RunLoop::Device] device The device to install on.
|
717
|
+
# @param [RunLoop::App] app The app to install.
|
718
|
+
#
|
719
|
+
# @raise [RunLoop::IncompatibleArchitecture] Raises an error if the
|
720
|
+
# application binary is not compatible with the target simulator.
|
721
|
+
def self.expect_simulator_compatible_arch(device, app)
|
722
|
+
lipo = RunLoop::Lipo.new(app.path)
|
723
|
+
lipo.expect_compatible_arch(device)
|
724
|
+
|
725
|
+
RunLoop.log_debug("Simulator instruction set '#{device.instruction_set}' is compatible with '#{lipo.info}'")
|
726
|
+
end
|
802
727
|
end
|
803
728
|
end
|
@@ -508,11 +508,9 @@ $ bundle exec run-loop simctl manage-processes
|
|
508
508
|
def sim_name
|
509
509
|
@sim_name ||= lambda {
|
510
510
|
if xcode.version_gte_7?
|
511
|
-
|
512
|
-
elsif xcode.version_gte_6?
|
513
|
-
'iOS Simulator'
|
511
|
+
"Simulator"
|
514
512
|
else
|
515
|
-
|
513
|
+
"iOS Simulator"
|
516
514
|
end
|
517
515
|
}.call
|
518
516
|
end
|
@@ -527,10 +525,8 @@ $ bundle exec run-loop simctl manage-processes
|
|
527
525
|
dev_dir = xcode.developer_dir
|
528
526
|
if xcode.version_gte_7?
|
529
527
|
"#{dev_dir}/Applications/Simulator.app"
|
530
|
-
elsif xcode.version_gte_6?
|
531
|
-
"#{dev_dir}/Applications/iOS Simulator.app"
|
532
528
|
else
|
533
|
-
"#{dev_dir}/
|
529
|
+
"#{dev_dir}/Applications/iOS Simulator.app"
|
534
530
|
end
|
535
531
|
}.call
|
536
532
|
end
|
@@ -3,6 +3,24 @@ module RunLoop
|
|
3
3
|
# @!visibility private
|
4
4
|
module DetectAUT
|
5
5
|
|
6
|
+
# @!visibility private
|
7
|
+
def self.detect_app_under_test(options)
|
8
|
+
app = self.detect_app(options)
|
9
|
+
if app.is_a?(RunLoop::App) || app.is_a?(RunLoop::Ipa)
|
10
|
+
{
|
11
|
+
:app => app,
|
12
|
+
:bundle_id => app.bundle_identifier,
|
13
|
+
:is_ipa => app.is_a?(RunLoop::Ipa)
|
14
|
+
}
|
15
|
+
else
|
16
|
+
{
|
17
|
+
:app => nil,
|
18
|
+
:bundle_id => app,
|
19
|
+
:is_ipa => false
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
6
24
|
# @!visibility private
|
7
25
|
class Detect
|
8
26
|
include RunLoop::DetectAUT::Errors
|
@@ -103,5 +121,59 @@ module RunLoop
|
|
103
121
|
end
|
104
122
|
end
|
105
123
|
end
|
124
|
+
|
125
|
+
private
|
126
|
+
|
127
|
+
# @!visibility private
|
128
|
+
def self.app_from_options(options)
|
129
|
+
options[:app] || options[:bundle_id]
|
130
|
+
end
|
131
|
+
|
132
|
+
# @!visibility private
|
133
|
+
def self.app_from_environment
|
134
|
+
RunLoop::Environment.path_to_app_bundle ||
|
135
|
+
RunLoop::Environment.bundle_id
|
136
|
+
end
|
137
|
+
|
138
|
+
# @!visibility private
|
139
|
+
def self.app_from_constant
|
140
|
+
(defined?(APP_BUNDLE_PATH) && APP_BUNDLE_PATH) ||
|
141
|
+
(defined?(APP) && APP)
|
142
|
+
end
|
143
|
+
|
144
|
+
# @!visibility private
|
145
|
+
def self.app_from_opts_or_env_or_constant(options)
|
146
|
+
self.app_from_options(options) ||
|
147
|
+
self.app_from_environment ||
|
148
|
+
self.app_from_constant
|
149
|
+
end
|
150
|
+
|
151
|
+
# @!visibility private
|
152
|
+
def self.detector
|
153
|
+
RunLoop::DetectAUT::Detect.new
|
154
|
+
end
|
155
|
+
|
156
|
+
# @!visibility private
|
157
|
+
def self.detect_app(options)
|
158
|
+
app = self.app_from_opts_or_env_or_constant(options)
|
159
|
+
|
160
|
+
# Options or constant defined an instance of App or Ipa
|
161
|
+
return app if app && (app.is_a?(RunLoop::App) || app.is_a?(RunLoop::Ipa))
|
162
|
+
|
163
|
+
# User provided no information, so we attempt to auto detect
|
164
|
+
if app.nil? || app == ""
|
165
|
+
return self.detector.app_for_simulator
|
166
|
+
end
|
167
|
+
|
168
|
+
extension = File.extname(app)
|
169
|
+
if extension == ".ipa" && File.exist?(app)
|
170
|
+
RunLoop::Ipa.new(app)
|
171
|
+
elsif extension == ".app" && File.exist?(app)
|
172
|
+
RunLoop::App.new(app)
|
173
|
+
else
|
174
|
+
# Probably a bundle identifier.
|
175
|
+
app
|
176
|
+
end
|
177
|
+
end
|
106
178
|
end
|
107
179
|
end
|
data/lib/run_loop/device.rb
CHANGED
@@ -128,6 +128,41 @@ Please update your sources.))
|
|
128
128
|
raise ArgumentError, "Could not find a device with a UDID or name matching '#{udid_or_name}'"
|
129
129
|
end
|
130
130
|
|
131
|
+
# @!visibility private
|
132
|
+
#
|
133
|
+
# Please don't call this method. It is for internal use only. The behavior
|
134
|
+
# may change at any time! You have been warned.
|
135
|
+
#
|
136
|
+
# @param [Hash] options The launch options passed to RunLoop::Core
|
137
|
+
# @param [RunLoop::Xcode] xcode An Xcode instance
|
138
|
+
# @param [RunLoop::SimControl] simctl A SimControl instance
|
139
|
+
# @param [RunLoop::Instruments] instruments An Instruments instance
|
140
|
+
#
|
141
|
+
# @raise [ArgumentError] If "device" is detected as the device target and
|
142
|
+
# there is no matching device.
|
143
|
+
# @raise [ArgumentError] If DEVICE_TARGET or options specify an identifier
|
144
|
+
# that does not match an iOS Simulator or phyiscal device.
|
145
|
+
def self.detect_device(options, xcode, simctl, instruments)
|
146
|
+
device = self.device_from_opts_or_env(options)
|
147
|
+
|
148
|
+
# Passed an instance of RunLoop::Device
|
149
|
+
return device if device && device.is_a?(RunLoop::Device)
|
150
|
+
|
151
|
+
# Need to infer what what the user wants from the environment and options.
|
152
|
+
if device == "device"
|
153
|
+
identifier = self.detect_physical_device_on_usb
|
154
|
+
self.ensure_physical_device_connected(identifier, options)
|
155
|
+
elsif device.nil? || device == "" || device == "simulator"
|
156
|
+
identifier = RunLoop::Core.default_simulator(xcode)
|
157
|
+
else
|
158
|
+
identifier = device
|
159
|
+
end
|
160
|
+
|
161
|
+
# Raises ArgumentError if no matching device can be found.
|
162
|
+
self.device_with_identifier(identifier, sim_control: simctl,
|
163
|
+
instruments: instruments)
|
164
|
+
end
|
165
|
+
|
131
166
|
# @!visibility private
|
132
167
|
def to_s
|
133
168
|
if simulator?
|
@@ -162,10 +197,8 @@ Please update your sources.))
|
|
162
197
|
|
163
198
|
if xcode.version_gte_7?
|
164
199
|
"#{name} (#{version_part})"
|
165
|
-
elsif xcode.version_gte_6?
|
166
|
-
"#{name} (#{version_part} Simulator)"
|
167
200
|
else
|
168
|
-
|
201
|
+
"#{name} (#{version_part} Simulator)"
|
169
202
|
end
|
170
203
|
end
|
171
204
|
end
|
@@ -173,13 +206,13 @@ Please update your sources.))
|
|
173
206
|
# Is this a physical device?
|
174
207
|
# @return [Boolean] Returns true if this is a device.
|
175
208
|
def physical_device?
|
176
|
-
|
209
|
+
!udid[DEVICE_UDID_REGEX, 0].nil?
|
177
210
|
end
|
178
211
|
|
179
212
|
# Is this a simulator?
|
180
213
|
# @return [Boolean] Returns true if this is a simulator.
|
181
214
|
def simulator?
|
182
|
-
|
215
|
+
!physical_device?
|
183
216
|
end
|
184
217
|
|
185
218
|
# Return the instruction set for this device.
|
@@ -572,5 +605,78 @@ Please update your sources.))
|
|
572
605
|
|
573
606
|
# TODO Is this a good idea? It speeds up rspec tests by a factor of ~2x...
|
574
607
|
SIM_CONTROL = RunLoop::SimControl.new
|
608
|
+
|
609
|
+
# @!visibility private
|
610
|
+
def self.device_from_options(options)
|
611
|
+
options[:device] || options[:device_target] || options[:udid]
|
612
|
+
end
|
613
|
+
|
614
|
+
# @!visibility private
|
615
|
+
def self.device_from_environment
|
616
|
+
RunLoop::Environment.device_target
|
617
|
+
end
|
618
|
+
|
619
|
+
# @!visibility private
|
620
|
+
def self.device_from_opts_or_env(options)
|
621
|
+
self.device_from_options(options) || self.device_from_environment
|
622
|
+
end
|
623
|
+
|
624
|
+
# @!visibility private
|
625
|
+
UDID_DETECT = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", 'scripts', "udidetect"))
|
626
|
+
|
627
|
+
# @!visibility private
|
628
|
+
def self.detect_physical_device_on_usb
|
629
|
+
require "command_runner"
|
630
|
+
|
631
|
+
udid = nil
|
632
|
+
begin
|
633
|
+
hash = CommandRunner.run([UDID_DETECT], timeout: 1)
|
634
|
+
udid = hash[:out].chomp
|
635
|
+
if udid == ""
|
636
|
+
udid = nil
|
637
|
+
end
|
638
|
+
rescue => e
|
639
|
+
RunLoop.log_debug("Running `udidetect` raised: #{e}")
|
640
|
+
ensure
|
641
|
+
`killall udidetect &> /dev/null`
|
642
|
+
end
|
643
|
+
udid
|
644
|
+
end
|
645
|
+
|
646
|
+
# @!visibility private
|
647
|
+
def self.ensure_physical_device_connected(identifier, options)
|
648
|
+
if identifier.nil?
|
649
|
+
env = self.device_from_environment
|
650
|
+
if env == "device"
|
651
|
+
message = "DEVICE_TARGET=device means that you want to test on physical device"
|
652
|
+
elsif env && env[DEVICE_UDID_REGEX, 0]
|
653
|
+
message = "DEVICE_TARGET=#{env} did not match any connected device"
|
654
|
+
else
|
655
|
+
if options[:device]
|
656
|
+
key = ":device"
|
657
|
+
elsif options[:device_target]
|
658
|
+
key = ":device_target"
|
659
|
+
else
|
660
|
+
key = ":udid"
|
661
|
+
end
|
662
|
+
message = "#{key} => \"device\" means that you want to test on a physical device"
|
663
|
+
end
|
664
|
+
|
665
|
+
raise ArgumentError, %Q[Expected a physical device to be connected via USB.
|
666
|
+
|
667
|
+
#{message}
|
668
|
+
|
669
|
+
1. Is your device connected?
|
670
|
+
2. Does your device appear in the output of `xcrun instruments -s devices`?
|
671
|
+
3. Does your device appear in Xcode > Windows > Devices without a warning message?
|
672
|
+
|
673
|
+
Please see the documentation about testing on physical devices.
|
674
|
+
|
675
|
+
https://github.com/calabash/calabash-ios/wiki/Testing-on-Physical-Devices
|
676
|
+
]
|
677
|
+
end
|
678
|
+
true
|
679
|
+
end
|
575
680
|
end
|
576
681
|
end
|
682
|
+
|
data/lib/run_loop/environment.rb
CHANGED
@@ -48,6 +48,11 @@ module RunLoop
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
+
# Should the app data be reset between Scenarios?
|
52
|
+
def self.reset_between_scenarios?
|
53
|
+
ENV["RESET_BETWEEN_SCENARIOS"] == "1"
|
54
|
+
end
|
55
|
+
|
51
56
|
# Returns the value of XCODEPROJ which can be used to specify an Xcode
|
52
57
|
# project directory (my.xcodeproj).
|
53
58
|
#
|
data/lib/run_loop/instruments.rb
CHANGED
@@ -198,20 +198,14 @@ module RunLoop
|
|
198
198
|
@instruments_templates ||= lambda do
|
199
199
|
args = ['instruments', '-s', 'templates']
|
200
200
|
hash = xcrun.exec(args, log_cmd: true)
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
end.compact
|
210
|
-
else
|
211
|
-
hash[:out].strip.split("\n").delete_if do |path|
|
212
|
-
not path =~ /tracetemplate/
|
213
|
-
end.map { |elm| elm.strip }
|
214
|
-
end
|
201
|
+
hash[:out].chomp.split("\n").map do |elm|
|
202
|
+
stripped = elm.strip.tr('"', '')
|
203
|
+
if stripped == '' || stripped == 'Known Templates:'
|
204
|
+
nil
|
205
|
+
else
|
206
|
+
stripped
|
207
|
+
end
|
208
|
+
end.compact
|
215
209
|
end.call
|
216
210
|
end
|
217
211
|
|
@@ -306,29 +300,7 @@ module RunLoop
|
|
306
300
|
array = ['instruments']
|
307
301
|
array << '-w'
|
308
302
|
|
309
|
-
|
310
|
-
# Ambiguous device name/identifier errors (from instruments)
|
311
|
-
if xcode.version_gte_7?
|
312
|
-
udid = options[:udid]
|
313
|
-
|
314
|
-
if udid[DEVICE_UDID_REGEX, 0]
|
315
|
-
array << udid
|
316
|
-
else
|
317
|
-
match = simulators.find do |simulator|
|
318
|
-
[simulator.name == udid,
|
319
|
-
simulator.udid == udid,
|
320
|
-
simulator.instruments_identifier(xcode) == udid].any?
|
321
|
-
end
|
322
|
-
|
323
|
-
if match
|
324
|
-
array << match.udid
|
325
|
-
else
|
326
|
-
array << udid
|
327
|
-
end
|
328
|
-
end
|
329
|
-
else
|
330
|
-
array << options[:udid]
|
331
|
-
end
|
303
|
+
array << options[:udid]
|
332
304
|
|
333
305
|
trace = options[:results_dir_trace]
|
334
306
|
if trace
|
@@ -339,7 +311,7 @@ module RunLoop
|
|
339
311
|
array << '-t'
|
340
312
|
array << automation_template
|
341
313
|
|
342
|
-
array << options[:
|
314
|
+
array << options[:bundle_id]
|
343
315
|
|
344
316
|
{
|
345
317
|
'UIARESULTSPATH' => options[:results_dir],
|
data/lib/run_loop/l10n.rb
CHANGED
@@ -70,31 +70,7 @@ module RunLoop
|
|
70
70
|
end
|
71
71
|
|
72
72
|
def uikit_bundle_l10n_path
|
73
|
-
|
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')
|
73
|
+
File.join(xcode.developer_dir, UIKIT_AXBUNDLE_PATH_CORE_SIM)
|
98
74
|
end
|
99
75
|
|
100
76
|
def is_full_name?(two_letter_country_code)
|
data/lib/run_loop/logging.rb
CHANGED
data/lib/run_loop/sim_control.rb
CHANGED
@@ -37,7 +37,9 @@ module RunLoop
|
|
37
37
|
end
|
38
38
|
|
39
39
|
# @!visibility private
|
40
|
+
# @deprecated 2.1.0
|
40
41
|
def xcode_version_gte_51?
|
42
|
+
RunLoop.deprecated("2.1.0", "No replacement.")
|
41
43
|
xcode.version_gte_51?
|
42
44
|
end
|
43
45
|
|
@@ -401,10 +403,6 @@ module RunLoop
|
|
401
403
|
end
|
402
404
|
|
403
405
|
def software_keyboard_enabled?(device)
|
404
|
-
unless xcode_version_gte_51?
|
405
|
-
raise RuntimeError, 'Keyboard enabling is only available on Xcode >= 6'
|
406
|
-
end
|
407
|
-
|
408
406
|
plist = device.simulator_preferences_plist_path
|
409
407
|
return false unless File.exist?(plist)
|
410
408
|
|
data/lib/run_loop/version.rb
CHANGED
data/lib/run_loop/xcode.rb
CHANGED
@@ -175,10 +175,12 @@ module RunLoop
|
|
175
175
|
version >= v60
|
176
176
|
end
|
177
177
|
|
178
|
+
# @deprecated 2.1.0
|
178
179
|
# Is the active Xcode version 5.1 or above?
|
179
180
|
#
|
180
181
|
# @return [Boolean] `true` if the current Xcode version is >= 5.1
|
181
182
|
def version_gte_51?
|
183
|
+
RunLoop.deprecated("2.1.0", "No replacement")
|
182
184
|
version >= v51
|
183
185
|
end
|
184
186
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: run_loop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.1.0.pre1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Karl Krukow
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-03-
|
11
|
+
date: 2016-03-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|