scriptty 0.5.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.
Files changed (69) hide show
  1. data/.gitattributes +1 -0
  2. data/.gitignore +3 -0
  3. data/COPYING +674 -0
  4. data/COPYING.LESSER +165 -0
  5. data/README.rdoc +31 -0
  6. data/Rakefile +49 -0
  7. data/VERSION +1 -0
  8. data/bin/scriptty-capture +5 -0
  9. data/bin/scriptty-dump-screens +4 -0
  10. data/bin/scriptty-replay +5 -0
  11. data/bin/scriptty-term-test +4 -0
  12. data/bin/scriptty-transcript-parse +4 -0
  13. data/examples/captures/xterm-overlong-line-prompt.bin +9 -0
  14. data/examples/captures/xterm-vim-session.bin +262 -0
  15. data/examples/demo-capture.rb +19 -0
  16. data/examples/telnet-nego.rb +55 -0
  17. data/lib/scriptty/apps/capture_app/console.rb +104 -0
  18. data/lib/scriptty/apps/capture_app/password_prompt.rb +65 -0
  19. data/lib/scriptty/apps/capture_app.rb +213 -0
  20. data/lib/scriptty/apps/dump_screens_app.rb +166 -0
  21. data/lib/scriptty/apps/replay_app.rb +229 -0
  22. data/lib/scriptty/apps/term_test_app.rb +124 -0
  23. data/lib/scriptty/apps/transcript_parse_app.rb +143 -0
  24. data/lib/scriptty/cursor.rb +39 -0
  25. data/lib/scriptty/exception.rb +38 -0
  26. data/lib/scriptty/expect.rb +392 -0
  27. data/lib/scriptty/multiline_buffer.rb +192 -0
  28. data/lib/scriptty/net/event_loop.rb +610 -0
  29. data/lib/scriptty/screen_pattern/generator.rb +398 -0
  30. data/lib/scriptty/screen_pattern/parser.rb +558 -0
  31. data/lib/scriptty/screen_pattern.rb +104 -0
  32. data/lib/scriptty/term/dg410/dg410-client-escapes.txt +37 -0
  33. data/lib/scriptty/term/dg410/dg410-escapes.txt +82 -0
  34. data/lib/scriptty/term/dg410/parser.rb +162 -0
  35. data/lib/scriptty/term/dg410.rb +489 -0
  36. data/lib/scriptty/term/xterm/xterm-escapes.txt +73 -0
  37. data/lib/scriptty/term/xterm.rb +661 -0
  38. data/lib/scriptty/term.rb +40 -0
  39. data/lib/scriptty/util/fsm/definition_parser.rb +111 -0
  40. data/lib/scriptty/util/fsm/scriptty_fsm_definition.treetop +189 -0
  41. data/lib/scriptty/util/fsm.rb +177 -0
  42. data/lib/scriptty/util/transcript/reader.rb +96 -0
  43. data/lib/scriptty/util/transcript/writer.rb +111 -0
  44. data/test/apps/capture_app_test.rb +123 -0
  45. data/test/apps/transcript_parse_app_test.rb +118 -0
  46. data/test/cursor_test.rb +51 -0
  47. data/test/fsm_definition_parser_test.rb +220 -0
  48. data/test/fsm_test.rb +322 -0
  49. data/test/multiline_buffer_test.rb +275 -0
  50. data/test/net/event_loop_test.rb +402 -0
  51. data/test/screen_pattern/generator_test.rb +408 -0
  52. data/test/screen_pattern/parser_test/explicit_cursor_pattern.txt +14 -0
  53. data/test/screen_pattern/parser_test/explicit_fields.txt +22 -0
  54. data/test/screen_pattern/parser_test/multiple_patterns.txt +42 -0
  55. data/test/screen_pattern/parser_test/simple_pattern.txt +14 -0
  56. data/test/screen_pattern/parser_test/truncated_heredoc.txt +12 -0
  57. data/test/screen_pattern/parser_test/utf16bebom_pattern.bin +0 -0
  58. data/test/screen_pattern/parser_test/utf16lebom_pattern.bin +0 -0
  59. data/test/screen_pattern/parser_test/utf8_pattern.bin +14 -0
  60. data/test/screen_pattern/parser_test/utf8_unix_pattern.bin +14 -0
  61. data/test/screen_pattern/parser_test/utf8bom_pattern.bin +14 -0
  62. data/test/screen_pattern/parser_test.rb +266 -0
  63. data/test/term/dg410/parser_test.rb +139 -0
  64. data/test/term/xterm_test.rb +327 -0
  65. data/test/test_helper.rb +3 -0
  66. data/test/util/transcript/reader_test.rb +131 -0
  67. data/test/util/transcript/writer_test.rb +126 -0
  68. data/test.watchr +29 -0
  69. metadata +175 -0
@@ -0,0 +1,266 @@
1
+ # = Tests for ScripTTY::ScreenPattern::Parser
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
+
19
+ require File.dirname(__FILE__) + "/../test_helper.rb"
20
+ require 'scriptty/screen_pattern/parser'
21
+
22
+ class ParserTest < Test::Unit::TestCase
23
+ # Test a simple pattern
24
+ def test_simple_pattern
25
+ result = []
26
+ ScripTTY::ScreenPattern::Parser.parse(read_file("simple_pattern.txt")) do |screen|
27
+ result << screen
28
+ end
29
+ offset = [3,4]
30
+ expected = [{
31
+ :name => "simple_pattern",
32
+ :properties => {
33
+ "position" => [0,0],
34
+ "size" => [4,5],
35
+ "cursor_pos" => [0,0],
36
+ "matches" => [
37
+ [[3,2], "X"],
38
+ ],
39
+ "fields" => {
40
+ "field1" => [0,2..4],
41
+ "apple" => [1, 0..0],
42
+ "orange" => [1, 2..2],
43
+ "banana" => [1, 4..4],
44
+ "foo" => [2,0..1],
45
+ "bar" => [3,3..4],
46
+ },
47
+ },
48
+ }]
49
+ assert_equal add_pos(offset, expected), result
50
+ end
51
+
52
+ def test_explicit_cursor_position
53
+ result = []
54
+ ScripTTY::ScreenPattern::Parser.parse(read_file("explicit_cursor_pattern.txt")) do |screen|
55
+ result << screen
56
+ end
57
+ offset = [3,4]
58
+ expected = [{
59
+ :name => "simple_pattern",
60
+ :properties => {
61
+ "position" => [0,0],
62
+ "size" => [4,5],
63
+ "cursor_pos" => [1,1],
64
+ "fields" => {
65
+ "field1" => [0,2..4],
66
+ "apple" => [1, 0..0],
67
+ "orange" => [1, 2..2],
68
+ "banana" => [1, 4..4],
69
+ "foo" => [2,0..1],
70
+ "bar" => [3,3..4],
71
+ },
72
+ },
73
+ }]
74
+ assert_equal add_pos(offset, expected), result
75
+ end
76
+
77
+ def test_explicit_fields
78
+ result = []
79
+ ScripTTY::ScreenPattern::Parser.parse(read_file("explicit_fields.txt")) do |screen|
80
+ result << screen
81
+ end
82
+ offset = [3,4]
83
+ expected = [{
84
+ :name => "explicit_fields",
85
+ :properties => {
86
+ "position" => [0,0],
87
+ "size" => [4,5],
88
+ "cursor_pos" => [0,0],
89
+ "fields" => {
90
+ "field1" => [0,2..4],
91
+ "apple" => [1, 0..0],
92
+ "orange" => [1, 2..2],
93
+ "banana" => [1, 4..4],
94
+ "foo" => [2,0..1],
95
+ "bar" => [3,3..4],
96
+ },
97
+ },
98
+ }]
99
+ assert_equal add_pos(offset, expected), result
100
+ end
101
+
102
+ # Multiple patterns can be specified in a single file
103
+ def test_multiple_patterns
104
+ result = []
105
+ ScripTTY::ScreenPattern::Parser.parse(read_file("multiple_patterns.txt")) do |screen|
106
+ result << screen
107
+ end
108
+ expected = [
109
+ add_pos([3,4], {
110
+ :name => "simple_pattern_1",
111
+ :properties => { # NB: [3,4] added to these properties
112
+ "position" => [0,0],
113
+ "size" => [4,5],
114
+ "cursor_pos" => [0,0],
115
+ "fields" => {
116
+ "field1" => [0,2..4],
117
+ "apple" => [1, 0..0],
118
+ "orange" => [1, 2..2],
119
+ "banana" => [1, 4..4],
120
+ "foo" => [2,0..1],
121
+ "bar" => [3,3..4],
122
+ },
123
+ },
124
+ }),
125
+ {
126
+ :name => "simple_pattern_2",
127
+ :properties => {
128
+ "position" => [0,0],
129
+ "size" => [4,5],
130
+ "cursor_pos" => [0,0],
131
+ "matches" => [
132
+ [[0,1], ":"],
133
+ [[2,0], "Hello"],
134
+ [[3,0], "World"],
135
+ ],
136
+ "fields" => {
137
+ "field1" => [0, 2..4],
138
+ },
139
+ },
140
+ },
141
+ {
142
+ :name => "simple_pattern_3",
143
+ :properties => {
144
+ "position" => [0,0],
145
+ "size" => [4,5],
146
+ "cursor_pos" => [0,0],
147
+ "matches" => [
148
+ [[0,1], ":"],
149
+ [[2,0], "Hello"],
150
+ [[3,0], "World"],
151
+ ],
152
+ "fields" => {
153
+ "field1" => [0, 2..4],
154
+ },
155
+ },
156
+ },
157
+ ]
158
+ assert_equal expected.length, result.length, "lengths do not match"
159
+ expected.zip(result).each do |e, r|
160
+ assert_equal e, r
161
+ end
162
+ end
163
+
164
+ # A here-document that's truncated should result in a parse error.
165
+ def test_truncated_heredoc
166
+ result = []
167
+ pattern = read_file("truncated_heredoc.txt")
168
+ e = nil
169
+ assert_raise(ArgumentError, "truncated here-document should result in parse error") do
170
+ begin
171
+ ScripTTY::ScreenPattern::Parser.parse(pattern) do |screen|
172
+ result << screen
173
+ end
174
+ rescue ArgumentError => e # save exception for assertion below
175
+ raise
176
+ end
177
+ end
178
+ assert_match /^error:line 12: expected: "END", got EOF/, e.message
179
+ end
180
+
181
+ # UTF-16 and UTF-8 should parse correctly
182
+ def test_unicode
183
+ expected = [
184
+ add_pos([3,4], {
185
+ :name => "unicode_pattern",
186
+ :properties => {
187
+ "position" => [0,0],
188
+ "size" => [4,5],
189
+ "cursor_pos" => [0,0],
190
+ "fields" => {
191
+ "field1" => [0,2..4],
192
+ "apple" => [1, 0..0],
193
+ "orange" => [1, 2..2],
194
+ "banana" => [1, 4..4],
195
+ "foo" => [2,0..1],
196
+ "bar" => [3,3..4],
197
+ },
198
+ },
199
+ }),
200
+ ]
201
+ for filename in %w( utf16bebom_pattern.bin utf16lebom_pattern.bin utf8_pattern.bin utf8_unix_pattern.bin utf8bom_pattern.bin )
202
+ result = []
203
+ assert_nothing_raised("#{filename} should parse ok") do
204
+ ScripTTY::ScreenPattern::Parser.parse(read_file(filename)) do |screen|
205
+ result << screen
206
+ end
207
+ end
208
+ assert_equal expected, result, "#{filename} should parse correctly"
209
+ end
210
+ end
211
+
212
+ # Unicode NFC normalization should be performed. This avoids user confusion if they enter two different representations of the same character.
213
+ def test_nfd_to_nfc_normalization
214
+ expected = [{
215
+ :name => "test",
216
+ :properties => {
217
+ "position" => [0,0],
218
+ "size" => [1,2],
219
+ "cursor_pos" => [0,1],
220
+ }
221
+ }]
222
+ input = <<EOF
223
+ [test]
224
+ char_cursor: "c\xcc\xa7" # ASCII "c" followed by U+0327 COMBINING CEDILLA
225
+ char_ignore: "."
226
+ text: <<END
227
+ +--+
228
+ |.\xc3\xa7| # U+00E7 LATIN SMALL LETTER C WITH CEDILLA
229
+ +--+
230
+ END
231
+ EOF
232
+ result = []
233
+ ScripTTY::ScreenPattern::Parser.parse(input) do |screen|
234
+ result << screen
235
+ end
236
+ assert_equal expected, result, "NFC unicode normalization should work correctly"
237
+ end
238
+
239
+ private
240
+
241
+ def read_file(basename)
242
+ File.read(File.join(File.dirname(__FILE__), "parser_test", basename))
243
+ end
244
+
245
+ def add_pos(offset, arg)
246
+ if arg.is_a?(Array) and arg[0].is_a?(Integer) and arg[1].is_a?(Integer)
247
+ [offset[0]+arg[0], offset[1]+arg[1]]
248
+ elsif arg.is_a?(Array) and arg[0].is_a?(Integer) and arg[1].is_a?(Range)
249
+ [offset[0]+arg[0], offset[1]+arg[1].first..offset[1]+arg[1].last]
250
+ elsif arg.is_a?(Array)
251
+ arg.map{|a| add_pos(offset, a)}
252
+ elsif arg.is_a?(Hash)
253
+ retval = {}
254
+ arg.each_pair do |k,v|
255
+ if k == "size"
256
+ retval[k] = v
257
+ else
258
+ retval[k] = add_pos(offset, v)
259
+ end
260
+ end
261
+ retval
262
+ else
263
+ arg # raise ArgumentError.new("Don't know how to handle #{arg.inspect}")
264
+ end
265
+ end
266
+ end
@@ -0,0 +1,139 @@
1
+ # = Tests for ScripTTY::Term::DG410::Parser
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
+
19
+ require File.dirname(__FILE__) + "/../../test_helper.rb"
20
+ require 'scriptty/term'
21
+
22
+ class ParserTest < Test::Unit::TestCase
23
+ def setup
24
+ # Tests should pass with $KCODE = "UTF8"
25
+ $KCODE = "UTF8"
26
+ end
27
+
28
+ def test_basic
29
+ expected_result = [
30
+ [:t_blink_enable, "\003"],
31
+ [:t_blink_disable, "\004"],
32
+ [:t_proprietary_ack, "\006"],
33
+ [:t_bell, "\007"],
34
+ [:t_window_home, "\010"],
35
+ [:t_new_line, "\n"],
36
+ [:t_erase_end_of_line, "\013"],
37
+ [:t_erase_window, "\014"],
38
+ [:t_carriage_return, "\015"],
39
+ [:t_blink_on, "\016"],
40
+ [:t_blink_off, "\017"],
41
+ [:t_write_window_address, "\020\000\000"],
42
+ [:t_write_window_address, "\020\006\177"],
43
+ [:t_print_window, "\021"],
44
+ [:t_roll_enable, "\022"],
45
+ [:t_roll_disable, "\023"],
46
+ [:t_underscore_on, "\024"],
47
+ [:t_underscore_off, "\025"],
48
+ [:t_cursor_up, "\027"],
49
+ [:t_cursor_right, "\30"],
50
+ [:t_cursor_left, "\031"],
51
+ [:t_cursor_down, "\032"],
52
+ [:t_osc_m, "\033]0M"],
53
+ [:t_osc_m, "\033]1M"],
54
+ [:t_osc_k, "\033]0K"],
55
+ [:t_osc_k, "\033]1K"],
56
+ [:t_dim_on, "\034"],
57
+ [:t_dim_off, "\035"],
58
+ [:t_reverse_video_on, "\036D"],
59
+ [:t_reverse_video_off, "\036E"],
60
+ [:t_reset, "\036FA"],
61
+ [:t_erase_unprotected, "\036FF"],
62
+ # [:t_delete_line, "\036FI"],
63
+ # [:t_set_cursor_type, "\036FQx"],
64
+ # [:t_delete_character, "\036K"],
65
+ [:t_proprietary_escape, "\036~xx\000"],
66
+ [:t_proprietary_escape, "\036~xx\001x"],
67
+ [:t_proprietary_escape, "\036~xx\002xx"],
68
+ [:t_proprietary_escape, "\036~xx\003xxx"],
69
+ # [:t_telnet_will, "\377\373\001"],
70
+ # [:t_telnet_wont, "\377\374\001"],
71
+ # [:t_telnet_do, "\377\375\001"],
72
+ # [:t_telnet_dont, "\377\376\001"],
73
+ [:t_printable, "h"],
74
+ [:t_printable, "e"],
75
+ [:t_printable, "l"],
76
+ [:t_printable, "l"],
77
+ [:t_printable, "o"],
78
+ ]
79
+ result = []
80
+ parser = ScripTTY::Term.class_by_name("dg410").parser_class.new :callback => Proc.new { |event, fsm|
81
+ result << [event, fsm.input_sequence.join]
82
+ }
83
+ # Mash the inputs together, then check that the parser splits them up properly.
84
+ input_string = expected_result.inject(""){|r, e| r += e[1]}
85
+ parser.feed_bytes(input_string)
86
+ assert_equal expected_result, result
87
+ end
88
+
89
+ def test_on_unknown_sequence_block
90
+ expected_result = [
91
+ [:t_erase_unprotected, "\036FF"],
92
+ [:t_printable, "o"],
93
+ [:UNKNOWN, "\x85"],
94
+ [:t_printable, "x"],
95
+ ]
96
+ result = []
97
+ parser = ScripTTY::Term.class_by_name("dg410").parser_class.new :callback => Proc.new { |event, fsm|
98
+ result << [event, fsm.input_sequence.join]
99
+ }
100
+ parser.on_unknown_sequence { |seq|
101
+ result << [:UNKNOWN, seq]
102
+ }
103
+ input_string = expected_result.inject(""){|r, e| r += e[1]}
104
+ parser.feed_bytes(input_string)
105
+ assert_equal expected_result, result
106
+ end
107
+
108
+ def test_on_unknown_sequence_ignore
109
+ expected_result = [
110
+ [:t_erase_unprotected, "\036FF"],
111
+ [:t_printable, "o"],
112
+ [:UNKNOWN, "\x80"],
113
+ [:t_printable, "x"],
114
+ ]
115
+ result = []
116
+ parser = ScripTTY::Term.class_by_name("dg410").parser_class.new :callback => Proc.new { |event, fsm|
117
+ result << [event, fsm.input_sequence.join]
118
+ }
119
+ parser.on_unknown_sequence :ignore
120
+ input_string = expected_result.inject(""){|r, e| r += e[1]}
121
+ parser.feed_bytes(input_string)
122
+ assert_equal expected_result.reject{|e| e[0] == :UNKNOWN}, result
123
+ end
124
+
125
+ def test_on_unknown_sequence_error
126
+ result = []
127
+ parser = ScripTTY::Term.class_by_name("dg410").parser_class.new :callback => Proc.new { |event, fsm|
128
+ result << [event, fsm.input_sequence.join]
129
+ }
130
+ # First iteration: test that :error is the default
131
+ # Second iteration: test that :error works when explicitly specified
132
+ 2.times do
133
+ assert_raises ScripTTY::Util::FSM::NoMatch do
134
+ parser.feed_bytes("\x80")
135
+ end
136
+ parser.on_unknown_sequence :error
137
+ end
138
+ end
139
+ end