class RunLoop::DeviceAgent::IOSDeviceManager

@!visibility private

A wrapper around the test-control binary.

Constants

EXIT_CODES

Public Class Methods

device_agent_dir() click to toggle source

@!visibility private

# File lib/run_loop/device_agent/ios_device_manager.rb, line 24
def self.device_agent_dir
  @@device_agent_dir ||= File.expand_path(File.dirname(__FILE__))
end
ios_device_manager() click to toggle source

@!visibility private

# File lib/run_loop/device_agent/ios_device_manager.rb, line 29
      def self.ios_device_manager
        @@ios_device_manager ||= begin
          from_env = RunLoop::Environment.ios_device_manager
          if from_env
            if File.exist?(from_env)
              RunLoop.log_debug("Using IOS_DEVICE_MANAGER=#{from_env}")
              from_env
            else
              raise RuntimeError, %Q[
IOS_DEVICE_MANAGER environment variable defined:

#{from_env}

but binary does not exist at that path.
]
            end
          else
            File.join(self.device_agent_dir, "bin", "iOSDeviceManager")
          end
        end
      end
log_file() click to toggle source

@!visibility private

In earlier implementations, the ios-device-manager.log was located in ~/.run-loop/xcuitest/ios-device-manager.log

Now iOSDeviceManager logs almost everything to a fixed location.

~/.calabash/iOSDeviceManager/logs/current.log

Starting in run-loop 2.4.0, iOSDeviceManager start_test was replaced by xcodebuild test-without-building. This change causes a name conflict: there is already an xcodebuild launcher with a log file ~/.run-loop/DeviceAgent/xcodebuild.log.

The original xcodebuild launcher requires access to the DeviceAgent Xcode project which is not yet available to the public.

Using ‘current.log` seems to make sense because the file is recreated for every call to `#launch`.

# File lib/run_loop/device_agent/ios_device_manager.rb, line 90
def self.log_file
  path = File.join(LauncherStrategy.dot_dir, "current.log")
  FileUtils.touch(path) if !File.exist?(path)
  legacy_path = File.join(LauncherStrategy.dot_dir, "ios-device-manager.log")
  if File.exist?(legacy_path)
    FileUtils.rm_rf(legacy_path)
  end
  path
end

Public Instance Methods

app_installed?(bundle_identifier) click to toggle source
# File lib/run_loop/device_agent/ios_device_manager.rb, line 186
      def app_installed?(bundle_identifier)
        options = {:log_cmd => true}

        cmd = RunLoop::DeviceAgent::IOSDeviceManager.ios_device_manager

        args = [
          cmd, "is-installed", bundle_identifier, "--device-id", device.udid
        ]

        start = Time.now
        hash = run_shell_command(args, options)

        exit_status = EXIT_CODES[hash[:exit_status].to_s]
        if exit_status == :success
          true
        elsif exit_status == :false
          false
        else
          raise RuntimeError, %Q[

Could not check if app is installed:

bundle identifier: #{bundle_identifier}
           device: #{device}

iOSDeviceManager says:

#{hash[:out]}

]
        end

        RunLoop::log_debug("Took #{Time.now - start} seconds to check if app was installed");

        hash[:exit_status] == 0
      end
inspect() click to toggle source

@!visibility private

# File lib/run_loop/device_agent/ios_device_manager.rb, line 62
def inspect
  to_s
end
launch(options) click to toggle source

@!visibility private

# File lib/run_loop/device_agent/ios_device_manager.rb, line 101
      def launch(options)
        code_sign_identity = options[:code_sign_identity]
        provisioning_profile = options[:provisioning_profile]
        install_timeout = options[:device_agent_install_timeout]

        RunLoop::DeviceAgent::Frameworks.instance.install
        cmd = RunLoop::DeviceAgent::IOSDeviceManager.ios_device_manager

        start = Time.now
        if device.simulator?
          RunLoop::DeviceAgent::Xcodebuild.terminate_simulator_tests

          cbxapp = RunLoop::App.new(runner.runner)
          sim = CoreSimulator.new(device, cbxapp)

          sim.install
          sim.launch_simulator
        else
          RunLoop::DeviceAgent::Xcodebuild.terminate_device_test(device.udid)

          if !install_timeout
            raise ArgumentError, %Q[

Expected :device_agent_install_timeout key in options:

#{options}

]
          end

          shell_options = {:log_cmd => true, :timeout => install_timeout}

          args = [
            cmd, "install", runner.runner, "--device-id", device.udid
          ]

          if code_sign_identity
            args = args + ["--codesign-identity", code_sign_identity]
          end

          if provisioning_profile
            args = args + ["--profile-path", provisioning_profile]
          end

          start = Time.now
          hash = run_shell_command(args, shell_options)

          if hash[:exit_status] != 0
            raise RuntimeError, %Q[

Could not install #{runner.runner}.  iOSDeviceManager says:

#{hash[:out]}

]
          end
        end

        RunLoop::log_debug("Took #{Time.now - start} seconds to install DeviceAgent")

        cmd = "xcrun"
        args = ["xcodebuild",
                "test-without-building",
                "-xctestrun", path_to_xctestrun,
                "-destination", "id=#{device.udid}",
                "-derivedDataPath", Xcodebuild.derived_data_directory]

        log_file = IOSDeviceManager.log_file
        FileUtils.rm_rf(log_file)
        FileUtils.touch(log_file)

        env = {
          # zsh support
          "CLOBBER" => "1"
        }

        options = {:out => log_file, :err => log_file}
        RunLoop.log_unix_cmd("#{cmd} #{args.join(" ")} >& #{log_file}")

        pid = Process.spawn(env, cmd, *args, options)
        Process.detach(pid)

        pid.to_i
      end
name() click to toggle source

@!visibility private

# File lib/run_loop/device_agent/ios_device_manager.rb, line 52
def name
  :ios_device_manager
end
path_to_xctestrun() click to toggle source
# File lib/run_loop/device_agent/ios_device_manager.rb, line 223
      def path_to_xctestrun
        if device.physical_device?
          path = File.join(runner.tester, "DeviceAgent-device.xctestrun")
          if !File.exist?(path)
            raise RuntimeError, %Q[
Could not find an xctestrun file at path:

#{path}

]
          end
          path
        else
          template = path_to_xctestrun_template
          path = File.join(IOSDeviceManager.dot_dir, "DeviceAgent-simulator.xctestrun")
          contents = File.read(template).force_encoding("UTF-8")
          substituted = contents.gsub("TEST_HOST_PATH", runner.runner)
          substituted = substituted.gsub("CBX_SERVER_PORT", "#{runner.port}")
          File.open(path, "w:UTF-8") do |file|
            file.write(substituted)
          end
          path
        end
      end
path_to_xctestrun_template() click to toggle source
# File lib/run_loop/device_agent/ios_device_manager.rb, line 248
      def path_to_xctestrun_template
        if device.physical_device?
          raise(ArgumentError, "Physical devices do not require an xctestrun template")
        end

        template = File.join(runner.tester, "DeviceAgent-simulator-template.xctestrun")
        if !File.exist?(template)
          raise RuntimeError, %Q[
Could not find an xctestrun template at path:

#{template}

]
        end
        template
      end
runner() click to toggle source

@!visibility private

# File lib/run_loop/device_agent/ios_device_manager.rb, line 67
def runner
  @runner ||= RunLoop::DeviceAgent::Runner.new(device)
end
to_s() click to toggle source

@!visibility private

# File lib/run_loop/device_agent/ios_device_manager.rb, line 57
def to_s
  "#<iOSDeviceManager: #{IOSDeviceManager.ios_device_manager}>"
end