diff --git a/lib/fs/__tests__/multi-param.test.js b/lib/fs/__tests__/multi-param.test.js new file mode 100644 index 0000000..92c619b --- /dev/null +++ b/lib/fs/__tests__/multi-param.test.js @@ -0,0 +1,154 @@ +'use strict' +/* eslint-env mocha */ +const assert = require('assert') +const path = require('path') +const crypto = require('crypto') +const os = require('os') +const semver = require('semver') +const fs = require('../..') + +const SIZE = 1000 + +// Used for tests on Node 7.2.0+ only +const onNode7it = semver.gte(process.version, '7.2.0') ? it : it.skip + +describe('fs.read()', () => { + let TEST_FILE + let TEST_DATA + let TEST_FD + + beforeEach(() => { + TEST_FILE = path.join(os.tmpdir(), 'fs-extra', 'read-test-file') + TEST_DATA = crypto.randomBytes(SIZE) + fs.writeFileSync(TEST_FILE, TEST_DATA) + TEST_FD = fs.openSync(TEST_FILE, 'r') + }) + + afterEach(() => { + return fs.close(TEST_FD) + .then(() => fs.remove(TEST_FILE)) + }) + + describe('with promises', () => { + it('returns an object', () => { + return fs.read(TEST_FD, Buffer.alloc(SIZE), 0, SIZE, 0) + .then(results => { + const bytesRead = results.bytesRead + const buffer = results.buffer + assert.equal(bytesRead, SIZE, 'bytesRead is correct') + assert(buffer.equals(TEST_DATA), 'data is correct') + }) + }) + + it('returns an object when position is not set', () => { + return fs.read(TEST_FD, Buffer.alloc(SIZE), 0, SIZE) + .then(results => { + const bytesRead = results.bytesRead + const buffer = results.buffer + assert.equal(bytesRead, SIZE, 'bytesRead is correct') + assert(buffer.equals(TEST_DATA), 'data is correct') + }) + }) + }) + + describe('with callbacks', () => { + it('works', done => { + fs.read(TEST_FD, Buffer.alloc(SIZE), 0, SIZE, 0, (err, bytesRead, buffer) => { + assert.ifError(err) + assert.equal(bytesRead, SIZE, 'bytesRead is correct') + assert(buffer.equals(TEST_DATA), 'data is correct') + done() + }) + }) + + it('works when position is null', done => { + fs.read(TEST_FD, Buffer.alloc(SIZE), 0, SIZE, null, (err, bytesRead, buffer) => { + assert.ifError(err) + assert.equal(bytesRead, SIZE, 'bytesRead is correct') + assert(buffer.equals(TEST_DATA), 'data is correct') + done() + }) + }) + }) +}) + +describe('fs.write()', () => { + let TEST_FILE + let TEST_DATA + let TEST_FD + + beforeEach(() => { + TEST_FILE = path.join(os.tmpdir(), 'fs-extra', 'write-test-file') + TEST_DATA = crypto.randomBytes(SIZE) + fs.ensureDirSync(path.dirname(TEST_FILE)) + TEST_FD = fs.openSync(TEST_FILE, 'w') + }) + + afterEach(() => { + return fs.close(TEST_FD) + .then(() => fs.remove(TEST_FILE)) + }) + + describe('with promises', () => { + it('returns an object', () => { + return fs.write(TEST_FD, TEST_DATA, 0, SIZE, 0) + .then(results => { + const bytesWritten = results.bytesWritten + const buffer = results.buffer + assert.equal(bytesWritten, SIZE, 'bytesWritten is correct') + assert(buffer.equals(TEST_DATA), 'data is correct') + }) + }) + + onNode7it('returns an object when minimal arguments are passed', () => { + return fs.write(TEST_FD, TEST_DATA) + .then(results => { + const bytesWritten = results.bytesWritten + const buffer = results.buffer + assert.equal(bytesWritten, SIZE, 'bytesWritten is correct') + assert(buffer.equals(TEST_DATA), 'data is correct') + }) + }) + + it('returns an object when writing a string', () => { + const message = 'Hello World!' + return fs.write(TEST_FD, message) + .then(results => { + const bytesWritten = results.bytesWritten + const buffer = results.buffer + assert.equal(bytesWritten, message.length, 'bytesWritten is correct') + assert.equal(buffer, message, 'data is correct') + }) + }) + }) + + describe('with callbacks', () => { + it('works', done => { + fs.write(TEST_FD, TEST_DATA, 0, SIZE, 0, (err, bytesWritten, buffer) => { + assert.ifError(err) + assert.equal(bytesWritten, SIZE, 'bytesWritten is correct') + assert(buffer.equals(TEST_DATA), 'data is correct') + done() + }) + }) + + onNode7it('works when minimal arguments are passed', done => { + fs.write(TEST_FD, TEST_DATA, (err, bytesWritten, buffer) => { + assert.ifError(err) + assert.equal(bytesWritten, SIZE, 'bytesWritten is correct') + assert(buffer.equals(TEST_DATA), 'data is correct') + done() + }) + }) + + it('works when writing a string', done => { + const message = 'Hello World!' + return fs.write(TEST_FD, message, (err, bytesWritten, buffer) => { + assert.ifError(err) + assert.equal(bytesWritten, message.length, 'bytesWritten is correct') + assert.equal(buffer, message, 'data is correct') + done() + }) + }) + }) +}) diff --git a/lib/fs/index.js b/lib/fs/index.js index e20ae76..551ca6a 100644 --- a/lib/fs/index.js +++ b/lib/fs/index.js @@ -21,7 +21,6 @@ const api = [ 'lstat', 'mkdir', 'open', - 'read', 'readFile', 'readdir', 'readlink', @@ -33,7 +32,6 @@ const api = [ 'truncate', 'unlink', 'utimes', - 'write', 'writeFile' ] // fs.mkdtemp() was added in Node.js v5.10.0, so check if it exists @@ -59,3 +57,45 @@ exports.exists = function (filename, callback) { return fs.exists(filename, resolve) }) } + +// fs.read() & fs.write need special treatment due to multiple callback args + +exports.read = function (fd, buffer, offset, length, position, callback) { + if (typeof callback === 'function') { + return fs.read(fd, buffer, offset, length, position, callback) + } + return new Promise((resolve, reject) => { + fs.read(fd, buffer, offset, length, position, (err, bytesRead, buffer) => { + if (err) return reject(err) + resolve({ bytesRead, buffer }) + }) + }) +} + +// Function signature can be +// fs.write(fd, buffer[, offset[, length[, position]]], callback) +// OR +// fs.write(fd, string[, position[, encoding]], callback) +// so we need to handle both cases +exports.write = function (fd, buffer, a, b, c, callback) { + if (typeof arguments[arguments.length - 1] === 'function') { + return fs.write(fd, buffer, a, b, c, callback) + } + + // Check for old, depricated fs.write(fd, string[, position[, encoding]], callback) + if (typeof buffer === 'string') { + return new Promise((resolve, reject) => { + fs.write(fd, buffer, a, b, (err, bytesWritten, buffer) => { + if (err) return reject(err) + resolve({ bytesWritten, buffer }) + }) + }) + } + + return new Promise((resolve, reject) => { + fs.write(fd, buffer, a, b, c, (err, bytesWritten, buffer) => { + if (err) return reject(err) + resolve({ bytesWritten, buffer }) + }) + }) +} diff --git a/package.json b/package.json index e539c95..6ba12c8 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "read-dir-files": "^0.1.1", "rimraf": "^2.2.8", "secure-random": "^1.1.1", + "semver": "^5.3.0", "standard": "^10.0.2", "standard-markdown": "^2.3.0" },