run_loop 1.3.3 → 1.4.0
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/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
|