blob: 622ee415d1a5a156bcd7acd58092bc188439ea9b [file] [log] [blame]
Ryan Dahl55048cd2011-03-10 08:54:521// Copyright Joyent, Inc. and other Node contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and associated documentation files (the
5// "Software"), to deal in the Software without restriction, including
6// without limitation the rights to use, copy, modify, merge, publish,
7// distribute, sublicense, and/or sell copies of the Software, and to permit
8// persons to whom the Software is furnished to do so, subject to the
9// following conditions:
10//
11// The above copyright notice and this permission notice shall be included
12// in all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20// USE OR OTHER DEALINGS IN THE SOFTWARE.
21
Ryan Dahla0159b42010-12-04 23:20:3422var common = require('../common');
23var assert = require('assert');
Ryan Dahla6942b32010-06-08 00:39:2424
Ryan Dahl02cc39f2010-12-04 21:40:3925common.globalCheck = false;
26
Oleg Efimov0ce9cba2010-12-04 22:45:5227var net = require('net'),
28 repl = require('repl'),
29 message = 'Read, Eval, Print Loop',
Oleg Efimov0ce9cba2010-12-04 22:45:5230 prompt_unix = 'node via Unix socket> ',
31 prompt_tcp = 'node via TCP socket> ',
32 prompt_multiline = '... ',
isaacs28e851c2012-06-05 19:02:3733 prompt_npm = 'npm should be run outside of the ' +
34 'node repl, in your normal shell.\n' +
35 '(Press Control-D to exit.)\n',
36 expect_npm = prompt_npm + prompt_unix,
Oleg Efimov0ce9cba2010-12-04 22:45:5237 server_tcp, server_unix, client_tcp, client_unix, timer;
Ryan Dahla6942b32010-06-08 00:39:2438
Ryan Dahl03a119e2011-08-09 23:06:3239
Ryan Dahl49627022010-09-19 18:20:2540// absolute path to test/fixtures/a.js
Oleg Efimov0ce9cba2010-12-04 22:45:5241var moduleFilename = require('path').join(common.fixturesDir, 'a');
Ryan Dahl49627022010-09-19 18:20:2542
Ryan Dahl9fd5e3c2010-07-15 18:47:2543common.error('repl test');
Matt Ranneyb7441042010-04-11 23:13:3244
45// function for REPL to run
Oleg Efimov0ce9cba2010-12-04 22:45:5246invoke_me = function(arg) {
47 return 'invoked ' + arg;
Matt Ranneyb7441042010-04-11 23:13:3248};
49
50function send_expect(list) {
51 if (list.length > 0) {
52 var cur = list.shift();
53
Oleg Efimov0ce9cba2010-12-04 22:45:5254 common.error('sending ' + JSON.stringify(cur.send));
Ryan Dahla6942b32010-06-08 00:39:2455
Matt Ranneyb7441042010-04-11 23:13:3256 cur.client.expect = cur.expect;
57 cur.client.list = list;
58 if (cur.send.length > 0) {
Nathan Rajlichaab7cb72012-04-06 19:20:0159 cur.client.write(cur.send + '\n');
Matt Ranneyb7441042010-04-11 23:13:3260 }
61 }
62}
63
Marco Rogers118b88e2010-11-20 23:44:5864function clean_up() {
65 client_tcp.end();
66 client_unix.end();
67 clearTimeout(timer);
68}
69
70function error_test() {
Ryan Dahl08d81162010-12-01 21:43:0571 // The other stuff is done so reuse unix socket
Oleg Efimov0ce9cba2010-12-04 22:45:5272 var read_buffer = '';
Ryan Dahl08d81162010-12-01 21:43:0573 client_unix.removeAllListeners('data');
Marco Rogers118b88e2010-11-20 23:44:5874
Ben Noordhuis018e1102011-10-14 23:08:3675 client_unix.on('data', function(data) {
Ryan Dahl08d81162010-12-01 21:43:0576 read_buffer += data.toString('ascii', 0, data.length);
Oleg Efimov0ce9cba2010-12-04 22:45:5277 common.error('Unix data: ' + JSON.stringify(read_buffer) + ', expecting ' +
78 (client_unix.expect.exec ?
79 client_unix.expect :
80 JSON.stringify(client_unix.expect)));
Marco Rogers118b88e2010-11-20 23:44:5881
Ryan Dahl08d81162010-12-01 21:43:0582 if (read_buffer.indexOf(prompt_unix) !== -1) {
isaacs28e851c2012-06-05 19:02:3783 // if it's an exact match, then don't do the regexp
84 if (read_buffer !== client_unix.expect) {
85 assert.ok(read_buffer.match(client_unix.expect));
86 common.error('match');
87 }
Oleg Efimov0ce9cba2010-12-04 22:45:5288 read_buffer = '';
Ryan Dahl08d81162010-12-01 21:43:0589 if (client_unix.list && client_unix.list.length > 0) {
90 send_expect(client_unix.list);
91 } else {
Oleg Efimov0ce9cba2010-12-04 22:45:5292 common.error('End of Error test, running TCP test.');
Ryan Dahl08d81162010-12-01 21:43:0593 tcp_test();
94 }
95
seebees3421f432011-11-12 01:44:3996 } else if (read_buffer.indexOf(prompt_multiline) !== -1) {
Ryan Dahl08d81162010-12-01 21:43:0597 // Check that you meant to send a multiline test
98 assert.strictEqual(prompt_multiline, client_unix.expect);
Oleg Efimov0ce9cba2010-12-04 22:45:5299 read_buffer = '';
Ryan Dahl08d81162010-12-01 21:43:05100 if (client_unix.list && client_unix.list.length > 0) {
101 send_expect(client_unix.list);
102 } else {
Oleg Efimov0ce9cba2010-12-04 22:45:52103 common.error('End of Error test, running TCP test.\n');
Ryan Dahl08d81162010-12-01 21:43:05104 tcp_test();
105 }
106
107 } else {
Oleg Efimov0ce9cba2010-12-04 22:45:52108 common.error('didn\'t see prompt yet, buffering.');
Ryan Dahl08d81162010-12-01 21:43:05109 }
110 });
111
112 send_expect([
113 // Uncaught error throws and prints out
Oleg Efimov0ce9cba2010-12-04 22:45:52114 { client: client_unix, send: 'throw new Error(\'test error\');',
115 expect: /^Error: test error/ },
Ryan Dahl08d81162010-12-01 21:43:05116 // Common syntax error is treated as multiline command
Oleg Efimov0ce9cba2010-12-04 22:45:52117 { client: client_unix, send: 'function test_func() {',
118 expect: prompt_multiline },
Ryan Dahl08d81162010-12-01 21:43:05119 // You can recover with the .break command
Oleg Efimov0ce9cba2010-12-04 22:45:52120 { client: client_unix, send: '.break',
121 expect: prompt_unix },
Ben Noordhuisb6e98972012-11-10 17:21:13122 // Floating point numbers are not interpreted as REPL commands.
123 { client: client_unix, send: '.1234',
124 expect: '0.1234' },
Nirk Niggler0459a232013-01-03 14:27:55125 // Floating point expressions are not interpreted as REPL commands
Ben Noordhuis8a65df92013-07-10 07:48:55126 { client: client_unix, send: '.1+.1',
Nirk Niggler0459a232013-01-03 14:27:55127 expect: '0.2' },
Ryan Dahl08d81162010-12-01 21:43:05128 // Can parse valid JSON
Oleg Efimov0ce9cba2010-12-04 22:45:52129 { client: client_unix, send: 'JSON.parse(\'{"valid": "json"}\');',
130 expect: '{ valid: \'json\' }'},
131 // invalid input to JSON.parse error is special case of syntax error,
132 // should throw
133 { client: client_unix, send: 'JSON.parse(\'{invalid: \\\'json\\\'}\');',
koichik8faf9412011-07-04 19:10:14134 expect: /^SyntaxError: Unexpected token i/ },
Nathan Rajlich3b7312d2012-10-01 18:36:06135 // end of input to JSON.parse error is special case of syntax error,
136 // should throw
Brian White774b28f2013-05-26 16:26:39137 { client: client_unix, send: 'JSON.parse(\'066\');',
138 expect: /^SyntaxError: Unexpected number/ },
139 // should throw
Nathan Rajlich3b7312d2012-10-01 18:36:06140 { client: client_unix, send: 'JSON.parse(\'{\');',
141 expect: /^SyntaxError: Unexpected end of input/ },
Nathan Rajlich4a267072012-09-22 01:46:16142 // invalid RegExps are a special case of syntax error,
143 // should throw
144 { client: client_unix, send: '/(/;',
145 expect: /^SyntaxError: Invalid regular expression\:/ },
Nathan Rajlichf1722a22012-10-01 05:43:35146 // invalid RegExp modifiers are a special case of syntax error,
147 // should throw (GH-4012)
148 { client: client_unix, send: 'new RegExp("foo", "wrong modifier");',
149 expect: /^SyntaxError: Invalid flags supplied to RegExp constructor/ },
Nathan Rajlich085f9d62013-03-30 20:10:30150 // strict mode syntax errors should be caught (GH-5178)
151 { client: client_unix, send: '(function() { "use strict"; return 0755; })()',
152 expect: /^SyntaxError: Octal literals are not allowed in strict mode/ },
153 { client: client_unix, send: '(function() { "use strict"; return { p: 1, p: 2 }; })()',
154 expect: /^SyntaxError: Duplicate data property in object literal not allowed in strict mode/ },
155 { client: client_unix, send: '(function(a, a, b) { "use strict"; return a + b + c; })()',
156 expect: /^SyntaxError: Strict mode function may not have duplicate parameter names/ },
157 { client: client_unix, send: '(function() { "use strict"; with (this) {} })()',
158 expect: /^SyntaxError: Strict mode code may not include a with statement/ },
159 { client: client_unix, send: '(function() { "use strict"; var x; delete x; })()',
160 expect: /^SyntaxError: Delete of an unqualified identifier in strict mode/ },
161 { client: client_unix, send: '(function() { "use strict"; eval = 17; })()',
162 expect: /^SyntaxError: Assignment to eval or arguments is not allowed in strict mode/ },
163 { client: client_unix, send: '(function() { "use strict"; if (true){ function f() { } } })()',
164 expect: /^SyntaxError: In strict mode code, functions can only be declared at top level or immediately within another function/ },
Ryan Dahlfeb77ea2011-01-03 02:08:08165 // Named functions can be used:
166 { client: client_unix, send: 'function blah() { return 1; }',
167 expect: prompt_unix },
168 { client: client_unix, send: 'blah()',
Colton Baker87286cc2011-10-04 22:08:18169 expect: '1\n' + prompt_unix },
Fedor Indutnyae5e2332012-02-17 18:18:11170 // Functions should not evaluate twice (#2773)
171 { client: client_unix, send: 'var I = [1,2,3,function() {}]; I.pop()',
172 expect: '[Function]' },
Ryan Dahlfeb77ea2011-01-03 02:08:08173 // Multiline object
174 { client: client_unix, send: '{ a: ',
175 expect: prompt_multiline },
176 { client: client_unix, send: '1 }',
Colton Baker87286cc2011-10-04 22:08:18177 expect: '{ a: 1 }' },
Ryan Dahlfeb77ea2011-01-03 02:08:08178 // Multiline anonymous function with comment
179 { client: client_unix, send: '(function () {',
180 expect: prompt_multiline },
181 { client: client_unix, send: '// blah',
182 expect: prompt_multiline },
183 { client: client_unix, send: 'return 1;',
184 expect: prompt_multiline },
185 { client: client_unix, send: '})()',
isaacs28e851c2012-06-05 19:02:37186 expect: '1' },
187 // npm prompt error message
188 { client: client_unix, send: 'npm install foobar',
Maciej Małecki6a11f3e2012-07-03 02:13:24189 expect: expect_npm },
190 { client: client_unix, send: '(function () {\n\nreturn 1;\n})()',
Nathan Rajlich9126dd22012-07-04 18:51:24191 expect: '1' },
192 { client: client_unix, send: '{\n\na: 1\n}',
Felix Böhm9bce5e82013-01-12 20:07:06193 expect: '{ a: 1 }' },
194 { client: client_unix, send: 'url.format("http://google.com")',
195 expect: 'http://google.com/' },
196 { client: client_unix, send: 'var path = 42; path',
197 expect: '42' }
Ryan Dahl08d81162010-12-01 21:43:05198 ]);
Marco Rogers118b88e2010-11-20 23:44:58199}
200
Matt Ranneyb7441042010-04-11 23:13:32201function tcp_test() {
Oleg Efimov0ce9cba2010-12-04 22:45:52202 server_tcp = net.createServer(function(socket) {
Matt Ranneyb7441042010-04-11 23:13:32203 assert.strictEqual(server_tcp, socket.server);
Ryan Dahla6942b32010-06-08 00:39:24204
Ben Noordhuis018e1102011-10-14 23:08:36205 socket.on('end', function() {
Matt Ranneyb7441042010-04-11 23:13:32206 socket.end();
207 });
208
209 repl.start(prompt_tcp, socket);
210 });
211
Oleg Efimov0ce9cba2010-12-04 22:45:52212 server_tcp.listen(common.PORT, function() {
213 var read_buffer = '';
Ryan Dahla6942b32010-06-08 00:39:24214
Ryan Dahl9fd5e3c2010-07-15 18:47:25215 client_tcp = net.createConnection(common.PORT);
Matt Ranneyb7441042010-04-11 23:13:32216
Ben Noordhuis018e1102011-10-14 23:08:36217 client_tcp.on('connect', function() {
Matt Ranneyb7441042010-04-11 23:13:32218 assert.equal(true, client_tcp.readable);
219 assert.equal(true, client_tcp.writable);
220
221 send_expect([
Oleg Efimov0665f022010-12-05 19:15:30222 { client: client_tcp, send: '',
223 expect: prompt_tcp },
Nathan Rajlichaab7cb72012-04-06 19:20:01224 { client: client_tcp, send: 'invoke_me(333)',
Oleg Efimov0665f022010-12-05 19:15:30225 expect: ('\'' + 'invoked 333' + '\'\n' + prompt_tcp) },
Nathan Rajlichaab7cb72012-04-06 19:20:01226 { client: client_tcp, send: 'a += 1',
Oleg Efimov0665f022010-12-05 19:15:30227 expect: ('12346' + '\n' + prompt_tcp) },
228 { client: client_tcp,
Nathan Rajlichaab7cb72012-04-06 19:20:01229 send: 'require(' + JSON.stringify(moduleFilename) + ').number',
Oleg Efimov0665f022010-12-05 19:15:30230 expect: ('42' + '\n' + prompt_tcp) }
231 ]);
Matt Ranneyb7441042010-04-11 23:13:32232 });
233
Ben Noordhuis018e1102011-10-14 23:08:36234 client_tcp.on('data', function(data) {
Ryan Dahl4fe5e862010-09-06 19:12:36235 read_buffer += data.toString('ascii', 0, data.length);
Oleg Efimov0ce9cba2010-12-04 22:45:52236 common.error('TCP data: ' + JSON.stringify(read_buffer) +
237 ', expecting ' + JSON.stringify(client_tcp.expect));
Matt Ranneyafe3c1c2010-04-12 21:29:49238 if (read_buffer.indexOf(prompt_tcp) !== -1) {
239 assert.strictEqual(client_tcp.expect, read_buffer);
Oleg Efimov0ce9cba2010-12-04 22:45:52240 common.error('match');
241 read_buffer = '';
Matt Ranneyafe3c1c2010-04-12 21:29:49242 if (client_tcp.list && client_tcp.list.length > 0) {
243 send_expect(client_tcp.list);
Ryan Dahl08d81162010-12-01 21:43:05244 } else {
Oleg Efimov0ce9cba2010-12-04 22:45:52245 common.error('End of TCP test.\n');
Marco Rogers118b88e2010-11-20 23:44:58246 clean_up();
Matt Ranneyafe3c1c2010-04-12 21:29:49247 }
Ryan Dahl08d81162010-12-01 21:43:05248 } else {
Oleg Efimov0ce9cba2010-12-04 22:45:52249 common.error('didn\'t see prompt yet, buffering');
Matt Ranneyb7441042010-04-11 23:13:32250 }
251 });
Ryan Dahla6942b32010-06-08 00:39:24252
Ben Noordhuis018e1102011-10-14 23:08:36253 client_tcp.on('error', function(e) {
Matt Ranneyb7441042010-04-11 23:13:32254 throw e;
255 });
Ryan Dahla6942b32010-06-08 00:39:24256
Ben Noordhuis018e1102011-10-14 23:08:36257 client_tcp.on('close', function() {
Matt Ranneyb7441042010-04-11 23:13:32258 server_tcp.close();
259 });
260 });
261
Matt Ranneyb7441042010-04-11 23:13:32262}
263
264function unix_test() {
Oleg Efimov0ce9cba2010-12-04 22:45:52265 server_unix = net.createServer(function(socket) {
Matt Ranneyb7441042010-04-11 23:13:32266 assert.strictEqual(server_unix, socket.server);
Matt Ranneyb7441042010-04-11 23:13:32267
Ben Noordhuis018e1102011-10-14 23:08:36268 socket.on('end', function() {
Matt Ranneyb7441042010-04-11 23:13:32269 socket.end();
270 });
271
Nathan Rajlichb1e78ce2012-10-12 23:34:36272 repl.start({
273 prompt: prompt_unix,
274 input: socket,
275 output: socket,
276 useGlobal: true
277 }).context.message = message;
Matt Ranneyb7441042010-04-11 23:13:32278 });
279
Ben Noordhuis018e1102011-10-14 23:08:36280 server_unix.on('listening', function() {
Oleg Efimov0ce9cba2010-12-04 22:45:52281 var read_buffer = '';
Ryan Dahla6942b32010-06-08 00:39:24282
Ryan Dahl03a119e2011-08-09 23:06:32283 client_unix = net.createConnection(common.PIPE);
Matt Ranneyb7441042010-04-11 23:13:32284
Ben Noordhuis018e1102011-10-14 23:08:36285 client_unix.on('connect', function() {
Matt Ranneyb7441042010-04-11 23:13:32286 assert.equal(true, client_unix.readable);
287 assert.equal(true, client_unix.writable);
288
289 send_expect([
Oleg Efimov0665f022010-12-05 19:15:30290 { client: client_unix, send: '',
291 expect: prompt_unix },
Nathan Rajlichaab7cb72012-04-06 19:20:01292 { client: client_unix, send: 'message',
Oleg Efimov0665f022010-12-05 19:15:30293 expect: ('\'' + message + '\'\n' + prompt_unix) },
Nathan Rajlichaab7cb72012-04-06 19:20:01294 { client: client_unix, send: 'invoke_me(987)',
Oleg Efimov0665f022010-12-05 19:15:30295 expect: ('\'' + 'invoked 987' + '\'\n' + prompt_unix) },
Nathan Rajlichaab7cb72012-04-06 19:20:01296 { client: client_unix, send: 'a = 12345',
Ryan Dahl8b352bd2011-01-02 05:14:06297 expect: ('12345' + '\n' + prompt_unix) },
Nathan Rajlichaab7cb72012-04-06 19:20:01298 { client: client_unix, send: '{a:1}',
Colton Baker87286cc2011-10-04 22:08:18299 expect: ('{ a: 1 }' + '\n' + prompt_unix) }
Oleg Efimov0665f022010-12-05 19:15:30300 ]);
Matt Ranneyb7441042010-04-11 23:13:32301 });
302
Ben Noordhuis018e1102011-10-14 23:08:36303 client_unix.on('data', function(data) {
Ryan Dahl4fe5e862010-09-06 19:12:36304 read_buffer += data.toString('ascii', 0, data.length);
Oleg Efimov0ce9cba2010-12-04 22:45:52305 common.error('Unix data: ' + JSON.stringify(read_buffer) +
306 ', expecting ' + JSON.stringify(client_unix.expect));
Matt Ranneyafe3c1c2010-04-12 21:29:49307 if (read_buffer.indexOf(prompt_unix) !== -1) {
308 assert.strictEqual(client_unix.expect, read_buffer);
Oleg Efimov0ce9cba2010-12-04 22:45:52309 common.error('match');
310 read_buffer = '';
Matt Ranneyafe3c1c2010-04-12 21:29:49311 if (client_unix.list && client_unix.list.length > 0) {
312 send_expect(client_unix.list);
Ryan Dahla6942b32010-06-08 00:39:24313 } else {
Oleg Efimov0ce9cba2010-12-04 22:45:52314 common.error('End of Unix test, running Error test.\n');
Marco Rogers118b88e2010-11-20 23:44:58315 process.nextTick(error_test);
Matt Ranneyafe3c1c2010-04-12 21:29:49316 }
Ryan Dahl08d81162010-12-01 21:43:05317 } else {
Oleg Efimov0ce9cba2010-12-04 22:45:52318 common.error('didn\'t see prompt yet, buffering.');
Matt Ranneyb7441042010-04-11 23:13:32319 }
320 });
Ryan Dahla6942b32010-06-08 00:39:24321
Ben Noordhuis018e1102011-10-14 23:08:36322 client_unix.on('error', function(e) {
Matt Ranneyb7441042010-04-11 23:13:32323 throw e;
324 });
325
Ben Noordhuis018e1102011-10-14 23:08:36326 client_unix.on('close', function() {
Matt Ranneyb7441042010-04-11 23:13:32327 server_unix.close();
328 });
329 });
330
Ryan Dahl03a119e2011-08-09 23:06:32331 server_unix.listen(common.PIPE);
Matt Ranneyb7441042010-04-11 23:13:32332}
333
334unix_test();
Marco Rogers118b88e2010-11-20 23:44:58335
Oleg Efimov0ce9cba2010-12-04 22:45:52336timer = setTimeout(function() {
337 assert.fail('Timeout');
Ryan Dahl129217a2011-01-26 01:35:06338}, 5000);