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