run_loop 1.0.0.pre3 → 1.0.0.pre5

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