├── .gitignore ├── .rubocop.yml ├── .travis.yml ├── CHANGELOG.md ├── Gemfile ├── Gemfile.lock ├── LICENSE.txt ├── README.md ├── Rakefile ├── bin ├── console └── setup ├── fourflusher.gemspec ├── lib ├── fourflusher.rb └── fourflusher │ ├── compat.rb │ ├── executable.rb │ ├── find.rb │ ├── simctl.rb │ ├── version.rb │ └── xcodebuild.rb └── spec ├── find_spec.rb ├── fixtures ├── simctl.json ├── simctl_bad.json ├── simctl_small.json ├── simctl_with_unavailable.json ├── simctl_xcode_10.1.json ├── simctl_xcode_10.2.json └── simctl_xcode_11.0.json ├── fixtures_spec.rb ├── sort_spec.rb └── unit_spec.rb /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /_yardoc/ 4 | /coverage/ 5 | /doc/ 6 | /pkg/ 7 | /spec/reports/ 8 | /tmp/ 9 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | Metrics/AbcSize: 2 | Max: 35 3 | 4 | Metrics/CyclomaticComplexity: 5 | Max: 10 6 | 7 | Metrics/LineLength: 8 | Max: 105 9 | 10 | Metrics/MethodLength: 11 | Max: 30 12 | 13 | Style/AsciiComments: 14 | Exclude: 15 | - 'lib/fourflusher/executable.rb' 16 | 17 | Style/ClassVars: 18 | Exclude: 19 | - 'lib/fourflusher/find.rb' 20 | 21 | Style/Documentation: 22 | Exclude: 23 | - 'spec/**/*' 24 | - 'test/**/*' 25 | - 'lib/fourflusher/version.rb' 26 | - 'lib/fourflusher/compat.rb' 27 | 28 | Lint/Void: 29 | Exclude: 30 | - 'spec/unit_spec.rb' 31 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | rvm: 3 | - 2.0.0-p648 4 | - 2.5.1 5 | cache: bundler 6 | before_install: gem install bundler -v "~> 1.17" 7 | script: 8 | - bundle exec rake 9 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | ## Master 3 | 4 | ##### Enhancements 5 | 6 | * None. 7 | 8 | ##### Bug Fixes 9 | 10 | * Fix handling of extraneous output in simctl list. 11 | [Dimitris Koutsogiorgas](https://github.com/dnkoutso) 12 | [#27](https://github.com/CocoaPods/fourflusher/pull/27) 13 | 14 | 15 | ## 2.3.1 (2019-06-18) 16 | 17 | ##### Enhancements 18 | 19 | * None. 20 | 21 | ##### Bug Fixes 22 | 23 | * Fixed crash with very long devices list/slow computers. 24 | [Martin Fiebig](https://github.com/mfiebig) 25 | [#17](https://github.com/CocoaPods/fourflusher/issues/17) 26 | 27 | 28 | ## 2.3.0 (2019-06-05) 29 | 30 | ##### Enhancements 31 | 32 | * Update simctl interface for Xcode 11. 33 | [Colin Humber](https://github.com/colinhumber) 34 | [#22](https://github.com/CocoaPods/fourflusher/pull/22) 35 | 36 | ##### Bug Fixes 37 | 38 | * None. 39 | 40 | 41 | ## 2.2.0 (2019-01-28) 42 | 43 | ##### Enhancements 44 | 45 | * Update simctl interface for Xcode 10.2. 46 | [Jeff Kelley](https://github.com/SlaunchaMan) 47 | [CocoaPods#8458](https://github.com/CocoaPods/CocoaPods/issues/8458) 48 | 49 | ##### Bug Fixes 50 | 51 | * None. 52 | 53 | 54 | ## 2.1.0 (2018-10-17) 55 | 56 | ##### Enhancements 57 | 58 | * Support Xcode 10.1. 59 | 60 | ##### Bug Fixes 61 | 62 | * None. 63 | 64 | 65 | ## 2.0.1 (2016-10-16) 66 | 67 | ##### Enhancements 68 | 69 | * None. 70 | 71 | ##### Bug Fixes 72 | 73 | * Fixed crash with simulators comparison, when device model is undefined 74 | [Roman Truba](https://github.com/dreddik) 75 | [#9](https://github.com/CocoaPods/fourflusher/pull/9) 76 | 77 | 78 | ## v2.0.0 (2016-10-02) 79 | 80 | ##### Breaking 81 | 82 | * Use JSON output from `xcrun simctl list`. Drop support for Xcode 6 (doesn't support JSON output) 83 | [Ben Asher](https://github.com/benasher44) 84 | [#6](https://github.com/CocoaPods/fourflusher/pull/6) 85 | 86 | ##### Enhancements 87 | 88 | * Update simulator count for Travis 89 | [Boris Bügling](https://github.com/neonichu) 90 | [#5](https://github.com/CocoaPods/fourflusher/pull/5) 91 | 92 | * A more helpful error message for missing simulators 93 | [Radek Pietruszewski](https://github.com/radex) 94 | [#4](https://github.com/CocoaPods/fourflusher/pull/4) 95 | 96 | ##### Bug Fixes 97 | 98 | * None 99 | 100 | ## v1.0.1 (2016-06-25) 101 | 102 | ##### Enhancements 103 | 104 | * Show better error for `:oldest` simulator search 105 | [Boris Bügling](https://github.com/neonichu) 106 | 107 | ## v1.0.0 (2016-06-24) 108 | 109 | ##### Enhancements 110 | 111 | * Improve finding simulators 112 | [Boris Bügling](https://github.com/neonichu) 113 | 114 | ## v0.3.2 (2016-06-16) 115 | 116 | ##### Enhancements 117 | 118 | * Support for parsing iOS 10.0 and tvOS 10.0 119 | [Boris Bügling](https://github.com/neonichu) 120 | 121 | ##### Bug Fixes 122 | 123 | * Rubocop fixes 124 | [Boris Bügling](https://github.com/neonichu) 125 | 126 | ## v0.3.1 (2016-05-30) 127 | 128 | ##### Enhancements 129 | 130 | * Travis CI improvements 131 | [Boris Bügling](https://github.com/neonichu) 132 | [#1](https://github.com/CocoaPods/fourflusher/pull/1) 133 | 134 | * Handle missing Xcode more gracefully 135 | [Boris Bügling](https://github.com/neonichu) 136 | 137 | ## v0.3.0 (2015-12-29) 138 | 139 | ##### Enhancements 140 | 141 | * Allow specifying constraints for `destination()` 142 | [Boris Bügling](https://github.com/neonichu) 143 | 144 | ## v0.2.0 (2015-12-29) 145 | 146 | ##### Enhancements 147 | 148 | * Allow constraining simulators by OS version 149 | [Boris Bügling](https://github.com/neonichu) 150 | 151 | ## v0.1.0 (2015-12-18) 152 | 153 | * List usable simulators. Find simulators by name. Get the destination setting for the simulator to pass to Xcodebuild 154 | [Boris Bügling](https://github.com/neonichu) 155 | 156 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gemspec 4 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: . 3 | specs: 4 | fourflusher (2.3.1) 5 | 6 | GEM 7 | remote: https://rubygems.org/ 8 | specs: 9 | ast (2.3.0) 10 | astrolabe (1.3.1) 11 | parser (~> 2.2) 12 | diff-lcs (1.2.5) 13 | parser (2.3.1.4) 14 | ast (~> 2.2) 15 | powerpack (0.1.1) 16 | rainbow (2.1.0) 17 | rake (10.5.0) 18 | rspec (2.99.0) 19 | rspec-core (~> 2.99.0) 20 | rspec-expectations (~> 2.99.0) 21 | rspec-mocks (~> 2.99.0) 22 | rspec-core (2.99.2) 23 | rspec-expectations (2.99.2) 24 | diff-lcs (>= 1.1.3, < 2.0) 25 | rspec-mocks (2.99.4) 26 | rubocop (0.35.1) 27 | astrolabe (~> 1.3) 28 | parser (>= 2.2.3.0, < 3.0) 29 | powerpack (~> 0.1) 30 | rainbow (>= 1.99.1, < 3.0) 31 | ruby-progressbar (~> 1.7) 32 | tins (<= 1.6.0) 33 | ruby-progressbar (1.8.1) 34 | tins (1.6.0) 35 | 36 | PLATFORMS 37 | ruby 38 | 39 | DEPENDENCIES 40 | bundler (~> 1.11) 41 | fourflusher! 42 | rake (~> 10.0) 43 | rspec (~> 2) 44 | rubocop (~> 0.35.0) 45 | 46 | BUNDLED WITH 47 | 1.17.3 48 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Boris Bügling 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # four-flusher 2 | 3 | A library for interacting with Xcode simulators. 4 | 5 | ## Installation 6 | 7 | Add this line to your application's Gemfile: 8 | 9 | ```ruby 10 | gem 'fourflusher' 11 | ``` 12 | 13 | And then execute: 14 | 15 | $ bundle 16 | 17 | Or install it yourself as: 18 | 19 | $ gem install fourflusher 20 | 21 | ## Development 22 | 23 | After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment. 24 | 25 | To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). 26 | 27 | ## Contributing 28 | 29 | Bug reports and pull requests are welcome on GitHub at https://github.com/CocoaPods/fourflusher. 30 | 31 | ## License 32 | 33 | The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT). 34 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler/gem_tasks' 2 | 3 | require 'rspec/core/rake_task' 4 | RSpec::Core::RakeTask.new 5 | 6 | require 'rubocop/rake_task' 7 | RuboCop::RakeTask.new(:rubocop) 8 | 9 | task default: [:spec, :rubocop] 10 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'bundler/setup' 4 | require 'fourflusher' 5 | 6 | # You can add fixtures and/or initialization code here to make experimenting 7 | # with your gem easier. You can also use a different console, if you like. 8 | 9 | # (If you use this, don't forget to add pry to your Gemfile!) 10 | # require "pry" 11 | # Pry.start 12 | 13 | require 'irb' 14 | IRB.start 15 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | set -vx 5 | 6 | bundle install 7 | 8 | # Do any other automated setup that you need to do here 9 | -------------------------------------------------------------------------------- /fourflusher.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'fourflusher/version' 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = 'fourflusher' 8 | spec.version = Fourflusher::VERSION 9 | spec.authors = ['Boris Bügling'] 10 | spec.email = ['boris@icculus.org'] 11 | 12 | spec.summary = 'A library for interacting with Xcode simulators.' 13 | spec.homepage = 'https://github.com/neonichu/fourflusher' 14 | spec.license = 'MIT' 15 | 16 | spec.files = `git ls-files -z`.split("\x0").reject { |f| 17 | f.match(%r{^(test|spec|features)/}) 18 | } 19 | spec.bindir = 'exe' 20 | spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } 21 | spec.require_paths = ['lib'] 22 | 23 | spec.add_development_dependency 'bundler', '~> 1.11' 24 | spec.add_development_dependency 'rake', '~> 10.0' 25 | spec.add_development_dependency 'rspec', '~> 2' 26 | spec.add_development_dependency 'rubocop', '~> 0.35.0' 27 | end 28 | -------------------------------------------------------------------------------- /lib/fourflusher.rb: -------------------------------------------------------------------------------- 1 | require 'fourflusher/find' 2 | require 'fourflusher/version' 3 | require 'fourflusher/xcodebuild' 4 | -------------------------------------------------------------------------------- /lib/fourflusher/compat.rb: -------------------------------------------------------------------------------- 1 | module Fourflusher 2 | class Config 3 | def self.instance 4 | @instance || new 5 | end 6 | 7 | def verbose? 8 | false 9 | end 10 | end 11 | 12 | class Informative < StandardError 13 | end 14 | 15 | class UI 16 | def self.indentation_level 17 | 0 18 | end 19 | 20 | def self.message(message) 21 | print(message) 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /lib/fourflusher/executable.rb: -------------------------------------------------------------------------------- 1 | require 'fourflusher/compat' 2 | 3 | # This file is a verbatim copy from CocoaPods, a project licensed under the MIT license. 4 | 5 | # Copyright (c) 2011 - 2015 Eloy Durán , 6 | # Fabio Pelosin , 7 | # Samuel Giddins , 8 | # Marius Rackwitz , 9 | # Kyle Fuller , 10 | # Boris Bügling , 11 | # Orta Therox , and 12 | # Olivier Halligon . 13 | 14 | # Permission is hereby granted, free of charge, to any person obtaining a copy 15 | # of this software and associated documentation files (the "Software"), to deal 16 | # in the Software without restriction, including without limitation the rights 17 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | # copies of the Software, and to permit persons to whom the Software is 19 | # furnished to do so, subject to the following conditions: 20 | 21 | # The above copyright notice and this permission notice shall be included in 22 | # all copies or substantial portions of the Software. 23 | 24 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 30 | # THE SOFTWARE. 31 | 32 | module Fourflusher 33 | # Module which provides support for running executables. 34 | # 35 | # In a class it can be used as: 36 | # 37 | # extend Executable 38 | # executable :git 39 | # 40 | # This will create two methods `git` and `git!` both accept a command but 41 | # the later will raise on non successful executions. The methods return the 42 | # output of the command. 43 | # 44 | module Executable 45 | # Creates the methods for the executable with the given name. 46 | # 47 | # @param [Symbol] name 48 | # the name of the executable. 49 | # 50 | # @return [void] 51 | # 52 | def executable(name) 53 | define_method(name) do |*command| 54 | Executable.execute_command(name, Array(command).flatten, false) 55 | end 56 | 57 | define_method(name.to_s + '!') do |*command| 58 | Executable.execute_command(name, Array(command).flatten, true) 59 | end 60 | end 61 | 62 | # Executes the given command displaying it if in verbose mode. 63 | # 64 | # @param [String] bin 65 | # The binary to use. 66 | # 67 | # @param [Array<#to_s>] command 68 | # The command to send to the binary. 69 | # 70 | # @param [Bool] raise_on_failure 71 | # Whether it should raise if the command fails. 72 | # 73 | # @raise If the executable could not be located. 74 | # 75 | # @raise If the command fails and the `raise_on_failure` is set to true. 76 | # 77 | # @return [String] the output of the command (STDOUT and STDERR). 78 | # 79 | def self.execute_command(executable, command, raise_on_failure = true) 80 | bin = which(executable) 81 | fail Fourflusher::Informative, "Unable to locate the executable `#{executable}`" unless bin 82 | 83 | command = command.map(&:to_s) 84 | full_command = "#{bin} #{command.join(' ')}" 85 | 86 | if Config.instance.verbose? 87 | UI.message("$ #{full_command}") 88 | stdout = Indenter.new(STDOUT) 89 | stderr = Indenter.new(STDERR) 90 | else 91 | stdout = Indenter.new 92 | stderr = Indenter.new 93 | end 94 | 95 | status = popen3(bin, command, stdout, stderr) 96 | stdout = stdout.join 97 | stderr = stderr.join 98 | output = stdout + stderr 99 | unless status.success? 100 | if raise_on_failure 101 | fail Fourflusher::Informative, "#{full_command}\n\n#{output}" 102 | else 103 | UI.message("[!] Failed: #{full_command}".red) 104 | end 105 | end 106 | 107 | output 108 | end 109 | 110 | # Returns the absolute path to the binary with the given name on the current 111 | # `PATH`, or `nil` if none is found. 112 | # 113 | # @param [String] program 114 | # The name of the program being searched for. 115 | # 116 | # @return [String,Nil] The absolute path to the given program, or `nil` if 117 | # it wasn't found in the current `PATH`. 118 | # 119 | def self.which(program) 120 | program = program.to_s 121 | ENV['PATH'].split(File::PATH_SEPARATOR).each do |path| 122 | bin = File.expand_path(program, path) 123 | return bin if File.file?(bin) && File.executable?(bin) 124 | end 125 | nil 126 | end 127 | 128 | # Runs the given command, capturing the desired output. 129 | # 130 | # @param [String] bin 131 | # The binary to use. 132 | # 133 | # @param [Array<#to_s>] command 134 | # The command to send to the binary. 135 | # 136 | # @param [Symbol] capture 137 | # Whether it should raise if the command fails. 138 | # 139 | # @raise If the executable could not be located. 140 | # 141 | # @return [(String, Process::Status)] 142 | # The desired captured output from the command, and the status from 143 | # running the command. 144 | # 145 | def self.capture_command(executable, command, capture: :merge) 146 | bin = which(executable) 147 | fail Fourflusher::Informative, "Unable to locate the executable `#{executable}`" unless bin 148 | 149 | require 'open3' 150 | command = command.map(&:to_s) 151 | case capture 152 | when :merge then Open3.capture2e(bin, *command) 153 | when :both then Open3.capture3(bin, *command) 154 | when :out then Open3.capture2(bin, *command) 155 | when :err then Open3.capture3(bin, *command).drop(1) 156 | when :none then Open3.capture2(bin, *command).last 157 | end 158 | end 159 | 160 | private 161 | 162 | def self.popen3(bin, command, stdout, stderr) 163 | require 'open3' 164 | Open3.popen3(bin, *command) do |i, o, e, t| 165 | stdout_thread = reader(o, stdout) 166 | stderr_thread = reader(e, stderr) 167 | i.close 168 | 169 | status = t.value 170 | 171 | o.flush 172 | e.flush 173 | 174 | # wait for both threads to process the streams 175 | stdout_thread.join 176 | stderr_thread.join 177 | 178 | status 179 | end 180 | end 181 | 182 | def self.reader(input, output) 183 | Thread.new do 184 | buf = '' 185 | begin 186 | loop do 187 | buf << input.readpartial(4096) 188 | loop do 189 | string, separator, buf = buf.partition(/[\r\n]/) 190 | if separator.empty? 191 | buf = string 192 | break 193 | end 194 | output << (string << separator) 195 | end 196 | end 197 | rescue EOFError 198 | output << (buf << $INPUT_RECORD_SEPARATOR) unless buf.empty? 199 | end 200 | end 201 | end 202 | 203 | #-------------------------------------------------------------------------# 204 | 205 | # Helper class that allows to write to an {IO} instance taking into account 206 | # the UI indentation level. 207 | # 208 | class Indenter < ::Array 209 | # @return [Fixnum] The indentation level of the UI. 210 | # 211 | attr_accessor :indent 212 | 213 | # @return [IO] the {IO} to which the output should be printed. 214 | # 215 | attr_accessor :io 216 | 217 | # Init a new Indenter 218 | # 219 | # @param [IO] io @see io 220 | # 221 | def initialize(io = nil) 222 | @io = io 223 | @indent = ' ' * UI.indentation_level 224 | end 225 | 226 | # Stores a portion of the output and prints it to the {IO} instance. 227 | # 228 | # @param [String] value 229 | # the output to print. 230 | # 231 | # @return [void] 232 | # 233 | def <<(value) 234 | super 235 | io << "#{indent}#{value}" if io 236 | end 237 | end 238 | end 239 | end 240 | -------------------------------------------------------------------------------- /lib/fourflusher/find.rb: -------------------------------------------------------------------------------- 1 | require 'fourflusher/simctl' 2 | require 'json' 3 | require 'rubygems/version' 4 | 5 | module Fourflusher 6 | # Metadata about an installed Xcode simulator 7 | class Simulator 8 | attr_reader :id 9 | attr_reader :name 10 | attr_reader :os_version 11 | 12 | def os_name 13 | @os_name.downcase.to_sym 14 | end 15 | 16 | def compatible?(other_version) 17 | other_version <= os_version 18 | end 19 | 20 | def to_s 21 | "#{@name} (#{@id}) - #{@os_name} #{@os_version}" 22 | end 23 | 24 | # Compare function for sorting simulators in order by 25 | # - OS Name: ascending 26 | # - OS Version: descending 27 | # - Device type: iPhone first, then ascending 28 | # - Model: ascending 29 | def sim_list_compare(other) 30 | return os_name.to_s <=> other.os_name.to_s unless os_name == other.os_name 31 | return other.os_version <=> os_version unless os_version == other.os_version 32 | device1, model1 = device_and_model 33 | device2, model2 = other.device_and_model 34 | return device_compare(device1, device2) unless device1 == device2 35 | return model1 <=> model2 unless model1.nil? || model2.nil? 36 | model2.nil? ? 1 : -1 37 | end 38 | 39 | def device_compare(my_device, other_device) 40 | return -1 if my_device == 'iPhone' 41 | return 1 if other_device == 'iPhone' 42 | return my_device <=> other_device unless my_device.nil? || other_device.nil? 43 | other_device.nil? ? 1 : -1 44 | end 45 | 46 | # Returns the [device, model] for use during sorting 47 | # Examples: [iPhone, 5s], [iPhone, 6s Plus], [Apple Watch Series 2, 38mm] 48 | def device_and_model 49 | if os_name == :watchos 50 | # Sample string: Apple Watch Series 2 - 38mm 51 | name.split ' - ' 52 | else 53 | # Sample string: "iPhone 5s" or "iPhone 6 Plus" or "iPad Air 2" 54 | if name.start_with? 'Apple TV' 55 | # The last part is the model, and the rest is the device 56 | parts = name.rpartition(' ').reject { |str| str.strip.empty? } 57 | [parts[0...-1].join(' '), parts.drop(parts.count - 1).join(' ')].map(&:strip) 58 | else 59 | # The first part is device, and the rest is the model 60 | name.split ' ', 2 61 | end 62 | end 63 | end 64 | 65 | private 66 | 67 | def initialize(device_json, os_name, os_version) 68 | @id = device_json['udid'] 69 | @name = device_json['name'] 70 | @os_name = os_name 71 | @os_version = Gem::Version.new os_version 72 | end 73 | end 74 | 75 | # { 76 | # "devices" : { 77 | # "iOS 10.0" : [ 78 | # { 79 | # "state" : "Shutdown", 80 | # "availability" : "(available)", 81 | # "name" : "iPhone 5", 82 | # "udid" : "B7D21008-CC16-47D6-A9A9-885FE1FC47A8" 83 | # }, 84 | # { 85 | # "state" : "Shutdown", 86 | # "availability" : "(available)", 87 | # "name" : "iPhone 5s", 88 | # "udid" : "38EAE7BD-90C3-4C3D-A672-3AF683EEC5A2" 89 | # }, 90 | # ] 91 | # } 92 | # } 93 | 94 | # Executes `simctl` commands 95 | class SimControl 96 | LINES_TO_REMOVE = [ 97 | 'Install Started', 98 | 'Install Succeeded', 99 | 'Install Failed', 100 | 'apply_selection_policy_once: prefer use of removable GPUs' 101 | ].freeze 102 | 103 | def simulator(filter, os_name = :ios, minimum_version = '1.0') 104 | usable_simulators(filter, os_name, minimum_version).first 105 | end 106 | 107 | def usable_simulators(filter = nil, os = :ios, minimum_version = '1.0') 108 | sims = fetch_sims 109 | oses = sims.map(&:os_name).uniq 110 | os = os.downcase.to_sym 111 | 112 | unless oses.include?(os) 113 | fail "Could not find a `#{os}` simulator (valid values: #{oses.join(', ')}). Ensure that "\ 114 | "Xcode -> Window -> Devices has at least one `#{os}` simulator listed or otherwise add one." 115 | end 116 | 117 | return sims if filter.nil? 118 | minimum_version = Gem::Version.new(minimum_version) 119 | sims = sims.select { |sim| sim.os_name == os && sim.compatible?(minimum_version) } 120 | 121 | return [sims.min_by(&:os_version)] if filter == :oldest 122 | 123 | found_sims = sims.select { |sim| sim.name == filter } 124 | return found_sims if found_sims.count > 0 125 | sims.select { |sim| sim.name.start_with?(filter) } 126 | end 127 | 128 | private 129 | 130 | # Gets the simulators and transforms the simctl json into Simulator objects 131 | def fetch_sims 132 | raw_list = list(['-j', 'devices']) 133 | regex_union = Regexp.union(LINES_TO_REMOVE) 134 | filtered_raw_list = raw_list.each_line.reject { |l| l =~ regex_union }.join 135 | 136 | device_list = JSON.parse(filtered_raw_list)['devices'] 137 | unless device_list.is_a?(Hash) 138 | msg = "Expected devices to be of type Hash but instated found #{device_list.class}" 139 | fail Fourflusher::Informative, msg 140 | end 141 | device_list.flat_map do |runtime_str, devices| 142 | # This format changed with Xcode 10.2. 143 | if runtime_str.start_with?('com.apple.CoreSimulator.SimRuntime.') 144 | # Sample string: com.apple.CoreSimulator.SimRuntime.iOS-12-2 145 | _unused, os_info = runtime_str.split 'com.apple.CoreSimulator.SimRuntime.' 146 | os_name, os_major_version, os_minor_version = os_info.split '-' 147 | os_version = "#{os_major_version}.#{os_minor_version}" 148 | else 149 | # Sample string: iOS 9.3 150 | os_name, os_version = runtime_str.split ' ' 151 | end 152 | 153 | devices.map do |device| 154 | device_is_available = device['isAvailable'] == 'YES' || device['isAvailable'] == true 155 | 156 | if device['availability'] == '(available)' || device_is_available 157 | Simulator.new(device, os_name, os_version) 158 | end 159 | end 160 | end.compact.sort(&:sim_list_compare) 161 | end 162 | end 163 | end 164 | -------------------------------------------------------------------------------- /lib/fourflusher/simctl.rb: -------------------------------------------------------------------------------- 1 | require 'fourflusher/executable' 2 | 3 | module Fourflusher 4 | # Executes `simctl` commands 5 | class SimControl 6 | extend Executable 7 | executable :xcrun 8 | 9 | def list(args) 10 | simctl!(['list'] + args) 11 | end 12 | 13 | private 14 | 15 | def simctl!(args) 16 | xcrun!(['simctl'] + args) 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /lib/fourflusher/version.rb: -------------------------------------------------------------------------------- 1 | module Fourflusher 2 | VERSION = '2.3.1' 3 | end 4 | -------------------------------------------------------------------------------- /lib/fourflusher/xcodebuild.rb: -------------------------------------------------------------------------------- 1 | require 'fourflusher/find' 2 | 3 | module Fourflusher 4 | # Executes `simctl` commands 5 | class SimControl 6 | def destination(filter, os = :ios, minimum_version = '1.0') 7 | sim = simulator(filter, os, minimum_version) 8 | filter = "for #{os} #{minimum_version}" if filter == :oldest 9 | fail "Simulator #{filter} is not available." if sim.nil? 10 | ['-destination', "id=#{sim.id}"] 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /spec/find_spec.rb: -------------------------------------------------------------------------------- 1 | require 'fourflusher' 2 | 3 | describe Fourflusher::SimControl do 4 | let(:simctl) { Fourflusher::SimControl.new } 5 | 6 | let(:simctl_json_file) { 'spec/fixtures/simctl.json' } 7 | before do 8 | simctl.stub(:list).and_return(File.read(simctl_json_file)) 9 | end 10 | 11 | describe 'finding simulators' do 12 | it 'can list all usable simulators' do 13 | sims = simctl.usable_simulators 14 | os_names = sims.map(&:os_name).uniq.sort 15 | 16 | # This check is silly, but I am too lazy to come up with sth better 17 | expect(sims.count).to eq 108 # from the fixture 18 | expect(sims.first.name).to eq 'iPhone 5' 19 | expect(sims.first.os_name).to eq :ios 20 | expect(sims.last.name).to eq 'Apple Watch - 42mm' 21 | expect(sims.last.os_name).to eq :watchos 22 | expect(os_names).to eq [:ios, :tvos, :watchos] 23 | end 24 | 25 | it 'can find a specific simulator' do 26 | sim = simctl.simulator('iPhone 6s') 27 | 28 | expect(sim.name).to eq 'iPhone 6s' 29 | end 30 | 31 | it 'can find a specific simulator for a minimum iOS version' do 32 | sim = simctl.simulator('iPhone 6s', :ios, '9.3') 33 | 34 | expect(sim.name).to eq 'iPhone 6s' 35 | end 36 | 37 | it 'will fail if the minimum iOS version cannot be satisfied' do 38 | sim = simctl.simulator('iPhone 6s', :ios, '11.0') 39 | 40 | expect(sim).to eq nil 41 | end 42 | 43 | it 'can find the oldest available simulator' do 44 | sim = simctl.simulator(:oldest) 45 | 46 | expect(sim.name).to eq 'iPhone 4s' 47 | end 48 | 49 | it 'can find available simulators by prefix' do 50 | sim = simctl.simulator('iPhone') 51 | 52 | expect(sim.name).to eq 'iPhone 5' 53 | end 54 | 55 | it 'can find the oldest available simulator for a minimum iOS version' do 56 | sim = simctl.simulator(:oldest, :ios, '9.3') 57 | 58 | expect(sim.name).to eq 'iPhone 4s' 59 | end 60 | 61 | it 'will fail if the minimum iOS version cannot be satisfied by the oldest simulator' do 62 | sim = simctl.simulator(:oldest, :ios, '11.0') 63 | 64 | expect(sim).to eq nil 65 | end 66 | 67 | it 'can find the oldest available watchOS simulator' do 68 | sim = simctl.simulator(:oldest, :watchos) 69 | 70 | expect(sim.name).to eq 'Apple Watch - 38mm' 71 | end 72 | end 73 | 74 | describe 'finding simulators with the Xcode 10.1 format' do 75 | let(:simctl_json_file) { 'spec/fixtures/simctl_xcode_10.1.json' } 76 | 77 | it 'can find simulators using the Xcode 10.1 format' do 78 | sim = simctl.simulator('iPhone X') 79 | expect(sim.name).to eq 'iPhone X' 80 | end 81 | end 82 | 83 | describe 'finding simulators with the Xcode 10.2 format' do 84 | let(:simctl_json_file) { 'spec/fixtures/simctl_xcode_10.2.json' } 85 | 86 | it 'can find simulators using the Xcode 10.2 format' do 87 | sim = simctl.simulator('iPhone X') 88 | expect(sim.name).to eq 'iPhone X' 89 | end 90 | end 91 | 92 | describe 'finding simulators with the Xcode 11.0 format' do 93 | let(:simctl_json_file) { 'spec/fixtures/simctl_xcode_11.0.json' } 94 | 95 | it 'can find simulators using the Xcode 11.0 format' do 96 | sim = simctl.simulator('iPhone X') 97 | expect(sim.name).to eq 'iPhone X' 98 | end 99 | end 100 | 101 | describe 'finding simulators with extraneous bad output' do 102 | let(:simctl_json_file) { 'spec/fixtures/simctl_bad.json' } 103 | 104 | it 'can find a specific simulator' do 105 | sim = simctl.simulator('iPhone 4s') 106 | expect(sim.name).to eq 'iPhone 4s' 107 | end 108 | end 109 | end 110 | -------------------------------------------------------------------------------- /spec/fixtures/simctl.json: -------------------------------------------------------------------------------- 1 | { 2 | "devices" : { 3 | "iOS 8.1" : [ 4 | { 5 | "state" : "Shutdown", 6 | "availability" : "(available)", 7 | "name" : "iPhone 4s", 8 | "udid" : "F86F61DF-60B0-4EAE-8A62-D2CB78708066" 9 | }, 10 | { 11 | "state" : "Shutdown", 12 | "availability" : "(available)", 13 | "name" : "iPhone 5", 14 | "udid" : "FDE9A448-6BFB-48D9-B2C9-0D80EA0705E1" 15 | }, 16 | { 17 | "state" : "Shutdown", 18 | "availability" : "(available)", 19 | "name" : "iPhone 5s", 20 | "udid" : "CE3907EC-46F6-4BED-A37D-393F820A746F" 21 | }, 22 | { 23 | "state" : "Shutdown", 24 | "availability" : "(available)", 25 | "name" : "iPhone 6", 26 | "udid" : "4C816B5D-B781-4F32-9F08-5FB2A0442B8F" 27 | }, 28 | { 29 | "state" : "Shutdown", 30 | "availability" : "(available)", 31 | "name" : "iPhone 6 Plus", 32 | "udid" : "B064B7AA-E60C-44A8-88DA-E3A22E6BA314" 33 | }, 34 | { 35 | "state" : "Shutdown", 36 | "availability" : "(available)", 37 | "name" : "iPad 2", 38 | "udid" : "9B6D5371-612F-4485-AFCD-B0AE089EA454" 39 | }, 40 | { 41 | "state" : "Shutdown", 42 | "availability" : "(available)", 43 | "name" : "iPad Retina", 44 | "udid" : "94CC76BE-A3FB-41AF-AB05-21EEA55E72CF" 45 | }, 46 | { 47 | "state" : "Shutdown", 48 | "availability" : "(available)", 49 | "name" : "iPad Air", 50 | "udid" : "62C1BA28-96C6-483F-B6AF-5BDFAC7E34DC" 51 | } 52 | ], 53 | "iOS 10.0" : [ 54 | { 55 | "state" : "Shutdown", 56 | "availability" : "(available)", 57 | "name" : "iPhone 5", 58 | "udid" : "872DB32B-E22D-4F31-A6C1-606F2B5EE2A1" 59 | }, 60 | { 61 | "state" : "Shutdown", 62 | "availability" : "(available)", 63 | "name" : "iPhone 5s", 64 | "udid" : "0CD964DF-5EC9-438D-9937-24FB9D9C266B" 65 | }, 66 | { 67 | "state" : "Shutdown", 68 | "availability" : "(available)", 69 | "name" : "iPhone 6", 70 | "udid" : "237D7619-4A4E-4624-8925-67A42A8A690A" 71 | }, 72 | { 73 | "state" : "Shutdown", 74 | "availability" : "(available)", 75 | "name" : "iPhone 6 Plus", 76 | "udid" : "7453E43C-6352-44AA-8BE0-2E09643F5F88" 77 | }, 78 | { 79 | "state" : "Shutdown", 80 | "availability" : "(available)", 81 | "name" : "iPhone 6s", 82 | "udid" : "9793E592-F0FF-4C4A-BEEF-FDD50A67E8C1" 83 | }, 84 | { 85 | "state" : "Shutdown", 86 | "availability" : "(available)", 87 | "name" : "iPhone 6s Plus", 88 | "udid" : "64DF30D4-4118-480F-9ADD-DCC32194B63D" 89 | }, 90 | { 91 | "state" : "Shutdown", 92 | "availability" : "(available)", 93 | "name" : "iPhone 7", 94 | "udid" : "5F911B30-5F23-403B-9697-1DFDC24773C8" 95 | }, 96 | { 97 | "state" : "Shutdown", 98 | "availability" : "(available)", 99 | "name" : "iPhone 7 Plus", 100 | "udid" : "E3B7D09E-DD71-4DAA-9D1D-6B678487D646" 101 | }, 102 | { 103 | "state" : "Shutdown", 104 | "availability" : "(available)", 105 | "name" : "iPhone SE", 106 | "udid" : "1A6EAD45-0A28-421A-A6D4-AD0866464FAA" 107 | }, 108 | { 109 | "state" : "Shutdown", 110 | "availability" : "(available)", 111 | "name" : "iPad Retina", 112 | "udid" : "2CB7C124-E268-4E00-9FBF-598C1003ABDC" 113 | }, 114 | { 115 | "state" : "Shutdown", 116 | "availability" : "(available)", 117 | "name" : "iPad Air", 118 | "udid" : "C08A3293-272A-4D95-9ECC-288D9A0C171A" 119 | }, 120 | { 121 | "state" : "Shutdown", 122 | "availability" : "(available)", 123 | "name" : "iPad Air 2", 124 | "udid" : "845F97F9-26FE-42AC-9412-EB6DBEEF78E9" 125 | }, 126 | { 127 | "state" : "Shutdown", 128 | "availability" : "(available)", 129 | "name" : "iPad Pro (9.7 inch)", 130 | "udid" : "0B89526F-FE59-4253-B5C8-5F59F48F4AE6" 131 | }, 132 | { 133 | "state" : "Shutdown", 134 | "availability" : "(available)", 135 | "name" : "iPad Pro (12.9 inch)", 136 | "udid" : "5F8F269D-E643-4E87-915D-12B7D49ED08D" 137 | }, 138 | { 139 | "state" : "Shutdown", 140 | "availability" : "(available)", 141 | "name" : "iPad", 142 | "udid" : "18B5770F-3C49-480E-BEC9-A6748612EBD3" 143 | } 144 | ], 145 | "watchOS 2.2" : [ 146 | { 147 | "state" : "Shutdown", 148 | "availability" : "(available)", 149 | "name" : "Apple Watch - 38mm", 150 | "udid" : "0ACDF8F4-1968-43C3-830F-D614E7138288" 151 | }, 152 | { 153 | "state" : "Shutdown", 154 | "availability" : "(available)", 155 | "name" : "Apple Watch - 42mm", 156 | "udid" : "4E651A7A-AB0B-445D-BD19-60E67536D0B8" 157 | } 158 | ], 159 | "iOS 9.0" : [ 160 | { 161 | "state" : "Shutdown", 162 | "availability" : "(available)", 163 | "name" : "iPhone 4s", 164 | "udid" : "84F3616D-0AB5-41EE-A499-89211620898F" 165 | }, 166 | { 167 | "state" : "Shutdown", 168 | "availability" : "(available)", 169 | "name" : "iPhone 5", 170 | "udid" : "19C842D1-57D0-407D-AA85-F373FB4D672A" 171 | }, 172 | { 173 | "state" : "Shutdown", 174 | "availability" : "(available)", 175 | "name" : "iPhone 5s", 176 | "udid" : "E8ABD8EA-CF53-4A2A-9C91-2760EFAF631D" 177 | }, 178 | { 179 | "state" : "Shutdown", 180 | "availability" : "(available)", 181 | "name" : "iPhone 6", 182 | "udid" : "4DFC7897-D8A4-45B3-80B2-44C854B3AD16" 183 | }, 184 | { 185 | "state" : "Shutdown", 186 | "availability" : "(available)", 187 | "name" : "iPhone 6 Plus", 188 | "udid" : "5D9864DD-4232-42A3-91F7-F13938CA6CA1" 189 | }, 190 | { 191 | "state" : "Shutdown", 192 | "availability" : "(available)", 193 | "name" : "iPhone 6s", 194 | "udid" : "C79C7BB8-1C9D-4415-84CE-A8A246B59F88" 195 | }, 196 | { 197 | "state" : "Shutdown", 198 | "availability" : "(available)", 199 | "name" : "iPhone 6s Plus", 200 | "udid" : "876FC4D4-E9E2-4533-8029-22B4F39FA475" 201 | }, 202 | { 203 | "state" : "Shutdown", 204 | "availability" : "(available)", 205 | "name" : "iPad 2", 206 | "udid" : "517B90F4-C5B2-4E62-933B-C7FE44C33719" 207 | }, 208 | { 209 | "state" : "Shutdown", 210 | "availability" : "(available)", 211 | "name" : "iPad Retina", 212 | "udid" : "EF94A3C6-A354-430F-A18E-CE88957164BA" 213 | }, 214 | { 215 | "state" : "Shutdown", 216 | "availability" : "(available)", 217 | "name" : "iPad Air", 218 | "udid" : "A7CF03DE-7E2C-43EB-A2E0-78466C47D815" 219 | }, 220 | { 221 | "state" : "Shutdown", 222 | "availability" : "(available)", 223 | "name" : "iPad Air 2", 224 | "udid" : "CF153479-57B4-4312-A6C7-45EE6B9CFC7D" 225 | } 226 | ], 227 | "watchOS 3.0" : [ 228 | { 229 | "state" : "Shutdown", 230 | "availability" : "(available)", 231 | "name" : "Apple Watch - 38mm", 232 | "udid" : "A1143FF4-11B4-4007-A46E-4AA2D09A9766" 233 | }, 234 | { 235 | "state" : "Shutdown", 236 | "availability" : "(available)", 237 | "name" : "Apple Watch - 42mm", 238 | "udid" : "CDA793A2-B900-4473-906F-4B20AE542A45" 239 | }, 240 | { 241 | "state" : "Shutdown", 242 | "availability" : "(available)", 243 | "name" : "Apple Watch Series 2 - 38mm", 244 | "udid" : "DE270554-EBC8-4F0A-88A7-762D3159A4C5" 245 | }, 246 | { 247 | "state" : "Shutdown", 248 | "availability" : "(available)", 249 | "name" : "Apple Watch Series 2 - 42mm", 250 | "udid" : "0AE9742E-5644-415D-A281-FB4948302C06" 251 | } 252 | ], 253 | "iOS 8.3" : [ 254 | { 255 | "state" : "Shutdown", 256 | "availability" : "(available)", 257 | "name" : "iPhone 4s", 258 | "udid" : "F1BBD469-7F68-4A3A-B6EF-3C7180741432" 259 | }, 260 | { 261 | "state" : "Shutdown", 262 | "availability" : "(available)", 263 | "name" : "iPhone 5", 264 | "udid" : "FDD91007-5DD8-4B84-819E-3F64EE39841A" 265 | }, 266 | { 267 | "state" : "Shutdown", 268 | "availability" : "(available)", 269 | "name" : "iPhone 5s", 270 | "udid" : "9DBC292B-6C2F-41C2-B0D1-C0FB175C4555" 271 | }, 272 | { 273 | "state" : "Shutdown", 274 | "availability" : "(available)", 275 | "name" : "iPhone 6", 276 | "udid" : "0A710201-1FE3-47B0-813D-15AA63BE1C82" 277 | }, 278 | { 279 | "state" : "Shutdown", 280 | "availability" : "(available)", 281 | "name" : "iPhone 6 Plus", 282 | "udid" : "12410241-2EE7-44F5-A4FE-B881EA1D1CC0" 283 | }, 284 | { 285 | "state" : "Shutdown", 286 | "availability" : "(available)", 287 | "name" : "iPad 2", 288 | "udid" : "1CE4DFEC-DA62-4E2F-9167-7722768FE3B4" 289 | }, 290 | { 291 | "state" : "Shutdown", 292 | "availability" : "(available)", 293 | "name" : "iPad Retina", 294 | "udid" : "6922BB1A-9667-43EC-82A3-D9084E580350" 295 | }, 296 | { 297 | "state" : "Shutdown", 298 | "availability" : "(available)", 299 | "name" : "iPad Air", 300 | "udid" : "8AFE52ED-EB97-4223-9450-714C99D4E3C0" 301 | } 302 | ], 303 | "iOS 9.2" : [ 304 | { 305 | "state" : "Shutdown", 306 | "availability" : "(available)", 307 | "name" : "iPhone 4s", 308 | "udid" : "6FF887AE-374C-4A20-BEAC-2C46E65C02C3" 309 | }, 310 | { 311 | "state" : "Shutdown", 312 | "availability" : "(available)", 313 | "name" : "iPhone 5", 314 | "udid" : "B1FA54F9-0EA9-43B9-9FDF-40C97E3D1ED5" 315 | }, 316 | { 317 | "state" : "Shutdown", 318 | "availability" : "(available)", 319 | "name" : "iPhone 5s", 320 | "udid" : "C02FF777-C646-44DB-9589-BC01F1508523" 321 | }, 322 | { 323 | "state" : "Shutdown", 324 | "availability" : "(available)", 325 | "name" : "iPhone 6", 326 | "udid" : "C1BA1EA3-189A-4E37-BF0D-2CDF3F1BAA74" 327 | }, 328 | { 329 | "state" : "Shutdown", 330 | "availability" : "(available)", 331 | "name" : "iPhone 6 Plus", 332 | "udid" : "4F17DD6C-A5F4-4E25-8E4C-14E3609BFBDC" 333 | }, 334 | { 335 | "state" : "Shutdown", 336 | "availability" : "(available)", 337 | "name" : "iPhone 6s", 338 | "udid" : "8F7E5CC6-46A1-4C8E-95EF-E6F1BCD598F2" 339 | }, 340 | { 341 | "state" : "Shutdown", 342 | "availability" : "(available)", 343 | "name" : "iPhone 6s Plus", 344 | "udid" : "093C40F3-8337-492A-9E17-E5B5CEE2D76A" 345 | }, 346 | { 347 | "state" : "Shutdown", 348 | "availability" : "(available)", 349 | "name" : "iPad 2", 350 | "udid" : "8F43DE3E-A076-4CC4-ABFA-2638FB77BCE0" 351 | }, 352 | { 353 | "state" : "Shutdown", 354 | "availability" : "(available)", 355 | "name" : "iPad Retina", 356 | "udid" : "1E2A6ACF-B157-42AC-BDC0-E0B79A1A0E89" 357 | }, 358 | { 359 | "state" : "Shutdown", 360 | "availability" : "(available)", 361 | "name" : "iPad Air", 362 | "udid" : "015D5072-BF2E-4719-BCF2-876380F1254C" 363 | }, 364 | { 365 | "state" : "Shutdown", 366 | "availability" : "(available)", 367 | "name" : "iPad Air 2", 368 | "udid" : "61FB9298-C820-4254-9193-B855E59735AE" 369 | }, 370 | { 371 | "state" : "Shutdown", 372 | "availability" : "(available)", 373 | "name" : "iPad Pro", 374 | "udid" : "1E986CFD-F91E-41EA-869F-E335B795FB41" 375 | } 376 | ], 377 | "tvOS 9.0" : [ 378 | { 379 | "state" : "Shutdown", 380 | "availability" : "(available)", 381 | "name" : "Apple TV 1080p", 382 | "udid" : "A0C94939-91E7-4FCF-BDA8-09802D47B87A" 383 | } 384 | ], 385 | "iOS 8.2" : [ 386 | { 387 | "state" : "Shutdown", 388 | "availability" : "(available)", 389 | "name" : "iPhone 4s", 390 | "udid" : "A9F0900E-4D9B-4A07-BB81-859A86404B8E" 391 | }, 392 | { 393 | "state" : "Shutdown", 394 | "availability" : "(available)", 395 | "name" : "iPhone 5", 396 | "udid" : "4D2B2F0C-96E9-4695-BDAD-D84CA2E0F1D1" 397 | }, 398 | { 399 | "state" : "Shutdown", 400 | "availability" : "(available)", 401 | "name" : "iPhone 5s", 402 | "udid" : "8345B4B0-140F-458F-8338-FD4B5345BD1A" 403 | }, 404 | { 405 | "state" : "Shutdown", 406 | "availability" : "(available)", 407 | "name" : "iPhone 6", 408 | "udid" : "08356397-B5E7-451F-A388-2EBE5932425B" 409 | }, 410 | { 411 | "state" : "Shutdown", 412 | "availability" : "(available)", 413 | "name" : "iPhone 6 Plus", 414 | "udid" : "FDC080B7-489D-4AAA-ABD1-5AE1F7369480" 415 | }, 416 | { 417 | "state" : "Shutdown", 418 | "availability" : "(available)", 419 | "name" : "iPad 2", 420 | "udid" : "7C1878DC-7281-4CFD-B20A-E8F2460BEC56" 421 | }, 422 | { 423 | "state" : "Shutdown", 424 | "availability" : "(available)", 425 | "name" : "iPad Retina", 426 | "udid" : "316EC3BB-9A93-4F94-BF8A-93C83DF512D3" 427 | }, 428 | { 429 | "state" : "Shutdown", 430 | "availability" : "(available)", 431 | "name" : "iPad Air", 432 | "udid" : "3ADFD2DF-B36D-4895-8A68-573992E09A82" 433 | } 434 | ], 435 | "tvOS 9.1" : [ 436 | { 437 | "state" : "Shutdown", 438 | "availability" : "(available)", 439 | "name" : "Apple TV 1080p", 440 | "udid" : "88F3E730-0240-4C4B-967C-7B07088F5C84" 441 | } 442 | ], 443 | "tvOS 10.0" : [ 444 | { 445 | "state" : "Shutdown", 446 | "availability" : "(available)", 447 | "name" : "Apple TV 1080p", 448 | "udid" : "273D776F-196E-4F2A-AEF2-E1E3EAE99B47" 449 | } 450 | ], 451 | "iOS 9.1" : [ 452 | { 453 | "state" : "Shutdown", 454 | "availability" : "(available)", 455 | "name" : "iPhone 4s", 456 | "udid" : "6BC8206C-F70B-4145-BF80-AD2EB0058CC9" 457 | }, 458 | { 459 | "state" : "Shutdown", 460 | "availability" : "(available)", 461 | "name" : "iPhone 5", 462 | "udid" : "9344A565-FBBE-4D94-B215-771E0C451CDB" 463 | }, 464 | { 465 | "state" : "Shutdown", 466 | "availability" : "(available)", 467 | "name" : "iPhone 5s", 468 | "udid" : "94CA4950-7920-4F31-B382-9DD829478653" 469 | }, 470 | { 471 | "state" : "Shutdown", 472 | "availability" : "(available)", 473 | "name" : "iPhone 6", 474 | "udid" : "70ED7942-8ED7-443F-AE49-373F2A78A6D1" 475 | }, 476 | { 477 | "state" : "Shutdown", 478 | "availability" : "(available)", 479 | "name" : "iPhone 6 Plus", 480 | "udid" : "6CABCF8B-BB48-4174-B60F-9ED874B26E9D" 481 | }, 482 | { 483 | "state" : "Shutdown", 484 | "availability" : "(available)", 485 | "name" : "iPhone 6s", 486 | "udid" : "5CDCE4F7-EB70-4398-AC18-2470BD4C2980" 487 | }, 488 | { 489 | "state" : "Shutdown", 490 | "availability" : "(available)", 491 | "name" : "iPhone 6s Plus", 492 | "udid" : "030359F2-F8DC-431F-AA25-E48428248FAE" 493 | }, 494 | { 495 | "state" : "Shutdown", 496 | "availability" : "(available)", 497 | "name" : "iPad 2", 498 | "udid" : "2E464BFA-A1CC-44AB-A26C-6D6C4DC61759" 499 | }, 500 | { 501 | "state" : "Shutdown", 502 | "availability" : "(available)", 503 | "name" : "iPad Retina", 504 | "udid" : "E2BE7D7D-4701-43C8-8CE9-B3CFA73263D1" 505 | }, 506 | { 507 | "state" : "Shutdown", 508 | "availability" : "(available)", 509 | "name" : "iPad Air", 510 | "udid" : "2C538F78-E298-4AB8-AB73-AA487945AA7A" 511 | }, 512 | { 513 | "state" : "Shutdown", 514 | "availability" : "(available)", 515 | "name" : "iPad Air 2", 516 | "udid" : "F5F5D82B-E735-410A-A92F-D1A3247114C7" 517 | }, 518 | { 519 | "state" : "Shutdown", 520 | "availability" : "(available)", 521 | "name" : "iPad Pro", 522 | "udid" : "130C53DF-E402-4E6D-B451-1EC60B1B3B56" 523 | } 524 | ], 525 | "watchOS 2.0" : [ 526 | { 527 | "state" : "Shutdown", 528 | "availability" : "(available)", 529 | "name" : "Apple Watch - 38mm", 530 | "udid" : "72DBEA8D-5BC4-4698-A3A4-7DB2C3CD7A99" 531 | }, 532 | { 533 | "state" : "Shutdown", 534 | "availability" : "(available)", 535 | "name" : "Apple Watch - 42mm", 536 | "udid" : "9461F950-CBEC-4401-88A9-2EF6705EB253" 537 | } 538 | ], 539 | "tvOS 9.2" : [ 540 | { 541 | "state" : "Shutdown", 542 | "availability" : "(available)", 543 | "name" : "Apple TV 1080p", 544 | "udid" : "F7AC92EE-B3A1-4E34-8F32-973080BF2C66" 545 | } 546 | ], 547 | "iOS 8.4" : [ 548 | { 549 | "state" : "Shutdown", 550 | "availability" : "(available)", 551 | "name" : "iPhone 4s", 552 | "udid" : "0C09F3E8-BEFE-4B36-A879-710C8502D3AC" 553 | }, 554 | { 555 | "state" : "Shutdown", 556 | "availability" : "(available)", 557 | "name" : "iPhone 5", 558 | "udid" : "804202DE-1F7E-47AE-877E-E99607864616" 559 | }, 560 | { 561 | "state" : "Shutdown", 562 | "availability" : "(available)", 563 | "name" : "iPhone 5s", 564 | "udid" : "A33683A0-F0EA-40C3-B7D8-BC69168BFE8B" 565 | }, 566 | { 567 | "state" : "Shutdown", 568 | "availability" : "(available)", 569 | "name" : "iPhone 6", 570 | "udid" : "C9AF15E6-2288-4FC7-A3B3-F520AF5C723A" 571 | }, 572 | { 573 | "state" : "Shutdown", 574 | "availability" : "(available)", 575 | "name" : "iPhone 6 Plus", 576 | "udid" : "B5C686FE-92BF-4B23-AFF4-6B3B2E556A57" 577 | }, 578 | { 579 | "state" : "Shutdown", 580 | "availability" : "(available)", 581 | "name" : "iPad 2", 582 | "udid" : "40824C07-5672-4940-9378-6E633886AC4E" 583 | }, 584 | { 585 | "state" : "Shutdown", 586 | "availability" : "(available)", 587 | "name" : "iPad Retina", 588 | "udid" : "B4ADDDFE-4ACC-4080-9E2A-3B1BB2BA2EEF" 589 | }, 590 | { 591 | "state" : "Shutdown", 592 | "availability" : "(available)", 593 | "name" : "iPad Air", 594 | "udid" : "09A8C45B-1611-4733-81BB-7931069915BD" 595 | } 596 | ], 597 | "watchOS 2.1" : [ 598 | { 599 | "state" : "Shutdown", 600 | "availability" : "(available)", 601 | "name" : "Apple Watch - 38mm", 602 | "udid" : "71819DE4-E516-49C3-84B1-06A10B8BFF6E" 603 | }, 604 | { 605 | "state" : "Shutdown", 606 | "availability" : "(available)", 607 | "name" : "Apple Watch - 42mm", 608 | "udid" : "2C0A38F5-86B7-457E-B353-141BBB606114" 609 | } 610 | ], 611 | "iOS 9.3" : [ 612 | { 613 | "state" : "Shutdown", 614 | "availability" : "(available)", 615 | "name" : "iPhone 4s", 616 | "udid" : "52DBE1DA-E90D-43E0-879D-B6D28B1682E8" 617 | }, 618 | { 619 | "state" : "Shutdown", 620 | "availability" : "(available)", 621 | "name" : "iPhone 5", 622 | "udid" : "26235FD2-F8EB-455D-8D34-0EA0C656CFAD" 623 | }, 624 | { 625 | "state" : "Shutdown", 626 | "availability" : "(available)", 627 | "name" : "iPhone 5s", 628 | "udid" : "97631C8B-5D9D-4665-94D6-D11D12B580F3" 629 | }, 630 | { 631 | "state" : "Shutdown", 632 | "availability" : "(available)", 633 | "name" : "iPhone 6", 634 | "udid" : "79A9445F-18A8-4DD1-A9BB-D2FACE658A81" 635 | }, 636 | { 637 | "state" : "Shutdown", 638 | "availability" : "(available)", 639 | "name" : "iPhone 6 Plus", 640 | "udid" : "A17081F2-8B40-4A8C-94E5-7073FCCA07E6" 641 | }, 642 | { 643 | "state" : "Shutdown", 644 | "availability" : "(available)", 645 | "name" : "iPhone 6s", 646 | "udid" : "C335FB1B-868F-4E8C-B14A-3264B3C7F51D" 647 | }, 648 | { 649 | "state" : "Shutdown", 650 | "availability" : "(available)", 651 | "name" : "iPhone 6s Plus", 652 | "udid" : "BA7E6117-CC6E-4A41-9A88-D4DB9A2F2179" 653 | }, 654 | { 655 | "state" : "Shutdown", 656 | "availability" : "(available)", 657 | "name" : "iPad 2", 658 | "udid" : "8E6A7679-B9E8-4599-9991-5AD320AA486B" 659 | }, 660 | { 661 | "state" : "Shutdown", 662 | "availability" : "(available)", 663 | "name" : "iPad Retina", 664 | "udid" : "8AE5B73B-58DE-4334-BBEB-E90AFC6DBD95" 665 | }, 666 | { 667 | "state" : "Shutdown", 668 | "availability" : "(available)", 669 | "name" : "iPad Air", 670 | "udid" : "98E48F03-7BA1-4427-98A6-8066F910C523" 671 | }, 672 | { 673 | "state" : "Shutdown", 674 | "availability" : "(available)", 675 | "name" : "iPad Air 2", 676 | "udid" : "7B727958-C4B5-4D69-905F-36595CCC4FA8" 677 | }, 678 | { 679 | "state" : "Shutdown", 680 | "availability" : "(available)", 681 | "name" : "iPad Pro", 682 | "udid" : "577FC482-9A34-44F3-8CAF-AFFA1B8ED38B" 683 | } 684 | ] 685 | } 686 | } -------------------------------------------------------------------------------- /spec/fixtures/simctl_bad.json: -------------------------------------------------------------------------------- 1 | Install Started 2 | 1%.........20.........40.........60........Install Succeeded 3 | apply_selection_policy_once: prefer use of removable GPUs 4 | { 5 | "devices" : { 6 | "iOS 8.1" : [ 7 | { 8 | "state" : "Shutdown", 9 | "availability" : "(available)", 10 | "name" : "iPhone 4s", 11 | "udid" : "F86F61DF-60B0-4EAE-8A62-D2CB78708066" 12 | }, 13 | { 14 | "state" : "Shutdown", 15 | "availability" : "(available)", 16 | "name" : "iPhone 5", 17 | "udid" : "FDE9A448-6BFB-48D9-B2C9-0D80EA0705E1" 18 | }, 19 | { 20 | "state" : "Shutdown", 21 | "availability" : "(available)", 22 | "name" : "iPhone 5s", 23 | "udid" : "CE3907EC-46F6-4BED-A37D-393F820A746F" 24 | }, 25 | { 26 | "state" : "Shutdown", 27 | "availability" : "(available)", 28 | "name" : "iPhone 6", 29 | "udid" : "4C816B5D-B781-4F32-9F08-5FB2A0442B8F" 30 | }, 31 | { 32 | "state" : "Shutdown", 33 | "availability" : "(available)", 34 | "name" : "iPhone 6 Plus", 35 | "udid" : "B064B7AA-E60C-44A8-88DA-E3A22E6BA314" 36 | }, 37 | { 38 | "state" : "Shutdown", 39 | "availability" : "(available)", 40 | "name" : "iPad 2", 41 | "udid" : "9B6D5371-612F-4485-AFCD-B0AE089EA454" 42 | }, 43 | { 44 | "state" : "Shutdown", 45 | "availability" : "(available)", 46 | "name" : "iPad Retina", 47 | "udid" : "94CC76BE-A3FB-41AF-AB05-21EEA55E72CF" 48 | }, 49 | { 50 | "state" : "Shutdown", 51 | "availability" : "(available)", 52 | "name" : "iPad Air", 53 | "udid" : "62C1BA28-96C6-483F-B6AF-5BDFAC7E34DC" 54 | } 55 | ], 56 | "iOS 10.0" : [ 57 | { 58 | "state" : "Shutdown", 59 | "availability" : "(available)", 60 | "name" : "iPhone 5", 61 | "udid" : "872DB32B-E22D-4F31-A6C1-606F2B5EE2A1" 62 | }, 63 | { 64 | "state" : "Shutdown", 65 | "availability" : "(available)", 66 | "name" : "iPhone 5s", 67 | "udid" : "0CD964DF-5EC9-438D-9937-24FB9D9C266B" 68 | }, 69 | { 70 | "state" : "Shutdown", 71 | "availability" : "(available)", 72 | "name" : "iPhone 6", 73 | "udid" : "237D7619-4A4E-4624-8925-67A42A8A690A" 74 | }, 75 | { 76 | "state" : "Shutdown", 77 | "availability" : "(available)", 78 | "name" : "iPhone 6 Plus", 79 | "udid" : "7453E43C-6352-44AA-8BE0-2E09643F5F88" 80 | }, 81 | { 82 | "state" : "Shutdown", 83 | "availability" : "(available)", 84 | "name" : "iPhone 6s", 85 | "udid" : "9793E592-F0FF-4C4A-BEEF-FDD50A67E8C1" 86 | }, 87 | { 88 | "state" : "Shutdown", 89 | "availability" : "(available)", 90 | "name" : "iPhone 6s Plus", 91 | "udid" : "64DF30D4-4118-480F-9ADD-DCC32194B63D" 92 | }, 93 | { 94 | "state" : "Shutdown", 95 | "availability" : "(available)", 96 | "name" : "iPhone 7", 97 | "udid" : "5F911B30-5F23-403B-9697-1DFDC24773C8" 98 | }, 99 | { 100 | "state" : "Shutdown", 101 | "availability" : "(available)", 102 | "name" : "iPhone 7 Plus", 103 | "udid" : "E3B7D09E-DD71-4DAA-9D1D-6B678487D646" 104 | }, 105 | { 106 | "state" : "Shutdown", 107 | "availability" : "(available)", 108 | "name" : "iPhone SE", 109 | "udid" : "1A6EAD45-0A28-421A-A6D4-AD0866464FAA" 110 | }, 111 | { 112 | "state" : "Shutdown", 113 | "availability" : "(available)", 114 | "name" : "iPad Retina", 115 | "udid" : "2CB7C124-E268-4E00-9FBF-598C1003ABDC" 116 | }, 117 | { 118 | "state" : "Shutdown", 119 | "availability" : "(available)", 120 | "name" : "iPad Air", 121 | "udid" : "C08A3293-272A-4D95-9ECC-288D9A0C171A" 122 | }, 123 | { 124 | "state" : "Shutdown", 125 | "availability" : "(available)", 126 | "name" : "iPad Air 2", 127 | "udid" : "845F97F9-26FE-42AC-9412-EB6DBEEF78E9" 128 | }, 129 | { 130 | "state" : "Shutdown", 131 | "availability" : "(available)", 132 | "name" : "iPad Pro (9.7 inch)", 133 | "udid" : "0B89526F-FE59-4253-B5C8-5F59F48F4AE6" 134 | }, 135 | { 136 | "state" : "Shutdown", 137 | "availability" : "(available)", 138 | "name" : "iPad Pro (12.9 inch)", 139 | "udid" : "5F8F269D-E643-4E87-915D-12B7D49ED08D" 140 | }, 141 | { 142 | "state" : "Shutdown", 143 | "availability" : "(available)", 144 | "name" : "iPad", 145 | "udid" : "18B5770F-3C49-480E-BEC9-A6748612EBD3" 146 | } 147 | ], 148 | "watchOS 2.2" : [ 149 | { 150 | "state" : "Shutdown", 151 | "availability" : "(available)", 152 | "name" : "Apple Watch - 38mm", 153 | "udid" : "0ACDF8F4-1968-43C3-830F-D614E7138288" 154 | }, 155 | { 156 | "state" : "Shutdown", 157 | "availability" : "(available)", 158 | "name" : "Apple Watch - 42mm", 159 | "udid" : "4E651A7A-AB0B-445D-BD19-60E67536D0B8" 160 | } 161 | ], 162 | "iOS 9.0" : [ 163 | { 164 | "state" : "Shutdown", 165 | "availability" : "(available)", 166 | "name" : "iPhone 4s", 167 | "udid" : "84F3616D-0AB5-41EE-A499-89211620898F" 168 | }, 169 | { 170 | "state" : "Shutdown", 171 | "availability" : "(available)", 172 | "name" : "iPhone 5", 173 | "udid" : "19C842D1-57D0-407D-AA85-F373FB4D672A" 174 | }, 175 | { 176 | "state" : "Shutdown", 177 | "availability" : "(available)", 178 | "name" : "iPhone 5s", 179 | "udid" : "E8ABD8EA-CF53-4A2A-9C91-2760EFAF631D" 180 | }, 181 | { 182 | "state" : "Shutdown", 183 | "availability" : "(available)", 184 | "name" : "iPhone 6", 185 | "udid" : "4DFC7897-D8A4-45B3-80B2-44C854B3AD16" 186 | }, 187 | { 188 | "state" : "Shutdown", 189 | "availability" : "(available)", 190 | "name" : "iPhone 6 Plus", 191 | "udid" : "5D9864DD-4232-42A3-91F7-F13938CA6CA1" 192 | }, 193 | { 194 | "state" : "Shutdown", 195 | "availability" : "(available)", 196 | "name" : "iPhone 6s", 197 | "udid" : "C79C7BB8-1C9D-4415-84CE-A8A246B59F88" 198 | }, 199 | { 200 | "state" : "Shutdown", 201 | "availability" : "(available)", 202 | "name" : "iPhone 6s Plus", 203 | "udid" : "876FC4D4-E9E2-4533-8029-22B4F39FA475" 204 | }, 205 | { 206 | "state" : "Shutdown", 207 | "availability" : "(available)", 208 | "name" : "iPad 2", 209 | "udid" : "517B90F4-C5B2-4E62-933B-C7FE44C33719" 210 | }, 211 | { 212 | "state" : "Shutdown", 213 | "availability" : "(available)", 214 | "name" : "iPad Retina", 215 | "udid" : "EF94A3C6-A354-430F-A18E-CE88957164BA" 216 | }, 217 | { 218 | "state" : "Shutdown", 219 | "availability" : "(available)", 220 | "name" : "iPad Air", 221 | "udid" : "A7CF03DE-7E2C-43EB-A2E0-78466C47D815" 222 | }, 223 | { 224 | "state" : "Shutdown", 225 | "availability" : "(available)", 226 | "name" : "iPad Air 2", 227 | "udid" : "CF153479-57B4-4312-A6C7-45EE6B9CFC7D" 228 | } 229 | ], 230 | "watchOS 3.0" : [ 231 | { 232 | "state" : "Shutdown", 233 | "availability" : "(available)", 234 | "name" : "Apple Watch - 38mm", 235 | "udid" : "A1143FF4-11B4-4007-A46E-4AA2D09A9766" 236 | }, 237 | { 238 | "state" : "Shutdown", 239 | "availability" : "(available)", 240 | "name" : "Apple Watch - 42mm", 241 | "udid" : "CDA793A2-B900-4473-906F-4B20AE542A45" 242 | }, 243 | { 244 | "state" : "Shutdown", 245 | "availability" : "(available)", 246 | "name" : "Apple Watch Series 2 - 38mm", 247 | "udid" : "DE270554-EBC8-4F0A-88A7-762D3159A4C5" 248 | }, 249 | { 250 | "state" : "Shutdown", 251 | "availability" : "(available)", 252 | "name" : "Apple Watch Series 2 - 42mm", 253 | "udid" : "0AE9742E-5644-415D-A281-FB4948302C06" 254 | } 255 | ], 256 | "iOS 8.3" : [ 257 | { 258 | "state" : "Shutdown", 259 | "availability" : "(available)", 260 | "name" : "iPhone 4s", 261 | "udid" : "F1BBD469-7F68-4A3A-B6EF-3C7180741432" 262 | }, 263 | { 264 | "state" : "Shutdown", 265 | "availability" : "(available)", 266 | "name" : "iPhone 5", 267 | "udid" : "FDD91007-5DD8-4B84-819E-3F64EE39841A" 268 | }, 269 | { 270 | "state" : "Shutdown", 271 | "availability" : "(available)", 272 | "name" : "iPhone 5s", 273 | "udid" : "9DBC292B-6C2F-41C2-B0D1-C0FB175C4555" 274 | }, 275 | { 276 | "state" : "Shutdown", 277 | "availability" : "(available)", 278 | "name" : "iPhone 6", 279 | "udid" : "0A710201-1FE3-47B0-813D-15AA63BE1C82" 280 | }, 281 | { 282 | "state" : "Shutdown", 283 | "availability" : "(available)", 284 | "name" : "iPhone 6 Plus", 285 | "udid" : "12410241-2EE7-44F5-A4FE-B881EA1D1CC0" 286 | }, 287 | { 288 | "state" : "Shutdown", 289 | "availability" : "(available)", 290 | "name" : "iPad 2", 291 | "udid" : "1CE4DFEC-DA62-4E2F-9167-7722768FE3B4" 292 | }, 293 | { 294 | "state" : "Shutdown", 295 | "availability" : "(available)", 296 | "name" : "iPad Retina", 297 | "udid" : "6922BB1A-9667-43EC-82A3-D9084E580350" 298 | }, 299 | { 300 | "state" : "Shutdown", 301 | "availability" : "(available)", 302 | "name" : "iPad Air", 303 | "udid" : "8AFE52ED-EB97-4223-9450-714C99D4E3C0" 304 | } 305 | ], 306 | "iOS 9.2" : [ 307 | { 308 | "state" : "Shutdown", 309 | "availability" : "(available)", 310 | "name" : "iPhone 4s", 311 | "udid" : "6FF887AE-374C-4A20-BEAC-2C46E65C02C3" 312 | }, 313 | { 314 | "state" : "Shutdown", 315 | "availability" : "(available)", 316 | "name" : "iPhone 5", 317 | "udid" : "B1FA54F9-0EA9-43B9-9FDF-40C97E3D1ED5" 318 | }, 319 | { 320 | "state" : "Shutdown", 321 | "availability" : "(available)", 322 | "name" : "iPhone 5s", 323 | "udid" : "C02FF777-C646-44DB-9589-BC01F1508523" 324 | }, 325 | { 326 | "state" : "Shutdown", 327 | "availability" : "(available)", 328 | "name" : "iPhone 6", 329 | "udid" : "C1BA1EA3-189A-4E37-BF0D-2CDF3F1BAA74" 330 | }, 331 | { 332 | "state" : "Shutdown", 333 | "availability" : "(available)", 334 | "name" : "iPhone 6 Plus", 335 | "udid" : "4F17DD6C-A5F4-4E25-8E4C-14E3609BFBDC" 336 | }, 337 | { 338 | "state" : "Shutdown", 339 | "availability" : "(available)", 340 | "name" : "iPhone 6s", 341 | "udid" : "8F7E5CC6-46A1-4C8E-95EF-E6F1BCD598F2" 342 | }, 343 | { 344 | "state" : "Shutdown", 345 | "availability" : "(available)", 346 | "name" : "iPhone 6s Plus", 347 | "udid" : "093C40F3-8337-492A-9E17-E5B5CEE2D76A" 348 | }, 349 | { 350 | "state" : "Shutdown", 351 | "availability" : "(available)", 352 | "name" : "iPad 2", 353 | "udid" : "8F43DE3E-A076-4CC4-ABFA-2638FB77BCE0" 354 | }, 355 | { 356 | "state" : "Shutdown", 357 | "availability" : "(available)", 358 | "name" : "iPad Retina", 359 | "udid" : "1E2A6ACF-B157-42AC-BDC0-E0B79A1A0E89" 360 | }, 361 | { 362 | "state" : "Shutdown", 363 | "availability" : "(available)", 364 | "name" : "iPad Air", 365 | "udid" : "015D5072-BF2E-4719-BCF2-876380F1254C" 366 | }, 367 | { 368 | "state" : "Shutdown", 369 | "availability" : "(available)", 370 | "name" : "iPad Air 2", 371 | "udid" : "61FB9298-C820-4254-9193-B855E59735AE" 372 | }, 373 | { 374 | "state" : "Shutdown", 375 | "availability" : "(available)", 376 | "name" : "iPad Pro", 377 | "udid" : "1E986CFD-F91E-41EA-869F-E335B795FB41" 378 | } 379 | ], 380 | "tvOS 9.0" : [ 381 | { 382 | "state" : "Shutdown", 383 | "availability" : "(available)", 384 | "name" : "Apple TV 1080p", 385 | "udid" : "A0C94939-91E7-4FCF-BDA8-09802D47B87A" 386 | } 387 | ], 388 | "iOS 8.2" : [ 389 | { 390 | "state" : "Shutdown", 391 | "availability" : "(available)", 392 | "name" : "iPhone 4s", 393 | "udid" : "A9F0900E-4D9B-4A07-BB81-859A86404B8E" 394 | }, 395 | { 396 | "state" : "Shutdown", 397 | "availability" : "(available)", 398 | "name" : "iPhone 5", 399 | "udid" : "4D2B2F0C-96E9-4695-BDAD-D84CA2E0F1D1" 400 | }, 401 | { 402 | "state" : "Shutdown", 403 | "availability" : "(available)", 404 | "name" : "iPhone 5s", 405 | "udid" : "8345B4B0-140F-458F-8338-FD4B5345BD1A" 406 | }, 407 | { 408 | "state" : "Shutdown", 409 | "availability" : "(available)", 410 | "name" : "iPhone 6", 411 | "udid" : "08356397-B5E7-451F-A388-2EBE5932425B" 412 | }, 413 | { 414 | "state" : "Shutdown", 415 | "availability" : "(available)", 416 | "name" : "iPhone 6 Plus", 417 | "udid" : "FDC080B7-489D-4AAA-ABD1-5AE1F7369480" 418 | }, 419 | { 420 | "state" : "Shutdown", 421 | "availability" : "(available)", 422 | "name" : "iPad 2", 423 | "udid" : "7C1878DC-7281-4CFD-B20A-E8F2460BEC56" 424 | }, 425 | { 426 | "state" : "Shutdown", 427 | "availability" : "(available)", 428 | "name" : "iPad Retina", 429 | "udid" : "316EC3BB-9A93-4F94-BF8A-93C83DF512D3" 430 | }, 431 | { 432 | "state" : "Shutdown", 433 | "availability" : "(available)", 434 | "name" : "iPad Air", 435 | "udid" : "3ADFD2DF-B36D-4895-8A68-573992E09A82" 436 | } 437 | ], 438 | "tvOS 9.1" : [ 439 | { 440 | "state" : "Shutdown", 441 | "availability" : "(available)", 442 | "name" : "Apple TV 1080p", 443 | "udid" : "88F3E730-0240-4C4B-967C-7B07088F5C84" 444 | } 445 | ], 446 | "tvOS 10.0" : [ 447 | { 448 | "state" : "Shutdown", 449 | "availability" : "(available)", 450 | "name" : "Apple TV 1080p", 451 | "udid" : "273D776F-196E-4F2A-AEF2-E1E3EAE99B47" 452 | } 453 | ], 454 | "iOS 9.1" : [ 455 | { 456 | "state" : "Shutdown", 457 | "availability" : "(available)", 458 | "name" : "iPhone 4s", 459 | "udid" : "6BC8206C-F70B-4145-BF80-AD2EB0058CC9" 460 | }, 461 | { 462 | "state" : "Shutdown", 463 | "availability" : "(available)", 464 | "name" : "iPhone 5", 465 | "udid" : "9344A565-FBBE-4D94-B215-771E0C451CDB" 466 | }, 467 | { 468 | "state" : "Shutdown", 469 | "availability" : "(available)", 470 | "name" : "iPhone 5s", 471 | "udid" : "94CA4950-7920-4F31-B382-9DD829478653" 472 | }, 473 | { 474 | "state" : "Shutdown", 475 | "availability" : "(available)", 476 | "name" : "iPhone 6", 477 | "udid" : "70ED7942-8ED7-443F-AE49-373F2A78A6D1" 478 | }, 479 | { 480 | "state" : "Shutdown", 481 | "availability" : "(available)", 482 | "name" : "iPhone 6 Plus", 483 | "udid" : "6CABCF8B-BB48-4174-B60F-9ED874B26E9D" 484 | }, 485 | { 486 | "state" : "Shutdown", 487 | "availability" : "(available)", 488 | "name" : "iPhone 6s", 489 | "udid" : "5CDCE4F7-EB70-4398-AC18-2470BD4C2980" 490 | }, 491 | { 492 | "state" : "Shutdown", 493 | "availability" : "(available)", 494 | "name" : "iPhone 6s Plus", 495 | "udid" : "030359F2-F8DC-431F-AA25-E48428248FAE" 496 | }, 497 | { 498 | "state" : "Shutdown", 499 | "availability" : "(available)", 500 | "name" : "iPad 2", 501 | "udid" : "2E464BFA-A1CC-44AB-A26C-6D6C4DC61759" 502 | }, 503 | { 504 | "state" : "Shutdown", 505 | "availability" : "(available)", 506 | "name" : "iPad Retina", 507 | "udid" : "E2BE7D7D-4701-43C8-8CE9-B3CFA73263D1" 508 | }, 509 | { 510 | "state" : "Shutdown", 511 | "availability" : "(available)", 512 | "name" : "iPad Air", 513 | "udid" : "2C538F78-E298-4AB8-AB73-AA487945AA7A" 514 | }, 515 | { 516 | "state" : "Shutdown", 517 | "availability" : "(available)", 518 | "name" : "iPad Air 2", 519 | "udid" : "F5F5D82B-E735-410A-A92F-D1A3247114C7" 520 | }, 521 | { 522 | "state" : "Shutdown", 523 | "availability" : "(available)", 524 | "name" : "iPad Pro", 525 | "udid" : "130C53DF-E402-4E6D-B451-1EC60B1B3B56" 526 | } 527 | ], 528 | "watchOS 2.0" : [ 529 | { 530 | "state" : "Shutdown", 531 | "availability" : "(available)", 532 | "name" : "Apple Watch - 38mm", 533 | "udid" : "72DBEA8D-5BC4-4698-A3A4-7DB2C3CD7A99" 534 | }, 535 | { 536 | "state" : "Shutdown", 537 | "availability" : "(available)", 538 | "name" : "Apple Watch - 42mm", 539 | "udid" : "9461F950-CBEC-4401-88A9-2EF6705EB253" 540 | } 541 | ], 542 | "tvOS 9.2" : [ 543 | { 544 | "state" : "Shutdown", 545 | "availability" : "(available)", 546 | "name" : "Apple TV 1080p", 547 | "udid" : "F7AC92EE-B3A1-4E34-8F32-973080BF2C66" 548 | } 549 | ], 550 | "iOS 8.4" : [ 551 | { 552 | "state" : "Shutdown", 553 | "availability" : "(available)", 554 | "name" : "iPhone 4s", 555 | "udid" : "0C09F3E8-BEFE-4B36-A879-710C8502D3AC" 556 | }, 557 | { 558 | "state" : "Shutdown", 559 | "availability" : "(available)", 560 | "name" : "iPhone 5", 561 | "udid" : "804202DE-1F7E-47AE-877E-E99607864616" 562 | }, 563 | { 564 | "state" : "Shutdown", 565 | "availability" : "(available)", 566 | "name" : "iPhone 5s", 567 | "udid" : "A33683A0-F0EA-40C3-B7D8-BC69168BFE8B" 568 | }, 569 | { 570 | "state" : "Shutdown", 571 | "availability" : "(available)", 572 | "name" : "iPhone 6", 573 | "udid" : "C9AF15E6-2288-4FC7-A3B3-F520AF5C723A" 574 | }, 575 | { 576 | "state" : "Shutdown", 577 | "availability" : "(available)", 578 | "name" : "iPhone 6 Plus", 579 | "udid" : "B5C686FE-92BF-4B23-AFF4-6B3B2E556A57" 580 | }, 581 | { 582 | "state" : "Shutdown", 583 | "availability" : "(available)", 584 | "name" : "iPad 2", 585 | "udid" : "40824C07-5672-4940-9378-6E633886AC4E" 586 | }, 587 | { 588 | "state" : "Shutdown", 589 | "availability" : "(available)", 590 | "name" : "iPad Retina", 591 | "udid" : "B4ADDDFE-4ACC-4080-9E2A-3B1BB2BA2EEF" 592 | }, 593 | { 594 | "state" : "Shutdown", 595 | "availability" : "(available)", 596 | "name" : "iPad Air", 597 | "udid" : "09A8C45B-1611-4733-81BB-7931069915BD" 598 | } 599 | ], 600 | "watchOS 2.1" : [ 601 | { 602 | "state" : "Shutdown", 603 | "availability" : "(available)", 604 | "name" : "Apple Watch - 38mm", 605 | "udid" : "71819DE4-E516-49C3-84B1-06A10B8BFF6E" 606 | }, 607 | { 608 | "state" : "Shutdown", 609 | "availability" : "(available)", 610 | "name" : "Apple Watch - 42mm", 611 | "udid" : "2C0A38F5-86B7-457E-B353-141BBB606114" 612 | } 613 | ], 614 | "iOS 9.3" : [ 615 | { 616 | "state" : "Shutdown", 617 | "availability" : "(available)", 618 | "name" : "iPhone 4s", 619 | "udid" : "52DBE1DA-E90D-43E0-879D-B6D28B1682E8" 620 | }, 621 | { 622 | "state" : "Shutdown", 623 | "availability" : "(available)", 624 | "name" : "iPhone 5", 625 | "udid" : "26235FD2-F8EB-455D-8D34-0EA0C656CFAD" 626 | }, 627 | { 628 | "state" : "Shutdown", 629 | "availability" : "(available)", 630 | "name" : "iPhone 5s", 631 | "udid" : "97631C8B-5D9D-4665-94D6-D11D12B580F3" 632 | }, 633 | { 634 | "state" : "Shutdown", 635 | "availability" : "(available)", 636 | "name" : "iPhone 6", 637 | "udid" : "79A9445F-18A8-4DD1-A9BB-D2FACE658A81" 638 | }, 639 | { 640 | "state" : "Shutdown", 641 | "availability" : "(available)", 642 | "name" : "iPhone 6 Plus", 643 | "udid" : "A17081F2-8B40-4A8C-94E5-7073FCCA07E6" 644 | }, 645 | { 646 | "state" : "Shutdown", 647 | "availability" : "(available)", 648 | "name" : "iPhone 6s", 649 | "udid" : "C335FB1B-868F-4E8C-B14A-3264B3C7F51D" 650 | }, 651 | { 652 | "state" : "Shutdown", 653 | "availability" : "(available)", 654 | "name" : "iPhone 6s Plus", 655 | "udid" : "BA7E6117-CC6E-4A41-9A88-D4DB9A2F2179" 656 | }, 657 | { 658 | "state" : "Shutdown", 659 | "availability" : "(available)", 660 | "name" : "iPad 2", 661 | "udid" : "8E6A7679-B9E8-4599-9991-5AD320AA486B" 662 | }, 663 | { 664 | "state" : "Shutdown", 665 | "availability" : "(available)", 666 | "name" : "iPad Retina", 667 | "udid" : "8AE5B73B-58DE-4334-BBEB-E90AFC6DBD95" 668 | }, 669 | { 670 | "state" : "Shutdown", 671 | "availability" : "(available)", 672 | "name" : "iPad Air", 673 | "udid" : "98E48F03-7BA1-4427-98A6-8066F910C523" 674 | }, 675 | { 676 | "state" : "Shutdown", 677 | "availability" : "(available)", 678 | "name" : "iPad Air 2", 679 | "udid" : "7B727958-C4B5-4D69-905F-36595CCC4FA8" 680 | }, 681 | { 682 | "state" : "Shutdown", 683 | "availability" : "(available)", 684 | "name" : "iPad Pro", 685 | "udid" : "577FC482-9A34-44F3-8CAF-AFFA1B8ED38B" 686 | } 687 | ] 688 | } 689 | } -------------------------------------------------------------------------------- /spec/fixtures/simctl_small.json: -------------------------------------------------------------------------------- 1 | { 2 | "devices" : { 3 | "iOS 8.1" : [ 4 | { 5 | "state" : "Shutdown", 6 | "availability" : "(available)", 7 | "name" : "iPhone 4s", 8 | "udid" : "F86F61DF-60B0-4EAE-8A62-D2CB78708066" 9 | }, 10 | { 11 | "state" : "Shutdown", 12 | "availability" : "(available)", 13 | "name" : "iPhone 5", 14 | "udid" : "FDE9A448-6BFB-48D9-B2C9-0D80EA0705E1" 15 | }, 16 | { 17 | "state" : "Shutdown", 18 | "availability" : "(available)", 19 | "name" : "iPhone 5s", 20 | "udid" : "CE3907EC-46F6-4BED-A37D-393F820A746F" 21 | }, 22 | { 23 | "state" : "Shutdown", 24 | "availability" : "(available)", 25 | "name" : "iPhone 6", 26 | "udid" : "4C816B5D-B781-4F32-9F08-5FB2A0442B8F" 27 | }, 28 | { 29 | "state" : "Shutdown", 30 | "availability" : "(available)", 31 | "name" : "iPhone 6 Plus", 32 | "udid" : "B064B7AA-E60C-44A8-88DA-E3A22E6BA314" 33 | }, 34 | { 35 | "state" : "Shutdown", 36 | "availability" : "(available)", 37 | "name" : "iPad 2", 38 | "udid" : "9B6D5371-612F-4485-AFCD-B0AE089EA454" 39 | }, 40 | { 41 | "state" : "Shutdown", 42 | "availability" : "(available)", 43 | "name" : "iPad Retina", 44 | "udid" : "94CC76BE-A3FB-41AF-AB05-21EEA55E72CF" 45 | }, 46 | { 47 | "state" : "Shutdown", 48 | "availability" : "(available)", 49 | "name" : "iPad Air", 50 | "udid" : "62C1BA28-96C6-483F-B6AF-5BDFAC7E34DC" 51 | } 52 | ], 53 | "iOS 10.0" : [ 54 | { 55 | "state" : "Shutdown", 56 | "availability" : "(available)", 57 | "name" : "iPhone 5", 58 | "udid" : "872DB32B-E22D-4F31-A6C1-606F2B5EE2A1" 59 | }, 60 | { 61 | "state" : "Shutdown", 62 | "availability" : "(available)", 63 | "name" : "iPhone 5s", 64 | "udid" : "0CD964DF-5EC9-438D-9937-24FB9D9C266B" 65 | }, 66 | { 67 | "state" : "Shutdown", 68 | "availability" : "(available)", 69 | "name" : "iPhone 6", 70 | "udid" : "237D7619-4A4E-4624-8925-67A42A8A690A" 71 | }, 72 | { 73 | "state" : "Shutdown", 74 | "availability" : "(available)", 75 | "name" : "iPhone 6 Plus", 76 | "udid" : "7453E43C-6352-44AA-8BE0-2E09643F5F88" 77 | }, 78 | { 79 | "state" : "Shutdown", 80 | "availability" : "(available)", 81 | "name" : "iPhone 6s", 82 | "udid" : "9793E592-F0FF-4C4A-BEEF-FDD50A67E8C1" 83 | }, 84 | { 85 | "state" : "Shutdown", 86 | "availability" : "(available)", 87 | "name" : "iPhone 6s Plus", 88 | "udid" : "64DF30D4-4118-480F-9ADD-DCC32194B63D" 89 | }, 90 | { 91 | "state" : "Shutdown", 92 | "availability" : "(available)", 93 | "name" : "iPhone 7", 94 | "udid" : "5F911B30-5F23-403B-9697-1DFDC24773C8" 95 | }, 96 | { 97 | "state" : "Shutdown", 98 | "availability" : "(available)", 99 | "name" : "iPhone 7 Plus", 100 | "udid" : "E3B7D09E-DD71-4DAA-9D1D-6B678487D646" 101 | }, 102 | { 103 | "state" : "Shutdown", 104 | "availability" : "(available)", 105 | "name" : "iPhone SE", 106 | "udid" : "1A6EAD45-0A28-421A-A6D4-AD0866464FAA" 107 | }, 108 | { 109 | "state" : "Shutdown", 110 | "availability" : "(available)", 111 | "name" : "iPad Retina", 112 | "udid" : "2CB7C124-E268-4E00-9FBF-598C1003ABDC" 113 | }, 114 | { 115 | "state" : "Shutdown", 116 | "availability" : "(available)", 117 | "name" : "iPad Air", 118 | "udid" : "C08A3293-272A-4D95-9ECC-288D9A0C171A" 119 | }, 120 | { 121 | "state" : "Shutdown", 122 | "availability" : "(available)", 123 | "name" : "iPad Air 2", 124 | "udid" : "845F97F9-26FE-42AC-9412-EB6DBEEF78E9" 125 | }, 126 | { 127 | "state" : "Shutdown", 128 | "availability" : "(available)", 129 | "name" : "iPad Pro (9.7 inch)", 130 | "udid" : "0B89526F-FE59-4253-B5C8-5F59F48F4AE6" 131 | }, 132 | { 133 | "state" : "Shutdown", 134 | "availability" : "(available)", 135 | "name" : "iPad Pro (12.9 inch)", 136 | "udid" : "5F8F269D-E643-4E87-915D-12B7D49ED08D" 137 | }, 138 | { 139 | "state" : "Shutdown", 140 | "availability" : "(available)", 141 | "name" : "iPad", 142 | "udid" : "18B5770F-3C49-480E-BEC9-A6748612EBD3" 143 | } 144 | ], 145 | "watchOS 2.2" : [ 146 | { 147 | "state" : "Shutdown", 148 | "availability" : "(available)", 149 | "name" : "Apple Watch - 38mm", 150 | "udid" : "0ACDF8F4-1968-43C3-830F-D614E7138288" 151 | }, 152 | { 153 | "state" : "Shutdown", 154 | "availability" : "(available)", 155 | "name" : "Apple Watch - 42mm", 156 | "udid" : "4E651A7A-AB0B-445D-BD19-60E67536D0B8" 157 | } 158 | ], 159 | "watchOS 3.0" : [ 160 | { 161 | "state" : "Shutdown", 162 | "availability" : "(available)", 163 | "name" : "Apple Watch - 38mm", 164 | "udid" : "A1143FF4-11B4-4007-A46E-4AA2D09A9766" 165 | }, 166 | { 167 | "state" : "Shutdown", 168 | "availability" : "(available)", 169 | "name" : "Apple Watch - 42mm", 170 | "udid" : "CDA793A2-B900-4473-906F-4B20AE542A45" 171 | }, 172 | { 173 | "state" : "Shutdown", 174 | "availability" : "(available)", 175 | "name" : "Apple Watch Series 2 - 38mm", 176 | "udid" : "DE270554-EBC8-4F0A-88A7-762D3159A4C5" 177 | }, 178 | { 179 | "state" : "Shutdown", 180 | "availability" : "(available)", 181 | "name" : "Apple Watch Series 2 - 42mm", 182 | "udid" : "0AE9742E-5644-415D-A281-FB4948302C06" 183 | } 184 | ], 185 | "tvOS 9.2" : [ 186 | { 187 | "state" : "Shutdown", 188 | "availability" : "(available)", 189 | "name" : "Apple TV 1080p", 190 | "udid" : "F7AC92EE-B3A1-4E34-8F32-973080BF2C66" 191 | } 192 | ] 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /spec/fixtures/simctl_with_unavailable.json: -------------------------------------------------------------------------------- 1 | { 2 | "devices" : { 3 | "iOS 10.0" : [ 4 | { 5 | "state" : "Shutdown", 6 | "availability" : "(available)", 7 | "name" : "iPhone 5", 8 | "udid" : "872DB32B-E22D-4F31-A6C1-606F2B5EE2A1" 9 | }, 10 | { 11 | "state" : "Shutdown", 12 | "availability" : "(available)", 13 | "name" : "iPhone 5s", 14 | "udid" : "0CD964DF-5EC9-438D-9937-24FB9D9C266B" 15 | }, 16 | { 17 | "state" : "Shutdown", 18 | "availability" : "(available)", 19 | "name" : "iPhone 6", 20 | "udid" : "237D7619-4A4E-4624-8925-67A42A8A690A" 21 | }, 22 | { 23 | "state" : "Shutdown", 24 | "availability" : "(available)", 25 | "name" : "iPhone 6 Plus", 26 | "udid" : "7453E43C-6352-44AA-8BE0-2E09643F5F88" 27 | }, 28 | { 29 | "state" : "Shutdown", 30 | "availability" : "(available)", 31 | "name" : "iPhone 6s", 32 | "udid" : "9793E592-F0FF-4C4A-BEEF-FDD50A67E8C1" 33 | }, 34 | { 35 | "state" : "Shutdown", 36 | "availability" : "(available)", 37 | "name" : "iPhone 6s Plus", 38 | "udid" : "64DF30D4-4118-480F-9ADD-DCC32194B63D" 39 | }, 40 | { 41 | "state" : "Shutdown", 42 | "availability" : "(available)", 43 | "name" : "iPhone 7", 44 | "udid" : "5F911B30-5F23-403B-9697-1DFDC24773C8" 45 | }, 46 | { 47 | "state" : "Shutdown", 48 | "availability" : "(available)", 49 | "name" : "iPhone 7 Plus", 50 | "udid" : "E3B7D09E-DD71-4DAA-9D1D-6B678487D646" 51 | }, 52 | { 53 | "state" : "Shutdown", 54 | "availability" : "(available)", 55 | "name" : "iPhone SE", 56 | "udid" : "1A6EAD45-0A28-421A-A6D4-AD0866464FAA" 57 | }, 58 | { 59 | "state" : "Shutdown", 60 | "availability" : "(available)", 61 | "name" : "iPad Retina", 62 | "udid" : "2CB7C124-E268-4E00-9FBF-598C1003ABDC" 63 | }, 64 | { 65 | "state" : "Shutdown", 66 | "availability" : "(available)", 67 | "name" : "iPad Air", 68 | "udid" : "C08A3293-272A-4D95-9ECC-288D9A0C171A" 69 | }, 70 | { 71 | "state" : "Shutdown", 72 | "availability" : "(available)", 73 | "name" : "iPad Air 2", 74 | "udid" : "845F97F9-26FE-42AC-9412-EB6DBEEF78E9" 75 | }, 76 | { 77 | "state" : "Shutdown", 78 | "availability" : "(available)", 79 | "name" : "iPad Pro (9.7 inch)", 80 | "udid" : "0B89526F-FE59-4253-B5C8-5F59F48F4AE6" 81 | }, 82 | { 83 | "state" : "Shutdown", 84 | "availability" : "(available)", 85 | "name" : "iPad Pro (12.9 inch)", 86 | "udid" : "5F8F269D-E643-4E87-915D-12B7D49ED08D" 87 | }, 88 | { 89 | "state" : "Shutdown", 90 | "availability" : "(available)", 91 | "name" : "iPad", 92 | "udid" : "18B5770F-3C49-480E-BEC9-A6748612EBD3" 93 | } 94 | ], 95 | "com.apple.CoreSimulator.SimRuntime.iOS-9-0" : [ 96 | { 97 | "state" : "Shutdown", 98 | "availability" : "(unavailable, runtime profile not found)", 99 | "name" : "iPhone 4s", 100 | "udid" : "84F3616D-0AB5-41EE-A499-89211620898F" 101 | }, 102 | { 103 | "state" : "Shutdown", 104 | "availability" : "(unavailable, runtime profile not found)", 105 | "name" : "iPhone 5", 106 | "udid" : "19C842D1-57D0-407D-AA85-F373FB4D672A" 107 | }, 108 | { 109 | "state" : "Shutdown", 110 | "availability" : "(unavailable, runtime profile not found)", 111 | "name" : "iPhone 5s", 112 | "udid" : "E8ABD8EA-CF53-4A2A-9C91-2760EFAF631D" 113 | }, 114 | { 115 | "state" : "Shutdown", 116 | "availability" : "(unavailable, runtime profile not found)", 117 | "name" : "iPhone 6", 118 | "udid" : "4DFC7897-D8A4-45B3-80B2-44C854B3AD16" 119 | }, 120 | { 121 | "state" : "Shutdown", 122 | "availability" : "(unavailable, runtime profile not found)", 123 | "name" : "iPhone 6 Plus", 124 | "udid" : "5D9864DD-4232-42A3-91F7-F13938CA6CA1" 125 | }, 126 | { 127 | "state" : "Shutdown", 128 | "availability" : "(unavailable, runtime profile not found)", 129 | "name" : "iPhone 6s", 130 | "udid" : "C79C7BB8-1C9D-4415-84CE-A8A246B59F88" 131 | }, 132 | { 133 | "state" : "Shutdown", 134 | "availability" : "(unavailable, runtime profile not found)", 135 | "name" : "iPhone 6s Plus", 136 | "udid" : "876FC4D4-E9E2-4533-8029-22B4F39FA475" 137 | }, 138 | { 139 | "state" : "Shutdown", 140 | "availability" : "(unavailable, runtime profile not found)", 141 | "name" : "iPad 2", 142 | "udid" : "517B90F4-C5B2-4E62-933B-C7FE44C33719" 143 | }, 144 | { 145 | "state" : "Shutdown", 146 | "availability" : "(unavailable, runtime profile not found)", 147 | "name" : "iPad Retina", 148 | "udid" : "EF94A3C6-A354-430F-A18E-CE88957164BA" 149 | }, 150 | { 151 | "state" : "Shutdown", 152 | "availability" : "(unavailable, runtime profile not found)", 153 | "name" : "iPad Air", 154 | "udid" : "A7CF03DE-7E2C-43EB-A2E0-78466C47D815" 155 | }, 156 | { 157 | "state" : "Shutdown", 158 | "availability" : "(unavailable, runtime profile not found)", 159 | "name" : "iPad Air 2", 160 | "udid" : "CF153479-57B4-4312-A6C7-45EE6B9CFC7D" 161 | } 162 | ] 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /spec/fixtures/simctl_xcode_10.1.json: -------------------------------------------------------------------------------- 1 | { 2 | "devices" : { 3 | "iOS 11.0" : [ 4 | { 5 | "state" : "Booted", 6 | "isAvailable" : "YES", 7 | "name" : "iPhone X", 8 | "udid" : "4899944E-F87A-4C26-800D-7FC0AAB23817", 9 | "availabilityError" : "" 10 | } 11 | ], 12 | "iOS 11.4" : [ 13 | { 14 | "state" : "Shutdown", 15 | "isAvailable" : "YES", 16 | "name" : "iPhone 5s", 17 | "udid" : "2E994DAC-0BDB-4553-AF68-E5301ACF446A", 18 | "availabilityError" : "" 19 | }, 20 | { 21 | "state" : "Shutdown", 22 | "isAvailable" : "YES", 23 | "name" : "iPhone 6", 24 | "udid" : "44B35171-767E-4AAF-A2D1-0363659E50F7", 25 | "availabilityError" : "" 26 | }, 27 | { 28 | "state" : "Shutdown", 29 | "isAvailable" : "YES", 30 | "name" : "iPhone 6 Plus", 31 | "udid" : "9B5EA166-71A1-4ED2-85A4-F68B84D7957A", 32 | "availabilityError" : "" 33 | }, 34 | { 35 | "state" : "Shutdown", 36 | "isAvailable" : "YES", 37 | "name" : "iPhone 6s", 38 | "udid" : "AE9196EF-6DF1-47A4-A8F8-6D5DF4DA18FA", 39 | "availabilityError" : "" 40 | }, 41 | { 42 | "state" : "Shutdown", 43 | "isAvailable" : "YES", 44 | "name" : "iPhone 6s Plus", 45 | "udid" : "0EAFB8BD-3EE0-46C0-920D-3CFEE45060F2", 46 | "availabilityError" : "" 47 | }, 48 | { 49 | "state" : "Shutdown", 50 | "isAvailable" : "YES", 51 | "name" : "iPhone 7", 52 | "udid" : "22241710-739D-43DB-AB94-001E58D1FB9C", 53 | "availabilityError" : "" 54 | }, 55 | { 56 | "state" : "Shutdown", 57 | "isAvailable" : "YES", 58 | "name" : "iPhone 7 Plus", 59 | "udid" : "9FC3DA3F-7DF4-40FE-9C24-671902AAF23C", 60 | "availabilityError" : "" 61 | }, 62 | { 63 | "state" : "Shutdown", 64 | "isAvailable" : "YES", 65 | "name" : "iPhone 8", 66 | "udid" : "72E9B28B-28EC-448F-8AB3-47C1F86993E8", 67 | "availabilityError" : "" 68 | }, 69 | { 70 | "state" : "Shutdown", 71 | "isAvailable" : "YES", 72 | "name" : "iPhone 8 Plus", 73 | "udid" : "FB3204E6-81B9-4703-A3A1-92CB5FD9F408", 74 | "availabilityError" : "" 75 | }, 76 | { 77 | "state" : "Shutdown", 78 | "isAvailable" : "YES", 79 | "name" : "iPhone SE", 80 | "udid" : "A534E3E3-F116-472A-9AE3-77D989901961", 81 | "availabilityError" : "" 82 | }, 83 | { 84 | "state" : "Shutdown", 85 | "isAvailable" : "YES", 86 | "name" : "iPhone X", 87 | "udid" : "21A52DF4-8F4F-4FA1-8AE9-5703DBF033B4", 88 | "availabilityError" : "" 89 | }, 90 | { 91 | "state" : "Shutdown", 92 | "isAvailable" : "YES", 93 | "name" : "iPad Air", 94 | "udid" : "1397462D-0C1A-4A93-8FC1-C08CC74F8F6D", 95 | "availabilityError" : "" 96 | }, 97 | { 98 | "state" : "Shutdown", 99 | "isAvailable" : "YES", 100 | "name" : "iPad Air 2", 101 | "udid" : "93FCFE25-29A1-4BE4-BEA6-4862C80E67A4", 102 | "availabilityError" : "" 103 | }, 104 | { 105 | "state" : "Shutdown", 106 | "isAvailable" : "YES", 107 | "name" : "iPad Pro (9.7-inch)", 108 | "udid" : "3BF5A6AB-334D-4657-B460-88F01266D09E", 109 | "availabilityError" : "" 110 | }, 111 | { 112 | "state" : "Shutdown", 113 | "isAvailable" : "YES", 114 | "name" : "iPad Pro (12.9-inch)", 115 | "udid" : "4655EC0D-3AAA-428C-8BAE-B07400DFE930", 116 | "availabilityError" : "" 117 | }, 118 | { 119 | "state" : "Shutdown", 120 | "isAvailable" : "YES", 121 | "name" : "iPad Pro (12.9-inch) (2nd generation)", 122 | "udid" : "03818E09-9942-432E-89C9-B0E1920D1E22", 123 | "availabilityError" : "" 124 | }, 125 | { 126 | "state" : "Shutdown", 127 | "isAvailable" : "YES", 128 | "name" : "iPad Pro (10.5-inch)", 129 | "udid" : "22052EDA-8E5C-4759-90C7-3A5B7B43C1E1", 130 | "availabilityError" : "" 131 | } 132 | ], 133 | "iOS 9.0" : [ 134 | { 135 | "state" : "Shutdown", 136 | "isAvailable" : "YES", 137 | "name" : "iPhone 5s", 138 | "udid" : "E8817E66-AF79-4F9F-89D7-CCC6486BA51A", 139 | "availabilityError" : "" 140 | }, 141 | { 142 | "state" : "Shutdown", 143 | "isAvailable" : "YES", 144 | "name" : "iPhone 6", 145 | "udid" : "3EDAE8EF-C804-4F2C-BBA0-A98640FBB3C7", 146 | "availabilityError" : "" 147 | } 148 | ], 149 | "tvOS 12.0" : [ 150 | { 151 | "state" : "Shutdown", 152 | "isAvailable" : "YES", 153 | "name" : "Apple TV", 154 | "udid" : "A2B8FB15-42C4-4B71-A82C-7EDA72074280", 155 | "availabilityError" : "" 156 | }, 157 | { 158 | "state" : "Shutdown", 159 | "isAvailable" : "YES", 160 | "name" : "Apple TV 4K", 161 | "udid" : "44F2FCEC-7D88-4162-AB27-48F339A727FD", 162 | "availabilityError" : "" 163 | }, 164 | { 165 | "state" : "Shutdown", 166 | "isAvailable" : "YES", 167 | "name" : "Apple TV 4K (at 1080p)", 168 | "udid" : "81BF0B04-8D43-4187-A137-68FBC301C674", 169 | "availabilityError" : "" 170 | } 171 | ], 172 | "watchOS 5.0" : [ 173 | { 174 | "state" : "Shutdown", 175 | "isAvailable" : "YES", 176 | "name" : "Apple Watch Series 2 - 38mm", 177 | "udid" : "FF2A9351-7A0E-4E10-8F9E-4EF6FA449673", 178 | "availabilityError" : "" 179 | }, 180 | { 181 | "state" : "Shutdown", 182 | "isAvailable" : "YES", 183 | "name" : "Apple Watch Series 2 - 42mm", 184 | "udid" : "A77B9482-0ABD-4868-9BF5-B744BECAE332", 185 | "availabilityError" : "" 186 | }, 187 | { 188 | "state" : "Shutdown", 189 | "isAvailable" : "YES", 190 | "name" : "Apple Watch Series 3 - 38mm", 191 | "udid" : "8287FC68-2835-49FD-B7F2-71F29864B1C2", 192 | "availabilityError" : "" 193 | }, 194 | { 195 | "state" : "Shutdown", 196 | "isAvailable" : "YES", 197 | "name" : "Apple Watch Series 3 - 42mm", 198 | "udid" : "7D77B634-E72C-4978-9ABE-5C546D93656F", 199 | "availabilityError" : "" 200 | }, 201 | { 202 | "state" : "Shutdown", 203 | "isAvailable" : "YES", 204 | "name" : "Apple Watch Series 4 - 40mm", 205 | "udid" : "FF9F638C-6DBC-4C04-9A91-7A9E347AFCEF", 206 | "availabilityError" : "" 207 | }, 208 | { 209 | "state" : "Shutdown", 210 | "isAvailable" : "YES", 211 | "name" : "Apple Watch Series 4 - 44mm", 212 | "udid" : "B426F7E3-D256-4A24-8EF8-7B7A60F35834", 213 | "availabilityError" : "" 214 | } 215 | ], 216 | "iOS 8.1" : [ 217 | { 218 | "state" : "Shutdown", 219 | "isAvailable" : "YES", 220 | "name" : "iPhone 6", 221 | "udid" : "72A4CC6A-85DF-4BAE-8744-E7A960BFF57E", 222 | "availabilityError" : "" 223 | } 224 | ], 225 | "watchOS 2.0" : [ 226 | { 227 | "state" : "Shutdown", 228 | "isAvailable" : "YES", 229 | "name" : "Apple Watch - 38mm", 230 | "udid" : "F9E3A138-4E06-4AA8-AE33-64FBC28DC7B6", 231 | "availabilityError" : "" 232 | } 233 | ], 234 | "iOS 12.0" : [ 235 | { 236 | "state" : "Shutdown", 237 | "isAvailable" : "YES", 238 | "name" : "iPhone 5s", 239 | "udid" : "5A797FFB-2C02-4598-8430-632CF619965A", 240 | "availabilityError" : "" 241 | }, 242 | { 243 | "state" : "Shutdown", 244 | "isAvailable" : "YES", 245 | "name" : "iPhone 6", 246 | "udid" : "40060469-ABD3-4621-B474-041A3BC5FD50", 247 | "availabilityError" : "" 248 | }, 249 | { 250 | "state" : "Shutdown", 251 | "isAvailable" : "YES", 252 | "name" : "iPhone 6 Plus", 253 | "udid" : "13672C98-8801-434D-9165-ABED7065641D", 254 | "availabilityError" : "" 255 | }, 256 | { 257 | "state" : "Shutdown", 258 | "isAvailable" : "YES", 259 | "name" : "iPhone 6s", 260 | "udid" : "5A9286F9-AA36-4D67-A906-AC1258B82762", 261 | "availabilityError" : "" 262 | }, 263 | { 264 | "state" : "Shutdown", 265 | "isAvailable" : "YES", 266 | "name" : "iPhone 6s Plus", 267 | "udid" : "24FCE76E-5310-4D85-A338-A3629A92D712", 268 | "availabilityError" : "" 269 | }, 270 | { 271 | "state" : "Shutdown", 272 | "isAvailable" : "YES", 273 | "name" : "iPhone 7", 274 | "udid" : "EDBDE1CE-C9D2-4FAF-A685-19302E7467AA", 275 | "availabilityError" : "" 276 | }, 277 | { 278 | "state" : "Shutdown", 279 | "isAvailable" : "YES", 280 | "name" : "iPhone 7 Plus", 281 | "udid" : "E2A13F05-0DD5-4761-B2A3-F7931373F86A", 282 | "availabilityError" : "" 283 | }, 284 | { 285 | "state" : "Shutdown", 286 | "isAvailable" : "YES", 287 | "name" : "iPhone 8", 288 | "udid" : "7729F176-A650-4E90-BF18-FBB39EEA964A", 289 | "availabilityError" : "" 290 | }, 291 | { 292 | "state" : "Shutdown", 293 | "isAvailable" : "YES", 294 | "name" : "iPhone 8 Plus", 295 | "udid" : "854925AF-5753-4853-BC01-DB0EC30EB055", 296 | "availabilityError" : "" 297 | }, 298 | { 299 | "state" : "Shutdown", 300 | "isAvailable" : "YES", 301 | "name" : "iPhone SE", 302 | "udid" : "B1728833-2FEB-4509-9F29-9AE0C9756E05", 303 | "availabilityError" : "" 304 | }, 305 | { 306 | "state" : "Shutdown", 307 | "isAvailable" : "YES", 308 | "name" : "iPhone X", 309 | "udid" : "BA5A32CE-FBDA-4175-A237-AF144AF3FCC9", 310 | "availabilityError" : "" 311 | }, 312 | { 313 | "state" : "Shutdown", 314 | "isAvailable" : "YES", 315 | "name" : "iPhone XR", 316 | "udid" : "B91D416A-AE82-4500-A5E3-F0B5912036AB", 317 | "availabilityError" : "" 318 | }, 319 | { 320 | "state" : "Shutdown", 321 | "isAvailable" : "YES", 322 | "name" : "iPhone XS", 323 | "udid" : "7807CD77-2C7F-43C0-8098-2C94C3FDEDE9", 324 | "availabilityError" : "" 325 | }, 326 | { 327 | "state" : "Shutdown", 328 | "isAvailable" : "YES", 329 | "name" : "iPhone XS Max", 330 | "udid" : "E4691728-FAEE-4C55-ACBA-912DDDE8BA19", 331 | "availabilityError" : "" 332 | }, 333 | { 334 | "state" : "Shutdown", 335 | "isAvailable" : "YES", 336 | "name" : "iPad Air", 337 | "udid" : "48C9CC87-2305-449D-95EA-B66B4DA80975", 338 | "availabilityError" : "" 339 | }, 340 | { 341 | "state" : "Shutdown", 342 | "isAvailable" : "YES", 343 | "name" : "iPad Air 2", 344 | "udid" : "927EF1C1-0095-40EC-B152-5B0AD9B48A99", 345 | "availabilityError" : "" 346 | }, 347 | { 348 | "state" : "Shutdown", 349 | "isAvailable" : "YES", 350 | "name" : "iPad (5th generation)", 351 | "udid" : "BECA510F-E7C5-450A-B97B-A3DD57FC70E7", 352 | "availabilityError" : "" 353 | }, 354 | { 355 | "state" : "Shutdown", 356 | "isAvailable" : "YES", 357 | "name" : "iPad Pro (9.7-inch)", 358 | "udid" : "78C0A393-5E94-483A-BF16-E520EBB17743", 359 | "availabilityError" : "" 360 | }, 361 | { 362 | "state" : "Shutdown", 363 | "isAvailable" : "YES", 364 | "name" : "iPad Pro (12.9-inch)", 365 | "udid" : "730CFA68-0436-4D5A-9FFA-D87CBD4EC715", 366 | "availabilityError" : "" 367 | }, 368 | { 369 | "state" : "Shutdown", 370 | "isAvailable" : "YES", 371 | "name" : "iPad Pro (12.9-inch) (2nd generation)", 372 | "udid" : "941F85BE-00FC-4C43-B973-08FEB67DE874", 373 | "availabilityError" : "" 374 | }, 375 | { 376 | "state" : "Shutdown", 377 | "isAvailable" : "YES", 378 | "name" : "iPad Pro (10.5-inch)", 379 | "udid" : "293BD8F2-69CA-4679-AE8B-CA1F7C3C0778", 380 | "availabilityError" : "" 381 | }, 382 | { 383 | "state" : "Shutdown", 384 | "isAvailable" : "YES", 385 | "name" : "iPad (6th generation)", 386 | "udid" : "AADFD6CD-008A-4EF0-94FB-DA692C3E2670", 387 | "availabilityError" : "" 388 | } 389 | ] 390 | } 391 | } 392 | -------------------------------------------------------------------------------- /spec/fixtures/simctl_xcode_11.0.json: -------------------------------------------------------------------------------- 1 | { 2 | "devicetypes" : [ 3 | { 4 | "name" : "iPhone 4s", 5 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/iPhone 4s.simdevicetype", 6 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.iPhone-4s" 7 | }, 8 | { 9 | "name" : "iPhone 5", 10 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/iPhone 5.simdevicetype", 11 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.iPhone-5" 12 | }, 13 | { 14 | "name" : "iPhone 5s", 15 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/iPhone 5s.simdevicetype", 16 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.iPhone-5s" 17 | }, 18 | { 19 | "name" : "iPhone 6", 20 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/iPhone 6.simdevicetype", 21 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.iPhone-6" 22 | }, 23 | { 24 | "name" : "iPhone 6 Plus", 25 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/iPhone 6 Plus.simdevicetype", 26 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.iPhone-6-Plus" 27 | }, 28 | { 29 | "name" : "iPhone 6s", 30 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/iPhone 6s.simdevicetype", 31 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.iPhone-6s" 32 | }, 33 | { 34 | "name" : "iPhone 6s Plus", 35 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/iPhone 6s Plus.simdevicetype", 36 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.iPhone-6s-Plus" 37 | }, 38 | { 39 | "name" : "iPhone 7", 40 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/iPhone 7.simdevicetype", 41 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.iPhone-7" 42 | }, 43 | { 44 | "name" : "iPhone 7 Plus", 45 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/iPhone 7 Plus.simdevicetype", 46 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.iPhone-7-Plus" 47 | }, 48 | { 49 | "name" : "iPhone 8", 50 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/iPhone 8.simdevicetype", 51 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.iPhone-8" 52 | }, 53 | { 54 | "name" : "iPhone 8 Plus", 55 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/iPhone 8 Plus.simdevicetype", 56 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.iPhone-8-Plus" 57 | }, 58 | { 59 | "name" : "iPhone SE", 60 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/iPhone SE.simdevicetype", 61 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.iPhone-SE" 62 | }, 63 | { 64 | "name" : "iPhone X", 65 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/iPhone X.simdevicetype", 66 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.iPhone-X" 67 | }, 68 | { 69 | "name" : "iPhone Xs", 70 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/iPhone Xs.simdevicetype", 71 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.iPhone-XS" 72 | }, 73 | { 74 | "name" : "iPhone Xs Max", 75 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/iPhone Xs Max.simdevicetype", 76 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.iPhone-XS-Max" 77 | }, 78 | { 79 | "name" : "iPhone Xʀ", 80 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/iPhone Xʀ.simdevicetype", 81 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.iPhone-XR" 82 | }, 83 | { 84 | "name" : "iPad 2", 85 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/iPad 2.simdevicetype", 86 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.iPad-2" 87 | }, 88 | { 89 | "name" : "iPad Retina", 90 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/iPad Retina.simdevicetype", 91 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.iPad-Retina" 92 | }, 93 | { 94 | "name" : "iPad Air", 95 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/iPad Air.simdevicetype", 96 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.iPad-Air" 97 | }, 98 | { 99 | "name" : "iPad mini 2", 100 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/iPad mini 2.simdevicetype", 101 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.iPad-mini-2" 102 | }, 103 | { 104 | "name" : "iPad mini 3", 105 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/iPad mini 3.simdevicetype", 106 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.iPad-mini-3" 107 | }, 108 | { 109 | "name" : "iPad mini 4", 110 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/iPad mini 4.simdevicetype", 111 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.iPad-mini-4" 112 | }, 113 | { 114 | "name" : "iPad Air 2", 115 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/iPad Air 2.simdevicetype", 116 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.iPad-Air-2" 117 | }, 118 | { 119 | "name" : "iPad Pro (9.7-inch)", 120 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/iPad Pro (9.7-inch).simdevicetype", 121 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.iPad-Pro--9-7-inch-" 122 | }, 123 | { 124 | "name" : "iPad Pro (12.9-inch)", 125 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/iPad Pro (12.9-inch).simdevicetype", 126 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.iPad-Pro" 127 | }, 128 | { 129 | "name" : "iPad (5th generation)", 130 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/iPad (5th generation).simdevicetype", 131 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.iPad--5th-generation-" 132 | }, 133 | { 134 | "name" : "iPad Pro (12.9-inch) (2nd generation)", 135 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/iPad Pro (12.9-inch) (2nd generation).simdevicetype", 136 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.iPad-Pro--12-9-inch---2nd-generation-" 137 | }, 138 | { 139 | "name" : "iPad Pro (10.5-inch)", 140 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/iPad Pro (10.5-inch).simdevicetype", 141 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.iPad-Pro--10-5-inch-" 142 | }, 143 | { 144 | "name" : "iPad (6th generation)", 145 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/iPad (6th generation).simdevicetype", 146 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.iPad--6th-generation-" 147 | }, 148 | { 149 | "name" : "iPad Pro (11-inch)", 150 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/iPad Pro (11-inch).simdevicetype", 151 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.iPad-Pro--11-inch-" 152 | }, 153 | { 154 | "name" : "iPad Pro (12.9-inch) (3rd generation)", 155 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/iPad Pro (12.9-inch) (3rd generation).simdevicetype", 156 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.iPad-Pro--12-9-inch---3rd-generation-" 157 | }, 158 | { 159 | "name" : "iPad mini (5th generation)", 160 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/iPad mini (5th generation).simdevicetype", 161 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.iPad-mini--5th-generation-" 162 | }, 163 | { 164 | "name" : "iPad Air (3rd generation)", 165 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/iPad Air (3rd generation).simdevicetype", 166 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.iPad-Air--3rd-generation-" 167 | }, 168 | { 169 | "name" : "Apple TV", 170 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/AppleTVOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/Apple TV.simdevicetype", 171 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.Apple-TV-1080p" 172 | }, 173 | { 174 | "name" : "Apple TV 4K", 175 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/AppleTVOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/Apple TV 4K.simdevicetype", 176 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.Apple-TV-4K-4K" 177 | }, 178 | { 179 | "name" : "Apple TV 4K (at 1080p)", 180 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/AppleTVOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/Apple TV 4K (at 1080p).simdevicetype", 181 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.Apple-TV-4K-1080p" 182 | }, 183 | { 184 | "name" : "Apple Watch - 38mm", 185 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/WatchOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/Apple Watch - 38mm.simdevicetype", 186 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.Apple-Watch-38mm" 187 | }, 188 | { 189 | "name" : "Apple Watch - 42mm", 190 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/WatchOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/Apple Watch - 42mm.simdevicetype", 191 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.Apple-Watch-42mm" 192 | }, 193 | { 194 | "name" : "Apple Watch Series 2 - 38mm", 195 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/WatchOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/Apple Watch Series 2 - 38mm.simdevicetype", 196 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.Apple-Watch-Series-2-38mm" 197 | }, 198 | { 199 | "name" : "Apple Watch Series 2 - 42mm", 200 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/WatchOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/Apple Watch Series 2 - 42mm.simdevicetype", 201 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.Apple-Watch-Series-2-42mm" 202 | }, 203 | { 204 | "name" : "Apple Watch Series 3 - 38mm", 205 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/WatchOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/Apple Watch Series 3 - 38mm.simdevicetype", 206 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.Apple-Watch-Series-3-38mm" 207 | }, 208 | { 209 | "name" : "Apple Watch Series 3 - 42mm", 210 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/WatchOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/Apple Watch Series 3 - 42mm.simdevicetype", 211 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.Apple-Watch-Series-3-42mm" 212 | }, 213 | { 214 | "name" : "Apple Watch Series 4 - 40mm", 215 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/WatchOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/Apple Watch Series 4 - 40mm.simdevicetype", 216 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.Apple-Watch-Series-4-40mm" 217 | }, 218 | { 219 | "name" : "Apple Watch Series 4 - 44mm", 220 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/WatchOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/DeviceTypes\/Apple Watch Series 4 - 44mm.simdevicetype", 221 | "identifier" : "com.apple.CoreSimulator.SimDeviceType.Apple-Watch-Series-4-44mm" 222 | } 223 | ], 224 | "runtimes" : [ 225 | { 226 | "version" : "9.3", 227 | "bundlePath" : "\/Library\/Developer\/CoreSimulator\/Profiles\/Runtimes\/iOS 9.3.simruntime", 228 | "isAvailable" : true, 229 | "name" : "iOS 9.3", 230 | "identifier" : "com.apple.CoreSimulator.SimRuntime.iOS-9-3", 231 | "buildversion" : "13E233" 232 | }, 233 | { 234 | "version" : "10.3.1", 235 | "bundlePath" : "\/Library\/Developer\/CoreSimulator\/Profiles\/Runtimes\/iOS 10.3.simruntime", 236 | "isAvailable" : true, 237 | "name" : "iOS 10.3", 238 | "identifier" : "com.apple.CoreSimulator.SimRuntime.iOS-10-3", 239 | "buildversion" : "14E8301" 240 | }, 241 | { 242 | "version" : "11.4", 243 | "bundlePath" : "\/Library\/Developer\/CoreSimulator\/Profiles\/Runtimes\/iOS 11.4.simruntime", 244 | "isAvailable" : true, 245 | "name" : "iOS 11.4", 246 | "identifier" : "com.apple.CoreSimulator.SimRuntime.iOS-11-4", 247 | "buildversion" : "15F79" 248 | }, 249 | { 250 | "version" : "12.2", 251 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/Runtimes\/iOS.simruntime", 252 | "isAvailable" : true, 253 | "name" : "iOS 12.2", 254 | "identifier" : "com.apple.CoreSimulator.SimRuntime.iOS-12-2", 255 | "buildversion" : "16E226" 256 | }, 257 | { 258 | "version" : "12.2", 259 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/AppleTVOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/Runtimes\/tvOS.simruntime", 260 | "isAvailable" : true, 261 | "name" : "tvOS 12.2", 262 | "identifier" : "com.apple.CoreSimulator.SimRuntime.tvOS-12-2", 263 | "buildversion" : "16L225" 264 | }, 265 | { 266 | "version" : "5.2", 267 | "bundlePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/WatchOS.platform\/Developer\/Library\/CoreSimulator\/Profiles\/Runtimes\/watchOS.simruntime", 268 | "isAvailable" : true, 269 | "name" : "watchOS 5.2", 270 | "identifier" : "com.apple.CoreSimulator.SimRuntime.watchOS-5-2", 271 | "buildversion" : "16T224" 272 | } 273 | ], 274 | "devices" : { 275 | "com.apple.CoreSimulator.SimRuntime.iOS-12-2" : [ 276 | { 277 | "state" : "Shutdown", 278 | "isAvailable" : true, 279 | "name" : "iPhone 5s", 280 | "udid" : "F0311D14-2473-4B62-A2D0-A5F0D1FE7EBC" 281 | }, 282 | { 283 | "state" : "Shutdown", 284 | "isAvailable" : true, 285 | "name" : "iPhone 6", 286 | "udid" : "A0143BE7-9341-4C08-9C1E-A3AF260D2633" 287 | }, 288 | { 289 | "state" : "Shutdown", 290 | "isAvailable" : true, 291 | "name" : "iPhone 6 Plus", 292 | "udid" : "1EE98DD5-5735-4211-B51B-F601F7C1BFC7" 293 | }, 294 | { 295 | "state" : "Shutdown", 296 | "isAvailable" : true, 297 | "name" : "iPhone 6s", 298 | "udid" : "EF9E6382-635D-43C1-8B5A-E11E2CA5C075" 299 | }, 300 | { 301 | "state" : "Shutdown", 302 | "isAvailable" : true, 303 | "name" : "iPhone 6s Plus", 304 | "udid" : "E1C56A31-7DF3-4021-864E-9E5106D53852" 305 | }, 306 | { 307 | "state" : "Shutdown", 308 | "isAvailable" : true, 309 | "name" : "iPhone 7", 310 | "udid" : "307214E0-278C-4418-8D29-F0CE867AA190" 311 | }, 312 | { 313 | "state" : "Shutdown", 314 | "isAvailable" : true, 315 | "name" : "iPhone 7 Plus", 316 | "udid" : "A1382E12-EF11-498F-BBDA-9DF926ECC611" 317 | }, 318 | { 319 | "state" : "Shutdown", 320 | "isAvailable" : true, 321 | "name" : "iPhone 8", 322 | "udid" : "7648DEA6-465D-436C-B477-B7F6C29665F0" 323 | }, 324 | { 325 | "state" : "Shutdown", 326 | "isAvailable" : true, 327 | "name" : "iPhone 8 Plus", 328 | "udid" : "CDF78B28-15EE-4F5B-8C72-037EA7A950BF" 329 | }, 330 | { 331 | "state" : "Shutdown", 332 | "isAvailable" : true, 333 | "name" : "iPhone SE", 334 | "udid" : "0F801E2F-DBDA-40CE-A365-9BB4073A99BB" 335 | }, 336 | { 337 | "state" : "Shutdown", 338 | "isAvailable" : true, 339 | "name" : "iPhone X", 340 | "udid" : "C0F2B9D4-D136-477C-90FA-CAD00A61A157" 341 | }, 342 | { 343 | "state" : "Shutdown", 344 | "isAvailable" : true, 345 | "name" : "iPhone Xs", 346 | "udid" : "2B7A5017-6784-42F7-9B5B-C2ADE7427A19" 347 | }, 348 | { 349 | "state" : "Shutdown", 350 | "isAvailable" : true, 351 | "name" : "iPhone Xs Max", 352 | "udid" : "115CDBCF-92D9-4B62-A694-E5D0D3B8BF8B" 353 | }, 354 | { 355 | "state" : "Shutdown", 356 | "isAvailable" : true, 357 | "name" : "iPhone Xʀ", 358 | "udid" : "CEEBBC11-C0D0-4F63-B056-2BC109C1BC54" 359 | }, 360 | { 361 | "state" : "Shutdown", 362 | "isAvailable" : true, 363 | "name" : "iPad Air", 364 | "udid" : "749092B2-0CCB-49BF-8BD2-53B41148A802" 365 | }, 366 | { 367 | "state" : "Shutdown", 368 | "isAvailable" : true, 369 | "name" : "iPad Air 2", 370 | "udid" : "4580F159-23E6-41A6-BA62-33804E786134" 371 | }, 372 | { 373 | "state" : "Shutdown", 374 | "isAvailable" : true, 375 | "name" : "iPad Pro (9.7-inch)", 376 | "udid" : "BCC1A4CE-6941-4F04-9A44-E87DA6AA2ABF" 377 | }, 378 | { 379 | "state" : "Shutdown", 380 | "isAvailable" : true, 381 | "name" : "iPad Pro (12.9-inch)", 382 | "udid" : "9090B4BE-E5BD-458C-8BFF-E3B4270AE3FE" 383 | }, 384 | { 385 | "state" : "Shutdown", 386 | "isAvailable" : true, 387 | "name" : "iPad (5th generation)", 388 | "udid" : "58508E72-5882-409C-B150-96043D4410D4" 389 | }, 390 | { 391 | "state" : "Shutdown", 392 | "isAvailable" : true, 393 | "name" : "iPad Pro (12.9-inch) (2nd generation)", 394 | "udid" : "86C0FDE3-7741-4474-9C3E-ECA9E6EB2461" 395 | }, 396 | { 397 | "state" : "Shutdown", 398 | "isAvailable" : true, 399 | "name" : "iPad Pro (10.5-inch)", 400 | "udid" : "884C9657-C229-41BB-9A2E-F45591042FAB" 401 | }, 402 | { 403 | "state" : "Shutdown", 404 | "isAvailable" : true, 405 | "name" : "iPad (6th generation)", 406 | "udid" : "0BDE3533-1D75-4398-962F-C9BF3CE690AF" 407 | }, 408 | { 409 | "state" : "Shutdown", 410 | "isAvailable" : true, 411 | "name" : "iPad Pro (11-inch)", 412 | "udid" : "ECCFA6BA-4F85-44D7-A8FA-38548F4C0350" 413 | }, 414 | { 415 | "state" : "Shutdown", 416 | "isAvailable" : true, 417 | "name" : "iPad Pro (12.9-inch) (3rd generation)", 418 | "udid" : "275B3229-AA26-4F18-8860-7E85516DFCE3" 419 | }, 420 | { 421 | "state" : "Shutdown", 422 | "isAvailable" : true, 423 | "name" : "iPad Air (3rd generation)", 424 | "udid" : "EBB5BE83-6848-41F4-AE21-ADE335FB67A6" 425 | } 426 | ], 427 | "com.apple.CoreSimulator.SimRuntime.tvOS-12-2" : [ 428 | { 429 | "state" : "Shutdown", 430 | "isAvailable" : true, 431 | "name" : "Apple TV", 432 | "udid" : "2ED0EE69-AF3A-49C5-BBFF-49F5E88AEF8E" 433 | }, 434 | { 435 | "state" : "Shutdown", 436 | "isAvailable" : true, 437 | "name" : "Apple TV 4K", 438 | "udid" : "9362B6C7-1C27-47A0-B0A2-929B0098E853" 439 | }, 440 | { 441 | "state" : "Shutdown", 442 | "isAvailable" : true, 443 | "name" : "Apple TV 4K (at 1080p)", 444 | "udid" : "74D6D58C-2348-40CD-85DA-7E8C466B08F4" 445 | } 446 | ], 447 | "com.apple.CoreSimulator.SimRuntime.iOS-11-4" : [ 448 | { 449 | "state" : "Shutdown", 450 | "isAvailable" : true, 451 | "name" : "iPhone 5s", 452 | "udid" : "2A2A27E5-5032-4656-8BA8-5362DCA686B1" 453 | }, 454 | { 455 | "state" : "Shutdown", 456 | "isAvailable" : true, 457 | "name" : "iPhone 6", 458 | "udid" : "D79ABD57-FFF8-4432-809C-387D915B805B" 459 | }, 460 | { 461 | "state" : "Shutdown", 462 | "isAvailable" : true, 463 | "name" : "iPhone 6 Plus", 464 | "udid" : "8DAA2007-6A4C-4CA5-8985-B83D0A6A06DD" 465 | }, 466 | { 467 | "state" : "Shutdown", 468 | "isAvailable" : true, 469 | "name" : "iPhone 6s", 470 | "udid" : "84082E71-99BA-4DF1-A3A0-6F85BB030F78" 471 | }, 472 | { 473 | "state" : "Shutdown", 474 | "isAvailable" : true, 475 | "name" : "iPhone 6s Plus", 476 | "udid" : "13AB68AD-61B4-495C-BF95-89527D32E0DB" 477 | }, 478 | { 479 | "state" : "Shutdown", 480 | "isAvailable" : true, 481 | "name" : "iPhone 7", 482 | "udid" : "2E7EB6C9-06BC-4D1B-8E62-AF85E3D49F2C" 483 | }, 484 | { 485 | "state" : "Shutdown", 486 | "isAvailable" : true, 487 | "name" : "iPhone 7 Plus", 488 | "udid" : "E6B354AE-6CBA-4DD9-BD49-10ADF386E7CD" 489 | }, 490 | { 491 | "state" : "Shutdown", 492 | "isAvailable" : true, 493 | "name" : "iPhone 8", 494 | "udid" : "0AFFA91B-3BFE-4EE5-86A9-BD62ABB63A37" 495 | }, 496 | { 497 | "state" : "Shutdown", 498 | "isAvailable" : true, 499 | "name" : "iPhone 8 Plus", 500 | "udid" : "ECD80978-77E4-402A-BC71-A7A4AFA3F7C7" 501 | }, 502 | { 503 | "state" : "Shutdown", 504 | "isAvailable" : true, 505 | "name" : "iPhone SE", 506 | "udid" : "C41F2103-CCBE-4F92-A919-CC8F6732465C" 507 | }, 508 | { 509 | "state" : "Shutdown", 510 | "isAvailable" : true, 511 | "name" : "iPhone X", 512 | "udid" : "F2F5197B-6EDF-4B3B-9A95-A66F7C5B45FF" 513 | }, 514 | { 515 | "state" : "Shutdown", 516 | "isAvailable" : true, 517 | "name" : "iPad Air", 518 | "udid" : "956905D3-58FF-441E-913F-2A7A72AE24BE" 519 | }, 520 | { 521 | "state" : "Shutdown", 522 | "isAvailable" : true, 523 | "name" : "iPad Air 2", 524 | "udid" : "7ADE540F-FEF6-494C-888F-34C504C7BDEA" 525 | }, 526 | { 527 | "state" : "Shutdown", 528 | "isAvailable" : true, 529 | "name" : "iPad Pro (9.7-inch)", 530 | "udid" : "DB60DCBD-E575-4D7E-A6DA-12BDCABD95C1" 531 | }, 532 | { 533 | "state" : "Shutdown", 534 | "isAvailable" : true, 535 | "name" : "iPad Pro (12.9-inch)", 536 | "udid" : "D595816C-40B6-40E2-BEA3-0DE28B53A5D0" 537 | }, 538 | { 539 | "state" : "Shutdown", 540 | "isAvailable" : true, 541 | "name" : "iPad (5th generation)", 542 | "udid" : "ADF1A30B-92C7-40A4-BE40-67B0A0E5BFDA" 543 | }, 544 | { 545 | "state" : "Shutdown", 546 | "isAvailable" : true, 547 | "name" : "iPad Pro (12.9-inch) (2nd generation)", 548 | "udid" : "B24EB98C-6D21-4049-98DC-B39FE9FB9382" 549 | }, 550 | { 551 | "state" : "Shutdown", 552 | "isAvailable" : true, 553 | "name" : "iPad Pro (10.5-inch)", 554 | "udid" : "3CB87F75-691F-49DB-8475-C4AA431C442D" 555 | }, 556 | { 557 | "state" : "Shutdown", 558 | "isAvailable" : true, 559 | "name" : "iPad (6th generation)", 560 | "udid" : "3B1371B4-752F-497A-A702-9C9B9A66F346" 561 | } 562 | ], 563 | "com.apple.CoreSimulator.SimRuntime.watchOS-5-2" : [ 564 | { 565 | "state" : "Shutdown", 566 | "isAvailable" : true, 567 | "name" : "Apple Watch Series 2 - 38mm", 568 | "udid" : "B224EEC2-B28D-420F-A2C8-EFBEC9B36745" 569 | }, 570 | { 571 | "state" : "Shutdown", 572 | "isAvailable" : true, 573 | "name" : "Apple Watch Series 2 - 42mm", 574 | "udid" : "F3A79223-7156-48C5-979F-803314260C94" 575 | }, 576 | { 577 | "state" : "Shutdown", 578 | "isAvailable" : true, 579 | "name" : "Apple Watch Series 3 - 38mm", 580 | "udid" : "F68324A2-BBDA-44B8-9E84-99BB61314D77" 581 | }, 582 | { 583 | "state" : "Shutdown", 584 | "isAvailable" : true, 585 | "name" : "Apple Watch Series 3 - 42mm", 586 | "udid" : "BB0DF06A-30F1-4171-899D-7D13BD01C420" 587 | }, 588 | { 589 | "state" : "Shutdown", 590 | "isAvailable" : true, 591 | "name" : "Apple Watch Series 4 - 40mm", 592 | "udid" : "43DC4548-62E8-4B67-8363-398985A0C330" 593 | }, 594 | { 595 | "state" : "Shutdown", 596 | "isAvailable" : true, 597 | "name" : "Apple Watch Series 4 - 44mm", 598 | "udid" : "6D13AA88-9E2E-4185-AE50-423A1EE1CA3E" 599 | } 600 | ], 601 | "com.apple.CoreSimulator.SimRuntime.iOS-9-3" : [ 602 | { 603 | "state" : "Shutdown", 604 | "isAvailable" : true, 605 | "name" : "iPhone 4s", 606 | "udid" : "273EECC5-6BB6-4A9F-8439-5EF8A7CA93E9" 607 | }, 608 | { 609 | "state" : "Shutdown", 610 | "isAvailable" : true, 611 | "name" : "iPhone 5", 612 | "udid" : "31B5E14C-47C8-45F1-B556-64F48225530C" 613 | }, 614 | { 615 | "state" : "Shutdown", 616 | "isAvailable" : true, 617 | "name" : "iPhone 5s", 618 | "udid" : "2234A887-CDBE-4A83-9B24-A7BFB7D7631A" 619 | }, 620 | { 621 | "state" : "Shutdown", 622 | "isAvailable" : true, 623 | "name" : "iPhone 6", 624 | "udid" : "B687C3E8-171B-4337-A0DB-C6F43C3410B8" 625 | }, 626 | { 627 | "state" : "Shutdown", 628 | "isAvailable" : true, 629 | "name" : "iPhone 6 Plus", 630 | "udid" : "63DE67D1-C176-4B9F-B948-465C82075E76" 631 | }, 632 | { 633 | "state" : "Shutdown", 634 | "isAvailable" : true, 635 | "name" : "iPhone 6s", 636 | "udid" : "BDF8D2A9-5A20-407E-AF25-F1AF41D620A2" 637 | }, 638 | { 639 | "state" : "Shutdown", 640 | "isAvailable" : true, 641 | "name" : "iPhone 6s Plus", 642 | "udid" : "06C08D5C-016B-4EA1-B5B2-EF4585325489" 643 | }, 644 | { 645 | "state" : "Shutdown", 646 | "isAvailable" : true, 647 | "name" : "iPad 2", 648 | "udid" : "406B309B-88DF-4369-917D-E2680A195BF0" 649 | }, 650 | { 651 | "state" : "Shutdown", 652 | "isAvailable" : true, 653 | "name" : "iPad Retina", 654 | "udid" : "7473AA5D-801A-4771-8608-26D9E8C6F670" 655 | }, 656 | { 657 | "state" : "Shutdown", 658 | "isAvailable" : true, 659 | "name" : "iPad Air", 660 | "udid" : "F44AC422-3E5C-4C00-89BB-E0D404FB8884" 661 | }, 662 | { 663 | "state" : "Shutdown", 664 | "isAvailable" : true, 665 | "name" : "iPad Air 2", 666 | "udid" : "0F57798B-28ED-4EAA-B959-066FC7495113" 667 | }, 668 | { 669 | "state" : "Shutdown", 670 | "isAvailable" : true, 671 | "name" : "iPad Pro", 672 | "udid" : "92FB00E6-C499-444B-BD23-D42547AD2015" 673 | } 674 | ], 675 | "com.apple.CoreSimulator.SimRuntime.iOS-10-3" : [ 676 | { 677 | "state" : "Shutdown", 678 | "isAvailable" : true, 679 | "name" : "iPhone 5", 680 | "udid" : "040E47BF-B96D-46A9-83EA-4E4FB3595171" 681 | }, 682 | { 683 | "state" : "Shutdown", 684 | "isAvailable" : true, 685 | "name" : "iPhone 5s", 686 | "udid" : "5DDDF71B-D27D-4EBF-8228-591B8F530F9F" 687 | }, 688 | { 689 | "state" : "Shutdown", 690 | "isAvailable" : true, 691 | "name" : "iPhone 6", 692 | "udid" : "B622B2CE-029D-4666-88FA-7A759CE4121D" 693 | }, 694 | { 695 | "state" : "Shutdown", 696 | "isAvailable" : true, 697 | "name" : "iPhone 6 Plus", 698 | "udid" : "F5B4049F-1883-4E5F-A284-A82AC6617AB6" 699 | }, 700 | { 701 | "state" : "Shutdown", 702 | "isAvailable" : true, 703 | "name" : "iPhone 6s", 704 | "udid" : "FF8C87A3-135E-4D35-BD61-5756378CD94F" 705 | }, 706 | { 707 | "state" : "Shutdown", 708 | "isAvailable" : true, 709 | "name" : "iPhone 6s Plus", 710 | "udid" : "053BB7E9-6A23-4BAC-BFAB-55D4F6266F50" 711 | }, 712 | { 713 | "state" : "Shutdown", 714 | "isAvailable" : true, 715 | "name" : "iPhone 7", 716 | "udid" : "FB747768-8C04-47BF-BBC2-FDFC34062254" 717 | }, 718 | { 719 | "state" : "Shutdown", 720 | "isAvailable" : true, 721 | "name" : "iPhone 7 Plus", 722 | "udid" : "F37A672D-B869-4B13-AD98-31893719C9F1" 723 | }, 724 | { 725 | "state" : "Shutdown", 726 | "isAvailable" : true, 727 | "name" : "iPhone SE", 728 | "udid" : "3F85F703-3CEE-416B-ACF4-7581EEB33D53" 729 | }, 730 | { 731 | "state" : "Shutdown", 732 | "isAvailable" : true, 733 | "name" : "iPad Air", 734 | "udid" : "94376131-6EBA-42A3-9BCD-8FB700959055" 735 | }, 736 | { 737 | "state" : "Shutdown", 738 | "isAvailable" : true, 739 | "name" : "iPad Air 2", 740 | "udid" : "2B164CEA-478D-4778-A84A-A8C1C7764286" 741 | }, 742 | { 743 | "state" : "Shutdown", 744 | "isAvailable" : true, 745 | "name" : "iPad Pro (9.7 inch)", 746 | "udid" : "E7F8739A-C3BC-4993-930E-DC68562A46FB" 747 | }, 748 | { 749 | "state" : "Shutdown", 750 | "isAvailable" : true, 751 | "name" : "iPad Pro (12.9 inch)", 752 | "udid" : "56E3B957-C434-4A80-B6A4-64764787A6AD" 753 | }, 754 | { 755 | "state" : "Shutdown", 756 | "isAvailable" : true, 757 | "name" : "iPad (5th generation)", 758 | "udid" : "79694815-C6D5-4A84-85DF-D153A011B9AB" 759 | }, 760 | { 761 | "state" : "Shutdown", 762 | "isAvailable" : true, 763 | "name" : "iPad Pro (12.9-inch) (2nd generation)", 764 | "udid" : "E6D3A8E1-7973-4ABA-BA83-623D29D46463" 765 | }, 766 | { 767 | "state" : "Shutdown", 768 | "isAvailable" : true, 769 | "name" : "iPad Pro (10.5-inch)", 770 | "udid" : "5C2C1B7B-FF95-44E3-9D4D-0D70283040E6" 771 | } 772 | ] 773 | }, 774 | "pairs" : { 775 | "EC9A5719-3B9F-4460-949A-87E39E7D1E4B" : { 776 | "watch" : { 777 | "name" : "Apple Watch Series 4 - 40mm", 778 | "udid" : "43DC4548-62E8-4B67-8363-398985A0C330", 779 | "state" : "Shutdown" 780 | }, 781 | "phone" : { 782 | "name" : "iPhone Xs", 783 | "udid" : "2B7A5017-6784-42F7-9B5B-C2ADE7427A19", 784 | "state" : "Shutdown" 785 | }, 786 | "state" : "(active, disconnected)" 787 | }, 788 | "68BC0B43-5BBF-4C60-89AF-CD0029CF156C" : { 789 | "watch" : { 790 | "name" : "Apple Watch Series 4 - 44mm", 791 | "udid" : "6D13AA88-9E2E-4185-AE50-423A1EE1CA3E", 792 | "state" : "Shutdown" 793 | }, 794 | "phone" : { 795 | "name" : "iPhone Xs Max", 796 | "udid" : "115CDBCF-92D9-4B62-A694-E5D0D3B8BF8B", 797 | "state" : "Shutdown" 798 | }, 799 | "state" : "(active, disconnected)" 800 | } 801 | } 802 | } 803 | -------------------------------------------------------------------------------- /spec/fixtures_spec.rb: -------------------------------------------------------------------------------- 1 | require 'fourflusher' 2 | 3 | module Fourflusher 4 | describe SimControl do 5 | describe 'verify behaviour with fixtures' do 6 | def sim_control(path) 7 | ctrl = SimControl.new 8 | ctrl.stub(:list).and_return(File.new("spec/fixtures/#{path}").read) 9 | ctrl 10 | end 11 | 12 | it 'can find the 5 simulator' do 13 | ctrl = sim_control('simctl.json') 14 | destination = ctrl.destination('iPhone 5') 15 | destination.first.should == '-destination' 16 | end 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /spec/sort_spec.rb: -------------------------------------------------------------------------------- 1 | module Fourflusher 2 | describe SimControl do 3 | describe 'Simulator sorting' do 4 | before do 5 | @ctrl = SimControl.new 6 | @ctrl.stub(:list).and_return(File.new('spec/fixtures/simctl_small.json').read) 7 | end 8 | 9 | it 'properly sorts the simulator list' do 10 | sims = @ctrl.usable_simulators 11 | sims.map do |sim| 12 | "#{sim.os_name} #{sim.os_version} - #{sim.name}" 13 | end.should == [ 14 | 'ios 10.0 - iPhone 5', 15 | 'ios 10.0 - iPhone 5s', 16 | 'ios 10.0 - iPhone 6', 17 | 'ios 10.0 - iPhone 6 Plus', 18 | 'ios 10.0 - iPhone 6s', 19 | 'ios 10.0 - iPhone 6s Plus', 20 | 'ios 10.0 - iPhone 7', 21 | 'ios 10.0 - iPhone 7 Plus', 22 | 'ios 10.0 - iPhone SE', 23 | 'ios 10.0 - iPad', 24 | 'ios 10.0 - iPad Air', 25 | 'ios 10.0 - iPad Air 2', 26 | 'ios 10.0 - iPad Pro (12.9 inch)', 27 | 'ios 10.0 - iPad Pro (9.7 inch)', 28 | 'ios 10.0 - iPad Retina', 29 | 'ios 8.1 - iPhone 4s', 30 | 'ios 8.1 - iPhone 5', 31 | 'ios 8.1 - iPhone 5s', 32 | 'ios 8.1 - iPhone 6', 33 | 'ios 8.1 - iPhone 6 Plus', 34 | 'ios 8.1 - iPad 2', 35 | 'ios 8.1 - iPad Air', 36 | 'ios 8.1 - iPad Retina', 37 | 'tvos 9.2 - Apple TV 1080p', 38 | 'watchos 3.0 - Apple Watch - 38mm', 39 | 'watchos 3.0 - Apple Watch - 42mm', 40 | 'watchos 3.0 - Apple Watch Series 2 - 38mm', 41 | 'watchos 3.0 - Apple Watch Series 2 - 42mm', 42 | 'watchos 2.2 - Apple Watch - 38mm', 43 | 'watchos 2.2 - Apple Watch - 42mm' 44 | ] 45 | end 46 | end 47 | end 48 | describe 'device_and_model' do 49 | it 'parses iPhone models' do 50 | json = { 'name' => 'iPhone 5', 'udid' => '1' } 51 | Simulator.new(json, 'iOS', '10.0').device_and_model.should == %w(iPhone 5) 52 | end 53 | 54 | it 'parses iPhone Plus models' do 55 | json = { 'name' => 'iPhone 6s Plus', 'udid' => '1' } 56 | Simulator.new(json, 'iOS', '10.0').device_and_model.should == [ 57 | 'iPhone', 58 | '6s Plus' 59 | ] 60 | end 61 | 62 | it 'parses iPad models' do 63 | json = { 'name' => 'iPad 2', 'udid' => '1' } 64 | Simulator.new(json, 'iOS', '10.0').device_and_model.should == %w(iPad 2) 65 | end 66 | 67 | it 'parses iPad Air' do 68 | json = { 'name' => 'iPad Air', 'udid' => '1' } 69 | Simulator.new(json, 'iOS', '10.0').device_and_model.should == %w(iPad Air) 70 | end 71 | 72 | it 'parses iPad Air 2' do 73 | json = { 'name' => 'iPad Air 2', 'udid' => '1' } 74 | Simulator.new(json, 'iOS', '10.0').device_and_model.should == [ 75 | 'iPad', 76 | 'Air 2' 77 | ] 78 | end 79 | 80 | it 'parses Apple Watch models' do 81 | json = { 'name' => 'Apple Watch - 42mm', 'udid' => '1' } 82 | Simulator.new(json, 'watchOS', '10.0').device_and_model.should == [ 83 | 'Apple Watch', 84 | '42mm' 85 | ] 86 | end 87 | 88 | it 'parses Apple Series 2 models' do 89 | json = { 'name' => 'Apple Watch Series 2 - 42mm', 'udid' => '1' } 90 | Simulator.new(json, 'watchOS', '10.0').device_and_model.should == [ 91 | 'Apple Watch Series 2', 92 | '42mm' 93 | ] 94 | end 95 | end 96 | end 97 | -------------------------------------------------------------------------------- /spec/unit_spec.rb: -------------------------------------------------------------------------------- 1 | module Fourflusher 2 | describe SimControl do 3 | describe 'In general' do 4 | before do 5 | @ctrl = SimControl.new 6 | @ctrl.stub(:list).and_return(File.new('spec/fixtures/simctl.json').read) 7 | end 8 | 9 | it 'can find all usable simulators' do 10 | sims = @ctrl.usable_simulators 11 | sims.count.should == 108 12 | end 13 | 14 | it 'can find a specific simulator' do 15 | sim = @ctrl.simulator('iPhone 5') 16 | 17 | sim.id.should == '872DB32B-E22D-4F31-A6C1-606F2B5EE2A1' 18 | sim.name.should == 'iPhone 5' 19 | sim.os_name.should == :ios 20 | sim.os_version.should == Gem::Version.new('10.0') 21 | end 22 | 23 | it 'can construct the destination argument for a specific simulator' do 24 | destination = @ctrl.destination('iPhone 5') 25 | 26 | destination.should == ['-destination', 'id=872DB32B-E22D-4F31-A6C1-606F2B5EE2A1'] 27 | end 28 | 29 | it 'can optionally specify a constraint on destinations' do 30 | destination = @ctrl.destination('iPhone 4s', :ios, '9.3') 31 | 32 | destination.should == ['-destination', 'id=52DBE1DA-E90D-43E0-879D-B6D28B1682E8'] 33 | end 34 | 35 | it 'throws if a destination cannot satisfy the OS constraint' do 36 | expect { @ctrl.destination('iPhone 4', :ios, '10.0') }.to raise_error(RuntimeError) 37 | end 38 | 39 | it 'still throws a helpful error if `:oldest` is used' do 40 | expect { @ctrl.destination(:oldest, 'iOS', '20.0') }.to \ 41 | raise_error(RuntimeError, 'Simulator for iOS 20.0 is not available.') 42 | end 43 | 44 | it 'throws if Xcode is not installed' do 45 | ENV['DEVELOPER_DIR'] = '/yolo' 46 | expect { SimControl.new.destination('iPhone 5', '9.0') }.to \ 47 | raise_error(Fourflusher::Informative) 48 | end 49 | it 'throws if the device list is not Hash' do 50 | ctrl = SimControl.new 51 | ctrl.stub(:list).and_return(JSON.dump('devices' => [])) 52 | expect { ctrl.usable_simulators }.to \ 53 | raise_error(Fourflusher::Informative) 54 | end 55 | end 56 | 57 | describe 'Unavailable simulators' do 58 | before do 59 | @ctrl = SimControl.new 60 | @ctrl.stub(:list).and_return(File.new('spec/fixtures/simctl_with_unavailable.json').read) 61 | end 62 | 63 | it 'ignores unavailable simulators' do 64 | sims = @ctrl.usable_simulators 65 | sims.count.should == 15 66 | # This response only has iOS 10 sims available 67 | os_versions = sims.map(&:os_version).uniq 68 | os_versions.count.should == 1 69 | os_versions.first.should == Gem::Version.new('10.0') 70 | end 71 | end 72 | end 73 | 74 | describe Simulator do 75 | describe 'In general' do 76 | before do 77 | @ctrl = SimControl.new 78 | @ctrl.stub(:list).and_return(File.new('spec/fixtures/simctl.json').read) 79 | end 80 | 81 | it 'can parse simctl output' do 82 | sim = @ctrl.usable_simulators.first 83 | 84 | sim.id.should == '872DB32B-E22D-4F31-A6C1-606F2B5EE2A1' 85 | sim.name.should == 'iPhone 5' 86 | sim.os_name.should == :ios 87 | sim.os_version.should == Gem::Version.new('10.0') 88 | end 89 | 90 | it 'has a meaningful string conversion' do 91 | device_json = { 'state' => 'Shutdown', 92 | 'availability' => '(available)', 93 | 'name' => 'iPhone 5', 94 | 'udid' => 'B7D21008-CC16-47D6-A9A9-885FE1FC47A8' } 95 | sim = Simulator.new(device_json, 'iOS', '10.0') 96 | 97 | sim.to_s.should == 'iPhone 5 (B7D21008-CC16-47D6-A9A9-885FE1FC47A8) - iOS 10.0' 98 | end 99 | end 100 | end 101 | end 102 | --------------------------------------------------------------------------------