diff --git a/.travis.yml b/.travis.yml index a2fa5ab..d9f1943 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,6 @@ node_js: - "4" - "0.12" - "0.10" - - "0.8" sudo: false cache: directories: diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..136640c --- /dev/null +++ b/package-lock.json @@ -0,0 +1,278 @@ +{ + "name": "tmp", + "version": "0.0.33", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "browser-stdout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", + "dev": true + }, + "commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "dev": true, + "requires": { + "graceful-readlink": "1.0.1" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "debug": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.0.tgz", + "integrity": "sha1-vFlryr52F/Edn6FTYe3tVgi4SZs=", + "dev": true, + "requires": { + "ms": "0.7.2" + } + }, + "diff": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", + "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", + "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true + }, + "growl": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", + "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", + "dev": true + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "json3": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", + "dev": true + }, + "lodash._baseassign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash.keys": "3.1.2" + } + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basecreate": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", + "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", + "dev": true + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash.create": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", + "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", + "dev": true, + "requires": { + "lodash._baseassign": "3.2.0", + "lodash._basecreate": "3.0.3", + "lodash._isiterateecall": "3.0.9" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.4.2.tgz", + "integrity": "sha1-0O9NMyEm2/GNDWQMmzgt1IvpdZQ=", + "dev": true, + "requires": { + "browser-stdout": "1.3.0", + "commander": "2.9.0", + "debug": "2.6.0", + "diff": "3.2.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.1", + "growl": "1.9.2", + "json3": "3.3.2", + "lodash.create": "3.1.1", + "mkdirp": "0.5.1", + "supports-color": "3.1.2" + } + }, + "ms": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "supports-color": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", + "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + } + } +} diff --git a/package.json b/package.json index bce4dda..482979a 100644 --- a/package.json +++ b/package.json @@ -19,20 +19,20 @@ "url": "http://github.com/raszi/node-tmp/issues" }, "engines": { - "node": ">=0.8.0" + "node": ">=0.10.0" }, "dependencies": { "os-tmpdir": "~1.0.2" }, "devDependencies": { - "vows": "~0.7.0" + "mocha": "~3.4.2" }, "main": "lib/tmp.js", "files": [ "lib/" ], "scripts": { - "test": "vows test/*-test.js", + "test": "mocha test/*-test.js", "doc": "jsdoc -c .jsdoc.json" } } diff --git a/test/assertions.js b/test/assertions.js new file mode 100644 index 0000000..2b0b891 --- /dev/null +++ b/test/assertions.js @@ -0,0 +1,68 @@ +/* eslint-disable no-octal */ + +var + assert = require('assert'), + fs = require('fs'), + path = require('path'), + existsSync = fs.existsSync || path.existsSync; + + +module.exports.assertName = function assertName(name, expected) { + assert.ok(typeof name == 'string'); + assert.ok(name.length > 0, 'an empty string is not a valid name'); + if (expected) { + assert.equal(path.basename(name), expected, 'should be the expected name'); + } +}; + + +module.exports.assertMode = function assertMode(name, mode) { + var stat = fs.statSync(name); + + // mode values do not work properly on Windows. Ignore “group” and + // “other” bits then. Ignore execute bit on that platform because it + // doesn’t exist—even for directories. + if (process.platform == 'win32') { + assert.equal(stat.mode & 000600, mode & 000600); + } else { + assert.equal(stat.mode & 000777, mode); + } +}; + + +module.exports.assertDir = function assertDir(name, dir) { + assert.equal(name.slice(0, dir.length), dir, 'should have the expected dir as the leading path'); +}; + + +module.exports.assertPrefix = function assertPrefix(name, prefix) { + assert.equal(path.basename(name).slice(0, prefix.length), prefix, 'should have the provided prefix'); +}; + + +module.exports.assertPostfix = function assertPostfix(name, postfix) { + assert.equal(name.slice(name.length - postfix.length, name.length), postfix, 'should have the provided postfix'); +}; + + +module.exports.assertProperResult = function assertProperResult(result, withfd) { + assert.ok(result); + assert.ok(result.name, 'should have a name'); + if (withfd) assert.ok(result.fd, 'should have an fd'); + else assert.strictEqual(result.fd, undefined, 'should not have a file descriptor (fd)'); + assert.ok(typeof result.removeCallback == 'function', 'should have a removeCallback'); +}; + + +module.exports.assertExists = function assertExists(name, isfile) { + assert.ok(existsSync(name), name + ' should exist'); + var stat = fs.statSync(name); + if (isfile) assert.ok(stat.isFile(), name + ' should be a file'); + else assert.ok(stat.isDirectory(), name + ' should be a directory'); +}; + + +module.exports.assertDoesNotExist = function assertDoesNotExist(name) { + assert.ok(!existsSync(name), name + ' should not exist'); +}; + diff --git a/test/base.js b/test/base.js deleted file mode 100644 index b136756..0000000 --- a/test/base.js +++ /dev/null @@ -1,227 +0,0 @@ -var - assert = require('assert'), - path = require('path'), - spawn = require('child_process').spawn, - tmp = require('../lib/tmp'); - -// make sure that we do not test spam the global tmp -tmp.TMP_DIR = './tmp'; - -function _bufferConcat(buffers) { - if (Buffer.concat) { - return Buffer.concat.apply(this, arguments); - } else { - return new Buffer(buffers.reduce(function (acc, buf) { - for (var i = 0; i < buf.length; i++) { - acc.push(buf[i]); - } - return acc; - }, [])); - } -} - -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 - node_path = process.argv[0], - command_args = [ path.join(__dirname, testFile) ].concat(params), - stdoutBufs = [], - stderrBufs = [], - child, - done = false, - stderrDone = false, - stdoutDone = false; - - // spawn doesn’t have the quoting problems that exec does, - // especially when going for Windows portability. - child = spawn(node_path, command_args); - child.stdin.end(); - // Cannot use 'close' event because not on node-0.6. - function _close() { - var - stderr = _bufferConcat(stderrBufs), - stdout = _bufferConcat(stdoutBufs); - if (stderrDone && stdoutDone && !done) { - done = true; - if (passError) { - if (stderr.length > 0) { - return cb(stderr.toString()); - } - } - return cb(null, _bufferConcat(stdoutBufs).toString()); - } - } - if (passError) { - child.on('error', function _spawnError(err) { - if (!done) { - done = true; - cb(err); - } - }); - } - child.stdout.on('data', function _stdoutData(data) { - stdoutBufs.push(data); - }).on('close', function _stdoutEnd() { - stdoutDone = true; - _close(); - }); - child.stderr.on('data', function _stderrData(data) { - stderrBufs.push(data); - }).on('close', function _stderrEnd() { - stderrDone = true; - _close(); - }); -} - -function _testStat(stat, mode) { - // getuid() and getgid() do not exist on Windows. - if (process.getuid) { - assert.equal(stat.uid, process.getuid(), 'should have the same UID'); - } - if (process.getgid) { - assert.equal(stat.gid, process.getgid(), 'should have the same GUID'); - } - // mode values do not work properly on Windows. Ignore “group” and - // “other” bits then. Ignore execute bit on that platform because it - // doesn’t exist—even for directories. - if (process.platform == 'win32') { - assert.equal(stat.mode & 0666600, mode & 0666600); - } else { - assert.equal(stat.mode, mode); - } -} - -function _testPrefix(prefix) { - return function _testPrefixGenerated(err, name) { - assert.equal(path.basename(name).slice(0, prefix.length), prefix, 'should have the provided prefix'); - }; -} - -function _testPrefixSync(prefix) { - return function _testPrefixGeneratedSync(result) { - if (result instanceof Error) { - throw result; - } - _testPrefix(prefix)(null, result.name, result.fd); - }; -} - -function _testPostfix(postfix) { - return function _testPostfixGenerated(err, name) { - assert.equal(name.slice(name.length - postfix.length, name.length), postfix, 'should have the provided postfix'); - }; -} - -function _testPostfixSync(postfix) { - return function _testPostfixGeneratedSync(result) { - if (result instanceof Error) { - throw result; - } - _testPostfix(postfix)(null, result.name, result.fd); - }; -} - -function _testKeep(type, keep, cb) { - _spawnTestWithError('keep.js', [ type, keep ], cb); -} - -function _testKeepSync(type, keep, cb) { - _spawnTestWithError('keep-sync.js', [ type, keep ], cb); -} - -function _testGraceful(type, graceful, cb) { - _spawnTestWithoutError('graceful.js', [ type, graceful ], cb); -} - -function _testGracefulSync(type, graceful, cb) { - _spawnTestWithoutError('graceful-sync.js', [ type, graceful ], cb); -} - -function _assertNoDescriptor(err, name, fd) { - assert.strictEqual(fd, undefined); -} - -function _assertNoDescriptorSync(result) { - assert.strictEqual(result.fd, undefined); -} - -function _assertName(err, name) { - assert.isString(name); - assert.isNotZero(name.length, 'an empty string is not a valid name'); -} - -function _assertNameSync(result) { - if (result instanceof Error) { - throw result; - } - var name = typeof(result) == 'string' ? result : result.name; - _assertName(null, name); -} - -function _testName(expected){ - return function _testNameGenerated(err, name) { - assert.equal(expected, name, 'should have the provided name'); - }; -} - -function _testNameSync(expected){ - return function _testNameGeneratedSync(result) { - if (result instanceof Error) { - throw result; - } - _testName(expected)(null, result.name, result.fd); - }; -} - -function _testUnsafeCleanup(unsafe, cb) { - _spawnTestWithoutError('unsafe.js', [ 'dir', unsafe ], cb); -} - -function _testIssue62(cb) { - _spawnTestWithoutError('issue62.js', [], cb); -} - -function _testUnsafeCleanupSync(unsafe, cb) { - _spawnTestWithoutError('unsafe-sync.js', [ 'dir', unsafe ], cb); -} - -function _testIssue62Sync(cb) { - _spawnTestWithoutError('issue62-sync.js', [], cb); -} - -function _testIssue115File(cb) { - _spawnTestWithError('issue115-file.js', [], cb); -} - -function _testIssue115FileSync(cb) { - _spawnTestWithError('issue115-file-sync.js', [], cb); -} - -module.exports.testStat = _testStat; -module.exports.testPrefix = _testPrefix; -module.exports.testPrefixSync = _testPrefixSync; -module.exports.testPostfix = _testPostfix; -module.exports.testPostfixSync = _testPostfixSync; -module.exports.testKeep = _testKeep; -module.exports.testKeepSync = _testKeepSync; -module.exports.testGraceful = _testGraceful; -module.exports.testGracefulSync = _testGracefulSync; -module.exports.assertName = _assertName; -module.exports.assertNameSync = _assertNameSync; -module.exports.assertNoDescriptor = _assertNoDescriptor; -module.exports.assertNoDescriptorSync = _assertNoDescriptorSync; -module.exports.testName = _testName; -module.exports.testNameSync = _testNameSync; -module.exports.testUnsafeCleanup = _testUnsafeCleanup; -module.exports.testIssue62 = _testIssue62; -module.exports.testIssue115File = _testIssue115File; -module.exports.testIssue115FileSync = _testIssue115FileSync; -module.exports.testUnsafeCleanupSync = _testUnsafeCleanupSync; -module.exports.testIssue62Sync = _testIssue62Sync; diff --git a/test/child-process.js b/test/child-process.js new file mode 100644 index 0000000..5c7b504 --- /dev/null +++ b/test/child-process.js @@ -0,0 +1,72 @@ +// vim: expandtab:ts=2:sw=2 + +var + fs = require('fs'), + path = require('path'), + existsSync = fs.existsSync || path.existsSync, + spawn = require('child_process').spawn; + + +module.exports = function spawnChildProcess(configFile, cb) { + var + node_path = process.argv[0], + command_args = [ path.join(__dirname, 'spawn.js') ].concat(configFile), + stdoutBufs = [], + stderrBufs = [], + child, + done = false, + stderrDone = false, + stdoutDone = false; + + // make sure that the config file exists + if (!existsSync(path.join(__dirname, configFile))) + return cb(new Error('ENOENT: configFile ' + path.join(__dirname, configFile) + ' does not exist')); + + // spawn doesn’t have the quoting problems that exec does, + // especially when going for Windows portability. + child = spawn(node_path, command_args); + child.stdin.end(); + // Cannot use 'close' event because not on node-0.6. + function _close() { + var + stderr = _bufferConcat(stderrBufs).toString(), + stdout = _bufferConcat(stdoutBufs).toString(); + if (stderrDone && stdoutDone && !done) { + done = true; + cb(null, stderr, stdout); + } + } + child.on('error', function _spawnError(err) { + if (!done) { + done = true; + cb(err); + } + }); + child.stdout.on('data', function _stdoutData(data) { + stdoutBufs.push(data); + }).on('close', function _stdoutEnd() { + stdoutDone = true; + _close(); + }); + child.stderr.on('data', function _stderrData(data) { + stderrBufs.push(data); + }).on('close', function _stderrEnd() { + stderrDone = true; + _close(); + }); +} + + +function _bufferConcat(buffers) { + if (Buffer.concat) { + return Buffer.concat.apply(this, arguments); + } else { + return new Buffer(buffers.reduce(function (acc, buf) { + for (var i = 0; i < buf.length; i++) { + acc.push(buf[i]); + } + return acc; + }, [])); + } +} + diff --git a/test/dir-sync-test.js b/test/dir-sync-test.js index d525e07..7f90b96 100644 --- a/test/dir-sync-test.js +++ b/test/dir-sync-test.js @@ -1,232 +1,139 @@ /* eslint-disable no-octal */ +// vim: expandtab:ts=2:sw=2 var - vows = require('vows'), assert = require('assert'), + fs = require('fs'), + path = require('path'), + inbandStandardTests = require('./inband-standard'), + childProcess = require('./child-process'), + assertions = require('./assertions'), + tmp = require('../lib/tmp'); + + +// make sure that everything gets cleaned up +tmp.setGracefulCleanup(); + + +describe('tmp', function () { + describe('#dirSync()', function () { + // API call standard inband tests + describe('when running inband standard tests', function () { + + inbandStandardTests(false, function before() { + this.topic = tmp.dirSync(this.opts); + }); + + describe('with invalid tries', function () { + it('should result in an error on negative tries', function () { + try { + tmp.dirSync({tries: -1}); + assert.fail('should have failed'); + } catch (err) { + assert.ok(err instanceof Error); + } + }); + it('should result in an error on non numeric tries', function () { + try { + tmp.dirSync({tries: 'nan'}); + assert.fail('should have failed'); + } catch (err) { + assert.ok(err instanceof Error); + } + }); + }); + }); + + // API call issue specific inband tests + describe('when running issue specific inband tests', function () { + // add your issue specific tests here + }); + + // API call standard outband tests + describe('when running standard outband tests', function () { + it('on graceful cleanup', function (done) { + childProcess('outband/graceful-dir-sync.json', function (err, stderr, stdout) { + if (err) return done(err); + else if (!stderr) assert.fail('stderr expected'); + else assertions.assertDoesNotExist(stdout); + done(); + }); + }); + it('on non graceful cleanup', function (done) { + childProcess('outband/non-graceful-dir-sync.json', function (err, stderr, stdout) { + if (err) return done(err); + else if (!stderr) assert.fail('stderr expected'); + else { + assertions.assertExists(stdout); + fs.rmdirSync(stdout); + } + done(); + }); + }); + it('on keep', function (done) { + childProcess('outband/keep-dir-sync.json', function (err, stderr, stdout) { + if (err) return done(err); + else if (stderr) assert.fail(stderr); + else { + assertions.assertExists(stdout); + fs.rmdirSync(stdout); + } + done(); + }); + }); + it('on unlink (keep == false)', function (done) { + childProcess('outband/unlink-dir-sync.json', function (err, stderr, stdout) { + if (err) return done(err); + else if (stderr) assert.fail(stderr); + else assertions.assertDoesNotExist(stdout); + done(); + }); + }); + it('on unsafe cleanup', function (done) { + childProcess('outband/unsafe-sync.json', function (err, stderr, stdout) { + if (err) return done(err); + else if (stderr) assert.fail(stderr); + else { + assertions.assertDoesNotExist(stdout); + var basepath = path.join(__dirname, 'outband', 'fixtures', 'symlinkme'); + assertions.assertExists(basepath); + assertions.assertExists(path.join(basepath, 'file.js'), true); + } + done(); + }); + }); + it('on non unsafe cleanup', function (done) { + childProcess('outband/non-unsafe-sync.json', function (err, stderr, stdout) { + if (err) return done(err); + else if (stderr) assert.fail(stderr); + else { + assertions.assertExists(stdout); + assertions.assertExists(path.join(stdout, 'should-be-removed.file'), true); + if (process.platform == 'win32') + assertions.assertExists(path.join(stdout, 'symlinkme-target'), true); + else + assertions.assertExists(path.join(stdout, 'symlinkme-target')); + fs.unlinkSync(path.join(stdout, 'should-be-removed.file')); + fs.unlinkSync(path.join(stdout, 'symlinkme-target')); + fs.rmdirSync(stdout); + } + done(); + }); + }); + }); + + // API call issue specific outband tests + describe('when running issue specific outband tests', function () { + // add your issue specific tests here + it('on issue #62', function (done) { + childProcess('outband/issue62-sync.json', function (err, stderr, stdout) { + if (err) return done(err); + else if (stderr) assert.fail(stderr); + else assertions.assertDoesNotExist(stdout); + done(); + }); + }); + }); + }); +}); - 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(result) { - assert.ok(existsSync(result.name), 'should exist'); - - var stat = fs.statSync(result.name); - assert.ok(stat.isDirectory(), 'should be a directory'); - - Test.testStat(stat, mode); - }; -} - -vows.describe('Synchronous directory creation').addBatch({ - 'when using without parameters': { - topic: function () { - return tmp.dirSync(); - }, - - 'should return with a name': Test.assertNameSync, - 'should be a directory': _testDir(040700), - 'should have the default prefix': Test.testPrefixSync('tmp-') - }, - - 'when using with prefix': { - topic: function () { - return tmp.dirSync({ prefix: 'something' }); - }, - - 'should return with a name': Test.assertNameSync, - 'should be a directory': _testDir(040700), - 'should have the provided prefix': Test.testPrefixSync('something') - }, - - 'when using with postfix': { - topic: function () { - return tmp.dirSync({ postfix: '.txt' }); - }, - - 'should return with a name': Test.assertNameSync, - 'should be a directory': _testDir(040700), - 'should have the provided postfix': Test.testPostfixSync('.txt') - }, - - 'when using template': { - topic: function () { - return tmp.dirSync({ template: 'clike-XXXXXX-postfix' }); - }, - - 'should return with a name': Test.assertNameSync, - 'should be a directory': _testDir(040700), - 'should have the provided prefix': Test.testPrefixSync('clike-'), - 'should have the provided postfix': Test.testPostfixSync('-postfix') - }, - - 'when using name': { - topic: function () { - return tmp.dirSync({ name: 'using-name' }); - }, - - 'should return with a name': Test.assertNameSync, - 'should have the provided name': Test.testNameSync(path.join(tmp.tmpdir, 'using-name')), - 'should be a directory': function (result) { - _testDir(040700)(result); - result.removeCallback(); - assert.ok(!existsSync(result.name), 'Directory should be removed'); - } - }, - - 'when using multiple options': { - topic: function () { - return tmp.dirSync({ prefix: 'foo', postfix: 'bar', mode: 0750 }); - }, - - 'should return with a name': Test.assertNameSync, - 'should be a directory': _testDir(040750), - 'should have the provided prefix': Test.testPrefixSync('foo'), - 'should have the provided postfix': Test.testPostfixSync('bar') - }, - - 'when using multiple options and mode': { - topic: function () { - return tmp.dirSync({ prefix: 'complicated', postfix: 'options', mode: 0755 }); - }, - - 'should return with a name': Test.assertNameSync, - 'should be a directory': _testDir(040755), - 'should have the provided prefix': Test.testPrefixSync('complicated'), - 'should have the provided postfix': Test.testPostfixSync('options') - }, - - 'no tries': { - topic: function () { - try { - return tmp.dirSync({ tries: -1 }); - } - catch (e) { - return e; - } - }, - - 'should return with an error': function (topic) { - assert.instanceOf(topic, Error); - } - }, - - 'keep testing': { - topic: function () { - Test.testKeepSync('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)({ name: name }); - fs.rmdirSync(name); - } - }, - - 'unlink testing': { - topic: function () { - Test.testKeepSync('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.testGracefulSync('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)({ name: name }); - fs.rmdirSync(name); - } - }, - - 'graceful testing': { - topic: function () { - Test.testGracefulSync('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.testUnsafeCleanupSync('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() { - assert.ok( - existsSync(__dirname + '/symlinkme/file.js'), - 'should not remove symlinked directory\'s content' - ); - } - }, - - 'unsafeCleanup === true with issue62 structure': { - topic: function () { - Test.testIssue62Sync(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 === false': { - topic: function () { - Test.testUnsafeCleanupSync('0', this.callback); - }, - - 'should not return with an error': assert.isNull, - 'should return with a name': Test.assertName, - 'should be a directory': function (err, name) { - _testDir(040700)({name:name}); - // make sure that everything gets cleaned up - fs.unlinkSync(path.join(name, 'should-be-removed.file')); - fs.unlinkSync(path.join(name, 'symlinkme-target')); - fs.rmdirSync(name); - } - }, - - 'remove callback': { - topic: function () { - return tmp.dirSync(); - }, - - 'should return with a name': Test.assertNameSync, - 'removeCallback should remove directory': function (result) { - result.removeCallback(); - assert.ok(!existsSync(result.name), 'Directory should be removed'); - } - } -}).exportTo(module); diff --git a/test/dir-test.js b/test/dir-test.js index e330cee..8c488e1 100644 --- a/test/dir-test.js +++ b/test/dir-test.js @@ -1,227 +1,142 @@ /* eslint-disable no-octal */ +// vim: expandtab:ts=2:sw=2 var - vows = require('vows'), assert = require('assert'), + fs = require('fs'), + path = require('path'), + inbandStandardTests = require('./inband-standard'), + childProcess = require('./child-process'), + assertions = require('./assertions'), + tmp = require('../lib/tmp'); + + +// make sure that everything gets cleaned up +tmp.setGracefulCleanup(); + + +describe('tmp', function () { + describe('#dir()', function () { + // API call standard inband tests + describe('when running inband standard tests', function () { + + inbandStandardTests(false, function before(done) { + var that = this; + tmp.dir(this.opts, function (err, name, removeCallback) { + if (err) done(err); + else { + that.topic = {name: name, removeCallback: removeCallback}; + done(); + } + }); + }); + + describe('with invalid tries', function () { + it('should result in an error on negative tries', function (done) { + tmp.dir({tries: -1}, function (err) { + assert.ok(err instanceof Error, 'should have failed'); + done(); + }); + }); + it('should result in an error on non numeric tries', function (done) { + tmp.dir({tries: 'nan'}, function (err) { + assert.ok(err instanceof Error, 'should have failed'); + done(); + }); + }); + }); + }); + + // API call issue specific inband tests + describe('when running issue specific inband tests', function () { + // add your issue specific tests here + }); + + // API call standard outband tests + describe('when running standard outband tests', function () { + it('on graceful cleanup', function (done) { + childProcess('outband/graceful-dir.json', function (err, stderr, stdout) { + if (err) return done(err); + else if (!stderr) assert.fail('stderr expected'); + else assertions.assertDoesNotExist(stdout); + done(); + }); + }); + it('on non graceful cleanup', function (done) { + childProcess('outband/non-graceful-dir.json', function (err, stderr, stdout) { + if (err) return done(err); + else if (!stderr) assert.fail('stderr expected'); + else { + assertions.assertExists(stdout); + fs.rmdirSync(stdout); + } + done(); + }); + }); + it('on keep', function (done) { + childProcess('outband/keep-dir.json', function (err, stderr, stdout) { + if (err) return done(err); + else if (stderr) assert.fail(stderr); + else { + assertions.assertExists(stdout); + fs.rmdirSync(stdout); + } + done(); + }); + }); + it('on unlink (keep == false)', function (done) { + childProcess('outband/unlink-dir.json', function (err, stderr, stdout) { + if (err) return done(err); + else if (stderr) assert.fail(stderr); + else assertions.assertDoesNotExist(stdout); + done(); + }); + }); + it('on unsafe cleanup', function (done) { + childProcess('outband/unsafe.json', function (err, stderr, stdout) { + if (err) return done(err); + else if (stderr) assert.fail(stderr); + else { + assertions.assertDoesNotExist(stdout); + var basepath = path.join(__dirname, 'outband', 'fixtures', 'symlinkme'); + assertions.assertExists(basepath); + assertions.assertExists(path.join(basepath, 'file.js'), true); + } + done(); + }); + }); + it('on non unsafe cleanup', function (done) { + childProcess('outband/non-unsafe.json', function (err, stderr, stdout) { + if (err) return done(err); + else if (stderr) assert.fail(stderr); + else { + assertions.assertExists(stdout); + assertions.assertExists(path.join(stdout, 'should-be-removed.file'), true); + if (process.platform == 'win32') + assertions.assertExists(path.join(stdout, 'symlinkme-target'), true); + else + assertions.assertExists(path.join(stdout, 'symlinkme-target')); + fs.unlinkSync(path.join(stdout, 'should-be-removed.file')); + fs.unlinkSync(path.join(stdout, 'symlinkme-target')); + fs.rmdirSync(stdout); + } + done(); + }); + }); + }); + + // API call issue specific outband tests + describe('when running issue specific outband tests', function () { + // add your issue specific tests here + it('on issue #62', function (done) { + childProcess('outband/issue62.json', function (err, stderr, stdout) { + if (err) return done(err); + else if (stderr) assert.fail(stderr); + else assertions.assertDoesNotExist(stdout); + done(); + }); + }); + }); + }); +}); - 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: 'clike-XXXXXX-postfix' }, this.callback); - }, - - 'should not return with error': assert.isNull, - 'should return with a name': Test.assertName, - 'should be a directory': _testDir(040700), - 'should have the provided prefix': Test.testPrefix('clike-'), - 'should have the provided postfix': Test.testPostfix('-postfix') - }, - - 'when using name': { - topic: function () { - tmp.dir({ name: 'using-name' }, 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 name': Test.testName(path.join(tmp.tmpdir, 'using-name')) - }, - - '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() { - assert.ok( - existsSync(__dirname + '/symlinkme/file.js'), - 'should not remove symlinked directory\'s content' - ); - } - }, - - 'unsafeCleanup === true with issue62 structure': { - topic: function () { - Test.testIssue62(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 === 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': function (err, name) { - _testDir(040700)(err, name); - // make sure that everything gets cleaned up - fs.unlinkSync(path.join(name, 'should-be-removed.file')); - fs.unlinkSync(path.join(name, 'symlinkme-target')); - fs.rmdirSync(name); - } - }, - - '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-sync-test.js b/test/file-sync-test.js index 0113428..c88daa0 100644 --- a/test/file-sync-test.js +++ b/test/file-sync-test.js @@ -1,242 +1,107 @@ /* eslint-disable no-octal */ +// vim: expandtab:ts=2:sw=2 var - vows = require('vows'), assert = require('assert'), + fs = require('fs'), + inbandStandardTests = require('./inband-standard'), + assertions = require('./assertions'), + childProcess = require('./child-process'), + tmp = require('../lib/tmp'); + + +// make sure that everything gets cleaned up +tmp.setGracefulCleanup(); + + +describe('tmp', function () { + describe('#fileSync()', function () { + // API call standard inband tests + describe('when running inband standard tests', function () { + + inbandStandardTests(true, function before() { + this.topic = tmp.fileSync(this.opts); + }); + + describe('with invalid tries', function () { + it('should result in an error on negative tries', function () { + try { + tmp.fileSync({tries: -1}); + assert.fail('should have failed'); + } catch (err) { + assert.ok(err instanceof Error); + } + }); + it('should result in an error on non numeric tries', function () { + try { + tmp.fileSync({tries: 'nan'}); + assert.fail('should have failed'); + } catch (err) { + assert.ok(err instanceof Error); + } + }); + }); + }); + + // API call issue specific inband tests + describe('when running issue specific inband tests', function () { + // add your issue specific tests here + }); + + // API call standard outband tests + describe('when running standard outband tests', function () { + it('on graceful', function (done) { + childProcess('outband/graceful-file-sync.json', function (err, stderr, stdout) { + if (err) return done(err); + else if (!stderr) assert.fail('stderr expected'); + else assertions.assertDoesNotExist(stdout); + done(); + }); + }); + it('on non graceful', function (done) { + childProcess('outband/non-graceful-file-sync.json', function (err, stderr, stdout) { + if (err) return done(err); + else if (!stderr) assert.fail('stderr expected'); + else { + assertions.assertExists(stdout, true); + fs.unlinkSync(stdout); + } + done(); + }); + }); + it('on keep', function (done) { + childProcess('outband/keep-file-sync.json', function (err, stderr, stdout) { + if (err) return done(err); + else if (stderr) assert.fail(stderr); + else { + assertions.assertExists(stdout, true); + fs.unlinkSync(stdout); + } + done(); + }); + }); + it('on unlink (keep == false)', function (done) { + childProcess('outband/unlink-file-sync.json', function (err, stderr, stdout) { + if (err) return done(err); + else if (stderr) assert.fail(stderr); + else assertions.assertDoesNotExist(stdout); + done(); + }); + }); + }); + + // API call issue specific outband tests + describe('when running issue specific outband tests', function () { + // add your issue specific tests here + it('on issue #115', function (done) { + childProcess('outband/issue115-sync.json', function (err, stderr, stdout) { + if (err) return done(err); + else if (stderr) assert.fail(stderr); + else assertions.assertDoesNotExist(stdout); + done(); + }); + }); + }); + }); +}); - 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(result) { - assert.ok(existsSync(result.name), 'should exist'); - - var stat = fs.statSync(result.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(result.fd); - assert.deepEqual(fstat, stat, 'fstat results should be the same'); - - var data = new Buffer('something'); - assert.equal(fs.writeSync(result.fd, data, 0, data.length, 0), data.length, 'should be writable'); - assert.ok(!fs.closeSync(result.fd), 'should not return with error'); - } - }; -} - -function _testFileNoDescriptor(mode) { - return function _testFileNoDescriptor(result) { - assert.ok(existsSync(result.name), 'should exist'); - - var stat = fs.statSync(result.name); - assert.equal(stat.size, 0, 'should have zero size'); - assert.ok(stat.isFile(), 'should be a file'); - - Test.testStat(stat, mode); - - assert.strictEqual(result.fd, undefined); - }; -} - -function _testFileAfterDetachRemove(mode) { - return function _testFileAfterDetachRemove(result) { - assert.ok(!existsSync(result.name), 'File should be removed'); - - var fstat = fs.fstatSync(result.fd); - assert.equal(fstat.size, 0, 'should have zero size'); - assert.ok(fstat.isFile(), 'should be a file'); - Test.testStat(fstat, mode); - - var data = new Buffer('something'); - assert.equal(fs.writeSync(result.fd, data, 0, data.length, 0), data.length, 'should be writable'); - assert.ok(!fs.closeSync(result.fd), 'should not return with error'); - }; -} - -vows.describe('Synchronous file creation').addBatch({ - 'when using without parameters': { - topic: function () { - return tmp.fileSync(); - }, - - 'should return with a name': Test.assertNameSync, - 'should be a file': _testFile(0100600, true), - 'should have the default prefix': Test.testPrefixSync('tmp-'), - 'should have the default postfix': Test.testPostfixSync('.tmp') - }, - - 'when using with prefix': { - topic: function () { - return tmp.fileSync({ prefix: 'something' }); - }, - - 'should return with a name': Test.assertNameSync, - 'should be a file': _testFile(0100600, true), - 'should have the provided prefix': Test.testPrefixSync('something') - }, - - 'when using with postfix': { - topic: function () { - return tmp.fileSync({ postfix: '.txt' }); - }, - - 'should return with a name': Test.assertNameSync, - 'should be a file': _testFile(0100600, true), - 'should have the provided postfix': Test.testPostfixSync('.txt') - }, - - 'when using template': { - topic: function () { - return tmp.fileSync({ template: 'clike-XXXXXX-postfix' }); - }, - - 'should return with a name': Test.assertNameSync, - 'should be a file': _testFile(0100600, true), - 'should have the provided prefix': Test.testPrefixSync('clike-'), - 'should have the provided postfix': Test.testPostfixSync('-postfix') - }, - - 'when using name': { - topic: function () { - return tmp.fileSync({ name: 'using-name-sync.tmp' }); - }, - - 'should return with a name': Test.assertNameSync, - 'should have the provided name': Test.testNameSync(path.join(tmp.tmpdir, 'using-name-sync.tmp')), - 'should be a file': function (result) { - _testFile(0100600, true); - fs.unlinkSync(result.name); - } - }, - - 'when using multiple options': { - topic: function () { - return tmp.fileSync({ prefix: 'foo', postfix: 'bar', mode: 0640 }); - }, - - 'should return with a name': Test.assertNameSync, - 'should be a file': _testFile(0100640, true), - 'should have the provided prefix': Test.testPrefixSync('foo'), - 'should have the provided postfix': Test.testPostfixSync('bar') - }, - - 'when using multiple options and mode': { - topic: function () { - return tmp.fileSync({ prefix: 'complicated', postfix: 'options', mode: 0644 }); - }, - - 'should return with a name': Test.assertNameSync, - 'should be a file': _testFile(0100644, true), - 'should have the provided prefix': Test.testPrefixSync('complicated'), - 'should have the provided postfix': Test.testPostfixSync('options') - }, - - 'no tries': { - topic: function () { - try { - return tmp.fileSync({ tries: -1 }); - } - catch (e) { - return e; - } - }, - - 'should return with an error': function (topic) { - assert.instanceOf(topic, Error); - } - }, - - 'keep testing': { - topic: function () { - Test.testKeepSync('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)({name:name}); - fs.unlinkSync(name); - } - }, - - 'unlink testing': { - topic: function () { - Test.testKeepSync('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.testGracefulSync('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)({name:name}); - fs.unlinkSync(name); - } - }, - - 'graceful testing': { - topic: function () { - Test.testGracefulSync('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 () { - return tmp.fileSync(); - }, - - 'should return with a name': Test.assertNameSync, - 'removeCallback should remove file': function (result) { - result.removeCallback(); - assert.ok(!existsSync(result.name), 'File should be removed'); - } - }, - - 'when using discardDescriptor': { - topic: function () { - return tmp.fileSync({ discardDescriptor: true }); - }, - - 'should return with a name': Test.assertNameSync, - 'should not return with a descriptor': Test.assertNoDescriptorSync, - 'should be a file': _testFileNoDescriptor(0100600), - }, - - 'when using detachDescriptor': { - topic: function () { - var result = tmp.fileSync({ detachDescriptor: true }); - result.removeCallback(); - return result; - }, - - 'should return with a name': Test.assertNameSync, - 'should have working descriptor after removeCallback': _testFileAfterDetachRemove(0100600), - } - -}).exportTo(module); diff --git a/test/file-test.js b/test/file-test.js index 51214a8..2922742 100644 --- a/test/file-test.js +++ b/test/file-test.js @@ -1,271 +1,110 @@ /* eslint-disable no-octal */ +// vim: expandtab:ts=2:sw=2 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'); - } - }; -} - -function _testFileNoDescriptor(mode) { - return function _testFileNoDescriptor(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); - - assert.strictEqual(fd, undefined); - }; -} - -function _testFileAfterDetachRemove(mode) { - return function _testFileAfterDetachRemove(err, name, fd) { - assert.ok(!existsSync(name), 'File should be removed'); - - var fstat = fs.fstatSync(fd); - assert.equal(fstat.size, 0, 'should have zero size'); - assert.ok(fstat.isFile(), 'should be a file'); - Test.testStat(fstat, mode); - - 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: '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 name': { - topic: function () { - tmp.file({ name: 'using-name.tmp' }, this.callback); - }, - - 'should not return with an error': assert.isNull, - 'should return with a name': Test.assertName, - 'should have the provided name': Test.testName(path.join(tmp.tmpdir, 'using-name.tmp')), - 'should be a file': function (err, name) { - _testFile(0100600, true); - fs.unlinkSync(name); - } - }, - - 'when using discardDescriptor': { - topic: function () { - tmp.file({ discardDescriptor: true }, this.callback); - }, - - 'should not return with an error': assert.isNull, - 'should return with a name': Test.assertName, - 'should not return with a descriptor': Test.assertNoDescriptor, - 'should be a file': _testFileNoDescriptor(0100600), - }, - - 'when using detachDescriptor': { - topic: function () { - var cb = this.callback; - tmp.file({ detachDescriptor: true }, function (err, name, fd, removeCallback) { - removeCallback(); - return cb(err, name, fd); + fs = require('fs'), + inbandStandardTests = require('./inband-standard'), + assertions = require('./assertions'), + childProcess = require('./child-process'), + tmp = require('../lib/tmp'); + + +// make sure that everything gets cleaned up +tmp.setGracefulCleanup(); + + +describe('tmp', function () { + describe('#file()', function () { + // API call standard inband tests + describe('when running inband standard tests', function () { + + inbandStandardTests(true, function before(done) { + var that = this; + tmp.file(this.opts, function (err, name, fd, removeCallback) { + if (err) done(err); + else { + that.topic = {name: name, fd: fd, removeCallback: removeCallback}; + done(); + } + }); }); - }, - - 'should not return with an error': assert.isNull, - 'should return with a name': Test.assertName, - 'should have working descriptor after removeCallback': _testFileAfterDetachRemove(0100600), - }, - - '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'); - } - }, - - 'issue115 async: user deleted tmp file prior to cleanup': { - topic: function () { - Test.testIssue115File(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'); - } - }, - - 'issue115 sync: user deleted tmp file prior to cleanup': { - topic: function () { - Test.testIssue115FileSync(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'); - } - }, + describe('with invalid tries', function () { + it('should result in an error on negative tries', function (done) { + tmp.file({tries: -1}, function (err) { + assert.ok(err instanceof Error, 'should have failed'); + done(); + }); + }); + it('should result in an error on non numeric tries', function (done) { + tmp.file({tries: 'nan'}, function (err) { + assert.ok(err instanceof Error, 'should have failed'); + done(); + }); + }); + }); + }); + + // API call issue specific inband tests + describe('when running issue specific inband tests', function () { + // add your issue specific tests here + }); + + // API call standard outband tests + describe('when running standard outband tests', function () { + it('on graceful', function (done) { + childProcess('outband/graceful-file.json', function (err, stderr, stdout) { + if (err) return done(err); + else if (!stderr) assert.fail('stderr expected'); + else assertions.assertDoesNotExist(stdout); + done(); + }); + }); + it('on non graceful', function (done) { + childProcess('outband/non-graceful-file.json', function (err, stderr, stdout) { + if (err) return done(err); + else if (!stderr) assert.fail('stderr expected'); + else { + assertions.assertExists(stdout, true); + fs.unlinkSync(stdout); + } + done(); + }); + }); + it('on keep', function (done) { + childProcess('outband/keep-file.json', function (err, stderr, stdout) { + if (err) return done(err); + else if (stderr) assert.fail(stderr); + else { + assertions.assertExists(stdout, true); + fs.unlinkSync(stdout); + } + done(); + }); + }); + it('on unlink (keep == false)', function (done) { + childProcess('outband/unlink-file.json', function (err, stderr, stdout) { + if (err) return done(err); + else if (stderr) assert.fail(stderr); + else assertions.assertDoesNotExist(stdout); + done(); + }); + }); + }); + + // API call issue specific outband tests + describe('when running issue specific outband tests', function () { + // add your issue specific tests here + it('on issue #115', function (done) { + childProcess('outband/issue115.json', function (err, stderr, stdout) { + if (err) return done(err); + else if (stderr) assert.fail(stderr); + else assertions.assertDoesNotExist(stdout); + done(); + }); + }); + }); + }); +}); -}).exportTo(module); diff --git a/test/graceful-sync.js b/test/graceful-sync.js deleted file mode 100644 index 37766ff..0000000 --- a/test/graceful-sync.js +++ /dev/null @@ -1,20 +0,0 @@ -var - tmp = require('../lib/tmp'), - spawn = require('./spawn-sync'); - -var graceful = spawn.arg; - -if (graceful) { - tmp.setGracefulCleanup(); -} - -try { - var result = spawn.tmpFunction(); - spawn.out(result.name, function () { - throw new Error('Thrown on purpose'); - }); -} -catch (e) { - spawn.err(e, spawn.exit); -} - diff --git a/test/graceful.js b/test/graceful.js deleted file mode 100644 index dbe554e..0000000 --- a/test/graceful.js +++ /dev/null @@ -1,15 +0,0 @@ -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/inband-standard.js b/test/inband-standard.js new file mode 100644 index 0000000..22002d5 --- /dev/null +++ b/test/inband-standard.js @@ -0,0 +1,81 @@ +/* eslint-disable no-octal */ +// vim: expandtab:ts=2:sw=2 + +var + assert = require('assert'), + fs = require('fs'), + path = require('path'), + existsSync = fs.existsSync || path.existsSync, + assertions = require('./assertions'), + tmp = require('../lib/tmp'); + + +module.exports = function inbandStandard(isFile, beforeHook) { + var testMode = isFile ? 0600 : 0700; + describe('without any parameters', inbandStandardTests({mode: testMode, prefix: 'tmp-'}, null, isFile, beforeHook)); + describe('with prefix', inbandStandardTests({mode: testMode}, {prefix: 'something'}, isFile, beforeHook)); + describe('with postfix', inbandStandardTests({mode: testMode}, {postfix: '.txt'}, isFile, beforeHook)); + describe('with template and no leading path', inbandStandardTests({mode: testMode, prefix: 'clike-', postfix: '-postfix'}, {template: 'clike-XXXXXX-postfix'}, isFile, beforeHook)); + describe('with template and leading path', inbandStandardTests({mode: testMode, prefix: 'clike-', postfix: '-postfix'}, {template: path.join(tmp.tmpdir, 'clike-XXXXXX-postfix')}, isFile, beforeHook)); + describe('with name', inbandStandardTests({mode: testMode}, {name: 'using-name'}, isFile, beforeHook)); + describe('with mode', inbandStandardTests(null, {mode: 0755}, isFile, beforeHook)); + describe('with multiple options', inbandStandardTests(null, {prefix: 'foo', postfix: 'bar', mode: 0750}, isFile, beforeHook)); + if (isFile) { + describe('with discardDescriptor', inbandStandardTests(null, {mode: testMode, discardDescriptor: true}, isFile, beforeHook)); + describe('with detachDescriptor', inbandStandardTests(null, {mode: testMode, detachDescriptor: true}, isFile, beforeHook)); + } +}; + + +function inbandStandardTests(testOpts, opts, isFile, beforeHook) { + return function () { + opts = opts || {}; + testOpts = testOpts || {}; + + // topic reference will be created by the beforeHook + topic = {topic: null, opts: opts}; + + // bind everything to topic so we avoid global + before(beforeHook.bind(topic)); + + it('should return a proper result', function () { + assertions.assertProperResult(this.topic, isFile && !opts.discardDescriptor); + }.bind(topic)); + + it('temporary ' + (isFile ? 'file' : 'directory') + ' should exist', function () { + assertions.assertExists(this.topic.name, isFile); + }.bind(topic)); + + it('temporary ' + (isFile ? 'file' : 'directory') + ' should have the expected mode', function () { + assertions.assertMode(this.topic.name, testOpts.mode || opts.mode); + }.bind(topic)); + + if (opts.prefix || testOpts.prefix) { + it('should have the expected prefix', function () { + assertions.assertPrefix(this.topic.name, testOpts.prefix || opts.prefix); + }.bind(topic)); + } + + if (opts.postfix || testOpts.postfix) { + it('should have the expected postfix', function () { + assertions.assertPostfix(this.topic.name, testOpts.postfix || opts.postfix); + }.bind(topic)); + } + + it('should have been created in the expected directory', function () { + assertions.assertDir(this.topic.name, testOpts.dir || opts.dir || tmp.tmpdir); + }.bind(topic)); + + if (opts.name) { + it('should have the expected name', function () { + assertions.assertName(this.topic.name, opts.name); + }.bind(topic)); + } + + it('should have a working removeCallback', function () { + this.topic.removeCallback(); + assert.ok(!existsSync(this.topic.name)); + }.bind(topic)); + }; +}; + diff --git a/test/issue115-file-sync.js b/test/issue115-file-sync.js deleted file mode 100644 index 35e84c9..0000000 --- a/test/issue115-file-sync.js +++ /dev/null @@ -1,25 +0,0 @@ -var - fs = require('fs'), - join = require('path').join, - tmp = require('../lib/tmp'), - spawn = require('./spawn'); - -spawn.tmpFunction({ unsafeCleanup: true }, function (err, name) { - if (err) { - spawn.err(err, spawn.exit); - return; - } - - try { - // creates a tmp file and then closes the file descriptor as per issue 115 - // https://github.com/raszi/node-tmp/issues/115 - - tmpobj = tmp.fileSync(); - fs.closeSync(tmpobj.fd); - tmpobj.removeCallback(); - spawn.out(tmpobj.name, spawn.exit); - } catch (e) { - spawn.err(e.toString() + ' with code: ' + e.code + ' and errno: ' + e.errno, spawn.exit); - } -}); - diff --git a/test/issue115-file.js b/test/issue115-file.js deleted file mode 100644 index 8c5db8d..0000000 --- a/test/issue115-file.js +++ /dev/null @@ -1,26 +0,0 @@ -var - fs = require('fs'), - join = require('path').join, - tmp = require('../lib/tmp'), - spawn = require('./spawn'); - -spawn.tmpFunction({ unsafeCleanup: true }, function (err, name) { - if (err) { - spawn.err(err, spawn.exit); - return; - } - - try { - // creates a tmp file and then closes the file descriptor it as per issue 115 - // https://github.com/raszi/node-tmp/issues/115 - - tmp.file(function (err, name, fd, callback) { - fs.closeSync(fd); - callback(); - spawn.out(name, spawn.exit); - }); - } catch (e) { - spawn.err(e.toString() + ' with code: ' + e.code + ' and errno: ' + e.errno, spawn.exit); - } -}); - diff --git a/test/issue62-sync.js b/test/issue62-sync.js deleted file mode 100644 index 94840c6..0000000 --- a/test/issue62-sync.js +++ /dev/null @@ -1,27 +0,0 @@ - -var - fs = require('fs'), - join = require('path').join, - spawn = require('./spawn-sync'); - -try { - var result = spawn.tmpFunction({ unsafeCleanup: true }); - try { - // creates structure from issue 62 - // https://github.com/raszi/node-tmp/issues/62 - - fs.mkdirSync(join(result.name, 'issue62')); - - ['foo', 'bar'].forEach(function(subdir) { - fs.mkdirSync(join(result.name, 'issue62', subdir)); - fs.writeFileSync(join(result.name, 'issue62', subdir, 'baz.txt'), ''); - }); - - spawn.out(result.name, spawn.exit); - } catch (e) { - spawn.err(e.toString(), spawn.exit); - } -} -catch (e) { - spawn.err(e, spawn.exit); -} diff --git a/test/issue62.js b/test/issue62.js deleted file mode 100644 index 004e190..0000000 --- a/test/issue62.js +++ /dev/null @@ -1,27 +0,0 @@ -var - fs = require('fs'), - join = require('path').join, - spawn = require('./spawn'); - -spawn.tmpFunction({ unsafeCleanup: true }, function (err, name) { - if (err) { - spawn.err(err, spawn.exit); - return; - } - - try { - // creates structure from issue 62 - // https://github.com/raszi/node-tmp/issues/62 - - fs.mkdirSync(join(name, 'issue62')); - - ['foo', 'bar'].forEach(function(subdir) { - fs.mkdirSync(join(name, 'issue62', subdir)); - fs.writeFileSync(join(name, 'issue62', subdir, 'baz.txt'), ''); - }); - - spawn.out(name, spawn.exit); - } catch (e) { - spawn.err(e.toString(), spawn.exit); - } -}); diff --git a/test/keep-sync.js b/test/keep-sync.js deleted file mode 100644 index 2498a52..0000000 --- a/test/keep-sync.js +++ /dev/null @@ -1,12 +0,0 @@ -var spawn = require('./spawn-sync'); - -var keep = spawn.arg; - -try { - var result = spawn.tmpFunction({ keep: keep }); - spawn.out(result.name, spawn.exit); -} -catch (e) { - spawn.err(e.toString(), spawn.exit); -} - diff --git a/test/keep.js b/test/keep.js deleted file mode 100644 index 9538605..0000000 --- a/test/keep.js +++ /dev/null @@ -1,11 +0,0 @@ -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-inband-standard.js b/test/name-inband-standard.js new file mode 100644 index 0000000..2c04962 --- /dev/null +++ b/test/name-inband-standard.js @@ -0,0 +1,55 @@ +/* eslint-disable no-octal */ +// vim: expandtab:ts=2:sw=2 + +var + assert = require('assert'), + fs = require('fs'), + path = require('path'), + existsSync = fs.existsSync || path.existsSync, + assertions = require('./assertions'), + tmp = require('../lib/tmp'); + + +module.exports = function inbandStandard(beforeHook) { + describe('without any parameters', inbandStandardTests({prefix: 'tmp-'}, null, beforeHook)); + describe('with prefix', inbandStandardTests(null, {prefix: 'something'}, beforeHook)); + describe('with postfix', inbandStandardTests(null, {postfix: '.txt'}, beforeHook)); + describe('with template and no leading path', inbandStandardTests({prefix: 'clike-', postfix: '-postfix'}, {template: 'clike-XXXXXX-postfix'}, beforeHook)); + describe('with template and leading path', inbandStandardTests({prefix: 'clike-', postfix: '-postfix'}, {template: path.join(tmp.tmpdir, 'clike-XXXXXX-postfix')}, beforeHook)); + describe('with multiple options', inbandStandardTests(null, {prefix: 'foo', postfix: 'bar', tries: 5}, beforeHook)); +}; + + +function inbandStandardTests(testOpts, opts, beforeHook) { + return function () { + opts = opts || {}; + testOpts = testOpts || {}; + topic = {topic: null, opts: opts}; + + // bind everything to topic so we avoid global + before(beforeHook.bind(topic)); + + it('should return a proper result', function () { + assertions.assertName(this.topic); + }.bind(topic)); + + if (opts.prefix || testOpts.prefix) { + it('should have the expected prefix', function () { + assertions.assertPrefix(this.topic, testOpts.prefix || opts.prefix); + }.bind(topic)); + } + + if (opts.postfix || testOpts.postfix) { + it('should have the expected postfix', function () { + assertions.assertPostfix(this.topic, testOpts.postfix || opts.postfix); + }.bind(topic)); + } + + if (opts.name) { + it('should have the expected name', function () { + assertions.assertName(this.topic, opts.name); + }.bind(topic)); + } + }; +}; + diff --git a/test/name-sync-test.js b/test/name-sync-test.js new file mode 100644 index 0000000..01f6d5e --- /dev/null +++ b/test/name-sync-test.js @@ -0,0 +1,54 @@ +/* eslint-disable no-octal */ +// vim: expandtab:ts=2:sw=2 + +var + assert = require('assert'), + inbandStandardTests = require('./name-inband-standard'), + tmp = require('../lib/tmp'); + + +describe('tmp', function () { + describe('#tmpNameSync()', function () { + // API call standard inband tests + describe('when running inband standard tests', function () { + + inbandStandardTests(function before() { + this.topic = tmp.tmpNameSync(this.opts); + }); + + describe('with invalid tries', function () { + it('should result in an error on negative tries', function () { + try { + tmp.tmpNameSync({tries: -1}); + assert.fail('should have failed'); + } catch (err) { + assert.ok(err instanceof Error); + } + }); + it('should result in an error on non numeric tries', function () { + try { + tmp.tmpNameSync({tries: 'nan'}); + assert.fail('should have failed'); + } catch (err) { + assert.ok(err instanceof Error); + } + }); + }); + }); + + // API call issue specific inband tests + describe('when running issue specific inband tests', function () { + // add your issue specific tests here + }); + + // API call standard outband tests + describe('when running standard outband tests', function () { + }); + + // API call issue specific outband tests + describe('when running issue specific outband tests', function () { + // add your issue specific tests here + }); + }); +}); + diff --git a/test/name-test.js b/test/name-test.js index ff9489c..8a5325a 100644 --- a/test/name-test.js +++ b/test/name-test.js @@ -1,84 +1,57 @@ -/* eslint-disable no-octal, no-unused-vars */ +/* eslint-disable no-octal */ +// vim: expandtab:ts=2:sw=2 var - vows = require('vows'), assert = require('assert'), + inbandStandardTests = require('./name-inband-standard'), + tmp = require('../lib/tmp'); + + +describe('tmp', function () { + describe('#tmpName()', function () { + // API call standard inband tests + describe('when running inband standard tests', function () { + + inbandStandardTests(function before(done) { + var that = this; + tmp.dir(this.opts, function (err, name) { + if (err) done(err); + else { + that.topic = name; + done(); + } + }); + }); + + describe('with invalid tries', function () { + it('should result in an error on negative tries', function (done) { + tmp.tmpName({tries: -1}, function (err) { + assert.ok(err instanceof Error, 'should have failed'); + done(); + }); + }); + it('should result in an error on non numeric tries', function (done) { + tmp.tmpName({tries: 'nan'}, function (err) { + assert.ok(err instanceof Error, 'should have failed'); + done(); + }); + }); + }); + }); + + // API call issue specific inband tests + describe('when running issue specific inband tests', function () { + // add your issue specific tests here + }); + + // API call standard outband tests + describe('when running standard outband tests', function () { + }); + + // API call issue specific outband tests + describe('when running issue specific outband tests', function () { + // add your issue specific tests here + }); + }); +}); - 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: '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/symlinkme/file.js b/test/outband/fixtures/symlinkme/file.js similarity index 100% rename from test/symlinkme/file.js rename to test/outband/fixtures/symlinkme/file.js diff --git a/test/outband/graceful-dir-sync.json b/test/outband/graceful-dir-sync.json new file mode 100644 index 0000000..ec20262 --- /dev/null +++ b/test/outband/graceful-dir-sync.json @@ -0,0 +1,7 @@ +{ + "tc": "graceful", + "async": false, + "file": false, + "options": {}, + "graceful": true +} diff --git a/test/outband/graceful-dir.json b/test/outband/graceful-dir.json new file mode 100644 index 0000000..d84a2bb --- /dev/null +++ b/test/outband/graceful-dir.json @@ -0,0 +1,7 @@ +{ + "tc": "graceful", + "async": true, + "type": "dir", + "options": {}, + "graceful": true +} diff --git a/test/outband/graceful-file-sync.json b/test/outband/graceful-file-sync.json new file mode 100644 index 0000000..2f544dd --- /dev/null +++ b/test/outband/graceful-file-sync.json @@ -0,0 +1,7 @@ +{ + "tc": "graceful", + "async": false, + "file": true, + "options": {}, + "graceful": true +} diff --git a/test/outband/graceful-file.json b/test/outband/graceful-file.json new file mode 100644 index 0000000..237ccfd --- /dev/null +++ b/test/outband/graceful-file.json @@ -0,0 +1,7 @@ +{ + "tc": "graceful", + "async": true, + "file": true, + "options": {}, + "graceful": true +} diff --git a/test/outband/graceful.js b/test/outband/graceful.js new file mode 100644 index 0000000..cd34818 --- /dev/null +++ b/test/outband/graceful.js @@ -0,0 +1,5 @@ +module.exports = function (result, tmp) { + this.out(result.name, function () { + throw new Error('(non-)graceful cleanup testing'); + }); +}; diff --git a/test/outband/issue115-sync.json b/test/outband/issue115-sync.json new file mode 100644 index 0000000..d1e2f7f --- /dev/null +++ b/test/outband/issue115-sync.json @@ -0,0 +1,7 @@ +{ + "tc": "issue115", + "async": false, + "file": true, + "options": {}, + "graceful": false +} diff --git a/test/outband/issue115.js b/test/outband/issue115.js new file mode 100644 index 0000000..f158d38 --- /dev/null +++ b/test/outband/issue115.js @@ -0,0 +1,10 @@ +var fs = require('fs'); + +module.exports = function (result, tmp) { + // creates a tmp file and then closes the file descriptor as per issue 115 + // https://github.com/raszi/node-tmp/issues/115 + fs.closeSync(result.fd); + result.removeCallback(); + this.out(result.name, this.exit); +}; + diff --git a/test/outband/issue115.json b/test/outband/issue115.json new file mode 100644 index 0000000..08df720 --- /dev/null +++ b/test/outband/issue115.json @@ -0,0 +1,7 @@ +{ + "tc": "issue115", + "async": true, + "file": true, + "options": {}, + "graceful": false +} diff --git a/test/outband/issue62-sync.json b/test/outband/issue62-sync.json new file mode 100644 index 0000000..f0b7f59 --- /dev/null +++ b/test/outband/issue62-sync.json @@ -0,0 +1,7 @@ +{ + "tc": "issue62", + "async": false, + "file": false, + "options": {"unsafeCleanup":true}, + "graceful": false +} diff --git a/test/outband/issue62.js b/test/outband/issue62.js new file mode 100644 index 0000000..54fb944 --- /dev/null +++ b/test/outband/issue62.js @@ -0,0 +1,18 @@ +var + fs = require('fs'), + join = require('path').join; + +module.exports = function (result, tmp) { + // creates structure from issue 62 + // https://github.com/raszi/node-tmp/issues/62 + + fs.mkdirSync(join(result.name, 'issue62')); + + ['foo', 'bar'].forEach(function(subdir) { + fs.mkdirSync(join(result.name, 'issue62', subdir)); + fs.writeFileSync(join(result.name, 'issue62', subdir, 'baz.txt'), ''); + }); + + this.out(result.name, this.exit); +}; + diff --git a/test/outband/issue62.json b/test/outband/issue62.json new file mode 100644 index 0000000..21b664e --- /dev/null +++ b/test/outband/issue62.json @@ -0,0 +1,7 @@ +{ + "tc": "issue62", + "async": true, + "file": false, + "options": {"unsafeCleanup":true}, + "graceful": false +} diff --git a/test/outband/keep-dir-sync.json b/test/outband/keep-dir-sync.json new file mode 100644 index 0000000..259350f --- /dev/null +++ b/test/outband/keep-dir-sync.json @@ -0,0 +1,7 @@ +{ + "tc": "keep", + "async": false, + "file": false, + "options": {"keep":true}, + "graceful": false +} diff --git a/test/outband/keep-dir.json b/test/outband/keep-dir.json new file mode 100644 index 0000000..7fb5330 --- /dev/null +++ b/test/outband/keep-dir.json @@ -0,0 +1,7 @@ +{ + "tc": "keep", + "async": true, + "file": false, + "options": {"keep":true}, + "graceful": false +} diff --git a/test/outband/keep-file-sync.json b/test/outband/keep-file-sync.json new file mode 100644 index 0000000..6f2c229 --- /dev/null +++ b/test/outband/keep-file-sync.json @@ -0,0 +1,7 @@ +{ + "tc": "keep", + "async": false, + "file": true, + "options": {"keep":true}, + "graceful": false +} diff --git a/test/outband/keep-file.json b/test/outband/keep-file.json new file mode 100644 index 0000000..d77e070 --- /dev/null +++ b/test/outband/keep-file.json @@ -0,0 +1,7 @@ +{ + "tc": "keep", + "async": true, + "file": true, + "options": {"keep":true}, + "graceful": false +} diff --git a/test/outband/keep.js b/test/outband/keep.js new file mode 100644 index 0000000..861458f --- /dev/null +++ b/test/outband/keep.js @@ -0,0 +1,3 @@ +module.exports = function (result, tmp) { + this.out(result.name); +}; diff --git a/test/outband/non-graceful-dir-sync.json b/test/outband/non-graceful-dir-sync.json new file mode 100644 index 0000000..af73d76 --- /dev/null +++ b/test/outband/non-graceful-dir-sync.json @@ -0,0 +1,7 @@ +{ + "tc": "graceful", + "async": false, + "file": false, + "options": {}, + "graceful": false +} diff --git a/test/outband/non-graceful-dir.json b/test/outband/non-graceful-dir.json new file mode 100644 index 0000000..76edaa6 --- /dev/null +++ b/test/outband/non-graceful-dir.json @@ -0,0 +1,7 @@ +{ + "tc": "graceful", + "async": true, + "file": false, + "options": {}, + "graceful": false +} diff --git a/test/outband/non-graceful-file-sync.json b/test/outband/non-graceful-file-sync.json new file mode 100644 index 0000000..089de4c --- /dev/null +++ b/test/outband/non-graceful-file-sync.json @@ -0,0 +1,7 @@ +{ + "tc": "graceful", + "async": false, + "file": true, + "options": {}, + "graceful": false +} diff --git a/test/outband/non-graceful-file.json b/test/outband/non-graceful-file.json new file mode 100644 index 0000000..a14e360 --- /dev/null +++ b/test/outband/non-graceful-file.json @@ -0,0 +1,7 @@ +{ + "tc": "graceful", + "async": true, + "file": true, + "options": {}, + "graceful": false +} diff --git a/test/outband/non-unsafe-sync.json b/test/outband/non-unsafe-sync.json new file mode 100644 index 0000000..b67e456 --- /dev/null +++ b/test/outband/non-unsafe-sync.json @@ -0,0 +1,7 @@ +{ + "tc": "unsafe", + "async": false, + "file": false, + "options": {"unsafeCleanup":false}, + "graceful": false +} diff --git a/test/outband/non-unsafe.json b/test/outband/non-unsafe.json new file mode 100644 index 0000000..42a2e7d --- /dev/null +++ b/test/outband/non-unsafe.json @@ -0,0 +1,7 @@ +{ + "tc": "unsafe", + "async": true, + "file": false, + "options": {"unsafeCleanup":false}, + "graceful": false +} diff --git a/test/outband/unlink-dir-sync.json b/test/outband/unlink-dir-sync.json new file mode 100644 index 0000000..ebacda0 --- /dev/null +++ b/test/outband/unlink-dir-sync.json @@ -0,0 +1,7 @@ +{ + "tc": "keep", + "async": false, + "file": false, + "options": {"keep":false}, + "graceful": false +} diff --git a/test/outband/unlink-dir.json b/test/outband/unlink-dir.json new file mode 100644 index 0000000..3132103 --- /dev/null +++ b/test/outband/unlink-dir.json @@ -0,0 +1,7 @@ +{ + "tc": "keep", + "async": true, + "file": false, + "options": {"keep":false}, + "graceful": false +} diff --git a/test/outband/unlink-file-sync.json b/test/outband/unlink-file-sync.json new file mode 100644 index 0000000..7fb9f6a --- /dev/null +++ b/test/outband/unlink-file-sync.json @@ -0,0 +1,7 @@ +{ + "tc": "keep", + "async": false, + "file": true, + "options": {"keep":false}, + "graceful": false +} diff --git a/test/outband/unlink-file.json b/test/outband/unlink-file.json new file mode 100644 index 0000000..5b708e0 --- /dev/null +++ b/test/outband/unlink-file.json @@ -0,0 +1,7 @@ +{ + "tc": "keep", + "async": true, + "file": true, + "options": {"keep":false}, + "graceful": false +} diff --git a/test/outband/unsafe-sync.json b/test/outband/unsafe-sync.json new file mode 100644 index 0000000..a769724 --- /dev/null +++ b/test/outband/unsafe-sync.json @@ -0,0 +1,7 @@ +{ + "tc": "unsafe", + "async": false, + "file": false, + "options": {"unsafeCleanup":true}, + "graceful": false +} diff --git a/test/outband/unsafe.js b/test/outband/unsafe.js new file mode 100644 index 0000000..f37c4df --- /dev/null +++ b/test/outband/unsafe.js @@ -0,0 +1,26 @@ +var + fs = require('fs'), + join = require('path').join; + +module.exports = function (result, tmp) { + // file that should be removed + var fd = fs.openSync(join(result.name, 'should-be-removed.file'), 'w'); + fs.closeSync(fd); + + // in tree source + var symlinkSource = join(__dirname, 'fixtures', 'symlinkme'); + // testing target + var symlinkTarget = join(result.name, 'symlinkme-target'); + + // symlink that should be removed but the contents should be preserved. + // Skip on Windows because symlinks require elevated privileges (instead just + // create the file) + if (process.platform == 'win32') { + fs.writeFileSync(symlinkTarget); + } else { + fs.symlinkSync(symlinkSource, symlinkTarget, 'dir'); + } + + this.out(result.name); +}; + diff --git a/test/outband/unsafe.json b/test/outband/unsafe.json new file mode 100644 index 0000000..74619f5 --- /dev/null +++ b/test/outband/unsafe.json @@ -0,0 +1,7 @@ +{ + "tc": "unsafe", + "async": true, + "file": false, + "options": {"unsafeCleanup":true}, + "graceful": false +} diff --git a/test/spawn-sync.js b/test/spawn-sync.js deleted file mode 100644 index fe8b5b6..0000000 --- a/test/spawn-sync.js +++ /dev/null @@ -1,30 +0,0 @@ -var 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.fileSync : tmp.dirSync; - -var arg = (process.argv[3] && parseInt(process.argv[3], 10) === 1) ? true : false; -module.exports.arg = arg; diff --git a/test/spawn.js b/test/spawn.js index 329de63..a3115aa 100644 --- a/test/spawn.js +++ b/test/spawn.js @@ -1,4 +1,9 @@ -var tmp = require('../lib/tmp'); +// vim: expandtab:ts=2:sw=2 + +var + fs = require('fs'), + path = require('path'), + tmp = require('../lib/tmp'); function _writeSync(stream, str, cb) { var flushed = stream.write(str); @@ -7,24 +12,62 @@ function _writeSync(stream, str, cb) { } stream.once('drain', function _flushed() { +console.log('draining'); cb(null); }); } -module.exports.out = function (str, cb) { - _writeSync(process.stdout, str, cb); +var spawn = { + out: function (str, cb) { + cb = cb || spawn.exit; + _writeSync(process.stdout, str, cb); + }, + err: function (errOrStr, cb) { + cb = cb || spawn.exit; + if (!config.graceful) _writeSync(process.stderr, (errOrStr instanceof Error) ? errOrStr.toString() : errOrStr, cb); + else cb(); + }, + exit: function (code) { + process.exit(code || 0); + }, + kill: function (signal) { + process.kill(signal || 'SIGINT'); + } }; -module.exports.err = function (str, cb) { - _writeSync(process.stderr, str, cb); -}; +var config = {}; +try { + var contents = fs.readFileSync(path.join(__dirname, process.argv[2])); + config = JSON.parse(contents); +} +catch (err) { + spawn.err(err); +} -module.exports.exit = function () { - process.exit(0); -}; +var fnUnderTest = null; + +if (config.async) fnUnderTest = (config.file) ? tmp.file : tmp.dir; +else fnUnderTest = (config.file) ? tmp.fileSync : tmp.dirSync; + +// do we test against tmp doing a graceful cleanup? +if (config.graceful) tmp.setGracefulCleanup(); -var type = process.argv[2]; -module.exports.tmpFunction = (type == 'file') ? tmp.file : tmp.dir; +// import the test case function and execute it +var fn = require(path.join(__dirname, 'outband', config.tc)); +if (config.async) + fnUnderTest(config.options, function (err, name, fdOrCallback, cb) { + if (err) spawn.err(err); + else { + var result = null; + if (config.file) result = {name: name, fd: fdOrCallback, removeCallback: cb}; + else result = {name: name, removeCallback: fdOrCallback}; + fn.apply(spawn, [result, tmp]); + } + }); +else { + var result = null; + var err = null; + result = fnUnderTest(config.options); + fn.apply(spawn, [result, tmp]); +} -var arg = (process.argv[3] && parseInt(process.argv[3], 10) === 1) ? true : false; -module.exports.arg = arg; diff --git a/test/unsafe-sync.js b/test/unsafe-sync.js deleted file mode 100644 index 97b684d..0000000 --- a/test/unsafe-sync.js +++ /dev/null @@ -1,36 +0,0 @@ -var - fs = require('fs'), - join = require('path').join, - spawn = require('./spawn-sync'); - -var unsafe = spawn.arg; - -try { - var result = spawn.tmpFunction({ unsafeCleanup: unsafe }); - try { - // file that should be removed - var fd = fs.openSync(join(result.name, 'should-be-removed.file'), 'w'); - fs.closeSync(fd); - - // in tree source - var symlinkSource = join(__dirname, 'symlinkme'); - // testing target - var symlinkTarget = join(result.name, 'symlinkme-target'); - - // symlink that should be removed but the contents should be preserved. - // Skip on Windows because symlinks require elevated privileges (instead just - // create the file so that tdir-sync-test.js can unlink it). - if (process.platform == 'win32') { - fs.writeFileSync(symlinkTarget); - } else { - fs.symlinkSync(symlinkSource, symlinkTarget, 'dir'); - } - - spawn.out(result.name, spawn.exit); - } catch (e) { - spawn.err(e.toString(), spawn.exit); - } -} -catch (e) { - spawn.err(e.toString(), spawn.exit); -} diff --git a/test/unsafe.js b/test/unsafe.js deleted file mode 100644 index 7e829c8..0000000 --- a/test/unsafe.js +++ /dev/null @@ -1,36 +0,0 @@ -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. - // Skip on Windows because symlinks require elevated privileges (instead just - // create the file so that tdir-sync-test.js can unlink it). - if (process.platform == 'win32') { - fs.writeFileSync(symlinkTarget); - } else { - fs.symlinkSync(symlinkSource, symlinkTarget, 'dir'); - } - - spawn.out(name, spawn.exit); - } catch (e) { - spawn.err(e.toString(), spawn.exit); - } -});