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,327 @@
|
|
1
|
+
# = Tests for ScripTTY::Term::XTerm
|
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/xterm'
|
21
|
+
|
22
|
+
class XtermTest < Test::Unit::TestCase
|
23
|
+
|
24
|
+
def test_initial_cursor_position
|
25
|
+
s = ScripTTY::Term::XTerm.new(5, 10)
|
26
|
+
assert_equal [0,0], s.cursor_pos
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_width_height
|
30
|
+
s = ScripTTY::Term::XTerm.new(5, 10)
|
31
|
+
assert_equal 10, s.width
|
32
|
+
assert_equal 5, s.height
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_unknown_sequence_raises_nomatch_by_default
|
36
|
+
before = [ "aaaaaaaaaa",
|
37
|
+
"bbbbbbbbbb",
|
38
|
+
"cccccccccc",
|
39
|
+
"dddddddddd",
|
40
|
+
"eeeeeeeeee" ]
|
41
|
+
|
42
|
+
after = [ "FOOaaaaaaa",
|
43
|
+
"bbbbbbbbbb",
|
44
|
+
"cccccccccc",
|
45
|
+
"dddddddddd",
|
46
|
+
"eeeeeeeeee" ]
|
47
|
+
|
48
|
+
screen_modify_test(before, after) do |s|
|
49
|
+
assert_raise ScripTTY::Util::FSM::NoMatch do
|
50
|
+
s.feed_bytes("\e[\e") # bogus escape sequence ESC [ ESC
|
51
|
+
end
|
52
|
+
s.feed_bytes("FOO")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_unknown_sequence_ignore
|
57
|
+
before = [ "aaaaaaaaaa",
|
58
|
+
"bbbbbbbbbb",
|
59
|
+
"cccccccccc",
|
60
|
+
"dddddddddd",
|
61
|
+
"eeeeeeeeee" ]
|
62
|
+
|
63
|
+
after = [ "FOOaaaaaaa",
|
64
|
+
"bbbbbbbbbb",
|
65
|
+
"cccccccccc",
|
66
|
+
"dddddddddd",
|
67
|
+
"eeeeeeeeee" ]
|
68
|
+
|
69
|
+
screen_modify_test(before, after) do |s|
|
70
|
+
s.on_unknown_sequence :ignore
|
71
|
+
s.feed_bytes("\e[\eFOO") # bogus escape sequence ESC [ ESC
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_unknown_sequence_proc
|
76
|
+
before = [ "aaaaaaaaaa",
|
77
|
+
"bbbbbbbbbb",
|
78
|
+
"cccccccccc",
|
79
|
+
"dddddddddd",
|
80
|
+
"eeeeeeeeee" ]
|
81
|
+
|
82
|
+
after = [ "[BOGO]FOOa",
|
83
|
+
"bbbbbbbbbb",
|
84
|
+
"cccccccccc",
|
85
|
+
"dddddddddd",
|
86
|
+
"eeeeeeeeee" ]
|
87
|
+
|
88
|
+
screen_modify_test(before, after) do |s|
|
89
|
+
s.on_unknown_sequence do |seq|
|
90
|
+
assert_equal "\e[\e", seq
|
91
|
+
s.feed_bytes "[BOGO]" # the state machine should already be reset, so we should be able to feed alternative bytes here.
|
92
|
+
end
|
93
|
+
s.feed_bytes("\e[\eFOO") # bogus escape sequence ESC [ ESC
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_cursor_position
|
98
|
+
s = ScripTTY::Term::XTerm.new(5, 10)
|
99
|
+
|
100
|
+
s.cursor_pos = [4,8]
|
101
|
+
s.feed_bytes("\e[H")
|
102
|
+
assert_equal [0,0], s.cursor_pos
|
103
|
+
|
104
|
+
s.cursor_pos = [4,8]
|
105
|
+
s.feed_bytes("\e[4H")
|
106
|
+
assert_equal [3,0], s.cursor_pos
|
107
|
+
|
108
|
+
s.cursor_pos = [4,8]
|
109
|
+
s.feed_bytes("\e[;4H")
|
110
|
+
assert_equal [0,3], s.cursor_pos
|
111
|
+
|
112
|
+
s.cursor_pos = [4,8]
|
113
|
+
s.feed_bytes("\e[0;0H")
|
114
|
+
assert_equal [0,0], s.cursor_pos
|
115
|
+
|
116
|
+
s.cursor_pos = [4,8]
|
117
|
+
s.feed_bytes("\e[1;1H")
|
118
|
+
assert_equal [0,0], s.cursor_pos
|
119
|
+
|
120
|
+
s.cursor_pos = [4,8]
|
121
|
+
s.feed_bytes("\e[4;5H")
|
122
|
+
assert_equal [3,4], s.cursor_pos
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_cursor_up
|
126
|
+
{"" => 1, "0" => 1, "1" => 1, "2" => 2, "3" => 3}.each_pair do |p,n|
|
127
|
+
s = ScripTTY::Term::XTerm.new(5, 10)
|
128
|
+
col = 1
|
129
|
+
(n..s.height-1).to_a.reverse.each do |row|
|
130
|
+
s.cursor_pos = [row,col]
|
131
|
+
s.feed_bytes("\e[#{p}A")
|
132
|
+
assert_equal [row-n,col], s.cursor_pos, "should move cursor from row #{row} to row #{row-n}"
|
133
|
+
end
|
134
|
+
|
135
|
+
assert_equal [0,col], s.cursor_pos, "sanity check"
|
136
|
+
s.feed_bytes("\e[#{p}A")
|
137
|
+
assert_equal [0,col], s.cursor_pos, "cursor should not move past screen edge"
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def test_cursor_down
|
142
|
+
{"" => 1, "0" => 1, "1" => 1, "2" => 2, "3" => 3}.each_pair do |p,n|
|
143
|
+
s = ScripTTY::Term::XTerm.new(5, 10)
|
144
|
+
col = 1
|
145
|
+
(0..s.height-1-n).each do |row|
|
146
|
+
s.cursor_pos = [row,col]
|
147
|
+
s.feed_bytes("\e[#{p}B")
|
148
|
+
assert_equal [row+n,col], s.cursor_pos, "ESC[#{p}B should move cursor from row #{row} to row #{row+n}"
|
149
|
+
end
|
150
|
+
|
151
|
+
assert_equal [s.height-1,col], s.cursor_pos, "sanity check"
|
152
|
+
s.feed_bytes("\e[#{p}B")
|
153
|
+
assert_equal [s.height-1,col], s.cursor_pos, "cursor should not move past screen edge"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def test_cursor_right
|
158
|
+
{"" => 1, "0" => 1, "1" => 1, "2" => 2, "3" => 3}.each_pair do |p,n|
|
159
|
+
s = ScripTTY::Term::XTerm.new(5, 10)
|
160
|
+
row = 1
|
161
|
+
(0..s.width-1-n).each do |col|
|
162
|
+
s.cursor_pos = [row,col]
|
163
|
+
s.feed_bytes("\e[#{p}C")
|
164
|
+
assert_equal [row,col+n], s.cursor_pos, "ESC[#{p}C should move cursor from col #{col} to col #{col+n}"
|
165
|
+
end
|
166
|
+
|
167
|
+
assert_equal [row,s.width-1], s.cursor_pos, "sanity check"
|
168
|
+
s.feed_bytes("\e[#{p}C")
|
169
|
+
assert_equal [row,s.width-1], s.cursor_pos, "cursor should not move past screen edge"
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def test_cursor_left
|
174
|
+
{"" => 1, "0" => 1, "1" => 1, "2" => 2, "3" => 3}.each_pair do |p,n|
|
175
|
+
s = ScripTTY::Term::XTerm.new(5, 10)
|
176
|
+
row = 1
|
177
|
+
(n..s.width-1).to_a.reverse.each do |col|
|
178
|
+
s.cursor_pos = [row,col]
|
179
|
+
s.feed_bytes("\e[#{p}D")
|
180
|
+
assert_equal [row,col-n], s.cursor_pos, "ESC[#{p}D should move cursor from col #{col} to col #{col-n}"
|
181
|
+
end
|
182
|
+
|
183
|
+
assert_equal [row,0], s.cursor_pos, "sanity check"
|
184
|
+
s.feed_bytes("\e[#{p}D")
|
185
|
+
assert_equal [row,0], s.cursor_pos, "cursor should not move past screen edge"
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
def test_new_line
|
190
|
+
s = ScripTTY::Term::XTerm.new(5, 10)
|
191
|
+
|
192
|
+
s.cursor_pos = [0,4]
|
193
|
+
s.feed_bytes("\n\n")
|
194
|
+
assert_equal [2,0], s.cursor_pos
|
195
|
+
end
|
196
|
+
|
197
|
+
def test_carriage_return
|
198
|
+
s = ScripTTY::Term::XTerm.new(5, 10)
|
199
|
+
|
200
|
+
s.cursor_pos = [0,4]
|
201
|
+
s.feed_bytes("\r\r")
|
202
|
+
assert_equal [0,0], s.cursor_pos
|
203
|
+
end
|
204
|
+
|
205
|
+
def test_restore_cursor_never_saved
|
206
|
+
s = ScripTTY::Term::XTerm.new(5, 10)
|
207
|
+
s.cursor_pos = [2, 4]
|
208
|
+
s.feed_bytes("\e[u") # ANSI restore cursor
|
209
|
+
assert_equal [0, 0], s.cursor_pos, "ANSI restore cursor should default to home position"
|
210
|
+
|
211
|
+
s.cursor_pos = [2, 4]
|
212
|
+
s.feed_bytes("\e8") # DEC restore cursor
|
213
|
+
assert_equal [0, 0], s.cursor_pos, "DEC restore cursor should default to home position"
|
214
|
+
end
|
215
|
+
|
216
|
+
def test_save_cursor_restore_cursor
|
217
|
+
s = ScripTTY::Term::XTerm.new(5, 10)
|
218
|
+
s.cursor_pos = [2, 4]
|
219
|
+
s.feed_bytes("\e[s") # ANSI save cursor
|
220
|
+
|
221
|
+
s.cursor_pos = [0, 0]
|
222
|
+
s.feed_bytes("\e[u") # ANSI restore cursor
|
223
|
+
assert_equal [2, 4], s.cursor_pos, "ANSI restore cursor"
|
224
|
+
|
225
|
+
s.cursor_pos = [1, 3]
|
226
|
+
s.feed_bytes("\e7") # DEC save cursor
|
227
|
+
|
228
|
+
s.cursor_pos = [0, 0]
|
229
|
+
s.feed_bytes("\e8") # DEC restore cursor
|
230
|
+
assert_equal [1, 3], s.cursor_pos, "DEC restore cursor"
|
231
|
+
end
|
232
|
+
|
233
|
+
def test_scroll_up
|
234
|
+
before = [ "aaaaaaaaaa",
|
235
|
+
"bbbbbbbbbb",
|
236
|
+
"cccccccccc",
|
237
|
+
"dddddddddd",
|
238
|
+
"eeeeeeeeee" ]
|
239
|
+
|
240
|
+
after = [ "bbbbbbbbbb",
|
241
|
+
"cccccccccc",
|
242
|
+
"dddddddddd",
|
243
|
+
"eeeeeeeeee",
|
244
|
+
" " ]
|
245
|
+
|
246
|
+
screen_modify_test(before, after, "scroll up on newline") do |s|
|
247
|
+
s.cursor_pos = [4,0]
|
248
|
+
s.feed_bytes("\n")
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
|
253
|
+
def test_scroll_up_with_scrolling_region
|
254
|
+
before = [ "aaaaaaaaaa",
|
255
|
+
"bbbbbbbbbb",
|
256
|
+
"cccccccccc",
|
257
|
+
"dddddddddd",
|
258
|
+
"eeeeeeeeee" ]
|
259
|
+
|
260
|
+
after = [ "aaaaaaaaaa",
|
261
|
+
"cccccccccc",
|
262
|
+
"dddddddddd",
|
263
|
+
" ",
|
264
|
+
"eeeeeeeeee" ]
|
265
|
+
|
266
|
+
screen_modify_test(before, after) do |s|
|
267
|
+
s.cursor_pos = [3,0]
|
268
|
+
s.feed_bytes("\e[2;4r") # set scrolling region
|
269
|
+
s.feed_bytes("\n")
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
def test_printable
|
274
|
+
before = [" "*10]*5
|
275
|
+
after = [ "Hello! ",
|
276
|
+
" ",
|
277
|
+
" ",
|
278
|
+
" ",
|
279
|
+
" " ]
|
280
|
+
|
281
|
+
screen_modify_test(before, after) do |s|
|
282
|
+
s.feed_bytes("Hello!")
|
283
|
+
assert_equal [0,6], s.cursor_pos
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
def test_carriage_return
|
288
|
+
before = [" "*10]*5
|
289
|
+
after = [ "world! ",
|
290
|
+
" ",
|
291
|
+
" ",
|
292
|
+
" ",
|
293
|
+
" " ]
|
294
|
+
|
295
|
+
screen_modify_test(before, after) do |s|
|
296
|
+
s.feed_bytes("hello!\rworld")
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
# Test line_feed (no wrapping)
|
301
|
+
def test_new_line
|
302
|
+
before = [" "*10]*5
|
303
|
+
after = [ "hello ",
|
304
|
+
"world ",
|
305
|
+
" ",
|
306
|
+
" ",
|
307
|
+
" " ]
|
308
|
+
screen_modify_test(before, after) do |s|
|
309
|
+
s.feed_bytes("hello\nworld")
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
private
|
314
|
+
|
315
|
+
def screen_modify_test(start_with, expected, message=nil)
|
316
|
+
raise "no block given" unless block_given?
|
317
|
+
|
318
|
+
s = ScripTTY::Term::XTerm.new(start_with.length, start_with[0].length)
|
319
|
+
s.text = start_with
|
320
|
+
|
321
|
+
# Do the operation
|
322
|
+
yield s
|
323
|
+
|
324
|
+
# Compare
|
325
|
+
assert_equal expected, s.text, message
|
326
|
+
end
|
327
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
# = Tests for ScripTTY::Util::Transcript::Reader
|
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/util/transcript/reader'
|
21
|
+
|
22
|
+
class TranscriptReaderTest < Test::Unit::TestCase
|
23
|
+
def test_basic
|
24
|
+
input_lines = <<-'EOF'.split("\n").map{|line| line.strip}
|
25
|
+
[0.000] * "Informational message" "with argument" "\377"
|
26
|
+
[0.000] Copen "10.0.0.5" "55555"
|
27
|
+
[0.000] Sopen "10.0.0.1" "1234"
|
28
|
+
[0.001] C "alice\211\0010"
|
29
|
+
[0.001] S "bob\042"
|
30
|
+
[2.500] Cp "foo" "arg"
|
31
|
+
[2.900] Sp "." "arg"
|
32
|
+
[3.000] Sp "ESC" "\033"
|
33
|
+
[4.000] Cx "disconnect"
|
34
|
+
[5.000] Sx "disconnect"
|
35
|
+
[5.000] Sx
|
36
|
+
[5] Cx
|
37
|
+
EOF
|
38
|
+
expected = [
|
39
|
+
[0.0, :info, ["Informational message", "with argument", "\xff"]],
|
40
|
+
[0.0, :client_open, ["10.0.0.5", 55555]],
|
41
|
+
[0.0, :server_open, ["10.0.0.1", 1234]],
|
42
|
+
[0.001, :from_client, ["alice\x89\x01\x30"]],
|
43
|
+
[0.001, :from_server, ["bob\x22"]],
|
44
|
+
[2.5, :client_parsed, ["foo", "arg"]],
|
45
|
+
[2.9, :server_parsed, [".", "arg"]],
|
46
|
+
[3.0, :server_parsed, ["ESC", "\x1b"]],
|
47
|
+
[4.0, :client_close, ["disconnect"]],
|
48
|
+
[5.0, :server_close, ["disconnect"]],
|
49
|
+
[5.0, :server_close, []],
|
50
|
+
[5.0, :client_close, []],
|
51
|
+
]
|
52
|
+
reader = ScripTTY::Util::Transcript::Reader.new
|
53
|
+
actual = input_lines.map{|line| reader.parse_line(line) }
|
54
|
+
assert_equal expected, actual
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_bad_inputs
|
58
|
+
# Each line of the following must fail to parse
|
59
|
+
input_lines = <<-'EOF'.split("\n").map{|line| line.strip}
|
60
|
+
[0.000] * "Lone backslash" "\"
|
61
|
+
[0.000] * "Bad octal value" "\400"
|
62
|
+
[0.100] * "No quotes" foo
|
63
|
+
[0.200] $ "Unknown type"
|
64
|
+
[0.200] Copen "bad port" "10abc"
|
65
|
+
[0.200] Sopen "bad port" "10abc"
|
66
|
+
[0.300] * "Non-printableASCII characters" "Café"
|
67
|
+
[0.400] Cx "too much whitespace"
|
68
|
+
* "No timestamp"
|
69
|
+
[] * "Empty timestamp"
|
70
|
+
[5.5.5] "multiple decimals in timestamp"
|
71
|
+
EOF
|
72
|
+
reader = ScripTTY::Util::Transcript::Reader.new
|
73
|
+
input_lines.each do |line|
|
74
|
+
assert_raise(ArgumentError, line.inspect) do
|
75
|
+
reader.parse_line(line)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# Every escape, as encoded by ScripTTY::Util::Transcript::Writer, should
|
80
|
+
# parse correctly.
|
81
|
+
def test_escapes
|
82
|
+
input = '[99.000] S "\000\001\002\003\004\005\006\007'
|
83
|
+
input += '\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027'
|
84
|
+
input += '\030\031\032\033\034\035\036\037 !\042#$%&' + "'"
|
85
|
+
input += '()*+,-./0123456789:;<=>?'
|
86
|
+
input += '@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\134]^_'
|
87
|
+
input += '`abcdefghijklmnopqrstuvwxyz{|}~\177'
|
88
|
+
input += '\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217'
|
89
|
+
input += '\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237'
|
90
|
+
input += '\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257'
|
91
|
+
input += '\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277'
|
92
|
+
input += '\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317'
|
93
|
+
input += '\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337'
|
94
|
+
input += '\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357'
|
95
|
+
input += '\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377'
|
96
|
+
input += "\"\n"
|
97
|
+
reader = ScripTTY::Util::Transcript::Reader.new
|
98
|
+
timestamp, type, args = reader.parse_line(input)
|
99
|
+
assert_equal 99.0, timestamp
|
100
|
+
assert_equal type, :from_server
|
101
|
+
assert_equal args, [(0..255).pack("C*")]
|
102
|
+
end
|
103
|
+
|
104
|
+
# Every octal escape between \000 and \377 should parse correctly.
|
105
|
+
def test_all_escapes
|
106
|
+
input = '[99.000] S "'
|
107
|
+
input += '\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017'
|
108
|
+
input += '\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037'
|
109
|
+
input += '\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057'
|
110
|
+
input += '\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077'
|
111
|
+
input += '\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117'
|
112
|
+
input += '\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137'
|
113
|
+
input += '\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157'
|
114
|
+
input += '\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177'
|
115
|
+
input += '\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217'
|
116
|
+
input += '\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237'
|
117
|
+
input += '\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257'
|
118
|
+
input += '\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277'
|
119
|
+
input += '\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317'
|
120
|
+
input += '\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337'
|
121
|
+
input += '\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357'
|
122
|
+
input += '\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377'
|
123
|
+
input += "\"\n"
|
124
|
+
reader = ScripTTY::Util::Transcript::Reader.new
|
125
|
+
timestamp, type, args = reader.parse_line(input)
|
126
|
+
assert_equal 99.0, timestamp
|
127
|
+
assert_equal type, :from_server
|
128
|
+
assert_equal args, [(0..255).pack("C*")]
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# = Tests for ScripTTY::Util::Transcript::Writer
|
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/util/transcript/writer'
|
21
|
+
require 'stringio'
|
22
|
+
|
23
|
+
class TranscriptWriterTest < Test::Unit::TestCase
|
24
|
+
def test_methods
|
25
|
+
sio = StringIO.new
|
26
|
+
writer = ScripTTY::Util::Transcript::Writer.new(sio)
|
27
|
+
writer.override_timestamp = 88.0
|
28
|
+
writer.client_open("10.0.0.5", 55555)
|
29
|
+
writer.server_open("10.0.0.1", 54321)
|
30
|
+
writer.from_client("\e[33m")
|
31
|
+
writer.from_server("\e[33m")
|
32
|
+
writer.client_parsed("t_foo", "\e[33m")
|
33
|
+
writer.server_parsed("t_foo", "\e[33m")
|
34
|
+
writer.client_close("msg")
|
35
|
+
writer.server_close("msg")
|
36
|
+
writer.info("msg")
|
37
|
+
writer.close
|
38
|
+
expected = <<-'EOF'.strip.split("\n").map{|line| line.strip}.join("\n") + "\n"
|
39
|
+
[88.000] Copen "10.0.0.5" "55555"
|
40
|
+
[88.000] Sopen "10.0.0.1" "54321"
|
41
|
+
[88.000] C "\033[33m"
|
42
|
+
[88.000] S "\033[33m"
|
43
|
+
[88.000] Cp "t_foo" "\033[33m"
|
44
|
+
[88.000] Sp "t_foo" "\033[33m"
|
45
|
+
[88.000] Cx "msg"
|
46
|
+
[88.000] Sx "msg"
|
47
|
+
[88.000] * "msg"
|
48
|
+
EOF
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_string_encoding
|
52
|
+
sio = StringIO.new
|
53
|
+
writer = ScripTTY::Util::Transcript::Writer.new(sio)
|
54
|
+
writer.override_timestamp = 99.0
|
55
|
+
writer.from_client((0..255).to_a.pack("C*"))
|
56
|
+
writer.close
|
57
|
+
|
58
|
+
# Backslash, double-quotes, and non-printableASCII (characters outside the
|
59
|
+
# range \x20-\x7e) should be octal-encoded.
|
60
|
+
expected = '[99.000] C "\000\001\002\003\004\005\006\007'
|
61
|
+
expected += '\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027'
|
62
|
+
expected += '\030\031\032\033\034\035\036\037 !\042#$%&' + "'"
|
63
|
+
expected += '()*+,-./0123456789:;<=>?'
|
64
|
+
expected += '@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\134]^_'
|
65
|
+
expected += '`abcdefghijklmnopqrstuvwxyz{|}~\177'
|
66
|
+
expected += '\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217'
|
67
|
+
expected += '\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237'
|
68
|
+
expected += '\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257'
|
69
|
+
expected += '\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277'
|
70
|
+
expected += '\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317'
|
71
|
+
expected += '\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337'
|
72
|
+
expected += '\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357'
|
73
|
+
expected += '\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377'
|
74
|
+
expected += "\"\n"
|
75
|
+
assert_equal expected, sio.string
|
76
|
+
end
|
77
|
+
|
78
|
+
# Check that the timestamp of the first message is zero, or within the amount
|
79
|
+
# of time it took to instantiate the writer and emit the first line.
|
80
|
+
def test_initial_timestamp
|
81
|
+
sio = StringIO.new
|
82
|
+
t0 = Time.now
|
83
|
+
writer = ScripTTY::Util::Transcript::Writer.new(sio)
|
84
|
+
writer.info("foo")
|
85
|
+
t1 = Time.now
|
86
|
+
assert sio.string =~ /^\[([\d.]+)\]/
|
87
|
+
relative_timestamp = $1
|
88
|
+
assert !relative_timestamp.empty?
|
89
|
+
relative_timestamp = relative_timestamp.to_f # convert to float
|
90
|
+
assert (relative_timestamp >= 0.0 && relative_timestamp <= (t1 - t0))
|
91
|
+
end
|
92
|
+
|
93
|
+
# Check that timestamps increase
|
94
|
+
def test_timestamps_increase
|
95
|
+
sio = StringIO.new
|
96
|
+
writer = ScripTTY::Util::Transcript::Writer.new(sio)
|
97
|
+
last_timestamp = 0.0
|
98
|
+
200.times do
|
99
|
+
sleep 0.002 # make sure the time increases enough to be within the resolution of the timestamp
|
100
|
+
writer.info("foo")
|
101
|
+
assert sio.string.strip.split("\n").last =~ /^\[([\d.]+)\]/
|
102
|
+
current_timestamp = $1.to_f
|
103
|
+
assert current_timestamp > last_timestamp, "timestamps should increase"
|
104
|
+
last_timestamp = current_timestamp
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# Test the override_timestamp attribute
|
109
|
+
def test_override_timestamp
|
110
|
+
sio = StringIO.new
|
111
|
+
writer = ScripTTY::Util::Transcript::Writer.new(sio)
|
112
|
+
writer.override_timestamp = 1.0 ; writer.info("one") ; sleep 0.02; writer.info("two")
|
113
|
+
writer.override_timestamp = 3.101 ; writer.info("three")
|
114
|
+
writer.override_timestamp = 4.222 ; writer.info("four")
|
115
|
+
writer.override_timestamp = 5.001 ; writer.info("five")
|
116
|
+
writer.close
|
117
|
+
expected = <<-'EOF'.strip.split("\n").map{|line| line.strip}.join("\n") + "\n"
|
118
|
+
[1.000] * "one"
|
119
|
+
[1.000] * "two"
|
120
|
+
[3.101] * "three"
|
121
|
+
[4.222] * "four"
|
122
|
+
[5.001] * "five"
|
123
|
+
EOF
|
124
|
+
assert_equal expected, sio.string
|
125
|
+
end
|
126
|
+
end
|
data/test.watchr
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# = autowatchr script for continuous testing of ScripTTY
|
2
|
+
# == Instructions
|
3
|
+
# - Install the 'watchr' and 'autowatchr' gems
|
4
|
+
# - Run "watchr test.watchr"
|
5
|
+
|
6
|
+
require 'autowatchr'
|
7
|
+
|
8
|
+
# Fixup mapping between files in lib/ and corresponding tests in test/
|
9
|
+
class ::Autowatchr # reopen
|
10
|
+
# Take a path like "lib/scriptty/foo/bar.rb" and run the corresponding test "test/foo/bar_test.rb"
|
11
|
+
def run_lib_file(path)
|
12
|
+
path_segments = path.split(File::SEPARATOR).reject{|s| s.empty?}
|
13
|
+
basename = path_segments.pop
|
14
|
+
path_segments.shift # Remove "lib"
|
15
|
+
path_segments.shift # Remove "scriptty"
|
16
|
+
path_segments.unshift @config.test_dir # Prepend "test"
|
17
|
+
path_segments << basename.gsub(/\.rb\Z/, "") + "_test.rb" # append test name
|
18
|
+
run_test_file(File.join(*path_segments))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
Autowatchr.new(self) do |config|
|
23
|
+
config.ruby = ENV['RUBY'] || 'ruby'
|
24
|
+
config.lib_dir = 'lib'
|
25
|
+
config.test_dir = 'test'
|
26
|
+
config.test_re = /^.*_test\.rb\Z/
|
27
|
+
end
|
28
|
+
|
29
|
+
# vim:set ft=ruby:
|