scriptty 0.5.0-java
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitattributes +1 -0
- data/.gitignore +3 -0
- data/COPYING +674 -0
- data/COPYING.LESSER +165 -0
- data/README.rdoc +31 -0
- data/Rakefile +49 -0
- data/VERSION +1 -0
- data/bin/scriptty-capture +5 -0
- data/bin/scriptty-dump-screens +4 -0
- data/bin/scriptty-replay +5 -0
- data/bin/scriptty-term-test +4 -0
- data/bin/scriptty-transcript-parse +4 -0
- data/examples/captures/xterm-overlong-line-prompt.bin +9 -0
- data/examples/captures/xterm-vim-session.bin +262 -0
- data/examples/demo-capture.rb +19 -0
- data/examples/telnet-nego.rb +55 -0
- data/lib/scriptty/apps/capture_app/console.rb +104 -0
- data/lib/scriptty/apps/capture_app/password_prompt.rb +65 -0
- data/lib/scriptty/apps/capture_app.rb +213 -0
- data/lib/scriptty/apps/dump_screens_app.rb +166 -0
- data/lib/scriptty/apps/replay_app.rb +229 -0
- data/lib/scriptty/apps/term_test_app.rb +124 -0
- data/lib/scriptty/apps/transcript_parse_app.rb +143 -0
- data/lib/scriptty/cursor.rb +39 -0
- data/lib/scriptty/exception.rb +38 -0
- data/lib/scriptty/expect.rb +392 -0
- data/lib/scriptty/multiline_buffer.rb +192 -0
- data/lib/scriptty/net/event_loop.rb +610 -0
- data/lib/scriptty/screen_pattern/generator.rb +398 -0
- data/lib/scriptty/screen_pattern/parser.rb +558 -0
- data/lib/scriptty/screen_pattern.rb +104 -0
- data/lib/scriptty/term/dg410/dg410-client-escapes.txt +37 -0
- data/lib/scriptty/term/dg410/dg410-escapes.txt +82 -0
- data/lib/scriptty/term/dg410/parser.rb +162 -0
- data/lib/scriptty/term/dg410.rb +489 -0
- data/lib/scriptty/term/xterm/xterm-escapes.txt +73 -0
- data/lib/scriptty/term/xterm.rb +661 -0
- data/lib/scriptty/term.rb +40 -0
- data/lib/scriptty/util/fsm/definition_parser.rb +111 -0
- data/lib/scriptty/util/fsm/scriptty_fsm_definition.treetop +189 -0
- data/lib/scriptty/util/fsm.rb +177 -0
- data/lib/scriptty/util/transcript/reader.rb +96 -0
- data/lib/scriptty/util/transcript/writer.rb +111 -0
- data/test/apps/capture_app_test.rb +123 -0
- data/test/apps/transcript_parse_app_test.rb +118 -0
- data/test/cursor_test.rb +51 -0
- data/test/fsm_definition_parser_test.rb +220 -0
- data/test/fsm_test.rb +322 -0
- data/test/multiline_buffer_test.rb +275 -0
- data/test/net/event_loop_test.rb +402 -0
- data/test/screen_pattern/generator_test.rb +408 -0
- data/test/screen_pattern/parser_test/explicit_cursor_pattern.txt +14 -0
- data/test/screen_pattern/parser_test/explicit_fields.txt +22 -0
- data/test/screen_pattern/parser_test/multiple_patterns.txt +42 -0
- data/test/screen_pattern/parser_test/simple_pattern.txt +14 -0
- data/test/screen_pattern/parser_test/truncated_heredoc.txt +12 -0
- data/test/screen_pattern/parser_test/utf16bebom_pattern.bin +0 -0
- data/test/screen_pattern/parser_test/utf16lebom_pattern.bin +0 -0
- data/test/screen_pattern/parser_test/utf8_pattern.bin +14 -0
- data/test/screen_pattern/parser_test/utf8_unix_pattern.bin +14 -0
- data/test/screen_pattern/parser_test/utf8bom_pattern.bin +14 -0
- data/test/screen_pattern/parser_test.rb +266 -0
- data/test/term/dg410/parser_test.rb +139 -0
- data/test/term/xterm_test.rb +327 -0
- data/test/test_helper.rb +3 -0
- data/test/util/transcript/reader_test.rb +131 -0
- data/test/util/transcript/writer_test.rb +126 -0
- data/test.watchr +29 -0
- 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
|