run_loop 2.1.6 → 2.1.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/run_loop.rb +1 -0
- data/lib/run_loop/app.rb +12 -8
- data/lib/run_loop/cli/cli.rb +2 -2
- data/lib/run_loop/cli/simctl.rb +0 -5
- data/lib/run_loop/core.rb +2 -1
- data/lib/run_loop/core_simulator.rb +56 -106
- data/lib/run_loop/device.rb +23 -41
- data/lib/run_loop/device_agent/Frameworks.zip +0 -0
- data/lib/run_loop/device_agent/app/CBX-Runner.app.zip +0 -0
- data/lib/run_loop/device_agent/bin/iOSDeviceManager +0 -0
- data/lib/run_loop/device_agent/ios_device_manager.rb +11 -2
- data/lib/run_loop/device_agent/ipa/CBX-Runner.app.zip +0 -0
- data/lib/run_loop/device_agent/xcodebuild.rb +7 -2
- data/lib/run_loop/environment.rb +2 -2
- data/lib/run_loop/instruments.rb +4 -1
- data/lib/run_loop/otool.rb +40 -24
- data/lib/run_loop/physical_device/ios_device_manager.rb +89 -0
- data/lib/run_loop/regex.rb +1 -1
- data/lib/run_loop/shell.rb +38 -4
- data/lib/run_loop/sim_control.rb +6 -2
- data/lib/run_loop/simctl.rb +298 -5
- data/lib/run_loop/version.rb +1 -1
- data/lib/run_loop/xcuitest.rb +168 -22
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8451119a8e88cf2179b1b7a0bfc554a19459e9c5
|
4
|
+
data.tar.gz: 0b75d4af7f258d99780c624750dc3e3f241e5581
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ad70df268ab1bcd8001f71cb81499653ec67428be5e5fd78a7a6a89d83e527b7fe3e2da982be52bb0c1480eee57de119b40b2a1c3a4b290e6a5d5b5c9565afb2
|
7
|
+
data.tar.gz: d75408caf251d7b4a4ebf532adfe361697dc7cf46e4aab6f15c6447818622604c13205a764202ff5796079e2e28ec0fed871fbe73309d63cdbf1f99e63eaeed5
|
data/lib/run_loop.rb
CHANGED
data/lib/run_loop/app.rb
CHANGED
@@ -180,7 +180,7 @@ Bundle must:
|
|
180
180
|
# See #marketing_version
|
181
181
|
alias_method :short_bundle_version, :marketing_version
|
182
182
|
|
183
|
-
# Returns the
|
183
|
+
# Returns the CFBundleVersion of the app as Version instance.
|
184
184
|
#
|
185
185
|
# Apple docs:
|
186
186
|
#
|
@@ -195,14 +195,14 @@ Bundle must:
|
|
195
195
|
# @return [RunLoop::Version, nil] Returns a Version instance if the
|
196
196
|
# CFBundleVersion string is well formed and nil if not.
|
197
197
|
def build_version
|
198
|
-
string = plist_buddy.plist_read("
|
198
|
+
string = plist_buddy.plist_read("CFBundleVersion", info_plist_path)
|
199
199
|
begin
|
200
200
|
version = RunLoop::Version.new(string)
|
201
201
|
rescue
|
202
202
|
if string && string != ""
|
203
|
-
RunLoop.log_debug("
|
203
|
+
RunLoop.log_debug("CFBundleVersion: '#{string}' is not a well formed version string")
|
204
204
|
else
|
205
|
-
RunLoop.log_debug("
|
205
|
+
RunLoop.log_debug("CFBundleVersion is not defined in Info.plist")
|
206
206
|
end
|
207
207
|
version = nil
|
208
208
|
end
|
@@ -218,7 +218,7 @@ Bundle must:
|
|
218
218
|
executables = []
|
219
219
|
Dir.glob("#{path}/**/*") do |file|
|
220
220
|
next if skip_executable_check?(file)
|
221
|
-
if otool(file)
|
221
|
+
if otool.executable?(file)
|
222
222
|
executables << file
|
223
223
|
end
|
224
224
|
end
|
@@ -262,9 +262,13 @@ Bundle must:
|
|
262
262
|
end
|
263
263
|
|
264
264
|
# @!visibility private
|
265
|
-
|
266
|
-
|
267
|
-
|
265
|
+
def otool
|
266
|
+
@otool ||= RunLoop::Otool.new(xcode)
|
267
|
+
end
|
268
|
+
|
269
|
+
# @!visibility private
|
270
|
+
def xcode
|
271
|
+
@xcode ||= RunLoop::Xcode.new
|
268
272
|
end
|
269
273
|
|
270
274
|
# @!visibility private
|
data/lib/run_loop/cli/cli.rb
CHANGED
@@ -30,8 +30,8 @@ module RunLoop
|
|
30
30
|
desc 'instruments', "Interact with Xcode's command-line instruments"
|
31
31
|
subcommand 'instruments', RunLoop::CLI::Instruments
|
32
32
|
|
33
|
-
desc
|
34
|
-
subcommand
|
33
|
+
desc "simctl", "Interact with Xcode's command-line simctl"
|
34
|
+
subcommand "simctl", RunLoop::CLI::Simctl
|
35
35
|
|
36
36
|
desc "locale", "Tools for interacting with locales"
|
37
37
|
subcommand "locale", RunLoop::CLI::Locale
|
data/lib/run_loop/cli/simctl.rb
CHANGED
@@ -103,11 +103,6 @@ module RunLoop
|
|
103
103
|
|
104
104
|
begin
|
105
105
|
RunLoop::CoreSimulator.terminate_core_simulator_processes
|
106
|
-
process_name = "com.apple.CoreSimulator.CoreSimulatorService"
|
107
|
-
RunLoop::ProcessWaiter.new(process_name).pids.each do |pid|
|
108
|
-
kill_options = { :timeout => 0.5 }
|
109
|
-
RunLoop::ProcessTerminator.new(pid, 'KILL', process_name, kill_options)
|
110
|
-
end
|
111
106
|
ensure
|
112
107
|
ENV['DEBUG'] = original_value if debug
|
113
108
|
end
|
data/lib/run_loop/core.rb
CHANGED
@@ -65,7 +65,8 @@ module RunLoop
|
|
65
65
|
xcode = options[:xcode] || RunLoop::Xcode.new
|
66
66
|
instruments = options[:instruments] || RunLoop::Instruments.new
|
67
67
|
|
68
|
-
|
68
|
+
# Guard against Xcode version check on the XTC.
|
69
|
+
if !RunLoop::Environment.xtc? && xcode.version_gte_8?
|
69
70
|
raise %Q[
|
70
71
|
UIAutomation is not available on Xcode >= 8.*.
|
71
72
|
|
@@ -22,7 +22,8 @@ class RunLoop::CoreSimulator
|
|
22
22
|
:install_app_timeout => RunLoop::Environment.ci? ? 120 : 30,
|
23
23
|
:uninstall_app_timeout => RunLoop::Environment.ci? ? 120 : 30,
|
24
24
|
:launch_app_timeout => RunLoop::Environment.ci? ? 120 : 30,
|
25
|
-
:wait_for_state_timeout => RunLoop::Environment.ci? ? 120 : 30
|
25
|
+
:wait_for_state_timeout => RunLoop::Environment.ci? ? 120 : 30,
|
26
|
+
:app_launch_retries => RunLoop::Environment.ci? ? 5 : 3
|
26
27
|
}
|
27
28
|
|
28
29
|
# @!visibility private
|
@@ -178,9 +179,8 @@ class RunLoop::CoreSimulator
|
|
178
179
|
#
|
179
180
|
# @param [RunLoop::Device] simulator The simulator to erase
|
180
181
|
# @param [Hash] options Control the behavior of the method.
|
181
|
-
# @option options [Numeric] :timeout
|
182
|
-
# shutdown
|
183
|
-
# each command.
|
182
|
+
# @option options [Numeric] :timeout How long to wait for simctl to
|
183
|
+
# shutdown the simulator. This is necessary for the erase to succeed.
|
184
184
|
#
|
185
185
|
# @raise RuntimeError If the simulator cannot be shutdown
|
186
186
|
# @raise RuntimeError If the simulator cannot be erased
|
@@ -191,61 +191,13 @@ class RunLoop::CoreSimulator
|
|
191
191
|
"#{simulator} is a physical device. This method is only for Simulators"
|
192
192
|
end
|
193
193
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
merged_options = default_options.merge(options)
|
199
|
-
|
200
|
-
self.quit_simulator
|
201
|
-
|
202
|
-
xcrun = merged_options[:xcrun] || RunLoop::Xcrun.new
|
203
|
-
timeout = merged_options[:timeout]
|
204
|
-
xcrun_opts = {
|
205
|
-
:log_cmd => true,
|
206
|
-
:timeout => timeout
|
207
|
-
}
|
208
|
-
|
209
|
-
if simulator.update_simulator_state != "Shutdown"
|
210
|
-
args = ["simctl", "shutdown", simulator.udid]
|
211
|
-
xcrun.run_command_in_context(args, xcrun_opts)
|
212
|
-
begin
|
213
|
-
self.wait_for_simulator_state(simulator, "Shutdown")
|
214
|
-
rescue RuntimeError => _
|
215
|
-
raise RuntimeError, %Q{
|
216
|
-
Could not erase simulator because it could not be Shutdown.
|
194
|
+
merged_options = DEFAULT_OPTIONS.merge(options)
|
195
|
+
simctl = merged_options[:simctl] || RunLoop::Simctl.new
|
196
|
+
timeout = merged_options[:timeout] || merged_options[:wait_for_state_timeout]
|
217
197
|
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
$ bundle exec run-loop simctl manage-processes
|
223
|
-
|
224
|
-
}
|
225
|
-
|
226
|
-
end
|
227
|
-
end
|
228
|
-
|
229
|
-
args = ["simctl", "erase", simulator.udid]
|
230
|
-
hash = xcrun.run_command_in_context(args, xcrun_opts)
|
231
|
-
|
232
|
-
if hash[:exit_status] != 0
|
233
|
-
raise RuntimeError, %Q{
|
234
|
-
Could not erase simulator because simctl returned this error:
|
235
|
-
|
236
|
-
#{hash[:out]}
|
237
|
-
|
238
|
-
This usually means your CoreSimulator processes need to be restarted.
|
239
|
-
|
240
|
-
You can restart the CoreSimulator processes with this command:
|
241
|
-
|
242
|
-
$ bundle exec run-loop simctl manage-processes
|
243
|
-
|
244
|
-
}
|
245
|
-
|
246
|
-
end
|
247
|
-
|
248
|
-
hash
|
198
|
+
simctl.erase(simulator,
|
199
|
+
timeout,
|
200
|
+
WAIT_FOR_SIMULATOR_STATE_INTERVAL)
|
249
201
|
end
|
250
202
|
|
251
203
|
# @!visibility private
|
@@ -351,6 +303,11 @@ $ bundle exec run-loop simctl manage-processes
|
|
351
303
|
@xcrun ||= RunLoop::Xcrun.new
|
352
304
|
end
|
353
305
|
|
306
|
+
# @!visibility private
|
307
|
+
def simctl
|
308
|
+
@simctl ||= RunLoop::Simctl.new
|
309
|
+
end
|
310
|
+
|
354
311
|
# Launch the simulator indicated by device.
|
355
312
|
def launch_simulator
|
356
313
|
|
@@ -404,29 +361,19 @@ $ bundle exec run-loop simctl manage-processes
|
|
404
361
|
# relaunch it.
|
405
362
|
launch_simulator
|
406
363
|
|
407
|
-
tries =
|
408
|
-
last_error = nil
|
364
|
+
tries = app_launch_retries
|
409
365
|
|
410
366
|
RunLoop.log_debug("Trying #{tries} times to launch #{app.bundle_identifier} on #{device}")
|
411
367
|
|
412
|
-
|
413
|
-
# Terminates CoreSimulatorService on failures.
|
414
|
-
hash = attempt_to_launch_app_with_simctl
|
415
|
-
|
416
|
-
exit_status = hash[:exit_status]
|
417
|
-
if exit_status != 0
|
418
|
-
# Last argument is how long to sleep after an error.
|
419
|
-
last_error = handle_failed_app_launch(hash, try, tries, 0.5)
|
420
|
-
else
|
421
|
-
last_error = nil
|
422
|
-
break
|
423
|
-
end
|
424
|
-
end
|
368
|
+
last_error = try_to_launch_app_n_times(tries)
|
425
369
|
|
426
370
|
if last_error
|
427
|
-
raise RuntimeError, %Q[
|
371
|
+
raise RuntimeError, %Q[
|
372
|
+
Could not launch #{app.bundle_identifier} on #{device} after trying #{tries} times:
|
428
373
|
|
429
|
-
#{last_error}
|
374
|
+
#{last_error}:
|
375
|
+
|
376
|
+
#{last_error.message}
|
430
377
|
|
431
378
|
]
|
432
379
|
end
|
@@ -487,10 +434,8 @@ $ bundle exec run-loop simctl manage-processes
|
|
487
434
|
|
488
435
|
launch_simulator
|
489
436
|
|
490
|
-
args = ['simctl', 'uninstall', device.udid, app.bundle_identifier]
|
491
|
-
|
492
437
|
timeout = DEFAULT_OPTIONS[:uninstall_app_timeout]
|
493
|
-
|
438
|
+
simctl.uninstall(device, app, timeout)
|
494
439
|
|
495
440
|
device.simulator_wait_for_stable_state
|
496
441
|
true
|
@@ -610,9 +555,8 @@ Command had no output
|
|
610
555
|
def install_app_with_simctl
|
611
556
|
launch_simulator
|
612
557
|
|
613
|
-
args = ['simctl', 'install', device.udid, app.path]
|
614
558
|
timeout = DEFAULT_OPTIONS[:install_app_timeout]
|
615
|
-
|
559
|
+
simctl.install(device, app, timeout)
|
616
560
|
|
617
561
|
device.simulator_wait_for_stable_state
|
618
562
|
installed_app_bundle_dir
|
@@ -620,42 +564,48 @@ Command had no output
|
|
620
564
|
|
621
565
|
# @!visibility private
|
622
566
|
def launch_app_with_simctl
|
623
|
-
args = ['simctl', 'launch', device.udid, app.bundle_identifier]
|
624
567
|
timeout = DEFAULT_OPTIONS[:launch_app_timeout]
|
625
|
-
|
568
|
+
simctl.launch(device, app, timeout)
|
626
569
|
end
|
627
570
|
|
628
571
|
# @!visibility private
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
572
|
+
#
|
573
|
+
# Returns nil if launch_app_with_simctl succeeds and the error if it fails.
|
574
|
+
def try_to_launch_app
|
575
|
+
begin
|
576
|
+
launch_app_with_simctl
|
577
|
+
nil
|
578
|
+
rescue RuntimeError, RunLoop::Xcrun::TimeoutError => error
|
579
|
+
# Simulator is probably in a bad state. Restart the service.
|
580
|
+
RunLoop::CoreSimulator.terminate_core_simulator_processes
|
581
|
+
Kernel.sleep(0.5)
|
582
|
+
launch_simulator
|
583
|
+
error
|
634
584
|
end
|
635
|
-
|
636
|
-
# (see above). If at all possible, we want to avoid terminating
|
637
|
-
# CoreSimulatorService, because it takes a long time to launch.
|
638
|
-
sleep(wait_time) if wait_time > 0
|
585
|
+
end
|
639
586
|
|
640
|
-
|
587
|
+
# @!visibility private
|
588
|
+
def app_launch_retries
|
589
|
+
DEFAULT_OPTIONS[:app_launch_retries]
|
641
590
|
end
|
642
591
|
|
643
592
|
# @!visibility private
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
#
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
593
|
+
#
|
594
|
+
# Returns nil if launch_app_with_simctl succeeds and the error if it fails.
|
595
|
+
def try_to_launch_app_n_times(tries)
|
596
|
+
last_error = nil
|
597
|
+
|
598
|
+
tries.times do |try|
|
599
|
+
# Terminates CoreSimulatorService on failures and launches the simulator again.
|
600
|
+
# Returns nil if app launched.
|
601
|
+
# Returns rescued Runtime or Timeout errors.
|
602
|
+
last_error = try_to_launch_app
|
603
|
+
|
604
|
+
break if last_error.nil?
|
605
|
+
RunLoop.log_debug("Failed to launch app on try #{try + 1} of #{tries}.")
|
657
606
|
end
|
658
|
-
|
607
|
+
|
608
|
+
last_error
|
659
609
|
end
|
660
610
|
|
661
611
|
# Required for support of iOS 7 CoreSimulators. Can be removed when
|
data/lib/run_loop/device.rb
CHANGED
@@ -4,6 +4,9 @@ module RunLoop
|
|
4
4
|
require 'securerandom'
|
5
5
|
include RunLoop::Regex
|
6
6
|
|
7
|
+
require "run_loop/shell"
|
8
|
+
include RunLoop::Shell
|
9
|
+
|
7
10
|
# Starting in Xcode 7, iOS 9 simulators have a new "booting" state.
|
8
11
|
#
|
9
12
|
# The simulator must completely boot before run-loop tries to do things
|
@@ -39,7 +42,6 @@ module RunLoop
|
|
39
42
|
attr_reader :simulator_accessibility_plist_path
|
40
43
|
attr_reader :simulator_preferences_plist_path
|
41
44
|
attr_reader :simulator_log_file_path
|
42
|
-
attr_reader :pbuddy
|
43
45
|
|
44
46
|
# Create a new device.
|
45
47
|
#
|
@@ -268,7 +270,7 @@ version: #{version}
|
|
268
270
|
raise RuntimeError, 'This method is available only for simulators'
|
269
271
|
end
|
270
272
|
|
271
|
-
@state =
|
273
|
+
@state = simctl.simulator_state_as_string(self)
|
272
274
|
end
|
273
275
|
|
274
276
|
# @!visibility private
|
@@ -498,20 +500,35 @@ version: #{version}
|
|
498
500
|
global_plist = simulator_global_preferences_path
|
499
501
|
|
500
502
|
cmd = [
|
501
|
-
"PlistBuddy",
|
503
|
+
"/usr/libexec/PlistBuddy",
|
502
504
|
"-c",
|
503
505
|
"Add :AppleLanguages:0 string '#{lang_code}'",
|
504
506
|
global_plist
|
505
507
|
]
|
506
508
|
|
507
509
|
# RunLoop::PlistBuddy cannot add items to arrays.
|
508
|
-
|
510
|
+
hash = run_shell_command(cmd, {:log_cmd => true})
|
511
|
+
|
512
|
+
if hash[:exit_status] != 0
|
513
|
+
raise RuntimeError, %Q[
|
514
|
+
Could not update the Simulator languages because this command:
|
515
|
+
|
516
|
+
#{cmd.join(" ")}
|
517
|
+
|
518
|
+
failed with this output:
|
519
|
+
|
520
|
+
#{hash[:out]}
|
521
|
+
|
522
|
+
]
|
523
|
+
end
|
509
524
|
|
510
525
|
simulator_languages
|
511
526
|
end
|
512
527
|
|
513
528
|
private
|
514
529
|
|
530
|
+
attr_reader :pbuddy, :simctl, :xcrun
|
531
|
+
|
515
532
|
# @!visibility private
|
516
533
|
def xcrun
|
517
534
|
RunLoop::Xcrun.new
|
@@ -523,43 +540,8 @@ version: #{version}
|
|
523
540
|
end
|
524
541
|
|
525
542
|
# @!visibility private
|
526
|
-
def
|
527
|
-
|
528
|
-
if line[/unavailable/, 0]
|
529
|
-
RunLoop.log_debug("Simulator state is unavailable: #{line}")
|
530
|
-
return 'Unavailable'
|
531
|
-
end
|
532
|
-
|
533
|
-
state = line[/(Booted|Shutdown|Shutting Down)/,0]
|
534
|
-
|
535
|
-
if state.nil?
|
536
|
-
RunLoop.log_debug("Simulator state is unknown: #{line}")
|
537
|
-
'Unknown'
|
538
|
-
else
|
539
|
-
state
|
540
|
-
end
|
541
|
-
end
|
542
|
-
|
543
|
-
# @!visibility private
|
544
|
-
def fetch_simulator_state
|
545
|
-
if physical_device?
|
546
|
-
raise RuntimeError, 'This method is available only for simulators'
|
547
|
-
end
|
548
|
-
|
549
|
-
args = ['simctl', 'list', 'devices']
|
550
|
-
hash = xcrun.run_command_in_context(args)
|
551
|
-
out = hash[:out]
|
552
|
-
|
553
|
-
matched_line = out.split("\n").find do |line|
|
554
|
-
line.include?(udid)
|
555
|
-
end
|
556
|
-
|
557
|
-
if matched_line.nil?
|
558
|
-
raise RuntimeError,
|
559
|
-
"Expected a simulator with udid '#{udid}', but found none"
|
560
|
-
end
|
561
|
-
|
562
|
-
detect_state_from_line(matched_line)
|
543
|
+
def simctl
|
544
|
+
@simctl ||= RunLoop::Simctl.new
|
563
545
|
end
|
564
546
|
|
565
547
|
# @!visibility private
|