Class: RunLoop::Device

Inherits:
Object
  • Object
show all
Includes:
Shell
Defined in:
lib/run_loop/device.rb

Constant Summary collapse

SIM_STABLE_STATE_OPTIONS =

Starting in Xcode 7, iOS 9 simulators have a new “booting” state.

The simulator must completely boot before run-loop tries to do things like installing an app or clearing an app sandbox. Run-loop tries to wait for a the simulator stabilize by watching the checksum of the simulator directory and the simulator log.

On resource constrained devices or CI systems, the default settings may not work.

You can override these values if they do not work in your environment.

For cucumber users, the best place to override would be in your features/support/env.rb.

For example:

RunLoop::Device::SIM_STABLE_STATE_OPTIONS = 60

{
  # The maximum amount of time to wait for the simulator
  # to stabilize.  No errors are raised if this timeout is
  # exceeded - if the default 30 seconds has passed, the
  # simulator is probably stable enough for subsequent
  # operations.
  :timeout => RunLoop::Environment.ci? ? 240 : 120
}

Constants included from Shell

Shell::DEFAULT_OPTIONS

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Shell

run_shell_command, #run_shell_command

Methods included from Encoding

#transliterate

Constructor Details

#initialize(name, version, udid, state = nil) ⇒ Device

Create a new device.

Parameters:

  • name (String)

    The name of the device. For sims this should be ‘iPhone 5s’ and for physical devices it will be the name the user gave to the device.

  • version (String, RunLoop::Version)

    The iOS version that is running on the device. Can be a string or a Version instance.

  • udid (String)

    The device identifier.

  • state (String) (defaults to: nil)

    (nil) This a simulator only value. It refers to the Booted/Shutdown/Creating state of the simulator. For pre-Xcode 6 simulators, this value should be nil.



57
58
59
60
61
62
63
64
65
66
67
# File 'lib/run_loop/device.rb', line 57

def initialize(name, version, udid, state=nil)
  @name = name
  @udid = udid
  @state = state

  if version.is_a? String
    @version = RunLoop::Version.new version
  else
    @version = version
  end
end

Instance Attribute Details

#nameObject (readonly)

Returns the value of attribute name.



37
38
39
# File 'lib/run_loop/device.rb', line 37

def name
  @name
end

#stateObject (readonly)

Returns the value of attribute state.



40
41
42
# File 'lib/run_loop/device.rb', line 40

def state
  @state
end

#udidObject (readonly)

Returns the value of attribute udid.



39
40
41
# File 'lib/run_loop/device.rb', line 39

def udid
  @udid
end

#versionObject (readonly)

Returns the value of attribute version.



38
39
40
# File 'lib/run_loop/device.rb', line 38

def version
  @version
end

Class Method Details

.device_with_identifier(udid_or_name, options = {}) ⇒ RunLoop::Device

Returns a device given a udid or name. In the case of a physical device, the udid is the device identifier. In the case of a simulator the name is the _instruments identifier_ as reported by ‘$ xcrun instruments -s devices` - this is the identifier that can be passed to instruments.

Note that if you have a device and simulator with the same name, the simulator will always be selected.

Examples:

RunLoop::Device.device_with_identifier('iPhone 4s (8.3 Simulator'))
RunLoop::Device.device_with_identifier('6E43E3CF-25F5-41CC-A833-588F043AE749')
RunLoop::Device.device_with_identifier('denis') # Simulator or device named 'denis'
RunLoop::Device.device_with_identifier('893688959205dc7eb48d603c558ede919ad8dd0c')

Parameters:

  • udid_or_name (String)

    A name or udid that identifies the device you are looking for.

  • options (Hash) (defaults to: {})

    Allows callers to pass runtime models that might optimize performance (via memoization).

Options Hash (options):

  • :simctl (RunLoop::Simctl)

    An instance of Simctl.

  • :instruments (RunLoop::Instruments)

    An instance of Instruments.

  • :xcode (RunLoop::Xcode)

    An instance of Xcode

Returns:

Raises:

  • (ArgumentError)

    If no matching device can be found.



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/run_loop/device.rb', line 96

def self.device_with_identifier(udid_or_name, options={})
  if options.is_a?(RunLoop::SimControl)
    raise ArgumentError, %q[Support for the 'sim_control' argument has been
removed (1.5.0).  It has been replaced by an options hash with two keys:
:simctl and :instruments. Please update your sources.))]
  end

  default_options = {
    :simctl => RunLoop::Simctl.new,
    :instruments => RunLoop::Instruments.new,
    :xcode => RunLoop::Xcode.new
  }

  merged_options = default_options.merge(options)

  instruments = merged_options[:instruments]
  simctl = merged_options[:simctl]
  xcode = merged_options[:xcode]

  simulator = simctl.simulators.detect do |sim|
    sim.instruments_identifier(xcode) == udid_or_name ||
          sim.udid == udid_or_name
  end

  return simulator if !simulator.nil?

  physical_device = instruments.physical_devices.detect do |device|
    device.name == udid_or_name ||
          device.udid == udid_or_name
  end

  return physical_device if !physical_device.nil?

  raise ArgumentError, "Could not find a device with a UDID or name matching '#{udid_or_name}'"
end

Instance Method Details

#instruction_setString

Note:

Finding the instruction set of a device requires a third-party tool like ideviceinfo. Example: ‘$ ideviceinfo -u 89b59 < snip > ab7ba –key ’CPUArchitecture’ => arm64`

Return the instruction set for this device.

Simulator The simulator instruction set will be i386 or x86_64 depending on the the (marketing) name of the device.

Returns:

  • (String)

    An instruction set.

Raises:

  • (RuntimeError)

    Raises an error if this device is a physical device.



243
244
245
246
247
248
249
250
251
252
253
# File 'lib/run_loop/device.rb', line 243

def instruction_set
  if simulator?
    if ['iPhone 4s', 'iPhone 5', 'iPad 2', 'iPad Retina'].include?(self.name)
      'i386'
    else
      'x86_64'
    end
  else
    raise 'Finding the instruction set of a device requires a third-party tool like ideviceinfo'
  end
end

#instruments_identifier(xcode) ⇒ String

Returns and instruments-ready device identifier that is a suitable value for DEVICE_TARGET environment variable.

Parameters:

Returns:

  • (String)

    An instruments-ready device identifier.

Raises:

  • (RuntimeError)

    If trying to obtain a instruments-ready identifier for a simulator when Xcode < 6.



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/run_loop/device.rb', line 190

def instruments_identifier(xcode)
  if physical_device?
    udid
  else
    if version == RunLoop::Version.new('7.0.3')
      version_part = version.to_s
    else
      version_part = "#{version.major}.#{version.minor}"
    end

    if xcode.version_gte_7?
      "#{name} (#{version_part})"
    else
      "#{name} (#{version_part} Simulator)"
    end
  end
end

#physical_device?Boolean

Is this a physical device?

Returns:

  • (Boolean)

    Returns true if this is a device.



210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/run_loop/device.rb', line 210

def physical_device?
  if udid.nil?
    stack = Kernel.caller(0, 6)[0..-1].join("\n")
    raise RuntimeError,
      %Q[udid is nil

#{stack}

   name: #{name}
version: #{version}
]
  end
  !udid[DEVICE_UDID_REGEX, 0].nil?
end

#simulator?Boolean

Is this a simulator?

Returns:

  • (Boolean)

    Returns true if this is a simulator.



227
228
229
# File 'lib/run_loop/device.rb', line 227

def simulator?
  !physical_device?
end

#simulator_ensure_software_keyboard_will_showObject



505
506
507
508
# File 'lib/run_loop/device.rb', line 505

def simulator_ensure_software_keyboard_will_show
  plist = simulator_preferences_plist_path
  pbuddy.plist_set("AutomaticMinimizationEnabled", "integer", 0, plist)
end

#simulator_software_keyboard_will_show?Boolean

Returns:

  • (Boolean)


500
501
502
503
# File 'lib/run_loop/device.rb', line 500

def simulator_software_keyboard_will_show?
  plist = simulator_preferences_plist_path
  pbuddy.plist_read("AutomaticMinimizationEnabled", plist).to_i == 0
end