[Pkg-javascript-commits] [node-multiparty] 02/05: Imported Upstream version 4.1.2

Andrew Kelley andrewrk-guest at moszumanska.debian.org
Sat May 16 17:30:49 UTC 2015


This is an automated email from the git hooks/post-receive script.

andrewrk-guest pushed a commit to branch master
in repository node-multiparty.

commit 9b66bc1409df6e72fd9a83dd868b4dc7d3456271
Author: Andrew Kelley <superjoe30 at gmail.com>
Date:   Sat May 16 17:26:41 2015 +0000

    Imported Upstream version 4.1.2
---
 .gitignore                                         |    4 +-
 .npmignore                                         |    4 +
 .travis.yml                                        |    6 +
 CHANGELOG.md                                       |   20 +
 README.md                                          |   20 +-
 examples/azureblobstorage.js                       |    2 +-
 examples/s3.js                                     |    4 -
 index.js                                           |   96 +-
 package.json                                       |   15 +-
 .../http/{no-filename => filename}/empty.http      |    0
 .../{no-filename => filename}/filename-name.http   |    0
 .../http/{no-filename => filename}/generic.http    |    0
 .../filename-name.http => filename/quotes.http}    |    4 +-
 test/fixture/js/{no-filename.js => filename.js}    |    5 +
 test/standalone/test-chunked.js                    |   43 -
 test/standalone/test-connection-aborted-closed.js  |   44 -
 test/standalone/test-connection-aborted.js         |   30 -
 test/standalone/test-content-transfer-encoding.js  |   52 -
 test/standalone/test-emit-order.js                 |   61 -
 test/standalone/test-epilogue-last-chunk.js        |   44 -
 test/standalone/test-error-listen-after-parse.js   |   20 -
 test/standalone/test-error-unpipe.js               |   43 -
 test/standalone/test-invalid.js                    |   35 -
 test/standalone/test-issue-15.js                   |   76 --
 test/standalone/test-issue-19.js                   |   44 -
 test/standalone/test-issue-21.js                   |   85 --
 test/standalone/test-issue-32.js                   |   38 -
 test/standalone/test-issue-36.js                   |   38 -
 test/standalone/test-issue-4.js                    |   53 -
 test/standalone/test-max-fields.js                 |   52 -
 test/standalone/test-max-files-size-exact.js       |   42 -
 test/standalone/test-max-files-size.js             |   50 -
 test/standalone/test-missing-boundary-end.js       |   46 -
 test/standalone/test-parse-type-error.js           |   39 -
 test/standalone/test-req-encoding.js               |   39 -
 test/standalone/test-stream-error.js               |   36 -
 test/test.js                                       | 1284 +++++++++++++++++++-
 37 files changed, 1372 insertions(+), 1102 deletions(-)

diff --git a/.gitignore b/.gitignore
index 07e6e47..4b173c6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,3 @@
-/node_modules
+node_modules/
+coverage/
+npm-debug.log
diff --git a/.npmignore b/.npmignore
index d457948..bc1e710 100644
--- a/.npmignore
+++ b/.npmignore
@@ -1,2 +1,6 @@
+coverage/
 test/ 
 examples/
+.jshintrc
+.travis.yml
+npm-debug.log
diff --git a/.travis.yml b/.travis.yml
index 6e5919d..da616f8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,3 +1,9 @@
 language: node_js
 node_js:
   - "0.10"
+  - "0.12"
+sudo: false
+script:
+  - "npm run test-travis"
+after_script:
+  - "npm install coveralls at 2 && cat ./coverage/lcov.info | ./node_modules/.bin/coveralls"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index de6139c..b3d0414 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,23 @@
+### 4.1.2
+
+ * Douglas Christopher Wilson:
+   - Do not emit error on part prior to emitting part
+   - Fix filename with quotes truncating from certain clients
+
+### 4.1.1
+
+ * Douglas Christopher Wilson:
+   - Do not clobber existing temporary files
+
+### 4.1.0
+
+ * Douglas Christopher Wilson:
+   - Update dependencies to latest
+   - HTTP-related errors have a `statusCode` field
+
+ * Andrew Kelley:
+   - Refactor tests so that we can have a coverage badge
+
 ### 4.0.0
 
  * Andrew Kelley:
diff --git a/README.md b/README.md
index f398ffb..02551f6 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# multiparty [![Build Status](https://travis-ci.org/andrewrk/node-multiparty.svg?branch=master)](https://travis-ci.org/andrewrk/node-multiparty) [![NPM version](https://badge.fury.io/js/multiparty.svg)](http://badge.fury.io/js/multiparty)
+# multiparty [![Build Status](https://travis-ci.org/andrewrk/node-multiparty.svg?branch=master)](https://travis-ci.org/andrewrk/node-multiparty) [![Coverage Status](https://img.shields.io/coveralls/andrewrk/node-multiparty.svg)](https://coveralls.io/r/andrewrk/node-multiparty)
 
 Parse http requests with content-type `multipart/form-data`, also known as file uploads.
 
@@ -31,9 +31,9 @@ npm install multiparty
 Parse an incoming `multipart/form-data` request.
 
 ```js
-var multiparty = require('multiparty')
-  , http = require('http')
-  , util = require('util')
+var multiparty = require('multiparty');
+var http = require('http');
+var util = require('util');
 
 http.createServer(function(req, res) {
   if (req.url === '/upload' && req.method === 'POST') {
@@ -110,15 +110,15 @@ form.on('part', function(part) {
   // You *must* act on the part by reading it
   // NOTE: if you want to ignore it, just call "part.resume()"
 
-  if (part.filename === null) {
-    // filename is "null" when this is a field and not a file
+  if (!part.filename) {
+    // filename is not defined when this is a field and not a file
     console.log('got field named ' + part.name);
     // ignore field's content
     part.resume();
   }
 
-  if (part.filename !== null) {
-    // filename is not "null" when this is a file
+  if (part.filename) {
+    // filename is defined when this is a file
     count++;
     console.log('got file named ' + part.name);
     // ignore file's content here
@@ -188,6 +188,10 @@ multipart requests!
 Only one 'error' event can ever be emitted, and if an 'error' event is
 emitted, then 'close' will not be emitted.
 
+If the error would correspond to a certain HTTP response code, the `err` object
+will have a `statusCode` property with the value of the suggested HTTP response
+code to send back.
+
 Note that an 'error' event will be emitted both from the `form` and from the
 current `part`.
 
diff --git a/examples/azureblobstorage.js b/examples/azureblobstorage.js
index 273c332..3dcb86a 100644
--- a/examples/azureblobstorage.js
+++ b/examples/azureblobstorage.js
@@ -21,7 +21,7 @@ var server = http.createServer(function(req, res) {
     form.on('part', function(part) {
 	    if (!part.filename) return;
 		
-		var size = part.byteCount - part.byteOffset;
+		var size = part.byteCount;
 		var name = part.filename;
 		var container = 'blobContainerName';
 		
diff --git a/examples/s3.js b/examples/s3.js
index a3b011d..d2b766d 100644
--- a/examples/s3.js
+++ b/examples/s3.js
@@ -56,10 +56,6 @@ var server = http.createServer(function(req, res) {
     res.writeHead(404, {'content-type': 'text/plain'});
     res.end('404');
   }
-
-  function onEnd() {
-    throw new Error("no uploaded file");
-  }
 });
 server.listen(PORT, function() {
   console.info('listening on http://0.0.0.0:'+PORT+'/');
diff --git a/index.js b/index.js
index 88fc224..ea28502 100644
--- a/index.js
+++ b/index.js
@@ -5,7 +5,7 @@ var crypto = require('crypto');
 var path = require('path');
 var os = require('os');
 var StringDecoder = require('string_decoder').StringDecoder;
-var FdSlicer = require('fd-slicer');
+var fdSlicer = require('fd-slicer');
 
 var START = 0;
 var START_BOUNDARY = 1;
@@ -151,13 +151,13 @@ Form.prototype.parse = function(req, cb) {
 
   var contentType = req.headers['content-type'];
   if (!contentType) {
-    validationError(new Error('missing content-type header'));
+    validationError(createError(415, 'missing content-type header'));
     return;
   }
 
   var m = CONTENT_TYPE_RE.exec(contentType);
   if (!m) {
-    validationError(new Error('unrecognized content-type: ' + contentType));
+    validationError(createError(415, 'unsupported content-type'));
     return;
   }
 
@@ -170,7 +170,7 @@ Form.prototype.parse = function(req, cb) {
   }
 
   if (!boundary) {
-    validationError(new Error('content-type missing boundary: ' + require('util').inspect(m)));
+    validationError(createError(400, 'content-type missing boundary'));
     return;
   }
 
@@ -194,7 +194,7 @@ Form.prototype.parse = function(req, cb) {
       req.removeListener('aborted', onReqAborted);
       req.removeListener('end', onReqEnd);
       if (self.destStream) {
-        self.destStream.emit('error', err);
+        errorEventQueue(self, self.destStream, err);
       }
     }
 
@@ -242,11 +242,11 @@ Form.prototype._write = function(buffer, encoding, cb) {
           state = CLOSE_BOUNDARY;
           break;
         } else if (index === boundaryLength - 2) {
-          if (c !== CR) return self.handleError(new Error("Expected CR Received " + c));
+          if (c !== CR) return self.handleError(createError(400, 'Expected CR Received ' + c));
           index++;
           break;
         } else if (index === boundaryLength - 1) {
-          if (c !== LF) return self.handleError(new Error("Expected LF Received " + c));
+          if (c !== LF) return self.handleError(createError(400, 'Expected LF Received ' + c));
           index = 0;
           self.onParsePartBegin();
           state = HEADER_FIELD_START;
@@ -274,7 +274,7 @@ Form.prototype._write = function(buffer, encoding, cb) {
         if (c === COLON) {
           if (index === 1) {
             // empty header field
-            self.handleError(new Error("Empty header field"));
+            self.handleError(createError(400, 'Empty header field'));
             return;
           }
           self.onParseHeaderField(buffer.slice(self.headerFieldMark, i));
@@ -285,7 +285,7 @@ Form.prototype._write = function(buffer, encoding, cb) {
 
         cl = lower(c);
         if (cl < A || cl > Z) {
-          self.handleError(new Error("Expected alphabetic character, received " + c));
+          self.handleError(createError(400, 'Expected alphabetic character, received ' + c));
           return;
         }
         break;
@@ -304,11 +304,11 @@ Form.prototype._write = function(buffer, encoding, cb) {
         }
         break;
       case HEADER_VALUE_ALMOST_DONE:
-        if (c !== LF) return self.handleError(new Error("Expected LF Received " + c));
+        if (c !== LF) return self.handleError(createError(400, 'Expected LF Received ' + c));
         state = HEADER_FIELD_START;
         break;
       case HEADERS_ALMOST_DONE:
-        if (c !== LF) return self.handleError(new Error("Expected LF Received " + c));
+        if (c !== LF) return self.handleError(createError(400, 'Expected LF Received ' + c));
         var err = self.onParseHeadersEnd(i + 1);
         if (err) return self.handleError(err);
         state = PART_DATA_START;
@@ -385,7 +385,7 @@ Form.prototype._write = function(buffer, encoding, cb) {
 
         break;
       case CLOSE_BOUNDARY:
-        if (c !== HYPHEN) return self.handleError(new Error("Expected HYPHEN Received " + c));
+        if (c !== HYPHEN) return self.handleError(createError(400, 'Expected HYPHEN Received ' + c));
         if (index === 1) {
           self.onParsePartEnd();
           state = END;
@@ -490,12 +490,12 @@ Form.prototype.onParseHeadersEnd = function(offset) {
 
     case 'base64': break;
     default:
-    return new Error("unknown transfer-encoding: " + self.partTransferEncoding);
+    return createError(400, 'unknown transfer-encoding: ' + self.partTransferEncoding);
   }
 
   self.totalFieldCount += 1;
   if (self.totalFieldCount > self.maxFields) {
-    return new Error("maxFields " + self.maxFields + " exceeded.");
+    return createError(413, 'maxFields ' + self.maxFields + ' exceeded.');
   }
 
   self.destStream = new stream.PassThrough();
@@ -587,24 +587,47 @@ function cleanupOpenFiles(self) {
   self.openedFiles = [];
 }
 
-function holdEmitQueue(self) {
-  var o = {cb: null};
-  self.emitQueue.push(o);
+function holdEmitQueue(self, eventEmitter) {
+  var item = {cb: null, ee: eventEmitter, err: null};
+  self.emitQueue.push(item);
   return function(cb) {
-    o.cb = cb;
+    item.cb = cb;
     flushEmitQueue(self);
   };
 }
 
+function errorEventQueue(self, eventEmitter, err) {
+  var items = self.emitQueue.filter(function (item) {
+    return item.ee === eventEmitter;
+  });
+
+  if (items.length === 0) {
+    eventEmitter.emit('error', err);
+    return;
+  }
+
+  items.forEach(function (item) {
+    item.err = err;
+  });
+}
+
 function flushEmitQueue(self) {
   while (self.emitQueue.length > 0 && self.emitQueue[0].cb) {
-    self.emitQueue.shift().cb();
+    var item = self.emitQueue.shift();
+
+    // invoke the callback
+    item.cb();
+
+    if (item.err) {
+      // emit the delayed error
+      item.ee.emit('error', item.err);
+    }
   }
 }
 
 function handlePart(self, partStream) {
   beginFlush(self);
-  var emitAndReleaseHold = holdEmitQueue(self);
+  var emitAndReleaseHold = holdEmitQueue(self, partStream);
   partStream.on('end', function() {
     endFlush(self);
   });
@@ -627,17 +650,17 @@ function handleFile(self, fileStream) {
     ws: null,
   };
   beginFlush(self); // flush to write stream
-  var emitAndReleaseHold = holdEmitQueue(self);
+  var emitAndReleaseHold = holdEmitQueue(self, fileStream);
   fileStream.on('error', function(err) {
     self.handleError(err);
   });
-  fs.open(publicFile.path, 'w', function(err, fd) {
+  fs.open(publicFile.path, 'wx', function(err, fd) {
     if (err) return self.handleError(err);
-    var fdSlicer = new FdSlicer(fd, {autoClose: true});
+    var slicer = fdSlicer.createFromFd(fd, {autoClose: true});
 
     // end option here guarantees that no more than that amount will be written
     // or else an error will be emitted
-    internalFile.ws = fdSlicer.createWriteStream({end: self.maxFilesSize - self.totalFileSize});
+    internalFile.ws = slicer.createWriteStream({end: self.maxFilesSize - self.totalFileSize});
 
     // if an error ocurred while we were waiting for fs.open we handle that
     // cleanup now
@@ -646,6 +669,10 @@ function handleFile(self, fileStream) {
 
     var prevByteCount = 0;
     internalFile.ws.on('error', function(err) {
+      if (err.code === 'ETOOBIG') {
+        err = createError(413, err.message);
+        err.code = 'ETOOBIG';
+      }
       self.handleError(err);
     });
     internalFile.ws.on('progress', function() {
@@ -654,7 +681,7 @@ function handleFile(self, fileStream) {
       self.totalFileSize += delta;
       prevByteCount = publicFile.size;
     });
-    fdSlicer.on('close', function() {
+    slicer.on('close', function() {
       if (self.error) return;
       emitAndReleaseHold(function() {
         self.emit('file', fileStream.name, publicFile);
@@ -670,7 +697,7 @@ function handleField(self, fieldStream) {
   var decoder = new StringDecoder(self.encoding);
 
   beginFlush(self);
-  var emitAndReleaseHold = holdEmitQueue(self);
+  var emitAndReleaseHold = holdEmitQueue(self, fieldStream);
   fieldStream.on('error', function(err) {
     self.handleError(err);
   });
@@ -680,7 +707,7 @@ function handleField(self, fieldStream) {
 
     self.totalFieldSize += buffer.length;
     if (self.totalFieldSize > self.maxFieldsSize) {
-      self.handleError(new Error("maxFieldsSize " + self.maxFieldsSize + " exceeded"));
+      self.handleError(createError(413, 'maxFieldsSize ' + self.maxFieldsSize + ' exceeded'));
       return;
     }
     value += decoder.write(buffer);
@@ -724,7 +751,7 @@ function setUpParser(self, boundary) {
   beginFlush(self);
   self.on('finish', function() {
     if (self.state !== END) {
-      self.handleError(new Error('stream ended unexpectedly'));
+      self.handleError(createError(400, 'stream ended unexpectedly'));
     }
     endFlush(self);
   });
@@ -762,15 +789,22 @@ function parseFilename(headerValue) {
     }
   }
 
-  var filename = m[1].substr(m[1].lastIndexOf('\\') + 1);
-  filename = filename.replace(/%22/g, '"');
+  var filename = m[1];
+  filename = filename.replace(/%22|\\"/g, '"');
   filename = filename.replace(/&#([\d]{4});/g, function(m, code) {
     return String.fromCharCode(code);
   });
-  return filename;
+  return filename.substr(filename.lastIndexOf('\\') + 1);
 }
 
 function lower(c) {
   return c | 0x20;
 }
 
+function createError(status, message) {
+  var error = new Error(message);
+  Error.captureStackTrace(error, createError);
+  error.status = status;
+  error.statusCode = status;
+  return error;
+}
diff --git a/package.json b/package.json
index 58a6498..b32bc9c 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "multiparty",
-  "version": "4.0.0",
+  "version": "4.1.2",
   "description": "multipart/form-data parser which supports streaming",
   "repository": {
     "type": "git",
@@ -14,21 +14,24 @@
     "s3"
   ],
   "devDependencies": {
+    "findit2": "~2.2.3",
+    "istanbul": "~0.3.4",
     "mkdirp": "~0.5.0",
-    "pend": "~1.1.3",
+    "pend": "~1.2.0",
     "rimraf": "~2.2.8",
-    "superagent": "~0.20.0",
-    "findit2": "~2.2.2"
+    "superagent": "~0.21.0"
   },
   "scripts": {
-    "test": "node test/test.js"
+    "test": "node test/test.js",
+    "test-cov": "istanbul cover test/test.js",
+    "test-travis": "istanbul cover test/test.js --report lcovonly"
   },
   "engines": {
     "node": ">=0.10.0"
   },
   "license": "MIT",
   "dependencies": {
-    "fd-slicer": "~0.3.2"
+    "fd-slicer": "~1.0.0"
   },
   "bugs": {
     "url": "https://github.com/andrewrk/node-multiparty/issues"
diff --git a/test/fixture/http/no-filename/empty.http b/test/fixture/http/filename/empty.http
similarity index 100%
rename from test/fixture/http/no-filename/empty.http
rename to test/fixture/http/filename/empty.http
diff --git a/test/fixture/http/no-filename/filename-name.http b/test/fixture/http/filename/filename-name.http
similarity index 100%
copy from test/fixture/http/no-filename/filename-name.http
copy to test/fixture/http/filename/filename-name.http
diff --git a/test/fixture/http/no-filename/generic.http b/test/fixture/http/filename/generic.http
similarity index 100%
rename from test/fixture/http/no-filename/generic.http
rename to test/fixture/http/filename/generic.http
diff --git a/test/fixture/http/no-filename/filename-name.http b/test/fixture/http/filename/quotes.http
similarity index 72%
rename from test/fixture/http/no-filename/filename-name.http
rename to test/fixture/http/filename/quotes.http
index 65261bd..5908f6d 100644
--- a/test/fixture/http/no-filename/filename-name.http
+++ b/test/fixture/http/filename/quotes.http
@@ -1,10 +1,10 @@
 POST /upload HTTP/1.1
 Host: localhost:8080
 Content-Type: multipart/form-data; boundary=----WebKitFormBoundarytyE4wkKlZ5CQJVTG
-Content-Length: 209
+Content-Length: 211
 
 ------WebKitFormBoundarytyE4wkKlZ5CQJVTG
-Content-Disposition: form-data; filename="plain.txt"; name="upload"
+Content-Disposition: form-data; name="upload"; filename="foo \"bar\""
 Content-Type: text/plain
 
 I am a plain text file
diff --git a/test/fixture/js/no-filename.js b/test/fixture/js/filename.js
similarity index 68%
rename from test/fixture/js/no-filename.js
rename to test/fixture/js/filename.js
index 556710b..b37f667 100644
--- a/test/fixture/js/no-filename.js
+++ b/test/fixture/js/filename.js
@@ -10,3 +10,8 @@ module.exports['filename-name.http'] = [
   {type: 'file', name: 'upload', filename: 'plain.txt', fixture: 'plain.txt',
   sha1: 'b31d07bac24ac32734de88b3687dddb10e976872'},
 ];
+
+module.exports['quotes.http'] = [
+  {type: 'file', name: 'upload', filename: 'foo "bar"', fixture: 'plain.txt',
+  sha1: 'b31d07bac24ac32734de88b3687dddb10e976872'},
+];
diff --git a/test/standalone/test-chunked.js b/test/standalone/test-chunked.js
deleted file mode 100644
index b2eda3f..0000000
--- a/test/standalone/test-chunked.js
+++ /dev/null
@@ -1,43 +0,0 @@
-var multiparty = require('../../')
-  , assert = require('assert')
-  , http = require('http')
-  , net = require('net');
-
-var server = http.createServer(function(req, resp) {
-  var form = new multiparty.Form();
-
-  var partCount = 0;
-  form.on('part', function(part) {
-    part.resume();
-    partCount++;
-    assert.strictEqual(typeof part.byteCount, 'undefined');
-  });
-  form.on('close', function() {
-    assert.strictEqual(partCount, 1);
-    resp.end();
-  });
-
-  form.parse(req);
-});
-server.listen(function() {
-  var socket = net.connect(server.address().port, 'localhost', function () {
-    socket.write('POST / HTTP/1.1\r\n');
-    socket.write('Host: localhost\r\n');
-    socket.write('Connection: close\r\n');
-    socket.write('Content-Type: multipart/form-data; boundary=foo\r\n');
-    socket.write('Transfer-Encoding: chunked\r\n');
-    socket.write('\r\n');
-    socket.write('7\r\n');
-    socket.write('--foo\r\n\r\n');
-    socket.write('43\r\n');
-    socket.write('Content-Disposition: form-data; name="file"; filename="plain.txt"\r\n\r\n');
-    socket.write('12\r\n');
-    socket.write('\r\nsome text here\r\n\r\n');
-    socket.write('9\r\n');
-    socket.write('--foo--\r\n\r\n');
-    socket.write('0\r\n\r\n');
-    socket.on('close', function () {
-      server.close();
-    });
-  });
-});
diff --git a/test/standalone/test-connection-aborted-closed.js b/test/standalone/test-connection-aborted-closed.js
deleted file mode 100644
index 1c3bc2c..0000000
--- a/test/standalone/test-connection-aborted-closed.js
+++ /dev/null
@@ -1,44 +0,0 @@
-var assert = require('assert');
-var http = require('http');
-var net = require('net');
-var multiparty = require('../../');
-
-var socket;
-var server = http.createServer(function (req, res) {
-  var called = false;
-  var form = new multiparty.Form();
-
-  form.parse(req, function (err, fields, files) {
-    assert.ok(!called);
-    called = true;
-
-    assert.ifError(err);
-    assert.equal(Object.keys(fields).length, 1);
-    socket.end();
-  });
-});
-
-server.listen(0, 'localhost', function () {
-  socket = net.connect(server.address().port, 'localhost', function () {
-    socket.write('POST / HTTP/1.1\r\n');
-    socket.write('Host: localhost\r\n');
-    socket.write('Connection: close\r\n');
-    socket.write('Content-Type: multipart/form-data; boundary=foo\r\n');
-    socket.write('Transfer-Encoding: chunked\r\n');
-    socket.write('\r\n');
-    socket.write('7\r\n');
-    socket.write('--foo\r\n\r\n');
-    socket.write('2D\r\n');
-    socket.write('Content-Disposition: form-data; name="data"\r\n\r\n');
-    socket.write('12\r\n');
-    socket.write('\r\nsome text here\r\n\r\n');
-    socket.write('7\r\n');
-    socket.write('--foo--\r\n');
-    socket.write('2\r\n');
-    socket.write('\r\n\r\n');
-    socket.write('0\r\n\r\n');
-    socket.on('close', function () {
-      server.close();
-    });
-  });
-});
diff --git a/test/standalone/test-connection-aborted.js b/test/standalone/test-connection-aborted.js
deleted file mode 100644
index 6448e79..0000000
--- a/test/standalone/test-connection-aborted.js
+++ /dev/null
@@ -1,30 +0,0 @@
-var assert = require('assert');
-var http = require('http');
-var net = require('net');
-var multiparty = require('../../');
-
-var server = http.createServer(function (req, res) {
-  var form = new multiparty.Form();
-  var aborted_received = false;
-  form.on('aborted', function () {
-    aborted_received = true;
-  });
-  form.on('error', function () {
-    assert(aborted_received, 'Error event should follow aborted');
-    server.close();
-  });
-  form.on('end', function () {
-    throw new Error('Unexpected "end" event');
-  });
-  form.on('close', function () {
-    throw new Error('Unexpected "close" event');
-  });
-  form.parse(req);
-}).listen(0, 'localhost', function () {
-  var client = net.connect(server.address().port);
-  client.write(
-    "POST / HTTP/1.1\r\n" +
-    "Content-Length: 70\r\n" +
-    "Content-Type: multipart/form-data; boundary=foo\r\n\r\n");
-  client.end();
-});
diff --git a/test/standalone/test-content-transfer-encoding.js b/test/standalone/test-content-transfer-encoding.js
deleted file mode 100644
index 35e5a1f..0000000
--- a/test/standalone/test-content-transfer-encoding.js
+++ /dev/null
@@ -1,52 +0,0 @@
-var assert = require('assert')
-  , multiparty = require('../../')
-  , http = require('http')
-  , path = require('path')
-  , TMP_PATH = path.join(__dirname, '..', 'tmp')
-
-var server = http.createServer(function(req, res) {
-  var form = new multiparty.Form();
-  form.uploadDir = TMP_PATH;
-  form.on('close', function () {
-    throw new Error('Unexpected "close" event');
-  });
-  form.on('end', function () {
-    throw new Error('Unexpected "end" event');
-  });
-  form.on('error', function (e) {
-    res.writeHead(500);
-    res.end(e.message);
-  });
-  form.parse(req);
-});
-
-server.listen(0, function() {
-  var body =
-    '--foo\r\n' +
-    'Content-Disposition: form-data; name="file1"; filename="file1"\r\n' +
-    'Content-Type: application/octet-stream\r\n' +
-    '\r\nThis is the first file\r\n' +
-    '--foo\r\n' +
-    'Content-Type: application/octet-stream\r\n' +
-    'Content-Disposition: form-data; name="file2"; filename="file2"\r\n' +
-    'Content-Transfer-Encoding: unknown\r\n' +
-    '\r\nThis is the second file\r\n' +
-    '--foo--\r\n';
-
-  var req = http.request({
-    method: 'POST',
-    port: server.address().port,
-    headers: {
-      'Content-Length': body.length,
-      'Content-Type': 'multipart/form-data; boundary=foo'
-    }
-  });
-  req.on('response', function (res) {
-    assert.equal(res.statusCode, 500);
-    res.on('data', function () {});
-    res.on('end', function () {
-      server.close();
-    });
-  });
-  req.end(body);
-});
diff --git a/test/standalone/test-emit-order.js b/test/standalone/test-emit-order.js
deleted file mode 100644
index a20869c..0000000
--- a/test/standalone/test-emit-order.js
+++ /dev/null
@@ -1,61 +0,0 @@
-var http = require('http');
-var multiparty = require('../../');
-var assert = require('assert');
-var superagent = require('superagent');
-var path = require('path');
-var bigFile = path.join(__dirname, "..", "fixture", "file", "pf1y5.png");
-
-var server = http.createServer(function(req, res) {
-  assert.strictEqual(req.url, '/upload');
-  assert.strictEqual(req.method, 'POST');
-
-  var fieldsInOrder = [
-    'a',
-    'b',
-    'myimage.png',
-    'c',
-  ];
-
-  var form = new multiparty.Form({
-    autoFields: true,
-  });
-
-  form.on('error', function (err) {
-    assert.ifError(err);
-  });
-
-  form.on('part', function(part) {
-    assert.ok(part.filename);
-    var expectedFieldName = fieldsInOrder.shift();
-    assert.strictEqual(part.name, expectedFieldName);
-    part.resume();
-  });
-
-  form.on('field', function(name, value) {
-    var expectedFieldName = fieldsInOrder.shift();
-    assert.strictEqual(name, expectedFieldName);
-  });
-
-  form.on('close', function() {
-    assert.strictEqual(fieldsInOrder.length, 0);
-    res.end("OK");
-  });
-
-  form.parse(req);
-});
-server.listen(function() {
-  var url = 'http://localhost:' + server.address().port + '/upload';
-  var req = superagent.post(url);
-  req.field('a', 'a-value');
-  req.field('b', 'b-value');
-  req.attach('myimage.png', bigFile);
-  req.field('c', 'hello');
-  req.on('error', function(err) {
-    assert.ifError(err);
-  });
-  req.on('response', function(res) {
-    assert.equal(res.statusCode, 200);
-    server.close();
-  });
-  req.end();
-});
diff --git a/test/standalone/test-epilogue-last-chunk.js b/test/standalone/test-epilogue-last-chunk.js
deleted file mode 100644
index 4e7320f..0000000
--- a/test/standalone/test-epilogue-last-chunk.js
+++ /dev/null
@@ -1,44 +0,0 @@
-var multiparty = require('../../')
-  , assert = require('assert')
-  , http = require('http')
-  , net = require('net');
-
-var server = http.createServer(function(req, res) {
-  var form = new multiparty.Form();
-
-  var partCount = 0;
-  form.on('part', function(part) {
-    part.resume();
-    partCount++;
-  });
-  form.on('close', function() {
-    assert.strictEqual(partCount, 1);
-    res.end();
-  });
-
-  form.parse(req);
-});
-server.listen(function() {
-  var socket = net.connect(server.address().port, 'localhost', function () {
-    socket.write('POST / HTTP/1.1\r\n');
-    socket.write('Host: localhost\r\n');
-    socket.write('Connection: close\r\n');
-    socket.write('Content-Type: multipart/form-data; boundary=foo\r\n');
-    socket.write('Transfer-Encoding: chunked\r\n');
-    socket.write('\r\n');
-    socket.write('7\r\n');
-    socket.write('--foo\r\n\r\n');
-    socket.write('43\r\n');
-    socket.write('Content-Disposition: form-data; name="file"; filename="plain.txt"\r\n\r\n');
-    socket.write('12\r\n');
-    socket.write('\r\nsome text here\r\n\r\n');
-    socket.write('7\r\n');
-    socket.write('--foo--\r\n');
-    socket.write('2\r\n');
-    socket.write('\r\n\r\n');
-    socket.write('0\r\n\r\n');
-    socket.on('close', function () {
-      server.close();
-    });
-  });
-});
diff --git a/test/standalone/test-error-listen-after-parse.js b/test/standalone/test-error-listen-after-parse.js
deleted file mode 100644
index 00e1469..0000000
--- a/test/standalone/test-error-listen-after-parse.js
+++ /dev/null
@@ -1,20 +0,0 @@
-var multiparty = require('../../');
-var assert = require('assert');
-var http = require('http');
-var net = require('net');
-var stream = require('stream');
-
-var form = new multiparty.Form();
-var req = new stream.Readable();
-
-req.headers = {};
-req._read = function(){
-  this.push(new Buffer('--foo!'));
-};
-
-form.parse(req);
-
-form.on('error', function(err){
-  // verification that error emitter when attached after form.parse
-  assert.ok(err);
-});
diff --git a/test/standalone/test-error-unpipe.js b/test/standalone/test-error-unpipe.js
deleted file mode 100644
index 0213f35..0000000
--- a/test/standalone/test-error-unpipe.js
+++ /dev/null
@@ -1,43 +0,0 @@
-var multiparty = require('../../');
-var assert = require('assert');
-var http = require('http');
-var net = require('net');
-var Pend = require('pend');
-var stream = require('stream');
-
-var err = null;
-var form = new multiparty.Form();
-var pend = new Pend();
-var req = new stream.Readable();
-var unpiped = false;
-
-req.headers = {
-  'content-type': 'multipart/form-data; boundary=foo'
-};
-req._read = function(){
-  this.push(new Buffer('--foo!'));
-};
-
-pend.go(function(){
-  form.on('error', function(e){
-    err = e;
-  });
-});
-
-pend.go(function(){
-  form.on('unpipe', function(){
-    unpiped = true;
-  });
-});
-
-pend.wait(function(){
-  // verification that error event implies unpipe call
-  assert.ok(err);
-  assert.ok(unpiped, 'req was unpiped');
-  assert.equal(req._readableState.flowing, false, 'req not flowing');
-  assert.equal(req._readableState.pipesCount, 0, 'req has 0 pipes');
-})
-
-form.parse(req)
-assert.equal(req._readableState.flowing, true, 'req flowing');
-assert.equal(req._readableState.pipesCount, 1, 'req has 1 pipe');
diff --git a/test/standalone/test-invalid.js b/test/standalone/test-invalid.js
deleted file mode 100644
index ede541d..0000000
--- a/test/standalone/test-invalid.js
+++ /dev/null
@@ -1,35 +0,0 @@
-var superagent = require('superagent')
-  , multiparty = require('../../')
-  , http = require('http')
-
-var server = http.createServer(function(req, resp) {
-  var form = new multiparty.Form();
-
-  var errCount = 0;
-  form.on('error', function(err) {
-    errCount += 1;
-    resp.end();
-  });
-  form.on('file', function(name, file) {
-  });
-  form.on('field', function(name, file) {
-  });
-
-  form.parse(req);
-});
-server.listen(function() {
-  var url = 'http://localhost:' + server.address().port + '/'
-  var req = superagent.post(url)
-  req.set('Content-Type', 'multipart/form-data; boundary=foo')
-  req.write('--foo\r\n')
-  req.write('Content-filename="foo.txt"\r\n')
-  req.write('\r\n')
-  req.write('some text here')
-  req.write('Content-Disposition: form-data; name="text"; filename="bar.txt"\r\n')
-  req.write('\r\n')
-  req.write('some more text stuff')
-  req.write('\r\n--foo--')
-  req.end(function(err, resp) {
-    server.close();
-  });
-});
diff --git a/test/standalone/test-issue-15.js b/test/standalone/test-issue-15.js
deleted file mode 100644
index fdec5f6..0000000
--- a/test/standalone/test-issue-15.js
+++ /dev/null
@@ -1,76 +0,0 @@
-var http = require('http')
-  , multiparty = require('../../')
-  , assert = require('assert')
-  , superagent = require('superagent')
-  , path = require('path')
-  , fs = require('fs')
-
-var server = http.createServer(function(req, res) {
-  assert.strictEqual(req.url, '/upload');
-  assert.strictEqual(req.method, 'POST');
-
-  var form = new multiparty.Form({autoFields:true,autoFiles:true});
-
-  form.on('error', function(err) {
-    console.log(err);
-  });
-
-  form.on('close', function() {
-  });
-
-  var fileCount = 0;
-  form.on('file', function(name, file) {
-    fileCount += 1;
-    fs.unlink(file.path, function () {});
-  });
-
-  form.parse(req, function(err, fields, files) {
-    var objFileCount = 0;
-    for (var file in files) {
-      objFileCount += 1;
-    }
-    // multiparty does NOT try to do intelligent things based on
-    // the part name.
-    assert.strictEqual(fileCount, 2);
-    assert.strictEqual(objFileCount, 1);
-    res.end();
-  });
-});
-server.listen(function() {
-  var url = 'http://localhost:' + server.address().port + '/upload';
-  var req = superagent.post(url);
-  req.attach('files[]', fixture('pf1y5.png'), 'SOG2.JPG');
-  req.attach('files[]', fixture('binaryfile.tar.gz'), 'BenF364_LIB353.zip');
-
-  req.end(function(err, resp) {
-    assert.ifError(err);
-    resp.on('end', function() {
-      server.close();
-    });
-  });
-
-  // No space.
-  createRequest('');
-
-  // Single space.
-  createRequest(' ');
-
-  // Multiple spaces.
-  createRequest('    ');
-});
-
-function createRequest(separator) {
-  var url = 'http://localhost:' + server.address().port + '/upload';
-  var req = superagent.post(url);
-  req.attach('files[]', fixture('pf1y5.png'), 'SOG2.JPG');
-  req.attach('files[]', fixture('binaryfile.tar.gz'), 'BenF364_LIB353.zip');
-
-  req.end(function(err, resp) {
-    assert.ifError(err);
-    // We don't close the server, to allow other requests to pass.
-  });
-}
-
-function fixture(name) {
-  return path.join(__dirname, '..', 'fixture', 'file', name)
-}
diff --git a/test/standalone/test-issue-19.js b/test/standalone/test-issue-19.js
deleted file mode 100644
index d7da0cf..0000000
--- a/test/standalone/test-issue-19.js
+++ /dev/null
@@ -1,44 +0,0 @@
-var assert = require('assert');
-var http = require('http');
-var net = require('net');
-var multiparty = require('../../');
-
-var client;
-var server = http.createServer(function (req, res) {
-  var form = new multiparty.Form({maxFields: 1});
-  form.on('aborted', function () {
-    throw new Error("did not expect aborted");
-  });
-  var first = true;
-  form.on('error', function (err) {
-    assert.ok(first);
-    first = false;
-    client.end();
-    assert.ok(/maxFields/.test(err.message));
-    server.close();
-  });
-  form.on('end', function () {
-    throw new Error('Unexpected "end" event');
-  });
-  form.parse(req);
-});
-server.listen(function() {
-  client = net.connect(server.address().port);
-
-  client.write("POST /upload HTTP/1.1\r\n" +
-    "Content-Length: 728\r\n" +
-    "Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
-    "\r\n" +
-    "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
-    "Content-Disposition: form-data; name=\"title\"\r\n" +
-    "\r\n" +
-    "foofoo" +
-    "\r\n" +
-    "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
-    "Content-Disposition: form-data; name=\"upload\"; filename=\"blah1.txt\"\r\n" +
-    "Content-Type: text/plain\r\n" +
-    "\r\n" +
-    "hi1\r\n" +
-    "\r\n" +
-    "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n");
-});
diff --git a/test/standalone/test-issue-21.js b/test/standalone/test-issue-21.js
deleted file mode 100644
index ea0fddf..0000000
--- a/test/standalone/test-issue-21.js
+++ /dev/null
@@ -1,85 +0,0 @@
-var assert = require('assert');
-var fs = require('fs');
-var http = require('http');
-var net = require('net');
-var multiparty = require('../../');
-
-var client;
-var server = http.createServer(function(req, res) {
-  var form = new multiparty.Form();
-
-  form.parse(req, function(err, fields, files) {
-    if (err) {
-      console.error(err.stack);
-      return;
-    }
-    var nameCount = 0;
-    var name;
-    for (name in fields) {
-      assert.strictEqual(name, "title");
-      nameCount += 1;
-
-      var values = fields[name];
-      assert.strictEqual(values.length, 1);
-      assert.strictEqual(values[0], "foofoo");
-    }
-    assert.strictEqual(nameCount, 1);
-
-    nameCount = 0;
-    for (name in files) {
-      assert.strictEqual(name, "upload");
-      nameCount += 1;
-
-      var filesList = files[name];
-      assert.strictEqual(filesList.length, 4);
-      filesList.forEach(function(file){
-        assert.strictEqual(file.fieldName, "upload");
-        fs.unlinkSync(file.path);
-      });
-    }
-    assert.strictEqual(nameCount, 1);
-
-    res.end();
-    client.end();
-    server.close();
-  });
-});
-server.listen(function() {
-  client = net.connect(server.address().port);
-
-  client.write("POST /upload HTTP/1.1\r\n" +
-    "Content-Length: 726\r\n" +
-    "Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
-    "\r\n" +
-    "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
-    "Content-Disposition: form-data; name=\"title\"\r\n" +
-    "\r\n" +
-    "foofoo" +
-    "\r\n" +
-    "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
-    "Content-Disposition: form-data; name=\"upload\"; filename=\"blah1.txt\"\r\n" +
-    "Content-Type: text/plain\r\n" +
-    "\r\n" +
-    "hi1\r\n" +
-    "\r\n" +
-    "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
-    "Content-Disposition: form-data; name=\"upload\"; filename=\"blah2.txt\"\r\n" +
-    "Content-Type: text/plain\r\n" +
-    "\r\n" +
-    "hi2\r\n" +
-    "\r\n" +
-    "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
-    "Content-Disposition: form-data; name=\"upload\"; filename=\"blah3.txt\"\r\n" +
-    "Content-Type: text/plain\r\n" +
-    "\r\n" +
-    "hi3\r\n" +
-    "\r\n" +
-    "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
-    "Content-Disposition: form-data; name=\"upload\"; filename=\"blah4.txt\"\r\n" +
-    "Content-Type: text/plain\r\n" +
-    "\r\n" +
-    "hi4\r\n" +
-    "\r\n" +
-    "------WebKitFormBoundaryvfUZhxgsZDO7FXLF--\r\n"
-  );
-});
diff --git a/test/standalone/test-issue-32.js b/test/standalone/test-issue-32.js
deleted file mode 100644
index 6e70c71..0000000
--- a/test/standalone/test-issue-32.js
+++ /dev/null
@@ -1,38 +0,0 @@
-var assert = require('assert');
-var fs = require('fs');
-var http = require('http');
-var net = require('net');
-var multiparty = require('../../');
-
-var client;
-var server = http.createServer(function(req, res) {
-  var form = new multiparty.Form();
-
-  form.parse(req, function(err, fields, files) {
-    if (err) {
-      console.error(err.stack);
-      return;
-    }
-    assert.strictEqual(files.image[0].originalFilename, "测试文档")
-    fs.unlinkSync(files.image[0].path);
-    res.end();
-    client.end();
-    server.close();
-  });
-});
-server.listen(function() {
-  client = net.connect(server.address().port);
-
-  client.write(
-    "POST /upload HTTP/1.1\r\n" +
-    "Accept: */*\r\n" +
-    "Content-Type: multipart/form-data; boundary=\"893e5556-f402-4fec-8180-c59333354c6f\"\r\n" +
-    "Content-Length: 187\r\n" +
-    "\r\n" +
-    "--893e5556-f402-4fec-8180-c59333354c6f\r\n" +
-    "Content-Disposition: form-data; name=\"image\"; filename*=utf-8''%E6%B5%8B%E8%AF%95%E6%96%87%E6%A1%A3\r\n" +
-    "\r\n" +
-    "\r\n" +
-    "--893e5556-f402-4fec-8180-c59333354c6f--\r\n"
-  );
-});
diff --git a/test/standalone/test-issue-36.js b/test/standalone/test-issue-36.js
deleted file mode 100644
index 3bacdda..0000000
--- a/test/standalone/test-issue-36.js
+++ /dev/null
@@ -1,38 +0,0 @@
-var assert = require('assert');
-var http = require('http');
-var net = require('net');
-var multiparty = require('../../');
-var superagent = require('superagent');
-
-var client;
-var server = http.createServer(function(req, res) {
-  var form = new multiparty.Form();
-  var endCalled = false;
-  form.on('part', function(part) {
-    part.on('end', function() {
-      endCalled = true;
-    });
-    part.resume();
-  });
-  form.on('close', function() {
-    assert.ok(endCalled);
-    res.end();
-  });
-  form.parse(req);
-});
-server.listen(function() {
-  var url = 'http://localhost:' + server.address().port + '/'
-  var req = superagent.post(url)
-  req.set('Content-Type', 'multipart/form-data; boundary=--WebKitFormBoundaryvfUZhxgsZDO7FXLF')
-  req.set('Content-Length', '186')
-  req.write('----WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n');
-  req.write('Content-Disposition: form-data; name="upload"; filename="blah1.txt"\r\n');
-  req.write('Content-Type: plain/text\r\n');
-  req.write('\r\n');
-  req.write('hi1\r\n');
-  req.write('\r\n');
-  req.write('----WebKitFormBoundaryvfUZhxgsZDO7FXLF--\r\n');
-  req.end(function(err, resp) {
-    server.close();
-  });
-});
diff --git a/test/standalone/test-issue-4.js b/test/standalone/test-issue-4.js
deleted file mode 100644
index de38125..0000000
--- a/test/standalone/test-issue-4.js
+++ /dev/null
@@ -1,53 +0,0 @@
-var http = require('http')
-  , multiparty = require('../../')
-  , assert = require('assert')
-  , superagent = require('superagent')
-  , path = require('path')
-  , fs = require('fs')
-
-var server = http.createServer(function(req, res) {
-  assert.strictEqual(req.url, '/upload');
-  assert.strictEqual(req.method, 'POST');
-
-  var form = new multiparty.Form({autoFields:true,autoFiles:true});
-
-  form.on('error', function(err) {
-    console.log(err);
-  });
-
-  form.on('close', function() {
-  });
-
-  var fileCount = 0;
-  form.on('file', function(name, file) {
-    fileCount += 1;
-    fs.unlink(file.path, function () {});
-  });
-
-  form.parse(req, function(err, fields, files) {
-    var objFileCount = 0;
-    for (var file in files) {
-      objFileCount += 1;
-    }
-    // multiparty does NOT try to do intelligent things based on
-    // the part name.
-    assert.strictEqual(fileCount, 2);
-    assert.strictEqual(objFileCount, 1);
-    res.end();
-  });
-});
-server.listen(function() {
-  var url = 'http://localhost:' + server.address().port + '/upload';
-  var req = superagent.post(url);
-  req.attach('files[]', fixture('pf1y5.png'), 'SOG2.JPG');
-  req.attach('files[]', fixture('binaryfile.tar.gz'), 'BenF364_LIB353.zip');
-  req.end(function(err, resp) {
-    assert.ifError(err);
-    resp.on('end', function() {
-      server.close();
-    });
-  });
-});
-function fixture(name) {
-  return path.join(__dirname, '..', 'fixture', 'file', name)
-}
diff --git a/test/standalone/test-max-fields.js b/test/standalone/test-max-fields.js
deleted file mode 100644
index 29f8b35..0000000
--- a/test/standalone/test-max-fields.js
+++ /dev/null
@@ -1,52 +0,0 @@
-var http = require('http')
-  , multiparty = require('../../')
-  , assert = require('assert')
-  , superagent = require('superagent')
-  , path = require('path')
-  , fs = require('fs')
-
-var server = http.createServer(function(req, res) {
-  assert.strictEqual(req.url, '/upload');
-  assert.strictEqual(req.method, 'POST');
-
-  var form = new multiparty.Form({autoFiles:true,maxFields:2});
-
-  var first = true;
-  form.on('error', function (err) {
-    assert.ok(first);
-    first = false;
-    assert.ok(/maxFields/.test(err.message));
-  });
-
-  var fieldCount = 0;
-  form.on('field', function() {
-    fieldCount += 1;
-  });
-
-  form.parse(req, function(err, fields, files) {
-    assert.ok(!first);
-    assert.ok(fieldCount <= 2);
-    res.statusCode = 413;
-    res.end('too many fields');
-  });
-});
-server.listen(function() {
-  var url = 'http://localhost:' + server.address().port + '/upload';
-  var req = superagent.post(url);
-  var val = new Buffer(10 * 1024);
-  req.field('a', val);
-  req.field('b', val);
-  req.field('c', val);
-  req.on('error', function(err) {
-    assert.ifError(err);
-  });
-  req.end();
-  req.on('response', function(res) {
-    assert.equal(res.statusCode, 413);
-    server.close();
-  });
-});
-
-function fixture(name) {
-  return path.join(__dirname, '..', 'fixture', 'file', name)
-}
diff --git a/test/standalone/test-max-files-size-exact.js b/test/standalone/test-max-files-size-exact.js
deleted file mode 100644
index 57892ec..0000000
--- a/test/standalone/test-max-files-size-exact.js
+++ /dev/null
@@ -1,42 +0,0 @@
-var http = require('http')
-  , multiparty = require('../../')
-  , assert = require('assert')
-  , superagent = require('superagent')
-  , path = require('path')
-  , fs = require('fs')
-
-var server = http.createServer(function(req, res) {
-  assert.strictEqual(req.url, '/upload');
-  assert.strictEqual(req.method, 'POST');
-
-  var form = new multiparty.Form({autoFiles:true,maxFilesSize:768323}); // exact size of pf1y5.png
-
-  var fileCount = 0;
-  form.on('file', function(name, file) {
-    fileCount += 1;
-    fs.unlink(file.path, function() {});
-  });
-
-  form.parse(req, function(err, fields, files) {
-    assert.ifError(err);
-    assert.ok(fileCount === 1);
-    res.end('OK');
-  });
-});
-server.listen(function() {
-  var url = 'http://localhost:' + server.address().port + '/upload';
-  var req = superagent.post(url);
-  req.attach('file0', fixture('pf1y5.png'), 'SOG1.JPG');
-  req.on('error', function(err) {
-    assert.ifError(err);
-  });
-  req.end();
-  req.on('response', function(res) {
-    assert.equal(res.statusCode, 200);
-    server.close();
-  });
-});
-
-function fixture(name) {
-  return path.join(__dirname, '..', 'fixture', 'file', name)
-}
diff --git a/test/standalone/test-max-files-size.js b/test/standalone/test-max-files-size.js
deleted file mode 100644
index 184f991..0000000
--- a/test/standalone/test-max-files-size.js
+++ /dev/null
@@ -1,50 +0,0 @@
-var http = require('http');
-var multiparty = require('../../');
-var assert = require('assert');
-var superagent = require('superagent');
-var path = require('path');
-var fs = require('fs');
-
-var server = http.createServer(function(req, res) {
-  assert.strictEqual(req.url, '/upload');
-  assert.strictEqual(req.method, 'POST');
-
-  var form = new multiparty.Form({autoFiles:true,maxFilesSize:800*1024});
-
-  var first = true;
-  form.on('error', function (err) {
-    assert.ok(first);
-    first = false;
-    assert.strictEqual(err.code, 'ETOOBIG');
-  });
-
-  var fileCount = 0;
-  form.on('file', function(name, file) {
-    fileCount += 1;
-    fs.unlinkSync(file.path);
-  });
-
-  form.parse(req, function(err, fields, files) {
-    assert.ok(fileCount <= 1);
-    res.statusCode = 413;
-    res.end('files too large');
-  });
-});
-server.listen(function() {
-  var url = 'http://localhost:' + server.address().port + '/upload';
-  var req = superagent.post(url);
-  req.attach('file0', fixture('pf1y5.png'), 'SOG1.JPG');
-  req.attach('file1', fixture('pf1y5.png'), 'SOG2.JPG');
-  req.on('error', function(err) {
-    assert.ifError(err);
-  });
-  req.end();
-  req.on('response', function(res) {
-    assert.equal(res.statusCode, 413);
-    server.close();
-  });
-});
-
-function fixture(name) {
-  return path.join(__dirname, '..', 'fixture', 'file', name)
-}
diff --git a/test/standalone/test-missing-boundary-end.js b/test/standalone/test-missing-boundary-end.js
deleted file mode 100644
index 3686413..0000000
--- a/test/standalone/test-missing-boundary-end.js
+++ /dev/null
@@ -1,46 +0,0 @@
-var superagent = require('superagent')
-  , assert = require('assert')
-  , multiparty = require('../../')
-  , http = require('http')
-
-var server = http.createServer(function(req, resp) {
-  var form = new multiparty.Form();
-
-  var errCount = 0;
-  form.on('error', function (err) {
-    assert.ok(err);
-    assert.equal(err.message, 'stream ended unexpectedly');
-    errCount += 1;
-    resp.end();
-  });
-  form.on('part', function (part) {
-    part.resume();
-  });
-  form.on('close', function () {
-    assert.equal(errCount, 1);
-  })
-
-  form.parse(req);
-});
-server.listen(function() {
-  var url = 'http://localhost:' + server.address().port + '/'
-  var req = superagent.post(url)
-  req.set('Content-Type', 'multipart/form-data; boundary=--WebKitFormBoundaryE19zNvXGzXaLvS5C')
-  req.write('----WebKitFormBoundaryE19zNvXGzXaLvS5C\r\n');
-  req.write('Content-Disposition: form-data; name="a[b]"\r\n');
-  req.write('\r\n');
-  req.write('3\r\n');
-  req.write('----WebKitFormBoundaryE19zNvXGzXaLvS5C\r\n');
-  req.write('Content-Disposition: form-data; name="a[c]"\r\n');
-  req.write('\r\n');
-  req.write('4\r\n');
-  req.write('----WebKitFormBoundaryE19zNvXGzXaLvS5C\r\n');
-  req.write('Content-Disposition: form-data; name="file"; filename="test.txt"\r\n');
-  req.write('Content-Type: plain/text\r\n');
-  req.write('\r\n');
-  req.write('and\r\n');
-  req.write('----WebKitFormBoundaryE19zNvXGzXaLvS5C\r\n');
-  req.end(function(err, resp) {
-    server.close();
-  });
-});
diff --git a/test/standalone/test-parse-type-error.js b/test/standalone/test-parse-type-error.js
deleted file mode 100644
index 42437c8..0000000
--- a/test/standalone/test-parse-type-error.js
+++ /dev/null
@@ -1,39 +0,0 @@
-var http = require('http')
-  , multiparty = require('../../')
-  , assert = require('assert')
-  , superagent = require('superagent')
-  , path = require('path');
-
-var server = http.createServer(function(req, res) {
-  assert.strictEqual(req.url, '/upload');
-  assert.strictEqual(req.method, 'POST');
-
-  var form = new multiparty.Form();
-
-  // this is invalid
-  delete req.headers['content-type'];
-
-  form.parse(req, function(err, fields, files) {
-    assert.ok(err);
-    assert.equal(err.message, 'missing content-type header');
-    res.statusCode = 415;
-    res.end();
-  });
-});
-server.listen(function() {
-  var url = 'http://localhost:' + server.address().port + '/upload';
-  var req = superagent.post(url);
-  req.attach('file0', fixture('pf1y5.png'), 'SOG1.JPG');
-  req.on('error', function(err) {
-    assert.ifError(err);
-  });
-  req.end();
-  req.on('response', function(res) {
-    assert.equal(res.statusCode, 415);
-    server.close();
-  });
-});
-
-function fixture(name) {
-  return path.join(__dirname, '..', 'fixture', 'file', name)
-}
diff --git a/test/standalone/test-req-encoding.js b/test/standalone/test-req-encoding.js
deleted file mode 100644
index aebd935..0000000
--- a/test/standalone/test-req-encoding.js
+++ /dev/null
@@ -1,39 +0,0 @@
-var http = require('http')
-  , multiparty = require('../../')
-  , assert = require('assert')
-  , superagent = require('superagent')
-  , path = require('path');
-
-var server = http.createServer(function(req, res) {
-  assert.strictEqual(req.url, '/upload');
-  assert.strictEqual(req.method, 'POST');
-
-  var form = new multiparty.Form();
-
-  // this is invalid
-  req.setEncoding('utf8');
-
-  form.parse(req, function(err, fields, files) {
-    assert.ok(err);
-    assert.equal(err.message, 'request encoding must not be set');
-    res.statusCode = 500;
-    res.end();
-  });
-});
-server.listen(function() {
-  var url = 'http://localhost:' + server.address().port + '/upload';
-  var req = superagent.post(url);
-  req.attach('file0', fixture('pf1y5.png'), 'SOG1.JPG');
-  req.on('error', function(err) {
-    assert.ifError(err);
-  });
-  req.end();
-  req.on('response', function(res) {
-    assert.equal(res.statusCode, 500);
-    server.close();
-  });
-});
-
-function fixture(name) {
-  return path.join(__dirname, '..', 'fixture', 'file', name)
-}
diff --git a/test/standalone/test-stream-error.js b/test/standalone/test-stream-error.js
deleted file mode 100644
index a9a9785..0000000
--- a/test/standalone/test-stream-error.js
+++ /dev/null
@@ -1,36 +0,0 @@
-var assert = require('assert');
-var http = require('http');
-var net = require('net');
-var multiparty = require('../../');
-
-var server = http.createServer(function (req, res) {
-  var form = new multiparty.Form();
-  var gotPartErr;
-  form.on('part', function(part) {
-    part.on('error', function(err) {
-      gotPartErr = err;
-    });
-    part.resume();
-  });
-  form.on('error', function () {
-    assert.ok(gotPartErr);
-    server.close();
-  });
-  form.on('close', function () {
-    throw new Error('Unexpected "close" event');
-  });
-  form.parse(req);
-}).listen(0, 'localhost', function () {
-  var client = net.connect(server.address().port);
-  client.write(
-    "POST / HTTP/1.1\r\n" +
-    "Content-Length: 186\r\n" +
-    "Content-Type: multipart/form-data; boundary=--WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
-    "\r\n" +
-    "----WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
-    "Content-Disposition: form-data; name=\"upload\"; filename=\"blah1.txt\"\r\n" +
-    "Content-Type: plain/text\r\n" +
-    "\r\n" +
-    "hi1\r\n");
-  client.end();
-});
diff --git a/test/test.js b/test/test.js
index 41ef5d6..1a7e788 100644
--- a/test/test.js
+++ b/test/test.js
@@ -1,4 +1,3 @@
-var spawn = require('child_process').spawn;
 var crypto = require('crypto');
 var findit = require('findit2');
 var path = require('path');
@@ -7,19 +6,1249 @@ var rimraf = require('rimraf');
 var fs = require('fs');
 var http = require('http');
 var net = require('net');
+var stream = require('stream');
 var assert = require('assert');
 var multiparty = require('../');
 var mkdirp = require('mkdirp');
+var superagent = require('superagent');
 var STANDALONE_PATH = path.join(__dirname, 'standalone');
 var server = http.createServer();
 var PORT = 13532;
 var FIXTURE_PATH = path.join(__dirname, 'fixture');
 var TMP_PATH = path.join(__dirname, 'tmp');
 
+var standaloneTests = [
+  {
+    name: 'chunked',
+    fn: function(cb) {
+      var server = http.createServer(function(req, resp) {
+        var form = new multiparty.Form();
+
+        var partCount = 0;
+        form.on('part', function(part) {
+          part.resume();
+          partCount++;
+          assert.strictEqual(typeof part.byteCount, 'undefined');
+        });
+        form.on('close', function() {
+          assert.strictEqual(partCount, 1);
+          resp.end();
+        });
+
+        form.parse(req);
+      });
+      server.listen(function() {
+        var socket = net.connect(server.address().port, 'localhost', function () {
+          socket.write('POST / HTTP/1.1\r\n');
+          socket.write('Host: localhost\r\n');
+          socket.write('Connection: close\r\n');
+          socket.write('Content-Type: multipart/form-data; boundary=foo\r\n');
+          socket.write('Transfer-Encoding: chunked\r\n');
+          socket.write('\r\n');
+          socket.write('7\r\n');
+          socket.write('--foo\r\n\r\n');
+          socket.write('43\r\n');
+          socket.write('Content-Disposition: form-data; name="file"; filename="plain.txt"\r\n\r\n');
+          socket.write('12\r\n');
+          socket.write('\r\nsome text here\r\n\r\n');
+          socket.write('9\r\n');
+          socket.write('--foo--\r\n\r\n');
+          socket.write('0\r\n\r\n');
+          socket.on('close', function () {
+            server.close(cb);
+          });
+        });
+      });
+    },
+  },
+  {
+    name: "connection aborted closed",
+    fn: function(cb) {
+      var socket;
+      var server = http.createServer(function (req, res) {
+        var called = false;
+        var form = new multiparty.Form();
+
+        form.parse(req, function (err, fields, files) {
+          assert.ok(!called);
+          called = true;
+
+          assert.ifError(err);
+          assert.equal(Object.keys(fields).length, 1);
+          socket.end();
+        });
+      });
+
+      server.listen(0, 'localhost', function () {
+        socket = net.connect(server.address().port, 'localhost', function () {
+          socket.write('POST / HTTP/1.1\r\n');
+          socket.write('Host: localhost\r\n');
+          socket.write('Connection: close\r\n');
+          socket.write('Content-Type: multipart/form-data; boundary=foo\r\n');
+          socket.write('Transfer-Encoding: chunked\r\n');
+          socket.write('\r\n');
+          socket.write('7\r\n');
+          socket.write('--foo\r\n\r\n');
+          socket.write('2D\r\n');
+          socket.write('Content-Disposition: form-data; name="data"\r\n\r\n');
+          socket.write('12\r\n');
+          socket.write('\r\nsome text here\r\n\r\n');
+          socket.write('7\r\n');
+          socket.write('--foo--\r\n');
+          socket.write('2\r\n');
+          socket.write('\r\n\r\n');
+          socket.write('0\r\n\r\n');
+          socket.on('close', function () {
+            server.close(cb);
+          });
+        });
+      });
+    },
+  },
+  {
+    name: "connection aborted",
+    fn: function(cb) {
+      var server = http.createServer(function (req, res) {
+        var form = new multiparty.Form();
+        var aborted_received = false;
+        form.on('aborted', function () {
+          aborted_received = true;
+        });
+        form.on('error', function () {
+          assert(aborted_received, 'Error event should follow aborted');
+          server.close(cb);
+        });
+        form.on('end', function () {
+          throw new Error('Unexpected "end" event');
+        });
+        form.on('close', function () {
+          throw new Error('Unexpected "close" event');
+        });
+        form.parse(req);
+      }).listen(0, 'localhost', function () {
+        var client = net.connect(server.address().port);
+        client.write(
+          "POST / HTTP/1.1\r\n" +
+          "Content-Length: 70\r\n" +
+          "Content-Type: multipart/form-data; boundary=foo\r\n\r\n");
+        client.end();
+      });
+    },
+  },
+  {
+    name: "content transfer encoding",
+    fn: function(cb) {
+      var server = http.createServer(function(req, res) {
+        var form = new multiparty.Form();
+        form.uploadDir = TMP_PATH;
+        form.on('close', function () {
+          throw new Error('Unexpected "close" event');
+        });
+        form.on('end', function () {
+          throw new Error('Unexpected "end" event');
+        });
+        form.on('error', function (e) {
+          res.writeHead(e.status || 500);
+          res.end(e.message);
+        });
+        form.parse(req);
+      });
+
+      server.listen(0, function() {
+        var body =
+          '--foo\r\n' +
+          'Content-Disposition: form-data; name="file1"; filename="file1"\r\n' +
+          'Content-Type: application/octet-stream\r\n' +
+          '\r\nThis is the first file\r\n' +
+          '--foo\r\n' +
+          'Content-Type: application/octet-stream\r\n' +
+          'Content-Disposition: form-data; name="file2"; filename="file2"\r\n' +
+          'Content-Transfer-Encoding: unknown\r\n' +
+          '\r\nThis is the second file\r\n' +
+          '--foo--\r\n';
+
+        var req = http.request({
+          method: 'POST',
+          port: server.address().port,
+          headers: {
+            'Content-Length': body.length,
+            'Content-Type': 'multipart/form-data; boundary=foo'
+          }
+        });
+        req.on('response', function (res) {
+          assert.equal(res.statusCode, 400);
+          res.on('data', function () {});
+          res.on('end', function () {
+            server.close(cb);
+          });
+        });
+        req.end(body);
+      });
+    },
+  },
+  {
+    name: "emit order",
+    fn: function(cb) {
+      var bigFile = path.join(FIXTURE_PATH, "file", "pf1y5.png");
+
+      var server = http.createServer(function(req, res) {
+        assert.strictEqual(req.url, '/upload');
+        assert.strictEqual(req.method, 'POST');
+
+        var fieldsInOrder = [
+          'a',
+          'b',
+          'myimage.png',
+          'c',
+        ];
+
+        var form = new multiparty.Form({
+          autoFields: true,
+        });
+
+        form.on('error', function (err) {
+          assert.ifError(err);
+        });
+
+        form.on('part', function(part) {
+          assert.ok(part.filename);
+          var expectedFieldName = fieldsInOrder.shift();
+          assert.strictEqual(part.name, expectedFieldName);
+          part.resume();
+        });
+
+        form.on('field', function(name, value) {
+          var expectedFieldName = fieldsInOrder.shift();
+          assert.strictEqual(name, expectedFieldName);
+        });
+
+        form.on('close', function() {
+          assert.strictEqual(fieldsInOrder.length, 0);
+          res.end("OK");
+        });
+
+        form.parse(req);
+      });
+      server.listen(function() {
+        var url = 'http://localhost:' + server.address().port + '/upload';
+        var req = superagent.post(url);
+        req.field('a', 'a-value');
+        req.field('b', 'b-value');
+        req.attach('myimage.png', bigFile);
+        req.field('c', 'hello');
+        req.on('error', function(err) {
+          assert.ifError(err);
+        });
+        req.on('response', function(res) {
+          assert.equal(res.statusCode, 200);
+          server.close(cb);
+        });
+        req.end();
+      });
+    },
+  },
+  {
+    name: "epilogue last chunk",
+    fn: function(cb) {
+      var server = http.createServer(function(req, res) {
+        var form = new multiparty.Form();
+
+        var partCount = 0;
+        form.on('part', function(part) {
+          part.resume();
+          partCount++;
+        });
+        form.on('close', function() {
+          assert.strictEqual(partCount, 1);
+          res.end();
+        });
+
+        form.parse(req);
+      });
+      server.listen(function() {
+        var socket = net.connect(server.address().port, 'localhost', function () {
+          socket.write('POST / HTTP/1.1\r\n');
+          socket.write('Host: localhost\r\n');
+          socket.write('Connection: close\r\n');
+          socket.write('Content-Type: multipart/form-data; boundary=foo\r\n');
+          socket.write('Transfer-Encoding: chunked\r\n');
+          socket.write('\r\n');
+          socket.write('7\r\n');
+          socket.write('--foo\r\n\r\n');
+          socket.write('43\r\n');
+          socket.write('Content-Disposition: form-data; name="file"; filename="plain.txt"\r\n\r\n');
+          socket.write('12\r\n');
+          socket.write('\r\nsome text here\r\n\r\n');
+          socket.write('7\r\n');
+          socket.write('--foo--\r\n');
+          socket.write('2\r\n');
+          socket.write('\r\n\r\n');
+          socket.write('0\r\n\r\n');
+          socket.on('close', function () {
+            server.close(cb);
+          });
+        });
+      });
+    },
+  },
+  {
+    name: "error listen after parse",
+    fn: function(cb) {
+      var form = new multiparty.Form();
+      var req = new stream.Readable();
+
+      req.headers = {};
+      req._read = function(){
+        this.push(new Buffer('--foo!'));
+      };
+
+      form.parse(req);
+
+      form.on('error', function(err){
+        // verification that error emitter when attached after form.parse
+        assert.ok(err);
+        cb();
+      });
+    },
+  },
+  {
+    name: "error unpipe",
+    fn: function(cb) {
+      var err = null;
+      var form = new multiparty.Form();
+      var pend = new Pend();
+      var req = new stream.Readable();
+      var unpiped = false;
+
+      req.headers = {
+        'content-type': 'multipart/form-data; boundary=foo'
+      };
+      req._read = function(){
+        this.push(new Buffer('--foo!'));
+      };
+
+      pend.go(function(cb){
+        form.on('error', function(e){
+          err = e;
+          cb();
+        });
+      });
+
+      pend.go(function(cb){
+        form.on('unpipe', function(){
+          unpiped = true;
+          cb();
+        });
+      });
+
+      pend.wait(function(){
+        // verification that error event implies unpipe call
+        assert.ok(err);
+        assert.ok(unpiped, 'req was unpiped');
+        assert.equal(req._readableState.flowing, false, 'req not flowing');
+        assert.equal(req._readableState.pipesCount, 0, 'req has 0 pipes');
+        cb();
+      })
+
+      form.parse(req)
+      assert.equal(req._readableState.flowing, true, 'req flowing');
+      assert.equal(req._readableState.pipesCount, 1, 'req has 1 pipe');
+    },
+  },
+  {
+    name: "invalid",
+    fn: function(cb) {
+      var server = http.createServer(function(req, resp) {
+        var form = new multiparty.Form();
+
+        var errCount = 0;
+        form.on('error', function(err) {
+          errCount += 1;
+          resp.end();
+        });
+        form.on('file', function(name, file) {
+        });
+        form.on('field', function(name, file) {
+        });
+
+        form.parse(req);
+      });
+      server.listen(function() {
+        var url = 'http://localhost:' + server.address().port + '/'
+        var req = superagent.post(url)
+        req.set('Content-Type', 'multipart/form-data; boundary=foo')
+        req.write('--foo\r\n')
+        req.write('Content-filename="foo.txt"\r\n')
+        req.write('\r\n')
+        req.write('some text here')
+        req.write('Content-Disposition: form-data; name="text"; filename="bar.txt"\r\n')
+        req.write('\r\n')
+        req.write('some more text stuff')
+        req.write('\r\n--foo--')
+        req.end(function(err, resp) {
+          server.close(cb);
+        });
+      });
+    },
+  },
+  {
+    name: "issue 15",
+    fn: function(cb) {
+      var server = http.createServer(function(req, res) {
+        assert.strictEqual(req.url, '/upload');
+        assert.strictEqual(req.method, 'POST');
+
+        var form = new multiparty.Form({autoFields:true,autoFiles:true});
+
+        form.on('error', function(err) {
+          console.log(err);
+        });
+
+        form.on('close', function() {
+        });
+
+        var fileCount = 0;
+        form.on('file', function(name, file) {
+          fileCount += 1;
+          fs.unlink(file.path, function () {});
+        });
+
+        form.parse(req, function(err, fields, files) {
+          var objFileCount = 0;
+          for (var file in files) {
+            objFileCount += 1;
+          }
+          // multiparty does NOT try to do intelligent things based on
+          // the part name.
+          assert.strictEqual(fileCount, 2);
+          assert.strictEqual(objFileCount, 1);
+          res.end();
+        });
+      });
+      server.listen(function() {
+        var url = 'http://localhost:' + server.address().port + '/upload';
+        var req = superagent.post(url);
+        req.attach('files[]', fixture('pf1y5.png'), 'SOG2.JPG');
+        req.attach('files[]', fixture('binaryfile.tar.gz'), 'BenF364_LIB353.zip');
+
+        req.end(function(err, resp) {
+          assert.ifError(err);
+          resp.on('end', function() {
+            server.close(cb);
+          });
+        });
+
+        // No space.
+        createRequest('');
+
+        // Single space.
+        createRequest(' ');
+
+        // Multiple spaces.
+        createRequest('    ');
+      });
+
+      function createRequest(separator) {
+        var url = 'http://localhost:' + server.address().port + '/upload';
+        var req = superagent.post(url);
+        req.attach('files[]', fixture('pf1y5.png'), 'SOG2.JPG');
+        req.attach('files[]', fixture('binaryfile.tar.gz'), 'BenF364_LIB353.zip');
+
+        req.end(function(err, resp) {
+          assert.ifError(err);
+          // We don't close the server, to allow other requests to pass.
+        });
+      }
+
+      function fixture(name) {
+        return path.join(FIXTURE_PATH, 'file', name)
+      }
+    },
+  },
+  {
+    name: "maxFields error",
+    fn: function(cb) {
+      var client;
+      var server = http.createServer(function (req, res) {
+        var form = new multiparty.Form({maxFields: 1});
+        form.on('aborted', function () {
+          throw new Error("did not expect aborted");
+        });
+        var first = true;
+        form.on('error', function (err) {
+          assert.ok(first);
+          first = false;
+          client.end();
+          assert.ok(/maxFields/.test(err.message));
+          assert.equal(err.status, 413);
+          server.close(cb);
+        });
+        form.on('end', function () {
+          throw new Error('Unexpected "end" event');
+        });
+        form.parse(req);
+      });
+      server.listen(function() {
+        client = net.connect(server.address().port);
+
+        client.write("POST /upload HTTP/1.1\r\n" +
+          "Content-Length: 728\r\n" +
+          "Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
+          "\r\n" +
+          "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
+          "Content-Disposition: form-data; name=\"title\"\r\n" +
+          "\r\n" +
+          "foofoo" +
+          "\r\n" +
+          "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
+          "Content-Disposition: form-data; name=\"upload\"; filename=\"blah1.txt\"\r\n" +
+          "Content-Type: text/plain\r\n" +
+          "\r\n" +
+          "hi1\r\n" +
+          "\r\n" +
+          "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n");
+      });
+    },
+  },
+  {
+    name: "maxFieldsSize error",
+    fn: function(cb) {
+      var client;
+      var server = http.createServer(function (req, res) {
+        var form = new multiparty.Form({maxFieldsSize: 8});
+        form.on('aborted', function () {
+          throw new Error("did not expect aborted");
+        });
+        var first = true;
+        form.on('error', function (err) {
+          assert.ok(first);
+          first = false;
+          client.end();
+          assert.ok(/maxFieldsSize/.test(err.message));
+          assert.equal(err.status, 413);
+          server.close(cb);
+        });
+        form.on('end', function () {
+          throw new Error('Unexpected "end" event');
+        });
+        form.on('field', function () {});
+        form.parse(req);
+      });
+      server.listen(function() {
+        client = net.connect(server.address().port);
+
+        client.write("POST /upload HTTP/1.1\r\n" +
+          "Content-Length: 678\r\n" +
+          "Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
+          "\r\n" +
+          "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
+          "Content-Disposition: form-data; name=\"title\"\r\n" +
+          "\r\n" +
+          "foofoo" +
+          "\r\n" +
+          "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
+          "Content-Disposition: form-data; name=\"text\"\r\n" +
+          "\r\n" +
+          "hi1\r\n" +
+          "\r\n" +
+          "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n");
+      });
+    },
+  },
+  {
+    name: "issue 21",
+    fn: function(cb) {
+      var client;
+      var server = http.createServer(function(req, res) {
+        var form = new multiparty.Form();
+
+        form.parse(req, function(err, fields, files) {
+          if (err) {
+            console.error(err.stack);
+            return;
+          }
+          var nameCount = 0;
+          var name;
+          for (name in fields) {
+            assert.strictEqual(name, "title");
+            nameCount += 1;
+
+            var values = fields[name];
+            assert.strictEqual(values.length, 1);
+            assert.strictEqual(values[0], "foofoo");
+          }
+          assert.strictEqual(nameCount, 1);
+
+          nameCount = 0;
+          for (name in files) {
+            assert.strictEqual(name, "upload");
+            nameCount += 1;
+
+            var filesList = files[name];
+            assert.strictEqual(filesList.length, 4);
+            filesList.forEach(assertAndUnlink);
+          }
+          
+          assert.strictEqual(nameCount, 1);
+
+          res.end();
+          client.end();
+          server.close(cb);
+
+          function assertAndUnlink(file){
+            assert.strictEqual(file.fieldName, "upload");
+            fs.unlinkSync(file.path);
+          }
+        });
+      });
+      server.listen(function() {
+        client = net.connect(server.address().port);
+
+        client.write("POST /upload HTTP/1.1\r\n" +
+          "Content-Length: 726\r\n" +
+          "Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
+          "\r\n" +
+          "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
+          "Content-Disposition: form-data; name=\"title\"\r\n" +
+          "\r\n" +
+          "foofoo" +
+          "\r\n" +
+          "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
+          "Content-Disposition: form-data; name=\"upload\"; filename=\"blah1.txt\"\r\n" +
+          "Content-Type: text/plain\r\n" +
+          "\r\n" +
+          "hi1\r\n" +
+          "\r\n" +
+          "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
+          "Content-Disposition: form-data; name=\"upload\"; filename=\"blah2.txt\"\r\n" +
+          "Content-Type: text/plain\r\n" +
+          "\r\n" +
+          "hi2\r\n" +
+          "\r\n" +
+          "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
+          "Content-Disposition: form-data; name=\"upload\"; filename=\"blah3.txt\"\r\n" +
+          "Content-Type: text/plain\r\n" +
+          "\r\n" +
+          "hi3\r\n" +
+          "\r\n" +
+          "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
+          "Content-Disposition: form-data; name=\"upload\"; filename=\"blah4.txt\"\r\n" +
+          "Content-Type: text/plain\r\n" +
+          "\r\n" +
+          "hi4\r\n" +
+          "\r\n" +
+          "------WebKitFormBoundaryvfUZhxgsZDO7FXLF--\r\n"
+        );
+      });
+    },
+  },
+  {
+    name: "issue 32",
+    fn: function(cb) {
+      var client;
+      var server = http.createServer(function(req, res) {
+        var form = new multiparty.Form();
+
+        form.parse(req, function(err, fields, files) {
+          if (err) {
+            console.error(err.stack);
+            return;
+          }
+          assert.strictEqual(files.image[0].originalFilename, "测试文档")
+          fs.unlinkSync(files.image[0].path);
+          res.end();
+          client.end();
+          server.close(cb);
+        });
+      });
+      server.listen(function() {
+        client = net.connect(server.address().port);
+
+        client.write(
+          "POST /upload HTTP/1.1\r\n" +
+          "Accept: */*\r\n" +
+          "Content-Type: multipart/form-data; boundary=\"893e5556-f402-4fec-8180-c59333354c6f\"\r\n" +
+          "Content-Length: 187\r\n" +
+          "\r\n" +
+          "--893e5556-f402-4fec-8180-c59333354c6f\r\n" +
+          "Content-Disposition: form-data; name=\"image\"; filename*=utf-8''%E6%B5%8B%E8%AF%95%E6%96%87%E6%A1%A3\r\n" +
+          "\r\n" +
+          "\r\n" +
+          "--893e5556-f402-4fec-8180-c59333354c6f--\r\n"
+        );
+      });
+    },
+  },
+  {
+    name: "issue 36",
+    fn: function(cb) {
+      var client;
+      var server = http.createServer(function(req, res) {
+        var form = new multiparty.Form();
+        var endCalled = false;
+        form.on('part', function(part) {
+          part.on('end', function() {
+            endCalled = true;
+          });
+          part.resume();
+        });
+        form.on('close', function() {
+          assert.ok(endCalled);
+          res.end();
+        });
+        form.parse(req);
+      });
+      server.listen(function() {
+        var url = 'http://localhost:' + server.address().port + '/'
+        var req = superagent.post(url)
+        req.set('Content-Type', 'multipart/form-data; boundary=--WebKitFormBoundaryvfUZhxgsZDO7FXLF')
+        req.set('Content-Length', '186')
+        req.write('----WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n');
+        req.write('Content-Disposition: form-data; name="upload"; filename="blah1.txt"\r\n');
+        req.write('Content-Type: plain/text\r\n');
+        req.write('\r\n');
+        req.write('hi1\r\n');
+        req.write('\r\n');
+        req.write('----WebKitFormBoundaryvfUZhxgsZDO7FXLF--\r\n');
+        req.end(function(err, resp) {
+          server.close(cb);
+        });
+      });
+    },
+  },
+  {
+    name: "issue 4",
+    fn: function(cb) {
+      var server = http.createServer(function(req, res) {
+        assert.strictEqual(req.url, '/upload');
+        assert.strictEqual(req.method, 'POST');
+
+        var form = new multiparty.Form({autoFields:true,autoFiles:true});
+
+        form.on('error', function(err) {
+          console.log(err);
+        });
+
+        form.on('close', function() {
+        });
+
+        var fileCount = 0;
+        form.on('file', function(name, file) {
+          fileCount += 1;
+          fs.unlink(file.path, function () {});
+        });
+
+        form.parse(req, function(err, fields, files) {
+          var objFileCount = 0;
+          for (var file in files) {
+            objFileCount += 1;
+          }
+          // multiparty does NOT try to do intelligent things based on
+          // the part name.
+          assert.strictEqual(fileCount, 2);
+          assert.strictEqual(objFileCount, 1);
+          res.end();
+        });
+      });
+      server.listen(function() {
+        var url = 'http://localhost:' + server.address().port + '/upload';
+        var req = superagent.post(url);
+        req.attach('files[]', fixture('pf1y5.png'), 'SOG2.JPG');
+        req.attach('files[]', fixture('binaryfile.tar.gz'), 'BenF364_LIB353.zip');
+        req.end(function(err, resp) {
+          assert.ifError(err);
+          resp.on('end', function() {
+            server.close(cb);
+          });
+        });
+      });
+      function fixture(name) {
+        return path.join(FIXTURE_PATH, 'file', name)
+      }
+    },
+  },
+  {
+    name: "max fields",
+    fn: function(cb) {
+      var server = http.createServer(function(req, res) {
+        assert.strictEqual(req.url, '/upload');
+        assert.strictEqual(req.method, 'POST');
+
+        var form = new multiparty.Form({autoFiles:true,maxFields:2});
+
+        var first = true;
+        form.on('error', function (err) {
+          assert.ok(first);
+          first = false;
+          assert.ok(/maxFields/.test(err.message));
+          assert.equal(err.status, 413);
+        });
+
+        var fieldCount = 0;
+        form.on('field', function() {
+          fieldCount += 1;
+        });
+
+        form.parse(req, function(err, fields, files) {
+          assert.ok(!first);
+          assert.ok(fieldCount <= 2);
+          res.statusCode = 413;
+          res.end('too many fields');
+        });
+      });
+      server.listen(function() {
+        var url = 'http://localhost:' + server.address().port + '/upload';
+        var req = superagent.post(url);
+        var val = new Buffer(10 * 1024);
+        req.field('a', val);
+        req.field('b', val);
+        req.field('c', val);
+        req.on('error', function(err) {
+          assert.ifError(err);
+        });
+        req.end();
+        req.on('response', function(res) {
+          assert.equal(res.statusCode, 413);
+          server.close(cb);
+        });
+      });
+
+      function fixture(name) {
+        return path.join(FIXTURE_PATH, 'file', name)
+      }
+    },
+  },
+  {
+    name: "max files size exact",
+    fn: function(cb) {
+      var server = http.createServer(function(req, res) {
+        assert.strictEqual(req.url, '/upload');
+        assert.strictEqual(req.method, 'POST');
+
+        var form = new multiparty.Form({autoFiles:true,maxFilesSize:768323}); // exact size of pf1y5.png
+
+        var fileCount = 0;
+        form.on('file', function(name, file) {
+          fileCount += 1;
+          fs.unlink(file.path, function() {});
+        });
+
+        form.parse(req, function(err, fields, files) {
+          assert.ifError(err);
+          assert.ok(fileCount === 1);
+          res.end('OK');
+        });
+      });
+      server.listen(function() {
+        var url = 'http://localhost:' + server.address().port + '/upload';
+        var req = superagent.post(url);
+        req.attach('file0', fixture('pf1y5.png'), 'SOG1.JPG');
+        req.on('error', function(err) {
+          assert.ifError(err);
+        });
+        req.end();
+        req.on('response', function(res) {
+          assert.equal(res.statusCode, 200);
+          server.close(cb);
+        });
+      });
+
+      function fixture(name) {
+        return path.join(FIXTURE_PATH, 'file', name)
+      }
+    },
+  },
+  {
+    name: "max files size",
+    fn: function(cb) {
+      var server = http.createServer(function(req, res) {
+        assert.strictEqual(req.url, '/upload');
+        assert.strictEqual(req.method, 'POST');
+
+        var form = new multiparty.Form({autoFiles:true,maxFilesSize:800*1024});
+
+        var first = true;
+        form.on('error', function (err) {
+          assert.ok(first);
+          first = false;
+          assert.strictEqual(err.code, 'ETOOBIG');
+          assert.strictEqual(err.status, 413);
+        });
+
+        var fileCount = 0;
+        form.on('file', function(name, file) {
+          fileCount += 1;
+          fs.unlinkSync(file.path);
+        });
+
+        form.parse(req, function(err, fields, files) {
+          assert.ok(fileCount <= 1);
+          res.statusCode = 413;
+          res.end('files too large');
+        });
+      });
+      server.listen(function() {
+        var url = 'http://localhost:' + server.address().port + '/upload';
+        var req = superagent.post(url);
+        req.attach('file0', fixture('pf1y5.png'), 'SOG1.JPG');
+        req.attach('file1', fixture('pf1y5.png'), 'SOG2.JPG');
+        req.on('error', function(err) {
+          assert.ifError(err);
+        });
+        req.end();
+        req.on('response', function(res) {
+          assert.equal(res.statusCode, 413);
+          server.close(cb);
+        });
+      });
+
+      function fixture(name) {
+        return path.join(FIXTURE_PATH, 'file', name)
+      }
+    },
+  },
+  {
+    name: "missing boundary end",
+    fn: function(cb) {
+      var server = http.createServer(function(req, resp) {
+        var form = new multiparty.Form();
+
+        var errCount = 0;
+        form.on('error', function (err) {
+          assert.ok(err);
+          assert.equal(err.message, 'stream ended unexpectedly');
+          assert.equal(err.status, 400);
+          errCount += 1;
+          resp.end();
+        });
+        form.on('part', function (part) {
+          part.resume();
+        });
+        form.on('close', function () {
+          assert.equal(errCount, 1);
+        })
+
+        form.parse(req);
+      });
+      server.listen(function() {
+        var url = 'http://localhost:' + server.address().port + '/'
+        var req = superagent.post(url)
+        req.set('Content-Type', 'multipart/form-data; boundary=--WebKitFormBoundaryE19zNvXGzXaLvS5C')
+        req.write('----WebKitFormBoundaryE19zNvXGzXaLvS5C\r\n');
+        req.write('Content-Disposition: form-data; name="a[b]"\r\n');
+        req.write('\r\n');
+        req.write('3\r\n');
+        req.write('----WebKitFormBoundaryE19zNvXGzXaLvS5C\r\n');
+        req.write('Content-Disposition: form-data; name="a[c]"\r\n');
+        req.write('\r\n');
+        req.write('4\r\n');
+        req.write('----WebKitFormBoundaryE19zNvXGzXaLvS5C\r\n');
+        req.write('Content-Disposition: form-data; name="file"; filename="test.txt"\r\n');
+        req.write('Content-Type: plain/text\r\n');
+        req.write('\r\n');
+        req.write('and\r\n');
+        req.write('----WebKitFormBoundaryE19zNvXGzXaLvS5C\r\n');
+        req.end(function(err, resp) {
+          server.close(cb);
+        });
+      });
+    },
+  },
+  {
+    name: "missing content-type error",
+    fn: function(cb) {
+      var server = http.createServer(function(req, res) {
+        assert.strictEqual(req.url, '/upload');
+        assert.strictEqual(req.method, 'POST');
+
+        var form = new multiparty.Form();
+
+        form.parse(req, function(err, fields, files) {
+          assert.ok(err);
+          assert.equal(err.message, 'missing content-type header');
+          assert.equal(err.status, 415);
+          res.statusCode = 415;
+          res.end();
+        });
+      });
+      server.listen(function() {
+        var url = 'http://localhost:' + server.address().port + '/upload';
+        var req = superagent.post(url);
+        req.on('error', function(err) {
+          assert.ifError(err);
+        });
+        req.end();
+        req.on('response', function(res) {
+          assert.equal(res.statusCode, 415);
+          server.close(cb);
+        });
+      });
+
+      function fixture(name) {
+        return path.join(FIXTURE_PATH, 'file', name)
+      }
+    },
+  },
+  {
+    name: "unsupported content-type error",
+    fn: function(cb) {
+      var server = http.createServer(function(req, res) {
+        assert.strictEqual(req.url, '/upload');
+        assert.strictEqual(req.method, 'POST');
+
+        var form = new multiparty.Form();
+
+        form.parse(req, function(err, fields, files) {
+          assert.ok(err);
+          assert.equal(err.message, 'unsupported content-type');
+          assert.equal(err.status, 415);
+          res.statusCode = 415;
+          res.end();
+        });
+      });
+      server.listen(function() {
+        var url = 'http://localhost:' + server.address().port + '/upload';
+        var req = superagent.post(url);
+        req.set('Content-Type', 'application/json');
+        req.write('{}');
+        req.on('error', function(err) {
+          assert.ifError(err);
+        });
+        req.end();
+        req.on('response', function(res) {
+          assert.equal(res.statusCode, 415);
+          server.close(cb);
+        });
+      });
+
+      function fixture(name) {
+        return path.join(FIXTURE_PATH, 'file', name)
+      }
+    },
+  },
+  {
+    name: "content-type missing boundary error",
+    fn: function(cb) {
+      var server = http.createServer(function(req, res) {
+        assert.strictEqual(req.url, '/upload');
+        assert.strictEqual(req.method, 'POST');
+
+        var form = new multiparty.Form();
+
+        form.parse(req, function(err, fields, files) {
+          assert.ok(err);
+          assert.equal(err.message, 'content-type missing boundary');
+          assert.equal(err.status, 400);
+          res.statusCode = 400;
+          res.end();
+        });
+      });
+      server.listen(function() {
+        var url = 'http://localhost:' + server.address().port + '/upload';
+        var req = superagent.post(url);
+        req.attach('file0', fixture('pf1y5.png'), 'SOG1.JPG');
+        req.on('error', function(err) {
+          assert.ifError(err);
+        });
+        req.end();
+        req.set('Content-Type', 'multipart/form-data');
+        req.on('response', function(res) {
+          assert.equal(res.statusCode, 400);
+          server.close(cb);
+        });
+      });
+
+      function fixture(name) {
+        return path.join(FIXTURE_PATH, 'file', name)
+      }
+    },
+  },
+  {
+    name: "empty header field error",
+    fn: function(cb) {
+      var server = http.createServer(function(req, resp) {
+        var form = new multiparty.Form();
+
+        var partCount = 0;
+        form.on('part', function(part) {
+          part.resume();
+          partCount++;
+          assert.strictEqual(typeof part.byteCount, 'undefined');
+        });
+        form.on('error', function(err) {
+          assert.ok(err);
+          assert.equal(err.message, 'Empty header field');
+          assert.equal(err.statusCode, 400);
+          server.close(cb);
+        });
+        form.on('close', function() {
+          throw new Error('Unexpected "close" event');
+        });
+
+        form.parse(req);
+      });
+      server.listen(function() {
+        var socket = net.connect(server.address().port, 'localhost', function () {
+          socket.write('POST / HTTP/1.1\r\n');
+          socket.write('Host: localhost\r\n');
+          socket.write('Connection: close\r\n');
+          socket.write('Content-Type: multipart/form-data; boundary=foo\r\n');
+          socket.write('Transfer-Encoding: chunked\r\n');
+          socket.write('\r\n');
+          socket.write('7\r\n');
+          socket.write('--foo\r\n\r\n');
+          socket.write('46\r\n');
+          socket.write('Content-Disposition: form-data; name="file"; filename="plain.txt"\r\n:\r\n\r\n');
+          socket.write('12\r\n');
+          socket.write('\r\nsome text here\r\n\r\n');
+          socket.write('9\r\n');
+          socket.write('--foo--\r\n\r\n');
+          socket.write('0\r\n\r\n');
+          socket.end();
+        });
+      });
+    },
+  },
+  {
+    name: "request encoding",
+    fn: function(cb) {
+      var server = http.createServer(function(req, res) {
+        assert.strictEqual(req.url, '/upload');
+        assert.strictEqual(req.method, 'POST');
+
+        var form = new multiparty.Form();
+
+        // this is invalid
+        req.setEncoding('utf8');
+
+        form.parse(req, function(err, fields, files) {
+          assert.ok(err);
+          assert.equal(err.message, 'request encoding must not be set');
+          res.statusCode = 500;
+          res.end();
+        });
+      });
+      server.listen(function() {
+        var url = 'http://localhost:' + server.address().port + '/upload';
+        var req = superagent.post(url);
+        req.attach('file0', fixture('pf1y5.png'), 'SOG1.JPG');
+        req.on('error', function(err) {
+          assert.ifError(err);
+        });
+        req.end();
+        req.on('response', function(res) {
+          assert.equal(res.statusCode, 500);
+          server.close(cb);
+        });
+      });
+
+      function fixture(name) {
+        return path.join(FIXTURE_PATH, 'file', name)
+      }
+    },
+  },
+  {
+    name: "stream error",
+    fn: function(cb) {
+      var server = http.createServer(function (req, res) {
+        var form = new multiparty.Form();
+        var gotPartErr;
+        form.on('part', function(part) {
+          part.on('error', function(err) {
+            gotPartErr = err;
+          });
+          part.resume();
+        });
+        form.on('error', function () {
+          assert.ok(gotPartErr);
+          server.close(cb);
+        });
+        form.on('close', function () {
+          throw new Error('Unexpected "close" event');
+        });
+        form.parse(req);
+      }).listen(0, 'localhost', function () {
+        var client = net.connect(server.address().port);
+        client.write(
+          "POST / HTTP/1.1\r\n" +
+          "Content-Length: 186\r\n" +
+          "Content-Type: multipart/form-data; boundary=--WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
+          "\r\n" +
+          "----WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
+          "Content-Disposition: form-data; name=\"upload\"; filename=\"blah1.txt\"\r\n" +
+          "Content-Type: plain/text\r\n" +
+          "\r\n" +
+          "hi1\r\n");
+        client.end();
+      });
+    },
+  },
+  {
+    name: "queued part error",
+    fn: function(cb) {
+      var server = http.createServer(function (req, res) {
+        var form = new multiparty.Form();
+        var pend = new Pend();
+
+        pend.go(function(cb){
+          form.on('part', function(part){
+            part.on('error', function(err){
+              assert.ok(err);
+              assert.equal(err.message, 'stream ended unexpectedly');
+              cb();
+            });
+            part.resume();
+          });
+        });
+
+        pend.go(function(cb){
+          form.on('field', function(){
+            cb();
+          });
+        });
+
+        pend.go(function(cb){
+          form.on('error', function(err){
+            assert.ok(err);
+            assert.equal(err.message, 'stream ended unexpectedly');
+            cb();
+          });
+        });
+
+        pend.wait(function(){
+          server.close(cb);
+        });
+
+        form.on('close', function () {
+          throw new Error('Unexpected "close" event');
+        });
+
+        form.parse(req);
+      }).listen(0, 'localhost', function () {
+        var client = net.connect(server.address().port);
+        client.end(
+          "POST / HTTP/1.1\r\n" +
+          "Content-Length: 174\r\n" +
+          "Content-Type: multipart/form-data; boundary=--bounds\r\n" +
+          "\r\n" +
+          "----bounds\r\n" +
+          "Content-Disposition: form-data; name=\"key\"\r\n" +
+          "\r\n" +
+          "hi\r\n" +
+          "----bounds\r\n" +
+          "Content-Disposition: form-data; name=\"upload\"; filename=\"blah1.txt\"\r\n" +
+          "Content-Type: plain/text\r\n" +
+          "\r\n" +
+          "bye");
+      });
+    },
+  },
+];
+
 resetTempDir(startFixtureTests);
 
 function startFixtureTests() {
-  console.log("Fixture tests:");
+  console.error("Fixture tests:");
   var walker = findit(path.join(FIXTURE_PATH, 'js'));
   var pend = new Pend();
   pend.max = 1;
@@ -44,43 +1273,26 @@ function startFixtureTests() {
 }
 
 function startStandaloneTests() {
-  console.log("\nStandalone tests:");
-  var walker = findit(STANDALONE_PATH);
+  console.error("\nStandalone tests:");
   var pend = new Pend();
   pend.max = 1;
-  walker.on('file', function(jsPath) {
-    if (!/\.js$/.test(jsPath)) return;
+  standaloneTests.forEach(function(test) {
     pend.go(function(cb) {
-      var name = path.basename(jsPath, '.js');
-      process.stdout.write(name + "...");
-      var child = spawn(process.execPath, [jsPath], { env: { TMPDIR: TMP_PATH }, stdio: 'inherit' });
-      child.on('error', function(err) {
-        throw err;
-      });
-      child.on('exit', function(code) {
-        if (code) throw new Error("exited with code " + code);
-        var tmpWalker = findit(TMP_PATH);
-        var fileNames = [];
-        tmpWalker.on('file', function(file) {
-          fileNames.push(file);
-        });
-        tmpWalker.on('end', function() {
-          if (fileNames.length) {
-            cleanFiles(fileNames);
-            throw new Error("failed to clean up auto files: " + fileNames.join(', '));
-          } else {
-            console.log("OK");
-            cb();
-          }
-        });
+      process.stderr.write(test.name + "...");
+      var timeoutRef = setTimeout(timeout, 2000);
+      test.fn(function(err) {
+        clearTimeout(timeoutRef);
+        if (err) throw err;
+        process.stderr.write("OK\n");
+        cb();
       });
+      function timeout() {
+        throw new Error("timeout");
+      }
     });
   });
-  walker.on('end', function() {
-    pend.wait(function(err) {
-      if (err) throw err;
-      console.log("\nAll tests passed.");
-    });
+  pend.wait(function() {
+    console.error("\nAll tests passed.");
   });
 }
 
@@ -107,12 +1319,6 @@ function createFixtureTest(name, fixture) {
   };
 }
 
-function cleanFiles(fileNames) {
-  fileNames.forEach(function(fileName) {
-    fs.unlinkSync(fileName);
-  });
-}
-
 function resetTempDir(cb) {
   rimraf(TMP_PATH, function(err) {
     if (err) throw err;

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-multiparty.git



More information about the Pkg-javascript-commits mailing list