module RunLoop
Constants
- VERSION
Public Class Methods
default_automator(xcode, device)
click to toggle source
@!visibility private
@param [RunLoop::Xcode] xcode The active Xcode
@param [RunLoop::Device] device The device under test.
# File lib/run_loop.rb, line 213 def self.default_automator(xcode, device) # TODO XTC support return :instruments if RunLoop::Environment.xtc? if xcode.version_gte_8? if device.version >= RunLoop::Version.new("9.0") :device_agent else raise RuntimeError, %Q[ Invalid Xcode and iOS combination: Xcode version: #{xcode.version.to_s} iOS version: #{device.version.to_s} Calabash cannot test iOS < 9.0 using Xcode 8 because DeviceAgent is not compatible with iOS < 9.0 and UIAutomation is not available in Xcode 8. You can rerun your test if you have Xcode 7 installed: $ DEVELOPER_DIR=/path/to/Xcode/7.3.1/Xcode.app/Contents/Developer cucumber ] end else :instruments end end
deprecated(version, msg)
click to toggle source
Prints a deprecated message that includes the line number.
@param [String] version Indicates when the feature was deprecated. @param [String] msg Deprecation message (possibly suggesting alternatives) @return [void]
# File lib/run_loop.rb, line 60 def self.deprecated(version, msg) stack = Kernel.caller(0, 6)[1..-1].join("\n") msg = "deprecated '#{version}' - #{msg}\n#{stack}" $stderr.puts "\033[34mWARN: #{msg}\033[0m" $stderr.flush end
detect_automator(options, xcode, device)
click to toggle source
@!visibility private
First pass at choosing the correct code path.
We don’t know if we can test on iOS 8 with UIAutomation or DeviceAgent
on Xcode
8.
@param [Hash] options The options passed by the user @param [RunLoop::Xcode] xcode The active Xcode
@param [RunLoop::Device] device The device under test
# File lib/run_loop.rb, line 252 def self.detect_automator(options, xcode, device) # TODO XTC support return :instruments if RunLoop::Environment.xtc? automator = options[:automator] if automator if xcode.version_gte_8? if automator == :instruments raise RuntimeError, %Q[ Incompatible :automator option for active Xcode. Detected :automator => :instruments and Xcode #{xcode.version}. Don't set the :automator option unless you are gem maintainer. ] elsif device.version < RunLoop::Version.new("9.0") raise RuntimeError, %Q[ Invalid Xcode and iOS combination: Xcode version: #{xcode.version.to_s} iOS version: #{device.version.to_s} Calabash cannot test iOS < 9.0 using Xcode 8 because DeviceAgent is not compatible with iOS < 9.0 and UIAutomation is not available in Xcode 8. You can rerun your test if you have Xcode 7 installed: $ DEVELOPER_DIR=/path/to/Xcode/7.3.1/Xcode.app/Contents/Developer cucumber Don't set the :automator option unless you are gem maintainer. ] end end if ![:device_agent, :instruments].include?(automator) raise RuntimeError, %Q[ Invalid :automator option: #{automator} Allowed automators: :device_agent or :instruments. Don't set the :automator option unless you are gem maintainer. ] end automator else RunLoop.default_automator(xcode, device) end end
log_debug(msg)
click to toggle source
magenta
# File lib/run_loop/logging.rb, line 56 def self.log_debug(msg) if RunLoop::Environment.debug? puts Color.magenta("DEBUG: #{msg}") if msg end end
log_error(msg)
click to toggle source
red
# File lib/run_loop/logging.rb, line 69 def self.log_error(msg) puts Color.red("ERROR: #{msg}") if msg end
log_info(*args)
click to toggle source
# File lib/run_loop.rb, line 205 def self.log_info(*args) RunLoop::Logging.log_info(*args) end
log_info2(msg)
click to toggle source
.log_info is already taken by the XTC logger. (>_O) green
# File lib/run_loop/logging.rb, line 64 def self.log_info2(msg) puts Color.green("INFO: #{msg}") if msg end
log_unix_cmd(msg)
click to toggle source
cyan
# File lib/run_loop/logging.rb, line 44 def self.log_unix_cmd(msg) if RunLoop::Environment.debug? puts Color.cyan("SHELL: #{msg}") if msg end end
log_warn(msg)
click to toggle source
blue
# File lib/run_loop/logging.rb, line 51 def self.log_warn(msg) puts Color.blue("WARN: #{msg}") if msg end
run(options={})
click to toggle source
# File lib/run_loop.rb, line 76 def self.run(options={}) cloned_options = options.clone # We want to use the _exact_ objects that were passed. if options[:xcode] cloned_options[:xcode] = options[:xcode] else cloned_options[:xcode] = RunLoop::Xcode.new end if options[:simctl] cloned_options[:simctl] = options[:simctl] else cloned_options[:simctl] = RunLoop::Simctl.new end if options[:instruments] cloned_options[:instruments] = options[:instruments] else cloned_options[:instruments] = RunLoop::Instruments.new end # Soon to be unsupported. if options[:sim_control] cloned_options[:sim_control] = options[:sim_control] end xcode = cloned_options[:xcode] simctl = cloned_options[:simctl] instruments = cloned_options[:instruments] device = Device.detect_device(cloned_options, xcode, simctl, instruments) cloned_options[:device] = device automator = RunLoop.detect_automator(cloned_options, xcode, device) if automator == :device_agent RunLoop::DeviceAgent::Client.run(cloned_options) else if RunLoop::Instruments.new.instruments_app_running? raise %q(The Instruments.app is open. If the Instruments.app is open, the instruments command line tool cannot take control of your application. Please quit the Instruments.app and try again.) end Core.run_with_options(cloned_options) end end
send_command(run_loop, cmd, options={timeout: 60}, num_retries=0, last_error=nil)
click to toggle source
# File lib/run_loop.rb, line 128 def self.send_command(run_loop, cmd, options={timeout: 60}, num_retries=0, last_error=nil) if num_retries > 3 if last_error raise last_error else raise "Max retries exceeded #{num_retries} > 3. No error recorded." end end if options.is_a?(Numeric) options = {timeout: options} end if not cmd.is_a?(String) raise "Illegal command #{cmd} (must be a string)" end if not options.is_a?(Hash) raise "Illegal options #{options} (must be a Hash (or number for compatibility))" end timeout = options[:timeout] || 60 logger = options[:logger] interrupt_retry_timeout = options[:interrupt_retry_timeout] || 25 expected_index = run_loop[:index] result = nil begin expected_index = Core.write_request(run_loop, cmd, logger) rescue RunLoop::WriteFailedError, Errno::EINTR => write_error # Attempt recover from interrupt by attempting to read result (assuming write went OK) # or retry if attempted read result fails run_loop[:index] = expected_index # restore expected index in case it changed log_info(logger, "Core.write_request failed: #{write_error}. Attempting recovery...") log_info(logger, "Attempting read in case the request was received... Please wait (#{interrupt_retry_timeout})...") begin Timeout::timeout(interrupt_retry_timeout, TimeoutError) do result = Core.read_response(run_loop, expected_index) end # Update run_loop expected index since we succeeded in reading the index run_loop[:index] = expected_index + 1 log_info(logger, "Did read response for interrupted request of index #{expected_index}... Proceeding.") return result rescue TimeoutError => _ log_info(logger, "Read did not result in a response for index #{expected_index}... Retrying send_command...") return send_command(run_loop, cmd, options, num_retries+1, write_error) end end begin Timeout::timeout(timeout, TimeoutError) do result = Core.read_response(run_loop, expected_index) end rescue TimeoutError => _ raise TimeoutError, "Time out waiting for UIAutomation run-loop for command #{cmd}. Waiting for index:#{expected_index}" end result end
stop(run_loop, out=Dir.pwd)
click to toggle source
# File lib/run_loop.rb, line 189 def self.stop(run_loop, out=Dir.pwd) return if run_loop.nil? results_dir = run_loop[:results_dir] dest = out RunLoop::Instruments.new.kill_instruments FileUtils.mkdir_p(dest) if results_dir pngs = Dir.glob(File.join(results_dir, 'Run 1', '*.png')) else pngs = [] end FileUtils.cp(pngs, dest) if pngs and pngs.length > 0 end