run_loop 2.1.6 → 2.1.7
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.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
|