run_loop 1.3.3 → 1.4.0
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/app.rb +1 -1
- data/lib/run_loop/cache/cache.rb +68 -0
- data/lib/run_loop/cli/simctl.rb +31 -0
- data/lib/run_loop/core.rb +11 -4
- data/lib/run_loop/device.rb +3 -4
- data/lib/run_loop/environment.rb +0 -6
- data/lib/run_loop/host_cache.rb +11 -5
- data/lib/run_loop/ipa.rb +112 -0
- data/lib/run_loop/sim_control.rb +30 -27
- data/lib/run_loop/simctl/bridge.rb +29 -23
- data/lib/run_loop/version.rb +1 -1
- data/lib/run_loop/xctools.rb +15 -0
- data/lib/run_loop.rb +2 -0
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cea6224dea61d80b7d0462a2e902a68b31941b38
|
4
|
+
data.tar.gz: 9d30691d96a4040031389cc8ec13839945274122
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 23d44bd5653d1bcf93cfbc298f9b97177269f296a309c042abd5150356ffb997ba6a53dd83de7203b9623a2bf0155bc50619096adf4606d94291e3c6c2007418
|
7
|
+
data.tar.gz: 0f1c02ae73981bb9dcd0799181152f234673aeb172909ecac90ae14ff263efa6fc5171c4c7ae21295fbd21173642e193dbaf4a73bd3d695ed813fdf9bb575f58
|
data/lib/run_loop/app.rb
CHANGED
@@ -46,7 +46,7 @@ module RunLoop
|
|
46
46
|
end
|
47
47
|
|
48
48
|
# Inspects the app's Info.plist for the executable name.
|
49
|
-
# @return [String] The value of
|
49
|
+
# @return [String] The value of CFBundleExecutable.
|
50
50
|
# @raise [RuntimeError] If the plist cannot be read or the
|
51
51
|
# CFBundleExecutable is empty or does not exist.
|
52
52
|
def executable_name
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module RunLoop
|
2
|
+
|
3
|
+
# @!visibility private
|
4
|
+
# A class for managing an on-disk cache.
|
5
|
+
class Cache
|
6
|
+
|
7
|
+
require 'fileutils'
|
8
|
+
|
9
|
+
def initialize(path)
|
10
|
+
@path = path
|
11
|
+
end
|
12
|
+
|
13
|
+
def clear
|
14
|
+
raise NotImplementedError, 'Subclasses must implement #clear'
|
15
|
+
end
|
16
|
+
|
17
|
+
def refresh
|
18
|
+
raise NotImplementedError, 'Subclasses must implement #refresh'
|
19
|
+
end
|
20
|
+
|
21
|
+
# Reads the current cache.
|
22
|
+
# @return [Hash] A hash representation of the cache on disk.
|
23
|
+
def read
|
24
|
+
if File.exist? path
|
25
|
+
File.open(path) do |file|
|
26
|
+
Marshal.load(file)
|
27
|
+
end
|
28
|
+
else
|
29
|
+
write({})
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
attr_reader :path
|
36
|
+
|
37
|
+
# @!visibility private
|
38
|
+
#
|
39
|
+
# Writes `hash` as a serial object. The existing data is overwritten.
|
40
|
+
#
|
41
|
+
# @param [Hash] hash The hash to write.
|
42
|
+
# @raise [ArgumentError] The `hash` parameter must not be nil and it must
|
43
|
+
# be a Hash.
|
44
|
+
# @raise [TypeError] If the hash contains objects that cannot be written
|
45
|
+
# by Marshal.dump.
|
46
|
+
#
|
47
|
+
# @return [Hash] Returns the `hash` argument.
|
48
|
+
def write(hash)
|
49
|
+
if hash.nil?
|
50
|
+
raise ArgumentError, 'Expected the hash parameter to be non-nil'
|
51
|
+
end
|
52
|
+
|
53
|
+
unless hash.is_a?(Hash)
|
54
|
+
raise ArgumentError, "Expected #{hash} to a Hash, but it is a #{hash.class}"
|
55
|
+
end
|
56
|
+
|
57
|
+
directory = File.dirname(path)
|
58
|
+
unless File.exist?(directory)
|
59
|
+
FileUtils.mkdir_p(directory)
|
60
|
+
end
|
61
|
+
|
62
|
+
File.open(path, 'w') do |file|
|
63
|
+
Marshal.dump(hash, file)
|
64
|
+
end
|
65
|
+
hash
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/lib/run_loop/cli/simctl.rb
CHANGED
@@ -31,6 +31,37 @@ module RunLoop
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
+
desc 'refresh', 'EXPERIMENTAL: Terminate CoreSimulatorService daemons'
|
35
|
+
|
36
|
+
method_option 'debug',
|
37
|
+
:desc => 'Enable debug logging.',
|
38
|
+
:aliases => '-v',
|
39
|
+
:required => false,
|
40
|
+
:default => false,
|
41
|
+
:type => :boolean
|
42
|
+
|
43
|
+
def refresh
|
44
|
+
debug = options[:debug]
|
45
|
+
original_value = ENV['DEBUG']
|
46
|
+
|
47
|
+
ENV['DEBUG'] = '1' if debug
|
48
|
+
|
49
|
+
RunLoop::SimControl.terminate_all_sims
|
50
|
+
|
51
|
+
begin
|
52
|
+
process_name = 'com.apple.CoreSimulator.CoreSimulatorService'
|
53
|
+
pids = RunLoop::ProcessWaiter.new(process_name, {:timeout => 0.2}).pids
|
54
|
+
if debug && pids.empty?
|
55
|
+
puts 'There are no CoreSimulatorServices processes running'
|
56
|
+
end
|
57
|
+
pids.each do |pid|
|
58
|
+
RunLoop::ProcessTerminator.new(pid, 'KILL', process_name).kill_process
|
59
|
+
end
|
60
|
+
ensure
|
61
|
+
ENV['DEBUG'] = original_value if debug
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
34
65
|
no_commands do
|
35
66
|
def sim_control
|
36
67
|
@sim_control ||= RunLoop::SimControl.new
|
data/lib/run_loop/core.rb
CHANGED
@@ -391,7 +391,9 @@ module RunLoop
|
|
391
391
|
# @param [RunLoop::XCTools] xcode_tools Used to detect the current xcode
|
392
392
|
# version.
|
393
393
|
def self.default_simulator(xcode_tools=RunLoop::XCTools.new)
|
394
|
-
if xcode_tools.
|
394
|
+
if xcode_tools.xcode_version_gte_7?
|
395
|
+
'iPhone 5s (9.0 Simulator)'
|
396
|
+
elsif xcode_tools.xcode_version_gte_64?
|
395
397
|
'iPhone 5s (8.4 Simulator)'
|
396
398
|
elsif xcode_tools.xcode_version_gte_63?
|
397
399
|
'iPhone 5s (8.3 Simulator)'
|
@@ -637,13 +639,18 @@ module RunLoop
|
|
637
639
|
#
|
638
640
|
# Xcode 6 Beta versions also return paths, but revert to 'normal'
|
639
641
|
# behavior when GM is released.
|
642
|
+
#
|
643
|
+
# Xcode 7 Beta versions appear to behavior like Xcode 6 Beta versions.
|
640
644
|
res = templates.select { |name| name == 'Automation' }.first
|
641
645
|
return res if res
|
642
646
|
|
643
|
-
|
647
|
+
candidate = templates.select do |path|
|
644
648
|
path =~ /\/Automation.tracetemplate/ and path =~ /Xcode/
|
645
|
-
end
|
646
|
-
|
649
|
+
end
|
650
|
+
|
651
|
+
if !candidate.empty? && !candidate.first.nil?
|
652
|
+
return candidate.first.tr("\"", '').strip
|
653
|
+
end
|
647
654
|
|
648
655
|
msgs = ['Expected instruments to report an Automation tracetemplate.',
|
649
656
|
'Please report this as bug: https://github.com/calabash/run_loop/issues',
|
data/lib/run_loop/device.rb
CHANGED
@@ -64,7 +64,6 @@ module RunLoop
|
|
64
64
|
return simulator if !simulator.nil?
|
65
65
|
|
66
66
|
physical_device = sim_control.xctools.instruments(:devices).detect do |device|
|
67
|
-
puts device
|
68
67
|
device.name == udid_or_name ||
|
69
68
|
device.udid == udid_or_name
|
70
69
|
end
|
@@ -76,9 +75,9 @@ module RunLoop
|
|
76
75
|
|
77
76
|
def to_s
|
78
77
|
if simulator?
|
79
|
-
"Simulator: #{instruments_identifier} #{udid} #{instruction_set}"
|
78
|
+
"#<Simulator: #{instruments_identifier} #{udid} #{instruction_set}>"
|
80
79
|
else
|
81
|
-
"Device: #{name} #{udid}"
|
80
|
+
"#<Device: #{name} #{udid}>"
|
82
81
|
end
|
83
82
|
end
|
84
83
|
|
@@ -93,7 +92,7 @@ module RunLoop
|
|
93
92
|
self.udid
|
94
93
|
else
|
95
94
|
unless xcode_tools.xcode_version_gte_6?
|
96
|
-
raise "Expected Xcode >= 6, but found version #{xcode_tools.
|
95
|
+
raise "Expected Xcode >= 6, but found version #{xcode_tools.xcode_version} - cannot create an identifier"
|
97
96
|
end
|
98
97
|
if self.version == RunLoop::Version.new('7.0.3')
|
99
98
|
version_part = self.version.to_s
|
data/lib/run_loop/environment.rb
CHANGED
data/lib/run_loop/host_cache.rb
CHANGED
@@ -22,9 +22,15 @@ module RunLoop
|
|
22
22
|
|
23
23
|
# The directory where the cache is stored.
|
24
24
|
# @return [String] Expanded path to the default cache directory.
|
25
|
+
# @raise [RuntimeError] When the ~/.run_loop exists, but is not a directory.
|
25
26
|
def self.default_directory
|
26
|
-
|
27
|
-
File.
|
27
|
+
run_loop_dir = File.expand_path('~/.run-loop')
|
28
|
+
if !File.exist?(run_loop_dir)
|
29
|
+
FileUtils.mkdir(run_loop_dir)
|
30
|
+
elsif !File.directory?(run_loop_dir)
|
31
|
+
raise "Expected '#{run_loop_dir}' to be a directory.\nRunLoop requires this directory to cache files."
|
32
|
+
end
|
33
|
+
run_loop_dir
|
28
34
|
end
|
29
35
|
|
30
36
|
# The default cache.
|
@@ -61,8 +67,8 @@ module RunLoop
|
|
61
67
|
# Reads the current cache.
|
62
68
|
# @return [Hash] A hash representation of the current state of the run-loop.
|
63
69
|
def read
|
64
|
-
if File.exist?
|
65
|
-
File.open(
|
70
|
+
if File.exist? path
|
71
|
+
File.open(path) do |file|
|
66
72
|
Marshal.load(file)
|
67
73
|
end
|
68
74
|
else
|
@@ -91,7 +97,7 @@ module RunLoop
|
|
91
97
|
raise ArgumentError, "Expected #{hash} to a Hash, but it is a #{hash.class}"
|
92
98
|
end
|
93
99
|
|
94
|
-
File.open(
|
100
|
+
File.open(path, 'w+') do |file|
|
95
101
|
Marshal.dump(hash, file)
|
96
102
|
end
|
97
103
|
true
|
data/lib/run_loop/ipa.rb
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
module RunLoop
|
2
|
+
# A model of the an .ipa - a application binary for iOS devices.
|
3
|
+
class Ipa
|
4
|
+
|
5
|
+
|
6
|
+
# The path to this .ipa.
|
7
|
+
# @!attribute [r] path
|
8
|
+
# @return [String] A path to this .ipa.
|
9
|
+
attr_reader :path
|
10
|
+
|
11
|
+
# The bundle identifier of this ipa.
|
12
|
+
# @!attribute [r] bundle_identifier
|
13
|
+
# @return [String] The bundle identifier of this ipa; obtained by inspecting
|
14
|
+
# the app's Info.plist.
|
15
|
+
attr_reader :bundle_identifier
|
16
|
+
|
17
|
+
# Create a new ipa instance.
|
18
|
+
# @param [String] path_to_ipa The path the .ipa file.
|
19
|
+
# @return [Calabash::Ipa] A new ipa instance.
|
20
|
+
# @raise [RuntimeError] If the file does not exist.
|
21
|
+
# @raise [RuntimeError] If the file does not end in .ipa.
|
22
|
+
def initialize(path_to_ipa)
|
23
|
+
unless File.exist? path_to_ipa
|
24
|
+
raise "Expected an ipa at '#{path_to_ipa}'"
|
25
|
+
end
|
26
|
+
|
27
|
+
unless path_to_ipa.end_with?('.ipa')
|
28
|
+
raise "Expected '#{path_to_ipa}' to be an .ipa"
|
29
|
+
end
|
30
|
+
@path = path_to_ipa
|
31
|
+
end
|
32
|
+
|
33
|
+
# @!visibility private
|
34
|
+
def to_s
|
35
|
+
"#<IPA: #{bundle_identifier}: '#{path}'>"
|
36
|
+
end
|
37
|
+
|
38
|
+
# The bundle identifier of this ipa.
|
39
|
+
# @return [String] A string representation of this ipa's CFBundleIdentifier
|
40
|
+
# @raise [RuntimeError] If ipa does not expand into a Payload/<app name>.app
|
41
|
+
# directory.
|
42
|
+
# @raise [RuntimeError] If an Info.plist does exist in the .app.
|
43
|
+
def bundle_identifier
|
44
|
+
if bundle_dir.nil? || !File.exist?(bundle_dir)
|
45
|
+
raise "Expected a '#{File.basename(path).split('.').first}.app'\nat path '#{payload_dir}'"
|
46
|
+
end
|
47
|
+
|
48
|
+
@bundle_identifier ||= lambda {
|
49
|
+
info_plist_path = File.join(bundle_dir, 'Info.plist')
|
50
|
+
unless File.exist? info_plist_path
|
51
|
+
raise "Expected an 'Info.plist' at '#{bundle_dir}'"
|
52
|
+
end
|
53
|
+
identifier = plist_buddy.plist_read('CFBundleIdentifier', info_plist_path)
|
54
|
+
|
55
|
+
unless identifier
|
56
|
+
raise "Expected key 'CFBundleIdentifier' in '#{info_plist_path}'"
|
57
|
+
end
|
58
|
+
identifier
|
59
|
+
}.call
|
60
|
+
end
|
61
|
+
|
62
|
+
# Inspects the app's Info.plist for the executable name.
|
63
|
+
# @return [String] The value of CFBundleExecutable.
|
64
|
+
# @raise [RuntimeError] If the plist cannot be read or the
|
65
|
+
# CFBundleExecutable is empty or does not exist.
|
66
|
+
def executable_name
|
67
|
+
if bundle_dir.nil? || !File.exist?(bundle_dir)
|
68
|
+
raise "Expected a '#{File.basename(path).split('.').first}.app'\nat path '#{payload_dir}'"
|
69
|
+
end
|
70
|
+
|
71
|
+
@executable_name ||= lambda {
|
72
|
+
info_plist_path = File.join(bundle_dir, 'Info.plist')
|
73
|
+
unless File.exist? info_plist_path
|
74
|
+
raise "Expected an 'Info.plist' at '#{bundle_dir}'"
|
75
|
+
end
|
76
|
+
name = plist_buddy.plist_read('CFBundleExecutable', info_plist_path)
|
77
|
+
|
78
|
+
unless name
|
79
|
+
raise "Expected key 'CFBundleExecutable' in '#{info_plist_path}'"
|
80
|
+
end
|
81
|
+
name
|
82
|
+
}.call
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
def tmpdir
|
88
|
+
@tmpdir ||= Dir.mktmpdir
|
89
|
+
end
|
90
|
+
|
91
|
+
def payload_dir
|
92
|
+
@payload_dir ||= lambda {
|
93
|
+
FileUtils.cp(path, tmpdir)
|
94
|
+
zip_path = File.join(tmpdir, File.basename(path))
|
95
|
+
Dir.chdir(tmpdir) do
|
96
|
+
system('unzip', *['-q', zip_path])
|
97
|
+
end
|
98
|
+
File.join(tmpdir, 'Payload')
|
99
|
+
}.call
|
100
|
+
end
|
101
|
+
|
102
|
+
def bundle_dir
|
103
|
+
@bundle_dir ||= lambda {
|
104
|
+
Dir.glob(File.join(payload_dir, '*')).detect {|f| File.directory?(f) && f.end_with?('.app')}
|
105
|
+
}.call
|
106
|
+
end
|
107
|
+
|
108
|
+
def plist_buddy
|
109
|
+
@plist_buddy ||= RunLoop::PlistBuddy.new
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
data/lib/run_loop/sim_control.rb
CHANGED
@@ -20,6 +20,16 @@ module RunLoop
|
|
20
20
|
@xctools ||= RunLoop::XCTools.new
|
21
21
|
end
|
22
22
|
|
23
|
+
# @!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
|
29
|
+
def xcode_version_gte_7?
|
30
|
+
xctools.xcode_version_gte_7?
|
31
|
+
end
|
32
|
+
|
23
33
|
# @!visibility private
|
24
34
|
# Are we running Xcode 6 or above?
|
25
35
|
#
|
@@ -69,26 +79,19 @@ module RunLoop
|
|
69
79
|
end
|
70
80
|
|
71
81
|
# If it is not already running, launch the simulator for the current version
|
72
|
-
# of Xcode.
|
82
|
+
# of Xcode. Launches the simulator in the background so it does not
|
83
|
+
# steal focus.
|
73
84
|
#
|
74
85
|
# @param [Hash] opts Optional controls.
|
75
86
|
# @option opts [Float] :post_launch_wait (2.0) How long to sleep after the
|
76
87
|
# simulator has launched.
|
77
|
-
# @option opts [Boolean] :hide_after (false) If true, will attempt to Hide
|
78
|
-
# the simulator after it is launched. This is useful `only when testing
|
79
|
-
# gem features` that require the simulator be launched repeated and you are
|
80
|
-
# tired of your editor losing focus. :)
|
81
88
|
#
|
82
89
|
# @todo Consider migrating apple script call to xctools.
|
83
90
|
def launch_sim(opts={})
|
84
91
|
unless sim_is_running?
|
85
|
-
default_opts = {:post_launch_wait => RunLoop::Environment.sim_post_launch_wait || 2.0
|
86
|
-
:hide_after => false}
|
92
|
+
default_opts = {:post_launch_wait => RunLoop::Environment.sim_post_launch_wait || 2.0}
|
87
93
|
merged_opts = default_opts.merge(opts)
|
88
|
-
`xcrun open -a "#{sim_app_path}"`
|
89
|
-
if merged_opts[:hide_after]
|
90
|
-
`xcrun /usr/bin/osascript -e 'tell application "System Events" to keystroke "h" using command down'`
|
91
|
-
end
|
94
|
+
`xcrun open -g -a "#{sim_app_path}"`
|
92
95
|
sleep(merged_opts[:post_launch_wait]) if merged_opts[:post_launch_wait]
|
93
96
|
end
|
94
97
|
end
|
@@ -101,14 +104,9 @@ module RunLoop
|
|
101
104
|
# simulator has quit.
|
102
105
|
# @option opts [Float] :post_launch_wait (2.0) How long to sleep after the
|
103
106
|
# simulator has launched.
|
104
|
-
# @option opts [Boolean] :hide_after (false) If true, will attempt to Hide
|
105
|
-
# the simulator after it is launched. This is useful `only when testing
|
106
|
-
# gem features` that require the simulator be launched repeated and you are
|
107
|
-
# tired of your editor losing focus. :)
|
108
107
|
def relaunch_sim(opts={})
|
109
108
|
default_opts = {:post_quit_wait => 1.0,
|
110
|
-
:post_launch_wait => RunLoop::Environment.sim_post_launch_wait || 2.0
|
111
|
-
:hide_after => false}
|
109
|
+
:post_launch_wait => RunLoop::Environment.sim_post_launch_wait || 2.0}
|
112
110
|
merged_opts = default_opts.merge(opts)
|
113
111
|
quit_sim(merged_opts)
|
114
112
|
launch_sim(merged_opts)
|
@@ -132,7 +130,13 @@ module RunLoop
|
|
132
130
|
# SimControl.new.quit_sim({:post_quit_wait => 0.5})
|
133
131
|
|
134
132
|
processes =
|
135
|
-
[
|
133
|
+
[
|
134
|
+
# Xcode < 5.1
|
135
|
+
'iPhone Simulator.app',
|
136
|
+
# 7.0 < Xcode <= 6.0
|
137
|
+
'iOS Simulator.app',
|
138
|
+
# Xcode >= 7.0
|
139
|
+
'Simulator.app',
|
136
140
|
|
137
141
|
# Multiple launchd_sim processes have been causing problems. This
|
138
142
|
# is a first pass at investigating what it would mean to kill the
|
@@ -190,17 +194,11 @@ module RunLoop
|
|
190
194
|
# simulator has launched. Waits longer than normal because we need the
|
191
195
|
# simulator directories to be repopulated. **NOTE:** This option is ignored
|
192
196
|
# in Xcode 6.
|
193
|
-
# @option opts [Boolean] :hide_after (false) If true, will attempt to Hide
|
194
|
-
# the simulator after it is launched. This is useful `only when testing
|
195
|
-
# gem features` that require the simulator be launched repeated and you are
|
196
|
-
# tired of your editor losing focus. :) **NOTE:** This option is ignored
|
197
|
-
# in Xcode 6.
|
198
197
|
# @option opts [String] :sim_udid (nil) The udid of the simulator to reset.
|
199
198
|
# **NOTE:** This option is ignored in Xcode < 6.
|
200
199
|
def reset_sim_content_and_settings(opts={})
|
201
200
|
default_opts = {:post_quit_wait => 1.0,
|
202
201
|
:post_launch_wait => RunLoop::Environment.sim_post_launch_wait || 3.0,
|
203
|
-
:hide_after => false,
|
204
202
|
:sim_udid => nil}
|
205
203
|
merged_opts = default_opts.merge(opts)
|
206
204
|
|
@@ -606,7 +604,8 @@ module RunLoop
|
|
606
604
|
#
|
607
605
|
# @return [String, nil] The pid as a String or nil if no process is found.
|
608
606
|
def sim_pid
|
609
|
-
|
607
|
+
process_name = "MacOS/#{sim_name}"
|
608
|
+
`xcrun ps x -o pid,command | grep "#{process_name}" | grep -v grep`.strip.split(' ').first
|
610
609
|
end
|
611
610
|
|
612
611
|
# @!visibility private
|
@@ -621,7 +620,9 @@ module RunLoop
|
|
621
620
|
# launching the current simulator.
|
622
621
|
def sim_name
|
623
622
|
@sim_name ||= lambda {
|
624
|
-
if
|
623
|
+
if xcode_version_gte_7?
|
624
|
+
'Simulator'
|
625
|
+
elsif xcode_version_gte_6?
|
625
626
|
'iOS Simulator'
|
626
627
|
else
|
627
628
|
'iPhone Simulator'
|
@@ -639,7 +640,9 @@ module RunLoop
|
|
639
640
|
def sim_app_path
|
640
641
|
@sim_app_path ||= lambda {
|
641
642
|
dev_dir = xctools.xcode_developer_dir
|
642
|
-
if
|
643
|
+
if xcode_version_gte_7?
|
644
|
+
"#{dev_dir}/Applications/Simulator.app"
|
645
|
+
elsif xcode_version_gte_6?
|
643
646
|
"#{dev_dir}/Applications/iOS Simulator.app"
|
644
647
|
else
|
645
648
|
"#{dev_dir}/Platforms/iPhoneSimulator.platform/Developer/Applications/iPhone Simulator.app"
|
@@ -27,10 +27,7 @@ module RunLoop::Simctl
|
|
27
27
|
@pbuddy = RunLoop::PlistBuddy.new
|
28
28
|
|
29
29
|
@sim_control = RunLoop::SimControl.new
|
30
|
-
@path_to_ios_sim_app_bundle =
|
31
|
-
dev_dir = @sim_control.xctools.xcode_developer_dir
|
32
|
-
"#{dev_dir}/Applications/iOS Simulator.app"
|
33
|
-
}.call
|
30
|
+
@path_to_ios_sim_app_bundle = @sim_control.send(:sim_app_path)
|
34
31
|
|
35
32
|
@app = RunLoop::App.new(app_bundle_path)
|
36
33
|
|
@@ -175,35 +172,43 @@ module RunLoop::Simctl
|
|
175
172
|
end
|
176
173
|
|
177
174
|
def terminate_core_simulator_processes
|
178
|
-
debug_logging = RunLoop::Environment.debug?
|
179
175
|
[
|
180
|
-
#
|
181
|
-
#'
|
182
|
-
|
176
|
+
# Pattern.
|
177
|
+
# [ '< process name >', < send term first > ]
|
178
|
+
|
179
|
+
# No. This process is a daemon, and requires 'KILL' to terminate.
|
180
|
+
# Killing the process is fast, but it takes a long time to restart.
|
181
|
+
# ['com.apple.CoreSimulator.CoreSimulatorService', false],
|
182
|
+
|
183
|
+
# Probably do not need to quit this, but it is tempting to do so.
|
184
|
+
#['com.apple.CoreSimulator.SimVerificationService', false],
|
183
185
|
|
184
186
|
# Started by Xamarin Studio, this is the parent process of the
|
185
187
|
# processes launched by Xamarin's interaction with
|
186
188
|
# CoreSimulatorBridge
|
187
|
-
'csproxy',
|
189
|
+
['csproxy', true],
|
188
190
|
|
189
191
|
# Yes.
|
190
|
-
'SimulatorBridge',
|
191
|
-
'configd_sim',
|
192
|
-
'launchd_sim',
|
192
|
+
['SimulatorBridge', true],
|
193
|
+
['configd_sim', true],
|
194
|
+
['launchd_sim', true],
|
193
195
|
|
194
196
|
# Yes, but does not always appear.
|
195
|
-
'CoreSimulatorBridge'
|
196
|
-
].each do |
|
197
|
+
['CoreSimulatorBridge', true]
|
198
|
+
].each do |pair|
|
199
|
+
name = pair[0]
|
200
|
+
send_term = pair[1]
|
197
201
|
pids = RunLoop::ProcessWaiter.new(name).pids
|
198
202
|
pids.each do |pid|
|
199
|
-
|
200
|
-
|
203
|
+
|
204
|
+
if send_term
|
205
|
+
term = RunLoop::ProcessTerminator.new(pid, 'TERM', name)
|
206
|
+
killed = term.kill_process
|
207
|
+
else
|
208
|
+
killed = false
|
201
209
|
end
|
202
|
-
|
203
|
-
unless
|
204
|
-
if debug_logging
|
205
|
-
puts "Sending 'KILL' to #{name} '#{pid}'"
|
206
|
-
end
|
210
|
+
|
211
|
+
unless killed
|
207
212
|
term = RunLoop::ProcessTerminator.new(pid, 'KILL', name)
|
208
213
|
term.kill_process
|
209
214
|
end
|
@@ -371,13 +376,14 @@ module RunLoop::Simctl
|
|
371
376
|
end
|
372
377
|
|
373
378
|
def launch_simulator
|
374
|
-
args = ['open', '-a', @path_to_ios_sim_app_bundle, '--args', '-CurrentDeviceUDID', device.udid]
|
379
|
+
args = ['open', '-g', '-a', @path_to_ios_sim_app_bundle, '--args', '-CurrentDeviceUDID', device.udid]
|
375
380
|
pid = spawn('xcrun', *args)
|
376
381
|
Process.detach(pid)
|
377
382
|
|
378
383
|
# @todo Does not always appear?
|
379
384
|
# RunLoop::ProcessWaiter.new('CoreSimulatorBridge', WAIT_FOR_APP_LAUNCH_OPTS).wait_for_any
|
380
|
-
|
385
|
+
sim_name = @sim_control.send(:sim_name)
|
386
|
+
RunLoop::ProcessWaiter.new(sim_name, WAIT_FOR_APP_LAUNCH_OPTS).wait_for_any
|
381
387
|
RunLoop::ProcessWaiter.new('SimulatorBridge', WAIT_FOR_APP_LAUNCH_OPTS).wait_for_any
|
382
388
|
wait_for_device_state 'Booted'
|
383
389
|
sleep(SIM_POST_LAUNCH_WAIT)
|
data/lib/run_loop/version.rb
CHANGED
data/lib/run_loop/xctools.rb
CHANGED
@@ -15,6 +15,14 @@ module RunLoop
|
|
15
15
|
# @todo Refactor instruments related code to instruments class.
|
16
16
|
class XCTools
|
17
17
|
|
18
|
+
# Returns a version instance for `Xcode 7.0`; used to check for the
|
19
|
+
# availability of features and paths to various items on the filesystem.
|
20
|
+
#
|
21
|
+
# @return [RunLoop::Version] 7.0
|
22
|
+
def v70
|
23
|
+
@xc70 ||= RunLoop::Version.new('7.0')
|
24
|
+
end
|
25
|
+
|
18
26
|
# Returns a version instance for `Xcode 6.4`; used to check for the
|
19
27
|
# availability of features and paths to various items on the filesystem.
|
20
28
|
#
|
@@ -106,6 +114,13 @@ module RunLoop
|
|
106
114
|
@xcode_gte_6 ||= xcode_version >= v60
|
107
115
|
end
|
108
116
|
|
117
|
+
# Are we running Xcode 6 or above?
|
118
|
+
#
|
119
|
+
# @return [Boolean] `true` if the current Xcode version is >= 6.0
|
120
|
+
def xcode_version_gte_7?
|
121
|
+
@xcode_gte_6 ||= xcode_version >= v70
|
122
|
+
end
|
123
|
+
|
109
124
|
# Are we running Xcode 5.1 or above?
|
110
125
|
#
|
111
126
|
# @return [Boolean] `true` if the current Xcode version is >= 5.1
|
data/lib/run_loop.rb
CHANGED
@@ -11,10 +11,12 @@ require 'run_loop/version'
|
|
11
11
|
require 'run_loop/xctools'
|
12
12
|
require 'run_loop/plist_buddy'
|
13
13
|
require 'run_loop/app'
|
14
|
+
require 'run_loop/ipa'
|
14
15
|
require 'run_loop/sim_control'
|
15
16
|
require 'run_loop/device'
|
16
17
|
require 'run_loop/instruments'
|
17
18
|
require 'run_loop/lipo'
|
19
|
+
require 'run_loop/cache/cache'
|
18
20
|
require 'run_loop/host_cache'
|
19
21
|
require 'run_loop/patches/awesome_print'
|
20
22
|
require 'run_loop/patches/retriable'
|
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: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Karl Krukow
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-07-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|
@@ -284,6 +284,7 @@ files:
|
|
284
284
|
- bin/run-loop
|
285
285
|
- lib/run_loop.rb
|
286
286
|
- lib/run_loop/app.rb
|
287
|
+
- lib/run_loop/cache/cache.rb
|
287
288
|
- lib/run_loop/cli/cli.rb
|
288
289
|
- lib/run_loop/cli/errors.rb
|
289
290
|
- lib/run_loop/cli/instruments.rb
|
@@ -296,6 +297,7 @@ files:
|
|
296
297
|
- lib/run_loop/fifo.rb
|
297
298
|
- lib/run_loop/host_cache.rb
|
298
299
|
- lib/run_loop/instruments.rb
|
300
|
+
- lib/run_loop/ipa.rb
|
299
301
|
- lib/run_loop/lipo.rb
|
300
302
|
- lib/run_loop/lldb.rb
|
301
303
|
- lib/run_loop/logging.rb
|
@@ -342,7 +344,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
342
344
|
version: '0'
|
343
345
|
requirements: []
|
344
346
|
rubyforge_project:
|
345
|
-
rubygems_version: 2.4.
|
347
|
+
rubygems_version: 2.4.7
|
346
348
|
signing_key:
|
347
349
|
specification_version: 4
|
348
350
|
summary: The bridge between Calabash iOS and Xcode command-line tools like instruments
|