]>
Commit | Line | Data |
---|---|---|
d76d5067 JB |
1 | var glob = require('glob'); |
2 | var fs = require('fs'); | |
e79e67c3 | 3 | var os = require('os'); |
bebe43e5 | 4 | var pty = require('node-pty'); |
56ecc77d | 5 | var Terminal = require('../xterm'); |
d76d5067 | 6 | |
e79e67c3 DI |
7 | if (os.platform() === 'win32') { |
8 | // Skip tests on Windows since pty.open isn't supported | |
9 | return; | |
10 | } | |
11 | ||
d76d5067 JB |
12 | var CONSOLE_LOG = console.log; |
13 | ||
14 | // expect files need terminal at 80x25! | |
15 | var COLS = 80; | |
16 | var ROWS = 25; | |
17 | ||
dcf30b40 JB |
18 | /** some helpers for pty interaction */ |
19 | // we need a pty in between to get the termios decorations | |
20 | // for the basic test cases a raw pty device is enough | |
d76d5067 JB |
21 | var primitive_pty = pty.native.open(COLS, ROWS); |
22 | ||
23 | // fake sychronous pty write - read | |
dcf30b40 | 24 | // we just pipe the data from slave to master as a child program would do |
d76d5067 JB |
25 | // pty.js opens pipe fds with O_NONBLOCK |
26 | // just wait 10ms instead of setting fds to blocking mode | |
b520e2fd | 27 | function ptyWriteRead(s, cb) { |
dcf30b40 | 28 | fs.writeSync(primitive_pty.slave, s); |
740d4a45 DI |
29 | setTimeout(() => { |
30 | var b = Buffer(64000); | |
31 | var bytes = fs.readSync(primitive_pty.master, b, 0, 64000); | |
32 | cb(b.toString('utf8', 0, bytes)); | |
33 | }); | |
d76d5067 JB |
34 | } |
35 | ||
ed1a31d1 | 36 | // make sure raw pty is at x=0 and has no pending data |
b520e2fd DI |
37 | function ptyReset(cb) { |
38 | ptyWriteRead('\r\n', cb); | |
dcf30b40 JB |
39 | } |
40 | ||
41 | /* debug helpers */ | |
42 | // generate colorful noisy output to compare xterm and emulator cell states | |
d76d5067 | 43 | function formatError(in_, out_, expected) { |
dcf30b40 JB |
44 | function addLineNumber(start, color) { |
45 | var counter = start || 0; | |
46 | return function(s) { | |
47 | counter += 1; | |
48 | return '\x1b[33m' + (' ' + counter).slice(-2) + color + s; | |
d76d5067 | 49 | } |
dcf30b40 JB |
50 | } |
51 | var line80 = '12345678901234567890123456789012345678901234567890123456789012345678901234567890'; | |
52 | var s = ''; | |
53 | s += '\n\x1b[34m' + JSON.stringify(in_); | |
54 | s += '\n\x1b[33m ' + line80 + '\n'; | |
55 | s += out_.split('\n').map(addLineNumber(0, '\x1b[31m')).join('\n'); | |
56 | s += '\n\x1b[33m ' + line80 + '\n'; | |
57 | s += expected.split('\n').map(addLineNumber(0, '\x1b[32m')).join('\n'); | |
58 | return s; | |
d76d5067 JB |
59 | } |
60 | ||
61 | // simple debug output of terminal cells | |
62 | function terminalToString(term) { | |
dcf30b40 JB |
63 | var result = ''; |
64 | var line_s = ''; | |
4e359043 | 65 | for (var line = term.buffer.ybase; line < term.buffer.ybase + term.rows; line++) { |
dcf30b40 JB |
66 | line_s = ''; |
67 | for (var cell=0; cell<term.cols; ++cell) { | |
0d498fcd | 68 | line_s += term.buffer.lines.get(line)[cell][1]; |
d76d5067 | 69 | } |
dcf30b40 JB |
70 | // rtrim empty cells as xterm does |
71 | line_s = line_s.replace(/\s+$/, ''); | |
72 | result += line_s; | |
73 | result += '\n'; | |
74 | } | |
75 | return result; | |
d76d5067 JB |
76 | } |
77 | ||
dcf30b40 JB |
78 | /** tests */ |
79 | describe('xterm output comparison', function() { | |
80 | var xterm; | |
d76d5067 | 81 | |
dcf30b40 JB |
82 | beforeEach(function () { |
83 | xterm = new Terminal(COLS, ROWS); | |
3c635f3c | 84 | xterm.refresh = function() {}; |
da16dd7c DI |
85 | xterm.viewport = { |
86 | syncScrollArea: function() {} | |
87 | }; | |
dcf30b40 | 88 | }); |
d76d5067 | 89 | |
dcf30b40 JB |
90 | // omit stack trace for escape sequence files |
91 | Error.stackTraceLimit = 0; | |
56ecc77d | 92 | var files = glob.sync('**/escape_sequence_files/*.in'); |
dcf30b40 | 93 | // only successful tests for now |
4f7ee7da DI |
94 | var skip = [ |
95 | 10, 16, 17, 19, 32, 33, 34, 35, 36, 39, | |
96 | 40, 42, 43, 44, 45, 46, 47, 48, 49, 50, | |
97 | 51, 52, 54, 55, 56, 57, 58, 59, 60, 61, | |
98 | 63, 68 | |
99 | ]; | |
64809338 DI |
100 | if (os.platform() === 'darwin') { |
101 | // These are failing on macOS only | |
102 | skip.push(3, 7, 11, 67); | |
103 | } | |
d5f0fff5 | 104 | for (var i = 0; i < files.length; i++) { |
4f7ee7da DI |
105 | if (skip.indexOf(i) >= 0) { |
106 | continue; | |
107 | } | |
d5f0fff5 | 108 | (function(filename) { |
740d4a45 | 109 | it(filename.split('/').slice(-1)[0], done => { |
b520e2fd | 110 | ptyReset(() => { |
740d4a45 | 111 | var in_file = fs.readFileSync(filename, 'utf8'); |
b520e2fd | 112 | ptyWriteRead(in_file, from_pty => { |
740d4a45 DI |
113 | // uncomment this to get log from terminal |
114 | //console.log = function(){}; | |
94c01ec3 | 115 | |
740d4a45 DI |
116 | // Perform a synchronous .write(data) |
117 | xterm.writeBuffer.push(from_pty); | |
118 | xterm.innerWrite(); | |
94c01ec3 | 119 | |
740d4a45 DI |
120 | var from_emulator = terminalToString(xterm); |
121 | console.log = CONSOLE_LOG; | |
122 | var expected = fs.readFileSync(filename.split('.')[0] + '.text', 'utf8'); | |
123 | // Some of the tests have whitespace on the right of lines, we trim all the linex | |
124 | // from xterm.js so ignore this for now at least. | |
125 | var expectedRightTrimmed = expected.split('\n').map(function (l) { | |
126 | return l.replace(/\s+$/, ''); | |
127 | }).join('\n'); | |
128 | if (from_emulator != expectedRightTrimmed) { | |
129 | // uncomment to get noisy output | |
130 | throw new Error(formatError(in_file, from_emulator, expected)); | |
131 | // throw new Error('mismatch'); | |
132 | } | |
133 | done(); | |
134 | }); | |
135 | }); | |
dcf30b40 JB |
136 | }); |
137 | })(files[i]); | |
138 | } | |
d76d5067 JB |
139 | }); |
140 |