scriptty 0.5.0-java

Sign up to get free protection for your applications and to get access to all the features.
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