run_loop 1.2.6 → 1.2.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 +7 -0
- data/lib/run_loop/app.rb +67 -0
- data/lib/run_loop/core.rb +17 -128
- data/lib/run_loop/device.rb +15 -3
- data/lib/run_loop/dylib_injector.rb +125 -0
- data/lib/run_loop/environment.rb +15 -0
- data/lib/run_loop/host_cache.rb +2 -1
- data/lib/run_loop/instruments.rb +59 -65
- data/lib/run_loop/lldb.rb +55 -0
- data/lib/run_loop/plist_buddy.rb +18 -2
- data/lib/run_loop/process_terminator.rb +140 -0
- data/lib/run_loop/process_waiter.rb +85 -0
- data/lib/run_loop/sim_control.rb +4 -4
- data/lib/run_loop/simctl/bridge.rb +242 -0
- data/lib/run_loop/version.rb +1 -1
- data/lib/run_loop/xctools.rb +16 -0
- data/scripts/calabash_script_uia.js +3667 -3590
- metadata +48 -24
- data/bin/run-loop +0 -9
- data/lib/run_loop/cli.rb +0 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2654e1672654ee6ae0af23cb582fec43864992df
|
4
|
+
data.tar.gz: d481bf34a098f76d83d94826575b021ace8232ca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: db03ba41012e7bf8f5d4cefa4833a36c478d16f9359339e415eae29dfa4faf62e6fb3491ad301d872941bcb30a1ebb71c1aabd55f95ceb01210119f2f57f00ff
|
7
|
+
data.tar.gz: 30e5ec4733c0ef6da15aa590c9390c46e3a9a6fa5ddb08f4e609602ace3a05579ea76d538a132f4667708ea1d4cf83307aeb243573b90635cbd6609c8b0e21d3
|
data/lib/run_loop.rb
CHANGED
@@ -1,10 +1,17 @@
|
|
1
|
+
require 'run_loop/environment'
|
2
|
+
require 'run_loop/process_terminator'
|
3
|
+
require 'run_loop/process_waiter'
|
4
|
+
require 'run_loop/lldb'
|
5
|
+
require 'run_loop/dylib_injector'
|
1
6
|
require 'run_loop/core'
|
2
7
|
require 'run_loop/version'
|
3
8
|
require 'run_loop/xctools'
|
4
9
|
require 'run_loop/plist_buddy'
|
10
|
+
require 'run_loop/app'
|
5
11
|
require 'run_loop/sim_control'
|
6
12
|
require 'run_loop/device'
|
7
13
|
require 'run_loop/instruments'
|
8
14
|
require 'run_loop/lipo'
|
9
15
|
require 'run_loop/host_cache'
|
10
16
|
require 'run_loop/monkey_patch'
|
17
|
+
require 'run_loop/simctl/bridge'
|
data/lib/run_loop/app.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
module RunLoop
|
2
|
+
# A class for interacting with .app bundles.
|
3
|
+
class App
|
4
|
+
|
5
|
+
# @!attribute [r] path
|
6
|
+
# @return [String] The path to the app bundle .app
|
7
|
+
attr_reader :path
|
8
|
+
|
9
|
+
# Creates a new App instance.
|
10
|
+
#
|
11
|
+
# @note The `app_bundle_path` is expanded during initialization.
|
12
|
+
#
|
13
|
+
# @param [String] app_bundle_path A path to a .app
|
14
|
+
# @return [RunLoop::App] A instance of App with a path.
|
15
|
+
def initialize(app_bundle_path)
|
16
|
+
@path = File.expand_path(app_bundle_path)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Is this a valid app?
|
20
|
+
def valid?
|
21
|
+
[File.exist?(path),
|
22
|
+
File.directory?(path),
|
23
|
+
File.extname(path) == '.app'].all?
|
24
|
+
end
|
25
|
+
|
26
|
+
# Returns the Info.plist path.
|
27
|
+
# @raise [RuntimeError] If there is no Info.plist.
|
28
|
+
def info_plist_path
|
29
|
+
info_plist = File.join(path, 'Info.plist')
|
30
|
+
unless File.exist?(info_plist)
|
31
|
+
raise "Expected an Info.plist at '#{path}'"
|
32
|
+
end
|
33
|
+
info_plist
|
34
|
+
end
|
35
|
+
|
36
|
+
# Inspects the app's Info.plist for the bundle identifier.
|
37
|
+
# @return [String] The value of CFBundleIdentifier.
|
38
|
+
# @raise [RuntimeError] If the plist cannot be read or the
|
39
|
+
# CFBundleIdentifier is empty or does not exist.
|
40
|
+
def bundle_identifier
|
41
|
+
identifier = plist_buddy.plist_read('CFBundleIdentifier', info_plist_path)
|
42
|
+
unless identifier
|
43
|
+
raise "Expected key 'CFBundleIdentifier' in '#{info_plist_path}'"
|
44
|
+
end
|
45
|
+
identifier
|
46
|
+
end
|
47
|
+
|
48
|
+
# Inspects the app's Info.plist for the executable name.
|
49
|
+
# @return [String] The value of CFBundleIdentifier.
|
50
|
+
# @raise [RuntimeError] If the plist cannot be read or the
|
51
|
+
# CFBundleExecutable is empty or does not exist.
|
52
|
+
def executable_name
|
53
|
+
identifier = plist_buddy.plist_read('CFBundleExecutable', info_plist_path)
|
54
|
+
unless identifier
|
55
|
+
raise "Expected key 'CFBundleExecutable' in '#{info_plist_path}'"
|
56
|
+
end
|
57
|
+
identifier
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def plist_buddy
|
63
|
+
@plist_buddy ||= RunLoop::PlistBuddy.new
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
data/lib/run_loop/core.rb
CHANGED
@@ -135,7 +135,8 @@ module RunLoop
|
|
135
135
|
sim_control ||= options[:sim_control] || RunLoop::SimControl.new
|
136
136
|
xctools ||= options[:xctools] || sim_control.xctools
|
137
137
|
|
138
|
-
RunLoop::Instruments.new
|
138
|
+
instruments = RunLoop::Instruments.new
|
139
|
+
instruments.kill_instruments
|
139
140
|
|
140
141
|
device_target = options[:udid] || options[:device_target] || detect_connected_device || 'simulator'
|
141
142
|
if device_target && device_target.to_s.downcase == 'device'
|
@@ -157,7 +158,6 @@ module RunLoop
|
|
157
158
|
|
158
159
|
script = File.join(results_dir, '_run_loop.js')
|
159
160
|
|
160
|
-
|
161
161
|
code = File.read(options[:script])
|
162
162
|
code = code.gsub(/\$PATH/, results_dir)
|
163
163
|
code = code.gsub(/\$READ_SCRIPT_PATH/, READ_SCRIPT_PATH)
|
@@ -186,10 +186,6 @@ module RunLoop
|
|
186
186
|
|
187
187
|
args = options.fetch(:args, [])
|
188
188
|
|
189
|
-
inject_dylib = self.dylib_path_from_options options
|
190
|
-
# WIP This is brute-force call against all lldb processes.
|
191
|
-
self.ensure_lldb_not_running if inject_dylib
|
192
|
-
|
193
189
|
log_file ||= File.join(results_dir, 'run_loop.out')
|
194
190
|
|
195
191
|
after = Time.now
|
@@ -217,22 +213,11 @@ module RunLoop
|
|
217
213
|
|
218
214
|
self.log_run_loop_options(merged_options, xctools)
|
219
215
|
|
220
|
-
|
216
|
+
automation_template = automation_template(xctools)
|
221
217
|
|
222
218
|
log_header("Starting on #{device_target} App: #{bundle_dir_or_bundle_id}")
|
223
|
-
cmd_str = cmd.join(' ')
|
224
219
|
|
225
|
-
|
226
|
-
|
227
|
-
if !jruby? && RUBY_VERSION && RUBY_VERSION.start_with?('1.8')
|
228
|
-
pid = fork do
|
229
|
-
exec(cmd_str)
|
230
|
-
end
|
231
|
-
else
|
232
|
-
pid = spawn(cmd_str)
|
233
|
-
end
|
234
|
-
|
235
|
-
Process.detach(pid)
|
220
|
+
pid = instruments.spawn(automation_template, merged_options, log_file)
|
236
221
|
|
237
222
|
File.open(File.join(results_dir, 'run_loop.pid'), 'w') do |f|
|
238
223
|
f.write pid
|
@@ -249,7 +234,6 @@ module RunLoop
|
|
249
234
|
|
250
235
|
uia_timeout = options[:uia_timeout] || (ENV['UIA_TIMEOUT'] && ENV['UIA_TIMEOUT'].to_f) || 10
|
251
236
|
|
252
|
-
raw_lldb_output = nil
|
253
237
|
before = Time.now
|
254
238
|
begin
|
255
239
|
|
@@ -262,63 +246,25 @@ module RunLoop
|
|
262
246
|
read_response(run_loop, 0, uia_timeout)
|
263
247
|
end
|
264
248
|
end
|
265
|
-
|
266
|
-
# inject_dylib will be nil or a path to a dylib
|
267
|
-
if inject_dylib
|
268
|
-
lldb_template_file = File.join(scripts_path, 'calabash.lldb.erb')
|
269
|
-
lldb_template = ::ERB.new(File.read(lldb_template_file))
|
270
|
-
lldb_template.filename = lldb_template_file
|
271
|
-
|
272
|
-
# Special!
|
273
|
-
# These are required by the ERB in calabash.lldb.erb
|
274
|
-
# noinspection RubyUnusedLocalVariable
|
275
|
-
cf_bundle_executable = find_cf_bundle_executable(bundle_dir_or_bundle_id)
|
276
|
-
# noinspection RubyUnusedLocalVariable
|
277
|
-
dylib_path_for_target = inject_dylib
|
278
|
-
|
279
|
-
lldb_cmd = lldb_template.result(binding)
|
280
|
-
|
281
|
-
tmpdir = Dir.mktmpdir('lldb_cmd')
|
282
|
-
lldb_script = File.join(tmpdir, 'lldb')
|
283
|
-
|
284
|
-
File.open(lldb_script, 'w') { |f| f.puts(lldb_cmd) }
|
285
|
-
|
286
|
-
if ENV['DEBUG'] == '1'
|
287
|
-
puts "lldb script #{lldb_script}"
|
288
|
-
puts "=== lldb script ==="
|
289
|
-
counter = 0
|
290
|
-
File.open(lldb_script, 'r').readlines.each { |line|
|
291
|
-
puts "#{counter} #{line}"
|
292
|
-
counter = counter + 1
|
293
|
-
}
|
294
|
-
puts "=== lldb script ==="
|
295
|
-
end
|
296
|
-
|
297
|
-
# Forcing a timeout. Do not retry here. If lldb is hanging,
|
298
|
-
# RunLoop::Core.run* needs to be called again. Put another way,
|
299
|
-
# instruments and lldb must be terminated.
|
300
|
-
Retriable.retriable({:tries => 1, :timeout => 12, :interval => 1}) do
|
301
|
-
raw_lldb_output = `xcrun lldb -s #{lldb_script}`
|
302
|
-
if ENV['DEBUG'] == '1'
|
303
|
-
puts raw_lldb_output
|
304
|
-
end
|
305
|
-
end
|
306
|
-
end
|
307
249
|
rescue TimeoutError => e
|
308
250
|
if ENV['DEBUG'] == '1'
|
309
251
|
puts "Failed to launch."
|
310
252
|
puts "#{e}: #{e && e.message}"
|
311
|
-
if raw_lldb_output
|
312
|
-
puts "LLDB OUTPUT: #{raw_lldb_output}"
|
313
|
-
end
|
314
253
|
end
|
315
254
|
raise TimeoutError, "Time out waiting for UIAutomation run-loop to Start. \n Logfile #{log_file} \n\n #{File.read(log_file)}\n"
|
316
255
|
end
|
317
256
|
|
318
|
-
after = Time.now()
|
319
|
-
|
320
257
|
if ENV['DEBUG']=='1'
|
321
|
-
puts "Launching took #{
|
258
|
+
puts "Launching took #{Time.now-before} seconds"
|
259
|
+
end
|
260
|
+
|
261
|
+
dylib_path = self.dylib_path_from_options(merged_options)
|
262
|
+
|
263
|
+
if dylib_path
|
264
|
+
RunLoop::LLDB.kill_lldb_processes
|
265
|
+
app = RunLoop::App.new(options[:app])
|
266
|
+
lldb = RunLoop::DylibInjector.new(app.executable_name, dylib_path)
|
267
|
+
lldb.retriable_inject_dylib
|
322
268
|
end
|
323
269
|
|
324
270
|
run_loop
|
@@ -392,15 +338,6 @@ module RunLoop
|
|
392
338
|
dylib_path
|
393
339
|
end
|
394
340
|
|
395
|
-
def self.find_cf_bundle_executable(bundle_dir_or_bundle_id)
|
396
|
-
unless File.directory?(bundle_dir_or_bundle_id)
|
397
|
-
raise "Injecting dylibs currently only works with simulator and app bundles"
|
398
|
-
end
|
399
|
-
info_plist = Dir[File.join(bundle_dir_or_bundle_id, 'Info.plist')].first
|
400
|
-
raise "Unable to find Info.plist in #{bundle_dir_or_bundle_id}" if info_plist.nil?
|
401
|
-
`/usr/libexec/PlistBuddy -c "Print :CFBundleExecutable" "#{info_plist}"`.strip
|
402
|
-
end
|
403
|
-
|
404
341
|
# Returns the a default simulator to target. This default needs to be one
|
405
342
|
# that installed by default in the current Xcode version.
|
406
343
|
#
|
@@ -409,7 +346,9 @@ module RunLoop
|
|
409
346
|
# @param [RunLoop::XCTools] xcode_tools Used to detect the current xcode
|
410
347
|
# version.
|
411
348
|
def self.default_simulator(xcode_tools=RunLoop::XCTools.new)
|
412
|
-
if xcode_tools.
|
349
|
+
if xcode_tools.xcode_version_gte_63?
|
350
|
+
'iPhone 5s (8.3 Simulator)'
|
351
|
+
elsif xcode_tools.xcode_version_gte_62?
|
413
352
|
'iPhone 5s (8.2 Simulator)'
|
414
353
|
elsif xcode_tools.xcode_version_gte_61?
|
415
354
|
'iPhone 5s (8.1 Simulator)'
|
@@ -615,40 +554,6 @@ module RunLoop
|
|
615
554
|
RunLoop::Instruments.new.instruments_pids(&block)
|
616
555
|
end
|
617
556
|
|
618
|
-
def self.instruments_command_prefix(udid, results_dir_trace)
|
619
|
-
instruments_path = 'xcrun instruments'
|
620
|
-
if udid
|
621
|
-
instruments_path = "#{instruments_path} -w \"#{udid}\""
|
622
|
-
end
|
623
|
-
instruments_path << " -D \"#{results_dir_trace}\"" if results_dir_trace
|
624
|
-
instruments_path
|
625
|
-
end
|
626
|
-
|
627
|
-
|
628
|
-
def self.instruments_command(options, xctools=RunLoop::XCTools.new)
|
629
|
-
udid = options[:udid]
|
630
|
-
results_dir_trace = options[:results_dir_trace]
|
631
|
-
bundle_dir_or_bundle_id = options[:bundle_dir_or_bundle_id]
|
632
|
-
results_dir = options[:results_dir]
|
633
|
-
script = options[:script]
|
634
|
-
log_file = options[:log_file]
|
635
|
-
args= options[:args] || []
|
636
|
-
|
637
|
-
instruments_prefix = instruments_command_prefix(udid, results_dir_trace)
|
638
|
-
cmd = [
|
639
|
-
instruments_prefix,
|
640
|
-
'-t', "\"#{automation_template(xctools)}\"",
|
641
|
-
"\"#{bundle_dir_or_bundle_id}\"",
|
642
|
-
'-e', 'UIARESULTSPATH', results_dir,
|
643
|
-
'-e', 'UIASCRIPT', script,
|
644
|
-
args.join(' ')
|
645
|
-
]
|
646
|
-
if log_file
|
647
|
-
cmd << "&> #{log_file}"
|
648
|
-
end
|
649
|
-
cmd
|
650
|
-
end
|
651
|
-
|
652
557
|
def self.automation_template(xctools, candidate = ENV['TRACE_TEMPLATE'])
|
653
558
|
unless candidate && File.exist?(candidate)
|
654
559
|
candidate = default_tracetemplate xctools
|
@@ -710,22 +615,6 @@ module RunLoop
|
|
710
615
|
def self.instruments_pids
|
711
616
|
RunLoop::Instruments.new.instruments_pids
|
712
617
|
end
|
713
|
-
|
714
|
-
# @todo This is a WIP
|
715
|
-
# @todo Needs rspec test
|
716
|
-
def self.ensure_lldb_not_running
|
717
|
-
descripts = `xcrun ps x -o pid,command | grep "lldb" | grep -v grep`.strip.split("\n")
|
718
|
-
descripts.each do |process_desc|
|
719
|
-
pid = process_desc.split(' ').first
|
720
|
-
Open3.popen3("xcrun kill -9 #{pid} && xcrun wait #{pid}") do |_, stdout, stderr, _|
|
721
|
-
out = stdout.read.strip
|
722
|
-
err = stderr.read.strip
|
723
|
-
next if out.to_s.empty? and err.to_s.empty?
|
724
|
-
# there lots of 'ownership' problems trying to kill the lldb process
|
725
|
-
#puts "kill process '#{pid}' => stdout: '#{out}' | stderr: '#{err}'"
|
726
|
-
end
|
727
|
-
end
|
728
|
-
end
|
729
618
|
end
|
730
619
|
|
731
620
|
def self.default_script_for_uia_strategy(uia_strategy)
|
data/lib/run_loop/device.rb
CHANGED
@@ -4,17 +4,29 @@ module RunLoop
|
|
4
4
|
attr_reader :name
|
5
5
|
attr_reader :version
|
6
6
|
attr_reader :udid
|
7
|
+
attr_reader :state
|
7
8
|
|
8
|
-
|
9
|
+
# Create a new device.
|
10
|
+
#
|
11
|
+
# @param [String] name The name of the device. For sims this should be
|
12
|
+
# 'iPhone 5s' and for physical devices it will be the name the user gave
|
13
|
+
# to the device.
|
14
|
+
# @param [String, RunLoop::Version] version The iOS version that is running
|
15
|
+
# on the device. Can be a string or a Version instance.
|
16
|
+
# @param [String] udid The device identifier.
|
17
|
+
# @param [String] state (nil) This a simulator only value. It refers to
|
18
|
+
# the Booted/Shutdown/Creating state of the simulator. For pre-Xcode 6
|
19
|
+
# simulators, this value should be nil.
|
20
|
+
def initialize(name, version, udid, state=nil)
|
9
21
|
@name = name
|
22
|
+
@udid = udid
|
23
|
+
@state = state
|
10
24
|
|
11
25
|
if version.is_a? String
|
12
26
|
@version = RunLoop::Version.new version
|
13
27
|
else
|
14
28
|
@version = version
|
15
29
|
end
|
16
|
-
|
17
|
-
@udid = udid
|
18
30
|
end
|
19
31
|
|
20
32
|
# Returns and instruments-ready device identifier that is a suitable value
|
@@ -0,0 +1,125 @@
|
|
1
|
+
module RunLoop
|
2
|
+
|
3
|
+
# @!visibility private
|
4
|
+
#
|
5
|
+
# This is experimental.
|
6
|
+
#
|
7
|
+
# Injects dylibs into running executables using lldb.
|
8
|
+
class DylibInjector
|
9
|
+
|
10
|
+
# @!attribute [r] process_name
|
11
|
+
# The name of the process to inject the dylib into. This should be obtained
|
12
|
+
# by inspecting the Info.plist in the app bundle.
|
13
|
+
# @return [String] The process_name
|
14
|
+
attr_reader :process_name
|
15
|
+
|
16
|
+
# @!attribute [r] dylib_path
|
17
|
+
# The path to the dylib that is to be injected.
|
18
|
+
# @return [String] The dylib_path
|
19
|
+
attr_reader :dylib_path
|
20
|
+
|
21
|
+
# Create a new dylib injector.
|
22
|
+
# @param [String] process_name The name of the process to inject the dylib
|
23
|
+
# into. This should be obtained by inspecting the Info.plist in the app
|
24
|
+
# bundle.
|
25
|
+
# @param [String] dylib_path The path the dylib to inject.
|
26
|
+
def initialize(process_name, dylib_path)
|
27
|
+
@process_name = process_name
|
28
|
+
@dylib_path = dylib_path
|
29
|
+
end
|
30
|
+
|
31
|
+
# Injects a dylib into a a currently running process.
|
32
|
+
def inject_dylib
|
33
|
+
debug_logging = RunLoop::Environment.debug?
|
34
|
+
puts "Starting lldb." if debug_logging
|
35
|
+
|
36
|
+
stderr_output = nil
|
37
|
+
lldb_status = nil
|
38
|
+
lldb_start_time = Time.now
|
39
|
+
Open3.popen3('sh') do |stdin, stdout, stderr, process_status|
|
40
|
+
stdin.puts 'xcrun lldb --no-lldbinit<<EOF'
|
41
|
+
stdin.puts "process attach -n '#{@process_name}'"
|
42
|
+
stdin.puts "expr (void*)dlopen(\"#{@dylib_path}\", 0x2)"
|
43
|
+
stdin.puts 'detach'
|
44
|
+
stdin.puts 'exit'
|
45
|
+
stdin.puts 'EOF'
|
46
|
+
stdin.close
|
47
|
+
|
48
|
+
puts "#{stdout.read}" if debug_logging
|
49
|
+
|
50
|
+
lldb_status = process_status
|
51
|
+
stderr_output = stderr.read.strip
|
52
|
+
end
|
53
|
+
|
54
|
+
pid = lldb_status.pid
|
55
|
+
exit_status = lldb_status.value.exitstatus
|
56
|
+
|
57
|
+
if stderr_output == ''
|
58
|
+
if debug_logging
|
59
|
+
puts "lldb '#{pid}' exited with value '#{exit_status}'."
|
60
|
+
puts "Took #{Time.now-lldb_start_time} for lldb to inject calabash dylib."
|
61
|
+
end
|
62
|
+
else
|
63
|
+
puts "#{stderr_output}"
|
64
|
+
if debug_logging
|
65
|
+
puts "lldb '#{pid}' exited with value '#{exit_status}'."
|
66
|
+
puts "lldb tried for #{Time.now-lldb_start_time} to inject calabash dylib before giving up."
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
stderr_output == ''
|
71
|
+
end
|
72
|
+
|
73
|
+
def inject_dylib_with_timeout(timeout)
|
74
|
+
success = false
|
75
|
+
Timeout.timeout(timeout) do
|
76
|
+
success = inject_dylib
|
77
|
+
end
|
78
|
+
success
|
79
|
+
end
|
80
|
+
|
81
|
+
def retriable_inject_dylib(options={})
|
82
|
+
merged_options = RETRIABLE_OPTIONS.merge(options)
|
83
|
+
|
84
|
+
debug_logging = RunLoop::Environment.debug?
|
85
|
+
|
86
|
+
on_retry = Proc.new do |_, try, elapsed_time, next_interval|
|
87
|
+
if debug_logging
|
88
|
+
# Retriable 2.0
|
89
|
+
if elapsed_time && next_interval
|
90
|
+
puts "LLDB: attempt #{try} failed in '#{elapsed_time}'; will retry in '#{next_interval}'"
|
91
|
+
else
|
92
|
+
puts "LLDB: attempt #{try} failed; will retry in '#{merged_options[:interval]}'"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
RunLoop::LLDB.kill_lldb_processes
|
96
|
+
RunLoop::ProcessWaiter.new('lldb').wait_for_none
|
97
|
+
end
|
98
|
+
|
99
|
+
# For some reason, :timeout does not work here - the lldb process can
|
100
|
+
# hang indefinitely. Seems to work when
|
101
|
+
Retriable.retriable({:tries => merged_options[:retries],
|
102
|
+
# Retriable 2.0
|
103
|
+
:interval => merged_options[:interval],
|
104
|
+
:base_interval => merged_options[:interval],
|
105
|
+
:on_retry => on_retry}) do
|
106
|
+
#unless inject_dylib_with_timeout merged_options[:timeout]
|
107
|
+
unless inject_dylib_with_timeout merged_options[:timeout]
|
108
|
+
raise RuntimeError, "Could not inject dylib"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
true
|
112
|
+
end
|
113
|
+
|
114
|
+
private
|
115
|
+
|
116
|
+
RETRIABLE_OPTIONS =
|
117
|
+
{
|
118
|
+
:retries => 3,
|
119
|
+
:timeout => 10,
|
120
|
+
# Retriable 2.0 replaces :interval with :base_interval
|
121
|
+
:interval => 2,
|
122
|
+
:base_interval => 2
|
123
|
+
}
|
124
|
+
end
|
125
|
+
end
|