scriptty 1.1.0-java → 1.2.0-java

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.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.1.0
1
+ 1.2.0
@@ -29,13 +29,17 @@ module ScripTTY
29
29
  class Expect
30
30
 
31
31
  # Methods to export to Evaluator
32
- EXPORTED_METHODS = Set.new [:basedir, :init_term, :term, :connect, :screen, :expect, :on, :wait, :send, :send_password, :capture, :match, :push_patterns, :pop_patterns, :exit, :eval_script_file, :eval_script_inline, :sleep, :set_basedir, :set_timeout, :load_screens, :print, :puts, :p, :pp ]
32
+ EXPORTED_METHODS = Set.new [:basedir, :init_term, :term, :connect, :screen, :expect, :on, :wait, :send, :send_password, :capture, :match, :push_patterns, :pop_patterns, :exit, :eval_script_file, :eval_script_inline, :sleep, :set_basedir, :set_timeout, :load_screens, :matched_screen, :matched_pattern, :print, :puts, :p, :pp ]
33
33
 
34
34
  attr_reader :term # The terminal emulation object
35
35
 
36
36
  attr_reader :capture # The last non-background captured fields. For a ScreenPattern match, this is a Hash of fields. For a String or Regexp match, this is a MatchData object.
37
37
  alias match capture # "match" is the deprecated name for "capture"
38
38
 
39
+ attr_accessor :matched_pattern # The last non-background pattern that matched (might be a RegExp or a ScreenPattern)
40
+
41
+ attr_accessor :matched_screen # The last non-background ScreenPattern that matched.
42
+
39
43
  attr_accessor :transcript_writer # Set this to an instance of ScripTTY::Util::Transcript::Writer
40
44
  attr_accessor :transcript_writer_autoclose # Set this to false to disable closing transcript_writer on exit
41
45
 
@@ -58,6 +62,8 @@ module ScripTTY
58
62
  @transcript_writer_autoclose = options[:transcript_writer_autoclose].nil? ? true : options[:transcript_writer_autoclose]
59
63
  @screen_patterns = {}
60
64
  @basedir = "."
65
+ @matched_pattern = nil
66
+ @matched_screen = nil
61
67
  end
62
68
 
63
69
  # Get instance variable from the Evaluator
@@ -87,20 +93,10 @@ module ScripTTY
87
93
  nil
88
94
  end
89
95
 
90
- # Return the expanded path relative to basedir
91
- def expand_path(path)
92
- base = Pathname.new(@basedir)
93
- p = Pathname.new(path)
94
- unless p.absolute?
95
- p = base.join(p)
96
- end
97
- p.expand_path.to_s
98
- end
99
-
100
96
  # Load and evaluate a script from a file.
101
97
  def eval_script_file(path)
102
98
  fail_unexpected_block if block_given?
103
- path = expand_path(path)
99
+ path = File.expand_path(path, @basedir)
104
100
  eval_script_inline(File.read(path), path)
105
101
  end
106
102
 
@@ -200,7 +196,7 @@ module ScripTTY
200
196
  fail_unexpected_block if block_given?
201
197
  filenames_or_glob = filenames_or_glob.to_s if filenames_or_glob.is_a?(Pathname)
202
198
  if filenames_or_glob.is_a?(String)
203
- filenames_or_glob = expand_path(filenames_or_glob)
199
+ filenames_or_glob = File.expand_path(filenames_or_glob, @basedir)
204
200
  filenames = Dir.glob(filenames_or_glob)
205
201
  elsif filenames_or_glob.is_a?(Array)
206
202
  filenames = filenames_or_glob
@@ -208,7 +204,7 @@ module ScripTTY
208
204
  raise ArgumentError.new("load_screens takes a string(glob) or an array, not #{filenames.class.name}")
209
205
  end
210
206
  filenames.each do |filename|
211
- ScreenPattern.parse(File.read(filename)).each do |pattern|
207
+ ScreenPattern.parse(File.read(filename), filename).each do |pattern|
212
208
  @screen_patterns[pattern.name.to_sym] = pattern
213
209
  end
214
210
  end
@@ -441,6 +437,8 @@ module ScripTTY
441
437
 
442
438
  # Make the next wait() call return
443
439
  unless ph.background?
440
+ @matched_pattern = ph.pattern
441
+ @matched_screen = ph.pattern if ph.pattern.is_a?(ScreenPattern)
444
442
  @capture = m
445
443
  @wait_finished = true
446
444
  @net.suspend
@@ -33,6 +33,9 @@ module ScripTTY
33
33
  # RequestDispatcher can be used, for example, to provide an HTTP interface to
34
34
  # functions of a screen-scraped terminal.
35
35
  class RequestDispatcher
36
+
37
+ class RequestCancelled < StandardError; end
38
+
36
39
  def initialize
37
40
  # Graceful shutdown flag
38
41
  @finishing_lock = Mutex.new
@@ -117,18 +120,27 @@ module ScripTTY
117
120
  def main
118
121
  loop do
119
122
  break if finishing?
120
- begin
121
- handle_one_request
122
- rescue => exc
123
- # Log & swallow exception
124
- show_exception(exc)
125
- close_expect rescue nil # Ignore errors while closing the connection
126
- sleep 0.5 # Delay just a tiny bit to keep an exception loop from consuming all available resources.
127
- end
123
+ wrap_in_exception_handler(
124
+ :body => Proc.new {
125
+ handle_one_request
126
+ },
127
+ :rescue => Proc.new { |exc|
128
+ # Log & swallow exception
129
+ show_exception(exc)
130
+ close_expect rescue nil # Ignore errors while closing the connection
131
+ sleep 0.5 # Delay just a tiny bit to keep an exception loop from consuming all available resources.
132
+ }
133
+ )
128
134
  end
129
135
  execute_hooks(:before_finish)
130
136
  ensure
131
137
  close_expect
138
+
139
+ # Clean up any remaining requests.
140
+ while (request = dequeue)
141
+ request[:exception] = RequestCancelled.new("main loop exited; request not executed")
142
+ signal_request_done(request)
143
+ end
132
144
  end
133
145
 
134
146
  def handle_one_request
@@ -140,22 +152,36 @@ module ScripTTY
140
152
 
141
153
  # Run the before_each_request hooks. If an exception is raised,
142
154
  # put the request back on the queue before re-raising the error.
143
- begin
144
- execute_hooks(:before_each_request)
145
- rescue
146
- requeue(request)
147
- raise
148
- end
155
+ wrap_in_exception_handler(
156
+ :body => Proc.new {
157
+ execute_hooks(:before_each_request)
158
+ },
159
+ :rescue => Proc.new { |exc|
160
+ requeue(request)
161
+ },
162
+ :reraise => true
163
+ )
149
164
 
150
165
  # Execute the request
166
+ success = false
167
+ exception_caught = false
151
168
  begin
152
- request[:result] = block_eval(request[:block_how], &request[:block])
153
- rescue => exc
154
- show_exception(exc, "in request")
155
- request[:exception] = exc
156
- close_expect rescue nil
169
+ wrap_in_exception_handler(
170
+ :body => Proc.new {
171
+ request[:result] = block_eval(request[:block_how], &request[:block])
172
+ success = true
173
+ },
174
+ :rescue => Proc.new { |exc|
175
+ show_exception(exc, "in request")
176
+ request[:exception] = exc
177
+ close_expect rescue nil
178
+ exception_caught = true
179
+ }
180
+ )
181
+ ensure
182
+ signal_request_done(request)
183
+ raise "RUBY BUG: No success and no exception caught: #{$ERROR_INFO.inspect}" unless success or exception_caught
157
184
  end
158
- request[:cv_mutex].synchronize { request[:cv].signal }
159
185
 
160
186
  # Execute the after_each_request hooks.
161
187
  execute_hooks(:after_each_request)
@@ -235,7 +261,32 @@ module ScripTTY
235
261
  output = ["Exception #{context || "in #{self}"}: #{exc} (#{exc.class.name})"]
236
262
  output += exc.backtrace.map { |line| " #{line}" }
237
263
  $stderr.puts output.join("\n")
238
- true # true means to re-raise the exception
264
+ end
265
+
266
+ def signal_request_done(request)
267
+ request[:cv_mutex].synchronize { request[:cv].signal }
268
+ end
269
+
270
+ # XXX - Workaround for JRuby bug.
271
+ #
272
+ # Apparently, if we do this:
273
+ #
274
+ # begin
275
+ # # some code here
276
+ # rescue Exception => exc
277
+ # # handle
278
+ # end
279
+ #
280
+ # Then other errors like SyntaxError and ArgumentError don't get caught
281
+ # when we do our block-passing-over-threads magic. However, if we
282
+ # enumerate a bunch of exception classes, it seems to work.
283
+ def wrap_in_exception_handler(options={})
284
+ begin
285
+ options[:body].call
286
+ rescue Exception, ScriptError, SystemStackError, StandardError => exc
287
+ options[:rescue].call(exc) if options[:rescue]
288
+ raise if options[:reraise]
289
+ end
239
290
  end
240
291
  end
241
292
  end
@@ -59,19 +59,20 @@ module ScripTTY
59
59
  RECOGNIZED_PROPERTIES = SINGLE_CHAR_PROPERTIES + TWO_TUPLE_PROPERTIES + %w( rectangle fields text )
60
60
 
61
61
  class <<self
62
- def parse(s, &block)
63
- new(s, &block).parse
62
+ def parse(s, filename=nil, lineno=nil, &block)
63
+ new(s, filename, lineno, &block).parse
64
64
  nil
65
65
  end
66
66
  protected :new # Users should not instantiate this object directly
67
67
  end
68
68
 
69
- def initialize(s, &block)
69
+ def initialize(s, filename=nil, lineno=nil, &block)
70
70
  raise ArgumentError.new("no block given") unless block
71
71
  @block = block
72
72
  @lines = preprocess(s).split("\n").map{|line| "#{line}\n"}
73
73
  @line = nil
74
- @lineno = 0
74
+ @filename = filename
75
+ @lineno = (lineno||1) - 1
75
76
  @state = :start
76
77
  end
77
78
 
@@ -529,7 +530,8 @@ module ScripTTY
529
530
 
530
531
  def parse_fail(message=nil, line=nil)
531
532
  line ||= @lineno
532
- raise ArgumentError.new("error:line #{line}: #{message || 'parse error'}")
533
+ f = @filename ? "#{@filename}:" : "line "
534
+ raise ArgumentError.new("error:#{f}#{line}: #{message || 'parse error'}")
533
535
  end
534
536
 
535
537
  # Pre-process an input string.
@@ -20,9 +20,9 @@ module ScripTTY
20
20
  class ScreenPattern
21
21
  class <<self
22
22
  # Parse a pattern file and return an array of ScreenPattern objects
23
- def parse(s)
23
+ def parse(s, filename=nil, lineno=nil)
24
24
  retval = []
25
- Parser.parse(s) do |spec|
25
+ Parser.parse(s, filename, lineno) do |spec|
26
26
  retval << new(spec[:name], spec[:properties])
27
27
  end
28
28
  retval
@@ -0,0 +1,76 @@
1
+ # = Tests for ScripTTY::RequestDispatcher
2
+ # Copyright (C) 2010 Infonium Inc.
3
+ #
4
+ # This file is part of ScripTTY.
5
+ #
6
+ # ScripTTY is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Lesser General Public License as published
8
+ # by the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # ScripTTY is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Lesser General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Lesser General Public License
17
+ # along with ScripTTY. If not, see <http://www.gnu.org/licenses/>.
18
+ require File.dirname(__FILE__) + "/test_helper.rb"
19
+ require 'scriptty/request_dispatcher'
20
+
21
+ class RequestDispatcherTest < Test::Unit::TestCase
22
+
23
+ if !defined?(Java)
24
+ # This test gets executed when JRuby is not detected
25
+ def test_dummy_no_jruby
26
+ raise LoadError.new("Cannot test ScripTTY::RequestDispatcher: Not running under JRuby")
27
+ end
28
+
29
+ else # defined?(Java)
30
+
31
+ def setup
32
+ @r = ScripTTY::RequestDispatcher.new
33
+ end
34
+
35
+ def teardown
36
+ @r.finish
37
+ end
38
+
39
+ def test_after_init
40
+ after_init_ran = false
41
+ @r.after_init { after_init_ran = true }
42
+ @r.start
43
+ sleep 0.2 # XXX - race condition
44
+ assert after_init_ran, "after_init hook should run"
45
+ end
46
+
47
+ def test_request
48
+ @r.start
49
+ assert_equal :success, @r.request { init_term "dg410"; :success }
50
+ end
51
+
52
+ def test_standard_exception_in_request
53
+ @r.instance_eval do
54
+ def show_exception(*args) end # Silence exceptions
55
+ end
56
+
57
+ @r.start
58
+ assert_raise ArgumentError do
59
+ @r.request { raise ArgumentError.new("foo") }
60
+ end
61
+ end
62
+
63
+ def test_base_exception_in_request
64
+ @r.instance_eval do
65
+ def show_exception(*args) end # Silence exceptions
66
+ end
67
+
68
+ @r.start
69
+ assert_raise SyntaxError do
70
+ @r.request { eval("*") }
71
+ end
72
+ end
73
+
74
+ end
75
+ end
76
+
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 1
7
- - 1
7
+ - 2
8
8
  - 0
9
- version: 1.1.0
9
+ version: 1.2.0
10
10
  platform: java
11
11
  authors:
12
12
  - Dwayne Litzenberger
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-05-13 00:00:00 -04:00
17
+ date: 2010-05-15 00:00:00 -04:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -119,6 +119,7 @@ files:
119
119
  - test/fsm_test.rb
120
120
  - test/multiline_buffer_test.rb
121
121
  - test/net/event_loop_test.rb
122
+ - test/request_dispatcher_test.rb
122
123
  - test/screen_pattern/generator_test.rb
123
124
  - test/screen_pattern/parser_test.rb
124
125
  - test/screen_pattern/parser_test/explicit_cursor_pattern.txt
@@ -172,6 +173,7 @@ test_files:
172
173
  - test/fsm_definition_parser_test.rb
173
174
  - test/fsm_test.rb
174
175
  - test/multiline_buffer_test.rb
176
+ - test/request_dispatcher_test.rb
175
177
  - test/test_helper.rb
176
178
  - test/apps/capture_app_test.rb
177
179
  - test/apps/transcript_parse_app_test.rb