You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

756 lines
20 KiB

  1. var common = require('../common');
  2. var MultipartParserStub = GENTLY.stub('./multipart_parser', 'MultipartParser'),
  3. QuerystringParserStub = GENTLY.stub('./querystring_parser', 'QuerystringParser'),
  4. EventEmitterStub = GENTLY.stub('events', 'EventEmitter'),
  5. StreamStub = GENTLY.stub('stream', 'Stream'),
  6. FileStub = GENTLY.stub('./file');
  7. var formidable = require(common.lib + '/index'),
  8. IncomingForm = formidable.IncomingForm,
  9. events = require('events'),
  10. fs = require('fs'),
  11. path = require('path'),
  12. Buffer = require('buffer').Buffer,
  13. fixtures = require(TEST_FIXTURES + '/multipart'),
  14. form,
  15. gently;
  16. function test(test) {
  17. gently = new Gently();
  18. gently.expect(EventEmitterStub, 'call');
  19. form = new IncomingForm();
  20. test();
  21. gently.verify(test.name);
  22. }
  23. test(function constructor() {
  24. assert.strictEqual(form.error, null);
  25. assert.strictEqual(form.ended, false);
  26. assert.strictEqual(form.type, null);
  27. assert.strictEqual(form.headers, null);
  28. assert.strictEqual(form.keepExtensions, false);
  29. // Can't assume dir === '/tmp' for portability
  30. // assert.strictEqual(form.uploadDir, '/tmp');
  31. // Make sure it is a directory instead
  32. assert.doesNotThrow(function () {
  33. assert(fs.statSync(form.uploadDir).isDirectory());
  34. });
  35. assert.strictEqual(form.encoding, 'utf-8');
  36. assert.strictEqual(form.bytesReceived, null);
  37. assert.strictEqual(form.bytesExpected, null);
  38. assert.strictEqual(form.maxFieldsSize, 2 * 1024 * 1024);
  39. assert.strictEqual(form._parser, null);
  40. assert.strictEqual(form._flushing, 0);
  41. assert.strictEqual(form._fieldsSize, 0);
  42. assert.ok(form instanceof EventEmitterStub);
  43. assert.equal(form.constructor.name, 'IncomingForm');
  44. (function testSimpleConstructor() {
  45. gently.expect(EventEmitterStub, 'call');
  46. var form = IncomingForm();
  47. assert.ok(form instanceof IncomingForm);
  48. })();
  49. (function testSimpleConstructorShortcut() {
  50. gently.expect(EventEmitterStub, 'call');
  51. var form = formidable();
  52. assert.ok(form instanceof IncomingForm);
  53. })();
  54. });
  55. test(function parse() {
  56. var REQ = {headers: {}}
  57. , emit = {};
  58. gently.expect(form, 'writeHeaders', function(headers) {
  59. assert.strictEqual(headers, REQ.headers);
  60. });
  61. var EVENTS = ['error', 'aborted', 'data', 'end'];
  62. gently.expect(REQ, 'on', EVENTS.length, function(event, fn) {
  63. assert.equal(event, EVENTS.shift());
  64. emit[event] = fn;
  65. return this;
  66. });
  67. form.parse(REQ);
  68. (function testPause() {
  69. gently.expect(REQ, 'pause');
  70. assert.strictEqual(form.pause(), true);
  71. })();
  72. (function testPauseCriticalException() {
  73. form.ended = false;
  74. var ERR = new Error('dasdsa');
  75. gently.expect(REQ, 'pause', function() {
  76. throw ERR;
  77. });
  78. gently.expect(form, '_error', function(err) {
  79. assert.strictEqual(err, ERR);
  80. });
  81. assert.strictEqual(form.pause(), false);
  82. })();
  83. (function testPauseHarmlessException() {
  84. form.ended = true;
  85. var ERR = new Error('dasdsa');
  86. gently.expect(REQ, 'pause', function() {
  87. throw ERR;
  88. });
  89. assert.strictEqual(form.pause(), false);
  90. })();
  91. (function testResume() {
  92. gently.expect(REQ, 'resume');
  93. assert.strictEqual(form.resume(), true);
  94. })();
  95. (function testResumeCriticalException() {
  96. form.ended = false;
  97. var ERR = new Error('dasdsa');
  98. gently.expect(REQ, 'resume', function() {
  99. throw ERR;
  100. });
  101. gently.expect(form, '_error', function(err) {
  102. assert.strictEqual(err, ERR);
  103. });
  104. assert.strictEqual(form.resume(), false);
  105. })();
  106. (function testResumeHarmlessException() {
  107. form.ended = true;
  108. var ERR = new Error('dasdsa');
  109. gently.expect(REQ, 'resume', function() {
  110. throw ERR;
  111. });
  112. assert.strictEqual(form.resume(), false);
  113. })();
  114. (function testEmitError() {
  115. var ERR = new Error('something bad happened');
  116. gently.expect(form, '_error',function(err) {
  117. assert.strictEqual(err, ERR);
  118. });
  119. emit.error(ERR);
  120. })();
  121. (function testEmitAborted() {
  122. gently.expect(form, 'emit',function(event) {
  123. assert.equal(event, 'aborted');
  124. });
  125. gently.expect(form, '_error');
  126. emit.aborted();
  127. })();
  128. (function testEmitData() {
  129. var BUFFER = [1, 2, 3];
  130. gently.expect(form, 'write', function(buffer) {
  131. assert.strictEqual(buffer, BUFFER);
  132. });
  133. emit.data(BUFFER);
  134. })();
  135. (function testEmitEnd() {
  136. form._parser = {};
  137. (function testWithError() {
  138. var ERR = new Error('haha');
  139. gently.expect(form._parser, 'end', function() {
  140. return ERR;
  141. });
  142. gently.expect(form, '_error', function(err) {
  143. assert.strictEqual(err, ERR);
  144. });
  145. emit.end();
  146. })();
  147. (function testWithoutError() {
  148. gently.expect(form._parser, 'end');
  149. emit.end();
  150. })();
  151. (function testAfterError() {
  152. form.error = true;
  153. emit.end();
  154. })();
  155. })();
  156. (function testWithCallback() {
  157. gently.expect(EventEmitterStub, 'call');
  158. var form = new IncomingForm(),
  159. REQ = {headers: {}},
  160. parseCalled = 0;
  161. gently.expect(form, 'on', 4, function(event, fn) {
  162. if (event == 'field') {
  163. fn('field1', 'foo');
  164. fn('field1', 'bar');
  165. fn('field2', 'nice');
  166. }
  167. if (event == 'file') {
  168. fn('file1', '1');
  169. fn('file1', '2');
  170. fn('file2', '3');
  171. }
  172. if (event == 'end') {
  173. fn();
  174. }
  175. return this;
  176. });
  177. gently.expect(form, 'writeHeaders');
  178. gently.expect(REQ, 'on', 4, function() {
  179. return this;
  180. });
  181. var parseCbOk = function (err, fields, files) {
  182. assert.deepEqual(fields, {field1: 'bar', field2: 'nice'});
  183. assert.deepEqual(files, {file1: '2', file2: '3'});
  184. };
  185. form.parse(REQ, parseCbOk);
  186. var ERR = new Error('test');
  187. gently.expect(form, 'on', 3, function(event, fn) {
  188. if (event == 'field') {
  189. fn('foo', 'bar');
  190. }
  191. if (event == 'error') {
  192. fn(ERR);
  193. gently.expect(form, 'on');
  194. gently.expect(form, 'writeHeaders');
  195. gently.expect(REQ, 'on', 4, function() {
  196. return this;
  197. });
  198. }
  199. return this;
  200. });
  201. form.parse(REQ, function parseCbErr(err, fields, files) {
  202. assert.strictEqual(err, ERR);
  203. assert.deepEqual(fields, {foo: 'bar'});
  204. });
  205. })();
  206. (function testWriteOrder() {
  207. gently.expect(EventEmitterStub, 'call');
  208. var form = new IncomingForm();
  209. var REQ = new events.EventEmitter();
  210. var BUF = {};
  211. var DATACB = null;
  212. REQ.on('newListener', function(event, fn) {
  213. if ('data' === event) fn(BUF);
  214. });
  215. gently.expect(form, 'writeHeaders');
  216. gently.expect(form, 'write', function(buf) {
  217. assert.strictEqual(buf, BUF);
  218. });
  219. form.parse(REQ);
  220. })();
  221. });
  222. test(function pause() {
  223. assert.strictEqual(form.pause(), false);
  224. });
  225. test(function resume() {
  226. assert.strictEqual(form.resume(), false);
  227. });
  228. test(function writeHeaders() {
  229. var HEADERS = {};
  230. gently.expect(form, '_parseContentLength');
  231. gently.expect(form, '_parseContentType');
  232. form.writeHeaders(HEADERS);
  233. assert.strictEqual(form.headers, HEADERS);
  234. });
  235. test(function write() {
  236. var parser = {},
  237. BUFFER = [1, 2, 3];
  238. form._parser = parser;
  239. form.bytesExpected = 523423;
  240. (function testBasic() {
  241. gently.expect(form, 'emit', function(event, bytesReceived, bytesExpected) {
  242. assert.equal(event, 'progress');
  243. assert.equal(bytesReceived, BUFFER.length);
  244. assert.equal(bytesExpected, form.bytesExpected);
  245. });
  246. gently.expect(parser, 'write', function(buffer) {
  247. assert.strictEqual(buffer, BUFFER);
  248. return buffer.length;
  249. });
  250. assert.equal(form.write(BUFFER), BUFFER.length);
  251. assert.equal(form.bytesReceived, BUFFER.length);
  252. })();
  253. (function testParserError() {
  254. gently.expect(form, 'emit');
  255. gently.expect(parser, 'write', function(buffer) {
  256. assert.strictEqual(buffer, BUFFER);
  257. return buffer.length - 1;
  258. });
  259. gently.expect(form, '_error', function(err) {
  260. assert.ok(err.message.match(/parser error/i));
  261. });
  262. assert.equal(form.write(BUFFER), BUFFER.length - 1);
  263. assert.equal(form.bytesReceived, BUFFER.length + BUFFER.length);
  264. })();
  265. (function testUninitialized() {
  266. delete form._parser;
  267. gently.expect(form, '_error', function(err) {
  268. assert.ok(err.message.match(/unintialized parser/i));
  269. });
  270. form.write(BUFFER);
  271. })();
  272. });
  273. test(function parseContentType() {
  274. var HEADERS = {};
  275. form.headers = {'content-type': 'application/x-www-form-urlencoded'};
  276. gently.expect(form, '_initUrlencoded');
  277. form._parseContentType();
  278. // accept anything that has 'urlencoded' in it
  279. form.headers = {'content-type': 'broken-client/urlencoded-stupid'};
  280. gently.expect(form, '_initUrlencoded');
  281. form._parseContentType();
  282. var BOUNDARY = '---------------------------57814261102167618332366269';
  283. form.headers = {'content-type': 'multipart/form-data; boundary='+BOUNDARY};
  284. gently.expect(form, '_initMultipart', function(boundary) {
  285. assert.equal(boundary, BOUNDARY);
  286. });
  287. form._parseContentType();
  288. (function testQuotedBoundary() {
  289. form.headers = {'content-type': 'multipart/form-data; boundary="' + BOUNDARY + '"'};
  290. gently.expect(form, '_initMultipart', function(boundary) {
  291. assert.equal(boundary, BOUNDARY);
  292. });
  293. form._parseContentType();
  294. })();
  295. (function testNoBoundary() {
  296. form.headers = {'content-type': 'multipart/form-data'};
  297. gently.expect(form, '_error', function(err) {
  298. assert.ok(err.message.match(/no multipart boundary/i));
  299. });
  300. form._parseContentType();
  301. })();
  302. (function testNoContentType() {
  303. form.headers = {};
  304. gently.expect(form, '_error', function(err) {
  305. assert.ok(err.message.match(/no content-type/i));
  306. });
  307. form._parseContentType();
  308. })();
  309. (function testUnknownContentType() {
  310. form.headers = {'content-type': 'invalid'};
  311. gently.expect(form, '_error', function(err) {
  312. assert.ok(err.message.match(/unknown content-type/i));
  313. });
  314. form._parseContentType();
  315. })();
  316. });
  317. test(function parseContentLength() {
  318. var HEADERS = {};
  319. form.headers = {};
  320. gently.expect(form, 'emit', function(event, bytesReceived, bytesExpected) {
  321. assert.equal(event, 'progress');
  322. assert.equal(bytesReceived, 0);
  323. assert.equal(bytesExpected, 0);
  324. });
  325. form._parseContentLength();
  326. form.headers['content-length'] = '8';
  327. gently.expect(form, 'emit', function(event, bytesReceived, bytesExpected) {
  328. assert.equal(event, 'progress');
  329. assert.equal(bytesReceived, 0);
  330. assert.equal(bytesExpected, 8);
  331. });
  332. form._parseContentLength();
  333. assert.strictEqual(form.bytesReceived, 0);
  334. assert.strictEqual(form.bytesExpected, 8);
  335. // JS can be evil, lets make sure we are not
  336. form.headers['content-length'] = '08';
  337. gently.expect(form, 'emit', function(event, bytesReceived, bytesExpected) {
  338. assert.equal(event, 'progress');
  339. assert.equal(bytesReceived, 0);
  340. assert.equal(bytesExpected, 8);
  341. });
  342. form._parseContentLength();
  343. assert.strictEqual(form.bytesExpected, 8);
  344. });
  345. test(function _initMultipart() {
  346. var BOUNDARY = '123',
  347. PARSER;
  348. gently.expect(MultipartParserStub, 'new', function() {
  349. PARSER = this;
  350. });
  351. gently.expect(MultipartParserStub.prototype, 'initWithBoundary', function(boundary) {
  352. assert.equal(boundary, BOUNDARY);
  353. });
  354. form._initMultipart(BOUNDARY);
  355. assert.equal(form.type, 'multipart');
  356. assert.strictEqual(form._parser, PARSER);
  357. (function testRegularField() {
  358. var PART;
  359. gently.expect(StreamStub, 'new', function() {
  360. PART = this;
  361. });
  362. gently.expect(form, 'onPart', function(part) {
  363. assert.strictEqual(part, PART);
  364. assert.deepEqual
  365. ( part.headers
  366. , { 'content-disposition': 'form-data; name="field1"'
  367. , 'foo': 'bar'
  368. }
  369. );
  370. assert.equal(part.name, 'field1');
  371. var strings = ['hello', ' world'];
  372. gently.expect(part, 'emit', 2, function(event, b) {
  373. assert.equal(event, 'data');
  374. assert.equal(b.toString(), strings.shift());
  375. });
  376. gently.expect(part, 'emit', function(event, b) {
  377. assert.equal(event, 'end');
  378. });
  379. });
  380. PARSER.onPartBegin();
  381. PARSER.onHeaderField(new Buffer('content-disposition'), 0, 10);
  382. PARSER.onHeaderField(new Buffer('content-disposition'), 10, 19);
  383. PARSER.onHeaderValue(new Buffer('form-data; name="field1"'), 0, 14);
  384. PARSER.onHeaderValue(new Buffer('form-data; name="field1"'), 14, 24);
  385. PARSER.onHeaderEnd();
  386. PARSER.onHeaderField(new Buffer('foo'), 0, 3);
  387. PARSER.onHeaderValue(new Buffer('bar'), 0, 3);
  388. PARSER.onHeaderEnd();
  389. PARSER.onHeadersEnd();
  390. PARSER.onPartData(new Buffer('hello world'), 0, 5);
  391. PARSER.onPartData(new Buffer('hello world'), 5, 11);
  392. PARSER.onPartEnd();
  393. })();
  394. (function testFileField() {
  395. var PART;
  396. gently.expect(StreamStub, 'new', function() {
  397. PART = this;
  398. });
  399. gently.expect(form, 'onPart', function(part) {
  400. assert.deepEqual
  401. ( part.headers
  402. , { 'content-disposition': 'form-data; name="field2"; filename="C:\\Documents and Settings\\IE\\Must\\Die\\Sun"et.jpg"'
  403. , 'content-type': 'text/plain'
  404. }
  405. );
  406. assert.equal(part.name, 'field2');
  407. assert.equal(part.filename, 'Sun"et.jpg');
  408. assert.equal(part.mime, 'text/plain');
  409. gently.expect(part, 'emit', function(event, b) {
  410. assert.equal(event, 'data');
  411. assert.equal(b.toString(), '... contents of file1.txt ...');
  412. });
  413. gently.expect(part, 'emit', function(event, b) {
  414. assert.equal(event, 'end');
  415. });
  416. });
  417. PARSER.onPartBegin();
  418. PARSER.onHeaderField(new Buffer('content-disposition'), 0, 19);
  419. PARSER.onHeaderValue(new Buffer('form-data; name="field2"; filename="C:\\Documents and Settings\\IE\\Must\\Die\\Sun"et.jpg"'), 0, 85);
  420. PARSER.onHeaderEnd();
  421. PARSER.onHeaderField(new Buffer('Content-Type'), 0, 12);
  422. PARSER.onHeaderValue(new Buffer('text/plain'), 0, 10);
  423. PARSER.onHeaderEnd();
  424. PARSER.onHeadersEnd();
  425. PARSER.onPartData(new Buffer('... contents of file1.txt ...'), 0, 29);
  426. PARSER.onPartEnd();
  427. })();
  428. (function testEnd() {
  429. gently.expect(form, '_maybeEnd');
  430. PARSER.onEnd();
  431. assert.ok(form.ended);
  432. })();
  433. });
  434. test(function _fileName() {
  435. // TODO
  436. return;
  437. });
  438. test(function _initUrlencoded() {
  439. var PARSER;
  440. gently.expect(QuerystringParserStub, 'new', function() {
  441. PARSER = this;
  442. });
  443. form._initUrlencoded();
  444. assert.equal(form.type, 'urlencoded');
  445. assert.strictEqual(form._parser, PARSER);
  446. (function testOnField() {
  447. var KEY = 'KEY', VAL = 'VAL';
  448. gently.expect(form, 'emit', function(field, key, val) {
  449. assert.equal(field, 'field');
  450. assert.equal(key, KEY);
  451. assert.equal(val, VAL);
  452. });
  453. PARSER.onField(KEY, VAL);
  454. })();
  455. (function testOnEnd() {
  456. gently.expect(form, '_maybeEnd');
  457. PARSER.onEnd();
  458. assert.equal(form.ended, true);
  459. })();
  460. });
  461. test(function _error() {
  462. var ERR = new Error('bla');
  463. gently.expect(form, 'pause');
  464. gently.expect(form, 'emit', function(event, err) {
  465. assert.equal(event, 'error');
  466. assert.strictEqual(err, ERR);
  467. });
  468. form._error(ERR);
  469. assert.strictEqual(form.error, ERR);
  470. // make sure _error only does its thing once
  471. form._error(ERR);
  472. });
  473. test(function onPart() {
  474. var PART = {};
  475. gently.expect(form, 'handlePart', function(part) {
  476. assert.strictEqual(part, PART);
  477. });
  478. form.onPart(PART);
  479. });
  480. test(function handlePart() {
  481. (function testUtf8Field() {
  482. var PART = new events.EventEmitter();
  483. PART.name = 'my_field';
  484. gently.expect(form, 'emit', function(event, field, value) {
  485. assert.equal(event, 'field');
  486. assert.equal(field, 'my_field');
  487. assert.equal(value, 'hello world: €');
  488. });
  489. form.handlePart(PART);
  490. PART.emit('data', new Buffer('hello'));
  491. PART.emit('data', new Buffer(' world: '));
  492. PART.emit('data', new Buffer([0xE2]));
  493. PART.emit('data', new Buffer([0x82, 0xAC]));
  494. PART.emit('end');
  495. })();
  496. (function testBinaryField() {
  497. var PART = new events.EventEmitter();
  498. PART.name = 'my_field2';
  499. gently.expect(form, 'emit', function(event, field, value) {
  500. assert.equal(event, 'field');
  501. assert.equal(field, 'my_field2');
  502. assert.equal(value, 'hello world: '+new Buffer([0xE2, 0x82, 0xAC]).toString('binary'));
  503. });
  504. form.encoding = 'binary';
  505. form.handlePart(PART);
  506. PART.emit('data', new Buffer('hello'));
  507. PART.emit('data', new Buffer(' world: '));
  508. PART.emit('data', new Buffer([0xE2]));
  509. PART.emit('data', new Buffer([0x82, 0xAC]));
  510. PART.emit('end');
  511. })();
  512. (function testFieldSize() {
  513. form.maxFieldsSize = 8;
  514. var PART = new events.EventEmitter();
  515. PART.name = 'my_field';
  516. gently.expect(form, '_error', function(err) {
  517. assert.equal(err.message, 'maxFieldsSize exceeded, received 9 bytes of field data');
  518. });
  519. form.handlePart(PART);
  520. form._fieldsSize = 1;
  521. PART.emit('data', new Buffer(7));
  522. PART.emit('data', new Buffer(1));
  523. })();
  524. (function testFilePart() {
  525. var PART = new events.EventEmitter(),
  526. FILE = new events.EventEmitter(),
  527. PATH = '/foo/bar';
  528. PART.name = 'my_file';
  529. PART.filename = 'sweet.txt';
  530. PART.mime = 'sweet.txt';
  531. gently.expect(form, '_uploadPath', function(filename) {
  532. assert.equal(filename, PART.filename);
  533. return PATH;
  534. });
  535. gently.expect(FileStub, 'new', function(properties) {
  536. assert.equal(properties.path, PATH);
  537. assert.equal(properties.name, PART.filename);
  538. assert.equal(properties.type, PART.mime);
  539. FILE = this;
  540. gently.expect(form, 'emit', function (event, field, file) {
  541. assert.equal(event, 'fileBegin');
  542. assert.strictEqual(field, PART.name);
  543. assert.strictEqual(file, FILE);
  544. });
  545. gently.expect(FILE, 'open');
  546. });
  547. form.handlePart(PART);
  548. assert.equal(form._flushing, 1);
  549. var BUFFER;
  550. gently.expect(form, 'pause');
  551. gently.expect(FILE, 'write', function(buffer, cb) {
  552. assert.strictEqual(buffer, BUFFER);
  553. gently.expect(form, 'resume');
  554. // @todo handle cb(new Err)
  555. cb();
  556. });
  557. PART.emit('data', BUFFER = new Buffer('test'));
  558. gently.expect(FILE, 'end', function(cb) {
  559. gently.expect(form, 'emit', function(event, field, file) {
  560. assert.equal(event, 'file');
  561. assert.strictEqual(file, FILE);
  562. });
  563. gently.expect(form, '_maybeEnd');
  564. cb();
  565. assert.equal(form._flushing, 0);
  566. });
  567. PART.emit('end');
  568. })();
  569. });
  570. test(function _uploadPath() {
  571. (function testUniqueId() {
  572. var UUID_A, UUID_B;
  573. gently.expect(GENTLY.hijacked.path, 'join', function(uploadDir, uuid) {
  574. assert.equal(uploadDir, form.uploadDir);
  575. UUID_A = uuid;
  576. });
  577. form._uploadPath();
  578. gently.expect(GENTLY.hijacked.path, 'join', function(uploadDir, uuid) {
  579. UUID_B = uuid;
  580. });
  581. form._uploadPath();
  582. assert.notEqual(UUID_A, UUID_B);
  583. })();
  584. (function testFileExtension() {
  585. form.keepExtensions = true;
  586. var FILENAME = 'foo.jpg',
  587. EXT = '.bar';
  588. gently.expect(GENTLY.hijacked.path, 'extname', function(filename) {
  589. assert.equal(filename, FILENAME);
  590. gently.restore(path, 'extname');
  591. return EXT;
  592. });
  593. gently.expect(GENTLY.hijacked.path, 'join', function(uploadDir, name) {
  594. assert.equal(path.extname(name), EXT);
  595. });
  596. form._uploadPath(FILENAME);
  597. })();
  598. });
  599. test(function _maybeEnd() {
  600. gently.expect(form, 'emit', 0);
  601. form._maybeEnd();
  602. form.ended = true;
  603. form._flushing = 1;
  604. form._maybeEnd();
  605. gently.expect(form, 'emit', function(event) {
  606. assert.equal(event, 'end');
  607. });
  608. form.ended = true;
  609. form._flushing = 0;
  610. form._maybeEnd();
  611. });