Merge from vscode 2b0b9136329c181a9e381463a1f7dc3a2d105a34 (#4880)

This commit is contained in:
Karl Burtram
2019-04-05 10:09:18 -07:00
committed by GitHub
parent 9bd7e30d18
commit cb5bcf2248
433 changed files with 8915 additions and 8361 deletions

View File

@@ -1,615 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'vs/base/common/path';
import { Readable } from 'stream';
import { canNormalize } from 'vs/base/common/normalization';
import { isLinux, isWindows } from 'vs/base/common/platform';
import * as uuid from 'vs/base/common/uuid';
import * as extfs from 'vs/base/node/extfs';
import { getPathFromAmdModule } from 'vs/base/common/amd';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
const ignore = () => { };
const mkdirp = (path: string, mode: number, callback: (error: any) => void) => {
extfs.mkdirp(path, mode).then(() => callback(null), error => callback(error));
};
const chunkSize = 64 * 1024;
const readError = 'Error while reading';
function toReadable(value: string, throwError?: boolean): Readable {
const totalChunks = Math.ceil(value.length / chunkSize);
const stringChunks: string[] = [];
for (let i = 0, j = 0; i < totalChunks; ++i, j += chunkSize) {
stringChunks[i] = value.substr(j, chunkSize);
}
let counter = 0;
return new Readable({
read: function () {
if (throwError) {
this.emit('error', new Error(readError));
}
let res!: string;
let canPush = true;
while (canPush && (res = stringChunks[counter++])) {
canPush = this.push(res);
}
// EOS
if (!res) {
this.push(null);
}
},
encoding: 'utf8'
});
}
suite('Extfs', () => {
test('mkdirp', function (done) {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extfs', id);
mkdirp(newDir, 493, error => {
if (error) {
return done(error);
}
assert.ok(fs.existsSync(newDir));
extfs.del(parentDir, os.tmpdir(), done, ignore);
}); // 493 = 0755
});
test('stat link', function (done) {
if (isWindows) {
// Symlinks are not the same on win, and we can not create them programitically without admin privileges
return done();
}
const id1 = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id1);
const directory = path.join(parentDir, 'extfs', id1);
const id2 = uuid.generateUuid();
const symbolicLink = path.join(parentDir, 'extfs', id2);
mkdirp(directory, 493, error => {
if (error) {
return done(error);
}
fs.symlinkSync(directory, symbolicLink);
extfs.statLink(directory, (error, statAndIsLink) => {
if (error) {
return done(error);
}
assert.ok(!statAndIsLink!.isSymbolicLink);
extfs.statLink(symbolicLink, (error, statAndIsLink) => {
if (error) {
return done(error);
}
assert.ok(statAndIsLink!.isSymbolicLink);
extfs.delSync(directory);
done();
});
});
});
});
test('delSync - swallows file not found error', function () {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extfs', id);
extfs.delSync(newDir);
assert.ok(!fs.existsSync(newDir));
});
test('delSync - simple', function (done) {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extfs', id);
mkdirp(newDir, 493, error => {
if (error) {
return done(error);
}
fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents');
fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents');
extfs.delSync(newDir);
assert.ok(!fs.existsSync(newDir));
done();
}); // 493 = 0755
});
test('delSync - recursive folder structure', function (done) {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extfs', id);
mkdirp(newDir, 493, error => {
if (error) {
return done(error);
}
fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents');
fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents');
fs.mkdirSync(path.join(newDir, 'somefolder'));
fs.writeFileSync(path.join(newDir, 'somefolder', 'somefile.txt'), 'Contents');
extfs.delSync(newDir);
assert.ok(!fs.existsSync(newDir));
done();
}); // 493 = 0755
});
test('copy, move and delete', function (done) {
const id = uuid.generateUuid();
const id2 = uuid.generateUuid();
const sourceDir = getPathFromAmdModule(require, './fixtures');
const parentDir = path.join(os.tmpdir(), 'vsctests', 'extfs');
const targetDir = path.join(parentDir, id);
const targetDir2 = path.join(parentDir, id2);
extfs.copy(sourceDir, targetDir, error => {
if (error) {
return done(error);
}
assert.ok(fs.existsSync(targetDir));
assert.ok(fs.existsSync(path.join(targetDir, 'index.html')));
assert.ok(fs.existsSync(path.join(targetDir, 'site.css')));
assert.ok(fs.existsSync(path.join(targetDir, 'examples')));
assert.ok(fs.statSync(path.join(targetDir, 'examples')).isDirectory());
assert.ok(fs.existsSync(path.join(targetDir, 'examples', 'small.jxs')));
extfs.mv(targetDir, targetDir2, error => {
if (error) {
return done(error);
}
assert.ok(!fs.existsSync(targetDir));
assert.ok(fs.existsSync(targetDir2));
assert.ok(fs.existsSync(path.join(targetDir2, 'index.html')));
assert.ok(fs.existsSync(path.join(targetDir2, 'site.css')));
assert.ok(fs.existsSync(path.join(targetDir2, 'examples')));
assert.ok(fs.statSync(path.join(targetDir2, 'examples')).isDirectory());
assert.ok(fs.existsSync(path.join(targetDir2, 'examples', 'small.jxs')));
extfs.mv(path.join(targetDir2, 'index.html'), path.join(targetDir2, 'index_moved.html'), error => {
if (error) {
return done(error);
}
assert.ok(!fs.existsSync(path.join(targetDir2, 'index.html')));
assert.ok(fs.existsSync(path.join(targetDir2, 'index_moved.html')));
extfs.del(parentDir, os.tmpdir(), error => {
if (error) {
return done(error);
}
}, error => {
if (error) {
return done(error);
}
assert.ok(!fs.existsSync(parentDir));
done();
});
});
});
});
});
test('readdir', function (done) {
if (canNormalize && typeof process.versions['electron'] !== 'undefined' /* needs electron */) {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extfs', id, 'öäü');
mkdirp(newDir, 493, error => {
if (error) {
return done(error);
}
assert.ok(fs.existsSync(newDir));
extfs.readdir(path.join(parentDir, 'extfs', id), (error, children) => {
assert.equal(children.some(n => n === 'öäü'), true); // Mac always converts to NFD, so
extfs.del(parentDir, os.tmpdir(), done, ignore);
});
}); // 493 = 0755
} else {
done();
}
});
test('writeFileAndFlush (string)', function (done) {
const smallData = 'Hello World';
const bigData = (new Array(100 * 1024)).join('Large String\n');
testWriteFileAndFlush(smallData, smallData, bigData, bigData, done);
});
test('writeFileAndFlush (Buffer)', function (done) {
const smallData = 'Hello World';
const bigData = (new Array(100 * 1024)).join('Large String\n');
testWriteFileAndFlush(Buffer.from(smallData), smallData, Buffer.from(bigData), bigData, done);
});
test('writeFileAndFlush (UInt8Array)', function (done) {
const smallData = 'Hello World';
const bigData = (new Array(100 * 1024)).join('Large String\n');
testWriteFileAndFlush(new TextEncoder().encode(smallData), smallData, new TextEncoder().encode(bigData), bigData, done);
});
test('writeFileAndFlush (stream)', function (done) {
const smallData = 'Hello World';
const bigData = (new Array(100 * 1024)).join('Large String\n');
testWriteFileAndFlush(toReadable(smallData), smallData, toReadable(bigData), bigData, done);
});
function testWriteFileAndFlush(
smallData: string | Buffer | NodeJS.ReadableStream | Uint8Array,
smallDataValue: string,
bigData: string | Buffer | NodeJS.ReadableStream | Uint8Array,
bigDataValue: string,
done: (error: Error | null) => void
): void {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extfs', id);
const testFile = path.join(newDir, 'flushed.txt');
mkdirp(newDir, 493, error => {
if (error) {
return done(error);
}
assert.ok(fs.existsSync(newDir));
extfs.writeFileAndFlush(testFile, smallData, null!, error => {
if (error) {
return done(error);
}
assert.equal(fs.readFileSync(testFile), smallDataValue);
extfs.writeFileAndFlush(testFile, bigData, null!, error => {
if (error) {
return done(error);
}
assert.equal(fs.readFileSync(testFile), bigDataValue);
extfs.del(parentDir, os.tmpdir(), done, ignore);
});
});
});
}
test('writeFileAndFlush (file stream)', function (done) {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const sourceFile = getPathFromAmdModule(require, './fixtures/index.html');
const newDir = path.join(parentDir, 'extfs', id);
const testFile = path.join(newDir, 'flushed.txt');
mkdirp(newDir, 493, error => {
if (error) {
return done(error);
}
assert.ok(fs.existsSync(newDir));
extfs.writeFileAndFlush(testFile, fs.createReadStream(sourceFile), null!, error => {
if (error) {
return done(error);
}
assert.equal(fs.readFileSync(testFile).toString(), fs.readFileSync(sourceFile).toString());
extfs.del(parentDir, os.tmpdir(), done, ignore);
});
});
});
test('writeFileAndFlush (string, error handling)', function (done) {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extfs', id);
const testFile = path.join(newDir, 'flushed.txt');
mkdirp(newDir, 493, error => {
if (error) {
return done(error);
}
assert.ok(fs.existsSync(newDir));
fs.mkdirSync(testFile); // this will trigger an error because testFile is now a directory!
extfs.writeFileAndFlush(testFile, 'Hello World', null!, error => {
if (!error) {
return done(new Error('Expected error for writing to readonly file'));
}
extfs.del(parentDir, os.tmpdir(), done, ignore);
});
});
});
test('writeFileAndFlush (stream, error handling EISDIR)', function (done) {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extfs', id);
const testFile = path.join(newDir, 'flushed.txt');
mkdirp(newDir, 493, error => {
if (error) {
return done(error);
}
assert.ok(fs.existsSync(newDir));
fs.mkdirSync(testFile); // this will trigger an error because testFile is now a directory!
const readable = toReadable('Hello World');
extfs.writeFileAndFlush(testFile, readable, null!, error => {
if (!error || (<any>error).code !== 'EISDIR') {
return done(new Error('Expected EISDIR error for writing to folder but got: ' + (error ? (<any>error).code : 'no error')));
}
// verify that the stream is still consumable (for https://github.com/Microsoft/vscode/issues/42542)
assert.equal(readable.read(), 'Hello World');
extfs.del(parentDir, os.tmpdir(), done, ignore);
});
});
});
test('writeFileAndFlush (stream, error handling READERROR)', function (done) {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extfs', id);
const testFile = path.join(newDir, 'flushed.txt');
mkdirp(newDir, 493, error => {
if (error) {
return done(error);
}
assert.ok(fs.existsSync(newDir));
extfs.writeFileAndFlush(testFile, toReadable('Hello World', true /* throw error */), null!, error => {
if (!error || error.message !== readError) {
return done(new Error('Expected error for writing to folder'));
}
extfs.del(parentDir, os.tmpdir(), done, ignore);
});
});
});
test('writeFileAndFlush (stream, error handling EACCES)', function (done) {
if (isLinux) {
return done(); // somehow this test fails on Linux in our TFS builds
}
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extfs', id);
const testFile = path.join(newDir, 'flushed.txt');
mkdirp(newDir, 493, error => {
if (error) {
return done(error);
}
assert.ok(fs.existsSync(newDir));
fs.writeFileSync(testFile, '');
fs.chmodSync(testFile, 33060); // make readonly
extfs.writeFileAndFlush(testFile, toReadable('Hello World'), null!, error => {
if (!error || !((<any>error).code !== 'EACCES' || (<any>error).code !== 'EPERM')) {
return done(new Error('Expected EACCES/EPERM error for writing to folder but got: ' + (error ? (<any>error).code : 'no error')));
}
extfs.del(parentDir, os.tmpdir(), done, ignore);
});
});
});
test('writeFileAndFlush (file stream, error handling)', function (done) {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const sourceFile = getPathFromAmdModule(require, './fixtures/index.html');
const newDir = path.join(parentDir, 'extfs', id);
const testFile = path.join(newDir, 'flushed.txt');
mkdirp(newDir, 493, error => {
if (error) {
return done(error);
}
assert.ok(fs.existsSync(newDir));
fs.mkdirSync(testFile); // this will trigger an error because testFile is now a directory!
extfs.writeFileAndFlush(testFile, fs.createReadStream(sourceFile), null!, error => {
if (!error) {
return done(new Error('Expected error for writing to folder'));
}
extfs.del(parentDir, os.tmpdir(), done, ignore);
});
});
});
test('writeFileAndFlushSync', function (done) {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extfs', id);
const testFile = path.join(newDir, 'flushed.txt');
mkdirp(newDir, 493, error => {
if (error) {
return done(error);
}
assert.ok(fs.existsSync(newDir));
extfs.writeFileAndFlushSync(testFile, 'Hello World', null!);
assert.equal(fs.readFileSync(testFile), 'Hello World');
const largeString = (new Array(100 * 1024)).join('Large String\n');
extfs.writeFileAndFlushSync(testFile, largeString, null!);
assert.equal(fs.readFileSync(testFile), largeString);
extfs.del(parentDir, os.tmpdir(), done, ignore);
});
});
test('realcase', (done) => {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extfs', id);
mkdirp(newDir, 493, error => {
// {{SQL CARBON EDIT}} don't run this test case on Windows as this fails in VSO
// assume case insensitive file system
if (process.platform === 'darwin') {
const upper = newDir.toUpperCase();
const real = extfs.realcaseSync(upper);
if (real) { // can be null in case of permission errors
assert.notEqual(real, upper);
assert.equal(real.toUpperCase(), upper);
assert.equal(real, newDir);
}
}
// linux, unix, etc. -> assume case sensitive file system
else if (process.platform !== 'win32') {
const real = extfs.realcaseSync(newDir);
assert.equal(real, newDir);
}
extfs.del(parentDir, os.tmpdir(), done, ignore);
});
});
test('realpath', (done) => {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extfs', id);
mkdirp(newDir, 493, error => {
extfs.realpath(newDir, (error, realpath) => {
assert.ok(realpath);
assert.ok(!error);
extfs.del(parentDir, os.tmpdir(), done, ignore);
});
});
});
test('realpathSync', (done) => {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extfs', id);
mkdirp(newDir, 493, error => {
let realpath!: string;
try {
realpath = extfs.realpathSync(newDir);
} catch (error) {
assert.ok(!error);
}
assert.ok(realpath!);
extfs.del(parentDir, os.tmpdir(), done, ignore);
});
});
test('mkdirp cancellation', (done) => {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extfs', id);
const source = new CancellationTokenSource();
const mkdirpPromise = extfs.mkdirp(newDir, 493, source.token);
source.cancel();
return mkdirpPromise.then(res => {
assert.equal(res, false);
extfs.del(parentDir, os.tmpdir(), done, ignore);
});
});
test('sanitizeFilePath', () => {
if (isWindows) {
assert.equal(extfs.sanitizeFilePath('.', 'C:\\the\\cwd'), 'C:\\the\\cwd');
assert.equal(extfs.sanitizeFilePath('', 'C:\\the\\cwd'), 'C:\\the\\cwd');
assert.equal(extfs.sanitizeFilePath('C:', 'C:\\the\\cwd'), 'C:\\');
assert.equal(extfs.sanitizeFilePath('C:\\', 'C:\\the\\cwd'), 'C:\\');
assert.equal(extfs.sanitizeFilePath('C:\\\\', 'C:\\the\\cwd'), 'C:\\');
assert.equal(extfs.sanitizeFilePath('C:\\folder\\my.txt', 'C:\\the\\cwd'), 'C:\\folder\\my.txt');
assert.equal(extfs.sanitizeFilePath('C:\\folder\\my', 'C:\\the\\cwd'), 'C:\\folder\\my');
assert.equal(extfs.sanitizeFilePath('C:\\folder\\..\\my', 'C:\\the\\cwd'), 'C:\\my');
assert.equal(extfs.sanitizeFilePath('C:\\folder\\my\\', 'C:\\the\\cwd'), 'C:\\folder\\my');
assert.equal(extfs.sanitizeFilePath('C:\\folder\\my\\\\\\', 'C:\\the\\cwd'), 'C:\\folder\\my');
assert.equal(extfs.sanitizeFilePath('my.txt', 'C:\\the\\cwd'), 'C:\\the\\cwd\\my.txt');
assert.equal(extfs.sanitizeFilePath('my.txt\\', 'C:\\the\\cwd'), 'C:\\the\\cwd\\my.txt');
assert.equal(extfs.sanitizeFilePath('\\\\localhost\\folder\\my', 'C:\\the\\cwd'), '\\\\localhost\\folder\\my');
assert.equal(extfs.sanitizeFilePath('\\\\localhost\\folder\\my\\', 'C:\\the\\cwd'), '\\\\localhost\\folder\\my');
} else {
assert.equal(extfs.sanitizeFilePath('.', '/the/cwd'), '/the/cwd');
assert.equal(extfs.sanitizeFilePath('', '/the/cwd'), '/the/cwd');
assert.equal(extfs.sanitizeFilePath('/', '/the/cwd'), '/');
assert.equal(extfs.sanitizeFilePath('/folder/my.txt', '/the/cwd'), '/folder/my.txt');
assert.equal(extfs.sanitizeFilePath('/folder/my', '/the/cwd'), '/folder/my');
assert.equal(extfs.sanitizeFilePath('/folder/../my', '/the/cwd'), '/my');
assert.equal(extfs.sanitizeFilePath('/folder/my/', '/the/cwd'), '/folder/my');
assert.equal(extfs.sanitizeFilePath('/folder/my///', '/the/cwd'), '/folder/my');
assert.equal(extfs.sanitizeFilePath('my.txt', '/the/cwd'), '/the/cwd/my.txt');
assert.equal(extfs.sanitizeFilePath('my.txt/', '/the/cwd'), '/the/cwd/my.txt');
}
});
});

View File

@@ -0,0 +1,73 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import * as os from 'os';
import * as path from 'vs/base/common/path';
import * as uuid from 'vs/base/common/uuid';
import * as pfs from 'vs/base/node/pfs';
import { realcaseSync, realpath, realpathSync } from 'vs/base/node/extpath';
suite('Extpath', () => {
test('realcase', async () => {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extpath', id);
await pfs.mkdirp(newDir, 493);
// assume case insensitive file system
if (process.platform === 'win32' || process.platform === 'darwin') {
const upper = newDir.toUpperCase();
const real = realcaseSync(upper);
if (real) { // can be null in case of permission errors
assert.notEqual(real, upper);
assert.equal(real.toUpperCase(), upper);
assert.equal(real, newDir);
}
}
// linux, unix, etc. -> assume case sensitive file system
else {
const real = realcaseSync(newDir);
assert.equal(real, newDir);
}
await pfs.rimraf(parentDir, pfs.RimRafMode.MOVE);
});
test('realpath', async () => {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extpath', id);
await pfs.mkdirp(newDir, 493);
const realpathVal = await realpath(newDir);
assert.ok(realpathVal);
await pfs.rimraf(parentDir, pfs.RimRafMode.MOVE);
});
test('realpathSync', async () => {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extpath', id);
await pfs.mkdirp(newDir, 493);
let realpath!: string;
try {
realpath = realpathSync(newDir);
} catch (error) {
assert.ok(!error);
}
assert.ok(realpath!);
await pfs.rimraf(parentDir, pfs.RimRafMode.MOVE);
});
});

View File

@@ -1,488 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import * as flow from 'vs/base/node/flow';
const loop = flow.loop;
const sequence = flow.sequence;
const parallel = flow.parallel;
suite('Flow', () => {
function assertCounterEquals(counter: number, expected: number): void {
assert.ok(counter === expected, 'Expected ' + expected + ' assertions, but got ' + counter);
}
function syncThrowsError(callback: any): void {
callback(new Error('foo'), null);
}
function syncSequenceGetThrowsError(value: any, callback: any) {
sequence(
function onError(error) {
callback(error, null);
},
function getFirst(this: any) {
syncThrowsError(this);
},
function handleFirst(first: number) {
//Foo
}
);
}
function syncGet(value: any, callback: any): void {
callback(null, value);
}
function syncGetError(value: any, callback: any): void {
callback(new Error(''), null);
}
function asyncGet(value: any, callback: any): void {
process.nextTick(function () {
callback(null, value);
});
}
function asyncGetError(value: any, callback: any): void {
process.nextTick(function () {
callback(new Error(''), null);
});
}
test('loopSync', function (done: () => void) {
const elements = ['1', '2', '3'];
loop(elements, function (element, callback, index, total) {
assert.ok(index === 0 || index === 1 || index === 2);
assert.deepEqual(3, total);
callback(null, element);
}, function (error, result) {
assert.equal(error, null);
assert.deepEqual(result, elements);
done();
});
});
test('loopByFunctionSync', function (done: () => void) {
const elements = function (callback: Function) {
callback(null, ['1', '2', '3']);
};
loop(elements, function (element, callback) {
callback(null, element);
}, function (error, result) {
assert.equal(error, null);
assert.deepEqual(result, ['1', '2', '3']);
done();
});
});
test('loopByFunctionAsync', function (done: () => void) {
const elements = function (callback: Function) {
process.nextTick(function () {
callback(null, ['1', '2', '3']);
});
};
loop(elements, function (element, callback) {
callback(null, element);
}, function (error, result) {
assert.equal(error, null);
assert.deepEqual(result, ['1', '2', '3']);
done();
});
});
test('loopSyncErrorByThrow', function (done: () => void) {
const elements = ['1', '2', '3'];
loop(elements, function (element, callback) {
if (element === '2') {
throw new Error('foo');
} else {
callback(null, element);
}
}, function (error, result) {
assert.ok(error);
assert.ok(!result);
done();
});
});
test('loopSyncErrorByCallback', function (done: () => void) {
const elements = ['1', '2', '3'];
loop(elements, function (element, callback) {
if (element === '2') {
callback(new Error('foo'), null);
} else {
callback(null, element);
}
}, function (error, result) {
assert.ok(error);
assert.ok(!result);
done();
});
});
test('loopAsync', function (done: () => void) {
const elements = ['1', '2', '3'];
loop(elements, function (element, callback) {
process.nextTick(function () {
callback(null, element);
});
}, function (error, result) {
assert.equal(error, null);
assert.deepEqual(result, elements);
done();
});
});
test('loopAsyncErrorByCallback', function (done: () => void) {
const elements = ['1', '2', '3'];
loop(elements, function (element, callback) {
process.nextTick(function () {
if (element === '2') {
callback(new Error('foo'), null);
} else {
callback(null, element);
}
});
}, function (error, result) {
assert.ok(error);
assert.ok(!result);
done();
});
});
test('sequenceSync', function (done: () => void) {
let assertionCount = 0;
let errorCount = 0;
sequence(
function onError(error) {
errorCount++;
},
function getFirst(this: any) {
syncGet('1', this);
},
function handleFirst(this: any, first: number) {
assert.deepEqual('1', first);
assertionCount++;
syncGet('2', this);
},
function handleSecond(this: any, second: any) {
assert.deepEqual('2', second);
assertionCount++;
syncGet(null, this);
},
function handleThird(third: any) {
assert.ok(!third);
assertionCount++;
assertCounterEquals(assertionCount, 3);
assertCounterEquals(errorCount, 0);
done();
}
);
});
test('sequenceAsync', function (done: () => void) {
let assertionCount = 0;
let errorCount = 0;
sequence(
function onError(error) {
errorCount++;
},
function getFirst(this: any) {
asyncGet('1', this);
},
function handleFirst(this: any, first: number) {
assert.deepEqual('1', first);
assertionCount++;
asyncGet('2', this);
},
function handleSecond(this: any, second: number) {
assert.deepEqual('2', second);
assertionCount++;
asyncGet(null, this);
},
function handleThird(third: number) {
assert.ok(!third);
assertionCount++;
assertCounterEquals(assertionCount, 3);
assertCounterEquals(errorCount, 0);
done();
}
);
});
test('sequenceSyncErrorByThrow', function (done: () => void) {
let assertionCount = 0;
let errorCount = 0;
sequence(
function onError(error) {
errorCount++;
assertCounterEquals(assertionCount, 1);
assertCounterEquals(errorCount, 1);
done();
},
function getFirst(this: any) {
syncGet('1', this);
},
function handleFirst(this: any, first: number) {
assert.deepEqual('1', first);
assertionCount++;
syncGet('2', this);
},
function handleSecond(second: number) {
if (true) {
throw new Error('');
}
// assertionCount++;
// syncGet(null, this);
},
function handleThird(third: number) {
throw new Error('We should not be here');
}
);
});
test('sequenceSyncErrorByCallback', function (done: () => void) {
let assertionCount = 0;
let errorCount = 0;
sequence(
function onError(error) {
errorCount++;
assertCounterEquals(assertionCount, 1);
assertCounterEquals(errorCount, 1);
done();
},
function getFirst(this: any) {
syncGet('1', this);
},
function handleFirst(this: any, first: number) {
assert.deepEqual('1', first);
assertionCount++;
syncGetError('2', this);
},
function handleSecond(second: number) {
throw new Error('We should not be here');
}
);
});
test('sequenceAsyncErrorByThrow', function (done: () => void) {
let assertionCount = 0;
let errorCount = 0;
sequence(
function onError(error) {
errorCount++;
assertCounterEquals(assertionCount, 1);
assertCounterEquals(errorCount, 1);
done();
},
function getFirst(this: any) {
asyncGet('1', this);
},
function handleFirst(this: any, first: number) {
assert.deepEqual('1', first);
assertionCount++;
asyncGet('2', this);
},
function handleSecond(second: number) {
if (true) {
throw new Error('');
}
// assertionCount++;
// asyncGet(null, this);
},
function handleThird(third: number) {
throw new Error('We should not be here');
}
);
});
test('sequenceAsyncErrorByCallback', function (done: () => void) {
let assertionCount = 0;
let errorCount = 0;
sequence(
function onError(error) {
errorCount++;
assertCounterEquals(assertionCount, 1);
assertCounterEquals(errorCount, 1);
done();
},
function getFirst(this: any) {
asyncGet('1', this);
},
function handleFirst(this: any, first: number) {
assert.deepEqual('1', first);
assertionCount++;
asyncGetError('2', this);
},
function handleSecond(second: number) {
throw new Error('We should not be here');
}
);
});
test('syncChainedSequenceError', function (done: () => void) {
sequence(
function onError(error) {
done();
},
function getFirst(this: any) {
syncSequenceGetThrowsError('1', this);
}
);
});
test('tolerateBooleanResults', function (done: () => void) {
let assertionCount = 0;
let errorCount = 0;
sequence(
function onError(error) {
errorCount++;
},
function getFirst(this: any) {
this(true);
},
function getSecond(this: any, result: boolean) {
assert.equal(result, true);
this(false);
},
function last(result: boolean) {
assert.equal(result, false);
assertionCount++;
assertCounterEquals(assertionCount, 1);
assertCounterEquals(errorCount, 0);
done();
}
);
});
test('loopTolerateBooleanResults', function (done: () => void) {
let elements = ['1', '2', '3'];
loop(elements, function (element, callback) {
process.nextTick(function () {
(<any>callback)(true);
});
}, function (error, result) {
assert.equal(error, null);
assert.deepEqual(result, [true, true, true]);
done();
});
});
test('parallel', function (done: () => void) {
let elements = [1, 2, 3, 4, 5];
let sum = 0;
parallel(elements, function (element, callback) {
sum += element;
callback(null!, element * element);
}, function (errors, result) {
assert.ok(!errors);
assert.deepEqual(sum, 15);
assert.deepEqual(result, [1, 4, 9, 16, 25]);
done();
});
});
test('parallel - setTimeout', function (done: () => void) {
let elements = [1, 2, 3, 4, 5];
let timeouts = [10, 30, 5, 0, 4];
let sum = 0;
parallel(elements, function (element, callback) {
setTimeout(function () {
sum += element;
callback(null!, element * element);
}, timeouts.pop());
}, function (errors, result) {
assert.ok(!errors);
assert.deepEqual(sum, 15);
assert.deepEqual(result, [1, 4, 9, 16, 25]);
done();
});
});
test('parallel - with error', function (done: () => void) {
const elements = [1, 2, 3, 4, 5];
const timeouts = [10, 30, 5, 0, 4];
let sum = 0;
parallel(elements, function (element, callback) {
setTimeout(function () {
if (element === 4) {
callback(new Error('error!'), null!);
} else {
sum += element;
callback(null!, element * element);
}
}, timeouts.pop());
}, function (errors, result) {
assert.ok(errors);
assert.deepEqual(errors, [null, null, null, new Error('error!'), null]);
assert.deepEqual(sum, 11);
assert.deepEqual(result, [1, 4, 9, null, 25]);
done();
});
});
});

View File

@@ -455,7 +455,7 @@ suite('Glob', () => {
expression = {
'**/*.js': {
}
} as any
};
assert.strictEqual('**/*.js', glob.match(expression, 'test.js', hasSibling));
@@ -474,7 +474,7 @@ suite('Glob', () => {
'**/*.js': { when: '$(basename).ts' },
'**/*.as': true,
'**/*.foo': false,
'**/*.bananas': { bananas: true }
'**/*.bananas': { bananas: true } as any
};
assert.strictEqual('**/*.js', glob.match(expression, 'test.js', hasSibling));
@@ -691,7 +691,7 @@ suite('Glob', () => {
});
test('expression with other falsy value', function () {
let expr = { '**/*.js': 0 };
let expr = { '**/*.js': 0 } as any;
assert.strictEqual(glob.match(expr, 'foo.js'), '**/*.js');
});

View File

@@ -1,138 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import * as os from 'os';
import * as path from 'vs/base/common/path';
import * as fs from 'fs';
import * as uuid from 'vs/base/common/uuid';
import * as pfs from 'vs/base/node/pfs';
import { timeout } from 'vs/base/common/async';
suite('PFS', () => {
test('writeFile', () => {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'pfs', id);
const testFile = path.join(newDir, 'writefile.txt');
return pfs.mkdirp(newDir, 493).then(() => {
assert.ok(fs.existsSync(newDir));
return pfs.writeFile(testFile, 'Hello World', null!).then(() => {
assert.equal(fs.readFileSync(testFile), 'Hello World');
return pfs.del(parentDir, os.tmpdir());
});
});
});
test('writeFile - parallel write on different files works', function () {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'pfs', id);
const testFile1 = path.join(newDir, 'writefile1.txt');
const testFile2 = path.join(newDir, 'writefile2.txt');
const testFile3 = path.join(newDir, 'writefile3.txt');
const testFile4 = path.join(newDir, 'writefile4.txt');
const testFile5 = path.join(newDir, 'writefile5.txt');
return pfs.mkdirp(newDir, 493).then(() => {
assert.ok(fs.existsSync(newDir));
return Promise.all([
pfs.writeFile(testFile1, 'Hello World 1', null!),
pfs.writeFile(testFile2, 'Hello World 2', null!),
pfs.writeFile(testFile3, 'Hello World 3', null!),
pfs.writeFile(testFile4, 'Hello World 4', null!),
pfs.writeFile(testFile5, 'Hello World 5', null!)
]).then(() => {
assert.equal(fs.readFileSync(testFile1), 'Hello World 1');
assert.equal(fs.readFileSync(testFile2), 'Hello World 2');
assert.equal(fs.readFileSync(testFile3), 'Hello World 3');
assert.equal(fs.readFileSync(testFile4), 'Hello World 4');
assert.equal(fs.readFileSync(testFile5), 'Hello World 5');
return pfs.del(parentDir, os.tmpdir());
});
});
});
test('writeFile - parallel write on same files works and is sequentalized', function () {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'pfs', id);
const testFile = path.join(newDir, 'writefile.txt');
return pfs.mkdirp(newDir, 493).then(() => {
assert.ok(fs.existsSync(newDir));
return Promise.all([
pfs.writeFile(testFile, 'Hello World 1', undefined),
pfs.writeFile(testFile, 'Hello World 2', undefined),
timeout(10).then(() => pfs.writeFile(testFile, 'Hello World 3', undefined)),
pfs.writeFile(testFile, 'Hello World 4', undefined),
timeout(10).then(() => pfs.writeFile(testFile, 'Hello World 5', undefined))
]).then(() => {
assert.equal(fs.readFileSync(testFile), 'Hello World 5');
return pfs.del(parentDir, os.tmpdir());
});
});
});
test('rimraf - simple', function () {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extfs', id);
return pfs.mkdirp(newDir, 493).then(() => {
fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents');
fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents');
return pfs.rimraf(newDir).then(() => {
assert.ok(!fs.existsSync(newDir));
});
});
});
test('rimraf - recursive folder structure', function () {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extfs', id);
return pfs.mkdirp(newDir, 493).then(() => {
fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents');
fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents');
fs.mkdirSync(path.join(newDir, 'somefolder'));
fs.writeFileSync(path.join(newDir, 'somefolder', 'somefile.txt'), 'Contents');
return pfs.rimraf(newDir).then(() => {
assert.ok(!fs.existsSync(newDir));
});
});
});
test('moveIgnoreError', function () {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'extfs', id);
return pfs.mkdirp(newDir, 493).then(() => {
return pfs.renameIgnoreError(path.join(newDir, 'foo'), path.join(newDir, 'bar')).then(() => {
return pfs.del(parentDir, os.tmpdir());
}, error => {
assert.fail(error);
return Promise.reject(error);
});
});
});
});

View File

@@ -1,6 +1,6 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/*----------------------------------------------------------

View File

@@ -0,0 +1,612 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import * as os from 'os';
import * as path from 'vs/base/common/path';
import * as fs from 'fs';
import { Readable } from 'stream';
import * as uuid from 'vs/base/common/uuid';
import * as pfs from 'vs/base/node/pfs';
import { timeout } from 'vs/base/common/async';
import { getPathFromAmdModule } from 'vs/base/common/amd';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { isWindows, isLinux } from 'vs/base/common/platform';
import { canNormalize } from 'vs/base/common/normalization';
import { VSBuffer } from 'vs/base/common/buffer';
const chunkSize = 64 * 1024;
const readError = 'Error while reading';
function toReadable(value: string, throwError?: boolean): Readable {
const totalChunks = Math.ceil(value.length / chunkSize);
const stringChunks: string[] = [];
for (let i = 0, j = 0; i < totalChunks; ++i, j += chunkSize) {
stringChunks[i] = value.substr(j, chunkSize);
}
let counter = 0;
return new Readable({
read: function () {
if (throwError) {
this.emit('error', new Error(readError));
}
let res!: string;
let canPush = true;
while (canPush && (res = stringChunks[counter++])) {
canPush = this.push(res);
}
// EOS
if (!res) {
this.push(null);
}
},
encoding: 'utf8'
});
}
suite('PFS', () => {
test('writeFile', async () => {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'pfs', id);
const testFile = path.join(newDir, 'writefile.txt');
await pfs.mkdirp(newDir, 493);
assert.ok(fs.existsSync(newDir));
await pfs.writeFile(testFile, 'Hello World', (null!));
assert.equal(fs.readFileSync(testFile), 'Hello World');
await pfs.rimraf(parentDir, pfs.RimRafMode.MOVE);
});
test('writeFile - parallel write on different files works', async () => {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'pfs', id);
const testFile1 = path.join(newDir, 'writefile1.txt');
const testFile2 = path.join(newDir, 'writefile2.txt');
const testFile3 = path.join(newDir, 'writefile3.txt');
const testFile4 = path.join(newDir, 'writefile4.txt');
const testFile5 = path.join(newDir, 'writefile5.txt');
await pfs.mkdirp(newDir, 493);
assert.ok(fs.existsSync(newDir));
await Promise.all([
pfs.writeFile(testFile1, 'Hello World 1', (null!)),
pfs.writeFile(testFile2, 'Hello World 2', (null!)),
pfs.writeFile(testFile3, 'Hello World 3', (null!)),
pfs.writeFile(testFile4, 'Hello World 4', (null!)),
pfs.writeFile(testFile5, 'Hello World 5', (null!))
]);
assert.equal(fs.readFileSync(testFile1), 'Hello World 1');
assert.equal(fs.readFileSync(testFile2), 'Hello World 2');
assert.equal(fs.readFileSync(testFile3), 'Hello World 3');
assert.equal(fs.readFileSync(testFile4), 'Hello World 4');
assert.equal(fs.readFileSync(testFile5), 'Hello World 5');
await pfs.rimraf(parentDir, pfs.RimRafMode.MOVE);
});
test('writeFile - parallel write on same files works and is sequentalized', async () => {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'pfs', id);
const testFile = path.join(newDir, 'writefile.txt');
await pfs.mkdirp(newDir, 493);
assert.ok(fs.existsSync(newDir));
await Promise.all([
pfs.writeFile(testFile, 'Hello World 1', undefined),
pfs.writeFile(testFile, 'Hello World 2', undefined),
timeout(10).then(() => pfs.writeFile(testFile, 'Hello World 3', undefined)),
pfs.writeFile(testFile, 'Hello World 4', undefined),
timeout(10).then(() => pfs.writeFile(testFile, 'Hello World 5', undefined))
]);
assert.equal(fs.readFileSync(testFile), 'Hello World 5');
await pfs.rimraf(parentDir, pfs.RimRafMode.MOVE);
});
test('rimraf - simple - unlink', async () => {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'pfs', id);
await pfs.mkdirp(newDir, 493);
fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents');
fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents');
await pfs.rimraf(newDir);
assert.ok(!fs.existsSync(newDir));
});
test('rimraf - simple - move', async () => {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'pfs', id);
await pfs.mkdirp(newDir, 493);
fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents');
fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents');
await pfs.rimraf(newDir, pfs.RimRafMode.MOVE);
assert.ok(!fs.existsSync(newDir));
});
test('rimraf - recursive folder structure - unlink', async () => {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'pfs', id);
await pfs.mkdirp(newDir, 493);
fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents');
fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents');
fs.mkdirSync(path.join(newDir, 'somefolder'));
fs.writeFileSync(path.join(newDir, 'somefolder', 'somefile.txt'), 'Contents');
await pfs.rimraf(newDir);
assert.ok(!fs.existsSync(newDir));
});
test('rimraf - recursive folder structure - move', async () => {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'pfs', id);
await pfs.mkdirp(newDir, 493);
fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents');
fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents');
fs.mkdirSync(path.join(newDir, 'somefolder'));
fs.writeFileSync(path.join(newDir, 'somefolder', 'somefile.txt'), 'Contents');
await pfs.rimraf(newDir, pfs.RimRafMode.MOVE);
assert.ok(!fs.existsSync(newDir));
});
test('rimraf - simple ends with dot - move', async () => {
const id = `${uuid.generateUuid()}.`;
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'pfs', id);
await pfs.mkdirp(newDir, 493);
fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents');
fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents');
await pfs.rimraf(newDir, pfs.RimRafMode.MOVE);
assert.ok(!fs.existsSync(newDir));
});
test('rimraf - simple ends with dot slash/backslash - move', async () => {
const id = `${uuid.generateUuid()}.`;
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'pfs', id);
await pfs.mkdirp(newDir, 493);
fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents');
fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents');
await pfs.rimraf(`${newDir}${path.sep}`, pfs.RimRafMode.MOVE);
assert.ok(!fs.existsSync(newDir));
});
test('rimrafSync - swallows file not found error', function () {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'pfs', id);
pfs.rimrafSync(newDir);
assert.ok(!fs.existsSync(newDir));
});
test('rimrafSync - simple', async () => {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'pfs', id);
await pfs.mkdirp(newDir, 493);
fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents');
fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents');
pfs.rimrafSync(newDir);
assert.ok(!fs.existsSync(newDir));
});
test('rimrafSync - recursive folder structure', async () => {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'pfs', id);
await pfs.mkdirp(newDir, 493);
fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents');
fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents');
fs.mkdirSync(path.join(newDir, 'somefolder'));
fs.writeFileSync(path.join(newDir, 'somefolder', 'somefile.txt'), 'Contents');
pfs.rimrafSync(newDir);
assert.ok(!fs.existsSync(newDir));
});
test('moveIgnoreError', async () => {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'pfs', id);
await pfs.mkdirp(newDir, 493);
try {
await pfs.renameIgnoreError(path.join(newDir, 'foo'), path.join(newDir, 'bar'));
return pfs.rimraf(parentDir, pfs.RimRafMode.MOVE);
}
catch (error) {
assert.fail(error);
return Promise.reject(error);
}
});
test('copy, move and delete', async () => {
const id = uuid.generateUuid();
const id2 = uuid.generateUuid();
const sourceDir = getPathFromAmdModule(require, './fixtures');
const parentDir = path.join(os.tmpdir(), 'vsctests', 'pfs');
const targetDir = path.join(parentDir, id);
const targetDir2 = path.join(parentDir, id2);
await pfs.copy(sourceDir, targetDir);
assert.ok(fs.existsSync(targetDir));
assert.ok(fs.existsSync(path.join(targetDir, 'index.html')));
assert.ok(fs.existsSync(path.join(targetDir, 'site.css')));
assert.ok(fs.existsSync(path.join(targetDir, 'examples')));
assert.ok(fs.statSync(path.join(targetDir, 'examples')).isDirectory());
assert.ok(fs.existsSync(path.join(targetDir, 'examples', 'small.jxs')));
await pfs.move(targetDir, targetDir2);
assert.ok(!fs.existsSync(targetDir));
assert.ok(fs.existsSync(targetDir2));
assert.ok(fs.existsSync(path.join(targetDir2, 'index.html')));
assert.ok(fs.existsSync(path.join(targetDir2, 'site.css')));
assert.ok(fs.existsSync(path.join(targetDir2, 'examples')));
assert.ok(fs.statSync(path.join(targetDir2, 'examples')).isDirectory());
assert.ok(fs.existsSync(path.join(targetDir2, 'examples', 'small.jxs')));
await pfs.move(path.join(targetDir2, 'index.html'), path.join(targetDir2, 'index_moved.html'));
assert.ok(!fs.existsSync(path.join(targetDir2, 'index.html')));
assert.ok(fs.existsSync(path.join(targetDir2, 'index_moved.html')));
await pfs.rimraf(parentDir, pfs.RimRafMode.MOVE);
assert.ok(!fs.existsSync(parentDir));
});
test('mkdirp', async () => {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'pfs', id);
await pfs.mkdirp(newDir, 493);
assert.ok(fs.existsSync(newDir));
return pfs.rimraf(parentDir, pfs.RimRafMode.MOVE);
});
test('mkdirp cancellation', async () => {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'pfs', id);
const source = new CancellationTokenSource();
const mkdirpPromise = pfs.mkdirp(newDir, 493, source.token);
source.cancel();
await mkdirpPromise;
assert.ok(!fs.existsSync(newDir));
return pfs.rimraf(parentDir, pfs.RimRafMode.MOVE);
});
test('readDirsInDir', async () => {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'pfs', id);
await pfs.mkdirp(newDir, 493);
fs.mkdirSync(path.join(newDir, 'somefolder1'));
fs.mkdirSync(path.join(newDir, 'somefolder2'));
fs.mkdirSync(path.join(newDir, 'somefolder3'));
fs.writeFileSync(path.join(newDir, 'somefile.txt'), 'Contents');
fs.writeFileSync(path.join(newDir, 'someOtherFile.txt'), 'Contents');
const result = await pfs.readDirsInDir(newDir);
assert.equal(result.length, 3);
assert.ok(result.indexOf('somefolder1') !== -1);
assert.ok(result.indexOf('somefolder2') !== -1);
assert.ok(result.indexOf('somefolder3') !== -1);
await pfs.rimraf(newDir);
});
test('stat link', async () => {
if (isWindows) {
return Promise.resolve(); // Symlinks are not the same on win, and we can not create them programitically without admin privileges
}
const id1 = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id1);
const directory = path.join(parentDir, 'pfs', id1);
const id2 = uuid.generateUuid();
const symbolicLink = path.join(parentDir, 'pfs', id2);
await pfs.mkdirp(directory, 493);
fs.symlinkSync(directory, symbolicLink);
let statAndIsLink = await pfs.statLink(directory);
assert.ok(!statAndIsLink!.isSymbolicLink);
statAndIsLink = await pfs.statLink(symbolicLink);
assert.ok(statAndIsLink!.isSymbolicLink);
pfs.rimrafSync(directory);
});
test('readdir', async () => {
if (canNormalize && typeof process.versions['electron'] !== 'undefined' /* needs electron */) {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'pfs', id, 'öäü');
await pfs.mkdirp(newDir, 493);
assert.ok(fs.existsSync(newDir));
const children = await pfs.readdir(path.join(parentDir, 'pfs', id));
assert.equal(children.some(n => n === 'öäü'), true); // Mac always converts to NFD, so
await pfs.rimraf(parentDir);
}
});
test('writeFile (string)', async () => {
const smallData = 'Hello World';
const bigData = (new Array(100 * 1024)).join('Large String\n');
return testWriteFileAndFlush(smallData, smallData, bigData, bigData);
});
test('writeFile (Buffer)', async () => {
const smallData = 'Hello World';
const bigData = (new Array(100 * 1024)).join('Large String\n');
return testWriteFileAndFlush(Buffer.from(smallData), smallData, Buffer.from(bigData), bigData);
});
test('writeFile (UInt8Array)', async () => {
const smallData = 'Hello World';
const bigData = (new Array(100 * 1024)).join('Large String\n');
return testWriteFileAndFlush(VSBuffer.fromString(smallData).buffer, smallData, VSBuffer.fromString(bigData).buffer, bigData);
});
test('writeFile (stream)', async () => {
const smallData = 'Hello World';
const bigData = (new Array(100 * 1024)).join('Large String\n');
return testWriteFileAndFlush(toReadable(smallData), smallData, toReadable(bigData), bigData);
});
async function testWriteFileAndFlush(
smallData: string | Buffer | NodeJS.ReadableStream | Uint8Array,
smallDataValue: string,
bigData: string | Buffer | NodeJS.ReadableStream | Uint8Array,
bigDataValue: string
): Promise<void> {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'pfs', id);
const testFile = path.join(newDir, 'flushed.txt');
await pfs.mkdirp(newDir, 493);
assert.ok(fs.existsSync(newDir));
await pfs.writeFile(testFile, smallData);
assert.equal(fs.readFileSync(testFile), smallDataValue);
await pfs.writeFile(testFile, bigData);
assert.equal(fs.readFileSync(testFile), bigDataValue);
await pfs.rimraf(parentDir);
}
test('writeFile (file stream)', async () => {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const sourceFile = getPathFromAmdModule(require, './fixtures/index.html');
const newDir = path.join(parentDir, 'pfs', id);
const testFile = path.join(newDir, 'flushed.txt');
await pfs.mkdirp(newDir, 493);
assert.ok(fs.existsSync(newDir));
await pfs.writeFile(testFile, fs.createReadStream(sourceFile));
assert.equal(fs.readFileSync(testFile).toString(), fs.readFileSync(sourceFile).toString());
await pfs.rimraf(parentDir);
});
test('writeFile (string, error handling)', async () => {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'pfs', id);
const testFile = path.join(newDir, 'flushed.txt');
await pfs.mkdirp(newDir, 493);
assert.ok(fs.existsSync(newDir));
fs.mkdirSync(testFile); // this will trigger an error because testFile is now a directory!
let expectedError: Error | undefined;
try {
await pfs.writeFile(testFile, 'Hello World');
} catch (error) {
expectedError = error;
}
assert.ok(expectedError);
await pfs.rimraf(parentDir);
});
test('writeFile (stream, error handling EISDIR)', async () => {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'pfs', id);
const testFile = path.join(newDir, 'flushed.txt');
await pfs.mkdirp(newDir, 493);
assert.ok(fs.existsSync(newDir));
fs.mkdirSync(testFile); // this will trigger an error because testFile is now a directory!
const readable = toReadable('Hello World');
let expectedError: Error | undefined;
try {
await pfs.writeFile(testFile, readable);
} catch (error) {
expectedError = error;
}
if (!expectedError || (<any>expectedError).code !== 'EISDIR') {
return Promise.reject(new Error('Expected EISDIR error for writing to folder but got: ' + (expectedError ? (<any>expectedError).code : 'no error')));
}
// verify that the stream is still consumable (for https://github.com/Microsoft/vscode/issues/42542)
assert.equal(readable.read(), 'Hello World');
await pfs.rimraf(parentDir);
});
test('writeFile (stream, error handling READERROR)', async () => {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'pfs', id);
const testFile = path.join(newDir, 'flushed.txt');
await pfs.mkdirp(newDir, 493);
assert.ok(fs.existsSync(newDir));
let expectedError: Error | undefined;
try {
await pfs.writeFile(testFile, toReadable('Hello World', true /* throw error */));
} catch (error) {
expectedError = error;
}
if (!expectedError || expectedError.message !== readError) {
return Promise.reject(new Error('Expected error for writing to folder'));
}
await pfs.rimraf(parentDir);
});
test('writeFile (stream, error handling EACCES)', async () => {
if (isLinux) {
return Promise.resolve(); // somehow this test fails on Linux in our TFS builds
}
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'pfs', id);
const testFile = path.join(newDir, 'flushed.txt');
await pfs.mkdirp(newDir, 493);
assert.ok(fs.existsSync(newDir));
fs.writeFileSync(testFile, '');
fs.chmodSync(testFile, 33060); // make readonly
let expectedError: Error | undefined;
try {
await pfs.writeFile(testFile, toReadable('Hello World'));
} catch (error) {
expectedError = error;
}
if (!expectedError || !((<any>expectedError).code !== 'EACCES' || (<any>expectedError).code !== 'EPERM')) {
return Promise.reject(new Error('Expected EACCES/EPERM error for writing to folder but got: ' + (expectedError ? (<any>expectedError).code : 'no error')));
}
await pfs.rimraf(parentDir);
});
test('writeFile (file stream, error handling)', async () => {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const sourceFile = getPathFromAmdModule(require, './fixtures/index.html');
const newDir = path.join(parentDir, 'pfs', id);
const testFile = path.join(newDir, 'flushed.txt');
await pfs.mkdirp(newDir, 493);
assert.ok(fs.existsSync(newDir));
fs.mkdirSync(testFile); // this will trigger an error because testFile is now a directory!
let expectedError: Error | undefined;
try {
await pfs.writeFile(testFile, fs.createReadStream(sourceFile));
} catch (error) {
expectedError = error;
}
if (!expectedError) {
return Promise.reject(new Error('Expected error for writing to folder'));
}
await pfs.rimraf(parentDir);
});
test('writeFileSync', async () => {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'pfs', id);
const testFile = path.join(newDir, 'flushed.txt');
await pfs.mkdirp(newDir, 493);
assert.ok(fs.existsSync(newDir));
pfs.writeFileSync(testFile, 'Hello World');
assert.equal(fs.readFileSync(testFile), 'Hello World');
const largeString = (new Array(100 * 1024)).join('Large String\n');
pfs.writeFileSync(testFile, largeString);
assert.equal(fs.readFileSync(testFile), largeString);
await pfs.rimraf(parentDir);
});
});

View File

@@ -8,7 +8,7 @@ import { generateUuid } from 'vs/base/common/uuid';
import { join } from 'vs/base/common/path';
import { tmpdir } from 'os';
import { equal, ok } from 'assert';
import { mkdirp, del, writeFile, exists, unlink } from 'vs/base/node/pfs';
import { mkdirp, writeFile, exists, unlink, rimraf, RimRafMode } from 'vs/base/node/pfs';
import { timeout } from 'vs/base/common/async';
import { Event, Emitter } from 'vs/base/common/event';
import { isWindows } from 'vs/base/common/platform';
@@ -92,7 +92,7 @@ suite('Storage Library', () => {
equal(deletePromiseResolved, true);
await storage.close();
await del(storageDir, tmpdir());
await rimraf(storageDir, RimRafMode.MOVE);
});
test('external changes', async () => {
@@ -148,7 +148,7 @@ suite('Storage Library', () => {
equal(changes.size, 0);
await storage.close();
await del(storageDir, tmpdir());
await rimraf(storageDir, RimRafMode.MOVE);
});
test('close flushes data', async () => {
@@ -202,7 +202,7 @@ suite('Storage Library', () => {
ok(!storage.get('bar'));
await storage.close();
await del(storageDir, tmpdir());
await rimraf(storageDir, RimRafMode.MOVE);
});
test('conflicting updates', async () => {
@@ -244,7 +244,7 @@ suite('Storage Library', () => {
ok(setAndDeletePromiseResolved);
await storage.close();
await del(storageDir, tmpdir());
await rimraf(storageDir, RimRafMode.MOVE);
});
test('corrupt DB recovers', async () => {
@@ -274,7 +274,7 @@ suite('Storage Library', () => {
equal(storage.get('foo'), 'bar');
await storage.close();
await del(storageDir, tmpdir());
await rimraf(storageDir, RimRafMode.MOVE);
});
});
@@ -372,7 +372,7 @@ suite('SQLite Storage Library', () => {
await testDBBasics(join(storageDir, 'storage.db'));
await del(storageDir, tmpdir());
await rimraf(storageDir, RimRafMode.MOVE);
});
test('basics (open multiple times)', async () => {
@@ -383,7 +383,7 @@ suite('SQLite Storage Library', () => {
await testDBBasics(join(storageDir, 'storage.db'));
await testDBBasics(join(storageDir, 'storage.db'));
await del(storageDir, tmpdir());
await rimraf(storageDir, RimRafMode.MOVE);
});
test('basics (corrupt DB falls back to empty DB)', async () => {
@@ -401,7 +401,7 @@ suite('SQLite Storage Library', () => {
ok(expectedError);
await del(storageDir, tmpdir());
await rimraf(storageDir, RimRafMode.MOVE);
});
test('basics (corrupt DB restores from previous backup)', async () => {
@@ -439,7 +439,7 @@ suite('SQLite Storage Library', () => {
equal(recoveryCalled, false);
await del(storageDir, tmpdir());
await rimraf(storageDir, RimRafMode.MOVE);
});
test('basics (corrupt DB falls back to empty DB if backup is corrupt)', async () => {
@@ -468,7 +468,7 @@ suite('SQLite Storage Library', () => {
await testDBBasics(storagePath);
await del(storageDir, tmpdir());
await rimraf(storageDir, RimRafMode.MOVE);
});
test('basics (DB that becomes corrupt during runtime stores all state from cache on close)', async () => {
@@ -536,7 +536,7 @@ suite('SQLite Storage Library', () => {
equal(recoveryCalled, false);
await del(storageDir, tmpdir());
await rimraf(storageDir, RimRafMode.MOVE);
});
test('real world example', async function () {
@@ -627,7 +627,7 @@ suite('SQLite Storage Library', () => {
await storage.close();
await del(storageDir, tmpdir());
await rimraf(storageDir, RimRafMode.MOVE);
});
test('very large item value', async function () {
@@ -682,7 +682,7 @@ suite('SQLite Storage Library', () => {
await storage.close();
await del(storageDir, tmpdir());
await rimraf(storageDir, RimRafMode.MOVE);
});
test('multiple concurrent writes execute in sequence', async () => {
@@ -739,7 +739,7 @@ suite('SQLite Storage Library', () => {
await storage.close();
await del(storageDir, tmpdir());
await rimraf(storageDir, RimRafMode.MOVE);
});
test('lots of INSERT & DELETE (below inline max)', async () => {
@@ -771,7 +771,7 @@ suite('SQLite Storage Library', () => {
await storage.close();
await del(storageDir, tmpdir());
await rimraf(storageDir, RimRafMode.MOVE);
});
test('lots of INSERT & DELETE (above inline max)', async () => {
@@ -803,6 +803,6 @@ suite('SQLite Storage Library', () => {
await storage.close();
await del(storageDir, tmpdir());
await rimraf(storageDir, RimRafMode.MOVE);
});
});

View File

@@ -6,7 +6,7 @@
import { generateUuid } from 'vs/base/common/uuid';
import { join } from 'vs/base/common/path';
import { tmpdir } from 'os';
import { mkdirp, del } from 'vs/base/node/pfs';
import { mkdirp, rimraf, RimRafMode } from 'vs/base/node/pfs';
export interface ITestFileResult {
testFile: string;
@@ -22,7 +22,7 @@ export function testFile(folder: string, file: string): Promise<ITestFileResult>
return mkdirp(newDir, 493).then(() => {
return {
testFile,
cleanUp: () => del(parentDir, tmpdir())
} as ITestFileResult;
cleanUp: () => rimraf(parentDir, RimRafMode.MOVE)
};
});
}