[Pkg-javascript-commits] [node-tmp] 01/03: Imported Upstream version 0.0.24

Sebastiaan Couwenberg sebastic at moszumanska.debian.org
Sat Feb 28 20:39:39 UTC 2015


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

sebastic pushed a commit to branch master
in repository node-tmp.

commit ba1f6ac99ecf7e284070afc4d4b85daba8fcddce
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Sat Feb 28 17:03:13 2015 +0100

    Imported Upstream version 0.0.24
---
 .gitignore             |   2 +
 .travis.yml            |   5 +
 README.md              | 162 ++++++++++++++++++++++++++
 lib/tmp.js             | 307 +++++++++++++++++++++++++++++++++++++++++++++++++
 package.json           |  41 +++++++
 test/base.js           |  74 ++++++++++++
 test/dir-test.js       | 196 +++++++++++++++++++++++++++++++
 test/file-test.js      | 177 ++++++++++++++++++++++++++++
 test/graceful.js       |  15 +++
 test/keep.js           |  11 ++
 test/name-test.js      |  82 +++++++++++++
 test/spawn.js          |  32 ++++++
 test/symlinkme/file.js |   0
 test/unsafe.js         |  30 +++++
 14 files changed, 1134 insertions(+)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..78f2710
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+node_modules/
+.idea/
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..0175d82
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,5 @@
+language: node_js
+node_js:
+  - "0.6"
+  - "0.8"
+  - "0.10"
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..3a1a509
--- /dev/null
+++ b/README.md
@@ -0,0 +1,162 @@
+# Tmp
+
+A simple temporary file and directory creator for [node.js.][1]
+
+[![Build Status](https://secure.travis-ci.org/raszi/node-tmp.png?branch=master)](http://travis-ci.org/raszi/node-tmp)
+
+## About
+
+The main difference between bruce's [node-temp][2] is that mine more
+aggressively checks for the existence of the newly created temporary file and
+creates the new file with `O_EXCL` instead of simple `O_CREAT | O_RDRW`, so it
+is safer.
+
+The API is slightly different as well, Tmp does not yet provide synchronous
+calls and all the parameters are optional.
+
+You can set whether you want to remove the temporary file on process exit or
+not, and the destination directory can also be set.
+
+## How to install
+
+```bash
+npm install tmp
+```
+
+## Usage
+
+### File creation
+
+Simple temporary file creation, the file will be unlinked on process exit.
+
+```javascript
+var tmp = require('tmp');
+
+tmp.file(function _tempFileCreated(err, path, fd) {
+  if (err) throw err;
+
+  console.log("File: ", path);
+  console.log("Filedescriptor: ", fd);
+});
+```
+
+### Directory creation
+
+Simple temporary directory creation, it will be removed on process exit.
+
+If the directory still contains items on process exit, then it won't be removed.
+
+```javascript
+var tmp = require('tmp');
+
+tmp.dir(function _tempDirCreated(err, path) {
+  if (err) throw err;
+
+  console.log("Dir: ", path);
+});
+```
+
+If you want to cleanup the directory even when there are entries in it, then
+you can pass the `unsafeCleanup` option when creating it.
+
+### Filename generation
+
+It is possible with this library to generate a unique filename in the specified
+directory.
+
+```javascript
+var tmp = require('tmp');
+
+tmp.tmpName(function _tempNameGenerated(err, path) {
+    if (err) throw err;
+
+    console.log("Created temporary filename: ", path);
+});
+```
+
+## Advanced usage
+
+### File creation
+
+Creates a file with mode `0644`, prefix will be `prefix-` and postfix will be `.txt`.
+
+```javascript
+var tmp = require('tmp');
+
+tmp.file({ mode: 0644, prefix: 'prefix-', postfix: '.txt' }, function _tempFileCreated(err, path, fd) {
+  if (err) throw err;
+
+  console.log("File: ", path);
+  console.log("Filedescriptor: ", fd);
+});
+```
+
+### Directory creation
+
+Creates a directory with mode `0755`, prefix will be `myTmpDir_`.
+
+```javascript
+var tmp = require('tmp');
+
+tmp.dir({ mode: 0750, prefix: 'myTmpDir_' }, function _tempDirCreated(err, path) {
+  if (err) throw err;
+
+  console.log("Dir: ", path);
+});
+```
+
+### mkstemps like
+
+Creates a new temporary directory with mode `0700` and filename like `/tmp/tmp-nk2J1u`.
+
+```javascript
+var tmp = require('tmp');
+
+tmp.dir({ template: '/tmp/tmp-XXXXXX' }, function _tempDirCreated(err, path) {
+  if (err) throw err;
+
+  console.log("Dir: ", path);
+});
+```
+
+### Filename generation
+
+The `tmpName()` function accepts the `prefix`, `postfix`, `dir`, etc. parameters also:
+
+```javascript
+var tmp = require('tmp');
+
+tmp.tmpName({ template: '/tmp/tmp-XXXXXX' }, function _tempNameGenerated(err, path) {
+    if (err) throw err;
+
+    console.log("Created temporary filename: ", path);
+});
+```
+
+## Graceful cleanup
+
+One may want to cleanup the temporary files even when an uncaught exception
+occurs. To enforce this, you can call the `setGracefulCleanup()` method:
+
+```javascript
+var tmp = require('tmp');
+
+tmp.setGracefulCleanup();
+```
+
+## Options
+
+All options are optional :)
+
+  * `mode`: the file mode to create with, it fallbacks to `0600` on file creation and `0700` on directory creation
+  * `prefix`: the optional prefix, fallbacks to `tmp-` if not provided
+  * `postfix`: the optional postfix, fallbacks to `.tmp` on file creation
+  * `template`: [`mkstemps`][3] like filename template, no default
+  * `dir`: the optional temporary directory, fallbacks to system default (guesses from environment)
+  * `tries`: how many times should the function try to get a unique filename before giving up, default `3`
+  * `keep`: signals that the temporary file or directory should not be deleted on exit, default is `false`, means delete
+  * `unsafeCleanup`: recursively removes the created temporary directory, even when it's not empty. default is `false`
+
+[1]: http://nodejs.org/
+[2]: https://github.com/bruce/node-temp
+[3]: http://www.kernel.org/doc/man-pages/online/pages/man3/mkstemp.3.html
diff --git a/lib/tmp.js b/lib/tmp.js
new file mode 100644
index 0000000..ea84faa
--- /dev/null
+++ b/lib/tmp.js
@@ -0,0 +1,307 @@
+/*!
+ * Tmp
+ *
+ * Copyright (c) 2011-2013 KARASZI Istvan <github at spam.raszi.hu>
+ *
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+var
+  fs     = require('fs'),
+  path   = require('path'),
+  os     = require('os'),
+  exists = fs.exists || path.exists,
+  tmpDir = os.tmpDir || _getTMPDir,
+  _c     = require('constants');
+
+/**
+ * The working inner variables.
+ */
+var
+  // store the actual TMP directory
+  _TMP = tmpDir(),
+
+  // the random characters to choose from
+  randomChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz",
+  randomCharsLength = randomChars.length,
+
+  // this will hold the objects need to be removed on exit
+  _removeObjects = [],
+
+  _gracefulCleanup = false,
+  _uncaughtException = false;
+
+/**
+ * Gets the temp directory.
+ *
+ * @return {String}
+ * @api private
+ */
+function _getTMPDir() {
+  var tmpNames = [ 'TMPDIR', 'TMP', 'TEMP' ];
+
+  for (var i = 0, length = tmpNames.length; i < length; i++) {
+    if (_isUndefined(process.env[tmpNames[i]])) continue;
+
+    return process.env[tmpNames[i]];
+  }
+
+  // fallback to the default
+  return '/tmp';
+}
+
+/**
+ * Checks whether the `obj` parameter is defined or not.
+ *
+ * @param {Object} obj
+ * @return {Boolean}
+ * @api private
+ */
+function _isUndefined(obj) {
+  return typeof obj === 'undefined';
+}
+
+/**
+ * Parses the function arguments.
+ *
+ * This function helps to have optional arguments.
+ *
+ * @param {Object} options
+ * @param {Function} callback
+ * @api private
+ */
+function _parseArguments(options, callback) {
+  if (!callback || typeof callback != "function") {
+    callback = options;
+    options = {};
+  }
+
+  return [ options, callback ];
+}
+
+/**
+ * Gets a temporary file name.
+ *
+ * @param {Object} opts
+ * @param {Function} cb
+ * @api private
+ */
+function _getTmpName(options, callback) {
+  var
+    args = _parseArguments(options, callback),
+    opts = args[0],
+    cb = args[1],
+    template = opts.template,
+    templateDefined = !_isUndefined(template),
+    tries = opts.tries || 3;
+
+  if (isNaN(tries) || tries < 0)
+    return cb(new Error('Invalid tries'));
+
+  if (templateDefined && !template.match(/XXXXXX/))
+    return cb(new Error('Invalid template provided'));
+
+  function _getName() {
+
+    // prefix and postfix
+    if (!templateDefined) {
+      var name = [
+        (_isUndefined(opts.prefix)) ? 'tmp-' : opts.prefix,
+        process.pid,
+        (Math.random() * 0x1000000000).toString(36),
+        opts.postfix
+      ].join('');
+
+      return path.join(opts.dir || _TMP, name);
+    }
+
+    // mkstemps like template
+    var chars = [];
+
+    for (var i = 0; i < 6; i++) {
+      chars.push(randomChars.substr(Math.floor(Math.random() * randomCharsLength), 1));
+    }
+
+    return template.replace(/XXXXXX/, chars.join(''));
+  }
+
+  (function _getUniqueName() {
+    var name = _getName();
+
+    // check whether the path exists then retry if needed
+    exists(name, function _pathExists(pathExists) {
+      if (pathExists) {
+        if (tries-- > 0) return _getUniqueName();
+
+        return cb(new Error('Could not get a unique tmp filename, max tries reached'));
+      }
+
+      cb(null, name);
+    });
+  }());
+}
+
+/**
+ * Creates and opens a temporary file.
+ *
+ * @param {Object} options
+ * @param {Function} callback
+ * @api public
+ */
+function _createTmpFile(options, callback) {
+  var
+    args = _parseArguments(options, callback),
+    opts = args[0],
+    cb = args[1];
+
+    opts.postfix = (_isUndefined(opts.postfix)) ? '.tmp' : opts.postfix;
+
+  // gets a temporary filename
+  _getTmpName(opts, function _tmpNameCreated(err, name) {
+    if (err) return cb(err);
+
+    // create and open the file
+    fs.open(name, _c.O_CREAT | _c.O_EXCL | _c.O_RDWR, opts.mode || 0600, function _fileCreated(err, fd) {
+      if (err) return cb(err);
+
+      var removeCallback = _prepareRemoveCallback(fs.unlinkSync.bind(fs), name);
+
+      if (!opts.keep) {
+        _removeObjects.unshift(removeCallback);
+      }
+
+      cb(null, name, fd, removeCallback);
+    });
+  });
+}
+
+/**
+ * Removes files and folders in a directory recursively.
+ *
+ * @param {String} dir
+ */
+function _rmdirRecursiveSync(dir) {
+  var files = fs.readdirSync(dir);
+
+  for (var i = 0, length = files.length; i < length; i++) {
+    var file = path.join(dir, files[i]);
+    // lstat so we don't recurse into symlinked directories.
+    var stat = fs.lstatSync(file);
+
+    if (stat.isDirectory()) {
+      _rmdirRecursiveSync(file);
+    } else {
+      fs.unlinkSync(file);
+    }
+  }
+
+  fs.rmdirSync(dir);
+}
+
+/**
+ *
+ * @param {Function} removeFunction
+ * @param {String} path
+ * @returns {Function}
+ * @private
+ */
+function _prepareRemoveCallback(removeFunction, path) {
+  var called = false;
+  return function() {
+    if (called) {
+      return;
+    }
+
+    removeFunction(path);
+
+    called = true;
+  };
+}
+
+/**
+ * Creates a temporary directory.
+ *
+ * @param {Object} options
+ * @param {Function} callback
+ * @api public
+ */
+function _createTmpDir(options, callback) {
+  var
+    args = _parseArguments(options, callback),
+    opts = args[0],
+    cb = args[1];
+
+  // gets a temporary filename
+  _getTmpName(opts, function _tmpNameCreated(err, name) {
+    if (err) return cb(err);
+
+    // create the directory
+    fs.mkdir(name, opts.mode || 0700, function _dirCreated(err) {
+      if (err) return cb(err);
+
+      var removeCallback = _prepareRemoveCallback(
+        opts.unsafeCleanup
+          ? _rmdirRecursiveSync
+          : fs.rmdirSync.bind(fs),
+        name
+      );
+
+      if (!opts.keep) {
+        _removeObjects.unshift(removeCallback);
+      }
+
+      cb(null, name, removeCallback);
+    });
+  });
+}
+
+/**
+ * The garbage collector.
+ *
+ * @api private
+ */
+function _garbageCollector() {
+  if (_uncaughtException && !_gracefulCleanup) {
+    return;
+  }
+
+  for (var i = 0, length = _removeObjects.length; i < length; i++) {
+    try {
+      _removeObjects[i].call(null);
+    } catch (e) {
+      // already removed?
+    }
+  }
+}
+
+function _setGracefulCleanup() {
+  _gracefulCleanup = true;
+}
+
+var version = process.versions.node.split('.').map(function (value) {
+  return parseInt(value, 10);
+});
+
+if (version[0] === 0 && (version[1] < 9 || version[1] === 9 && version[2] < 5)) {
+  process.addListener('uncaughtException', function _uncaughtExceptionThrown( err ) {
+    _uncaughtException = true;
+    _garbageCollector();
+
+    throw err;
+  });
+}
+
+process.addListener('exit', function _exit(code) {
+  if (code) _uncaughtException = true;
+  _garbageCollector();
+});
+
+// exporting all the needed methods
+module.exports.tmpdir = _TMP;
+module.exports.dir = _createTmpDir;
+module.exports.file = _createTmpFile;
+module.exports.tmpName = _getTmpName;
+module.exports.setGracefulCleanup = _setGracefulCleanup;
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..eeb3127
--- /dev/null
+++ b/package.json
@@ -0,0 +1,41 @@
+{
+  "name":        "tmp",
+  "version":     "0.0.24",
+  "description": "Temporary file and directory creator",
+  "author":      "KARASZI István <github at spam.raszi.hu> (http://raszi.hu/)",
+
+  "homepage": "http://github.com/raszi/node-tmp",
+  "keywords": [ "temporary", "tmp", "temp", "tempdir", "tempfile", "tmpdir", "tmpfile" ],
+
+  "licenses": [
+    {
+      "type": "MIT",
+      "url": "http://opensource.org/licenses/MIT"
+    }
+  ],
+
+  "repository": {
+    "type": "git",
+    "url":  "git://github.com/raszi/node-tmp.git"
+  },
+
+  "bugs": {
+    "url":  "http://github.com/raszi/node-tmp/issues"
+  },
+
+  "main": "lib/tmp.js",
+
+  "scripts": {
+    "test": "vows test/*-test.js"
+  },
+
+  "engines": {
+    "node": ">=0.4.0"
+  },
+
+  "dependencies": {},
+
+  "devDependencies": {
+    "vows": "~0.7.0"
+  }
+}
diff --git a/test/base.js b/test/base.js
new file mode 100644
index 0000000..498d8fb
--- /dev/null
+++ b/test/base.js
@@ -0,0 +1,74 @@
+var
+  assert = require('assert'),
+  path   = require('path'),
+  exec   = require('child_process').exec;
+
+function _spawnTestWithError(testFile, params, cb) {
+  _spawnTest(true, testFile, params, cb);
+}
+
+function _spawnTestWithoutError(testFile, params, cb) {
+  _spawnTest(false, testFile, params, cb);
+}
+
+function _spawnTest(passError, testFile, params, cb) {
+  var
+    filename,
+    node_path = process.argv[0],
+    command = [ node_path, path.join(__dirname, testFile) ].concat(params).join(' ');
+
+  exec(command, function _execDone(err, stdout, stderr) {
+    if (passError) {
+      if (err) {
+        return cb(err);
+      } else if (stderr.length > 0) {
+        return cb(stderr.toString());
+      }
+    }
+
+    return cb(null, stdout.toString());
+  });
+}
+
+function _testStat(stat, mode) {
+  assert.equal(stat.uid, process.getuid(), 'should have the same UID');
+  assert.equal(stat.gid, process.getgid(), 'should have the same GUID');
+  assert.equal(stat.mode, mode);
+}
+
+function _testPrefix(prefix) {
+  return function _testPrefixGenerated(err, name, fd) {
+    assert.equal(path.basename(name).slice(0, prefix.length), prefix, 'should have the provided prefix');
+  };
+}
+
+function _testPostfix(postfix) {
+  return function _testPostfixGenerated(err, name, fd) {
+    assert.equal(name.slice(name.length - postfix.length, name.length), postfix, 'should have the provided postfix');
+  };
+}
+
+function _testKeep(type, keep, cb) {
+  _spawnTestWithError('keep.js', [ type, keep ], cb);
+}
+
+function _testGraceful(type, graceful, cb) {
+  _spawnTestWithoutError('graceful.js', [ type, graceful ], cb);
+}
+
+function _assertName(err, name) {
+  assert.isString(name);
+  assert.isNotZero(name.length);
+}
+
+function _testUnsafeCleanup(unsafe, cb) {
+  _spawnTestWithoutError('unsafe.js', [ 'dir', unsafe ], cb);
+}
+
+module.exports.testStat = _testStat;
+module.exports.testPrefix = _testPrefix;
+module.exports.testPostfix = _testPostfix;
+module.exports.testKeep = _testKeep;
+module.exports.testGraceful = _testGraceful;
+module.exports.assertName = _assertName;
+module.exports.testUnsafeCleanup = _testUnsafeCleanup;
diff --git a/test/dir-test.js b/test/dir-test.js
new file mode 100644
index 0000000..2e4e529
--- /dev/null
+++ b/test/dir-test.js
@@ -0,0 +1,196 @@
+var
+  vows   = require('vows'),
+  assert = require('assert'),
+
+  path       = require('path'),
+  fs         = require('fs'),
+  existsSync = fs.existsSync || path.existsSync,
+
+  tmp    = require('../lib/tmp.js'),
+  Test   = require('./base.js');
+
+
+function _testDir(mode) {
+  return function _testDirGenerated(err, name) {
+    assert.ok(existsSync(name), 'should exist');
+
+    var stat = fs.statSync(name);
+    assert.ok(stat.isDirectory(), 'should be a directory');
+
+    Test.testStat(stat, mode);
+  };
+}
+
+vows.describe('Directory creation').addBatch({
+  'when using without parameters': {
+    topic: function () {
+      tmp.dir(this.callback);
+    },
+
+    'should be a directory': _testDir(040700),
+    'should have the default prefix': Test.testPrefix('tmp-')
+  },
+
+  'when using with prefix': {
+    topic: function () {
+      tmp.dir({ prefix: 'something' }, this.callback);
+    },
+
+    'should not return with an error': assert.isNull,
+    'should return with a name': Test.assertName,
+    'should be a directory': _testDir(040700),
+    'should have the provided prefix': Test.testPrefix('something')
+  },
+
+  'when using with postfix': {
+    topic: function () {
+      tmp.dir({ postfix: '.txt' }, this.callback);
+    },
+
+    'should not return with an error': assert.isNull,
+    'should return with a name': Test.assertName,
+    'should be a directory': _testDir(040700),
+    'should have the provided postfix': Test.testPostfix('.txt')
+  },
+
+  'when using template': {
+    topic: function () {
+      tmp.dir({ template: path.join(tmp.tmpdir, 'clike-XXXXXX-postfix') }, this.callback);
+    },
+
+    'should not return with error': assert.isNull,
+    'should return with a name': Test.assertName,
+    'should be a file': _testDir(040700),
+    'should have the provided prefix': Test.testPrefix('clike-'),
+    'should have the provided postfix': Test.testPostfix('-postfix')
+  },
+
+  'when using multiple options': {
+    topic: function () {
+      tmp.dir({ prefix: 'foo', postfix: 'bar', mode: 0750 }, this.callback);
+    },
+
+    'should not return with an error': assert.isNull,
+    'should return with a name': Test.assertName,
+    'should be a directory': _testDir(040750),
+    'should have the provided prefix': Test.testPrefix('foo'),
+    'should have the provided postfix': Test.testPostfix('bar')
+  },
+
+  'when using multiple options and mode': {
+    topic: function () {
+      tmp.dir({ prefix: 'complicated', postfix: 'options', mode: 0755 }, this.callback);
+    },
+
+    'should not return with an error': assert.isNull,
+    'should return with a name': Test.assertName,
+    'should be a directory': _testDir(040755),
+    'should have the provided prefix': Test.testPrefix('complicated'),
+    'should have the provided postfix': Test.testPostfix('options')
+  },
+
+  'no tries': {
+    topic: function () {
+      tmp.dir({ tries: -1 }, this.callback);
+    },
+
+    'should return with an error': assert.isObject
+  },
+
+  'keep testing': {
+    topic: function () {
+      Test.testKeep('dir', '1', this.callback);
+    },
+
+    'should not return with an error': assert.isNull,
+    'should return with a name': Test.assertName,
+    'should be a dir': function (err, name) {
+      _testDir(040700)(err, name);
+      fs.rmdirSync(name);
+    }
+  },
+
+  'unlink testing': {
+    topic: function () {
+      Test.testKeep('dir', '0', this.callback);
+    },
+
+    'should not return with error': assert.isNull,
+    'should return with a name': Test.assertName,
+    'should not exist': function (err, name) {
+      assert.ok(!existsSync(name), "Directory should be removed");
+    }
+  },
+
+  'non graceful testing': {
+    topic: function () {
+      Test.testGraceful('dir', '0', this.callback);
+    },
+
+    'should not return with error': assert.isNull,
+    'should return with a name': Test.assertName,
+    'should be a dir': function (err, name) {
+      _testDir(040700)(err, name);
+      fs.rmdirSync(name);
+    }
+  },
+
+  'graceful testing': {
+    topic: function () {
+      Test.testGraceful('dir', '1', this.callback);
+    },
+
+    'should not return with an error': assert.isNull,
+    'should return with a name': Test.assertName,
+    'should not exist': function (err, name) {
+      assert.ok(!existsSync(name), "Directory should be removed");
+    }
+  },
+
+  'unsafeCleanup === true': {
+    topic: function () {
+      Test.testUnsafeCleanup('1', this.callback);
+    },
+
+    'should not return with an error': assert.isNull,
+    'should return with a name': Test.assertName,
+    'should not exist': function (err, name) {
+      assert.ok(!existsSync(name), "Directory should be removed");
+    },
+    'should remove symlinked dir': function(err, name) {
+      assert.ok(
+        !existsSync(name + '/symlinkme-target'),
+        'should remove target'
+      );
+    },
+    'should not remove contents of symlink dir': function(err, name) {
+      assert.ok(
+        existsSync(__dirname + '/symlinkme/file.js'),
+        'should not remove symlinked directory\'s content'
+      );
+    }
+  },
+
+  'unsafeCleanup === false': {
+    topic: function () {
+      Test.testUnsafeCleanup('0', this.callback);
+    },
+
+    'should not return with an error': assert.isNull,
+    'should return with a name': Test.assertName,
+    'should be a directory': _testDir(040700)
+  },
+
+  'remove callback': {
+    topic: function () {
+      tmp.dir(this.callback);
+    },
+
+    'should not return with an error': assert.isNull,
+    'should return with a name': Test.assertName,
+    'removeCallback should remove directory': function (_err, name, removeCallback) {
+      removeCallback();
+      assert.ok(!existsSync(name), "Directory should be removed");
+    }
+  }
+}).exportTo(module);
diff --git a/test/file-test.js b/test/file-test.js
new file mode 100644
index 0000000..d9605b3
--- /dev/null
+++ b/test/file-test.js
@@ -0,0 +1,177 @@
+var
+  vows   = require('vows'),
+  assert = require('assert'),
+
+  path       = require('path'),
+  fs         = require('fs'),
+  existsSync = fs.existsSync || path.existsSync,
+
+  tmp    = require('../lib/tmp.js'),
+  Test   = require('./base.js');
+
+
+function _testFile(mode, fdTest) {
+  return function _testFileGenerated(err, name, fd) {
+    assert.ok(existsSync(name), 'should exist');
+
+    var stat = fs.statSync(name);
+    assert.equal(stat.size, 0, 'should have zero size');
+    assert.ok(stat.isFile(), 'should be a file');
+
+    Test.testStat(stat, mode);
+
+    // check with fstat as well (fd checking)
+    if (fdTest) {
+      var fstat = fs.fstatSync(fd);
+      assert.deepEqual(fstat, stat, 'fstat results should be the same');
+
+      var data = new Buffer('something');
+      assert.equal(fs.writeSync(fd, data, 0, data.length, 0), data.length, 'should be writable');
+      assert.ok(!fs.closeSync(fd), 'should not return with error');
+    }
+  };
+}
+
+vows.describe('File creation').addBatch({
+  'when using without parameters': {
+    topic: function () {
+      tmp.file(this.callback);
+    },
+
+    'should not return with an error': assert.isNull,
+    'should return with a name': Test.assertName,
+    'should be a file': _testFile(0100600, true),
+    'should have the default prefix': Test.testPrefix('tmp-'),
+    'should have the default postfix': Test.testPostfix('.tmp')
+  },
+
+  'when using with prefix': {
+    topic: function () {
+      tmp.file({ prefix: 'something' }, this.callback);
+    },
+
+    'should not return with an error': assert.isNull,
+    'should return with a name': Test.assertName,
+    'should be a file': _testFile(0100600, true),
+    'should have the provided prefix': Test.testPrefix('something')
+  },
+
+  'when using with postfix': {
+    topic: function () {
+      tmp.file({ postfix: '.txt' }, this.callback);
+    },
+
+    'should not return with an error': assert.isNull,
+    'should return with a name': Test.assertName,
+    'should be a file': _testFile(0100600, true),
+    'should have the provided postfix': Test.testPostfix('.txt')
+  },
+
+  'when using template': {
+    topic: function () {
+      tmp.file({ template: path.join(tmp.tmpdir, 'clike-XXXXXX-postfix') }, this.callback);
+    },
+
+    'should not return with an error': assert.isNull,
+    'should return with a name': Test.assertName,
+    'should be a file': _testFile(0100600, true),
+    'should have the provided prefix': Test.testPrefix('clike-'),
+    'should have the provided postfix': Test.testPostfix('-postfix')
+  },
+
+  'when using multiple options': {
+    topic: function () {
+      tmp.file({ prefix: 'foo', postfix: 'bar', mode: 0640 }, this.callback);
+    },
+
+    'should not return with an error': assert.isNull,
+    'should return with a name': Test.assertName,
+    'should be a file': _testFile(0100640, true),
+    'should have the provided prefix': Test.testPrefix('foo'),
+    'should have the provided postfix': Test.testPostfix('bar')
+  },
+
+  'when using multiple options and mode': {
+    topic: function () {
+      tmp.file({ prefix: 'complicated', postfix: 'options', mode: 0644 }, this.callback);
+    },
+
+    'should not return with an error': assert.isNull,
+    'should return with a name': Test.assertName,
+    'should be a file': _testFile(0100644, true),
+    'should have the provided prefix': Test.testPrefix('complicated'),
+    'should have the provided postfix': Test.testPostfix('options')
+  },
+
+  'no tries': {
+    topic: function () {
+      tmp.file({ tries: -1 }, this.callback);
+    },
+
+    'should not be created': assert.isObject
+  },
+
+  'keep testing': {
+    topic: function () {
+      Test.testKeep('file', '1', this.callback);
+    },
+
+    'should not return with an error': assert.isNull,
+    'should return with a name': Test.assertName,
+    'should be a file': function (err, name) {
+      _testFile(0100600, false)(err, name, null);
+      fs.unlinkSync(name);
+    }
+  },
+
+  'unlink testing': {
+    topic: function () {
+      Test.testKeep('file', '0', this.callback);
+    },
+
+    'should not return with an error': assert.isNull,
+    'should return with a name': Test.assertName,
+    'should not exist': function (err, name) {
+      assert.ok(!existsSync(name), "File should be removed");
+    }
+  },
+
+  'non graceful testing': {
+    topic: function () {
+      Test.testGraceful('file', '0', this.callback);
+    },
+
+    'should not return with error': assert.isNull,
+    'should return with a name': Test.assertName,
+    'should be a file': function (err, name) {
+      _testFile(0100600, false)(err, name, null);
+      fs.unlinkSync(name);
+    }
+  },
+
+  'graceful testing': {
+    topic: function () {
+      Test.testGraceful('file', '1', this.callback);
+    },
+
+    'should not return with an error': assert.isNull,
+    'should return with a name': Test.assertName,
+    'should not exist': function (err, name) {
+      assert.ok(!existsSync(name), "File should be removed");
+    }
+  },
+
+  'remove callback': {
+    topic: function () {
+      tmp.file(this.callback);
+    },
+
+    'should not return with an error': assert.isNull,
+    'should return with a name': Test.assertName,
+    'removeCallback should remove file': function (_err, name, _fd, removeCallback) {
+      removeCallback();
+      assert.ok(!existsSync(name), "File should be removed");
+    }
+  }
+
+}).exportTo(module);
diff --git a/test/graceful.js b/test/graceful.js
new file mode 100644
index 0000000..c898656
--- /dev/null
+++ b/test/graceful.js
@@ -0,0 +1,15 @@
+var
+  tmp = require('../lib/tmp'),
+  spawn = require('./spawn');
+
+var graceful = spawn.arg;
+
+if (graceful) {
+  tmp.setGracefulCleanup();
+}
+
+spawn.tmpFunction(function (err, name) {
+  spawn.out(name, function () {
+    throw new Error("Thrown on purpose");
+  });
+});
diff --git a/test/keep.js b/test/keep.js
new file mode 100644
index 0000000..9538605
--- /dev/null
+++ b/test/keep.js
@@ -0,0 +1,11 @@
+var spawn = require('./spawn');
+
+var keep = spawn.arg;
+
+spawn.tmpFunction({ keep: keep }, function (err, name) {
+  if (err) {
+    spawn.err(err, spawn.exit);
+  } else {
+    spawn.out(name, spawn.exit);
+  }
+});
diff --git a/test/name-test.js b/test/name-test.js
new file mode 100644
index 0000000..a242c21
--- /dev/null
+++ b/test/name-test.js
@@ -0,0 +1,82 @@
+var
+  vows   = require('vows'),
+  assert = require('assert'),
+
+  path   = require('path'),
+
+  tmp    = require('../lib/tmp.js'),
+  Test   = require('./base.js');
+
+vows.describe('Name creation').addBatch({
+  'when using without parameters': {
+    topic: function () {
+      tmp.tmpName(this.callback);
+    },
+
+    'should not return with error': assert.isNull,
+    'should have the default prefix': Test.testPrefix('tmp-')
+  },
+
+  'when using with prefix': {
+    topic: function () {
+      tmp.tmpName({ prefix: 'something' }, this.callback);
+    },
+
+    'should not return with error': assert.isNull,
+    'should have the provided prefix': Test.testPrefix('something')
+  },
+
+  'when using with postfix': {
+    topic: function () {
+      tmp.tmpName({ postfix: '.txt' }, this.callback);
+    },
+
+    'should not return with error': assert.isNull,
+    'should have the provided postfix': Test.testPostfix('.txt')
+
+  },
+
+  'when using template': {
+    topic: function () {
+      tmp.tmpName({ template: path.join(tmp.tmpdir, 'clike-XXXXXX-postfix') }, this.callback);
+    },
+
+    'should not return with error': assert.isNull,
+    'should have the provided prefix': Test.testPrefix('clike-'),
+    'should have the provided postfix': Test.testPostfix('-postfix'),
+    'should have template filled': function (err, name) {
+      assert.isTrue(/[a-zA-Z0-9]{6}/.test(name));
+    }
+  },
+
+  'when using multiple options': {
+    topic: function () {
+      tmp.tmpName({ prefix: 'foo', postfix: 'bar', tries: 5 }, this.callback);
+    },
+
+    'should not return with error': assert.isNull,
+    'should have the provided prefix': Test.testPrefix('foo'),
+    'should have the provided postfix': Test.testPostfix('bar')
+  },
+
+  'no tries': {
+    topic: function () {
+      tmp.tmpName({ tries: -1 }, this.callback);
+    },
+
+    'should fail': function (err, name) {
+      assert.isObject(err);
+    }
+  },
+
+  'tries not numeric': {
+    topic: function () {
+      tmp.tmpName({ tries: 'hello'}, this.callback);
+    },
+
+    'should fail': function (err, name) {
+      assert.isObject(err);
+    }
+  }
+
+}).exportTo(module);
diff --git a/test/spawn.js b/test/spawn.js
new file mode 100644
index 0000000..6468eb3
--- /dev/null
+++ b/test/spawn.js
@@ -0,0 +1,32 @@
+var
+  fs = require('fs'),
+  tmp = require('../lib/tmp');
+
+function _writeSync(stream, str, cb) {
+  var flushed = stream.write(str);
+  if (flushed) {
+    return cb(null);
+  }
+
+  stream.once('drain', function _flushed() {
+    cb(null);
+  });
+}
+
+module.exports.out = function (str, cb) {
+  _writeSync(process.stdout, str, cb);
+};
+
+module.exports.err = function (str, cb) {
+  _writeSync(process.stderr, str, cb);
+};
+
+module.exports.exit = function () {
+  process.exit(0);
+};
+
+var type = process.argv[2];
+module.exports.tmpFunction = (type == 'file') ? tmp.file : tmp.dir;
+
+var arg = (process.argv[3] && parseInt(process.argv[3], 10) === 1) ? true : false;
+module.exports.arg = arg;
diff --git a/test/symlinkme/file.js b/test/symlinkme/file.js
new file mode 100644
index 0000000..e69de29
diff --git a/test/unsafe.js b/test/unsafe.js
new file mode 100644
index 0000000..73e4fb3
--- /dev/null
+++ b/test/unsafe.js
@@ -0,0 +1,30 @@
+var
+  fs    = require('fs'),
+  join  = require('path').join,
+  spawn = require('./spawn');
+
+var unsafe = spawn.arg;
+spawn.tmpFunction({ unsafeCleanup: unsafe }, function (err, name) {
+  if (err) {
+    spawn.err(err, spawn.exit);
+    return;
+  }
+
+  try {
+    // file that should be removed
+    var fd = fs.openSync(join(name, 'should-be-removed.file'), 'w');
+    fs.closeSync(fd);
+
+    // in tree source
+    var symlinkSource = join(__dirname, 'symlinkme');
+    // testing target
+    var symlinkTarget = join(name, 'symlinkme-target');
+
+    // symlink that should be removed but the contents should be preserved.
+    fs.symlinkSync(symlinkSource, symlinkTarget, 'dir');
+
+    spawn.out(name, spawn.exit);
+  } catch (e) {
+    spawn.err(e.toString(), spawn.exit);
+  }
+});

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



More information about the Pkg-javascript-commits mailing list