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 +5 -5
- data/ThirdPartyNotices.txt +119 -0
- data/lib/run_loop/core.rb +3 -1
- data/lib/run_loop/device.rb +26 -0
- data/lib/run_loop/device_agent/Frameworks.zip +0 -0
- data/lib/run_loop/device_agent/bin/iOSDeviceManager +0 -0
- data/lib/run_loop/device_agent/bin/iOSDeviceManager.LICENSE +21 -0
- data/lib/run_loop/device_agent/client.rb +9 -0
- data/lib/run_loop/directory.rb +18 -7
- data/lib/run_loop/instruments.rb +6 -2
- data/lib/run_loop/ipa.rb +17 -3
- data/lib/run_loop/physical_device/ios_device_manager.rb +124 -32
- data/lib/run_loop/physical_device/life_cycle.rb +28 -46
- data/lib/run_loop/shell.rb +11 -10
- data/lib/run_loop/version.rb +1 -1
- data/lib/run_loop/xcode.rb +16 -0
- metadata +25 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: efa428373fed36e57c707789351dddb5c6019d52985b0f4503b32f857a3fb9a0
|
4
|
+
data.tar.gz: d20c552c8130a4921c0505f9f50a88079e9acd401680495c9d51fd6134ce819d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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)"
|
data/lib/run_loop/device.rb
CHANGED
@@ -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**
|
Binary file
|
Binary file
|
@@ -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]
|
data/lib/run_loop/directory.rb
CHANGED
@@ -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
|
-
|
64
|
-
|
65
|
-
|
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
|
-
|
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
|
-
#{
|
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
|
-
|
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)
|
data/lib/run_loop/instruments.rb
CHANGED
@@ -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
|
-
|
222
|
-
|
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
|
-
|
30
|
+
if !File.exist? path_to_ipa
|
17
31
|
raise "Expected an ipa at '#{path_to_ipa}'"
|
18
32
|
end
|
19
33
|
|
20
|
-
|
21
|
-
raise "Expected '#{path_to_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
|
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
|
-
"
|
29
|
-
|
30
|
-
"-
|
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
|
-
|
37
|
-
|
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
|
-
|
42
|
-
|
43
|
-
app = app_or_ipa.app
|
44
|
-
end
|
85
|
+
install_app_internal(app_or_ipa, ["--force"])
|
86
|
+
end
|
45
87
|
|
46
|
-
|
47
|
-
|
48
|
-
|
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
|
-
"
|
54
|
-
|
55
|
-
"-
|
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
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
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
|
-
|
72
|
-
|
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
|
-
"
|
77
|
-
|
78
|
-
"-
|
147
|
+
"install",
|
148
|
+
app_or_ipa.path,
|
149
|
+
"-d", device.udid
|
79
150
|
]
|
80
151
|
|
81
|
-
|
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
|
-
|
85
|
-
|
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]
|
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?(
|
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
|
-
#
|
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 [
|
94
|
-
def install_app(
|
90
|
+
# @return [Boolean] true or false
|
91
|
+
def install_app(app)
|
95
92
|
abstract_method!
|
96
93
|
end
|
97
94
|
|
98
|
-
# Uninstall the app
|
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
|
-
#
|
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
|
-
|
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
|
128
|
-
#
|
129
|
-
# Possible return values:
|
120
|
+
# If possible, the app data should be preserved across re-installation.
|
130
121
|
#
|
131
|
-
#
|
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 [
|
146
|
-
def ensure_newest_installed(
|
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]
|
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?(
|
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 [
|
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
|
183
|
-
def reset_app_sandbox(
|
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
|
-
|
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
|
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
|
-
#
|
194
|
+
# Side-load data into the app's sandbox.
|
213
195
|
#
|
214
196
|
# These directories exist in the application sandbox.
|
215
197
|
#
|
data/lib/run_loop/shell.rb
CHANGED
@@ -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
|
-
|
68
|
+
environment = options.fetch(:environment, {})
|
68
69
|
|
69
|
-
|
70
|
-
command_output = CommandRunner.run(args,
|
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 -
|
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" % (
|
104
|
+
elapsed = "%0.2f" % (hash[:seconds_elapsed])
|
102
105
|
|
103
|
-
if timeout_exceeded?(
|
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
|
-
|
data/lib/run_loop/version.rb
CHANGED
data/lib/run_loop/xcode.rb
CHANGED
@@ -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.
|
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-
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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
|
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
|