run_loop 1.5.4 → 1.5.5

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
2
  SHA1:
3
- metadata.gz: 2912f8769ebd18c671989ea3db4dcf73e22522d0
4
- data.tar.gz: f1463e434006a9cab612ff2a574169806c992842
3
+ metadata.gz: 2423db81abf3240a09a78b36e626e7fe9805e1b5
4
+ data.tar.gz: 2c121c18d79c9faaab075f94dea364042aed23d0
5
5
  SHA512:
6
- metadata.gz: f1a1a854eab024c26b38a9db6d5c9b6ee5c000acfcd9858cc6a82cf27f0acddc1566749fc2d0981778e34312568cf42f2559902846800980dc3bcb5b86a84b4a
7
- data.tar.gz: ebd998b3cfbdd5a10ecd1d053bf7ff7a79ff8fb15088b760fe75e83da4b63738e69ccfccab4ce1d088fdfdd84c22b938f77d5a56ffd9976afeb3cadabe3fb307
6
+ metadata.gz: 5be1f66ae222c299dd0bdd685c52c4860064fabe99f91610a166662a88adc5e52c7d61450a5abb96ecd2390fae7ee5116a31c7afc19a2592ca4cd804c7a0554c
7
+ data.tar.gz: 523a6ab61c1090605b802dd5701f280d5ab033343093b42684af40de6952b143a43e70508e1aafdf1d379831ef1f7b1a9e27ae38b77f35fd9190cda8525766ca
data/lib/run_loop.rb CHANGED
@@ -24,6 +24,7 @@ require 'run_loop/cache/cache'
24
24
  require 'run_loop/host_cache'
25
25
  require 'run_loop/patches/awesome_print'
26
26
  require 'run_loop/patches/retriable'
27
+ require 'run_loop/life_cycle/simulator'
27
28
  require 'run_loop/life_cycle/core_simulator'
28
29
  require 'run_loop/simctl/bridge'
29
30
  require 'run_loop/simctl/plists'
@@ -109,7 +109,7 @@ module RunLoop
109
109
 
110
110
  begin
111
111
  RunLoop::SimControl.terminate_all_sims
112
- terminate_core_simulator_processes
112
+ RunLoop::LifeCycle::Simulator.new.terminate_core_simulator_processes
113
113
  ensure
114
114
  ENV['DEBUG'] = original_value if debug
115
115
  end
@@ -125,33 +125,6 @@ module RunLoop
125
125
  device.state == 'Booted'
126
126
  end
127
127
  end
128
-
129
- # TODO this is duplicated code; extract!
130
- # https://github.com/calabash/run_loop/issues/225
131
- def terminate_core_simulator_processes
132
- to_manage = RunLoop::LifeCycle::CoreSimulator::MANAGED_PROCESSES
133
- to_manage << ['com.apple.CoreSimulator.CoreSimulatorService', false]
134
-
135
- to_manage.each do |pair|
136
- name = pair[0]
137
- send_term = pair[1]
138
- pids = RunLoop::ProcessWaiter.new(name).pids
139
- pids.each do |pid|
140
-
141
- if send_term
142
- term = RunLoop::ProcessTerminator.new(pid, 'TERM', name)
143
- killed = term.kill_process
144
- else
145
- killed = false
146
- end
147
-
148
- unless killed
149
- term = RunLoop::ProcessTerminator.new(pid, 'KILL', name)
150
- term.kill_process
151
- end
152
- end
153
- end
154
- end
155
128
  end
156
129
 
157
130
  desc 'install --app [OPTIONS]', 'Installs an app on a device'
data/lib/run_loop/core.rb CHANGED
@@ -443,8 +443,11 @@ Logfile: #{log_file}
443
443
  xcode = sim_control.xcode
444
444
  if xcode.version_gte_6?
445
445
  simulator = sim_control.simulators.find do |sim|
446
- sim.instruments_identifier(xcode) == value ||
447
- sim.udid == value
446
+ [
447
+ sim.instruments_identifier(xcode) == value,
448
+ sim.udid == value,
449
+ sim.name == value
450
+ ].any?
448
451
  end
449
452
  !simulator.nil?
450
453
  else
@@ -282,23 +282,27 @@ Please update your sources to pass an instance of RunLoop::Xcode))
282
282
  #
283
283
  # 1. The SHA sum of the simulator data/ directory to be stable.
284
284
  # 2. No more log messages are begin generated
285
- # 3. 1 and 2 must hold for 2 seconds.
285
+ # 3. 1 and 2 must hold for 1 seconds.
286
286
  #
287
287
  # When the simulator version is >= iOS 9 _and_ it is the first launch of
288
288
  # the simulator after a reset or a new simulator install, a fourth condition
289
289
  # is added:
290
290
  #
291
291
  # 4. The first three conditions must be met a second time.
292
+ #
293
+ # and the quiet time is increased to 2.0.
292
294
  def simulator_wait_for_stable_state
293
295
  require 'securerandom'
294
296
 
295
- quiet_time = 2
296
297
  delay = 0.5
297
298
 
298
299
  first_launch = false
299
300
 
300
301
  if version >= RunLoop::Version.new('9.0')
301
302
  first_launch = simulator_data_dir_size < 20
303
+ quiet_time = 2
304
+ else
305
+ quiet_time = 1
302
306
  end
303
307
 
304
308
  now = Time.now
@@ -9,6 +9,10 @@ module RunLoop
9
9
 
10
10
  attr_reader :xcode
11
11
 
12
+ def pbuddy
13
+ @pbuddy ||= RunLoop::PlistBuddy.new
14
+ end
15
+
12
16
  def xcode
13
17
  @xcode ||= RunLoop::Xcode.new
14
18
  end
@@ -110,10 +114,9 @@ Please update your sources to pass an instance of RunLoop::Xcode))
110
114
  # @return [RunLoop::Version] A version object.
111
115
  def version
112
116
  @instruments_version ||= lambda do
113
- args = ['instruments']
114
- hash = xcrun.exec(args, log_cmd: true)
115
- version_str = hash[:err][VERSION_REGEX, 0]
116
- RunLoop::Version.new(version_str)
117
+ version_string = pbuddy.plist_read('CFBundleShortVersionString',
118
+ path_to_instruments_app_plist)
119
+ RunLoop::Version.new(version_string)
117
120
  end.call
118
121
  end
119
122
 
@@ -398,5 +401,16 @@ Please update your sources to pass an instance of RunLoop::Xcode))
398
401
  def line_is_simulator_paired_with_watch?(line)
399
402
  line[CORE_SIMULATOR_UDID_REGEX, 0] && line[/Apple Watch/, 0]
400
403
  end
404
+
405
+ # @!visibility private
406
+ def path_to_instruments_app_plist
407
+ @path_to_instruments_app_plist ||=
408
+ File.expand_path(File.join(xcode.developer_dir,
409
+ '..',
410
+ 'Applications',
411
+ 'Instruments.app',
412
+ 'Contents',
413
+ 'Info.plist'))
414
+ end
401
415
  end
402
416
  end
@@ -1,7 +1,7 @@
1
1
  module RunLoop
2
2
  module LifeCycle
3
3
 
4
- class CoreSimulator
4
+ class CoreSimulator < Simulator
5
5
 
6
6
  require 'securerandom'
7
7
 
@@ -11,36 +11,6 @@ module RunLoop
11
11
  # @!visibility private
12
12
  CORE_SIMULATOR_DEVICE_DIR = File.expand_path('~/Library/Developer/CoreSimulator/Devices')
13
13
 
14
- # @!visibility private
15
- # Pattern.
16
- # [ '< process name >', < send term first > ]
17
- MANAGED_PROCESSES =
18
- [
19
- # This process is a daemon, and requires 'KILL' to terminate.
20
- # Killing the process is fast, but it takes a long time to
21
- # restart.
22
- # ['com.apple.CoreSimulator.CoreSimulatorService', false],
23
-
24
- # Probably do not need to quit this, but it is tempting to do so.
25
- #['com.apple.CoreSimulator.SimVerificationService', false],
26
-
27
- # Started by Xamarin Studio, this is the parent process of the
28
- # processes launched by Xamarin's interaction with
29
- # CoreSimulatorBridge.
30
- ['csproxy', true],
31
-
32
- # Yes.
33
- ['SimulatorBridge', true],
34
- ['configd_sim', true],
35
- ['launchd_sim', true],
36
-
37
- # Does not always appear.
38
- ['CoreSimulatorBridge', true],
39
-
40
- # Xcode 7
41
- ['ids_simd', true]
42
- ]
43
-
44
14
  # @!visibility private
45
15
  # How long to wait after the simulator has launched.
46
16
  SIM_POST_LAUNCH_WAIT = RunLoop::Environment.sim_post_launch_wait || 1.0
@@ -409,29 +379,6 @@ module RunLoop
409
379
  end
410
380
  end
411
381
 
412
- # @!visibility private
413
- def terminate_core_simulator_processes
414
- MANAGED_PROCESSES.each do |pair|
415
- name = pair[0]
416
- send_term = pair[1]
417
- pids = RunLoop::ProcessWaiter.new(name).pids
418
- pids.each do |pid|
419
-
420
- if send_term
421
- term = RunLoop::ProcessTerminator.new(pid, 'TERM', name)
422
- killed = term.kill_process
423
- else
424
- killed = false
425
- end
426
-
427
- unless killed
428
- term = RunLoop::ProcessTerminator.new(pid, 'KILL', name)
429
- term.kill_process
430
- end
431
- end
432
- end
433
- end
434
-
435
382
  # @!visibility private
436
383
  def wait_for_device_state(target_state)
437
384
  now = Time.now
@@ -537,9 +484,13 @@ module RunLoop
537
484
  # For testing.
538
485
  def launch
539
486
 
540
- install
541
487
  launch_simulator
542
488
 
489
+ args = ['simctl', 'install', device.udid, app.path]
490
+ RunLoop::Xcrun.new.exec(args, log_cmd: true, timeout: 10)
491
+
492
+ device.simulator_wait_for_stable_state
493
+
543
494
  args = ['simctl', 'launch', device.udid, app.bundle_identifier]
544
495
  hash = RunLoop::Xcrun.new.exec(args, log_cmd: true, timeout: 20)
545
496
 
@@ -551,7 +502,12 @@ module RunLoop
551
502
  raise RuntimeError, "Could not launch #{app.bundle_identifier} on #{device}"
552
503
  end
553
504
 
554
- RunLoop::ProcessWaiter.new(app.executable_name, WAIT_FOR_APP_LAUNCH_OPTS).wait_for_any
505
+ RunLoop::ProcessWaiter.new(app.executable_name, {:timeout => 10,
506
+ :raise_on_timeout => true}).wait_for_any
507
+
508
+
509
+ device.simulator_wait_for_stable_state
510
+
555
511
  true
556
512
  end
557
513
  end
@@ -0,0 +1,73 @@
1
+ module RunLoop
2
+
3
+ # @!visibility private
4
+ module LifeCycle
5
+
6
+ # @!visibility private
7
+ #
8
+ # Defines a Life Cycle interface for Simulators.
9
+ class Simulator
10
+
11
+ # @!visibility private
12
+ # Pattern.
13
+ # [ '< process name >', < send term first > ]
14
+ MANAGED_PROCESSES =
15
+ [
16
+ # This process is a daemon, and requires 'KILL' to terminate.
17
+ # Killing the process is fast, but it takes a long time to
18
+ # restart.
19
+ # ['com.apple.CoreSimulator.CoreSimulatorService', false],
20
+
21
+ # Probably do not need to quit this, but it is tempting to do so.
22
+ #['com.apple.CoreSimulator.SimVerificationService', false],
23
+
24
+ # Started by Xamarin Studio, this is the parent process of the
25
+ # processes launched by Xamarin's interaction with
26
+ # CoreSimulatorBridge.
27
+ ['csproxy', true],
28
+
29
+ # Yes.
30
+ ['SimulatorBridge', true],
31
+ ['configd_sim', true],
32
+ ['launchd_sim', true],
33
+
34
+ # Does not always appear.
35
+ ['CoreSimulatorBridge', true],
36
+
37
+ # assetsd instances clobber each other and are not properly
38
+ # killed when quiting the simulator.
39
+ ['assetsd', true],
40
+
41
+ # iproxy is started by UITest. It is not necessary to send
42
+ # TERM first.
43
+ ['iproxy', false],
44
+
45
+ # Xcode 7
46
+ ['ids_simd', true]
47
+ ]
48
+
49
+ # @!visibility private
50
+ def terminate_core_simulator_processes
51
+ MANAGED_PROCESSES.each do |pair|
52
+ name = pair[0]
53
+ send_term = pair[1]
54
+ pids = RunLoop::ProcessWaiter.new(name).pids
55
+ pids.each do |pid|
56
+
57
+ if send_term
58
+ term = RunLoop::ProcessTerminator.new(pid, 'TERM', name)
59
+ killed = term.kill_process
60
+ else
61
+ killed = false
62
+ end
63
+
64
+ unless killed
65
+ term = RunLoop::ProcessTerminator.new(pid, 'KILL', name)
66
+ term.kill_process
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -15,7 +15,7 @@ module RunLoop::Simctl
15
15
  # TODO Reinstall if checksum does not match.
16
16
  # TODO Analyze terminate_core_simulator_processes.
17
17
  # TODO Figure out when CoreSimulator appears and does not appear.
18
- class Bridge
18
+ class Bridge < RunLoop::LifeCycle::CoreSimulator
19
19
 
20
20
  attr_reader :device
21
21
  attr_reader :app
@@ -186,54 +186,6 @@ module RunLoop::Simctl
186
186
  @device.state
187
187
  end
188
188
 
189
- def terminate_core_simulator_processes
190
- [
191
- # Pattern.
192
- # [ '< process name >', < send term first > ]
193
-
194
- # No. This process is a daemon, and requires 'KILL' to terminate.
195
- # Killing the process is fast, but it takes a long time to restart.
196
- # ['com.apple.CoreSimulator.CoreSimulatorService', false],
197
-
198
- # Probably do not need to quit this, but it is tempting to do so.
199
- #['com.apple.CoreSimulator.SimVerificationService', false],
200
-
201
- # Started by Xamarin Studio, this is the parent process of the
202
- # processes launched by Xamarin's interaction with
203
- # CoreSimulatorBridge
204
- ['csproxy', true],
205
-
206
- # Yes.
207
- ['SimulatorBridge', true],
208
- ['configd_sim', true],
209
- ['launchd_sim', true],
210
-
211
- # Yes, but does not always appear.
212
- ['CoreSimulatorBridge', true],
213
-
214
- # Xcode 7
215
- ['ids_simd', true],
216
- ].each do |pair|
217
- name = pair[0]
218
- send_term = pair[1]
219
- pids = RunLoop::ProcessWaiter.new(name).pids
220
- pids.each do |pid|
221
-
222
- if send_term
223
- term = RunLoop::ProcessTerminator.new(pid, 'TERM', name)
224
- killed = term.kill_process
225
- else
226
- killed = false
227
- end
228
-
229
- unless killed
230
- term = RunLoop::ProcessTerminator.new(pid, 'KILL', name)
231
- term.kill_process
232
- end
233
- end
234
- end
235
- end
236
-
237
189
  def wait_for_device_state(target_state)
238
190
  return true if update_device_state == target_state
239
191
 
@@ -1,5 +1,5 @@
1
1
  module RunLoop
2
- VERSION = '1.5.4'
2
+ VERSION = '1.5.5'
3
3
 
4
4
  # A model of a software release version that can be used to compare two versions.
5
5
  #
@@ -1,20 +1,23 @@
1
1
  module RunLoop
2
2
  class Xcrun
3
3
 
4
+ require 'command_runner' if RUBY_VERSION >= '2.0'
5
+
4
6
  DEFAULT_OPTIONS =
5
7
  {
6
- :timeout => 10,
8
+ :timeout => 30,
7
9
  :log_cmd => false
8
10
  }
9
11
 
10
- DEFAULT_TIMEOUT = 10
11
-
12
12
  # Raised when Xcrun fails.
13
- class XcrunError < RuntimeError; end
13
+ class Error < RuntimeError; end
14
14
 
15
- attr_reader :stdin, :stdout, :stderr, :pid
15
+
16
+ # Raised when Xcrun times out.
17
+ class TimeoutError < RuntimeError; end
16
18
 
17
19
  def exec(args, options={})
20
+
18
21
  merged_options = DEFAULT_OPTIONS.merge(options)
19
22
 
20
23
  timeout = merged_options[:timeout]
@@ -24,7 +27,13 @@ module RunLoop
24
27
  "Expected args '#{args}' to be an Array, but found '#{args.class}'"
25
28
  end
26
29
 
27
- @stdin, @stdout, out, @stderr, err, process_status, @pid, exit_status = nil
30
+ args.each do |arg|
31
+ unless arg.is_a?(String)
32
+ raise ArgumentError,
33
+ %Q{Expected arg '#{arg}' to be a String, but found '#{arg.class}'
34
+ IO.popen requires all arguments to be Strings.}
35
+ end
36
+ end
28
37
 
29
38
  cmd = "xcrun #{args.join(' ')}"
30
39
 
@@ -32,8 +41,61 @@ module RunLoop
32
41
  # Commands are only logged when debugging.
33
42
  RunLoop.log_unix_cmd(cmd) if merged_options[:log_cmd]
34
43
 
44
+ # Ruby < 2.0 support
45
+ return exec_ruby19(args, merged_options) if RUBY_VERSION < '2.0'
46
+
47
+ hash = {}
48
+
49
+ begin
50
+
51
+ start_time = Time.now
52
+ command_output = CommandRunner.run(['xcrun'] + args, timeout: timeout)
53
+
54
+ if command_output[:out]
55
+ out = command_output[:out].force_encoding('utf-8').chomp
56
+ else
57
+ out = ''
58
+ end
59
+
60
+ process_status = command_output[:status]
61
+
62
+ hash =
63
+ {
64
+ :out => out,
65
+ :pid => process_status.pid,
66
+ # nil if process was killed before completion
67
+ :exit_status => process_status.exitstatus
68
+ }
69
+
70
+ rescue => e
71
+ elapsed = "%0.2f" % (Time.now - start_time)
72
+ raise Error, "Xcrun encountered an error after #{elapsed} seconds: #{e}"
73
+ end
74
+
75
+ if hash[:exit_status].nil?
76
+ elapsed = "%0.2f" % (Time.now - start_time)
77
+ raise TimeoutError,
78
+ "Xcrun timed out after #{elapsed} seconds executing '#{cmd}' with a timeout of #{timeout}"
79
+ end
80
+
81
+ hash
82
+ end
83
+
84
+ private
85
+
86
+ attr_reader :stdin, :stdout, :stderr, :pid
87
+
88
+ def exec_ruby19(args, options)
89
+
90
+ timeout = options[:timeout]
91
+
92
+ cmd = "xcrun #{args.join(' ')}"
93
+
94
+ err, out, pid, exit_status, process_status = nil
95
+
96
+ hash = nil
35
97
  begin
36
- Timeout.timeout(timeout, TimeoutError) do
98
+ Timeout.timeout(timeout, Timeout::Error) do
37
99
  @stdin, @stdout, @stderr, process_status = Open3.popen3('xcrun', *args)
38
100
 
39
101
  @pid = process_status.pid
@@ -45,14 +107,17 @@ module RunLoop
45
107
  out = @stdout.read.force_encoding('utf-8').chomp
46
108
  end
47
109
 
48
- {
49
- :err => err,
50
- :out => out,
51
- :pid => pid,
52
- :exit_status => exit_status
53
- }
110
+ hash =
111
+ {
112
+ :err => err,
113
+ :out => out,
114
+ :pid => pid,
115
+ :exit_status => exit_status
116
+ }
117
+ rescue Timeout::Error => _
118
+ raise TimeoutError, "Xcrun.exec timed out after #{timeout} running '#{cmd}'"
54
119
  rescue StandardError => e
55
- raise XcrunError, e
120
+ raise Error, e
56
121
  ensure
57
122
  stdin.close if stdin && !stdin.closed?
58
123
  stdout.close if stdout && !stdout.closed?
@@ -70,6 +135,7 @@ module RunLoop
70
135
  process_status.join
71
136
  end
72
137
  end
138
+ hash
73
139
  end
74
140
  end
75
141
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: run_loop
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.4
4
+ version: 1.5.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Karl Krukow
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-16 00:00:00.000000000 Z
11
+ date: 2015-09-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -92,6 +92,20 @@ dependencies:
92
92
  - - "<"
93
93
  - !ruby/object:Gem::Version
94
94
  version: '1.0'
95
+ - !ruby/object:Gem::Dependency
96
+ name: command_runner_ng
97
+ requirement: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: 0.0.2
102
+ type: :runtime
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: 0.0.2
95
109
  - !ruby/object:Gem::Dependency
96
110
  name: luffa
97
111
  requirement: !ruby/object:Gem::Requirement
@@ -286,6 +300,7 @@ files:
286
300
  - lib/run_loop/ipa.rb
287
301
  - lib/run_loop/l10n.rb
288
302
  - lib/run_loop/life_cycle/core_simulator.rb
303
+ - lib/run_loop/life_cycle/simulator.rb
289
304
  - lib/run_loop/lipo.rb
290
305
  - lib/run_loop/lldb.rb
291
306
  - lib/run_loop/logging.rb
@@ -341,3 +356,4 @@ specification_version: 4
341
356
  summary: The bridge between Calabash iOS and Xcode command-line tools like instruments
342
357
  and simctl.
343
358
  test_files: []
359
+ has_rdoc: