run_loop 2.6.6 → 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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