Browse files

better testing situation

  • Loading branch information...
1 parent 1a0c00a commit 2bbcb0f8e3b76e5a1dec3c26a35c6e937fb5c51a @andrewrk committed Apr 2, 2013
View
5 .gitignore
@@ -1,4 +1 @@
-/test/tmp/*
-*.upload
-*.un~
-/node_modules/*
+/node_modules
View
70 .jshintrc
@@ -0,0 +1,70 @@
+{
+ // Settings
+ "passfail" : false, // Stop on first error.
+ "maxerr" : 100, // Maximum errors before stopping.
+
+
+ // Predefined globals whom JSHint will ignore.
+ "browser" : false, // Standard browser globals e.g. `window`, `document`.
+
+ "node" : true,
+ "rhino" : false,
+ "couch" : false,
+ "wsh" : false, // Windows Scripting Host.
+
+ "jquery" : false,
+ "prototypejs" : false,
+ "mootools" : false,
+ "dojo" : false,
+
+
+ "predef" : [
+ "describe", "it", "before", "after"
+ ],
+
+ // Development.
+ "debug" : true, // Allow debugger statements e.g. browser breakpoints.
+ "devel" : true, // Allow development statements e.g. `console.log();`.
+
+
+ // EcmaScript 5.
+ "es5" : true, // Allow EcmaScript 5 syntax.
+ "strict" : false, // Require `use strict` pragma in every file.
+ "globalstrict" : true, // Allow global "use strict" (also enables 'strict').
+
+
+ // The Good Parts.
+ "asi" : true, // Tolerate Automatic Semicolon Insertion (no semicolons).
+ "laxbreak" : false, // Tolerate unsafe line breaks e.g. `return [\n] x` without semicolons.
+ "laxcomma" : true,
+ "bitwise" : false, // Prohibit bitwise operators (&, |, ^, etc.).
+ "boss" : true, // Tolerate assignments inside if, for & while. Usually conditions & loops are for comparison, not assignments.
+ "curly" : false, // Require {} for every new block or scope.
+ "eqeqeq" : true, // Require triple equals i.e. `===`.
+ "eqnull" : true, // Tolerate use of `== null`.
+ "evil" : false, // Tolerate use of `eval`.
+ "expr" : false, // Tolerate `ExpressionStatement` as Programs.
+ "forin" : false, // Prohibt `for in` loops without `hasOwnProperty`.
+ "immed" : true, // Require immediate invocations to be wrapped in parens e.g. `( function(){}() );`
+ "latedef" : false, // Prohibit variable use before definition.
+ "loopfunc" : false, // Allow functions to be defined within loops.
+ "noarg" : true, // Prohibit use of `arguments.caller` and `arguments.callee`.
+ "regexp" : false, // Prohibit `.` and `[^...]` in regular expressions.
+ "regexdash" : false, // Tolerate unescaped last dash i.e. `[-...]`.
+ "scripturl" : false, // Tolerate script-targeted URLs.
+ "shadow" : false, // Allows re-define variables later in code e.g. `var x=1; x=2;`.
+ "supernew" : false, // Tolerate `new function () { ... };` and `new Object;`.
+ "undef" : true, // Require all non-global variables be declared before they are used.
+
+
+ // Persone styling prefrences.
+ "newcap" : true, // Require capitalization of all constructor functions e.g. `new F()`.
+ "noempty" : true, // Prohibit use of empty blocks.
+ "nonew" : true, // Prohibit use of constructors for side-effects.
+ "nomen" : false, // Prohibit use of initial or trailing underbars in names.
+ "onevar" : false, // Allow only one `var` statement per function.
+ "plusplus" : false, // Prohibit use of `++` & `--`.
+ "sub" : false, // Tolerate all forms of subscript notation besides dot notation e.g. `dict['key']` instead of `dict.key`.
+ "trailing" : true, // Prohibit trailing whitespaces.
+ "white" : false // Check against strict whitespace and indentation rules.
+}
View
71 benchmark/bench-multipart-parser.js
@@ -1,71 +0,0 @@
-var assert = require('assert');
-require('../test/common');
-var multipartParser = require('../lib/multipart_parser'),
- MultipartParser = multipartParser.MultipartParser,
- parser = new MultipartParser(),
- Buffer = require('buffer').Buffer,
- boundary = '-----------------------------168072824752491622650073',
- mb = 100,
- buffer = createMultipartBuffer(boundary, mb * 1024 * 1024),
- callbacks =
- { partBegin: -1,
- partEnd: -1,
- headerField: -1,
- headerValue: -1,
- partData: -1,
- end: -1,
- };
-
-
-parser.initWithBoundary(boundary);
-parser.onHeaderField = function() {
- callbacks.headerField++;
-};
-
-parser.onHeaderValue = function() {
- callbacks.headerValue++;
-};
-
-parser.onPartBegin = function() {
- callbacks.partBegin++;
-};
-
-parser.onPartData = function() {
- callbacks.partData++;
-};
-
-parser.onPartEnd = function() {
- callbacks.partEnd++;
-};
-
-parser.onEnd = function() {
- callbacks.end++;
-};
-
-var start = +new Date(),
- nparsed = parser.write(buffer),
- duration = +new Date - start,
- mbPerSec = (mb / (duration / 1000)).toFixed(2);
-
-console.log(mbPerSec+' mb/sec');
-
-assert.equal(nparsed, buffer.length);
-
-function createMultipartBuffer(boundary, size) {
- var head =
- '--'+boundary+'\r\n'
- + 'content-disposition: form-data; name="field1"\r\n'
- + '\r\n'
- , tail = '\r\n--'+boundary+'--\r\n'
- , buffer = new Buffer(size);
-
- buffer.write(head, 'ascii', 0);
- buffer.write(tail, 'ascii', buffer.length - tail.length);
- return buffer;
-}
-
-process.on('exit', function() {
- for (var k in callbacks) {
- assert.equal(0, callbacks[k], k+' count off by '+callbacks[k]);
- }
-});
View
2 lib/index.js → index.js
@@ -1,3 +1,3 @@
-var IncomingForm = require('./incoming_form').IncomingForm;
+var IncomingForm = require('./lib/incoming_form').IncomingForm;
IncomingForm.IncomingForm = IncomingForm;
module.exports = IncomingForm;
View
22 lib/incoming_form.js
@@ -4,7 +4,7 @@ var fs = require('fs');
var util = require('util'),
path = require('path'),
File = require('./file'),
- MultipartParser = require('./multipart_parser').MultipartParser,
+ MultipartParser = require('./multipart_parser'),
StringDecoder = require('string_decoder').StringDecoder,
EventEmitter = require('events').EventEmitter,
Stream = require('stream').Stream,
@@ -37,7 +37,7 @@ function IncomingForm(opts) {
this.openedFiles = [];
return this;
-};
+}
util.inherits(IncomingForm, EventEmitter);
exports.IncomingForm = IncomingForm;
@@ -131,12 +131,8 @@ IncomingForm.prototype.write = function(buffer) {
this.bytesReceived += buffer.length;
this.emit('progress', this.bytesReceived, this.bytesExpected);
- var bytesParsed = this._parser.write(buffer);
- if (bytesParsed !== buffer.length) {
- this._error(new Error('parser error, '+bytesParsed+' of '+buffer.length+' bytes parsed'));
- }
-
- return bytesParsed;
+ this._parser.write(buffer);
+ return buffer.length;
};
IncomingForm.prototype.pause = function() {
@@ -252,7 +248,11 @@ IncomingForm.prototype._error = function(err) {
if (Array.isArray(this.openedFiles)) {
this.openedFiles.forEach(function(file) {
file._writeStream.destroy();
- setTimeout(fs.unlink, 0, file.path);
+ process.nextTick(function() {
+ fs.unlink(file.path, function(err) {
+ // this is already an error condition, ignore 2nd error
+ });
+ });
});
}
};
@@ -377,6 +377,10 @@ IncomingForm.prototype._initMultipart = function(boundary) {
self._maybeEnd();
};
+ parser.on('error', function(err) {
+ self._error(err);
+ });
+
this._parser = parser;
};
View
154 lib/multipart_parser.js
@@ -1,3 +1,5 @@
+module.exports = MultipartParser;
+
var PARSER_UNINITIALIZED = 0
, START = 1
, START_BOUNDARY = 2
@@ -23,7 +25,13 @@ var PARSER_UNINITIALIZED = 0
, A = 97
, Z = 122
+ , stream = require('stream')
+ , util = require('util')
+
+util.inherits(MultipartParser, stream.Writable);
function MultipartParser() {
+ stream.Writable.call(this);
+
this.boundary = null;
this.boundaryChars = null;
this.lookbehind = null;
@@ -32,7 +40,6 @@ function MultipartParser() {
this.index = null;
this.flags = 0;
}
-exports.MultipartParser = MultipartParser;
MultipartParser.prototype.initWithBoundary = function(str) {
this.boundary = new Buffer(str.length+4);
@@ -47,85 +54,49 @@ MultipartParser.prototype.initWithBoundary = function(str) {
}
};
-MultipartParser.prototype.write = function(buffer) {
- var self = this,
- i = 0,
- len = buffer.length,
- prevIndex = this.index,
- index = this.index,
- state = this.state,
- flags = this.flags,
- lookbehind = this.lookbehind,
- boundary = this.boundary,
- boundaryChars = this.boundaryChars,
- boundaryLength = this.boundary.length,
- boundaryEnd = boundaryLength - 1,
- bufferLength = buffer.length,
- c,
- cl,
-
- mark = function(name) {
- self[name+'Mark'] = i;
- },
- clear = function(name) {
- delete self[name+'Mark'];
- },
- callback = function(name, buffer, start, end) {
- if (start !== undefined && start === end) {
- return;
- }
-
- var callbackSymbol = 'on'+name.substr(0, 1).toUpperCase()+name.substr(1);
- if (callbackSymbol in self) {
- self[callbackSymbol](buffer, start, end);
- }
- },
- dataCallback = function(name, clear) {
- var markSymbol = name+'Mark';
- if (!(markSymbol in self)) {
- return;
- }
-
- if (!clear) {
- callback(name, buffer, self[markSymbol], buffer.length);
- self[markSymbol] = 0;
- } else {
- callback(name, buffer, self[markSymbol], i);
- delete self[markSymbol];
- }
- };
+MultipartParser.prototype._write = function(buffer, encoding, cb) {
+ var self = this
+ , i = 0
+ , len = buffer.length
+ , prevIndex = this.index
+ , index = this.index
+ , state = this.state
+ , flags = this.flags
+ , lookbehind = this.lookbehind
+ , boundary = this.boundary
+ , boundaryChars = this.boundaryChars
+ , boundaryLength = this.boundary.length
+ , boundaryEnd = boundaryLength - 1
+ , bufferLength = buffer.length
+ , c
+ , cl
for (i = 0; i < len; i++) {
c = buffer[i];
switch (state) {
case PARSER_UNINITIALIZED:
- return i;
+ return cb(new Error("Parser uninitialized"));
case START:
index = 0;
state = START_BOUNDARY;
/* falls through */
case START_BOUNDARY:
- if (index === boundary.length - 2) {
- if (c !== CR) {
- return i;
- }
+ if (index === boundaryLength - 2) {
+ if (c !== CR) return cb(new Error("Expected CR Received " + c));
index++;
break;
- } else if (index - 1 === boundary.length - 2) {
- if (c !== LF) {
- return i;
- }
+ } else if (index === boundaryLength - 1) {
+ if (c !== LF) return cb(new Error("Expected LF Received " + c));
index = 0;
callback('partBegin');
state = HEADER_FIELD_START;
break;
}
- if (c !== boundary[index+2]) {
- index = -2;
- }
if (c === boundary[index+2]) {
index++;
+ } else {
+ index = -2;
}
break;
case HEADER_FIELD_START:
@@ -141,14 +112,13 @@ MultipartParser.prototype.write = function(buffer) {
}
index++;
- if (c === HYPHEN) {
- break;
- }
+ if (c === HYPHEN) break;
if (c === COLON) {
if (index === 1) {
// empty header field
- return i;
+ cb(new Error("Empty header field"));
+ return;
}
dataCallback('headerField', true);
state = HEADER_VALUE_START;
@@ -157,13 +127,11 @@ MultipartParser.prototype.write = function(buffer) {
cl = lower(c);
if (cl < A || cl > Z) {
- return i;
+ cb(new Error("Expected alphabetic character, received " + c));
}
break;
case HEADER_VALUE_START:
- if (c === SPACE) {
- break;
- }
+ if (c === SPACE) break;
mark('headerValue');
state = HEADER_VALUE;
@@ -176,16 +144,11 @@ MultipartParser.prototype.write = function(buffer) {
}
break;
case HEADER_VALUE_ALMOST_DONE:
- if (c !== LF) {
- return i;
- }
+ if (c !== LF) return cb(new Error("Expected LF Received " + c));
state = HEADER_FIELD_START;
break;
case HEADERS_ALMOST_DONE:
- if (c !== LF) {
- return i;
- }
-
+ if (c !== LF) return cb(new Error("Expected LF Received " + c));
callback('headersEnd');
state = PART_DATA_START;
break;
@@ -206,7 +169,7 @@ MultipartParser.prototype.write = function(buffer) {
c = buffer[i];
}
- if (index < boundary.length) {
+ if (index < boundaryLength) {
if (boundary[index] === c) {
if (index === 0) {
dataCallback('partData', true);
@@ -215,7 +178,7 @@ MultipartParser.prototype.write = function(buffer) {
} else {
index = 0;
}
- } else if (index === boundary.length) {
+ } else if (index === boundaryLength) {
index++;
if (c === CR) {
// CR = part boundary
@@ -226,7 +189,7 @@ MultipartParser.prototype.write = function(buffer) {
} else {
index = 0;
}
- } else if (index - 1 === boundary.length) {
+ } else if (index - 1 === boundaryLength) {
if (flags & PART_BOUNDARY) {
index = 0;
if (c === LF) {
@@ -270,7 +233,7 @@ MultipartParser.prototype.write = function(buffer) {
case END:
break;
default:
- return i;
+ cb(new Error("Parser has invalid state."));
}
}
@@ -282,7 +245,38 @@ MultipartParser.prototype.write = function(buffer) {
this.state = state;
this.flags = flags;
- return len;
+ cb();
+
+ function mark(name) {
+ self[name+'Mark'] = i;
+ }
+ function clear(name) {
+ delete self[name+'Mark'];
+ }
+ function callback(name, buffer, start, end) {
+ if (start !== undefined && start === end) {
+ return;
+ }
+
+ var callbackSymbol = 'on'+name.substr(0, 1).toUpperCase()+name.substr(1);
+ if (callbackSymbol in self) {
+ self[callbackSymbol](buffer, start, end);
+ }
+ }
+ function dataCallback(name, clear) {
+ var markSymbol = name+'Mark';
+ if (!(markSymbol in self)) {
+ return;
+ }
+
+ if (!clear) {
+ callback(name, buffer, self[markSymbol], buffer.length);
+ self[markSymbol] = 0;
+ } else {
+ callback(name, buffer, self[markSymbol], i);
+ delete self[markSymbol];
+ }
+ }
};
MultipartParser.prototype.end = function() {
View
35 package.json
@@ -1,33 +1,26 @@
{
"name": "formidable",
- "description": "A node.js module for parsing form data, especially file uploads.",
- "homepage": "https://github.com/felixge/node-formidable",
+ "description": "multipart/form-data parser which supports streaming",
+ "keywords": [
+ "file",
+ "upload",
+ "formidable",
+ "stream",
+ "s3"
+ ],
"version": "1.0.13",
"devDependencies": {
- "gently": "0.8.0",
"findit": "0.1.1",
"hashish": "0.0.4",
- "urun": "~0.0.6",
- "utest": "0.0.3",
- "request": "~2.11.4"
+ "mocha": "~1.8.2",
+ "request": "~2.16.6",
+ "mkdirp": "~0.3.5"
},
- "directories": {
- "lib": "./lib"
- },
- "main": "./lib/index",
+ "main": "index.js",
"scripts": {
- "test": "node test/run.js",
- "clean": "rm test/tmp/*"
+ "test": "mocha --reporter spec --recursive test/test.js"
},
"engines": {
"node": ">=0.8.0"
- },
- "repository": {
- "type": "git",
- "url": "git://github.com/felixge/node-formidable.git"
- },
- "bugs": {
- "url": "http://github.com/felixge/node-formidable/issues"
- },
- "optionalDependencies": {}
+ }
}
View
69 test/bench-multipart-parser.js
@@ -0,0 +1,69 @@
+var assert = require('assert')
+ , MultipartParser = require('../lib/multipart_parser')
+ , parser = new MultipartParser()
+ , boundary = '-----------------------------168072824752491622650073'
+ , mb = 100
+ , buffer = createMultipartBuffer(boundary, mb * 1024 * 1024)
+
+var callbacks = {
+ partBegin: -1,
+ partEnd: -1,
+ headerField: -1,
+ headerValue: -1,
+ partData: -1,
+ end: -1,
+};
+
+
+parser.initWithBoundary(boundary);
+parser.onHeaderField = function() {
+ callbacks.headerField++;
+};
+
+parser.onHeaderValue = function() {
+ callbacks.headerValue++;
+};
+
+parser.onPartBegin = function() {
+ callbacks.partBegin++;
+};
+
+parser.onPartData = function() {
+ callbacks.partData++;
+};
+
+parser.onPartEnd = function() {
+ callbacks.partEnd++;
+};
+
+parser.onEnd = function() {
+ callbacks.end++;
+};
+
+var start = new Date();
+parser.write(buffer, function(err) {
+ var duration = new Date() - start;
+ assert.ifError(err);
+ var mbPerSec = (mb / (duration / 1000)).toFixed(2);
+ console.log(mbPerSec+' mb/sec');
+});
+
+process.on('exit', function() {
+ for (var k in callbacks) {
+ assert.equal(0, callbacks[k], k+' count off by '+callbacks[k]);
+ }
+});
+
+function createMultipartBuffer(boundary, size) {
+ var head =
+ '--'+boundary+'\r\n' +
+ 'content-disposition: form-data; name="field1"\r\n' +
+ '\r\n'
+ , tail = '\r\n--'+boundary+'--\r\n'
+ , buffer = new Buffer(size);
+
+ buffer.write(head, 'ascii', 0);
+ buffer.write(tail, 'ascii', buffer.length - tail.length);
+ return buffer;
+}
+
View
18 test/common.js
@@ -1,18 +0,0 @@
-var path = require('path');
-
-var root = path.join(__dirname, '../');
-exports.dir = {
- root : root,
- lib : root + '/lib',
- fixture : root + '/test/fixture',
- tmp : root + '/test/tmp',
-};
-
-exports.port = 13532;
-
-exports.formidable = require('..');
-exports.assert = require('assert');
-
-exports.require = function(lib) {
- return require(exports.dir.lib + '/' + lib);
-};
View
96 test/integration/test-fixtures.js
@@ -1,96 +0,0 @@
-var hashish = require('hashish');
-var fs = require('fs');
-var findit = require('findit');
-var path = require('path');
-var http = require('http');
-var net = require('net');
-var assert = require('assert');
-
-var common = require('../common');
-var formidable = common.formidable;
-
-var server = http.createServer();
-server.listen(common.port, findFixtures);
-
-function findFixtures() {
- var fixtures = [];
- findit
- .sync(common.dir.fixture + '/js')
- .forEach(function(jsPath) {
- if (!/\.js$/.test(jsPath)) return;
-
- var group = path.basename(jsPath, '.js');
- hashish.forEach(require(jsPath), function(fixture, name) {
- fixtures.push({
- name : group + '/' + name,
- fixture : fixture,
- });
- });
- });
-
- testNext(fixtures);
-}
-
-function testNext(fixtures) {
- var fixture = fixtures.shift();
- if (!fixture) return server.close();
-
- var name = fixture.name;
- var fixture = fixture.fixture;
-
- uploadFixture(name, function(err, parts) {
- if (err) throw err;
-
- fixture.forEach(function(expectedPart, i) {
- var parsedPart = parts[i];
- assert.equal(parsedPart.type, expectedPart.type);
- assert.equal(parsedPart.name, expectedPart.name);
-
- if (parsedPart.type === 'file') {
- var file = parsedPart.value;
- assert.equal(file.name, expectedPart.filename);
- if(expectedPart.sha1) assert.equal(file.hash, expectedPart.sha1);
- }
- });
-
- testNext(fixtures);
- });
-};
-
-function uploadFixture(name, cb) {
- server.once('request', function(req, res) {
- var form = new formidable.IncomingForm();
- form.uploadDir = common.dir.tmp;
- form.hash = "sha1";
- form.parse(req);
-
- function callback() {
- var realCallback = cb;
- cb = function() {};
- realCallback.apply(null, arguments);
- }
-
- var parts = [];
- form
- .on('error', callback)
- .on('fileBegin', function(name, value) {
- parts.push({type: 'file', name: name, value: value});
- })
- .on('field', function(name, value) {
- parts.push({type: 'field', name: name, value: value});
- })
- .on('end', function() {
- res.end('OK');
- callback(null, parts);
- });
- });
-
- var socket = net.createConnection(common.port);
- var file = fs.createReadStream(common.dir.fixture + '/http/' + name);
-
- file.pipe(socket, {end: false});
- socket.on('data', function () {
- socket.end();
- });
-
-}
View
0 tool/record.js → test/record.js
File renamed without changes.
View
1 test/run.js
@@ -1 +0,0 @@
-require('urun')(__dirname)
View
2 test/standalone/test-connection-aborted.js
@@ -1,7 +1,7 @@
var assert = require('assert');
var http = require('http');
var net = require('net');
-var formidable = require('../../lib/index');
+var formidable = require('../../');
var server = http.createServer(function (req, res) {
var form = new formidable.IncomingForm();
View
11 test/standalone/test-content-transfer-encoding.js
@@ -1,11 +1,12 @@
-var assert = require('assert');
-var common = require('../common');
-var formidable = require('../../lib/index');
-var http = require('http');
+var assert = require('assert')
+ , formidable = require('../../')
+ , http = require('http')
+ , path = require('path')
+ , TMP_PATH = path.join(__dirname, '..', 'tmp')
var server = http.createServer(function(req, res) {
var form = new formidable.IncomingForm();
- form.uploadDir = common.dir.tmp;
+ form.uploadDir = TMP_PATH;
form.on('end', function () {
throw new Error('Unexpected "end" event');
});
View
8 test/standalone/test-issue-46.js
@@ -1,5 +1,5 @@
var http = require('http'),
- formidable = require('../../lib/index'),
+ formidable = require('../../'),
request = require('request'),
assert = require('assert');
@@ -15,7 +15,7 @@ var index = [
var server = http.createServer(function(req, res) {
// Show a form for testing purposes.
- if (req.method == 'GET') {
+ if (req.method === 'GET') {
res.writeHead(200, {'content-type': 'text/html'});
res.end(index);
return;
@@ -24,14 +24,14 @@ var server = http.createServer(function(req, res) {
// Parse form and write results to response.
var form = new formidable.IncomingForm();
form.parse(req, function(err, fields, files) {
- res.writeHead(200, {'content-type': 'text/plain'});
+ res.writeHead(200, {'content-type': 'text/plain'});
res.write(JSON.stringify({err: err, fields: fields, files: files}));
res.end();
});
}).listen(0, host, function() {
- console.log("Server up and running...");
+ //console.log("Server up and running...");
var server = this,
url = 'http://' + host + ':' + server.address().port;
View
114 test/test.js
@@ -0,0 +1,114 @@
+var spawn = require('child_process').spawn
+ , findit = require('findit')
+ , path = require('path')
+ , hashish = require('hashish')
+ , fs = require('fs')
+ , http = require('http')
+ , net = require('net')
+ , assert = require('assert')
+ , formidable = require('../')
+ , mkdirp = require('mkdirp')
+ , STANDALONE_PATH = path.join(__dirname, 'standalone')
+ , server = http.createServer()
+ , PORT = 13532
+ , FIXTURE_PATH = path.join(__dirname, 'fixture')
+ , TMP_PATH = path.join(__dirname, 'tmp')
+
+mkdirp.sync(TMP_PATH);
+
+describe("fixtures", function() {
+ before(function(done) {
+ server.listen(PORT, done);
+ });
+ var fixtures = [];
+ findit
+ .sync(path.join(FIXTURE_PATH, 'js'))
+ .forEach(function(jsPath) {
+ if (!/\.js$/.test(jsPath)) return;
+ var group = path.basename(jsPath, '.js');
+ hashish.forEach(require(jsPath), function(fixture, name) {
+ it(group + '/' + name, createTest({
+ name : group + '/' + name,
+ fixture : fixture,
+ }));
+ });
+ });
+});
+
+describe("standalone", function() {
+ findit
+ .sync(STANDALONE_PATH)
+ .forEach(function(jsPath) {
+ if (!/\.js$/.test(jsPath)) return;
+ it(path.basename(jsPath, '.js'), function(done) {
+ var child = spawn(process.execPath, [jsPath], { stdio: 'inherit' });
+ child.on('error', function(err) {
+ done(err);
+ });
+ child.on('exit', function(code) {
+ if (code) return done(new Error("exited with code " + code));
+ done();
+ });
+ });
+ });
+});
+
+function createTest(fixture) {
+ var name = fixture.name;
+ fixture = fixture.fixture;
+ return function(done) {
+ uploadFixture(name, function(err, parts) {
+ if (err) return done(err);
+ fixture.forEach(function(expectedPart, i) {
+ var parsedPart = parts[i];
+ assert.equal(parsedPart.type, expectedPart.type);
+ assert.equal(parsedPart.name, expectedPart.name);
+
+ if (parsedPart.type === 'file') {
+ var file = parsedPart.value;
+ assert.equal(file.name, expectedPart.filename);
+ if(expectedPart.sha1) assert.equal(file.hash, expectedPart.sha1);
+ }
+ });
+ done();
+ });
+ };
+
+}
+
+function uploadFixture(name, cb) {
+ server.once('request', function(req, res) {
+ var parts = [];
+ var form = new formidable.IncomingForm();
+ form.uploadDir = TMP_PATH;
+ form.hash = "sha1";
+
+ form
+ .on('error', callback)
+ .on('fileBegin', function(name, value) {
+ parts.push({type: 'file', name: name, value: value});
+ })
+ .on('field', function(name, value) {
+ parts.push({type: 'field', name: name, value: value});
+ })
+ .on('end', function() {
+ res.end('OK');
+ callback(null, parts);
+ });
+ form.parse(req);
+
+ function callback() {
+ var realCallback = cb;
+ cb = function() {};
+ realCallback.apply(null, arguments);
+ }
+ });
+
+ var socket = net.createConnection(PORT);
+ var file = fs.createReadStream(FIXTURE_PATH + '/http/' + name);
+
+ file.pipe(socket, {end: false});
+ socket.on('data', function () {
+ socket.end();
+ });
+}
View
0 test/tmp/.empty
No changes.
View
67 test/tools/base64.html
@@ -1,67 +0,0 @@
-<html>
-<head>
- <title>Convert a file to a base64 request</title>
-
-<script type="text/javascript">
-
-function form_submit(e){
- console.log(e)
-
- var resultOutput = document.getElementById('resultOutput');
- var fileInput = document.getElementById('fileInput');
- var fieldInput = document.getElementById('fieldInput');
-
- makeRequestBase64(fileInput.files[0], fieldInput.value, function(err, result){
- resultOutput.value = result;
- });
-
- return false;
-}
-
-function makeRequestBase64(file, fieldName, cb){
- var boundary = '\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/';
- var crlf = "\r\n";
-
- var reader = new FileReader();
- reader.onload = function(e){
- var body = '';
-
- body += '--' + boundary + crlf;
- body += 'Content-Disposition: form-data; name="' + fieldName + '"; filename="' + escape(file.name)+ '"' + crlf;
- body += 'Content-Type: ' + file.type + '' + crlf;
- body += 'Content-Transfer-Encoding: base64' + crlf
- body += crlf;
- body += e.target.result.substring(e.target.result.indexOf(',') + 1) + crlf;
-
- body += '--' + boundary + '--';
-
- var head = '';
- head += 'POST /upload HTTP/1.1' + crlf;
- head += 'Host: localhost:8080' + crlf;
- head += 'Content-Type: multipart/form-data; boundary=' + boundary + '' + crlf;
- head += 'Content-Length: ' + body.length + '' + crlf;
-
- cb(null, head + crlf + body);
- };
-
- reader.readAsDataURL(file);
-}
-
-</script>
-
-</head>
-
-<body>
-
-<form action="" onsubmit="return form_submit();">
- <label>File: <input id="fileInput" type="file" /></label><br />
- <label>Field: <input id="fieldInput" type="text" value="file" /></label><br />
- <button type="submit">Ok!</button><br />
- <label>Request: <textarea id="resultOutput" readonly="readonly" rows="20" cols="80"></textarea></label><br />
-</form>
-<p>
-Don't forget to save the output with windows (CRLF) line endings!
-</p>
-
-</body>
-</html>
View
33 test/unit/test-file.js
@@ -1,33 +0,0 @@
-var common = require('../common');
-var test = require('utest');
-var assert = common.assert;
-var File = common.require('file');
-
-var file;
-var now = new Date;
-test('IncomingForm', {
- before: function() {
- file = new File({
- size: 1024,
- path: '/tmp/cat.png',
- name: 'cat.png',
- type: 'image/png',
- lastModifiedDate: now,
- filename: 'cat.png',
- mime: 'image/png'
- })
- },
-
- '#toJSON()': function() {
- var obj = file.toJSON();
- var len = Object.keys(obj).length;
- assert.equal(1024, obj.size);
- assert.equal('/tmp/cat.png', obj.path);
- assert.equal('cat.png', obj.name);
- assert.equal('image/png', obj.type);
- assert.equal('image/png', obj.mime);
- assert.equal('cat.png', obj.filename);
- assert.equal(now, obj.mtime);
- assert.equal(len, 8);
- }
-});
View
63 test/unit/test-incoming-form.js
@@ -1,63 +0,0 @@
-var common = require('../common');
-var test = require('utest');
-var assert = common.assert;
-var IncomingForm = common.require('incoming_form').IncomingForm;
-var path = require('path');
-
-var form;
-test('IncomingForm', {
- before: function() {
- form = new IncomingForm();
- },
-
- '#_fileName with regular characters': function() {
- var filename = 'foo.txt';
- assert.equal(form._fileName(makeHeader(filename)), 'foo.txt');
- },
-
- '#_fileName with unescaped quote': function() {
- var filename = 'my".txt';
- assert.equal(form._fileName(makeHeader(filename)), 'my".txt');
- },
-
- '#_fileName with escaped quote': function() {
- var filename = 'my%22.txt';
- assert.equal(form._fileName(makeHeader(filename)), 'my".txt');
- },
-
- '#_fileName with bad quote and additional sub-header': function() {
- var filename = 'my".txt';
- var header = makeHeader(filename) + '; foo="bar"';
- assert.equal(form._fileName(header), filename);
- },
-
- '#_fileName with semicolon': function() {
- var filename = 'my;.txt';
- assert.equal(form._fileName(makeHeader(filename)), 'my;.txt');
- },
-
- '#_fileName with utf8 character': function() {
- var filename = 'my&#9731;.txt';
- assert.equal(form._fileName(makeHeader(filename)), 'my☃.txt');
- },
-
- '#_uploadPath strips harmful characters from extension when keepExtensions': function() {
- form.keepExtensions = true;
-
- var ext = path.extname(form._uploadPath('fine.jpg?foo=bar'));
- assert.equal(ext, '.jpg');
-
- var ext = path.extname(form._uploadPath('fine?foo=bar'));
- assert.equal(ext, '');
-
- var ext = path.extname(form._uploadPath('super.cr2+dsad'));
- assert.equal(ext, '.cr2');
-
- var ext = path.extname(form._uploadPath('super.bar'));
- assert.equal(ext, '.bar');
- },
-});
-
-function makeHeader(filename) {
- return 'Content-Disposition: form-data; name="upload"; filename="' + filename + '"';
-}

0 comments on commit 2bbcb0f

Please sign in to comment.