run_loop 1.0.0.pre3 → 1.0.0.pre5

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: 8fbeb69acc86dff93a612295675c56e5c60b9286
4
- data.tar.gz: 3d8639044fcbf76a09a8b1dc3ec426ad6dcae537
3
+ metadata.gz: fc544f0548cb7f02b158070fa88a30215d494c4f
4
+ data.tar.gz: c6db656c4e9b52ed5225f0eedea4edc178cc604f
5
5
  SHA512:
6
- metadata.gz: 521d737aa170ac8ef6be590b47024aced47db7b8698641a0124b1bc5bff4a6fb7e6207ca01039039cea551e2776c8ae4f55e14ce61f3ad93573a0b6293f36f0e
7
- data.tar.gz: 4c22b25f74512d2590efd9a0ee79c7c8d776319672f938215acbae5861ca0163b706311ee05d5569951ec6fc968168d9517b77dd83ebaf558a7ba517e86d9090
6
+ metadata.gz: 127d85c861b0180ccd3d6f628047b30a8e8216802f76f8add3b68e299cf1fb75355dd3e98772ba8e425814e08b8e84462d1f76d5bd334ec40fd2dd5708b1c3b2
7
+ data.tar.gz: 3a3cab1c95a93fb7860ef0c636170f360d70f9b95bca6038b654250e97589f4585dba30b2731e5736d8eccf23ee6a56c12950e2a07dd40cea63d27ed892c885c
data/lib/run_loop/core.rb CHANGED
@@ -3,6 +3,7 @@ require 'tmpdir'
3
3
  require 'timeout'
4
4
  require 'json'
5
5
  require 'open3'
6
+ require 'erb'
6
7
 
7
8
  module RunLoop
8
9
 
@@ -21,6 +22,8 @@ module RunLoop
21
22
  :run_loop_host => 'run_loop_host.js'
22
23
  }
23
24
 
25
+ READ_SCRIPT_PATH = File.join(SCRIPTS_PATH, 'read-cmd.sh')
26
+
24
27
  def self.scripts_path
25
28
  SCRIPTS_PATH
26
29
  end
@@ -67,9 +70,10 @@ module RunLoop
67
70
  sim_control ||= options[:sim_control] || RunLoop::SimControl.new
68
71
  xctools ||= options[:xctools] || sim_control.xctools
69
72
 
70
- # @todo only enable accessibility when there is simulator target
71
- # @todo only enable accessibility on the targeted simulator
72
- sim_control.enable_accessibility_on_sims({:verbose => true})
73
+ if self.simulator_target?(options, sim_control)
74
+ # @todo only enable accessibility on the targeted simulator
75
+ sim_control.enable_accessibility_on_sims({:verbose => true})
76
+ end
73
77
 
74
78
  device_target = options[:udid] || options[:device_target] || detect_connected_device || 'simulator'
75
79
  if device_target && device_target.to_s.downcase == 'device'
@@ -94,31 +98,50 @@ module RunLoop
94
98
 
95
99
  code = File.read(options[:script])
96
100
  code = code.gsub(/\$PATH/, results_dir)
101
+ code = code.gsub(/\$READ_SCRIPT_PATH/, READ_SCRIPT_PATH)
97
102
  code = code.gsub(/\$MODE/, 'FLUSH') unless options[:no_flush]
98
103
 
99
- repl_path = File.join(results_dir, 'repl-cmd.txt')
100
- File.open(repl_path, 'w') { |file| file.puts "0:UIALogger.logMessage('Listening for run loop commands');" }
104
+ repl_path = File.join(results_dir, 'repl-cmd.pipe')
105
+ FileUtils.rm_f(repl_path)
101
106
 
102
- File.open(script, 'w') { |file| file.puts code }
107
+ uia_strategy = options[:uia_strategy]
108
+ if uia_strategy == :host
109
+ unless system(%Q[mkfifo "#{repl_path}"])
110
+ raise 'Unable to create pipe (mkfifo failed)'
111
+ end
112
+ end
103
113
 
114
+ cal_script = File.join(SCRIPTS_PATH, 'calabash_script_uia.js')
115
+ File.open(script, 'w') do |file|
116
+ file.puts IO.read(cal_script)
117
+ file.puts code
118
+ end
104
119
 
105
120
  # Compute udid and bundle_dir / bundle_id from options and target depending on Xcode version
106
121
  udid, bundle_dir_or_bundle_id = udid_and_bundle_for_launcher(device_target, options, xctools)
107
122
 
108
123
  args = options.fetch(:args, [])
109
124
 
110
- inject_dylib = options.fetch(:inject_dylib, (ENV['CALABASH_USE_DYLIB']=='1'))
125
+ inject_dylib = self.dylib_path_from_options options
126
+ # WIP This is brute-force call against all lldb processes.
127
+ self.ensure_lldb_not_running if inject_dylib
111
128
 
112
129
  log_file ||= File.join(results_dir, 'run_loop.out')
113
130
 
114
131
  if ENV['DEBUG']=='1'
115
- p options
132
+ exclude = [:device_target, :udid, :sim_control, :args, :inject_dylib, :app]
133
+ options.each_pair { |key, value|
134
+ unless exclude.include? key
135
+ puts "#{key} => #{value}"
136
+ end
137
+ }
116
138
  puts "device_target=#{device_target}"
117
139
  puts "udid=#{udid}"
118
140
  puts "bundle_dir_or_bundle_id=#{bundle_dir_or_bundle_id}"
119
141
  puts "script=#{script}"
120
142
  puts "log_file=#{log_file}"
121
143
  puts "timeout=#{timeout}"
144
+ puts "uia_strategy=#{options[:uia_strategy]}"
122
145
  puts "args=#{args}"
123
146
  puts "inject_dylib=#{inject_dylib}"
124
147
  end
@@ -158,25 +181,39 @@ module RunLoop
158
181
  f.write pid
159
182
  end
160
183
 
161
- run_loop = {:pid => pid, :udid => udid, :app => bundle_dir_or_bundle_id, :repl_path => repl_path, :log_file => log_file, :results_dir => results_dir}
184
+ run_loop = {:pid => pid,
185
+ :index => 1,
186
+ :uia_strategy => uia_strategy,
187
+ :udid => udid,
188
+ :app => bundle_dir_or_bundle_id,
189
+ :repl_path => repl_path,
190
+ :log_file => log_file,
191
+ :results_dir => results_dir}
162
192
 
163
193
  uia_timeout = options[:uia_timeout] || (ENV['UIA_TIMEOUT'] && ENV['UIA_TIMEOUT'].to_f) || 10
164
194
 
165
195
  raw_lldb_output = nil
166
196
  before = Time.now
167
197
  begin
198
+
199
+ File.open(repl_path, 'w') { |file| file.puts "0:UIALogger.logMessage('Listening for run loop commands');" }
200
+
168
201
  Timeout::timeout(timeout, TimeoutError) do
169
202
  read_response(run_loop, 0, uia_timeout)
170
203
  end
204
+
205
+ # inject_dylib will be nil or a path to a dylib
171
206
  if inject_dylib
172
207
  lldb_template_file = File.join(scripts_path,'calabash.lldb.erb')
173
- require 'erb'
174
208
  lldb_template = ::ERB.new(File.read(lldb_template_file))
175
209
  lldb_template.filename = lldb_template_file
176
210
 
211
+ # Special!
212
+ # These are required by the ERB in calabash.lldb.erb
213
+ # noinspection RubyUnusedLocalVariable
177
214
  cf_bundle_executable = find_cf_bundle_executable(bundle_dir_or_bundle_id)
178
- require 'calabash/dylibs'
179
- dylib_path_for_target = Calabash::Dylibs.path_to_sim_dylib
215
+ # noinspection RubyUnusedLocalVariable
216
+ dylib_path_for_target = inject_dylib
180
217
 
181
218
  lldb_cmd = lldb_template.result(binding)
182
219
 
@@ -187,11 +224,23 @@ module RunLoop
187
224
 
188
225
  if ENV['DEBUG'] == '1'
189
226
  puts "lldb script #{lldb_script}"
227
+ puts "=== lldb script ==="
228
+ counter = 0
229
+ File.open(lldb_script, 'r').readlines.each { |line|
230
+ puts "#{counter} #{line}"
231
+ counter = counter + 1
232
+ }
233
+ puts "=== lldb script ==="
190
234
  end
191
235
 
192
- raw_lldb_output = `lldb -s #{lldb_script}`
193
- if ENV['DEBUG'] == '1'
194
- puts raw_lldb_output
236
+ # Forcing a timeout. Do not retry here. If lldb is hanging,
237
+ # RunLoop::Core.run* needs to be called again. Put another way,
238
+ # instruments and lldb must be terminated.
239
+ Retriable.retriable({:tries => 1, :timeout => 12, :interval => 1}) do
240
+ raw_lldb_output = `xcrun lldb -s #{lldb_script}`
241
+ if ENV['DEBUG'] == '1'
242
+ puts raw_lldb_output
243
+ end
195
244
  end
196
245
  end
197
246
  rescue TimeoutError => e
@@ -204,6 +253,7 @@ module RunLoop
204
253
  puts "script=#{script}"
205
254
  puts "log_file=#{log_file}"
206
255
  puts "timeout=#{timeout}"
256
+ puts "uia_strategy=#{uia_strategy}"
207
257
  puts "args=#{args}"
208
258
  puts "lldb_output=#{raw_lldb_output}" if raw_lldb_output
209
259
  end
@@ -219,6 +269,56 @@ module RunLoop
219
269
  run_loop
220
270
  end
221
271
 
272
+ # @!visibility private
273
+ # Are we targeting a simulator?
274
+ #
275
+ # @note The behavior of this method is different than the corresponding
276
+ # method in Calabash::Cucumber::Launcher method. If
277
+ # `:device_target => {nil | ''}`, then the calabash-ios method returns
278
+ # _false_. I am basing run-loop's behavior off the behavior in
279
+ # `self.udid_and_bundle_for_launcher`
280
+ #
281
+ # @see {Core::RunLoop.udid_and_bundle_for_launcher}
282
+ def self.simulator_target?(run_options, sim_control = RunLoop::SimControl.new)
283
+ value = run_options[:device_target]
284
+
285
+ # match the behavior of udid_and_bundle_for_launcher
286
+ return true if value.nil? or value == ''
287
+
288
+ # support for 'simulator' and Xcode >= 5.1 device targets
289
+ return true if value.downcase.include?('simulator')
290
+
291
+ # if Xcode < 6.0, we are done
292
+ return false if not sim_control.xcode_version_gte_6?
293
+
294
+ # support for Xcode >= 6 simulator udids
295
+ return true if sim_control.sim_udid? value
296
+
297
+ # support for Xcode >= 6 'named simulators'
298
+ sims = sim_control.simulators.each
299
+ sims.find_index { |device| device.name == value } != nil
300
+ end
301
+
302
+ # Extracts the value of :inject_dylib from options Hash.
303
+ # @param options [Hash] arguments passed to {RunLoop.run}
304
+ # @return [String, nil] If the options contains :inject_dylibs and it is a
305
+ # path to a dylib that exists, return the path. Otherwise return nil or
306
+ # raise an error.
307
+ # @raise [RuntimeError] If :inject_dylib points to a path that does not exist.
308
+ # @raise [ArgumentError] If :inject_dylib is not a String.
309
+ def self.dylib_path_from_options(options)
310
+ inject_dylib = options.fetch(:inject_dylib, nil)
311
+ return nil if inject_dylib.nil?
312
+ unless inject_dylib.is_a? String
313
+ raise ArgumentError, "Expected :inject_dylib to be a path to a dylib, but found '#{inject_dylib}'"
314
+ end
315
+ dylib_path = File.expand_path(inject_dylib)
316
+ unless File.exist?(dylib_path)
317
+ raise "Cannot load dylib. The file '#{dylib_path}' does not exist."
318
+ end
319
+ dylib_path
320
+ end
321
+
222
322
  def self.find_cf_bundle_executable(bundle_dir_or_bundle_id)
223
323
  unless File.directory?(bundle_dir_or_bundle_id)
224
324
  raise "Injecting dylibs currently only works with simulator and app bundles"
@@ -291,26 +391,10 @@ module RunLoop
291
391
 
292
392
  def self.write_request(run_loop, cmd)
293
393
  repl_path = run_loop[:repl_path]
394
+ index = run_loop[:index]
395
+ File.open(repl_path, 'w') {|f| f.puts("#{index}:#{cmd}")}
396
+ run_loop[:index] = index + 1
294
397
 
295
- cur = File.read(repl_path)
296
-
297
- colon = cur.index(':')
298
-
299
- if colon.nil?
300
- raise "Illegal contents of #{repl_path}: #{cur}"
301
- end
302
- index = cur[0, colon].to_i + 1
303
-
304
-
305
- tmp_cmd = File.join(File.dirname(repl_path), '__repl-cmd.txt')
306
- File.open(tmp_cmd, 'w') do |f|
307
- f.write("#{index}:#{cmd}")
308
- if ENV['DEBUG']
309
- puts "Wrote: #{index}:#{cmd}"
310
- end
311
- end
312
-
313
- FileUtils.mv(tmp_cmd, repl_path)
314
398
  index
315
399
  end
316
400
 
@@ -490,12 +574,38 @@ module RunLoop
490
574
  pids_str.split(',').map { |pid| pid.to_i }
491
575
  end
492
576
 
577
+ # @todo This is a WIP
578
+ # @todo Needs rspec test
579
+ def self.ensure_lldb_not_running
580
+ descripts = `xcrun ps x -o pid,command | grep "lldb" | grep -v grep`.strip.split("\n")
581
+ descripts.each do |process_desc|
582
+ pid = process_desc.split(' ').first
583
+ Open3.popen3("xcrun kill -9 #{pid} && xcrun wait #{pid}") do |_, stdout, stderr, _|
584
+ out = stdout.read.strip
585
+ err = stderr.read.strip
586
+ next if out.to_s.empty? and err.to_s.empty?
587
+ # there lots of 'ownership' problems trying to kill the lldb process
588
+ #puts "kill process '#{pid}' => stdout: '#{out}' | stderr: '#{err}'"
589
+ end
590
+ end
591
+ end
493
592
  end
494
593
 
495
594
 
496
595
  def self.run(options={})
497
- script = validate_script(options)
596
+
597
+ uia_strategy = options[:uia_strategy]
598
+ if uia_strategy
599
+ if uia_strategy == :host
600
+ script = Core.script_for_key(:run_loop_host)
601
+ else
602
+ script = Core.script_for_key(:run_loop_fast_uia)
603
+ end
604
+ else
605
+ uia_strategy, script = validate_script(options)
606
+ end
498
607
  options[:script] = script
608
+ options[:uia_strategy] = uia_strategy
499
609
 
500
610
  Core.run_with_options(options)
501
611
  end
@@ -546,24 +656,37 @@ module RunLoop
546
656
 
547
657
 
548
658
  def self.validate_script(options)
659
+ if options[:calabash_lite]
660
+ return :host, Core.script_for_key(:run_loop_host)
661
+ end
662
+ uia_strategy = options[:uia_strategy]
663
+ if uia_strategy
664
+ if uia_strategy == :host
665
+ script = :run_loop_host
666
+ elsif uia_strategy == :preferences
667
+ script = :run_loop_fast_uia
668
+ else
669
+ raise "Invalid :uia_strategy #{uia_strategy}"
670
+ end
671
+ return uia_strategy, Core.script_for_key(script)
672
+ end
673
+
549
674
  script = options[:script]
550
675
  if script
551
676
  if script.is_a?(Symbol)
677
+ uia_strategy = (script == :run_loop_fast_uia ? :preferences : :host)
552
678
  script = Core.script_for_key(script)
553
679
  unless script
554
680
  raise "Unknown script for symbol: #{options[:script]}. Options: #{Core::SCRIPTS.keys.join(', ')}"
555
681
  end
556
- elsif script.is_a?(String)
557
- unless File.exist?(script)
558
- raise "File does not exist: #{script}"
559
- end
560
682
  else
561
- raise "Unknown type for :script key: #{options[:script].class}"
683
+ raise "Script must be a symbol: #{script}"
562
684
  end
563
685
  else
564
686
  script = Core.script_for_key(:run_loop_fast_uia)
687
+ uia_strategy = :preferences
565
688
  end
566
- script
689
+ return uia_strategy, script
567
690
  end
568
691
 
569
692
  end
@@ -30,6 +30,16 @@ module RunLoop
30
30
  xctools.xcode_version_gte_6?
31
31
  end
32
32
 
33
+ # @!visibility private
34
+ # Are we running Xcode 5.1 or above?
35
+ #
36
+ # This is a convenience method.
37
+ #
38
+ # @return [Boolean] `true` if the current Xcode version is >= 5.1
39
+ def xcode_version_gte_51?
40
+ xctools.xcode_version_gte_51?
41
+ end
42
+
33
43
  # Return an instance of PlistBuddy.
34
44
  # @return [RunLoop::PlistBuddy] The plist buddy instance that is used internally.
35
45
  def pbuddy
@@ -286,6 +296,32 @@ module RunLoop
286
296
  results.all?
287
297
  end
288
298
 
299
+ # Is the arg a valid Xcode >= 6.0 simulator udid?
300
+ # @param [String] udid the String to check
301
+ # @return [Boolean] Returns true iff the `udid` matches /[A-F0-9]{8}-([A-F0-9]{4}-){3}[A-F0-9]{12}/
302
+ def sim_udid?(udid)
303
+ udid.length == 36 and udid[XCODE_6_SIM_UDID_REGEX,0] != nil
304
+ end
305
+
306
+ def simulators
307
+ unless xcode_version_gte_51?
308
+ raise RuntimeError, 'simctl is only available on Xcode >= 6'
309
+ end
310
+
311
+ if xcode_version_gte_6?
312
+ hash = simctl_list :devices
313
+ sims = []
314
+ hash.each_pair do |sdk, list|
315
+ list.each do |details|
316
+ sims << RunLoop::Device.new(details[:name], sdk, details[:udid])
317
+ end
318
+ end
319
+ sims
320
+ else
321
+ raise NotImplementedError, 'the simulators method is not available yet for Xcode 5.1.1'
322
+ end
323
+ end
324
+
289
325
  private
290
326
 
291
327
 
@@ -326,7 +362,7 @@ module RunLoop
326
362
  #
327
363
  # I don't know what the behavior is on Xcode 5.0*.
328
364
  :inspector_showing => {:key => 'AXInspectorEnabled',
329
- :value => 'true',
365
+ :value => 'false',
330
366
  :type => 'bool'},
331
367
 
332
368
  # Controls if the Accessibility Inspector is expanded or not
@@ -783,5 +819,136 @@ module RunLoop
783
819
  end
784
820
  res.all?
785
821
  end
822
+
823
+ # @!visibility private
824
+ #
825
+ # A ruby interface to the `simctl list` command.
826
+ #
827
+ # @note This is an Xcode >= 6.0 method.
828
+ # @raise [RuntimeError] if called on Xcode < 6.0
829
+ # @return [Hash] A hash whose primary key is a base SDK. For example,
830
+ # SDK 7.0.3 => "7.0". The value of the Hash will vary based on what is
831
+ # being listed.
832
+ def simctl_list(what)
833
+ unless xcode_version_gte_6?
834
+ raise RuntimeError, 'simctl is only available on Xcode >= 6'
835
+ end
836
+
837
+ case what
838
+ when :devices
839
+ simctl_list_devices
840
+ when :runtimes
841
+ # The 'com.apple.CoreSimulator.SimRuntime.iOS-7-0' is the runtime-id,
842
+ # which can be used to create devices.
843
+ simctl_list_runtimes
844
+ else
845
+ allowed = [:devices, :runtimes]
846
+ raise ArgumentError, "expected '#{what}' to be one of '#{allowed}'"
847
+ end
848
+ end
849
+
850
+ # @!visibility private
851
+ #
852
+ # Helper method for simctl_list.
853
+ #
854
+ # @example
855
+ # RunLoop::SimControl.new.simctl_list :devices
856
+ # {
857
+ # "7.1" =>
858
+ # [
859
+ # {
860
+ # :name => "iPhone 4s",
861
+ # :udid => "3BC5E3D7-9B81-4CE0-9C76-1888287F507B",
862
+ # :state => "Shutdown"
863
+ # }
864
+ # ],
865
+ # "8.0" => [
866
+ # {
867
+ # :name => "iPad 2",
868
+ # :udid => "D8F224D3-A59F-4F01-81AB-1959557A7E4E",
869
+ # :state => "Shutdown"
870
+ # }
871
+ # ]
872
+ # }
873
+ # @return [Hash<Array<Hash>>] Lists of available simulator details keyed by
874
+ # base sdk version.
875
+ # @see #simctl_list
876
+ def simctl_list_devices
877
+ cmd = 'xcrun simctl list devices'
878
+ Open3.popen3(cmd) do |_, stdout, stderr, _|
879
+ out = stdout.read.strip
880
+ err = stderr.read.strip
881
+ if ENV['DEBUG_UNIX_CALLS'] == '1'
882
+ puts "#{cmd} => stdout: '#{out}' | stderr: '#{err}'"
883
+ end
884
+
885
+ current_sdk = nil
886
+ res = {}
887
+ out.split("\n").each do |line|
888
+ possible_sdk = line[/(\d\.\d(\.\d)?)/,0]
889
+ if possible_sdk
890
+ current_sdk = possible_sdk
891
+ res[current_sdk] = []
892
+ next
893
+ end
894
+
895
+ if current_sdk
896
+ name = line.split('(').first.strip
897
+ udid = line[XCODE_6_SIM_UDID_REGEX,0]
898
+ state = line[/(Booted|Shutdown)/,0]
899
+ res[current_sdk] << {:name => name, :udid => udid, :state => state}
900
+ end
901
+ end
902
+ res
903
+ end
904
+ end
905
+
906
+ # @!visibility private
907
+ # Helper method for simctl_list
908
+ #
909
+ # @example
910
+ # RunLoop::SimControl.new.simctl_list :runtimes
911
+ # {
912
+ # "7.0" => {
913
+ # :sdk => "7.0.3",
914
+ # :runtime => "com.apple.CoreSimulator.SimRuntime.iOS-7-0"
915
+ # },
916
+ # "7.1" => {
917
+ # :sdk => "7.1",
918
+ # :runtime => "com.apple.CoreSimulator.SimRuntime.iOS-7-1"
919
+ # },
920
+ # "8.0" => {
921
+ # :sdk => "8.0",
922
+ # :runtime => "com.apple.CoreSimulator.SimRuntime.iOS-8-0"
923
+ # }
924
+ # }
925
+ # @see #simctl_list
926
+ def simctl_list_runtimes
927
+ # The 'com.apple.CoreSimulator.SimRuntime.iOS-7-0' is the runtime-id,
928
+ # which can be used to create devices.
929
+ cmd = 'xcrun simctl list runtimes'
930
+ Open3.popen3(cmd) do |_, stdout, stderr, _|
931
+ out = stdout.read.strip
932
+ err = stderr.read.strip
933
+ if ENV['DEBUG_UNIX_CALLS'] == '1'
934
+ puts "#{cmd} => stdout: '#{out}' | stderr: '#{err}'"
935
+ end
936
+ # Ex.
937
+ # == Runtimes ==
938
+ # iOS 7.0 (7.0.3 - 11B507) (com.apple.CoreSimulator.SimRuntime.iOS-7-0)
939
+ # iOS 7.1 (7.1 - 11D167) (com.apple.CoreSimulator.SimRuntime.iOS-7-1)
940
+ # iOS 8.0 (8.0 - 12A4331d) (com.apple.CoreSimulator.SimRuntime.iOS-8-0)
941
+ lines = out.split("\n").delete_if { |line| not line =~ /com.apple.CoreSimulator.SimRuntime/ }
942
+ res = {}
943
+ lines.each do |line|
944
+ key = line[/iOS (\d.\d)/,1]
945
+ sdk_version = line[/(\d.\d)(.\d)?\s-/, 0].tr(' -','')
946
+ runtime = line[/com.apple.CoreSimulator.SimRuntime.iOS-\d-\d/,0]
947
+ value = {:sdk => sdk_version, :runtime => runtime}
948
+ res[key] = value
949
+ end
950
+ res
951
+ end
952
+ end
786
953
  end
787
- end
954
+ end
@@ -1,5 +1,5 @@
1
1
  module RunLoop
2
- VERSION = '1.0.0.pre3'
2
+ VERSION = '1.0.0.pre5'
3
3
 
4
4
  # A model of a software release version that can be used to compare two versions.
5
5
  #
@@ -0,0 +1,7 @@
1
+ (function(){function m(){return h.frontMostApp()}function r(){return m().mainWindow()}function s(){return m().windows().toArray()}function n(){return m().keyboard()}function l(a,c){this.reason=a;this.a=c||"";this.message=this.toString()}function k(a){return!a||a instanceof UIAElementNil}function t(a,c){var b=c||[],e,d;if(k(a))return b;e=a.elements();for(var f=0,g=e.length;f<g;f+=1)d=e[f],b.push(d),t(d,b);return b}function q(a,c){for(var b=0,e=c.length;b<e;b+=1)a.push(c[b])}function u(a,c){var b=[];
2
+ if(k(c))return b;c instanceof this[a]&&b.push(c);for(var e=c.elements(),d=0,f=e.length;d<f;d+=1)q(b,u(a,e[d]));return b}function x(a,c){var b=null;if(a instanceof Array){if(3===a.length){var e=a[0],b=a[1],d=a[2];if("string"==typeof d)if(-1==d.indexOf("'"))d="'"+d+"'";else if(-1==d.indexOf('"'))d='"'+d+'"';else throw new l("Escaping for filters not supported yet.");b=c.withPredicate(e+" "+b+" "+d);return!k(b)}return!1}for(e in a)if(a.hasOwnProperty(e))if(b=a[e],"marked"==e){if(c.name()!=b&&c.label()!=
3
+ b&&(!c.value||c.value!=b))return!1}else if(b=c.withValueForKey(b,e),k(b))return!1;return!0}function v(a,c){if(c(a))return a;var b,e;if(k(a))return null;b=a.elements();for(var d=0,f=b.length;d<f;d+=1)if(e=b[d],v(e,c))return e;return null}function w(a){h.delay(a);return h}var g={},h=UIATarget.localTarget();h.setTimeout(0);l.prototype=error();l.prototype.toString=function(){var a="UIAutomationError[reason="+this.reason;0<this.a.length&&(a+=", details="+this.a);return a+"]"};g.sleep=w;g.query=function(a,
4
+ c){if(!c)return g.query(a,s());c instanceof UIAElement&&(c=[c]);var b=c,e=null,d=null,f=[],p,h,k,l;p=0;for(k=a.length;p<k;p+=1){e=a[p];h=0;for(l=b.length;h<l;h+=1)d=b[h],"string"===typeof e?"*"===e||"view"==e||"UIAElement"===e?q(f,t(d,[d])):q(f,u(e,d)):x(e,d)&&f.push(d);b=f;f=[]}return b};g.keyboard_visible=function(){return!k(n())};g.keyboard_enter_text=function(a,c){if(!g.keyboard_visible())throw new l("Keyboard not visible");c=c||{};if(c.unsafe)return n().typeString(a),!0;var b=v(r(),function(a){return 1==
5
+ a.hasKeyboardFocus()});if(k(b))return n().typeString(a),!0;var e=c.initial_text||"",d=new Date,f=c.timeout||60,h=n();do try{return h.typeString(a),!0}catch(m){UIALogger.logMessage("keyboard_enter_text failed: "+m),UIALogger.logMessage("keyboard_enter_text retrying with restore to: "+e),b.setValue(e)}while(!(new Date-d>=1E3*f));throw new l("Unable to enter text","text: "+a+" failed after retrying for "+f);};g.deactivate=function(a){h.deactivateAppForDuration(a)};g.tap_offset=function(a,c,b){b=b||{};
6
+ return b.unsafe?function(){return c.apply(this,arguments)}:function(){var e=new Date,d=b.timeout||60,f=b.frequency||.1;do try{return c.apply(this,arguments)}catch(g){UIALogger.logMessage(a+"Error: "+g+". Arguments: "+arguments[0]+", "+arguments[1]),w(f)}while(!(new Date-e>=1E3*d));throw new l(a,"Arguments: "+arguments[0]+", "+arguments[1]);}}("tap_offset failed",function(a,c){h.tapWithOptions(a,c||{})},{timeout:60,frequency:.5});this.target=h;this.uia=g;g.app=m;g.window=r;g.windows=s;g.keyboard=n;
7
+ g.alert=function(){return m().alert()}})();
@@ -0,0 +1,2 @@
1
+ #!/bin/bash
2
+ read line < $1 && echo $line
@@ -1,5 +1,3 @@
1
- #import "calabash_script_uia.js"
2
-
3
1
  if (typeof JSON !== 'object') {
4
2
  JSON = {};
5
3
  }
@@ -1,4 +1,4 @@
1
- #import "calabash_script_uia.js"
1
+ //#import "calabash_script_uia.js"
2
2
 
3
3
  if (typeof JSON !== 'object') {
4
4
  JSON = {};
@@ -151,7 +151,11 @@ var commandPath = "$PATH";
151
151
  if (!/\/$/.test(commandPath)) {
152
152
  commandPath += "/";
153
153
  }
154
- commandPath += "repl-cmd.txt";
154
+ commandPath += "repl-cmd.pipe";
155
+
156
+ var blockingReadScriptPath = "$READ_SCRIPT_PATH";
157
+
158
+
155
159
 
156
160
 
157
161
  var _expectedIndex = 0,//expected index of next command
@@ -269,19 +273,20 @@ var target = null,
269
273
 
270
274
  while (true) {
271
275
  target = UIATarget.localTarget();
276
+
272
277
  host = target.host();
273
- target.delay(0.2);
274
278
  try {
275
- _process = host.performTaskWithPathArgumentsTimeout("/bin/cat",
276
- [commandPath],
277
- 2);
279
+ _process = host.performTaskWithPathArgumentsTimeout("/bin/bash",
280
+ [blockingReadScriptPath, commandPath],
281
+ //[commandPath],
282
+ 1);
278
283
 
279
284
  } catch (e) {
280
- Log.output("Timeout on cat...");
285
+ Log.output("Timeout on read command...");
281
286
  continue;
282
287
  }
283
288
  if (_process.exitCode != 0) {
284
- Log.output("unable to execute /bin/cat " + commandPath + " exitCode " + _process.exitCode + ". Error: " + _process.stderr);
289
+ Log.output("unable to execute: " + blockingReadScriptPath + " " + commandPath + " exitCode " + _process.exitCode + ". Error: " + _process.stderr + _process.stdout);
285
290
  }
286
291
  else {
287
292
  _input = _process.stdout;
@@ -291,7 +296,9 @@ while (true) {
291
296
  _actualIndex = parseInt(_input.substring(0, _index), 10);
292
297
  if (!isNaN(_actualIndex) && _actualIndex >= _expectedIndex) {
293
298
  _exp = _input.substring(_index + 1, _input.length);
299
+ Log.output("Execute: "+_exp);
294
300
  _result = eval(_exp);
301
+ Log.output("res: "+_result);
295
302
  }
296
303
  else {//likely old command is lingering...
297
304
  continue;
@@ -309,6 +316,7 @@ while (true) {
309
316
  }
310
317
 
311
318
  _expectedIndex++;
319
+ Log.output("log result: "+_result);
312
320
  Log.result("success", _result);
313
321
 
314
322
  }
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: run_loop
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.pre3
4
+ version: 1.0.0.pre5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Karl Krukow
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-11 00:00:00.000000000 Z
11
+ date: 2014-08-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - '>='
18
18
  - !ruby/object:Gem::Version
19
- version: '0.19'
19
+ version: '0.18'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - '>='
25
25
  - !ruby/object:Gem::Version
26
- version: '0.19'
26
+ version: '0.18'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: json
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - ~>
46
46
  - !ruby/object:Gem::Version
47
- version: '1.4'
47
+ version: '1.3'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ~>
53
53
  - !ruby/object:Gem::Version
54
- version: '1.4'
54
+ version: '1.3'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: CFPropertyList
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -210,6 +210,7 @@ files:
210
210
  - lib/run_loop/version.rb
211
211
  - lib/run_loop/xctools.rb
212
212
  - lib/run_loop.rb
213
+ - scripts/calabash-uia-min.js
213
214
  - scripts/calabash_script_uia.js
214
215
  - scripts/json2-min.js
215
216
  - scripts/json2.js
@@ -218,6 +219,7 @@ files:
218
219
  - scripts/run_loop_host.js
219
220
  - scripts/udidetect
220
221
  - scripts/calabash.lldb.erb
222
+ - scripts/read-cmd.sh
221
223
  - LICENSE
222
224
  homepage: http://calaba.sh
223
225
  licenses: