run_loop 1.1.1.pre7 → 1.1.1.pre8
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 +2 -0
- data/lib/run_loop/core.rb +51 -8
- data/lib/run_loop/device.rb +36 -12
- data/lib/run_loop/lipo.rb +107 -0
- data/lib/run_loop/version.rb +1 -1
- 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: 9340394da27267a6ea43ce6a61c2cb018faf97ff
|
4
|
+
data.tar.gz: 54d9b6db6739d00d5895b7d6108b8fd374f51aa1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9cbcdcee2fe866606caff3ec4609375777617a2de2ea216f314662539b2addda8ae42562bba6b624355a8398500568e442f7f8ac4980cd96e08dccfd047b54cf
|
7
|
+
data.tar.gz: 83bb516e414e2e1c05a1cc63f45e32194c2dbc3359c52894a406f48fd9b93b759f3adc5aef026060d0a4a66c5f8900a24e5be2b183a2f9c055c1c120eda3f8b2
|
data/lib/run_loop.rb
CHANGED
data/lib/run_loop/core.rb
CHANGED
@@ -83,6 +83,48 @@ module RunLoop
|
|
83
83
|
nil
|
84
84
|
end
|
85
85
|
|
86
|
+
# Raise an error if the application binary is not compatible with the
|
87
|
+
# target simulator.
|
88
|
+
#
|
89
|
+
# @note This method is implemented for CoreSimulator environments only;
|
90
|
+
# for Xcode < 6.0 this method does nothing.
|
91
|
+
#
|
92
|
+
# @param [Hash] launch_options These options need to contain the app bundle
|
93
|
+
# path and a udid that corresponds to a simulator name or simulator udid.
|
94
|
+
# In practical terms: call this after merging the original launch
|
95
|
+
# options with those options that are discovered.
|
96
|
+
#
|
97
|
+
# @param [RunLoop::SimControl] sim_control A simulator control object.
|
98
|
+
# @raise [RuntimeError] Raises an error if the `launch_options[:udid]`
|
99
|
+
# cannot be used to find a simulator.
|
100
|
+
# @raise [RunLoop::IncompatibleArchitecture] Raises an error if the
|
101
|
+
# application binary is not compatible with the target simulator.
|
102
|
+
def self.expect_compatible_simulator_architecture(launch_options, sim_control)
|
103
|
+
if sim_control.xcode_version_gte_6?
|
104
|
+
sim_identifier = launch_options[:udid]
|
105
|
+
simulator = sim_control.simulators.find do |simulator|
|
106
|
+
[simulator.instruments_identifier(sim_control.xctools),
|
107
|
+
simulator.udid].include?(sim_identifier)
|
108
|
+
end
|
109
|
+
|
110
|
+
if simulator.nil?
|
111
|
+
raise "Could not find simulator with identifier '#{sim_identifier}'"
|
112
|
+
end
|
113
|
+
|
114
|
+
lipo = RunLoop::Lipo.new(launch_options[:bundle_dir_or_bundle_id])
|
115
|
+
lipo.expect_compatible_arch(simulator)
|
116
|
+
if ENV['DEBUG'] == '1'
|
117
|
+
puts "Simulator instruction set '#{simulator.instruction_set}' is compatible with #{lipo.info}"
|
118
|
+
end
|
119
|
+
true
|
120
|
+
else
|
121
|
+
if ENV['DEBUG'] == '1'
|
122
|
+
puts "Xcode #{sim_control.xctools.xcode_version} detected; skipping simulator architecture check."
|
123
|
+
end
|
124
|
+
false
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
86
128
|
def self.run_with_options(options)
|
87
129
|
before = Time.now
|
88
130
|
|
@@ -91,11 +133,6 @@ module RunLoop
|
|
91
133
|
|
92
134
|
RunLoop::Instruments.new.kill_instruments(xctools)
|
93
135
|
|
94
|
-
if self.simulator_target?(options, sim_control)
|
95
|
-
# @todo only enable accessibility on the targeted simulator
|
96
|
-
sim_control.enable_accessibility_on_sims({:verbose => false})
|
97
|
-
end
|
98
|
-
|
99
136
|
device_target = options[:udid] || options[:device_target] || detect_connected_device || 'simulator'
|
100
137
|
if device_target && device_target.to_s.downcase == 'device'
|
101
138
|
device_target = detect_connected_device
|
@@ -150,7 +187,7 @@ module RunLoop
|
|
150
187
|
log_file ||= File.join(results_dir, 'run_loop.out')
|
151
188
|
|
152
189
|
after = Time.now
|
153
|
-
if ENV['DEBUG']=='1'
|
190
|
+
if ENV['DEBUG'] == '1'
|
154
191
|
puts "Preparation took #{after-before} seconds"
|
155
192
|
end
|
156
193
|
|
@@ -166,6 +203,12 @@ module RunLoop
|
|
166
203
|
}
|
167
204
|
merged_options = options.merge(discovered_options)
|
168
205
|
|
206
|
+
if self.simulator_target?(merged_options, sim_control)
|
207
|
+
# @todo only enable accessibility on the targeted simulator
|
208
|
+
sim_control.enable_accessibility_on_sims({:verbose => false})
|
209
|
+
self.expect_compatible_simulator_architecture(merged_options, sim_control)
|
210
|
+
end
|
211
|
+
|
169
212
|
self.log_run_loop_options(merged_options, xctools)
|
170
213
|
|
171
214
|
cmd = instruments_command(merged_options, xctools)
|
@@ -819,9 +862,9 @@ module RunLoop
|
|
819
862
|
script
|
820
863
|
end
|
821
864
|
|
822
|
-
def self.log_info(
|
865
|
+
def self.log_info(logger, message)
|
823
866
|
msg = "#{Time.now}: #{message}"
|
824
|
-
if
|
867
|
+
if logger && logger.respond_to?(:info)
|
825
868
|
logger.info(msg)
|
826
869
|
else
|
827
870
|
puts msg if ENV['DEBUG'] == '1'
|
data/lib/run_loop/device.rb
CHANGED
@@ -17,18 +17,6 @@ module RunLoop
|
|
17
17
|
@udid = udid
|
18
18
|
end
|
19
19
|
|
20
|
-
# Is this device a simulator?
|
21
|
-
# @return [Boolean] Return true if this device is a simulator.
|
22
|
-
def simulator?
|
23
|
-
not physical_device?
|
24
|
-
end
|
25
|
-
|
26
|
-
# Is this is a physical device?
|
27
|
-
# @return [Boolean] Return true if this is a physical device.
|
28
|
-
def physical_device?
|
29
|
-
(self.udid =~ /[a-f0-9]{40}/) == 0
|
30
|
-
end
|
31
|
-
|
32
20
|
# Returns and instruments-ready device identifier that is a suitable value
|
33
21
|
# for DEVICE_TARGET environment variable.
|
34
22
|
#
|
@@ -50,5 +38,41 @@ module RunLoop
|
|
50
38
|
"#{self.name} (#{version_part} Simulator)"
|
51
39
|
end
|
52
40
|
end
|
41
|
+
|
42
|
+
# Is this a physical device?
|
43
|
+
# @return [Boolean] Returns true if this is a device.
|
44
|
+
def physical_device?
|
45
|
+
not self.udid[/[a-f0-9]{40}/, 0].nil?
|
46
|
+
end
|
47
|
+
|
48
|
+
# Is this a simulator?
|
49
|
+
# @return [Boolean] Returns true if this is a simulator.
|
50
|
+
def simulator?
|
51
|
+
not self.physical_device?
|
52
|
+
end
|
53
|
+
|
54
|
+
# Return the instruction set for this device.
|
55
|
+
#
|
56
|
+
# **Simulator**
|
57
|
+
# The simulator instruction set will be i386 or x86_64 depending on the
|
58
|
+
# the (marketing) name of the device.
|
59
|
+
#
|
60
|
+
# @note Finding the instruction set of a device requires a third-party tool
|
61
|
+
# like ideviceinfo. Example:
|
62
|
+
# `$ ideviceinfo -u 89b59 < snip > ab7ba --key 'CPUArchitecture' => arm64`
|
63
|
+
#
|
64
|
+
# @raise [RuntimeError] Raises an error if this device is a physical device.
|
65
|
+
# @return [String] An instruction set.
|
66
|
+
def instruction_set
|
67
|
+
if self.simulator?
|
68
|
+
if ['iPhone 4s', 'iPhone 5', 'iPad 2', 'iPad Retina'].include?(self.name)
|
69
|
+
'i386'
|
70
|
+
else
|
71
|
+
'x86_64'
|
72
|
+
end
|
73
|
+
else
|
74
|
+
raise 'Finding the instruction set of a device requires a third-party tool like ideviceinfo'
|
75
|
+
end
|
76
|
+
end
|
53
77
|
end
|
54
78
|
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'open3'
|
2
|
+
|
3
|
+
module RunLoop
|
4
|
+
|
5
|
+
# An error class for signaling an incompatible architecture.
|
6
|
+
class IncompatibleArchitecture < StandardError
|
7
|
+
end
|
8
|
+
|
9
|
+
# A class for interacting with the lipo command-line tool to verify that an
|
10
|
+
# executable is valid for the test target (device or simulator).
|
11
|
+
#
|
12
|
+
# @note All lipo commands are run in the context of `xcrun`.
|
13
|
+
class Lipo
|
14
|
+
|
15
|
+
# The path to the application bundle we are inspecting.
|
16
|
+
# @!attribute [wr] bundle_path
|
17
|
+
# @return [String] The path to the application bundle (.app).
|
18
|
+
attr_accessor :bundle_path
|
19
|
+
|
20
|
+
def initialize(bundle_path)
|
21
|
+
@bundle_path = bundle_path
|
22
|
+
@plist_buddy = RunLoop::PlistBuddy.new
|
23
|
+
end
|
24
|
+
|
25
|
+
# Inspect the `CFBundleExecutable` in the app bundle path with `lipo` and
|
26
|
+
# compare the result with the target device's instruction set.
|
27
|
+
#
|
28
|
+
# **Simulators**
|
29
|
+
#
|
30
|
+
# If the target is a simulator and the binary contains an i386 slice, the
|
31
|
+
# app will launch on the 64-bit simulators.
|
32
|
+
#
|
33
|
+
# If the target is a simulator and the binary contains _only_ an x86_64
|
34
|
+
# slice, the app will not launch on these simulators:
|
35
|
+
#
|
36
|
+
# ```
|
37
|
+
# iPhone 4S, iPad 2, iPhone 5, and iPad Retina.
|
38
|
+
# ```
|
39
|
+
#
|
40
|
+
# All other simulators are 64-bit.
|
41
|
+
#
|
42
|
+
# **Devices**
|
43
|
+
#
|
44
|
+
# @see {https://www.innerfence.com/howto/apple-ios-devices-dates-versions-instruction-sets}
|
45
|
+
#
|
46
|
+
# ```
|
47
|
+
# armv7 <== 3gs, 4s, iPad 2, iPad mini, iPad 3, iPod 3, iPod 4, iPod 5
|
48
|
+
# armv7s <== 5, 5c, iPad 4
|
49
|
+
# arm64 <== 5s, 6, 6 Plus, Air, Air 2, iPad Mini Retina, iPad Mini 3
|
50
|
+
# ```
|
51
|
+
#
|
52
|
+
# @note At the moment, we are focusing on simulator compatibility. Since we
|
53
|
+
# don't have an automated way of installing an .ipa on local device, we
|
54
|
+
# don't require an .ipa path. Without an .ipa path, we cannot verify the
|
55
|
+
# architectures. Further, we would need to adopt a third-party tool like
|
56
|
+
# ideviceinfo to find the target device's instruction set.
|
57
|
+
# @param [RunLoop::Device] device The test target.
|
58
|
+
# @raise [RuntimeError] Raises an error if the device is a physical device.
|
59
|
+
# @raise [RunLoop::IncompatibleArchitecture] Raises an error if the instruction set of the target
|
60
|
+
# device is not compatible with the executable in the application.
|
61
|
+
def expect_compatible_arch(device)
|
62
|
+
if device.physical_device?
|
63
|
+
raise 'Ensuring compatible arches for physical devices is NYI'
|
64
|
+
else
|
65
|
+
arches = self.info
|
66
|
+
# An i386 binary will run on any simulator.
|
67
|
+
return true if arches.include?('i386')
|
68
|
+
|
69
|
+
instruction_set = device.instruction_set
|
70
|
+
unless arches.include?(instruction_set)
|
71
|
+
raise RunLoop::IncompatibleArchitecture,
|
72
|
+
['Binary at:',
|
73
|
+
binary_path,
|
74
|
+
"does not contain a compatible architecture for target device.",
|
75
|
+
"Expected '#{instruction_set}' but found #{arches}."].join("\n")
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Returns a list of architecture in the binary.
|
81
|
+
# @return [Array<String>] A list of architecture.
|
82
|
+
def info
|
83
|
+
execute_lipo("-info #{binary_path}") do |stdout, _, _|
|
84
|
+
output = stdout.read.strip
|
85
|
+
output.split(':')[-1].strip.split
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def execute_lipo(argument)
|
92
|
+
command = "xcrun lipo #{argument}"
|
93
|
+
Open3.popen3(command) do |_, stdout, stderr, wait_thr|
|
94
|
+
yield stdout, stderr, wait_thr
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def plist_path
|
99
|
+
File.join(@bundle_path, 'Info.plist');
|
100
|
+
end
|
101
|
+
|
102
|
+
def binary_path
|
103
|
+
binary_relative_path = @plist_buddy.plist_read('CFBundleExecutable', plist_path)
|
104
|
+
File.join(@bundle_path, binary_relative_path)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
data/lib/run_loop/version.rb
CHANGED
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.1.1.
|
4
|
+
version: 1.1.1.pre8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Karl Krukow
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-12-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -222,6 +222,7 @@ files:
|
|
222
222
|
- lib/run_loop/core.rb
|
223
223
|
- lib/run_loop/device.rb
|
224
224
|
- lib/run_loop/instruments.rb
|
225
|
+
- lib/run_loop/lipo.rb
|
225
226
|
- lib/run_loop/plist_buddy.rb
|
226
227
|
- lib/run_loop/sim_control.rb
|
227
228
|
- lib/run_loop/version.rb
|