run_loop 2.6.6 → 2.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 859e2ab5bd1352f4d5b41267c7fb1d28c49c9607
4
- data.tar.gz: 857468c645b8619b998bbf9c2f2e15f85eb4a81c
2
+ SHA256:
3
+ metadata.gz: efa428373fed36e57c707789351dddb5c6019d52985b0f4503b32f857a3fb9a0
4
+ data.tar.gz: d20c552c8130a4921c0505f9f50a88079e9acd401680495c9d51fd6134ce819d
5
5
  SHA512:
6
- metadata.gz: ad9097c29c97dddd9e3100a7c3e685820d6e3499a84cee13dac1c191ce255458157d5a372806b6803e77b04b4402beda1fb8bf895398db2fa7989a1be196dbf2
7
- data.tar.gz: 47e7304ea46a8465781a8869f58d3ded32e606be6c691216d7d2368991863898b81198ade718216ee988a79fcf2a477ebc24473f27c89797d9847832025895e1
6
+ metadata.gz: 8b750e02559f0b0656c435c7a11e16b13ef5ef58f2dd54127a5a6ebabeb6318de80b130e6cb04b3166d24b6d7c9e284334a7dcfa4597019bde83ee120188fdd2
7
+ data.tar.gz: d441a636cb58d67099a59ad32fae2410b2aec38a8e41256d56821c4b9c6b2105ba4857601b546fcededf6420ba297f38cc2238a87472b13d72285f97d9400390
@@ -0,0 +1,119 @@
1
+ run-loop incorporates third party material from the projects listed
2
+ below. The original copyright notice and the license under which Microsoft
3
+ received such third party material are set forth below. Microsoft reserves all
4
+ other rights not expressly granted, whether by implication, estoppel or
5
+ otherwise.
6
+
7
+ ===
8
+
9
+ The MIT License (MIT)
10
+
11
+ For iOSDeviceManager software
12
+
13
+ Copyright (c) 2016 Microsoft Corporation
14
+
15
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
16
+ this software and associated documentation files (the "Software"), to deal in
17
+ the Software without restriction, including without limitation the rights to
18
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
19
+ of the Software, and to permit persons to whom the Software is furnished to do
20
+ so, subject to the following conditions:
21
+
22
+ The above copyright notice and this permission notice shall be included in all
23
+ copies or substantial portions of the Software.
24
+
25
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31
+ SOFTWARE.
32
+
33
+ ===
34
+
35
+ The MIT License (MIT)
36
+
37
+ For DeviceAgent.iOS software
38
+
39
+ Copyright (c) Microsoft Corporation
40
+
41
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
42
+ this software and associated documentation files (the "Software"), to deal in
43
+ the Software without restriction, including without limitation the rights to
44
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
45
+ of the Software, and to permit persons to whom the Software is furnished to do
46
+ so, subject to the following conditions:
47
+
48
+ The above copyright notice and this permission notice shall be included in all
49
+ copies or substantial portions of the Software.
50
+
51
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
52
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
53
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
54
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
55
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
56
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
57
+ SOFTWARE.
58
+
59
+ ===
60
+
61
+ BSD License
62
+
63
+ For FBSimulatorControl software
64
+
65
+ Copyright (c) 2015-present, Facebook, Inc. All rights reserved.
66
+
67
+ Redistribution and use in source and binary forms, with or without modification,
68
+ are permitted provided that the following conditions are met:
69
+
70
+ * Redistributions of source code must retain the above copyright notice, this
71
+ list of conditions and the following disclaimer.
72
+
73
+ * Redistributions in binary form must reproduce the above copyright notice,
74
+ this list of conditions and the following disclaimer in the documentation
75
+ and/or other materials provided with the distribution.
76
+
77
+ * Neither the name Facebook nor the names of its contributors may be used to
78
+ endorse or promote products derived from this software without specific prior
79
+ written permission.
80
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
81
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
82
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
83
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
84
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
85
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
86
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
87
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
88
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
89
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
90
+
91
+ ===
92
+
93
+ BSD License
94
+
95
+ For CocoaLumberjack software
96
+
97
+ Copyright (c) 2010-present, Deusty, LLC. All rights reserved.
98
+
99
+ Redistribution and use of this software in source and binary forms, with or
100
+ without modification, are permitted provided that the following conditions are
101
+ met:
102
+
103
+ * Redistributions of source code must retain the above copyright notice, this
104
+ list of conditions and the following disclaimer.
105
+
106
+ * Neither the name of Deusty nor the names of its contributors may be used to
107
+ endorse or promote products derived from this software without specific prior
108
+ written permission of Deusty, LLC.
109
+
110
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
111
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
112
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
113
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
114
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
115
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
116
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
117
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
118
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
119
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/lib/run_loop/core.rb CHANGED
@@ -320,7 +320,9 @@ Logfile: #{log_file}
320
320
  # version.
321
321
  def self.default_simulator(xcode=RunLoop::Xcode.new)
322
322
 
323
- if xcode.version_gte_93?
323
+ if xcode.version_gte_94?
324
+ "iPhone 8 (11.4)"
325
+ elsif xcode.version_gte_93?
324
326
  "iPhone 8 (11.3)"
325
327
  elsif xcode.version_gte_92?
326
328
  "iPhone 8 (11.2)"
@@ -228,6 +228,32 @@ version: #{version}
228
228
  !physical_device?
229
229
  end
230
230
 
231
+ # Is the iOS version installed on this device compatible with an Xcode
232
+ # version?
233
+ def compatible_with_xcode_version?(xcode_version)
234
+ ios_version = version
235
+
236
+ if ios_version.major < (xcode_version.major + 2)
237
+ if physical_device?
238
+ return true
239
+ else
240
+ # iOS 8 simulators are available in Xcode 9
241
+ # iOS 7 simulators are not available in Xcode 9
242
+ if ios_version.major <= (xcode_version.major - 2)
243
+ return false
244
+ else
245
+ return true
246
+ end
247
+ end
248
+ end
249
+
250
+ if ios_version.major == (xcode_version.major + 2)
251
+ return ios_version.minor <= xcode_version.minor
252
+ end
253
+
254
+ false
255
+ end
256
+
231
257
  # Return the instruction set for this device.
232
258
  #
233
259
  # **Simulator**
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Microsoft Corporation
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9
+ of the Software, and to permit persons to whom the Software is furnished to do
10
+ so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ 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 THE
21
+ SOFTWARE.
@@ -125,6 +125,15 @@ module RunLoop
125
125
  core_sim.install
126
126
  end
127
127
 
128
+ if !RunLoop::Environment.xtc?
129
+ if device.physical_device? && app
130
+ if reset_options
131
+ idm = RunLoop::PhysicalDevice::IOSDeviceManager.new(device)
132
+ idm.reset_app_sandbox(app)
133
+ end
134
+ end
135
+ end
136
+
128
137
  cbx_launcher = Client.detect_cbx_launcher(merged_options, device)
129
138
 
130
139
  code_sign_identity = options[:code_sign_identity]
@@ -52,7 +52,7 @@ found '#{handle_errors_by}'
52
52
  raise ArgumentError, "Expected '#{path}' to be a directory"
53
53
  end
54
54
 
55
- entries = self.recursive_glob_for_entries(path)
55
+ entries = self.recursive_glob_for_entries(path).sort
56
56
 
57
57
  if entries.empty?
58
58
  raise ArgumentError, "Expected a non-empty dir at '#{path}' found '#{entries}'"
@@ -60,11 +60,16 @@ found '#{handle_errors_by}'
60
60
 
61
61
  debug = RunLoop::Environment.debug?
62
62
 
63
- sha = OpenSSL::Digest::SHA256.new
64
- entries.each do |file|
65
- unless self.skip_file?(file, 'SHA1', debug)
63
+ file_shas = []
64
+ cumulative = OpenSSL::Digest::SHA256.new
65
+ entries.each do |path|
66
+ if !self.skip_file?(path, "SHA256", debug)
66
67
  begin
67
- sha << File.read(file)
68
+ file_sha = OpenSSL::Digest::SHA256.new
69
+ contents = File.read(path, {mode: "rb"})
70
+ file_sha << contents
71
+ cumulative << contents
72
+ file_shas << [file_sha.hexdigest]
68
73
  rescue => e
69
74
  case handle_errors_by
70
75
  when :logging
@@ -75,7 +80,7 @@ found '#{handle_errors_by}'
75
80
 
76
81
  while trying to find the SHA of this file:
77
82
 
78
- #{file}
83
+ #{path}
79
84
 
80
85
  This is not a fatal error; it can be ignored.
81
86
  }
@@ -90,7 +95,13 @@ This is not a fatal error; it can be ignored.
90
95
  end
91
96
  end
92
97
  end
93
- sha.hexdigest
98
+ digest_of_digests = OpenSSL::Digest::SHA256.new
99
+ digest_of_digests << file_shas.join("\n")
100
+ # We have at least one example where the cumulative digest has an
101
+ # unexpected value when computing the digest of an installed .app on an
102
+ # iOS Simulator. I want return the cumulative.hexdigest in case there is
103
+ # a client (end user) who is using this method.
104
+ return digest_of_digests.hexdigest, cumulative.hexdigest
94
105
  end
95
106
 
96
107
  def self.size(path, format)
@@ -218,8 +218,12 @@ module RunLoop
218
218
  udid = line[DEVICE_UDID_REGEX, 0]
219
219
  if udid
220
220
  version = line[VERSION_REGEX, 0]
221
- name = line.split('(').first.strip
222
- RunLoop::Device.new(name, version, udid)
221
+ if version
222
+ name = line.split('(').first.strip
223
+ if name
224
+ RunLoop::Device.new(name, version, udid)
225
+ end
226
+ end
223
227
  else
224
228
  nil
225
229
  end
data/lib/run_loop/ipa.rb CHANGED
@@ -2,6 +2,20 @@ module RunLoop
2
2
  # A model of the an .ipa - a application binary for iOS devices.
3
3
  class Ipa
4
4
 
5
+ require "run_loop/shell"
6
+
7
+ # Return true if the path_to_ipa to a zip archive
8
+ def self.is_zip_archive?(path_to_ipa)
9
+ hash = RunLoop::Shell.run_shell_command(["file", path_to_ipa],
10
+ {log_cmd: true})
11
+ hash[:out][/Zip archive data/]
12
+ end
13
+
14
+ # Return true if the path_to_ipa is probably an .ipa
15
+ def self.is_ipa?(path_to_ipa)
16
+ path_to_ipa.end_with?('.ipa') || RunLoop::Ipa.is_zip_archive?(path_to_ipa)
17
+ end
18
+
5
19
  # The path to this .ipa.
6
20
  # @!attribute [r] path
7
21
  # @return [String] A path to this .ipa.
@@ -13,12 +27,12 @@ module RunLoop
13
27
  # @raise [RuntimeError] If the file does not exist.
14
28
  # @raise [RuntimeError] If the file does not end in .ipa.
15
29
  def initialize(path_to_ipa)
16
- unless File.exist? path_to_ipa
30
+ if !File.exist? path_to_ipa
17
31
  raise "Expected an ipa at '#{path_to_ipa}'"
18
32
  end
19
33
 
20
- unless path_to_ipa.end_with?('.ipa')
21
- raise "Expected '#{path_to_ipa}' to be an .ipa"
34
+ if !RunLoop::Ipa.is_ipa?(path_to_ipa)
35
+ raise "Expected '#{path_to_ipa}' have extension .ipa or be a zip archive"
22
36
  end
23
37
  @path = path_to_ipa
24
38
  end
@@ -5,6 +5,17 @@ module RunLoop
5
5
  require "run_loop/physical_device/life_cycle"
6
6
  class IOSDeviceManager < RunLoop::PhysicalDevice::LifeCycle
7
7
 
8
+ require "fileutils"
9
+ require "run_loop/dot_dir"
10
+ require "run_loop/device_agent/frameworks"
11
+ require "run_loop/device_agent/ios_device_manager"
12
+
13
+ NOT_INSTALLED_EXIT_CODE = 2
14
+
15
+ DEFAULTS = {
16
+ install_timeout: RunLoop::Environment.ci? ? 240 : 120
17
+ }
18
+
8
19
  # Is the tool installed?
9
20
  def self.tool_is_installed?
10
21
  File.exist?(IOSDeviceManager.executable_path)
@@ -22,67 +33,148 @@ module RunLoop
22
33
  RunLoop::DeviceAgent::Frameworks.instance.install
23
34
  end
24
35
 
25
- def app_installed?(bundle_id)
36
+ def raise_error_on_failure(error_klass, message, app, device, hash)
37
+ if hash[:exit_status] == 0
38
+ true
39
+ else
40
+ raise error_klass, %Q[
41
+ #{message}
42
+
43
+ app: #{app}
44
+ device: #{device}
45
+ exit status: #{hash[:exit_status]}
46
+
47
+ #{hash[:out]}
48
+
49
+ ]
50
+ end
51
+ end
52
+
53
+ def app_installed?(app)
54
+ bundle_id = app
55
+ if is_ipa?(app) || is_app?(app)
56
+ bundle_id = app.bundle_identifier
57
+ end
58
+
26
59
  args = [
27
60
  IOSDeviceManager.executable_path,
28
- "is_installed",
29
- "-d", device.udid,
30
- "-b", bundle_id
61
+ "is-installed",
62
+ bundle_id,
63
+ "-d", device.udid
31
64
  ]
32
65
 
33
66
  options = { :log_cmd => true }
34
67
  hash = run_shell_command(args, options)
35
68
 
36
- # TODO: error reporting
37
- hash[:exit_status] == 0
69
+ exit_status = hash[:exit_status]
70
+
71
+ if exit_status != 0 && exit_status != NOT_INSTALLED_EXIT_CODE
72
+ raise_error_on_failure(
73
+ RuntimeError,
74
+ "Encountered an error checking if app is installed on device",
75
+ app, device, hash
76
+ )
77
+ else
78
+ RunLoop::log_debug("Took #{hash[:seconds_elapsed]} seconds to check " +
79
+ "app was installed")
80
+ hash[:exit_status] == 0
81
+ end
38
82
  end
39
83
 
40
84
  def install_app(app_or_ipa)
41
- app = app_or_ipa
42
- if is_ipa?(app)
43
- app = app_or_ipa.app
44
- end
85
+ install_app_internal(app_or_ipa, ["--force"])
86
+ end
45
87
 
46
- code_sign_identity = RunLoop::Environment.code_sign_identity
47
- if !code_sign_identity
48
- code_sign_identity = "iPhone Developer"
88
+ def ensure_newest_installed(app_or_ipa)
89
+ install_app_internal(app_or_ipa)
90
+ end
91
+
92
+ def uninstall_app(app_or_ipa)
93
+ bundle_identifier = app_or_ipa.bundle_identifier
94
+ if !app_installed?(bundle_identifier)
95
+ return :was_not_installed
49
96
  end
50
97
 
51
98
  args = [
52
99
  IOSDeviceManager.executable_path,
53
- "install",
54
- "-d", device.udid,
55
- "-a", app.path,
56
- "-c", code_sign_identity
100
+ "uninstall",
101
+ bundle_identifier,
102
+ "-d", device.udid
57
103
  ]
58
104
 
59
105
  options = { :log_cmd => true }
60
106
  hash = run_shell_command(args, options)
61
107
 
62
- # TODO: error reporting
63
- if hash[:exit_status] == 0
64
- true
65
- else
66
- puts hash[:out]
67
- false
68
- end
108
+ raise_error_on_failure(
109
+ UninstallError,
110
+ "Could not remove app from device",
111
+ app_or_ipa, device, hash
112
+ )
113
+ hash[:out]
114
+ end
115
+
116
+ def can_reset_app_sandbox?
117
+ true
118
+ end
119
+
120
+ def reset_app_sandbox(app_or_ipa)
121
+ args = [IOSDeviceManager.executable_path,
122
+ "clear-app-data",
123
+ app_or_ipa.path,
124
+ device.udid]
125
+
126
+ options = { :log_cmd => true }
127
+ hash = run_shell_command(args, options)
128
+
129
+ raise_error_on_failure(
130
+ ResetAppSandboxError,
131
+ "Could not clear app data",
132
+ app_or_ipa, device, hash
133
+ )
134
+
135
+ hash[:out]
69
136
  end
70
137
 
71
- def uninstall_app(bundle_id)
72
- return true if !app_installed?(bundle_id)
138
+ =begin
139
+ Private Methods
140
+ =end
141
+
142
+ private
73
143
 
144
+ def install_app_internal(app_or_ipa, additional_args=[])
74
145
  args = [
75
146
  IOSDeviceManager.executable_path,
76
- "uninstall",
77
- "-d", device.udid,
78
- "-b", bundle_id
147
+ "install",
148
+ app_or_ipa.path,
149
+ "-d", device.udid
79
150
  ]
80
151
 
81
- options = { :log_cmd => true }
152
+ args = args + additional_args
153
+
154
+ code_sign_identity = RunLoop::Environment.code_sign_identity
155
+ if code_sign_identity
156
+ args = args + ["-c", code_sign_identity]
157
+ end
158
+
159
+ provisioning_profile = RunLoop::Environment.provisioning_profile
160
+ if provisioning_profile
161
+ args = args + ["-p", provisioning_profile]
162
+ end
163
+
164
+ options = {
165
+ :log_cmd => true,
166
+ timeout: DEFAULTS[:install_timeout]
167
+ }
82
168
  hash = run_shell_command(args, options)
83
169
 
84
- # TODO: error reporting
85
- hash[:exit_status] == 0
170
+ raise_error_on_failure(
171
+ InstallError,
172
+ "Could not install app on device",
173
+ app_or_ipa, device, hash
174
+ )
175
+
176
+ RunLoop::log_debug("Took #{hash[:seconds_elapsed]} seconds to install app")
177
+ hash[:out]
86
178
  end
87
179
  end
88
180
  end
@@ -8,6 +8,9 @@ module RunLoop
8
8
  # Raised when uninstall fails.
9
9
  class UninstallError < RuntimeError; end
10
10
 
11
+ # Raised when clear app data fails
12
+ class ResetAppSandboxError < RuntimeError; end
13
+
11
14
  # Raised when tool cannot perform task.
12
15
  class NotImplementedError < StandardError; end
13
16
 
@@ -65,37 +68,31 @@ must be a physical device.]
65
68
 
66
69
  # Is the app installed?
67
70
  #
68
- # @param [String] bundle_id The CFBundleIdentifier of an app.
71
+ # @param [RunLoop::Ipa, RunLoop::App, String] app an App, Ipa, or a bundle
72
+ # identifier.
69
73
  # @return [Boolean] true or false
70
- def app_installed?(bundle_id)
74
+ def app_installed?(app)
71
75
  abstract_method!
72
76
  end
73
77
 
74
78
  # Install the app or ipa.
75
79
  #
76
80
  # If the app is already installed, it will be reinstalled from disk;
77
- # no version check is performed.
81
+ # no version check is performed. This is a force reinstall.
78
82
  #
79
83
  # App data is never preserved. If you want to preserve the app data,
80
84
  # call `ensure_newest_installed`.
81
85
  #
82
- # Possible return values:
83
- #
84
- # * :reinstalled => app was installed, but app data was not preserved.
85
- # * :installed => app was not installed.
86
- #
87
- # @param [RunLoop::Ipa, RunLoop::App] app_or_ipa The ipa to install.
88
- # The caller is responsible for validating the ipa for the device by
89
- # checking that the codesign and instruction set is correct.
86
+ # @param [RunLoop::Ipa, RunLoop::App] app The ipa to install.
90
87
  #
91
88
  # @raise [InstallError] If app was not installed.
92
89
  #
93
- # @return [Symbol] A keyword describing the action that was performed.
94
- def install_app(app_or_ipa)
90
+ # @return [Boolean] true or false
91
+ def install_app(app)
95
92
  abstract_method!
96
93
  end
97
94
 
98
- # Uninstall the app with bundle_id.
95
+ # Uninstall the app.
99
96
  #
100
97
  # App data is never preserved. If you want to install a new version of
101
98
  # an app and preserve app data (upgrade testing), call
@@ -103,16 +100,12 @@ must be a physical device.]
103
100
  #
104
101
  # Possible return values:
105
102
  #
106
- # * :nothing => app was not installed
107
- # * :uninstall => app was uninstalled
108
- #
109
- # @param [String] bundle_id The CFBundleIdentifier of an app.
103
+ # @param [RunLoop::Ipa, RunLoop::App] app the App or Ipa
110
104
  #
111
105
  # @raise [UninstallError] If the app cannot be uninstalled, usually
112
106
  # because it is a system app.
113
- #
114
- # @return [Symbol] A keyword that describes what action was performed.
115
- def uninstall_app(bundle_id)
107
+ # @return [String] Output from the shell command
108
+ def uninstall_app(app)
116
109
  abstract_method!
117
110
  end
118
111
 
@@ -124,26 +117,15 @@ must be a physical device.]
124
117
  # the CFBundleShortVersionString. If either are different, then the
125
118
  # app should be reinstalled.
126
119
  #
127
- # If possible, the app data should be preserved across reinstallation.
128
- #
129
- # Possible return values:
120
+ # If possible, the app data should be preserved across re-installation.
130
121
  #
131
- # * :nothing => app was already installed and versions matched.
132
- # * :upgraded => app was stale; newer version from disk was installed and
133
- # app data was preserved.
134
- # * :reinstalled => app was stale; newer version from disk was installed,
135
- # but app data was not preserved.
136
- # * :installed => app was not installed.
137
- #
138
- # @param [RunLoop::Ipa, RunLoop::App] app_or_ipa The ipa to install.
139
- # The caller is responsible for validating the ipa for the device by
140
- # checking that the codesign and instruction set is correct.
122
+ # @param [RunLoop::Ipa, RunLoop::App] app The App or Ipa to install.
141
123
  #
142
124
  # @raise [InstallError] If the app could not be installed.
143
125
  # @raise [UninstallError] If the app could not be uninstalled.
144
126
  #
145
- # @return [Symbol] A keyword that describes the action that was taken.
146
- def ensure_newest_installed(app_or_ipa)
127
+ # @return [String] Output from the shell command
128
+ def ensure_newest_installed(app)
147
129
  abstract_method!
148
130
  end
149
131
 
@@ -153,12 +135,10 @@ must be a physical device.]
153
135
  # the CFBundleShortVersionString. If either are different, then this
154
136
  # method returns false.
155
137
  #
156
- # @param [RunLoop::Ipa, RunLoop::App] app_or_ipa The ipa to install.
157
- # The caller is responsible for validating the ipa for the device by
158
- # checking that the codesign and instruction set is correct.
138
+ # @param [RunLoop::Ipa, RunLoop::App] app The Ipa or App to install.
159
139
  #
160
140
  # @raise [RuntimeError] If app is not already installed.
161
- def installed_app_same_as?(app_or_ipa)
141
+ def installed_app_same_as?(app)
162
142
  abstract_method!
163
143
  end
164
144
 
@@ -176,11 +156,11 @@ must be a physical device.]
176
156
  #
177
157
  # Does not clear Keychain. Use the Calabash iOS Keychain API.
178
158
  #
179
- # @param [String] bundle_id The CFBundleIdentifier of an app.
159
+ # @param [RunLoop::Ipa, RunLoop::App] app The App or Ipa
180
160
  #
181
161
  # @raise [RunLoop::PhysicalDevice::NotImplementedError] If this tool
182
- # cannot reset the app sandbox without unintalling the app.
183
- def reset_app_sandbox(bundle_id)
162
+ # cannot reset the app sandbox without uninstalling the app.
163
+ def reset_app_sandbox(app)
184
164
  abstract_method!
185
165
  end
186
166
 
@@ -190,7 +170,9 @@ must be a physical device.]
190
170
  end
191
171
 
192
172
  # Is the app or ipa compatible with the architecture of the device?
193
- def app_has_compatible_architecture?(app_or_ipa)
173
+ #
174
+ # @param [RunLoop::Ipa, RunLoop::App] app The App or Ipa
175
+ def app_has_compatible_architecture?(app)
194
176
  abstract_method!
195
177
  end
196
178
 
@@ -199,7 +181,7 @@ must be a physical device.]
199
181
  abstract_method!
200
182
  end
201
183
 
202
- # Return false if the device is an iPad.
184
+ # Return true if the device is an iPad.
203
185
  def ipad?
204
186
  abstract_method!
205
187
  end
@@ -209,7 +191,7 @@ must be a physical device.]
209
191
  abstract_method!
210
192
  end
211
193
 
212
- # Sideload data into the app's sandbox.
194
+ # Side-load data into the app's sandbox.
213
195
  #
214
196
  # These directories exist in the application sandbox.
215
197
  #
@@ -63,11 +63,14 @@ IO.popen requires all arguments to be Strings.
63
63
  RunLoop.log_unix_cmd(cmd) if merged_options[:log_cmd]
64
64
 
65
65
  hash = {}
66
+ shell_start_time = Time.now
66
67
 
67
- begin
68
+ environment = options.fetch(:environment, {})
68
69
 
69
- start_time = Time.now
70
- command_output = CommandRunner.run(args, timeout: timeout)
70
+ begin
71
+ command_output = CommandRunner.run(args,
72
+ timeout: timeout,
73
+ environment: environment)
71
74
 
72
75
  out = ensure_command_output_utf8(command_output[:out], cmd)
73
76
  process_status = command_output[:status]
@@ -83,7 +86,7 @@ IO.popen requires all arguments to be Strings.
83
86
  rescue RunLoop::Encoding::UTF8Error => e
84
87
  raise e
85
88
  rescue => e
86
- elapsed = "%0.2f" % (Time.now - start_time)
89
+ elapsed = "%0.2f" % (Time.now - shell_start_time)
87
90
  raise Error,
88
91
  %Q{Encountered an error after #{elapsed} seconds:
89
92
 
@@ -93,14 +96,14 @@ executing this command:
93
96
 
94
97
  #{cmd}
95
98
  }
99
+ ensure
100
+ hash[:seconds_elapsed] = Time.now - shell_start_time
96
101
  end
97
102
 
98
- now = Time.now
99
-
100
103
  if hash[:exit_status].nil?
101
- elapsed = "%0.2f" % (now - start_time)
104
+ elapsed = "%0.2f" % (hash[:seconds_elapsed])
102
105
 
103
- if timeout_exceeded?(start_time, timeout)
106
+ if timeout_exceeded?(shell_start_time, timeout)
104
107
  raise TimeoutError,
105
108
  %Q[
106
109
  Timed out after #{elapsed} seconds executing
@@ -123,7 +126,6 @@ The command generated this output:
123
126
 
124
127
  end
125
128
  end
126
-
127
129
  hash
128
130
  end
129
131
 
@@ -134,4 +136,3 @@ The command generated this output:
134
136
  end
135
137
  end
136
138
  end
137
-
@@ -1,5 +1,5 @@
1
1
  module RunLoop
2
- VERSION = "2.6.6"
2
+ VERSION = "2.7.0"
3
3
 
4
4
  # A model of a software release version that can be used to compare two versions.
5
5
  #
@@ -26,6 +26,14 @@ module RunLoop
26
26
  to_s
27
27
  end
28
28
 
29
+ # Returns a version instance for Xcode 9.4; used to check for the
30
+ # availability of features and paths to various items on the filesystem
31
+ #
32
+ # @return [RunLoop::Version] 9.4
33
+ def v94
34
+ fetch_version(:v94)
35
+ end
36
+
29
37
  # Returns a version instance for Xcode 9.3; used to check for the
30
38
  # availability of features and paths to various items on the filesystem
31
39
  #
@@ -177,6 +185,14 @@ module RunLoop
177
185
  def v50
178
186
  fetch_version(:v50)
179
187
  end
188
+
189
+ # Is the active Xcode version 9.3 or above?
190
+ #
191
+ # @return [Boolean] `true` if the current Xcode version is >= 9.3
192
+ def version_gte_94?
193
+ version >= v94
194
+ end
195
+
180
196
  # Is the active Xcode version 9.3 or above?
181
197
  #
182
198
  # @return [Boolean] `true` if the current Xcode version is >= 9.3
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: run_loop
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.6.6
4
+ version: 2.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Karl Krukow
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-04-02 00:00:00.000000000 Z
12
+ date: 2018-04-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json
@@ -133,14 +133,14 @@ dependencies:
133
133
  requirements:
134
134
  - - "~>"
135
135
  - !ruby/object:Gem::Version
136
- version: '0.2'
136
+ version: '0.3'
137
137
  type: :development
138
138
  prerelease: false
139
139
  version_requirements: !ruby/object:Gem::Requirement
140
140
  requirements:
141
141
  - - "~>"
142
142
  - !ruby/object:Gem::Version
143
- version: '0.2'
143
+ version: '0.3'
144
144
  - !ruby/object:Gem::Dependency
145
145
  name: luffa
146
146
  requirement: !ruby/object:Gem::Requirement
@@ -203,28 +203,42 @@ dependencies:
203
203
  requirements:
204
204
  - - "~>"
205
205
  - !ruby/object:Gem::Version
206
- version: '4.3'
206
+ version: '4.0'
207
207
  type: :development
208
208
  prerelease: false
209
209
  version_requirements: !ruby/object:Gem::Requirement
210
210
  requirements:
211
211
  - - "~>"
212
212
  - !ruby/object:Gem::Version
213
- version: '4.3'
213
+ version: '4.0'
214
+ - !ruby/object:Gem::Dependency
215
+ name: terminal-notifier
216
+ requirement: !ruby/object:Gem::Requirement
217
+ requirements:
218
+ - - "~>"
219
+ - !ruby/object:Gem::Version
220
+ version: '2.0'
221
+ type: :development
222
+ prerelease: false
223
+ version_requirements: !ruby/object:Gem::Requirement
224
+ requirements:
225
+ - - "~>"
226
+ - !ruby/object:Gem::Version
227
+ version: '2.0'
214
228
  - !ruby/object:Gem::Dependency
215
229
  name: terminal-notifier-guard
216
230
  requirement: !ruby/object:Gem::Requirement
217
231
  requirements:
218
232
  - - "~>"
219
233
  - !ruby/object:Gem::Version
220
- version: '1.7'
234
+ version: '1.0'
221
235
  type: :development
222
236
  prerelease: false
223
237
  version_requirements: !ruby/object:Gem::Requirement
224
238
  requirements:
225
239
  - - "~>"
226
240
  - !ruby/object:Gem::Version
227
- version: '1.7'
241
+ version: '1.0'
228
242
  - !ruby/object:Gem::Dependency
229
243
  name: guard-bundler
230
244
  requirement: !ruby/object:Gem::Requirement
@@ -317,6 +331,7 @@ files:
317
331
  - "./vendor-licenses/Facebook-WebDriverAgent.LICENSE"
318
332
  - "./vendor-licenses/RoutingHTTPServer.LICENSE"
319
333
  - LICENSE
334
+ - ThirdPartyNotices.txt
320
335
  - bin/run-loop
321
336
  - lib/run_loop.rb
322
337
  - lib/run_loop/abstract.rb
@@ -339,6 +354,7 @@ files:
339
354
  - lib/run_loop/device_agent/Frameworks.zip
340
355
  - lib/run_loop/device_agent/app/DeviceAgent-Runner.app.zip
341
356
  - lib/run_loop/device_agent/bin/iOSDeviceManager
357
+ - lib/run_loop/device_agent/bin/iOSDeviceManager.LICENSE
342
358
  - lib/run_loop/device_agent/client.rb
343
359
  - lib/run_loop/device_agent/frameworks.rb
344
360
  - lib/run_loop/device_agent/ios_device_manager.rb
@@ -415,7 +431,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
415
431
  version: '0'
416
432
  requirements: []
417
433
  rubyforge_project:
418
- rubygems_version: 2.6.14
434
+ rubygems_version: 2.7.6
419
435
  signing_key:
420
436
  specification_version: 4
421
437
  summary: The bridge between Calabash iOS and Xcode command-line tools like instruments