From 84790f269f89ebd85309f273e2b56a46077d3c16 Mon Sep 17 00:00:00 2001 From: Nico Jansen Date: Tue, 19 Jul 2016 07:37:51 +0200 Subject: [PATCH] fix(StrykerTempFolder): Use local tmp folder (#121) * fix(StrykerTempFolder): Use local tmp folder When running mocha tests, we need to be able to resolve the local node_modules. The way this works in npm is that it searches for a node_modules in de current working directory. If not found, check the dir above. Etc. By creating the tmp-folder's locally, node_,modules will be resolved as expected. * fix(stryker-temp): Clean temp folder * fix(delete-dir): Fix for deleting a dir recrusive --- src/Stryker.ts | 5 ++-- src/utils/StrykerTempFolder.ts | 19 ++++++++++-- src/utils/fileUtils.ts | 53 ++++++++++++++++++++-------------- test/unit/StrykerSpec.ts | 11 ++++++- 4 files changed, 61 insertions(+), 27 deletions(-) diff --git a/src/Stryker.ts b/src/Stryker.ts index 5180ea7097..f1e3b3f763 100644 --- a/src/Stryker.ts +++ b/src/Stryker.ts @@ -17,6 +17,7 @@ import InputFileResolver from './InputFileResolver'; import ConfigReader from './ConfigReader'; import PluginLoader from './PluginLoader'; import {freezeRecursively, isPromise} from './utils/objectUtils'; +import StrykerTempFolder from './utils/StrykerTempFolder'; import * as log4js from 'log4js'; const log = log4js.getLogger('Stryker'); @@ -49,7 +50,7 @@ export default class Stryker { runMutationTest(): Promise { let reporter = new ReporterOrchestrator(this.config).createBroadcastReporter(); let testSelector = new TestSelectorOrchestrator(this.config).determineTestSelector(); - + return new InputFileResolver(this.config.mutate, this.config.files).resolve() .then(inputFiles => { let testRunnerOrchestrator = new TestRunnerOrchestrator(this.config, inputFiles, testSelector, reporter); @@ -83,7 +84,7 @@ export default class Stryker { } else { return mutantResults; } - }); + }).then(mutantResults => StrykerTempFolder.clean().then(() => mutantResults)); } filterOutUnsuccesfulResults(runResults: RunResult[]) { diff --git a/src/utils/StrykerTempFolder.ts b/src/utils/StrykerTempFolder.ts index 886967dfe3..07a97ec9f9 100644 --- a/src/utils/StrykerTempFolder.ts +++ b/src/utils/StrykerTempFolder.ts @@ -2,9 +2,13 @@ import * as os from 'os' import * as fs from 'fs'; import * as path from 'path'; import * as mkdirp from 'mkdirp'; +import * as fileUtils from './fileUtils'; +import * as log4js from 'log4js'; -let baseTempFolder = os.tmpdir() + path.sep + 'stryker'; -let tempFolder = baseTempFolder + path.sep + random(); +const log = log4js.getLogger('fileUtils'); + +let baseTempFolder = path.join(process.cwd(), '.stryker-tmp'); +let tempFolder = path.join(baseTempFolder, random().toString()); ensureFolderExists(baseTempFolder); ensureFolderExists(tempFolder); @@ -86,9 +90,18 @@ function copyFile(fromFilename: string, toFilename: string): Promise { }); } +/** + * Deletes the Stryker-temp folder + */ +function clean() { + log.info(`Cleaning stryker temp folder ${baseTempFolder}`) + return fileUtils.deleteDir(baseTempFolder); +} + export default { createRandomFolder, writeFile, copyFile, - ensureFolderExists + ensureFolderExists, + clean }; diff --git a/src/utils/fileUtils.ts b/src/utils/fileUtils.ts index 9f944cdfc6..b2a281324c 100644 --- a/src/utils/fileUtils.ts +++ b/src/utils/fileUtils.ts @@ -103,30 +103,41 @@ function rmFile(path: string) { }); } -export function deleteDir(dirToDelete: string): Promise { +function rmdir(dirToDelete: string): Promise { return new Promise((resolve, reject) => { - fileOrFolderExists(dirToDelete).then(exists => { - if (exists) { - readdir(dirToDelete).then(files => { - let promisses: Promise[] = []; - files.forEach(file => { - let currentPath = path.join(dirToDelete, file); - promisses.push(stats(currentPath).then(stats => { - if (stats.isDirectory()) { - // recurse - return deleteDir(currentPath); - } else { - // delete file - return rmFile(currentPath); - } - })); - }); - Promise.all(promisses).then(() => resolve()); - }); + fs.rmdir(dirToDelete, error => { + if (error) { + reject(error); } else { resolve(); } - }); + }) + }); +} + +/** + * Deletes a directory recursively + */ +export function deleteDir(dirToDelete: string): Promise { + return fileOrFolderExists(dirToDelete).then(exists => { + if (exists) { + return readdir(dirToDelete).then(files => { + let promisses = files.map(file => { + let currentPath = path.join(dirToDelete, file); + return stats(currentPath).then(stats => { + if (stats.isDirectory()) { + // recursive + return deleteDir(currentPath); + } else { + // delete file + return rmFile(currentPath); + } + }); + }); + // delete dir + return Promise.all(promisses).then(() => rmdir(dirToDelete)); + }); + } }); } @@ -136,7 +147,7 @@ export function cleanFolder(folderName: string) { if (exists) { return deleteDir(folderName) .then(() => mkdirRecursive(folderName)); - }else{ + } else { return mkdirRecursive(folderName); } }); diff --git a/test/unit/StrykerSpec.ts b/test/unit/StrykerSpec.ts index 3e07023cf3..45d19a3af9 100644 --- a/test/unit/StrykerSpec.ts +++ b/test/unit/StrykerSpec.ts @@ -14,6 +14,7 @@ import * as testSelectorOrchestrator from '../../src/TestSelectorOrchestrator'; import * as testRunnerOrchestrator from '../../src/TestRunnerOrchestrator'; import * as reporterOrchestrator from '../../src/ReporterOrchestrator'; import * as pluginLoader from '../../src/PluginLoader'; +import StrykerTempFolder from '../../src/utils/StrykerTempFolder'; import log from '../helpers/log4jsMock'; class FakeConfigWriter implements ConfigWriter { @@ -62,6 +63,7 @@ describe('Stryker', function () { sandbox.stub(reporterOrchestrator, 'default').returns(reporterOrchestratorMock); sandbox.stub(configReader, 'default').returns(configReaderMock); sandbox.stub(pluginLoader, 'default').returns(pluginLoaderMock); + sandbox.stub(StrykerTempFolder, 'clean').returns(Promise.resolve()); }); function actAndShouldResultInARejection() { @@ -187,12 +189,15 @@ describe('Stryker', function () { describe('and running of mutators was successfull while reporter.wrapUp() results in void', () => { beforeEach(() => { runMutationsPromiseResolve(); + return strykerPromise; }); it('should resolve the stryker promise', () => strykerPromise); it('should have logged the amount of tests ran', () => { expect(log.info).to.have.been.calledWith('Initial test run succeeded. Ran %s tests.', 6); }); + + it('should clean the stryker temp folder', () => expect(StrykerTempFolder.clean).to.have.been.called); }); describe('and running of mutators was successfull while reporter.wrapUp() results in a promise', () => { @@ -213,10 +218,14 @@ describe('Stryker', function () { describe('and the reporter has wrapped up', () => { - beforeEach(() => wrapUpDoneFn()); + beforeEach(() => { + wrapUpDoneFn(); + return strykerPromise; + }); it('should resolve the stryker promise', () => strykerPromise); + it('should clean the stryker temp folder', () => expect(StrykerTempFolder.clean).to.have.been.called); }); }); });