diff --git a/.travis.yml b/.travis.yml index 50623a195..d50f8000b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,9 +6,9 @@ install: script: - npm run build # Testing & Coverage -- npm test -after_success: - npm run coverage +after_success: +- codecov deploy: provider: npm email: 'lorenz.junglas@student.kit.edu' diff --git a/README.md b/README.md index 79f200643..852dae602 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,16 @@ The real power of this transpiler is usage together with good declarations for t - [Dota 2 Modding](https://github.com/ModDota/API/tree/master/declarations/server) - [Defold Game Engine Scripting](https://github.com/dasannikov/DefoldTypeScript/blob/master/defold.d.ts) +## Building & Tests + +`npm run build` to build the project. + +`npm run test` to run tests. + +`npm run test-threaded` runs test in parallel, faster but less detailed output. + +`npm run coverage` or `npm run coverage-html` to generate a coverage report. + ## Sublime Text integration This compiler works great in combination with the [Sublime Text Typescript plugin](https://github.com/Microsoft/TypeScript-Sublime-Plugin) (available through the package manager as `TypeScript`). diff --git a/package-lock.json b/package-lock.json index e9ab642d4..0ef4fd2c8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,29 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@types/events": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz", + "integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==", + "dev": true + }, + "@types/glob": { + "version": "5.0.35", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-5.0.35.tgz", + "integrity": "sha512-wc+VveszMLyMWFvXLkloixT4n0harUIVZjnpzztaZ0nKLuul7Z32iMt2fUFGAaZ4y1XWjFRMtCI5ewvyh4aIeg==", + "dev": true, + "requires": { + "@types/events": "*", + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, "@types/node": { "version": "9.6.23", "resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.23.tgz", @@ -176,6 +199,12 @@ "supports-color": "^2.0.0" } }, + "circular-json": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.5.tgz", + "integrity": "sha512-13YaR6kiz0kBNmIVM87Io8Hp7bWOo4r61vkEANy8iH9R9bc6avud/1FT0SBpqR1RpIQADOh/Q+yHZDA1iL6ysA==", + "dev": true + }, "cliui": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", @@ -341,6 +370,12 @@ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", "dev": true }, + "eventemitter3": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz", + "integrity": "sha1-teEHm1n7XhuidxwKmTvgYKWMmbo=", + "dev": true + }, "events-to-array": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/events-to-array/-/events-to-array-1.1.2.tgz", @@ -715,6 +750,12 @@ } } }, + "native-promise-only": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/native-promise-only/-/native-promise-only-0.8.1.tgz", + "integrity": "sha1-IKMYwwy0X3H+et+/eyHJnBRy7xE=", + "dev": true + }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", @@ -4022,6 +4063,16 @@ "readable-stream": "^2" } }, + "threads": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/threads/-/threads-0.12.0.tgz", + "integrity": "sha512-4B7hd61lDsVW1Z/+FAVX7D9QbiQYUbtGMHVkkwWT/nKPKas8u4FEc+Rg8E8h2erhNTQGNqNJ0TsholmhpKNPRg==", + "dev": true, + "requires": { + "eventemitter3": "^2.0.2", + "native-promise-only": "^0.8.1" + } + }, "through2": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", diff --git a/package.json b/package.json index 8ef30e5ce..afb00e256 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,9 @@ "scripts": { "build": "tsc -p tsconfig.json", "test": "tslint -p . && ts-node ./test/runner.ts", - "coverage": "nyc npm test && nyc report --reporter=text-lcov > coverage.lcov && codecov", + "test-threaded": "tslint -p . && ts-node ./test/threaded_runner.ts", + "coverage-threaded": "nyc npm run test-threaded && nyc report --reporter=text-lcov > coverage.lcov", + "coverage": "nyc npm test && nyc report --reporter=text-lcov > coverage.lcov", "coverage-html": "nyc npm test && nyc report --reporter=html", "release-patch": "npm version patch", "release-minor": "npm version minor", @@ -40,13 +42,17 @@ "yargs": "^11.1.0" }, "devDependencies": { + "@types/glob": "^5.0.35", "@types/node": "^9.6.23", "@types/yargs": "^11.0.0", "alsatian": "^2.2.1", + "circular-json": "^0.5.5", "codecov": "3.0.2", "deep-equal": "^1.0.1", "fengari": "^0.1.2", + "glob": "^7.1.2", "nyc": "^11.9.0", + "threads": "^0.12.0", "ts-node": "^7.0.0", "tslint": "^5.10.0", "tslint-override": "^0.1.2" diff --git a/test/test_thread.ts b/test/test_thread.ts new file mode 100644 index 000000000..784ac3323 --- /dev/null +++ b/test/test_thread.ts @@ -0,0 +1,31 @@ +import { MatchError, TestRunner, TestSet, TestOutcome } from "alsatian"; +import * as JSON from "circular-json"; + +module.exports = function(input, done) { + const testSet = TestSet.create(); + testSet.addTestsFromFiles(input.files); + const testRunner = new TestRunner(); + + testRunner.onTestComplete((result) => { + if (result.outcome === TestOutcome.Fail) { + if (result.error instanceof MatchError) { + console.log(`Test ${result.testFixture.description}, ${result.test.key}(${JSON.stringify(result.testCase.caseArguments)}) Failed!`) + console.log(" ---\n" + + ' message: "' + + result.error.message + + '"\n' + + " severity: fail\n" + + " data:\n" + + " got: " + + result.error.actual + + "\n" + + " expect: " + + result.error.expected + + "\n"); + } + } + }) + + testRunner.run(testSet) + .then((results) => done(results, input)) +}; diff --git a/test/threaded_runner.ts b/test/threaded_runner.ts new file mode 100644 index 000000000..08a304e1a --- /dev/null +++ b/test/threaded_runner.ts @@ -0,0 +1,56 @@ +import {MatchError} from "alsatian"; +import * as glob from "glob"; +import * as os from "os"; +import * as path from "path"; +import {config, Pool} from "threads"; + +config.set({ + basepath: { + node: __dirname, + } +}); + +let cpuCount = os.cpus().length + 1; +if ("TRAVIS" in process.env && "CI" in process.env) { + // fixed thread count for CI + cpuCount = 8; +} +const testFiles: string[] = glob.sync("./test/**/*.spec.ts"); +const pool = new Pool(cpuCount); +let jobCounter = 0; + +const fileArrToString = (fileArr: string[]) => + fileArr.map(val => path.basename(val).replace(".spec.ts", "")).join(", "); + +console.log( + `Running tests: ${fileArrToString(testFiles)} with ${cpuCount} threads`); + +const filesPerThread = Math.floor(testFiles.length / cpuCount); +const threadsWithMoreWork = testFiles.length % cpuCount; + +for (let i = 1; i <= cpuCount; i++) { + let files: string[] = []; + if (i <= threadsWithMoreWork) { + files = testFiles.splice(0, filesPerThread + 1); + } else { + files = testFiles.splice(0, filesPerThread); + } + console.log(`Running tests: ${fileArrToString(files)} in thread ${i}`); + + pool.run("./test_thread") + .send({files: files}) + .on("done", + (results, input) => { + jobCounter++; + console.log(`Tests ${fileArrToString(files)} ${jobCounter}/${ + cpuCount} done.`); + }) + .on("error", error => { + console.log("Exception in test:", files, error); + }); +} + +pool.on("finished", () => { + console.log("Everything done, shutting down the thread pool."); + pool.killAll(); +}); diff --git a/test/unit/string.spec.ts b/test/unit/string.spec.ts index ccbdae962..8398fce1a 100644 --- a/test/unit/string.spec.ts +++ b/test/unit/string.spec.ts @@ -18,7 +18,7 @@ export class StringTests { @TestCase([65, 66]) @TestCase([65, 66, 67]) @Test("String.fromCharCode") - public stringFromCharcode(inp: number[], expected: string) { + public stringFromCharcode(inp: number[]) { // Transpile const lua = util.transpileString( `return String.fromCharCode(${inp.toString()})`