run_loop 1.5.4 → 1.5.5

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
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: