diff --git a/_infrastructure/tests/runner.js b/_infrastructure/tests/runner.js
index e3eca657f..c6ab61c8a 100644
--- a/_infrastructure/tests/runner.js
+++ b/_infrastructure/tests/runner.js
@@ -52,7 +52,6 @@ var DT;
this.ext = path.extname(this.filePathWithName);
this.file = path.basename(this.filePathWithName, this.ext);
this.dir = path.dirname(this.filePathWithName);
- this.formatName = path.join(this.dir, this.file + this.ext);
this.fullPath = path.join(this.baseDir, this.dir, this.file + this.ext);
// lock it (shallow) (needs `use strict` in each file to work)
// Object.freeze(this);
@@ -202,6 +201,7 @@ var DT;
var fs = require('fs');
var path = require('path');
+ var glob = require('glob');
var Lazy = require('lazy.js');
var Promise = require('bluebird');
@@ -211,7 +211,8 @@ var DT;
// Track all files in the repo: map full path to File objects
/////////////////////////////////
var FileIndex = (function () {
- function FileIndex(options) {
+ function FileIndex(runner, options) {
+ this.runner = runner;
this.options = options;
}
FileIndex.prototype.hasFile = function (target) {
@@ -225,14 +226,76 @@ var DT;
return null;
};
- FileIndex.prototype.parseFiles = function (files) {
+ FileIndex.prototype.setFile = function (file) {
+ if (file.fullPath in this.fileMap) {
+ throw new Error('cannot overwrite file');
+ }
+ this.fileMap[file.fullPath] = file;
+ };
+
+ FileIndex.prototype.readIndex = function () {
+ var _this = this;
+ this.fileMap = Object.create(null);
+
+ return Promise.promisify(glob).call(glob, '**/*.ts', {
+ cwd: this.runner.dtPath
+ }).then(function (filesNames) {
+ _this.files = Lazy(filesNames).filter(function (fileName) {
+ return _this.runner.checkAcceptFile(fileName);
+ }).map(function (fileName) {
+ var file = new DT.File(_this.runner.dtPath, fileName);
+ _this.fileMap[file.fullPath] = file;
+ return file;
+ }).toArray();
+ });
+ };
+
+ FileIndex.prototype.collectDiff = function (changes) {
+ var _this = this;
+ return new Promise(function (resolve) {
+ // filter changes and bake map for easy lookup
+ _this.changed = Object.create(null);
+ _this.removed = Object.create(null);
+
+ Lazy(changes).filter(function (full) {
+ return _this.runner.checkAcceptFile(full);
+ }).uniq().each(function (local) {
+ var full = path.resolve(_this.runner.dtPath, local);
+ var file = _this.getFile(full);
+ if (!file) {
+ // TODO figure out what to do here
+ // what does it mean? deleted?ss
+ file = new DT.File(_this.runner.dtPath, local);
+ _this.setFile(file);
+ _this.removed[full] = file;
+ // console.log('not in index? %', file.fullPath);
+ } else {
+ _this.changed[full] = file;
+ }
+ });
+
+ // console.log('changed:\n' + Object.keys(this.changed).join('\n'));
+ // console.log('removed:\n' + Object.keys(this.removed).join('\n'));
+ resolve();
+ });
+ };
+
+ FileIndex.prototype.parseFiles = function () {
+ var _this = this;
+ return this.loadReferences(this.files).then(function () {
+ return _this.getMissingReferences();
+ });
+ };
+
+ FileIndex.prototype.getMissingReferences = function () {
var _this = this;
return Promise.attempt(function () {
- _this.fileMap = Object.create(null);
- files.forEach(function (file) {
- _this.fileMap[file.fullPath] = file;
+ _this.missing = Object.create(null);
+ Lazy(_this.removed).keys().each(function (removed) {
+ if (removed in _this.refMap) {
+ _this.missing[removed] = _this.refMap[removed];
+ }
});
- return _this.loadReferences(files);
});
};
@@ -262,6 +325,19 @@ var DT;
}
};
next();
+ }).then(function () {
+ // bake reverse reference map (referenced to referrers)
+ _this.refMap = Object.create(null);
+
+ Lazy(files).each(function (file) {
+ Lazy(file.references).each(function (ref) {
+ if (ref.fullPath in _this.refMap) {
+ _this.refMap[ref.fullPath].push(file);
+ } else {
+ _this.refMap[ref.fullPath] = [file];
+ }
+ });
+ });
});
};
@@ -287,11 +363,43 @@ var DT;
return file;
});
};
+
+ FileIndex.prototype.collectTargets = function () {
+ var _this = this;
+ return new Promise(function (resolve) {
+ // map out files linked to changes
+ // - queue holds files touched by a change
+ // - pre-fill with actually changed files
+ // - loop queue, if current not seen:
+ // - add to result
+ // - from refMap queue all files referring to current
+ var result = Object.create(null);
+ var queue = Lazy(_this.changed).values().toArray();
+
+ while (queue.length > 0) {
+ var next = queue.shift();
+ var fp = next.fullPath;
+ if (result[fp]) {
+ continue;
+ }
+ result[fp] = next;
+ if (fp in _this.refMap) {
+ var arr = _this.refMap[fp];
+ for (var i = 0, ii = arr.length; i < ii; i++) {
+ // just add it and skip expensive checks
+ queue.push(arr[i]);
+ }
+ }
+ }
+ resolve(Lazy(result).values().toArray());
+ });
+ };
return FileIndex;
})();
DT.FileIndex = FileIndex;
})(DT || (DT = {}));
///
+///
var DT;
(function (DT) {
'use strict';
@@ -302,11 +410,10 @@ var DT;
var Promise = require('bluebird');
var GitChanges = (function () {
- function GitChanges(baseDir) {
- this.baseDir = baseDir;
+ function GitChanges(runner) {
+ this.runner = runner;
this.options = {};
- this.paths = [];
- var dir = path.join(baseDir, '.git');
+ var dir = path.join(this.runner.dtPath, '.git');
if (!fs.existsSync(dir)) {
throw new Error('cannot locate git-dir: ' + dir);
}
@@ -315,12 +422,11 @@ var DT;
this.git = new Git(this.options);
this.git.exec = Promise.promisify(this.git.exec);
}
- GitChanges.prototype.getChanges = function () {
- var _this = this;
+ GitChanges.prototype.readChanges = function () {
var opts = {};
var args = ['--name-only HEAD~1'];
return this.git.exec('diff', opts, args).then(function (msg) {
- _this.paths = msg.replace(/^\s+/, '').replace(/\s+$/, '').split(/\r?\n/g);
+ return msg.replace(/^\s+/, '').replace(/\s+$/, '').split(/\r?\n/g);
});
};
return GitChanges;
@@ -393,7 +499,7 @@ var DT;
};
Print.prototype.printErrorsForFile = function (testResult) {
- this.out('----------------- For file:' + testResult.targetFile.formatName);
+ this.out('----------------- For file:' + testResult.targetFile.filePathWithName);
this.printBreak().out(testResult.stderr).printBreak();
};
@@ -471,6 +577,101 @@ var DT;
});
}
};
+
+ Print.prototype.printTestComplete = function (testResult, index) {
+ var reporter = testResult.hostedBy.testReporter;
+ if (testResult.success) {
+ reporter.printPositiveCharacter(index, testResult);
+ } else {
+ reporter.printNegativeCharacter(index, testResult);
+ }
+ };
+
+ Print.prototype.printSuiteComplete = function (suite) {
+ this.printBreak();
+
+ this.printDiv();
+ this.printElapsedTime(suite.timer.asString, suite.timer.time);
+ this.printSuccessCount(suite.okTests.length, suite.testResults.length);
+ this.printFailedCount(suite.ngTests.length, suite.testResults.length);
+ };
+
+ Print.prototype.printTests = function (adding) {
+ var _this = this;
+ this.printDiv();
+ this.printSubHeader('Testing');
+ this.printDiv();
+
+ Object.keys(adding).sort().map(function (src) {
+ _this.printLine(adding[src].filePathWithName);
+ return adding[src];
+ });
+ };
+
+ Print.prototype.printFiles = function (files) {
+ var _this = this;
+ this.printDiv();
+ this.printSubHeader('Files:');
+ this.printDiv();
+
+ files.forEach(function (file) {
+ _this.printLine(file.filePathWithName);
+ file.references.forEach(function (file) {
+ _this.printElement(file.filePathWithName);
+ });
+ });
+ };
+
+ Print.prototype.printMissing = function (index, refMap) {
+ var _this = this;
+ this.printDiv();
+ this.printSubHeader('Missing references');
+ this.printDiv();
+
+ Object.keys(refMap).sort().forEach(function (src) {
+ var ref = index.getFile(src);
+ _this.printLine('\33[31m\33[1m' + ref.filePathWithName + '\33[0m');
+ refMap[src].forEach(function (file) {
+ _this.printElement(file.filePathWithName);
+ });
+ });
+ };
+
+ Print.prototype.printAllChanges = function (paths) {
+ var _this = this;
+ this.printSubHeader('All changes');
+ this.printDiv();
+
+ paths.sort().forEach(function (line) {
+ _this.printLine(line);
+ });
+ };
+
+ Print.prototype.printRelChanges = function (changeMap) {
+ var _this = this;
+ this.printDiv();
+ this.printSubHeader('Relevant changes');
+ this.printDiv();
+
+ Object.keys(changeMap).sort().forEach(function (src) {
+ _this.printLine(changeMap[src].filePathWithName);
+ });
+ };
+
+ Print.prototype.printRefMap = function (index, refMap) {
+ var _this = this;
+ this.printDiv();
+ this.printSubHeader('Referring');
+ this.printDiv();
+
+ Object.keys(refMap).sort().forEach(function (src) {
+ var ref = index.getFile(src);
+ _this.printLine(ref.filePathWithName);
+ refMap[src].forEach(function (file) {
+ _this.printLine(' - ' + file.filePathWithName);
+ });
+ });
+ };
return Print;
})();
DT.Print = Print;
@@ -607,7 +808,7 @@ var DT;
}
SyntaxChecking.prototype.filterTargetFiles = function (files) {
return Promise.cast(files.filter(function (file) {
- return endDts.test(file.formatName);
+ return endDts.test(file.filePathWithName);
}));
};
return SyntaxChecking;
@@ -634,7 +835,7 @@ var DT;
}
TestEval.prototype.filterTargetFiles = function (files) {
return Promise.cast(files.filter(function (file) {
- return endTestDts.test(file.formatName);
+ return endTestDts.test(file.filePathWithName);
}));
};
return TestEval;
@@ -664,7 +865,7 @@ var DT;
this.testReporter = {
printPositiveCharacter: function (index, testResult) {
- _this.print.clearCurrentLine().printTypingsWithoutTestName(testResult.targetFile.formatName);
+ _this.print.clearCurrentLine().printTypingsWithoutTestName(testResult.targetFile.filePathWithName);
},
printNegativeCharacter: function (index, testResult) {
}
@@ -680,7 +881,7 @@ var DT;
FindNotRequiredTscparams.prototype.runTest = function (targetFile) {
var _this = this;
- this.print.clearCurrentLine().out(targetFile.formatName);
+ this.print.clearCurrentLine().out(targetFile.filePathWithName);
return new DT.Test(this, targetFile, {
tscVersion: this.options.tscVersion,
@@ -729,7 +930,6 @@ var DT;
var fs = require('fs');
var path = require('path');
- var glob = require('glob');
var assert = require('assert');
var tsExp = /\.ts$/;
@@ -792,8 +992,9 @@ var DT;
this.suites = [];
this.options.findNotRequiredTscparams = !!this.options.findNotRequiredTscparams;
- this.index = new DT.FileIndex(this.options);
- this.changes = new DT.GitChanges(this.dtPath);
+ this.index = new DT.FileIndex(this, this.options);
+ this.changes = new DT.GitChanges(this);
+
this.print = new DT.Print(this.options.tscVersion);
}
TestRunner.prototype.addSuite = function (suite) {
@@ -813,102 +1014,37 @@ var DT;
this.timer = new DT.Timer();
this.timer.start();
+ this.print.printChangeHeader();
+
// only includes .d.ts or -tests.ts or -test.ts or .ts
- return Promise.promisify(glob).call(glob, '**/*.ts', {
- cwd: dtPath
- }).then(function (filesNames) {
- _this.files = Lazy(filesNames).filter(function (fileName) {
- return _this.checkAcceptFile(fileName);
- }).map(function (fileName) {
- return new DT.File(dtPath, fileName);
- }).toArray();
-
- _this.print.printChangeHeader();
-
- return _this.changes.getChanges().then(function () {
- _this.printAllChanges(_this.changes.paths);
- });
+ return this.index.readIndex().then(function () {
+ return _this.changes.readChanges();
+ }).then(function (changes) {
+ _this.print.printAllChanges(changes);
+ return _this.index.collectDiff(changes);
}).then(function () {
- return _this.index.parseFiles(_this.files).then(function () {
- // this.printFiles(this.files);
- });
+ return _this.index.parseFiles();
}).then(function () {
- return _this.collectTargets(_this.files, _this.changes.paths);
- }).then(function (files) {
- return _this.runTests(files);
- }).then(function () {
- return !_this.suites.some(function (suite) {
- return suite.ngTests.length !== 0;
- });
- });
- };
+ // this.print.printRefMap(this.index, this.index.refMap);
+ if (Lazy(_this.index.missing).some(function (arr) {
+ return arr.length > 0;
+ })) {
+ _this.print.printMissing(_this.index, _this.index.missing);
+ _this.print.printBoldDiv();
- TestRunner.prototype.collectTargets = function (files, changes) {
- var _this = this;
- return new Promise(function (resolve) {
- // filter changes and bake map for easy lookup
- var changeMap = Object.create(null);
-
- Lazy(changes).filter(function (full) {
- return _this.checkAcceptFile(full);
- }).map(function (local) {
- return path.resolve(_this.dtPath, local);
- }).each(function (full) {
- var file = _this.index.getFile(full);
- if (!file) {
- // TODO figure out what to do here
- // what does it mean? deleted?
- console.log('not in index: ' + full);
- return;
- }
- changeMap[full] = file;
- });
-
- _this.printRelChanges(changeMap);
-
- // bake reverse reference map (referenced to referrers)
- var refMap = Object.create(null);
-
- Lazy(files).each(function (file) {
- Lazy(file.references).each(function (ref) {
- if (ref.fullPath in refMap) {
- refMap[ref.fullPath].push(file);
- } else {
- refMap[ref.fullPath] = [file];
- }
- });
- });
-
- // this.printRefMap(refMap);
- // map out files linked to changes
- // - queue holds files touched by a change
- // - pre-fill with actually changed files
- // - loop queue, if current not seen:
- // - add to result
- // - from refMap queue all files referring to current
- var adding = Object.create(null);
- var queue = Lazy(changeMap).values().toArray();
-
- while (queue.length > 0) {
- var next = queue.shift();
- var fp = next.fullPath;
- if (adding[fp]) {
- continue;
- }
- adding[fp] = next;
- if (fp in refMap) {
- var arr = refMap[fp];
- for (var i = 0, ii = arr.length; i < ii; i++) {
- // just add it and skip expensive checks
- queue.push(arr[i]);
- }
- }
+ // bail
+ return Promise.delay(500).return(false);
}
- _this.printTests(adding);
-
- var result = Lazy(adding).values().toArray();
- resolve(result);
+ // this.print.printFiles(this.files);
+ return _this.index.collectTargets().then(function (files) {
+ // this.print.printTests(files);
+ return _this.runTests(files);
+ }).then(function () {
+ return !_this.suites.some(function (suite) {
+ return suite.ngTests.length !== 0;
+ });
+ });
});
};
@@ -944,10 +1080,10 @@ var DT;
return suite.filterTargetFiles(files).then(function (targetFiles) {
return suite.start(targetFiles, function (testResult, index) {
- _this.printTestComplete(testResult, index);
+ _this.print.printTestComplete(testResult, index);
});
}).then(function (suite) {
- _this.printSuiteComplete(suite);
+ _this.print.printSuiteComplete(suite);
return count++;
});
}, 0);
@@ -957,85 +1093,6 @@ var DT;
});
};
- TestRunner.prototype.printTests = function (adding) {
- var _this = this;
- this.print.printDiv();
- this.print.printSubHeader('Testing');
- this.print.printDiv();
-
- Object.keys(adding).sort().map(function (src) {
- _this.print.printLine(adding[src].formatName);
- return adding[src];
- });
- };
- TestRunner.prototype.printFiles = function (files) {
- var _this = this;
- this.print.printDiv();
- this.print.printSubHeader('Files:');
- this.print.printDiv();
-
- files.forEach(function (file) {
- _this.print.printLine(file.filePathWithName);
- file.references.forEach(function (file) {
- _this.print.printElement(file.filePathWithName);
- });
- });
- };
-
- TestRunner.prototype.printAllChanges = function (paths) {
- var _this = this;
- this.print.printSubHeader('All changes');
- this.print.printDiv();
-
- paths.sort().forEach(function (line) {
- _this.print.printLine(line);
- });
- };
-
- TestRunner.prototype.printRelChanges = function (changeMap) {
- var _this = this;
- this.print.printDiv();
- this.print.printSubHeader('Relevant changes');
- this.print.printDiv();
-
- Object.keys(changeMap).sort().forEach(function (src) {
- _this.print.printLine(changeMap[src].formatName);
- });
- };
-
- TestRunner.prototype.printRefMap = function (refMap) {
- var _this = this;
- this.print.printDiv();
- this.print.printSubHeader('Referring');
- this.print.printDiv();
-
- Object.keys(refMap).sort().forEach(function (src) {
- var ref = _this.index.getFile(src);
- _this.print.printLine(ref.formatName);
- refMap[src].forEach(function (file) {
- _this.print.printLine(' - ' + file.formatName);
- });
- });
- };
-
- TestRunner.prototype.printTestComplete = function (testResult, index) {
- var reporter = testResult.hostedBy.testReporter;
- if (testResult.success) {
- reporter.printPositiveCharacter(index, testResult);
- } else {
- reporter.printNegativeCharacter(index, testResult);
- }
- };
-
- TestRunner.prototype.printSuiteComplete = function (suite) {
- this.print.printBreak();
-
- this.print.printDiv();
- this.print.printElapsedTime(suite.timer.asString, suite.timer.time);
- this.print.printSuccessCount(suite.okTests.length, suite.testResults.length);
- this.print.printFailedCount(suite.ngTests.length, suite.testResults.length);
- };
-
TestRunner.prototype.finaliseTests = function (files) {
var _this = this;
var testEval = Lazy(this.suites).filter(function (suite) {
diff --git a/_infrastructure/tests/runner.ts b/_infrastructure/tests/runner.ts
index 8dfcc7b4c..126b824b2 100644
--- a/_infrastructure/tests/runner.ts
+++ b/_infrastructure/tests/runner.ts
@@ -27,7 +27,6 @@ module DT {
var fs = require('fs');
var path = require('path');
- var glob = require('glob');
var assert = require('assert');
var tsExp = /\.ts$/;
@@ -79,31 +78,23 @@ module DT {
findNotRequiredTscparams?:boolean;
}
- export interface FileDict {
- [fullPath:string]: File;
- }
-
- export interface FileArrDict {
- [fullPath:string]: File[];
- }
-
/////////////////////////////////
// The main class to kick things off
/////////////////////////////////
export class TestRunner {
- private files: File[];
private timer: Timer;
private suites: ITestSuite[] = [];
- private index: FileIndex;
- private changes: GitChanges;
- private print: Print;
+ public changes: GitChanges;
+ public index: FileIndex;
+ public print: Print;
constructor(public dtPath: string, public options: ITestRunnerOptions = {tscVersion: DT.DEFAULT_TSC_VERSION}) {
this.options.findNotRequiredTscparams = !!this.options.findNotRequiredTscparams;
- this.index = new FileIndex(this.options);
- this.changes = new GitChanges(this.dtPath);
+ this.index = new FileIndex(this, this.options);
+ this.changes = new GitChanges(this);
+
this.print = new Print(this.options.tscVersion);
}
@@ -111,7 +102,7 @@ module DT {
this.suites.push(suite);
}
- private checkAcceptFile(fileName: string): boolean {
+ public checkAcceptFile(fileName: string): boolean {
var ok = tsExp.test(fileName);
ok = ok && fileName.indexOf('_infrastructure') < 0;
ok = ok && fileName.indexOf('node_modules/') < 0;
@@ -123,104 +114,35 @@ module DT {
this.timer = new Timer();
this.timer.start();
+ this.print.printChangeHeader();
+
// only includes .d.ts or -tests.ts or -test.ts or .ts
- return Promise.promisify(glob).call(glob, '**/*.ts', {
- cwd: dtPath
- }).then((filesNames: string[]) => {
- this.files = Lazy(filesNames).filter((fileName) => {
- return this.checkAcceptFile(fileName);
- }).map((fileName: string) => {
- return new File(dtPath, fileName);
- }).toArray();
-
- this.print.printChangeHeader();
-
- return this.changes.getChanges().then(() => {
- this.printAllChanges(this.changes.paths);
- });
+ return this.index.readIndex().then(() => {
+ return this.changes.readChanges();
+ }).then((changes: string[]) => {
+ this.print.printAllChanges(changes);
+ return this.index.collectDiff(changes);
}).then(() => {
- return this.index.parseFiles(this.files).then(() => {
- // this.printFiles(this.files);
- });
+ return this.index.parseFiles();
}).then(() => {
- return this.collectTargets(this.files, this.changes.paths);
- }).then((files) => {
- return this.runTests(files);
- }).then(() => {
- return !this.suites.some((suite) => {
- return suite.ngTests.length !== 0
- });
- });
- }
+ // this.print.printRefMap(this.index, this.index.refMap);
- private collectTargets(files: File[], changes: string[]): Promise {
- return new Promise((resolve) => {
+ if (Lazy(this.index.missing).some((arr: any[]) => arr.length > 0)) {
+ this.print.printMissing(this.index, this.index.missing);
+ this.print.printBoldDiv();
+ // bail
+ return Promise.delay(500).return(false);
+ }
+ // this.print.printFiles(this.files);
+ return this.index.collectTargets().then((files) => {
+ // this.print.printTests(files);
- // filter changes and bake map for easy lookup
- var changeMap: FileDict = Object.create(null);
-
- Lazy(changes).filter((full) => {
- return this.checkAcceptFile(full);
- }).map((local) => {
- return path.resolve(this.dtPath, local);
- }).each((full) => {
- var file = this.index.getFile(full);
- if (!file) {
- // TODO figure out what to do here
- // what does it mean? deleted?
- console.log('not in index: ' + full);
- return;
- }
- changeMap[full] = file;
- });
-
- this.printRelChanges(changeMap);
-
- // bake reverse reference map (referenced to referrers)
- var refMap: FileArrDict = Object.create(null);
-
- Lazy(files).each((file) => {
- Lazy(file.references).each((ref) => {
- if (ref.fullPath in refMap) {
- refMap[ref.fullPath].push(file);
- }
- else {
- refMap[ref.fullPath] = [file];
- }
+ return this.runTests(files);
+ }).then(() => {
+ return !this.suites.some((suite) => {
+ return suite.ngTests.length !== 0
});
});
-
- // this.printRefMap(refMap);
-
- // map out files linked to changes
- // - queue holds files touched by a change
- // - pre-fill with actually changed files
- // - loop queue, if current not seen:
- // - add to result
- // - from refMap queue all files referring to current
- var adding: FileDict = Object.create(null);
- var queue = Lazy(changeMap).values().toArray();
-
- while (queue.length > 0) {
- var next = queue.shift();
- var fp = next.fullPath;
- if (adding[fp]) {
- continue;
- }
- adding[fp] = next;
- if (fp in refMap) {
- var arr = refMap[fp];
- for (var i = 0, ii = arr.length; i < ii; i++) {
- // just add it and skip expensive checks
- queue.push(arr[i]);
- }
- }
- }
-
- this.printTests(adding);
-
- var result: File[] = Lazy(adding).values().toArray();
- resolve(result);
});
}
@@ -255,10 +177,10 @@ module DT {
return suite.filterTargetFiles(files).then((targetFiles) => {
return suite.start(targetFiles, (testResult, index) => {
- this.printTestComplete(testResult, index);
+ this.print.printTestComplete(testResult, index);
});
}).then((suite) => {
- this.printSuiteComplete(suite);
+ this.print.printSuiteComplete(suite);
return count++;
});
}, 0);
@@ -268,81 +190,6 @@ module DT {
});
}
- private printTests(adding: FileDict): void {
- this.print.printDiv();
- this.print.printSubHeader('Testing');
- this.print.printDiv();
-
- Object.keys(adding).sort().map((src) => {
- this.print.printLine(adding[src].formatName);
- return adding[src];
- });
- }
- private printFiles(files: File[]): void {
- this.print.printDiv();
- this.print.printSubHeader('Files:');
- this.print.printDiv();
-
- files.forEach((file) => {
- this.print.printLine(file.filePathWithName);
- file.references.forEach((file) => {
- this.print.printElement(file.filePathWithName);
- });
- });
- }
-
- private printAllChanges(paths: string[]): void {
- this.print.printSubHeader('All changes');
- this.print.printDiv();
-
- paths.sort().forEach((line) => {
- this.print.printLine(line);
- });
- }
-
- private printRelChanges(changeMap: FileDict): void {
- this.print.printDiv();
- this.print.printSubHeader('Relevant changes');
- this.print.printDiv();
-
- Object.keys(changeMap).sort().forEach((src) => {
- this.print.printLine(changeMap[src].formatName);
- });
- }
-
- private printRefMap(refMap: FileArrDict): void {
- this.print.printDiv();
- this.print.printSubHeader('Referring');
- this.print.printDiv();
-
- Object.keys(refMap).sort().forEach((src) => {
- var ref = this.index.getFile(src);
- this.print.printLine(ref.formatName);
- refMap[src].forEach((file) => {
- this.print.printLine(' - ' + file.formatName);
- });
- });
- }
-
- private printTestComplete(testResult: TestResult, index: number): void {
- var reporter = testResult.hostedBy.testReporter;
- if (testResult.success) {
- reporter.printPositiveCharacter(index, testResult);
- }
- else {
- reporter.printNegativeCharacter(index, testResult);
- }
- }
-
- private printSuiteComplete(suite: ITestSuite): void {
- this.print.printBreak();
-
- this.print.printDiv();
- this.print.printElapsedTime(suite.timer.asString, suite.timer.time);
- this.print.printSuccessCount(suite.okTests.length, suite.testResults.length);
- this.print.printFailedCount(suite.ngTests.length, suite.testResults.length);
- }
-
private finaliseTests(files: File[]): void {
var testEval: TestEval = Lazy(this.suites).filter((suite) => {
return suite instanceof TestEval;
diff --git a/_infrastructure/tests/src/changes.ts b/_infrastructure/tests/src/changes.ts
index f3ec26208..a56c4029e 100644
--- a/_infrastructure/tests/src/changes.ts
+++ b/_infrastructure/tests/src/changes.ts
@@ -1,4 +1,5 @@
///
+///
module DT {
'use strict';
@@ -12,10 +13,9 @@ module DT {
git;
options = {};
- paths: string[] = [];
- constructor(public baseDir: string) {
- var dir = path.join(baseDir, '.git');
+ constructor(private runner: TestRunner) {
+ var dir = path.join(this.runner.dtPath, '.git');
if (!fs.existsSync(dir)) {
throw new Error('cannot locate git-dir: ' + dir);
}
@@ -25,11 +25,11 @@ module DT {
this.git.exec = Promise.promisify(this.git.exec);
}
- getChanges(): Promise {
+ public readChanges(): Promise {
var opts = {};
var args = ['--name-only HEAD~1'];
return this.git.exec('diff', opts, args).then((msg: string) => {
- this.paths = msg.replace(/^\s+/, '').replace(/\s+$/, '').split(/\r?\n/g);
+ return msg.replace(/^\s+/, '').replace(/\s+$/, '').split(/\r?\n/g);
});
}
}
diff --git a/_infrastructure/tests/src/file.ts b/_infrastructure/tests/src/file.ts
index 389936b49..2c69f8f88 100644
--- a/_infrastructure/tests/src/file.ts
+++ b/_infrastructure/tests/src/file.ts
@@ -5,6 +5,14 @@ module DT {
var path = require('path');
+ export interface FileDict {
+ [fullPath:string]: File;
+ }
+
+ export interface FileArrDict {
+ [fullPath:string]: File[];
+ }
+
/////////////////////////////////
// Given a document root + ts file pattern this class returns:
// all the TS files OR just tests OR just definition files
@@ -15,7 +23,6 @@ module DT {
dir: string;
file: string;
ext: string;
- formatName: string;
fullPath: string;
references: File[] = [];
@@ -26,14 +33,13 @@ module DT {
this.ext = path.extname(this.filePathWithName);
this.file = path.basename(this.filePathWithName, this.ext);
this.dir = path.dirname(this.filePathWithName);
- this.formatName = path.join(this.dir, this.file + this.ext);
this.fullPath = path.join(this.baseDir, this.dir, this.file + this.ext);
// lock it (shallow) (needs `use strict` in each file to work)
// Object.freeze(this);
}
- toString() {
+ toString(): string {
return '[File ' + this.filePathWithName + ']';
}
}
diff --git a/_infrastructure/tests/src/index.ts b/_infrastructure/tests/src/index.ts
index 183c1e64d..7f5878dcb 100644
--- a/_infrastructure/tests/src/index.ts
+++ b/_infrastructure/tests/src/index.ts
@@ -7,7 +7,8 @@ module DT {
var fs = require('fs');
var path = require('path');
- var Lazy = require('lazy.js');
+ var glob = require('glob');
+ var Lazy: LazyJS.LazyStatic = require('lazy.js');
var Promise: typeof Promise = require('bluebird');
var readFile = Promise.promisify(fs.readFile);
@@ -17,31 +18,95 @@ module DT {
/////////////////////////////////
export class FileIndex {
- fileMap: {[fullPath:string]:File};
+ files: File[];
+ fileMap: FileDict;
+ refMap: FileArrDict;
options: ITestRunnerOptions;
+ changed: FileDict;
+ removed: FileDict;
+ missing: FileArrDict;
- constructor(options: ITestRunnerOptions) {
+ constructor(private runner: TestRunner, options: ITestRunnerOptions) {
this.options = options;
}
- hasFile(target: string): boolean {
+ public hasFile(target: string): boolean {
return target in this.fileMap;
}
- getFile(target: string): File {
+ public getFile(target: string): File {
if (target in this.fileMap) {
return this.fileMap[target];
}
return null;
}
- parseFiles(files: File[]): Promise {
- return Promise.attempt(() => {
- this.fileMap = Object.create(null);
- files.forEach((file) => {
+ public setFile(file: File): void {
+ if (file.fullPath in this.fileMap) {
+ throw new Error('cannot overwrite file');
+ }
+ this.fileMap[file.fullPath] = file;
+ }
+
+ public readIndex(): Promise {
+ this.fileMap = Object.create(null);
+
+ return Promise.promisify(glob).call(glob, '**/*.ts', {
+ cwd: this.runner.dtPath
+ }).then((filesNames: string[]) => {
+ this.files = Lazy(filesNames).filter((fileName) => {
+ return this.runner.checkAcceptFile(fileName);
+ }).map((fileName: string) => {
+ var file = new File(this.runner.dtPath, fileName);
this.fileMap[file.fullPath] = file;
+ return file;
+ }).toArray();
+ });
+ }
+
+ public collectDiff(changes: string[]): Promise {
+ return new Promise((resolve) => {
+ // filter changes and bake map for easy lookup
+ this.changed = Object.create(null);
+ this.removed = Object.create(null);
+
+ Lazy(changes).filter((full) => {
+ return this.runner.checkAcceptFile(full);
+ }).uniq().each((local) => {
+ var full = path.resolve(this.runner.dtPath, local);
+ var file = this.getFile(full);
+ if (!file) {
+ // TODO figure out what to do here
+ // what does it mean? deleted?ss
+ file = new File(this.runner.dtPath, local);
+ this.setFile(file);
+ this.removed[full] = file;
+ // console.log('not in index? %', file.fullPath);
+ }
+ else {
+ this.changed[full] = file;
+ }
+ });
+ // console.log('changed:\n' + Object.keys(this.changed).join('\n'));
+ // console.log('removed:\n' + Object.keys(this.removed).join('\n'));
+ resolve();
+ });
+ }
+
+ public parseFiles(): Promise {
+ return this.loadReferences(this.files).then(() => {
+ return this.getMissingReferences();
+ });
+ }
+
+ private getMissingReferences(): Promise {
+ return Promise.attempt(() => {
+ this.missing = Object.create(null);
+ Lazy(this.removed).keys().each((removed) => {
+ if (removed in this.refMap) {
+ this.missing[removed] = this.refMap[removed];
+ }
});
- return this.loadReferences(files);
});
}
@@ -70,6 +135,20 @@ module DT {
}
};
next();
+ }).then(() => {
+ // bake reverse reference map (referenced to referrers)
+ this.refMap = Object.create(null);
+
+ Lazy(files).each((file) => {
+ Lazy(file.references).each((ref) => {
+ if (ref.fullPath in this.refMap) {
+ this.refMap[ref.fullPath].push(file);
+ }
+ else {
+ this.refMap[ref.fullPath] = [file];
+ }
+ });
+ });
});
}
@@ -94,5 +173,36 @@ module DT {
return file;
});
}
+
+ public collectTargets(): Promise {
+ return new Promise((resolve) => {
+ // map out files linked to changes
+ // - queue holds files touched by a change
+ // - pre-fill with actually changed files
+ // - loop queue, if current not seen:
+ // - add to result
+ // - from refMap queue all files referring to current
+
+ var result: FileDict = Object.create(null);
+ var queue = Lazy(this.changed).values().toArray();
+
+ while (queue.length > 0) {
+ var next = queue.shift();
+ var fp = next.fullPath;
+ if (result[fp]) {
+ continue;
+ }
+ result[fp] = next;
+ if (fp in this.refMap) {
+ var arr = this.refMap[fp];
+ for (var i = 0, ii = arr.length; i < ii; i++) {
+ // just add it and skip expensive checks
+ queue.push(arr[i]);
+ }
+ }
+ }
+ resolve(Lazy(result).values().toArray());
+ });
+ }
}
}
diff --git a/_infrastructure/tests/src/printer.ts b/_infrastructure/tests/src/printer.ts
index 613251b82..9be9a79aa 100644
--- a/_infrastructure/tests/src/printer.ts
+++ b/_infrastructure/tests/src/printer.ts
@@ -72,7 +72,7 @@ module DT {
}
public printErrorsForFile(testResult: TestResult) {
- this.out('----------------- For file:' + testResult.targetFile.formatName);
+ this.out('----------------- For file:' + testResult.targetFile.filePathWithName);
this.printBreak().out(testResult.stderr).printBreak();
}
@@ -149,5 +149,95 @@ module DT {
});
}
}
+
+ public printTestComplete(testResult: TestResult, index: number): void {
+ var reporter = testResult.hostedBy.testReporter;
+ if (testResult.success) {
+ reporter.printPositiveCharacter(index, testResult);
+ }
+ else {
+ reporter.printNegativeCharacter(index, testResult);
+ }
+ }
+
+ public printSuiteComplete(suite: ITestSuite): void {
+ this.printBreak();
+
+ this.printDiv();
+ this.printElapsedTime(suite.timer.asString, suite.timer.time);
+ this.printSuccessCount(suite.okTests.length, suite.testResults.length);
+ this.printFailedCount(suite.ngTests.length, suite.testResults.length);
+ }
+
+ public printTests(adding: FileDict): void {
+ this.printDiv();
+ this.printSubHeader('Testing');
+ this.printDiv();
+
+ Object.keys(adding).sort().map((src) => {
+ this.printLine(adding[src].filePathWithName);
+ return adding[src];
+ });
+ }
+
+ public printFiles(files: File[]): void {
+ this.printDiv();
+ this.printSubHeader('Files:');
+ this.printDiv();
+
+ files.forEach((file) => {
+ this.printLine(file.filePathWithName);
+ file.references.forEach((file) => {
+ this.printElement(file.filePathWithName);
+ });
+ });
+ }
+
+ public printMissing(index: FileIndex, refMap: FileArrDict): void {
+ this.printDiv();
+ this.printSubHeader('Missing references');
+ this.printDiv();
+
+ Object.keys(refMap).sort().forEach((src) => {
+ var ref = index.getFile(src);
+ this.printLine('\33[31m\33[1m' + ref.filePathWithName + '\33[0m');
+ refMap[src].forEach((file) => {
+ this.printElement(file.filePathWithName);
+ });
+ });
+ }
+
+ public printAllChanges(paths: string[]): void {
+ this.printSubHeader('All changes');
+ this.printDiv();
+
+ paths.sort().forEach((line) => {
+ this.printLine(line);
+ });
+ }
+
+ public printRelChanges(changeMap: FileDict): void {
+ this.printDiv();
+ this.printSubHeader('Relevant changes');
+ this.printDiv();
+
+ Object.keys(changeMap).sort().forEach((src) => {
+ this.printLine(changeMap[src].filePathWithName);
+ });
+ }
+
+ public printRefMap(index: FileIndex, refMap: FileArrDict): void {
+ this.printDiv();
+ this.printSubHeader('Referring');
+ this.printDiv();
+
+ Object.keys(refMap).sort().forEach((src) => {
+ var ref = index.getFile(src);
+ this.printLine(ref.filePathWithName);
+ refMap[src].forEach((file) => {
+ this.printLine(' - ' + file.filePathWithName);
+ });
+ });
+ }
}
}
diff --git a/_infrastructure/tests/src/suite/syntax.ts b/_infrastructure/tests/src/suite/syntax.ts
index 41808b2a2..2e0d0b71a 100644
--- a/_infrastructure/tests/src/suite/syntax.ts
+++ b/_infrastructure/tests/src/suite/syntax.ts
@@ -19,7 +19,7 @@ module DT {
public filterTargetFiles(files: File[]): Promise {
return Promise.cast(files.filter((file) => {
- return endDts.test(file.formatName);
+ return endDts.test(file.filePathWithName);
}));
}
}
diff --git a/_infrastructure/tests/src/suite/testEval.ts b/_infrastructure/tests/src/suite/testEval.ts
index bc842549f..95044daa7 100644
--- a/_infrastructure/tests/src/suite/testEval.ts
+++ b/_infrastructure/tests/src/suite/testEval.ts
@@ -19,7 +19,7 @@ module DT {
public filterTargetFiles(files: File[]): Promise {
return Promise.cast(files.filter((file) => {
- return endTestDts.test(file.formatName);
+ return endTestDts.test(file.filePathWithName);
}));
}
}
diff --git a/_infrastructure/tests/src/suite/tscParams.ts b/_infrastructure/tests/src/suite/tscParams.ts
index cef23d622..bb064dd81 100644
--- a/_infrastructure/tests/src/suite/tscParams.ts
+++ b/_infrastructure/tests/src/suite/tscParams.ts
@@ -22,7 +22,7 @@ module DT {
printPositiveCharacter: (index: number, testResult: TestResult) => {
this.print
.clearCurrentLine()
- .printTypingsWithoutTestName(testResult.targetFile.formatName);
+ .printTypingsWithoutTestName(testResult.targetFile.filePathWithName);
},
printNegativeCharacter: (index: number, testResult: TestResult) => {
}
@@ -38,7 +38,7 @@ module DT {
}
public runTest(targetFile: File): Promise {
- this.print.clearCurrentLine().out(targetFile.formatName);
+ this.print.clearCurrentLine().out(targetFile.filePathWithName);
return new Test(this, targetFile, {
tscVersion: this.options.tscVersion,
diff --git a/_infrastructure/tests/typings/lazy.js/lazy.js.d.ts b/_infrastructure/tests/typings/lazy.js/lazy.js.d.ts
index b9367b73b..b2909dfce 100644
--- a/_infrastructure/tests/typings/lazy.js/lazy.js.d.ts
+++ b/_infrastructure/tests/typings/lazy.js/lazy.js.d.ts
@@ -6,12 +6,12 @@
declare module LazyJS {
interface LazyStatic {
- (value: string):StringLikeSequence;
(value: T[]):ArrayLikeSequence;
(value: any[]):ArrayLikeSequence;
(value: Object):ObjectLikeSequence;
(value: Object):ObjectLikeSequence;
+ (value: string):StringLikeSequence;
strict():LazyStatic;
@@ -200,7 +200,7 @@ declare module LazyJS {
functions(): Sequence;
get(property: string): ObjectLikeSequence;
invert(): ObjectLikeSequence;
- keys(): StringLikeSequence;
+ keys(): Sequence;
omit(properties: string[]): ObjectLikeSequence;
pairs(): Sequence;
pick(properties: string[]): ObjectLikeSequence;