Class: RunLoop::Device

Inherits:
Object
  • Object
show all
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? ? 120 : 30
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

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.


53
54
55
56
57
58
59
60
61
62
63
# File 'lib/run_loop/device.rb', line 53

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


33
34
35
# File 'lib/run_loop/device.rb', line 33

def name
  @name
end

#stateObject (readonly)

Returns the value of attribute state


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

def state
  @state
end

#udidObject (readonly)

Returns the value of attribute udid


35
36
37
# File 'lib/run_loop/device.rb', line 35

def udid
  @udid
end

#versionObject (readonly)

Returns the value of attribute version


34
35
36
# File 'lib/run_loop/device.rb', line 34

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):

Returns:

Raises:

  • (ArgumentError)

    If no matching device can be found.


91
92
93
94
95
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
# File 'lib/run_loop/device.rb', line 91

def self.device_with_identifier(udid_or_name, options={})
  if options.is_a?(RunLoop::SimControl)
    RunLoop.deprecated('1.5.0', %q(
The 'sim_control' argument has been deprecated.  It has been replaced by an
options hash with two keys: :sim_control and :instruments.
Please update your sources.))
    merged_options = {
          :sim_control => options,
          :instruments => RunLoop::Instruments.new
    }
  else
    default_options = {
          :sim_control => RunLoop::SimControl.new,
          :instruments => RunLoop::Instruments.new
    }
    merged_options = default_options.merge(options)
  end

  instruments = merged_options[:instruments]
  sim_control = merged_options[:sim_control]

  xcode = sim_control.xcode
  simulator = sim_control.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.


196
197
198
199
200
201
202
203
204
205
206
# File 'lib/run_loop/device.rb', line 196

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 = SIM_CONTROL.xcode) ⇒ String

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

Parameters:

  • xcode (RunLoop::Xcode) (defaults to: SIM_CONTROL.xcode)

    The version of the active Xcode.

Returns:

  • (String)

    An instruments-ready device identifier.

Raises:

  • (RuntimeError)

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


152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/run_loop/device.rb', line 152

def instruments_identifier(xcode=SIM_CONTROL.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})"
    elsif xcode.version_gte_6?
      "#{name} (#{version_part} Simulator)"
    else
      udid
    end
  end
end

#physical_device?Boolean

Is this a physical device?

Returns:

  • (Boolean)

    Returns true if this is a device.


174
175
176
# File 'lib/run_loop/device.rb', line 174

def physical_device?
  not udid[DEVICE_UDID_REGEX, 0].nil?
end

#simulator?Boolean

Is this a simulator?

Returns:

  • (Boolean)

    Returns true if this is a simulator.


180
181
182
# File 'lib/run_loop/device.rb', line 180

def simulator?
  not physical_device?
end