From d433643a5f5b73ba47d352977470c01916613297 Mon Sep 17 00:00:00 2001 From: Mate Pek Date: Mon, 22 Oct 2018 11:48:30 +0200 Subject: [PATCH 01/18] cleanup tests --- .travis.yml | 2 +- CHANGELOG.md | 6 +- package.json | 4 +- src/test/C2TestAdapter.test.ts | 890 ++++++++++++++------------------- 4 files changed, 387 insertions(+), 515 deletions(-) diff --git a/.travis.yml b/.travis.yml index f6565979..b5f90aa4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ sudo: false +language: node_js os: - osx @@ -14,7 +15,6 @@ before_install: install: - npm install - npm run compile - #- npm run vscode:prepublish script: - npm test --silent \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 1532ee5e..a7c74856 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,9 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.1.3] + +Bugfix release + ## [1.1.2] -Bugfix release. +Bugfix release ## [1.1.1] diff --git a/package.json b/package.json index a172578f..28939633 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "icon": "icon.png", "author": "Mate Pek", "publisher": "matepek", - "version": "1.1.2", + "version": "1.1.3", "license": "Unlicense", "homepage": "https://github.com/matepek/vscode-catch2-test-adapter", "repository": { @@ -152,4 +152,4 @@ } } } -} +} \ No newline at end of file diff --git a/src/test/C2TestAdapter.test.ts b/src/test/C2TestAdapter.test.ts index dd4099d7..ed5d8b01 100644 --- a/src/test/C2TestAdapter.test.ts +++ b/src/test/C2TestAdapter.test.ts @@ -174,72 +174,97 @@ describe('C2TestAdapter', function() { describe('detect config change', function() { this.slow(150); - const waitForReloadAndAssert = (): Promise => { - const waitForReloadAndAssertInner = (tryCount: number): Promise => { - if (testsEvents.length < 2) - return new Promise(r => setTimeout(r, 10)) - .then(() => {waitForReloadAndAssertInner(tryCount - 1)}); - else { - assert.equal(testsEvents.length, 2); - assert.equal(testsEvents[0].type, 'started'); - assert.equal(testsEvents[1].type, 'finished'); - const suite = (testsEvents[1]).suite; - assert.notEqual(suite, undefined); - assert.equal(suite!.children.length, 0); - return Promise.resolve(); - } - }; - return waitForReloadAndAssertInner(20); - }; + let adapter: C2TestAdapter; - afterEach(() => { + before(() => { + adapter = createAdapterAndSubscribe(); + assert.deepStrictEqual(testsEvents, []); + }) + + after(() => { disposeAdapterAndSubscribers(); return resetConfig(); - }); + }) - it('workerMaxNumber', () => { - createAdapterAndSubscribe(); - assert.deepStrictEqual(testsEvents, []); - return getConfig() - .update('workerMaxNumber', 42) - .then(waitForReloadAndAssert); - }); + describe('expectation to (re)load', function() { + afterEach(() => { + const waitForReloadAndAsser = (tryCount: number): Promise => { + if (testsEvents.length < 2) + return new Promise(r => setTimeout(r, 10)) + .then(() => {waitForReloadAndAsser(tryCount - 1)}); + else { + assert.equal(testsEvents.length, 2); + assert.equal(testsEvents[0].type, 'started'); + assert.equal(testsEvents[1].type, 'finished'); + const suite = (testsEvents[1]).suite; + assert.notEqual(suite, undefined); + assert.equal(suite!.children.length, 0); - it('defaultEnv', () => { - createAdapterAndSubscribe(); - assert.deepStrictEqual(testsEvents, []); - return getConfig() - .update('defaultEnv', {'APPLE': 'apple'}) - .then(waitForReloadAndAssert); - }); + // cleanup + testsEvents.pop(); + testsEvents.pop(); - it('defaultCwd', () => { - createAdapterAndSubscribe(); - assert.deepStrictEqual(testsEvents, []); - return getConfig() - .update('defaultCwd', 'apple/peach') - .then(waitForReloadAndAssert); - }); + return Promise.resolve(); + } + }; + return waitForReloadAndAsser(20); + }) + + it('workerMaxNumber', () => { + return updateConfig('workerMaxNumber', 42); + }) + + it('defaultEnv', () => { + return updateConfig('defaultEnv', {'APPLE': 'apple'}); + }) + + it('defaultCwd', () => { + return updateConfig('defaultCwd', 'apple/peach'); + }) + }) it('enableSourceDecoration', () => { - const adapter = createAdapterAndSubscribe(); - assert.deepStrictEqual(testsEvents, []); - return getConfig().update('enableSourceDecoration', false).then(() => { + return updateConfig('enableSourceDecoration', false).then(() => { assert.ok(!adapter.getIsEnabledSourceDecoration()); }); - }); + }) it('defaultRngSeed', () => { - const adapter = createAdapterAndSubscribe(); - assert.deepStrictEqual(testsEvents, []); - return getConfig().update('defaultRngSeed', 987).then(() => { + return updateConfig('defaultRngSeed', 987).then(() => { assert.equal(adapter.getRngSeed(), 987); }); + }) + }) + + it('load with empty config', async function() { + const adapter = createAdapterAndSubscribe(); + await adapter.load(); + assert.equal(testsEvents.length, 2); + assert.equal(testsEvents[0].type, 'started'); + assert.equal(testsEvents[1].type, 'finished'); + const suite = (testsEvents[1]).suite; + assert.notEqual(suite, undefined); + assert.equal(suite!.children.length, 0); + disposeAdapterAndSubscribers(); + }) + + describe('run example1', function() { + let tests: any; + + before(() => { + for (let suite of example1.outputs) { + for (let scenario of suite[1]) { + spawnStub.withArgs(suite[0], scenario[0]).callsFake(() => { + return new ChildProcessStub(scenario[1]); + }); + } + } + }) + + after(() => { + stubsResetToThrow(); }); - }); - // describe('detect config change' - describe('adapter:', () => { let adapter: C2TestAdapter; beforeEach(() => { @@ -250,331 +275,133 @@ describe('C2TestAdapter', function() { disposeAdapterAndSubscribers(); }); - it('fill with empty config', function() { - return adapter.load().then(() => { - assert.equal(testsEvents.length, 2); - assert.equal(testsEvents[0].type, 'started'); - assert.equal(testsEvents[1].type, 'finished'); - const suite = (testsEvents[1]).suite; - assert.notEqual(suite, undefined); - assert.equal(suite!.children.length, 0); - }); - }); - - describe('example1', function() { - let tests: any; - - before(() => { - for (let suite of example1.outputs) { - for (let scenario of suite[1]) { - spawnStub.withArgs(suite[0], scenario[0]).callsFake(() => { - return new ChildProcessStub(scenario[1]); - }); - } - } - }) - - after(() => { - stubsResetToThrow(); - }); - - beforeEach(() => { - return adapter.load() - .then(() => { - const root = (testsEvents[1]).suite; - assert.notEqual(undefined, root); - return root!; - }) - .then((suite: TestSuiteInfo) => { - const root = suite; - const s1 = - root.createChildSuite('s1', example1.suite1.execPath, {}); - const s1t1 = s1.createChildTest( - 's1t1', 'd', ['tag1'], example1.suite1.execPath, 1); - const s1t2 = s1.createChildTest( - 's1t2', 'd', ['tag1'], example1.suite1.execPath, 2); - const s2 = - root.createChildSuite('s2', example1.suite2.execPath, {}); - const s2t1 = s2.createChildTest( - 's2t1', 'd', ['tag1'], example1.suite2.execPath, 1); - const s2t2 = s2.createChildTest( - 's2t2', 'd', ['[.]'], example1.suite2.execPath, 2); - const s2t3 = s2.createChildTest( - 's2t3', 'd', ['tag1'], example1.suite2.execPath, 3); - - tests = { - root: root, - s1: s1, - s1t1: s1t1, - s1t2: s1t2, - s2: s2, - s2t1: s2t1, - s2t2: s2t2, - s2t3: s2t3 - } - }); - }) - - it('run: 1 test (succ)', function() { - return adapter.run([tests.s1t1.id]).then(() => { - assert.deepStrictEqual(testStatesEvents, [ - {type: 'started', tests: [tests.s1t1.id]}, - {type: 'suite', state: 'running', suite: tests.s1}, - {type: 'test', state: 'running', test: tests.s1t1}, - { - type: 'test', - state: 'passed', - test: tests.s1t1, - decorations: undefined, - message: 'Duration: 0.000112 second(s)\n' - }, - {type: 'suite', state: 'completed', suite: tests.s1}, - {type: 'finished'}, - ]); - }); - }) - - it('run: 1 test (skipped)', function() { - return adapter.run([tests.s2t2.id]).then(() => { - assert.deepStrictEqual(testStatesEvents, [ - {type: 'started', tests: [tests.s2t2.id]}, - {type: 'suite', state: 'running', suite: tests.s2}, - {type: 'test', state: 'running', test: tests.s2t2}, - { - type: 'test', - state: 'passed', - test: tests.s2t2, - decorations: undefined, - message: 'Duration: 0.001294 second(s)\n' - }, - {type: 'suite', state: 'completed', suite: tests.s2}, - {type: 'finished'}, - ]); - }); - }); - // it('run: 1 test (skipped)' - - it('run: 1 test (fails)', function() { - return adapter.run([tests.s2t3.id]).then(() => { - assert.deepStrictEqual(testStatesEvents, [ - {type: 'started', tests: [tests.s2t3.id]}, - {type: 'suite', state: 'running', suite: tests.s2}, - {type: 'test', state: 'running', test: tests.s2t3}, - { - type: 'test', - state: 'failed', - test: tests.s2t3, - decorations: [{line: 20, message: 'Expanded: false'}], - message: - 'Duration: 0.000596 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }, - {type: 'suite', state: 'completed', suite: tests.s2}, - {type: 'finished'}, - ]); - }); - }); - // it('run: 1 test (fails)' - - it('run: s2t3 with chunks', function() { - const withArgs = spawnStub.withArgs( - tests.s2.execPath, example1.suite2.t3.outputs[0][0]); - withArgs.onCall(withArgs.callCount) - .returns(new ChildProcessStub(example1.suite2.t3.outputs[0][1])); - - return adapter.run([tests.s2t3.id]).then(() => { - assert.deepStrictEqual(testStatesEvents, [ - {type: 'started', tests: [tests.s2t3.id]}, - {type: 'suite', state: 'running', suite: tests.s2}, - {type: 'test', state: 'running', test: tests.s2t3}, - { - type: 'test', - state: 'failed', - test: tests.s2t3, - decorations: [{line: 20, message: 'Expanded: false'}], - message: - 'Duration: 0.000596 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }, - {type: 'suite', state: 'completed', suite: tests.s2}, - {type: 'finished'}, - ]); - }); - }); - // it('run: 1 test (fails) with chunks' - - it('run: suite1 (1 succ 1 fails)', function() { - return adapter.run([tests.s1.id]).then(() => { - assert.deepStrictEqual(testStatesEvents, [ - {type: 'started', tests: [tests.s1.id]}, - {type: 'suite', state: 'running', suite: tests.s1}, - {type: 'test', state: 'running', test: tests.s1t1}, - { - type: 'test', - state: 'passed', - test: tests.s1t1, - decorations: undefined, - message: 'Duration: 0.000132 second(s)\n' - }, - {type: 'test', state: 'running', test: tests.s1t2}, - { - type: 'test', - state: 'failed', - test: tests.s1t2, - decorations: [{line: 14, message: 'Expanded: false'}], - message: - 'Duration: 0.000204 second(s)\n>>> s1t2(line: 13) REQUIRE (line: 15) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }, - {type: 'suite', state: 'completed', suite: tests.s1}, - {type: 'finished'}, - ]); - }); - }); - // it('run: suite1 (1 succ 1 fails)' - - it('run: root (at least 2 slots)', function() { - return adapter.run([tests.root.id]).then(() => { - assert.deepStrictEqual( - {type: 'started', tests: [tests.root.id]}, testStatesEvents[0]); - assert.deepStrictEqual( - {type: 'finished'}, - testStatesEvents[testStatesEvents.length - 1]); - - const s1running = {type: 'suite', state: 'running', suite: tests.s1}; - const s1finished = { - type: 'suite', - state: 'completed', - suite: tests.s1 - }; - assert.ok(testStatesEvI(s1running) < testStatesEvI(s1finished)); - - const s2running = {type: 'suite', state: 'running', suite: tests.s2}; - const s2finished = { - type: 'suite', - state: 'completed', - suite: tests.s2 - }; - assert.ok(testStatesEvI(s2running) < testStatesEvI(s2finished)); - - const s1t1running = { - type: 'test', - state: 'running', - test: tests.s1t1 - }; - assert.ok(testStatesEvI(s1running) < testStatesEvI(s1t1running)); + beforeEach(() => { + return adapter.load() + .then(() => { + const root = (testsEvents[1]).suite; + assert.notEqual(undefined, root); + return root!; + }) + .then((suite: TestSuiteInfo) => { + const root = suite; + const s1 = + root.createChildSuite('s1', example1.suite1.execPath, {}); + const s1t1 = s1.createChildTest( + 's1t1', 'd', ['tag1'], example1.suite1.execPath, 1); + const s1t2 = s1.createChildTest( + 's1t2', 'd', ['tag1'], example1.suite1.execPath, 2); + const s2 = + root.createChildSuite('s2', example1.suite2.execPath, {}); + const s2t1 = s2.createChildTest( + 's2t1', 'd', ['tag1'], example1.suite2.execPath, 1); + const s2t2 = s2.createChildTest( + 's2t2', 'd', ['[.]'], example1.suite2.execPath, 2); + const s2t3 = s2.createChildTest( + 's2t3', 'd', ['tag1'], example1.suite2.execPath, 3); + + tests = { + root: root, + s1: s1, + s1t1: s1t1, + s1t2: s1t2, + s2: s2, + s2t1: s2t1, + s2t2: s2t2, + s2t3: s2t3 + } + }); + }) - const s1t1finished = { + it('run: 1 test (succ)', function() { + return adapter.run([tests.s1t1.id]).then(() => { + assert.deepStrictEqual(testStatesEvents, [ + {type: 'started', tests: [tests.s1t1.id]}, + {type: 'suite', state: 'running', suite: tests.s1}, + {type: 'test', state: 'running', test: tests.s1t1}, + { type: 'test', state: 'passed', test: tests.s1t1, decorations: undefined, - message: 'Duration: 0.000132 second(s)\n' - }; - assert.ok(testStatesEvI(s1t1running) < testStatesEvI(s1t1finished)); - assert.ok(testStatesEvI(s1t1finished) < testStatesEvI(s1finished)); - - const s1t2running = { - type: 'test', - state: 'running', - test: tests.s1t2 - }; - assert.ok(testStatesEvI(s1running) < testStatesEvI(s1t2running)); - - const s1t2finished = { - type: 'test', - state: 'failed', - test: tests.s1t2, - decorations: [{line: 14, message: 'Expanded: false'}], - message: - 'Duration: 0.000204 second(s)\n>>> s1t2(line: 13) REQUIRE (line: 15) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }; - assert.ok(testStatesEvI(s1t2running) < testStatesEvI(s1t2finished)); - assert.ok(testStatesEvI(s1t2finished) < testStatesEvI(s1finished)); - - const s2t1running = { - type: 'test', - state: 'running', - test: tests.s2t1 - }; - assert.ok(testStatesEvI(s2running) < testStatesEvI(s2t1running)); + message: 'Duration: 0.000112 second(s)\n' + }, + {type: 'suite', state: 'completed', suite: tests.s1}, + {type: 'finished'}, + ]); + }); + }) - const s2t1finished = { + it('run: 1 test (skipped)', function() { + return adapter.run([tests.s2t2.id]).then(() => { + assert.deepStrictEqual(testStatesEvents, [ + {type: 'started', tests: [tests.s2t2.id]}, + {type: 'suite', state: 'running', suite: tests.s2}, + {type: 'test', state: 'running', test: tests.s2t2}, + { type: 'test', state: 'passed', - test: tests.s2t1, + test: tests.s2t2, decorations: undefined, - message: 'Duration: 0.00037 second(s)\n' - }; - assert.ok(testStatesEvI(s2t1running) < testStatesEvI(s2t1finished)); - assert.ok(testStatesEvI(s2t1finished) < testStatesEvI(s2finished)); - - const s2t2running = { - type: 'test', - state: 'running', - test: tests.s2t2 - }; - assert.ok(testStatesEvI(s2running) < testStatesEvI(s2t2running)); - - const s2t2finished = { - type: 'test', - state: 'skipped', - test: tests.s2t2 - }; - assert.ok(testStatesEvI(s2t2running) < testStatesEvI(s2t2finished)); - assert.ok(testStatesEvI(s2t2finished) < testStatesEvI(s2finished)); - - const s2t3running = { - type: 'test', - state: 'running', - test: tests.s2t3 - }; - assert.ok(testStatesEvI(s2running) < testStatesEvI(s2t3running)); + message: 'Duration: 0.001294 second(s)\n' + }, + {type: 'suite', state: 'completed', suite: tests.s2}, + {type: 'finished'}, + ]); + }); + }); + // it('run: 1 test (skipped)' - const s2t3finished = { + it('run: 1 test (fails)', function() { + return adapter.run([tests.s2t3.id]).then(() => { + assert.deepStrictEqual(testStatesEvents, [ + {type: 'started', tests: [tests.s2t3.id]}, + {type: 'suite', state: 'running', suite: tests.s2}, + {type: 'test', state: 'running', test: tests.s2t3}, + { type: 'test', state: 'failed', test: tests.s2t3, decorations: [{line: 20, message: 'Expanded: false'}], message: - 'Duration: 0.000178 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }; - assert.ok(testStatesEvI(s2t3running) < testStatesEvI(s2t3finished)); - assert.ok(testStatesEvI(s2t3finished) < testStatesEvI(s2finished)); - - assert.equal(testStatesEvents.length, 16, inspect(testStatesEvents)); - }); - }) - - it('run: wrong xml 1', async function() { - const m = example1.suite1.t1.outputs[0][1].match(']+>'); - assert.notEqual(m, undefined); - assert.notEqual(m!.input, undefined); - assert.notEqual(m!.index, undefined); - const part = m!.input!.substr(0, m!.index! + m![0].length); - const withArgs = spawnStub.withArgs( - tests.s1.execPath, example1.suite1.t1.outputs[0][0]); - withArgs.onCall(withArgs.callCount).returns(new ChildProcessStub(part)); + 'Duration: 0.000596 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' + }, + {type: 'suite', state: 'completed', suite: tests.s2}, + {type: 'finished'}, + ]); + }); + }); + // it('run: 1 test (fails)' - await adapter.run([tests.s1t1.id]); + it('run: s2t3 with chunks', function() { + const withArgs = spawnStub.withArgs( + tests.s2.execPath, example1.suite2.t3.outputs[0][0]); + withArgs.onCall(withArgs.callCount) + .returns(new ChildProcessStub(example1.suite2.t3.outputs[0][1])); - const expected = [ - {type: 'started', tests: [tests.s1t1.id]}, - {type: 'suite', state: 'running', suite: tests.s1}, - {type: 'test', state: 'running', test: tests.s1t1}, + return adapter.run([tests.s2t3.id]).then(() => { + assert.deepStrictEqual(testStatesEvents, [ + {type: 'started', tests: [tests.s2t3.id]}, + {type: 'suite', state: 'running', suite: tests.s2}, + {type: 'test', state: 'running', test: tests.s2t3}, { type: 'test', state: 'failed', - test: tests.s1t1, - message: 'Unexpected test error. (Is Catch2 crashed?)\n' + test: tests.s2t3, + decorations: [{line: 20, message: 'Expanded: false'}], + message: + 'Duration: 0.000596 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' }, - {type: 'suite', state: 'completed', suite: tests.s1}, + {type: 'suite', state: 'completed', suite: tests.s2}, {type: 'finished'}, - ]; - assert.deepStrictEqual(testStatesEvents, expected); + ]); + }); + }); + // it('run: 1 test (fails) with chunks' - // this tests the sinon stubs too - await adapter.run([tests.s1t1.id]); + it('run: suite1 (1 succ 1 fails)', function() { + return adapter.run([tests.s1.id]).then(() => { assert.deepStrictEqual(testStatesEvents, [ - ...expected, - {type: 'started', tests: [tests.s1t1.id]}, + {type: 'started', tests: [tests.s1.id]}, {type: 'suite', state: 'running', suite: tests.s1}, {type: 'test', state: 'running', test: tests.s1t1}, { @@ -582,176 +409,217 @@ describe('C2TestAdapter', function() { state: 'passed', test: tests.s1t1, decorations: undefined, - message: 'Duration: 0.000112 second(s)\n' + message: 'Duration: 0.000132 second(s)\n' + }, + {type: 'test', state: 'running', test: tests.s1t2}, + { + type: 'test', + state: 'failed', + test: tests.s1t2, + decorations: [{line: 14, message: 'Expanded: false'}], + message: + 'Duration: 0.000204 second(s)\n>>> s1t2(line: 13) REQUIRE (line: 15) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' }, {type: 'suite', state: 'completed', suite: tests.s1}, {type: 'finished'}, ]); - }) + }); + }); + // it('run: suite1 (1 succ 1 fails)' - it('cancel: empty', function() { - adapter.cancel(); - }) + it('run: root (at least 2 slots)', function() { + return adapter.run([tests.root.id]).then(() => { + assert.deepStrictEqual( + {type: 'started', tests: [tests.root.id]}, testStatesEvents[0]); + assert.deepStrictEqual( + {type: 'finished'}, testStatesEvents[testStatesEvents.length - 1]); - it('cancel', function() { - const suite1Kill = sinon.spy(); - const suite2Kill = sinon.spy(); - { - const spawnEvent = - new ChildProcessStub(example1.suite1.outputs[2][1]); - spawnEvent.kill = suite1Kill; - spawnStub - .withArgs( - tests.s1.execPath, - ['--reporter', 'xml', '--durations', 'yes'], - tests.s1.execOptions) - .returns(spawnEvent); - } - { - const spawnEvent = - new ChildProcessStub(example1.suite2.outputs[2][1]); - spawnEvent.kill = suite2Kill; - spawnStub - .withArgs( - tests.s2.execPath, - ['--reporter', 'xml', '--durations', 'yes'], - tests.s2.execOptions) - .returns(spawnEvent); - } - const run = adapter.run([tests.root.id]); - adapter.cancel(); - run.then(() => { - assert.deepStrictEqual( - testStatesEvents, - [{type: 'started', tests: [tests.root.id]}, {type: 'finished'}]); - assert.equal(suite1Kill.callCount, 1); - assert.equal(suite2Kill.callCount, 1); - }); - }) + const s1running = {type: 'suite', state: 'running', suite: tests.s1}; + const s1finished = {type: 'suite', state: 'completed', suite: tests.s1}; + assert.ok(testStatesEvI(s1running) < testStatesEvI(s1finished)); - it('cancel: after run finished', function() { - const suite1Kill = sinon.spy(); - const suite2Kill = sinon.spy(); - { - const spawnEvent = - new ChildProcessStub(example1.suite1.outputs[2][1]); - spawnEvent.kill = suite1Kill; - spawnStub - .withArgs( - tests.s1.execPath, - ['--reporter', 'xml', '--durations', 'yes'], - tests.s1.execOptions) - .returns(spawnEvent); - } - { - const spawnEvent = - new ChildProcessStub(example1.suite2.outputs[2][1]); - spawnEvent.kill = suite2Kill; - spawnStub - .withArgs( - tests.s2.execPath, - ['--reporter', 'xml', '--durations', 'yes'], - tests.s2.execOptions) - .returns(spawnEvent); - } - const run = adapter.run([tests.root.id]); - run.then(() => { - adapter.cancel(); - assert.equal(suite1Kill.callCount, 0); - assert.equal(suite2Kill.callCount, 0); - }); - }) - }) - }) + const s2running = {type: 'suite', state: 'running', suite: tests.s2}; + const s2finished = {type: 'suite', state: 'completed', suite: tests.s2}; + assert.ok(testStatesEvI(s2running) < testStatesEvI(s2finished)); - describe('executables:', function() { - this.slow(150); - const cwd = path.join(process.cwd(), 'out', 'test'); + const s1t1running = {type: 'test', state: 'running', test: tests.s1t1}; + assert.ok(testStatesEvI(s1running) < testStatesEvI(s1t1running)); - afterEach(() => { - disposeAdapterAndSubscribers(); - stubsResetToThrow(); - return resetConfig(); - }); + const s1t1finished = { + type: 'test', + state: 'passed', + test: tests.s1t1, + decorations: undefined, + message: 'Duration: 0.000132 second(s)\n' + }; + assert.ok(testStatesEvI(s1t1running) < testStatesEvI(s1t1finished)); + assert.ok(testStatesEvI(s1t1finished) < testStatesEvI(s1finished)); - const updateAndVerify = (value: any, expected: any[]) => { - return getConfig() - .update('executables', value) - .then(() => { - const adapter = createAdapterAndSubscribe(); + const s1t2running = {type: 'test', state: 'running', test: tests.s1t2}; + assert.ok(testStatesEvI(s1running) < testStatesEvI(s1t2running)); - const verifyIsCatch2TestExecutable = - sinonSandbox.stub(adapter, 'verifyIsCatch2TestExecutable'); - verifyIsCatch2TestExecutable.returns(Promise.resolve(true)); + const s1t2finished = { + type: 'test', + state: 'failed', + test: tests.s1t2, + decorations: [{line: 14, message: 'Expanded: false'}], + message: + 'Duration: 0.000204 second(s)\n>>> s1t2(line: 13) REQUIRE (line: 15) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' + }; + assert.ok(testStatesEvI(s1t2running) < testStatesEvI(s1t2finished)); + assert.ok(testStatesEvI(s1t2finished) < testStatesEvI(s1finished)); - const loadSuiteMock = sinon.expectation.create('loadSuiteMock'); - loadSuiteMock.exactly(expected.length).returns(Promise.resolve()) - sinonSandbox.replace(adapter, 'loadSuite', loadSuiteMock); + const s2t1running = {type: 'test', state: 'running', test: tests.s2t1}; + assert.ok(testStatesEvI(s2running) < testStatesEvI(s2t1running)); - return adapter.load().then(() => { - return loadSuiteMock; - }); - }) - .then((loadSuiteMock) => { - assert.equal(testsEvents.length, 2); - loadSuiteMock.verify(); - const calls = loadSuiteMock.getCalls(); - const args = calls.map((call: any) => { - const arg = call.args[0]; - const filteredKeys = - Object.keys(arg.env).filter(k => k.startsWith('C2TEST')); - const newEnv: {[prop: string]: string} = {}; - filteredKeys.forEach((k: string) => { - newEnv[k] = arg.env[k]; - }) - arg.env = newEnv; - return arg; - }); - assert.deepEqual(args, expected); - }); - }; - - it('"exe1.exe"', () => { - return updateAndVerify('exe1.exe', [{ - name: 'exe1.exe', - path: path.join(cwd, 'exe1.exe'), - regex: '', - cwd: cwd, - env: {} - }]); - }); + const s2t1finished = { + type: 'test', + state: 'passed', + test: tests.s2t1, + decorations: undefined, + message: 'Duration: 0.00037 second(s)\n' + }; + assert.ok(testStatesEvI(s2t1running) < testStatesEvI(s2t1finished)); + assert.ok(testStatesEvI(s2t1finished) < testStatesEvI(s2finished)); + + const s2t2running = {type: 'test', state: 'running', test: tests.s2t2}; + assert.ok(testStatesEvI(s2running) < testStatesEvI(s2t2running)); + + const s2t2finished = {type: 'test', state: 'skipped', test: tests.s2t2}; + assert.ok(testStatesEvI(s2t2running) < testStatesEvI(s2t2finished)); + assert.ok(testStatesEvI(s2t2finished) < testStatesEvI(s2finished)); + + const s2t3running = {type: 'test', state: 'running', test: tests.s2t3}; + assert.ok(testStatesEvI(s2running) < testStatesEvI(s2t3running)); + + const s2t3finished = { + type: 'test', + state: 'failed', + test: tests.s2t3, + decorations: [{line: 20, message: 'Expanded: false'}], + message: + 'Duration: 0.000178 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' + }; + assert.ok(testStatesEvI(s2t3running) < testStatesEvI(s2t3finished)); + assert.ok(testStatesEvI(s2t3finished) < testStatesEvI(s2finished)); + + assert.equal(testStatesEvents.length, 16, inspect(testStatesEvents)); + }); + }) - it('["exe1.exe", "exe2.exe"]', () => { - return updateAndVerify(['exe1.exe', 'exe2.exe'], [ + it('run: wrong xml 1', async function() { + const m = example1.suite1.t1.outputs[0][1].match(']+>'); + assert.notEqual(m, undefined); + assert.notEqual(m!.input, undefined); + assert.notEqual(m!.index, undefined); + const part = m!.input!.substr(0, m!.index! + m![0].length); + const withArgs = spawnStub.withArgs( + tests.s1.execPath, example1.suite1.t1.outputs[0][0]); + withArgs.onCall(withArgs.callCount).returns(new ChildProcessStub(part)); + + await adapter.run([tests.s1t1.id]); + + const expected = [ + {type: 'started', tests: [tests.s1t1.id]}, + {type: 'suite', state: 'running', suite: tests.s1}, + {type: 'test', state: 'running', test: tests.s1t1}, { - name: 'exe1.exe', - path: path.join(cwd, 'exe1.exe'), - regex: '', - cwd: cwd, - env: {} + type: 'test', + state: 'failed', + test: tests.s1t1, + message: 'Unexpected test error. (Is Catch2 crashed?)\n' }, + {type: 'suite', state: 'completed', suite: tests.s1}, + {type: 'finished'}, + ]; + assert.deepStrictEqual(testStatesEvents, expected); + + // this tests the sinon stubs too + await adapter.run([tests.s1t1.id]); + assert.deepStrictEqual(testStatesEvents, [ + ...expected, + {type: 'started', tests: [tests.s1t1.id]}, + {type: 'suite', state: 'running', suite: tests.s1}, + {type: 'test', state: 'running', test: tests.s1t1}, { - name: 'exe2.exe', - path: path.join(cwd, 'exe2.exe'), - regex: '', - cwd: cwd, - env: {} - } + type: 'test', + state: 'passed', + test: tests.s1t1, + decorations: undefined, + message: 'Duration: 0.000112 second(s)\n' + }, + {type: 'suite', state: 'completed', suite: tests.s1}, + {type: 'finished'}, ]); - }); + }) - it('{path: "path1"}', () => { - return updateAndVerify({path: 'path1'}, [{ - name: '${dirname} : ${name}', - path: path.join(cwd, 'path1'), - regex: '', - cwd: cwd, - env: {} - }]); - }); + it('cancel: empty', function() { + adapter.cancel(); + }) + + it('cancel', function() { + const suite1Kill = sinon.spy(); + const suite2Kill = sinon.spy(); + { + const spawnEvent = new ChildProcessStub(example1.suite1.outputs[2][1]); + spawnEvent.kill = suite1Kill; + spawnStub + .withArgs( + tests.s1.execPath, ['--reporter', 'xml', '--durations', 'yes'], + tests.s1.execOptions) + .returns(spawnEvent); + } + { + const spawnEvent = new ChildProcessStub(example1.suite2.outputs[2][1]); + spawnEvent.kill = suite2Kill; + spawnStub + .withArgs( + tests.s2.execPath, ['--reporter', 'xml', '--durations', 'yes'], + tests.s2.execOptions) + .returns(spawnEvent); + } + const run = adapter.run([tests.root.id]); + adapter.cancel(); + run.then(() => { + assert.deepStrictEqual( + testStatesEvents, + [{type: 'started', tests: [tests.root.id]}, {type: 'finished'}]); + assert.equal(suite1Kill.callCount, 1); + assert.equal(suite2Kill.callCount, 1); + }); + }) + + it('cancel: after run finished', function() { + const suite1Kill = sinon.spy(); + const suite2Kill = sinon.spy(); + { + const spawnEvent = new ChildProcessStub(example1.suite1.outputs[2][1]); + spawnEvent.kill = suite1Kill; + spawnStub + .withArgs( + tests.s1.execPath, ['--reporter', 'xml', '--durations', 'yes'], + tests.s1.execOptions) + .returns(spawnEvent); + } + { + const spawnEvent = new ChildProcessStub(example1.suite2.outputs[2][1]); + spawnEvent.kill = suite2Kill; + spawnStub + .withArgs( + tests.s2.execPath, ['--reporter', 'xml', '--durations', 'yes'], + tests.s2.execOptions) + .returns(spawnEvent); + } + const run = adapter.run([tests.root.id]); + run.then(() => { + adapter.cancel(); + assert.equal(suite1Kill.callCount, 0); + assert.equal(suite2Kill.callCount, 0); + }); + }) }) - describe('load: example1', function() { + describe('load example1', function() { before(() => { for (let suite of example1.outputs) { for (let scenario of suite[1]) { @@ -1242,16 +1110,16 @@ describe('C2TestAdapter', function() { context('executables=[{...}] and env={...}', function() { before(async () => { await updateConfig('executables', [{ - name: '${dirname}: ${name} (${absDirname})', - path: '.', - regex: 'execPath(1|2)', - cwd: '${workspaceFolder}/cwd', - env: { - 'C2LOCALTESTENV': 'c2localtestenv', - 'C2OVERRIDETESTENV': 'c2overridetestenv-l', - } - }]); - await updateConfig('defaultEnv',{ + name: '${dirname}: ${name} (${absDirname})', + path: '.', + regex: 'execPath(1|2)', + cwd: '${workspaceFolder}/cwd', + env: { + 'C2LOCALTESTENV': 'c2localtestenv', + 'C2OVERRIDETESTENV': 'c2overridetestenv-l', + } + }]); + await updateConfig('defaultEnv', { 'C2GLOBALTESTENV': 'c2globaltestenv', 'C2OVERRIDETESTENV': 'c2overridetestenv-g', }); @@ -1397,7 +1265,7 @@ describe('C2TestAdapter', function() { }); await adapter.run([suite1.id]); assert.ok(called1); - + let called2 = false; spawnStub .withArgs( From 71f415224d591ecae256822e9524006495692e5a Mon Sep 17 00:00:00 2001 From: Mate Pek Date: Mon, 22 Oct 2018 22:23:32 +0200 Subject: [PATCH 02/18] refactor tests, resources folder with icon.png --- .gitignore | 1 + package.json | 2 +- icon.png => resources/icon.png | Bin resources/logo.xcf | Bin 0 -> 29543 bytes src/test/C2TestAdapter.test.ts | 645 +++++++++++---------------------- 5 files changed, 214 insertions(+), 434 deletions(-) rename icon.png => resources/icon.png (100%) create mode 100644 resources/logo.xcf diff --git a/.gitignore b/.gitignore index f683c593..aa5d6d6c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.DS_Store node_modules out *.vsix diff --git a/package.json b/package.json index 28939633..ad46f74c 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "vscode-catch2-test-adapter", "displayName": "Catch2 Test Explorer", "description": "Run your Catch2 tests in the Sidebar of Visual Studio Code", - "icon": "icon.png", + "icon": "resources/icon.png", "author": "Mate Pek", "publisher": "matepek", "version": "1.1.3", diff --git a/icon.png b/resources/icon.png similarity index 100% rename from icon.png rename to resources/icon.png diff --git a/resources/logo.xcf b/resources/logo.xcf new file mode 100644 index 0000000000000000000000000000000000000000..fb23a06c7729769b13f100aceb72ac0b112545c1 GIT binary patch literal 29543 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 literal 0 HcmV?d00001 diff --git a/src/test/C2TestAdapter.test.ts b/src/test/C2TestAdapter.test.ts index ed5d8b01..becbdf98 100644 --- a/src/test/C2TestAdapter.test.ts +++ b/src/test/C2TestAdapter.test.ts @@ -248,377 +248,6 @@ describe('C2TestAdapter', function() { disposeAdapterAndSubscribers(); }) - describe('run example1', function() { - let tests: any; - - before(() => { - for (let suite of example1.outputs) { - for (let scenario of suite[1]) { - spawnStub.withArgs(suite[0], scenario[0]).callsFake(() => { - return new ChildProcessStub(scenario[1]); - }); - } - } - }) - - after(() => { - stubsResetToThrow(); - }); - - let adapter: C2TestAdapter; - - beforeEach(() => { - adapter = createAdapterAndSubscribe(); - }); - - afterEach(() => { - disposeAdapterAndSubscribers(); - }); - - beforeEach(() => { - return adapter.load() - .then(() => { - const root = (testsEvents[1]).suite; - assert.notEqual(undefined, root); - return root!; - }) - .then((suite: TestSuiteInfo) => { - const root = suite; - const s1 = - root.createChildSuite('s1', example1.suite1.execPath, {}); - const s1t1 = s1.createChildTest( - 's1t1', 'd', ['tag1'], example1.suite1.execPath, 1); - const s1t2 = s1.createChildTest( - 's1t2', 'd', ['tag1'], example1.suite1.execPath, 2); - const s2 = - root.createChildSuite('s2', example1.suite2.execPath, {}); - const s2t1 = s2.createChildTest( - 's2t1', 'd', ['tag1'], example1.suite2.execPath, 1); - const s2t2 = s2.createChildTest( - 's2t2', 'd', ['[.]'], example1.suite2.execPath, 2); - const s2t3 = s2.createChildTest( - 's2t3', 'd', ['tag1'], example1.suite2.execPath, 3); - - tests = { - root: root, - s1: s1, - s1t1: s1t1, - s1t2: s1t2, - s2: s2, - s2t1: s2t1, - s2t2: s2t2, - s2t3: s2t3 - } - }); - }) - - it('run: 1 test (succ)', function() { - return adapter.run([tests.s1t1.id]).then(() => { - assert.deepStrictEqual(testStatesEvents, [ - {type: 'started', tests: [tests.s1t1.id]}, - {type: 'suite', state: 'running', suite: tests.s1}, - {type: 'test', state: 'running', test: tests.s1t1}, - { - type: 'test', - state: 'passed', - test: tests.s1t1, - decorations: undefined, - message: 'Duration: 0.000112 second(s)\n' - }, - {type: 'suite', state: 'completed', suite: tests.s1}, - {type: 'finished'}, - ]); - }); - }) - - it('run: 1 test (skipped)', function() { - return adapter.run([tests.s2t2.id]).then(() => { - assert.deepStrictEqual(testStatesEvents, [ - {type: 'started', tests: [tests.s2t2.id]}, - {type: 'suite', state: 'running', suite: tests.s2}, - {type: 'test', state: 'running', test: tests.s2t2}, - { - type: 'test', - state: 'passed', - test: tests.s2t2, - decorations: undefined, - message: 'Duration: 0.001294 second(s)\n' - }, - {type: 'suite', state: 'completed', suite: tests.s2}, - {type: 'finished'}, - ]); - }); - }); - // it('run: 1 test (skipped)' - - it('run: 1 test (fails)', function() { - return adapter.run([tests.s2t3.id]).then(() => { - assert.deepStrictEqual(testStatesEvents, [ - {type: 'started', tests: [tests.s2t3.id]}, - {type: 'suite', state: 'running', suite: tests.s2}, - {type: 'test', state: 'running', test: tests.s2t3}, - { - type: 'test', - state: 'failed', - test: tests.s2t3, - decorations: [{line: 20, message: 'Expanded: false'}], - message: - 'Duration: 0.000596 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }, - {type: 'suite', state: 'completed', suite: tests.s2}, - {type: 'finished'}, - ]); - }); - }); - // it('run: 1 test (fails)' - - it('run: s2t3 with chunks', function() { - const withArgs = spawnStub.withArgs( - tests.s2.execPath, example1.suite2.t3.outputs[0][0]); - withArgs.onCall(withArgs.callCount) - .returns(new ChildProcessStub(example1.suite2.t3.outputs[0][1])); - - return adapter.run([tests.s2t3.id]).then(() => { - assert.deepStrictEqual(testStatesEvents, [ - {type: 'started', tests: [tests.s2t3.id]}, - {type: 'suite', state: 'running', suite: tests.s2}, - {type: 'test', state: 'running', test: tests.s2t3}, - { - type: 'test', - state: 'failed', - test: tests.s2t3, - decorations: [{line: 20, message: 'Expanded: false'}], - message: - 'Duration: 0.000596 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }, - {type: 'suite', state: 'completed', suite: tests.s2}, - {type: 'finished'}, - ]); - }); - }); - // it('run: 1 test (fails) with chunks' - - it('run: suite1 (1 succ 1 fails)', function() { - return adapter.run([tests.s1.id]).then(() => { - assert.deepStrictEqual(testStatesEvents, [ - {type: 'started', tests: [tests.s1.id]}, - {type: 'suite', state: 'running', suite: tests.s1}, - {type: 'test', state: 'running', test: tests.s1t1}, - { - type: 'test', - state: 'passed', - test: tests.s1t1, - decorations: undefined, - message: 'Duration: 0.000132 second(s)\n' - }, - {type: 'test', state: 'running', test: tests.s1t2}, - { - type: 'test', - state: 'failed', - test: tests.s1t2, - decorations: [{line: 14, message: 'Expanded: false'}], - message: - 'Duration: 0.000204 second(s)\n>>> s1t2(line: 13) REQUIRE (line: 15) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }, - {type: 'suite', state: 'completed', suite: tests.s1}, - {type: 'finished'}, - ]); - }); - }); - // it('run: suite1 (1 succ 1 fails)' - - it('run: root (at least 2 slots)', function() { - return adapter.run([tests.root.id]).then(() => { - assert.deepStrictEqual( - {type: 'started', tests: [tests.root.id]}, testStatesEvents[0]); - assert.deepStrictEqual( - {type: 'finished'}, testStatesEvents[testStatesEvents.length - 1]); - - const s1running = {type: 'suite', state: 'running', suite: tests.s1}; - const s1finished = {type: 'suite', state: 'completed', suite: tests.s1}; - assert.ok(testStatesEvI(s1running) < testStatesEvI(s1finished)); - - const s2running = {type: 'suite', state: 'running', suite: tests.s2}; - const s2finished = {type: 'suite', state: 'completed', suite: tests.s2}; - assert.ok(testStatesEvI(s2running) < testStatesEvI(s2finished)); - - const s1t1running = {type: 'test', state: 'running', test: tests.s1t1}; - assert.ok(testStatesEvI(s1running) < testStatesEvI(s1t1running)); - - const s1t1finished = { - type: 'test', - state: 'passed', - test: tests.s1t1, - decorations: undefined, - message: 'Duration: 0.000132 second(s)\n' - }; - assert.ok(testStatesEvI(s1t1running) < testStatesEvI(s1t1finished)); - assert.ok(testStatesEvI(s1t1finished) < testStatesEvI(s1finished)); - - const s1t2running = {type: 'test', state: 'running', test: tests.s1t2}; - assert.ok(testStatesEvI(s1running) < testStatesEvI(s1t2running)); - - const s1t2finished = { - type: 'test', - state: 'failed', - test: tests.s1t2, - decorations: [{line: 14, message: 'Expanded: false'}], - message: - 'Duration: 0.000204 second(s)\n>>> s1t2(line: 13) REQUIRE (line: 15) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }; - assert.ok(testStatesEvI(s1t2running) < testStatesEvI(s1t2finished)); - assert.ok(testStatesEvI(s1t2finished) < testStatesEvI(s1finished)); - - const s2t1running = {type: 'test', state: 'running', test: tests.s2t1}; - assert.ok(testStatesEvI(s2running) < testStatesEvI(s2t1running)); - - const s2t1finished = { - type: 'test', - state: 'passed', - test: tests.s2t1, - decorations: undefined, - message: 'Duration: 0.00037 second(s)\n' - }; - assert.ok(testStatesEvI(s2t1running) < testStatesEvI(s2t1finished)); - assert.ok(testStatesEvI(s2t1finished) < testStatesEvI(s2finished)); - - const s2t2running = {type: 'test', state: 'running', test: tests.s2t2}; - assert.ok(testStatesEvI(s2running) < testStatesEvI(s2t2running)); - - const s2t2finished = {type: 'test', state: 'skipped', test: tests.s2t2}; - assert.ok(testStatesEvI(s2t2running) < testStatesEvI(s2t2finished)); - assert.ok(testStatesEvI(s2t2finished) < testStatesEvI(s2finished)); - - const s2t3running = {type: 'test', state: 'running', test: tests.s2t3}; - assert.ok(testStatesEvI(s2running) < testStatesEvI(s2t3running)); - - const s2t3finished = { - type: 'test', - state: 'failed', - test: tests.s2t3, - decorations: [{line: 20, message: 'Expanded: false'}], - message: - 'Duration: 0.000178 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }; - assert.ok(testStatesEvI(s2t3running) < testStatesEvI(s2t3finished)); - assert.ok(testStatesEvI(s2t3finished) < testStatesEvI(s2finished)); - - assert.equal(testStatesEvents.length, 16, inspect(testStatesEvents)); - }); - }) - - it('run: wrong xml 1', async function() { - const m = example1.suite1.t1.outputs[0][1].match(']+>'); - assert.notEqual(m, undefined); - assert.notEqual(m!.input, undefined); - assert.notEqual(m!.index, undefined); - const part = m!.input!.substr(0, m!.index! + m![0].length); - const withArgs = spawnStub.withArgs( - tests.s1.execPath, example1.suite1.t1.outputs[0][0]); - withArgs.onCall(withArgs.callCount).returns(new ChildProcessStub(part)); - - await adapter.run([tests.s1t1.id]); - - const expected = [ - {type: 'started', tests: [tests.s1t1.id]}, - {type: 'suite', state: 'running', suite: tests.s1}, - {type: 'test', state: 'running', test: tests.s1t1}, - { - type: 'test', - state: 'failed', - test: tests.s1t1, - message: 'Unexpected test error. (Is Catch2 crashed?)\n' - }, - {type: 'suite', state: 'completed', suite: tests.s1}, - {type: 'finished'}, - ]; - assert.deepStrictEqual(testStatesEvents, expected); - - // this tests the sinon stubs too - await adapter.run([tests.s1t1.id]); - assert.deepStrictEqual(testStatesEvents, [ - ...expected, - {type: 'started', tests: [tests.s1t1.id]}, - {type: 'suite', state: 'running', suite: tests.s1}, - {type: 'test', state: 'running', test: tests.s1t1}, - { - type: 'test', - state: 'passed', - test: tests.s1t1, - decorations: undefined, - message: 'Duration: 0.000112 second(s)\n' - }, - {type: 'suite', state: 'completed', suite: tests.s1}, - {type: 'finished'}, - ]); - }) - - it('cancel: empty', function() { - adapter.cancel(); - }) - - it('cancel', function() { - const suite1Kill = sinon.spy(); - const suite2Kill = sinon.spy(); - { - const spawnEvent = new ChildProcessStub(example1.suite1.outputs[2][1]); - spawnEvent.kill = suite1Kill; - spawnStub - .withArgs( - tests.s1.execPath, ['--reporter', 'xml', '--durations', 'yes'], - tests.s1.execOptions) - .returns(spawnEvent); - } - { - const spawnEvent = new ChildProcessStub(example1.suite2.outputs[2][1]); - spawnEvent.kill = suite2Kill; - spawnStub - .withArgs( - tests.s2.execPath, ['--reporter', 'xml', '--durations', 'yes'], - tests.s2.execOptions) - .returns(spawnEvent); - } - const run = adapter.run([tests.root.id]); - adapter.cancel(); - run.then(() => { - assert.deepStrictEqual( - testStatesEvents, - [{type: 'started', tests: [tests.root.id]}, {type: 'finished'}]); - assert.equal(suite1Kill.callCount, 1); - assert.equal(suite2Kill.callCount, 1); - }); - }) - - it('cancel: after run finished', function() { - const suite1Kill = sinon.spy(); - const suite2Kill = sinon.spy(); - { - const spawnEvent = new ChildProcessStub(example1.suite1.outputs[2][1]); - spawnEvent.kill = suite1Kill; - spawnStub - .withArgs( - tests.s1.execPath, ['--reporter', 'xml', '--durations', 'yes'], - tests.s1.execOptions) - .returns(spawnEvent); - } - { - const spawnEvent = new ChildProcessStub(example1.suite2.outputs[2][1]); - spawnEvent.kill = suite2Kill; - spawnStub - .withArgs( - tests.s2.execPath, ['--reporter', 'xml', '--durations', 'yes'], - tests.s2.execOptions) - .returns(spawnEvent); - } - const run = adapter.run([tests.root.id]); - run.then(() => { - adapter.cancel(); - assert.equal(suite1Kill.callCount, 0); - assert.equal(suite2Kill.callCount, 0); - }); - }) - }) - describe('load example1', function() { before(() => { for (let suite of example1.outputs) { @@ -935,8 +564,9 @@ describe('C2TestAdapter', function() { assert.equal(root.children[0].type, 'suite'); assert.equal(root.children[1].type, 'suite'); suite1 = root.children[0]; + assert.equal(example1.suite1.outputs.length, 4 + 2 * 2); suite2 = root.children[1]; - if (suite2.label == 'execPath1') { + if (suite2.children.length == 2) { suite1 = root.children[1]; suite2 = root.children[0]; } @@ -959,7 +589,7 @@ describe('C2TestAdapter', function() { s2t2 = suite2.children[1]; assert.equal(suite2.children[2].type, 'test'); s2t3 = suite2.children[2]; - }); + }) it('should run with not existing test id', async function() { await adapter.run(['not existing id']); @@ -968,9 +598,9 @@ describe('C2TestAdapter', function() { {type: 'started', tests: ['not existing id']}, {type: 'finished'}, ]); - }); + }) - it('should run s1t1 with success', async function() { + it('should run s1t1', async function() { await adapter.run([s1t1.id]); const expected = [ {type: 'started', tests: [s1t1.id]}, @@ -990,7 +620,80 @@ describe('C2TestAdapter', function() { await adapter.run([s1t1.id]); assert.deepStrictEqual(testStatesEvents, [...expected, ...expected]); - }); + }) + + it('should run skipped s2t2', async function() { + await adapter.run([s2t2.id]); + const expected = [ + {type: 'started', tests: [s2t2.id]}, + {type: 'suite', state: 'running', suite: suite2}, + {type: 'test', state: 'running', test: s2t2}, + { + type: 'test', + state: 'passed', + test: s2t2, + decorations: undefined, + message: 'Duration: 0.001294 second(s)\n' + }, + {type: 'suite', state: 'completed', suite: suite2}, + {type: 'finished'}, + ]; + assert.deepStrictEqual(testStatesEvents, expected); + + await adapter.run([s2t2.id]); + assert.deepStrictEqual(testStatesEvents, [...expected, ...expected]); + }) + + it('should run failing test s2t3', async function() { + await adapter.run([s2t3.id]); + const expected = [ + {type: 'started', tests: [s2t3.id]}, + {type: 'suite', state: 'running', suite: suite2}, + {type: 'test', state: 'running', test: s2t3}, + { + type: 'test', + state: 'failed', + test: s2t3, + decorations: [{line: 20, message: 'Expanded: false'}], + message: + 'Duration: 0.000596 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' + }, + {type: 'suite', state: 'completed', suite: suite2}, + {type: 'finished'}, + ]; + assert.deepStrictEqual(testStatesEvents, expected); + + await adapter.run([s2t3.id]); + assert.deepStrictEqual(testStatesEvents, [...expected, ...expected]); + }) + + it('should run failing test s2t3 with chunks', async function() { + const withArgs = spawnStub.withArgs( + example1.suite2.execPath, example1.suite2.t3.outputs[0][0]); + withArgs.onCall(withArgs.callCount) + .returns(new ChildProcessStub(example1.suite2.t3.outputs[0][1])); + + await adapter.run([s2t3.id]); + const expected = [ + {type: 'started', tests: [s2t3.id]}, + {type: 'suite', state: 'running', suite: suite2}, + {type: 'test', state: 'running', test: s2t3}, + { + type: 'test', + state: 'failed', + test: s2t3, + decorations: [{line: 20, message: 'Expanded: false'}], + message: + 'Duration: 0.000596 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' + }, + {type: 'suite', state: 'completed', suite: suite2}, + {type: 'finished'}, + ]; + assert.deepStrictEqual(testStatesEvents, expected); + + await adapter.run([s2t3.id]); + assert.deepStrictEqual(testStatesEvents, [...expected, ...expected]); + }) it('should run suite1', async function() { await adapter.run([suite1.id]); @@ -1021,7 +724,7 @@ describe('C2TestAdapter', function() { await adapter.run([suite1.id]); assert.deepStrictEqual(testStatesEvents, [...expected, ...expected]); - }); + }) it('should run all', async function() { await adapter.run([root.id]); @@ -1105,9 +808,139 @@ describe('C2TestAdapter', function() { assert.equal(testStatesEvents.length, 16, inspect(testStatesEvents)); }) + + it('should run with wrong xml', async function() { + const m = example1.suite1.t1.outputs[0][1].match(']+>'); + assert.notEqual(m, undefined); + assert.notEqual(m!.input, undefined); + assert.notEqual(m!.index, undefined); + const part = m!.input!.substr(0, m!.index! + m![0].length); + const withArgs = spawnStub.withArgs( + example1.suite1.execPath, example1.suite1.t1.outputs[0][0]); + withArgs.onCall(withArgs.callCount).returns(new ChildProcessStub(part)); + + await adapter.run([s1t1.id]); + + const expected = [ + {type: 'started', tests: [s1t1.id]}, + {type: 'suite', state: 'running', suite: suite1}, + {type: 'test', state: 'running', test: s1t1}, + { + type: 'test', + state: 'failed', + test: s1t1, + message: 'Unexpected test error. (Is Catch2 crashed?)\n' + }, + {type: 'suite', state: 'completed', suite: suite1}, + {type: 'finished'}, + ]; + assert.deepStrictEqual(testStatesEvents, expected); + + // this tests the sinon stubs too + await adapter.run([s1t1.id]); + assert.deepStrictEqual(testStatesEvents, [ + ...expected, + {type: 'started', tests: [s1t1.id]}, + {type: 'suite', state: 'running', suite: suite1}, + {type: 'test', state: 'running', test: s1t1}, + { + type: 'test', + state: 'passed', + test: s1t1, + decorations: undefined, + message: 'Duration: 0.000112 second(s)\n' + }, + {type: 'suite', state: 'completed', suite: suite1}, + {type: 'finished'}, + ]); + }) + + it('should cancel without error', function() { + adapter.cancel(); + }) + + it('cancel', async function() { + let spyKill1: sinon.SinonSpy; + let spyKill2: sinon.SinonSpy; + { + const spawnEvent = + new ChildProcessStub(example1.suite1.outputs[2][1]); + spyKill1 = sinon.spy(spawnEvent, 'kill'); + const withArgs = spawnStub.withArgs( + example1.suite1.execPath, example1.suite1.outputs[2][0]); + withArgs.onCall(withArgs.callCount).returns(spawnEvent); + } + { + const spawnEvent = + new ChildProcessStub(example1.suite2.outputs[2][1]); + spyKill2 = sinon.spy(spawnEvent, 'kill'); + const withArgs = spawnStub.withArgs( + example1.suite2.execPath, example1.suite2.outputs[2][0]); + withArgs.onCall(withArgs.callCount).returns(spawnEvent); + } + + const run = adapter.run([root.id]); + adapter.cancel(); + await run; + + assert.equal(spyKill1.callCount, 1); + assert.equal(spyKill2.callCount, 1); + + const running = {type: 'started', tests: [root.id]}; + + const s1running = {type: 'suite', state: 'running', suite: suite1}; + const s1finished = {type: 'suite', state: 'completed', suite: suite1}; + assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); + assert.ok(testStatesEvI(s1running) < testStatesEvI(s1finished)); + + const s2running = {type: 'suite', state: 'running', suite: suite2}; + const s2finished = {type: 'suite', state: 'completed', suite: suite2}; + assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); + assert.ok(testStatesEvI(s2running) < testStatesEvI(s2finished)); + + const s2t2running = {type: 'test', state: 'running', test: s2t2}; + assert.ok(testStatesEvI(s2running) < testStatesEvI(s2t2running)); + + const s2t2finished = {type: 'test', state: 'skipped', test: s2t2}; + assert.ok(testStatesEvI(s2t2running) < testStatesEvI(s2t2finished)); + assert.ok(testStatesEvI(s2t2finished) < testStatesEvI(s2finished)); + + const finished = {type: 'finished'}; + assert.ok(testStatesEvI(s1finished) < testStatesEvI(finished)); + assert.ok(testStatesEvI(s2finished) < testStatesEvI(finished)); + + assert.equal(testStatesEvents.length, 8, inspect(testStatesEvents)); + }) + + it('cancel after run finished', function() { + let spyKill1: sinon.SinonSpy; + let spyKill2: sinon.SinonSpy; + { + const spawnEvent = + new ChildProcessStub(example1.suite1.outputs[2][1]); + spyKill1 = sinon.spy(spawnEvent, 'kill'); + const withArgs = spawnStub.withArgs( + example1.suite1.execPath, example1.suite1.outputs[2][0]); + withArgs.onCall(withArgs.callCount).returns(spawnEvent); + } + { + const spawnEvent = + new ChildProcessStub(example1.suite2.outputs[2][1]); + spyKill2 = sinon.spy(spawnEvent, 'kill'); + const withArgs = spawnStub.withArgs( + example1.suite2.execPath, example1.suite2.outputs[2][0]); + withArgs.onCall(withArgs.callCount).returns(spawnEvent); + } + const run = adapter.run([root.id]); + return run.then(() => { + adapter.cancel(); + assert.equal(spyKill1.callCount, 0); + assert.equal(spyKill2.callCount, 0); + }); + }) }) - context('executables=[{...}] and env={...}', function() { + context('executables=[{}] and env={...}', function() { before(async () => { await updateConfig('executables', [{ name: '${dirname}: ${name} (${absDirname})', @@ -1283,58 +1116,4 @@ describe('C2TestAdapter', function() { }); }) }) -}) - -describe.skip('a', function() { - this.timeout(99999); - - before(() => { - debugger; - }); - beforeEach(() => { - debugger; - }); - - after(() => { - debugger; - }); - afterEach(() => { - debugger; - }); - - it('a-it', () => { - debugger; - }); - - describe('b', () => { - before(() => { - debugger; - }); - beforeEach(() => { - debugger; - }); - - after(() => { - debugger; - }); - afterEach(() => { - debugger; - }); - - it('b-it1', () => { - debugger; - }); - - it('b-it2', () => { - debugger; - }); - }); -}); -// fswatcher test aztan atiras vscode workspace watcherre -// bonyolultabb teszteset parsoleasa de az mehet kulon fileba c2testinfo -// mock getExecutables regex meg sima minden test -// ExecutableConfig -// execOptions -// writing xml -// re-load soame object -// deepstrictequal \ No newline at end of file +}) \ No newline at end of file From 4fe3d6512b0a20b6057ec14565e2bc1fc8a52931 Mon Sep 17 00:00:00 2001 From: Mate Pek Date: Mon, 22 Oct 2018 23:58:21 +0200 Subject: [PATCH 03/18] fix tests --- src/test/C2TestAdapter.test.ts | 1008 +++++++++++++++++--------------- src/test/Helpers.ts | 2 + 2 files changed, 554 insertions(+), 456 deletions(-) diff --git a/src/test/C2TestAdapter.test.ts b/src/test/C2TestAdapter.test.ts index becbdf98..c93591ed 100644 --- a/src/test/C2TestAdapter.test.ts +++ b/src/test/C2TestAdapter.test.ts @@ -16,7 +16,6 @@ import {TestEvent, TestLoadFinishedEvent, TestLoadStartedEvent, TestRunFinishedE import {Log} from 'vscode-test-adapter-util'; import {inspect} from 'util'; -import {C2AllTestSuiteInfo} from '../C2AllTestSuiteInfo'; import {C2TestAdapter} from '../C2TestAdapter'; import {example1} from './example1'; import {ChildProcessStub} from './Helpers'; @@ -155,10 +154,15 @@ describe('C2TestAdapter', function() { adapter = undefined; spawnStub = sinonSandbox.stub(child_process, 'spawn'); + spawnStub.named('spawnStub'); fsWatchStub = sinonSandbox.stub(fs, 'watch'); + fsWatchStub.named('fsWatchStub'); fsExistsStub = sinonSandbox.stub(fs, 'exists'); + fsExistsStub.named('fsExistsStub'); c2fsReaddirSyncStub = sinonSandbox.stub(c2fs, 'readdirSync'); + c2fsReaddirSyncStub.named('c2fsReaddirSyncStub'); c2fsStatSyncStub = sinonSandbox.stub(c2fs, 'statSync'); + c2fsStatSyncStub.named('c2fsStatSyncStub'); stubsResetToThrow(); @@ -328,7 +332,15 @@ describe('C2TestAdapter', function() { const uniqueIdC = new Set(); const watchEvents: Map = new Map(); let adapter: TestAdapter; + let root: TestSuiteInfo; + let suite1: TestSuiteInfo|any; + let s1t1: TestInfo|any; + let s1t2: TestInfo|any; + let suite2: TestSuiteInfo|any; + let s2t1: TestInfo|any; + let s2t2: TestInfo|any; + let s2t3: TestInfo|any; beforeEach(async function() { adapter = createAdapterAndSubscribe(); @@ -341,6 +353,14 @@ describe('C2TestAdapter', function() { testsEvents.pop(); testsEvents.pop(); + suite1 = undefined; + s1t1 = undefined; + s1t2 = undefined; + suite2 = undefined; + s2t1 = undefined; + s2t2 = undefined; + s2t3 = undefined; + example1.assertWithoutChildren(root, uniqueIdC); assert.deepStrictEqual(testStatesEvents, []); }); @@ -360,10 +380,6 @@ describe('C2TestAdapter', function() { return updateConfig('executables', undefined); }); - let suite1: TestSuiteInfo; - let s1t1: TestInfo; - let s1t2: TestInfo; - beforeEach(async function() { assert.deepStrictEqual( getConfig().get('executables'), 'execPath1'); @@ -537,6 +553,530 @@ describe('C2TestAdapter', function() { }) }) + async function testShouldRunS1AndS2AsAll() { + await adapter.run([root.id]); + + const running = {type: 'started', tests: [root.id]}; + + const s1running = {type: 'suite', state: 'running', suite: suite1}; + const s1finished = {type: 'suite', state: 'completed', suite: suite1}; + assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); + assert.ok(testStatesEvI(s1running) < testStatesEvI(s1finished)); + + const s2running = {type: 'suite', state: 'running', suite: suite2}; + const s2finished = {type: 'suite', state: 'completed', suite: suite2}; + assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); + assert.ok(testStatesEvI(s2running) < testStatesEvI(s2finished)); + + const s1t1running = {type: 'test', state: 'running', test: s1t1}; + assert.ok(testStatesEvI(s1running) < testStatesEvI(s1t1running)); + + const s1t1finished = { + type: 'test', + state: 'passed', + test: s1t1, + decorations: undefined, + message: 'Duration: 0.000132 second(s)\n' + }; + assert.ok(testStatesEvI(s1t1running) < testStatesEvI(s1t1finished)); + assert.ok(testStatesEvI(s1t1finished) < testStatesEvI(s1finished)); + + const s1t2running = {type: 'test', state: 'running', test: s1t2}; + assert.ok(testStatesEvI(s1running) < testStatesEvI(s1t2running)); + + const s1t2finished = { + type: 'test', + state: 'failed', + test: s1t2, + decorations: [{line: 14, message: 'Expanded: false'}], + message: + 'Duration: 0.000204 second(s)\n>>> s1t2(line: 13) REQUIRE (line: 15) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' + }; + assert.ok(testStatesEvI(s1t2running) < testStatesEvI(s1t2finished)); + assert.ok(testStatesEvI(s1t2finished) < testStatesEvI(s1finished)); + + const s2t1running = {type: 'test', state: 'running', test: s2t1}; + assert.ok(testStatesEvI(s2running) < testStatesEvI(s2t1running)); + + const s2t1finished = { + type: 'test', + state: 'passed', + test: s2t1, + decorations: undefined, + message: 'Duration: 0.00037 second(s)\n' + }; + assert.ok(testStatesEvI(s2t1running) < testStatesEvI(s2t1finished)); + assert.ok(testStatesEvI(s2t1finished) < testStatesEvI(s2finished)); + + const s2t2running = {type: 'test', state: 'running', test: s2t2}; + assert.ok(testStatesEvI(s2running) < testStatesEvI(s2t2running)); + + const s2t2finished = {type: 'test', state: 'skipped', test: s2t2}; + assert.ok(testStatesEvI(s2t2running) < testStatesEvI(s2t2finished)); + assert.ok(testStatesEvI(s2t2finished) < testStatesEvI(s2finished)); + + const s2t3running = {type: 'test', state: 'running', test: s2t3}; + assert.ok(testStatesEvI(s2running) < testStatesEvI(s2t3running)); + + const s2t3finished = { + type: 'test', + state: 'failed', + test: s2t3, + decorations: [{line: 20, message: 'Expanded: false'}], + message: + 'Duration: 0.000178 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' + }; + assert.ok(testStatesEvI(s2t3running) < testStatesEvI(s2t3finished)); + assert.ok(testStatesEvI(s2t3finished) < testStatesEvI(s2finished)); + + const finished = {type: 'finished'}; + assert.ok(testStatesEvI(s1finished) < testStatesEvI(finished)); + assert.ok(testStatesEvI(s2finished) < testStatesEvI(finished)); + + assert.equal(testStatesEvents.length, 16, inspect(testStatesEvents)); + } + + const testsForAdapterWithSuite1AndSuite2: + [string, Mocha.AsyncFunc|Mocha.Func][] = [ + [ + 'test variables are fine, suite1 and suite1 are loaded', + function() { + assert.equal(root.children.length, 2); + assert.ok(suite1 != undefined); + assert.ok(s1t1 != undefined); + assert.ok(s1t2 != undefined); + assert.ok(suite2 != undefined); + assert.ok(s2t1 != undefined); + assert.ok(s2t2 != undefined); + assert.ok(s2t3 != undefined); + } + ], + [ + 'should run all', + async function() { + assert.equal(root.children.length, 2); + await adapter.run([root.id]); + + const running = {type: 'started', tests: [root.id]}; + + const s1running = { + type: 'suite', + state: 'running', + suite: suite1 + }; + const s1finished = { + type: 'suite', + state: 'completed', + suite: suite1 + }; + assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); + assert.ok(testStatesEvI(s1running) < testStatesEvI(s1finished)); + + const s2running = { + type: 'suite', + state: 'running', + suite: suite2 + }; + const s2finished = { + type: 'suite', + state: 'completed', + suite: suite2 + }; + assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); + assert.ok(testStatesEvI(s2running) < testStatesEvI(s2finished)); + + const s1t1running = {type: 'test', state: 'running', test: s1t1}; + assert.ok(testStatesEvI(s1running) < testStatesEvI(s1t1running)); + + const s1t1finished = { + type: 'test', + state: 'passed', + test: s1t1, + decorations: undefined, + message: 'Duration: 0.000132 second(s)\n' + }; + assert.ok( + testStatesEvI(s1t1running) < testStatesEvI(s1t1finished)); + assert.ok( + testStatesEvI(s1t1finished) < testStatesEvI(s1finished)); + + const s1t2running = {type: 'test', state: 'running', test: s1t2}; + assert.ok(testStatesEvI(s1running) < testStatesEvI(s1t2running)); + + const s1t2finished = { + type: 'test', + state: 'failed', + test: s1t2, + decorations: [{line: 14, message: 'Expanded: false'}], + message: + 'Duration: 0.000204 second(s)\n>>> s1t2(line: 13) REQUIRE (line: 15) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' + }; + assert.ok( + testStatesEvI(s1t2running) < testStatesEvI(s1t2finished)); + assert.ok( + testStatesEvI(s1t2finished) < testStatesEvI(s1finished)); + + const s2t1running = {type: 'test', state: 'running', test: s2t1}; + assert.ok(testStatesEvI(s2running) < testStatesEvI(s2t1running)); + + const s2t1finished = { + type: 'test', + state: 'passed', + test: s2t1, + decorations: undefined, + message: 'Duration: 0.00037 second(s)\n' + }; + assert.ok( + testStatesEvI(s2t1running) < testStatesEvI(s2t1finished)); + assert.ok( + testStatesEvI(s2t1finished) < testStatesEvI(s2finished)); + + const s2t2running = {type: 'test', state: 'running', test: s2t2}; + assert.ok(testStatesEvI(s2running) < testStatesEvI(s2t2running)); + + const s2t2finished = {type: 'test', state: 'skipped', test: s2t2}; + assert.ok( + testStatesEvI(s2t2running) < testStatesEvI(s2t2finished)); + assert.ok( + testStatesEvI(s2t2finished) < testStatesEvI(s2finished)); + + const s2t3running = {type: 'test', state: 'running', test: s2t3}; + assert.ok(testStatesEvI(s2running) < testStatesEvI(s2t3running)); + + const s2t3finished = { + type: 'test', + state: 'failed', + test: s2t3, + decorations: [{line: 20, message: 'Expanded: false'}], + message: + 'Duration: 0.000178 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' + }; + assert.ok( + testStatesEvI(s2t3running) < testStatesEvI(s2t3finished)); + assert.ok( + testStatesEvI(s2t3finished) < testStatesEvI(s2finished)); + + const finished = {type: 'finished'}; + assert.ok(testStatesEvI(s1finished) < testStatesEvI(finished)); + assert.ok(testStatesEvI(s2finished) < testStatesEvI(finished)); + + assert.equal( + testStatesEvents.length, 16, inspect(testStatesEvents)); + } + ], + [ + 'should run with not existing test id', + async function() { + await adapter.run(['not existing id']); + + assert.deepStrictEqual(testStatesEvents, [ + {type: 'started', tests: ['not existing id']}, + {type: 'finished'}, + ]); + } + ], + [ + 'should run s1t1', + async function() { + await adapter.run([s1t1.id]); + const expected = [ + {type: 'started', tests: [s1t1.id]}, + {type: 'suite', state: 'running', suite: suite1}, + {type: 'test', state: 'running', test: s1t1}, + { + type: 'test', + state: 'passed', + test: s1t1, + decorations: undefined, + message: 'Duration: 0.000112 second(s)\n' + }, + {type: 'suite', state: 'completed', suite: suite1}, + {type: 'finished'}, + ]; + assert.deepStrictEqual(testStatesEvents, expected); + + await adapter.run([s1t1.id]); + assert.deepStrictEqual( + testStatesEvents, [...expected, ...expected]); + } + ], + [ + 'should run skipped s2t2', + async function() { + await adapter.run([s2t2.id]); + const expected = [ + {type: 'started', tests: [s2t2.id]}, + {type: 'suite', state: 'running', suite: suite2}, + {type: 'test', state: 'running', test: s2t2}, + { + type: 'test', + state: 'passed', + test: s2t2, + decorations: undefined, + message: 'Duration: 0.001294 second(s)\n' + }, + {type: 'suite', state: 'completed', suite: suite2}, + {type: 'finished'}, + ]; + assert.deepStrictEqual(testStatesEvents, expected); + + await adapter.run([s2t2.id]); + assert.deepStrictEqual( + testStatesEvents, [...expected, ...expected]); + } + ], + [ + 'should run failing test s2t3', + async function() { + await adapter.run([s2t3.id]); + const expected = [ + {type: 'started', tests: [s2t3.id]}, + {type: 'suite', state: 'running', suite: suite2}, + {type: 'test', state: 'running', test: s2t3}, + { + type: 'test', + state: 'failed', + test: s2t3, + decorations: [{line: 20, message: 'Expanded: false'}], + message: + 'Duration: 0.000596 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' + }, + {type: 'suite', state: 'completed', suite: suite2}, + {type: 'finished'}, + ]; + assert.deepStrictEqual(testStatesEvents, expected); + + await adapter.run([s2t3.id]); + assert.deepStrictEqual( + testStatesEvents, [...expected, ...expected]); + } + ], + [ + 'should run failing test s2t3 with chunks', + async function() { + const withArgs = spawnStub.withArgs( + example1.suite2.execPath, example1.suite2.t3.outputs[0][0]); + withArgs.onCall(withArgs.callCount) + .returns( + new ChildProcessStub(example1.suite2.t3.outputs[0][1])); + + await adapter.run([s2t3.id]); + const expected = [ + {type: 'started', tests: [s2t3.id]}, + {type: 'suite', state: 'running', suite: suite2}, + {type: 'test', state: 'running', test: s2t3}, + { + type: 'test', + state: 'failed', + test: s2t3, + decorations: [{line: 20, message: 'Expanded: false'}], + message: + 'Duration: 0.000596 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' + }, + {type: 'suite', state: 'completed', suite: suite2}, + {type: 'finished'}, + ]; + assert.deepStrictEqual(testStatesEvents, expected); + + await adapter.run([s2t3.id]); + assert.deepStrictEqual( + testStatesEvents, [...expected, ...expected]); + } + ], + [ + 'should run suite1', + async function() { + await adapter.run([suite1.id]); + const expected = [ + {type: 'started', tests: [suite1.id]}, + {type: 'suite', state: 'running', suite: suite1}, + {type: 'test', state: 'running', test: s1t1}, + { + type: 'test', + state: 'passed', + test: s1t1, + decorations: undefined, + message: 'Duration: 0.000132 second(s)\n' + }, + {type: 'test', state: 'running', test: s1t2}, + { + type: 'test', + state: 'failed', + test: s1t2, + decorations: [{line: 14, message: 'Expanded: false'}], + message: + 'Duration: 0.000204 second(s)\n>>> s1t2(line: 13) REQUIRE (line: 15) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' + }, + {type: 'suite', state: 'completed', suite: suite1}, + {type: 'finished'}, + ]; + assert.deepStrictEqual(testStatesEvents, expected); + + await adapter.run([suite1.id]); + assert.deepStrictEqual( + testStatesEvents, [...expected, ...expected]); + } + ], + [ + 'should run with wrong xml', + async function() { + const m = + example1.suite1.t1.outputs[0][1].match(']+>'); + assert.notEqual(m, undefined); + assert.notEqual(m!.input, undefined); + assert.notEqual(m!.index, undefined); + const part = m!.input!.substr(0, m!.index! + m![0].length); + const withArgs = spawnStub.withArgs( + example1.suite1.execPath, example1.suite1.t1.outputs[0][0]); + withArgs.onCall(withArgs.callCount) + .returns(new ChildProcessStub(part)); + + await adapter.run([s1t1.id]); + + const expected = [ + {type: 'started', tests: [s1t1.id]}, + {type: 'suite', state: 'running', suite: suite1}, + {type: 'test', state: 'running', test: s1t1}, + { + type: 'test', + state: 'failed', + test: s1t1, + message: 'Unexpected test error. (Is Catch2 crashed?)\n' + }, + {type: 'suite', state: 'completed', suite: suite1}, + {type: 'finished'}, + ]; + assert.deepStrictEqual(testStatesEvents, expected); + + // this tests the sinon stubs too + await adapter.run([s1t1.id]); + assert.deepStrictEqual(testStatesEvents, [ + ...expected, + {type: 'started', tests: [s1t1.id]}, + {type: 'suite', state: 'running', suite: suite1}, + {type: 'test', state: 'running', test: s1t1}, + { + type: 'test', + state: 'passed', + test: s1t1, + decorations: undefined, + message: 'Duration: 0.000112 second(s)\n' + }, + {type: 'suite', state: 'completed', suite: suite1}, + {type: 'finished'}, + ]); + } + ], + [ + 'should cancel without error', + function() { + adapter.cancel(); + } + ], + [ + 'cancel', + async function() { + let spyKill1: sinon.SinonSpy; + let spyKill2: sinon.SinonSpy; + { + const spawnEvent = + new ChildProcessStub(example1.suite1.outputs[2][1]); + spyKill1 = sinon.spy(spawnEvent, 'kill'); + const withArgs = spawnStub.withArgs( + example1.suite1.execPath, example1.suite1.outputs[2][0]); + withArgs.onCall(withArgs.callCount).returns(spawnEvent); + } + { + const spawnEvent = + new ChildProcessStub(example1.suite2.outputs[2][1]); + spyKill2 = sinon.spy(spawnEvent, 'kill'); + const withArgs = spawnStub.withArgs( + example1.suite2.execPath, example1.suite2.outputs[2][0]); + withArgs.onCall(withArgs.callCount).returns(spawnEvent); + } + const run = adapter.run([root.id]); + adapter.cancel(); + await run; + + assert.equal(spyKill1.callCount, 1); + assert.equal(spyKill2.callCount, 1); + + const running = {type: 'started', tests: [root.id]}; + + const s1running = { + type: 'suite', + state: 'running', + suite: suite1 + }; + const s1finished = { + type: 'suite', + state: 'completed', + suite: suite1 + }; + assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); + assert.ok(testStatesEvI(s1running) < testStatesEvI(s1finished)); + + const s2running = { + type: 'suite', + state: 'running', + suite: suite2 + }; + const s2finished = { + type: 'suite', + state: 'completed', + suite: suite2 + }; + assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); + assert.ok(testStatesEvI(s2running) < testStatesEvI(s2finished)); + + const s2t2running = {type: 'test', state: 'running', test: s2t2}; + assert.ok(testStatesEvI(s2running) < testStatesEvI(s2t2running)); + + const s2t2finished = {type: 'test', state: 'skipped', test: s2t2}; + assert.ok( + testStatesEvI(s2t2running) < testStatesEvI(s2t2finished)); + assert.ok( + testStatesEvI(s2t2finished) < testStatesEvI(s2finished)); + + const finished = {type: 'finished'}; + assert.ok(testStatesEvI(s1finished) < testStatesEvI(finished)); + assert.ok(testStatesEvI(s2finished) < testStatesEvI(finished)); + + assert.equal( + testStatesEvents.length, 8, inspect(testStatesEvents)); + } + ], + [ + 'cancel after run finished', + function() { + let spyKill1: sinon.SinonSpy; + let spyKill2: sinon.SinonSpy; + { + const spawnEvent = + new ChildProcessStub(example1.suite1.outputs[2][1]); + spyKill1 = sinon.spy(spawnEvent, 'kill'); + const withArgs = spawnStub.withArgs( + example1.suite1.execPath, example1.suite1.outputs[2][0]); + withArgs.onCall(withArgs.callCount).returns(spawnEvent); + } + { + const spawnEvent = + new ChildProcessStub(example1.suite2.outputs[2][1]); + spyKill2 = sinon.spy(spawnEvent, 'kill'); + const withArgs = spawnStub.withArgs( + example1.suite2.execPath, example1.suite2.outputs[2][0]); + withArgs.onCall(withArgs.callCount).returns(spawnEvent); + } + const run = adapter.run([root.id]); + return run.then(() => { + adapter.cancel(); + assert.equal(spyKill1.callCount, 0); + assert.equal(spyKill2.callCount, 0); + }); + } + ], + ]; + context('executables=["execPath1", "${workspaceFolder}/execPath2"]', () => { before(() => { return updateConfig( @@ -547,14 +1087,6 @@ describe('C2TestAdapter', function() { return updateConfig('executables', undefined); }); - let suite1: TestSuiteInfo; - let s1t1: TestInfo; - let s1t2: TestInfo; - let suite2: TestSuiteInfo; - let s2t1: TestInfo; - let s2t2: TestInfo; - let s2t3: TestInfo; - beforeEach(async function() { assert.deepStrictEqual( getConfig().get('executables'), @@ -591,353 +1123,7 @@ describe('C2TestAdapter', function() { s2t3 = suite2.children[2]; }) - it('should run with not existing test id', async function() { - await adapter.run(['not existing id']); - - assert.deepStrictEqual(testStatesEvents, [ - {type: 'started', tests: ['not existing id']}, - {type: 'finished'}, - ]); - }) - - it('should run s1t1', async function() { - await adapter.run([s1t1.id]); - const expected = [ - {type: 'started', tests: [s1t1.id]}, - {type: 'suite', state: 'running', suite: suite1}, - {type: 'test', state: 'running', test: s1t1}, - { - type: 'test', - state: 'passed', - test: s1t1, - decorations: undefined, - message: 'Duration: 0.000112 second(s)\n' - }, - {type: 'suite', state: 'completed', suite: suite1}, - {type: 'finished'}, - ]; - assert.deepStrictEqual(testStatesEvents, expected); - - await adapter.run([s1t1.id]); - assert.deepStrictEqual(testStatesEvents, [...expected, ...expected]); - }) - - it('should run skipped s2t2', async function() { - await adapter.run([s2t2.id]); - const expected = [ - {type: 'started', tests: [s2t2.id]}, - {type: 'suite', state: 'running', suite: suite2}, - {type: 'test', state: 'running', test: s2t2}, - { - type: 'test', - state: 'passed', - test: s2t2, - decorations: undefined, - message: 'Duration: 0.001294 second(s)\n' - }, - {type: 'suite', state: 'completed', suite: suite2}, - {type: 'finished'}, - ]; - assert.deepStrictEqual(testStatesEvents, expected); - - await adapter.run([s2t2.id]); - assert.deepStrictEqual(testStatesEvents, [...expected, ...expected]); - }) - - it('should run failing test s2t3', async function() { - await adapter.run([s2t3.id]); - const expected = [ - {type: 'started', tests: [s2t3.id]}, - {type: 'suite', state: 'running', suite: suite2}, - {type: 'test', state: 'running', test: s2t3}, - { - type: 'test', - state: 'failed', - test: s2t3, - decorations: [{line: 20, message: 'Expanded: false'}], - message: - 'Duration: 0.000596 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }, - {type: 'suite', state: 'completed', suite: suite2}, - {type: 'finished'}, - ]; - assert.deepStrictEqual(testStatesEvents, expected); - - await adapter.run([s2t3.id]); - assert.deepStrictEqual(testStatesEvents, [...expected, ...expected]); - }) - - it('should run failing test s2t3 with chunks', async function() { - const withArgs = spawnStub.withArgs( - example1.suite2.execPath, example1.suite2.t3.outputs[0][0]); - withArgs.onCall(withArgs.callCount) - .returns(new ChildProcessStub(example1.suite2.t3.outputs[0][1])); - - await adapter.run([s2t3.id]); - const expected = [ - {type: 'started', tests: [s2t3.id]}, - {type: 'suite', state: 'running', suite: suite2}, - {type: 'test', state: 'running', test: s2t3}, - { - type: 'test', - state: 'failed', - test: s2t3, - decorations: [{line: 20, message: 'Expanded: false'}], - message: - 'Duration: 0.000596 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }, - {type: 'suite', state: 'completed', suite: suite2}, - {type: 'finished'}, - ]; - assert.deepStrictEqual(testStatesEvents, expected); - - await adapter.run([s2t3.id]); - assert.deepStrictEqual(testStatesEvents, [...expected, ...expected]); - }) - - it('should run suite1', async function() { - await adapter.run([suite1.id]); - const expected = [ - {type: 'started', tests: [suite1.id]}, - {type: 'suite', state: 'running', suite: suite1}, - {type: 'test', state: 'running', test: s1t1}, - { - type: 'test', - state: 'passed', - test: s1t1, - decorations: undefined, - message: 'Duration: 0.000132 second(s)\n' - }, - {type: 'test', state: 'running', test: s1t2}, - { - type: 'test', - state: 'failed', - test: s1t2, - decorations: [{line: 14, message: 'Expanded: false'}], - message: - 'Duration: 0.000204 second(s)\n>>> s1t2(line: 13) REQUIRE (line: 15) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }, - {type: 'suite', state: 'completed', suite: suite1}, - {type: 'finished'}, - ]; - assert.deepStrictEqual(testStatesEvents, expected); - - await adapter.run([suite1.id]); - assert.deepStrictEqual(testStatesEvents, [...expected, ...expected]); - }) - - it('should run all', async function() { - await adapter.run([root.id]); - - const running = {type: 'started', tests: [root.id]}; - - const s1running = {type: 'suite', state: 'running', suite: suite1}; - const s1finished = {type: 'suite', state: 'completed', suite: suite1}; - assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); - assert.ok(testStatesEvI(s1running) < testStatesEvI(s1finished)); - - const s2running = {type: 'suite', state: 'running', suite: suite2}; - const s2finished = {type: 'suite', state: 'completed', suite: suite2}; - assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); - assert.ok(testStatesEvI(s2running) < testStatesEvI(s2finished)); - - const s1t1running = {type: 'test', state: 'running', test: s1t1}; - assert.ok(testStatesEvI(s1running) < testStatesEvI(s1t1running)); - - const s1t1finished = { - type: 'test', - state: 'passed', - test: s1t1, - decorations: undefined, - message: 'Duration: 0.000132 second(s)\n' - }; - assert.ok(testStatesEvI(s1t1running) < testStatesEvI(s1t1finished)); - assert.ok(testStatesEvI(s1t1finished) < testStatesEvI(s1finished)); - - const s1t2running = {type: 'test', state: 'running', test: s1t2}; - assert.ok(testStatesEvI(s1running) < testStatesEvI(s1t2running)); - - const s1t2finished = { - type: 'test', - state: 'failed', - test: s1t2, - decorations: [{line: 14, message: 'Expanded: false'}], - message: - 'Duration: 0.000204 second(s)\n>>> s1t2(line: 13) REQUIRE (line: 15) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }; - assert.ok(testStatesEvI(s1t2running) < testStatesEvI(s1t2finished)); - assert.ok(testStatesEvI(s1t2finished) < testStatesEvI(s1finished)); - - const s2t1running = {type: 'test', state: 'running', test: s2t1}; - assert.ok(testStatesEvI(s2running) < testStatesEvI(s2t1running)); - - const s2t1finished = { - type: 'test', - state: 'passed', - test: s2t1, - decorations: undefined, - message: 'Duration: 0.00037 second(s)\n' - }; - assert.ok(testStatesEvI(s2t1running) < testStatesEvI(s2t1finished)); - assert.ok(testStatesEvI(s2t1finished) < testStatesEvI(s2finished)); - - const s2t2running = {type: 'test', state: 'running', test: s2t2}; - assert.ok(testStatesEvI(s2running) < testStatesEvI(s2t2running)); - - const s2t2finished = {type: 'test', state: 'skipped', test: s2t2}; - assert.ok(testStatesEvI(s2t2running) < testStatesEvI(s2t2finished)); - assert.ok(testStatesEvI(s2t2finished) < testStatesEvI(s2finished)); - - const s2t3running = {type: 'test', state: 'running', test: s2t3}; - assert.ok(testStatesEvI(s2running) < testStatesEvI(s2t3running)); - - const s2t3finished = { - type: 'test', - state: 'failed', - test: s2t3, - decorations: [{line: 20, message: 'Expanded: false'}], - message: - 'Duration: 0.000178 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }; - assert.ok(testStatesEvI(s2t3running) < testStatesEvI(s2t3finished)); - assert.ok(testStatesEvI(s2t3finished) < testStatesEvI(s2finished)); - - const finished = {type: 'finished'}; - assert.ok(testStatesEvI(s1finished) < testStatesEvI(finished)); - assert.ok(testStatesEvI(s2finished) < testStatesEvI(finished)); - - assert.equal(testStatesEvents.length, 16, inspect(testStatesEvents)); - }) - - it('should run with wrong xml', async function() { - const m = example1.suite1.t1.outputs[0][1].match(']+>'); - assert.notEqual(m, undefined); - assert.notEqual(m!.input, undefined); - assert.notEqual(m!.index, undefined); - const part = m!.input!.substr(0, m!.index! + m![0].length); - const withArgs = spawnStub.withArgs( - example1.suite1.execPath, example1.suite1.t1.outputs[0][0]); - withArgs.onCall(withArgs.callCount).returns(new ChildProcessStub(part)); - - await adapter.run([s1t1.id]); - - const expected = [ - {type: 'started', tests: [s1t1.id]}, - {type: 'suite', state: 'running', suite: suite1}, - {type: 'test', state: 'running', test: s1t1}, - { - type: 'test', - state: 'failed', - test: s1t1, - message: 'Unexpected test error. (Is Catch2 crashed?)\n' - }, - {type: 'suite', state: 'completed', suite: suite1}, - {type: 'finished'}, - ]; - assert.deepStrictEqual(testStatesEvents, expected); - - // this tests the sinon stubs too - await adapter.run([s1t1.id]); - assert.deepStrictEqual(testStatesEvents, [ - ...expected, - {type: 'started', tests: [s1t1.id]}, - {type: 'suite', state: 'running', suite: suite1}, - {type: 'test', state: 'running', test: s1t1}, - { - type: 'test', - state: 'passed', - test: s1t1, - decorations: undefined, - message: 'Duration: 0.000112 second(s)\n' - }, - {type: 'suite', state: 'completed', suite: suite1}, - {type: 'finished'}, - ]); - }) - - it('should cancel without error', function() { - adapter.cancel(); - }) - - it('cancel', async function() { - let spyKill1: sinon.SinonSpy; - let spyKill2: sinon.SinonSpy; - { - const spawnEvent = - new ChildProcessStub(example1.suite1.outputs[2][1]); - spyKill1 = sinon.spy(spawnEvent, 'kill'); - const withArgs = spawnStub.withArgs( - example1.suite1.execPath, example1.suite1.outputs[2][0]); - withArgs.onCall(withArgs.callCount).returns(spawnEvent); - } - { - const spawnEvent = - new ChildProcessStub(example1.suite2.outputs[2][1]); - spyKill2 = sinon.spy(spawnEvent, 'kill'); - const withArgs = spawnStub.withArgs( - example1.suite2.execPath, example1.suite2.outputs[2][0]); - withArgs.onCall(withArgs.callCount).returns(spawnEvent); - } - - const run = adapter.run([root.id]); - adapter.cancel(); - await run; - - assert.equal(spyKill1.callCount, 1); - assert.equal(spyKill2.callCount, 1); - - const running = {type: 'started', tests: [root.id]}; - - const s1running = {type: 'suite', state: 'running', suite: suite1}; - const s1finished = {type: 'suite', state: 'completed', suite: suite1}; - assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); - assert.ok(testStatesEvI(s1running) < testStatesEvI(s1finished)); - - const s2running = {type: 'suite', state: 'running', suite: suite2}; - const s2finished = {type: 'suite', state: 'completed', suite: suite2}; - assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); - assert.ok(testStatesEvI(s2running) < testStatesEvI(s2finished)); - - const s2t2running = {type: 'test', state: 'running', test: s2t2}; - assert.ok(testStatesEvI(s2running) < testStatesEvI(s2t2running)); - - const s2t2finished = {type: 'test', state: 'skipped', test: s2t2}; - assert.ok(testStatesEvI(s2t2running) < testStatesEvI(s2t2finished)); - assert.ok(testStatesEvI(s2t2finished) < testStatesEvI(s2finished)); - - const finished = {type: 'finished'}; - assert.ok(testStatesEvI(s1finished) < testStatesEvI(finished)); - assert.ok(testStatesEvI(s2finished) < testStatesEvI(finished)); - - assert.equal(testStatesEvents.length, 8, inspect(testStatesEvents)); - }) - - it('cancel after run finished', function() { - let spyKill1: sinon.SinonSpy; - let spyKill2: sinon.SinonSpy; - { - const spawnEvent = - new ChildProcessStub(example1.suite1.outputs[2][1]); - spyKill1 = sinon.spy(spawnEvent, 'kill'); - const withArgs = spawnStub.withArgs( - example1.suite1.execPath, example1.suite1.outputs[2][0]); - withArgs.onCall(withArgs.callCount).returns(spawnEvent); - } - { - const spawnEvent = - new ChildProcessStub(example1.suite2.outputs[2][1]); - spyKill2 = sinon.spy(spawnEvent, 'kill'); - const withArgs = spawnStub.withArgs( - example1.suite2.execPath, example1.suite2.outputs[2][0]); - withArgs.onCall(withArgs.callCount).returns(spawnEvent); - } - const run = adapter.run([root.id]); - return run.then(() => { - adapter.cancel(); - assert.equal(spyKill1.callCount, 0); - assert.equal(spyKill2.callCount, 0); - }); - }) + for (let t of testsForAdapterWithSuite1AndSuite2) it(t[0], t[1]); }) context('executables=[{}] and env={...}', function() { @@ -963,14 +1149,6 @@ describe('C2TestAdapter', function() { await updateConfig('defaultEnv', undefined); }); - let suite1: TestSuiteInfo; - let s1t1: TestInfo; - let s1t2: TestInfo; - let suite2: TestSuiteInfo; - let s2t1: TestInfo; - let s2t2: TestInfo; - let s2t3: TestInfo; - beforeEach(async function() { assert.equal(root.children.length, 2); @@ -1000,91 +1178,9 @@ describe('C2TestAdapter', function() { s2t3 = suite2.children[2]; }) - it('should run all', async function() { - await adapter.run([root.id]); - - const running = {type: 'started', tests: [root.id]}; - - const s1running = {type: 'suite', state: 'running', suite: suite1}; - const s1finished = {type: 'suite', state: 'completed', suite: suite1}; - assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); - assert.ok(testStatesEvI(s1running) < testStatesEvI(s1finished)); - - const s2running = {type: 'suite', state: 'running', suite: suite2}; - const s2finished = {type: 'suite', state: 'completed', suite: suite2}; - assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); - assert.ok(testStatesEvI(s2running) < testStatesEvI(s2finished)); - - const s1t1running = {type: 'test', state: 'running', test: s1t1}; - assert.ok(testStatesEvI(s1running) < testStatesEvI(s1t1running)); - - const s1t1finished = { - type: 'test', - state: 'passed', - test: s1t1, - decorations: undefined, - message: 'Duration: 0.000132 second(s)\n' - }; - assert.ok(testStatesEvI(s1t1running) < testStatesEvI(s1t1finished)); - assert.ok(testStatesEvI(s1t1finished) < testStatesEvI(s1finished)); - - const s1t2running = {type: 'test', state: 'running', test: s1t2}; - assert.ok(testStatesEvI(s1running) < testStatesEvI(s1t2running)); - - const s1t2finished = { - type: 'test', - state: 'failed', - test: s1t2, - decorations: [{line: 14, message: 'Expanded: false'}], - message: - 'Duration: 0.000204 second(s)\n>>> s1t2(line: 13) REQUIRE (line: 15) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }; - assert.ok(testStatesEvI(s1t2running) < testStatesEvI(s1t2finished)); - assert.ok(testStatesEvI(s1t2finished) < testStatesEvI(s1finished)); - - const s2t1running = {type: 'test', state: 'running', test: s2t1}; - assert.ok(testStatesEvI(s2running) < testStatesEvI(s2t1running)); - - const s2t1finished = { - type: 'test', - state: 'passed', - test: s2t1, - decorations: undefined, - message: 'Duration: 0.00037 second(s)\n' - }; - assert.ok(testStatesEvI(s2t1running) < testStatesEvI(s2t1finished)); - assert.ok(testStatesEvI(s2t1finished) < testStatesEvI(s2finished)); - - const s2t2running = {type: 'test', state: 'running', test: s2t2}; - assert.ok(testStatesEvI(s2running) < testStatesEvI(s2t2running)); - - const s2t2finished = {type: 'test', state: 'skipped', test: s2t2}; - assert.ok(testStatesEvI(s2t2running) < testStatesEvI(s2t2finished)); - assert.ok(testStatesEvI(s2t2finished) < testStatesEvI(s2finished)); - - const s2t3running = {type: 'test', state: 'running', test: s2t3}; - assert.ok(testStatesEvI(s2running) < testStatesEvI(s2t3running)); - - const s2t3finished = { - type: 'test', - state: 'failed', - test: s2t3, - decorations: [{line: 20, message: 'Expanded: false'}], - message: - 'Duration: 0.000178 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }; - assert.ok(testStatesEvI(s2t3running) < testStatesEvI(s2t3finished)); - assert.ok(testStatesEvI(s2t3finished) < testStatesEvI(s2finished)); - - const finished = {type: 'finished'}; - assert.ok(testStatesEvI(s1finished) < testStatesEvI(finished)); - assert.ok(testStatesEvI(s2finished) < testStatesEvI(finished)); - - assert.equal(testStatesEvents.length, 16, inspect(testStatesEvents)); - }) + for (let t of testsForAdapterWithSuite1AndSuite2) it(t[0], t[1]); it('should get execution options', async function() { - let called1 = false; spawnStub .withArgs( example1.suite1.execPath, sinon.match.any, sinon.match.any) @@ -1093,13 +1189,13 @@ describe('C2TestAdapter', function() { assert.equal(ops.env.C2LOCALTESTENV, 'c2localtestenv'); assert.ok(!ops.env.hasOwnProperty('C2GLOBALTESTENV')); assert.equal(ops.env.C2OVERRIDETESTENV, 'c2overridetestenv-l'); - called1 = true; return new ChildProcessStub(example1.suite1.outputs[2][1]); }); + + let spawnCallCount = spawnStub.callCount; await adapter.run([suite1.id]); - assert.ok(called1); + assert.equal(spawnStub.callCount, ++spawnCallCount); - let called2 = false; spawnStub .withArgs( example1.suite2.execPath, sinon.match.any, sinon.match.any) @@ -1108,11 +1204,11 @@ describe('C2TestAdapter', function() { assert.equal(ops.env.C2LOCALTESTENV, 'c2localtestenv'); assert.ok(!ops.env.hasOwnProperty('C2GLOBALTESTENV')); assert.equal(ops.env.C2OVERRIDETESTENV, 'c2overridetestenv-l'); - called2 = true; return new ChildProcessStub(example1.suite2.outputs[2][1]); }); + await adapter.run([suite2.id]); - assert.ok(called2); + assert.equal(spawnStub.callCount, ++spawnCallCount); }); }) }) diff --git a/src/test/Helpers.ts b/src/test/Helpers.ts index 5ca63c21..01600375 100644 --- a/src/test/Helpers.ts +++ b/src/test/Helpers.ts @@ -3,10 +3,12 @@ import {Stream} from 'stream'; export class ChildProcessStub extends EventEmitter { readonly stdout = new Stream.Readable(); + public closed: boolean = false; constructor(data?: string|Iterable) { super(); this.stdout.on('end', () => { + this.closed = true; this.emit('close', 1); }); if (data != undefined) { From 6fa65b5f6904a75cecfc679ef2660c572e8155cc Mon Sep 17 00:00:00 2001 From: Mate Pek Date: Tue, 23 Oct 2018 01:11:08 +0200 Subject: [PATCH 04/18] clearer tests --- src/test/C2TestAdapter.test.ts | 1227 +++++++++++++++----------------- 1 file changed, 586 insertions(+), 641 deletions(-) diff --git a/src/test/C2TestAdapter.test.ts b/src/test/C2TestAdapter.test.ts index c93591ed..5381e25a 100644 --- a/src/test/C2TestAdapter.test.ts +++ b/src/test/C2TestAdapter.test.ts @@ -74,7 +74,7 @@ describe('C2TestAdapter', function() { Object.keys(properties).forEach(key => { assert.ok(key.startsWith('catch2TestExplorer.')); const k = key.replace('catch2TestExplorer.', '') - t = t.then(() => { + t = t.then(function() { return getConfig().update(k, undefined); }); }); @@ -149,7 +149,7 @@ describe('C2TestAdapter', function() { // TODO stub.callThrough(); } - before(() => { + before(function() { fse.removeSync(dotVscodePath); adapter = undefined; @@ -170,7 +170,7 @@ describe('C2TestAdapter', function() { return resetConfig(); }); - after(() => { + after(function() { disposeAdapterAndSubscribers(); sinonSandbox.restore(); }); @@ -180,22 +180,23 @@ describe('C2TestAdapter', function() { let adapter: C2TestAdapter; - before(() => { + before(function() { adapter = createAdapterAndSubscribe(); assert.deepStrictEqual(testsEvents, []); }) - after(() => { + after(function() { disposeAdapterAndSubscribers(); return resetConfig(); }) describe('expectation to (re)load', function() { - afterEach(() => { + afterEach(function() { const waitForReloadAndAsser = (tryCount: number): Promise => { if (testsEvents.length < 2) - return new Promise(r => setTimeout(r, 10)) - .then(() => {waitForReloadAndAsser(tryCount - 1)}); + return new Promise(r => setTimeout(r, 10)).then(function() { + waitForReloadAndAsser(tryCount - 1) + }); else { assert.equal(testsEvents.length, 2); assert.equal(testsEvents[0].type, 'started'); @@ -214,27 +215,27 @@ describe('C2TestAdapter', function() { return waitForReloadAndAsser(20); }) - it('workerMaxNumber', () => { + it('workerMaxNumber', function() { return updateConfig('workerMaxNumber', 42); }) - it('defaultEnv', () => { + it('defaultEnv', function() { return updateConfig('defaultEnv', {'APPLE': 'apple'}); }) - it('defaultCwd', () => { + it('defaultCwd', function() { return updateConfig('defaultCwd', 'apple/peach'); }) }) - it('enableSourceDecoration', () => { - return updateConfig('enableSourceDecoration', false).then(() => { + it('enableSourceDecoration', function() { + return updateConfig('enableSourceDecoration', false).then(function() { assert.ok(!adapter.getIsEnabledSourceDecoration()); }); }) - it('defaultRngSeed', () => { - return updateConfig('defaultRngSeed', 987).then(() => { + it('defaultRngSeed', function() { + return updateConfig('defaultRngSeed', 987).then(function() { assert.equal(adapter.getRngSeed(), 987); }); }) @@ -253,10 +254,10 @@ describe('C2TestAdapter', function() { }) describe('load example1', function() { - before(() => { + before(function() { for (let suite of example1.outputs) { for (let scenario of suite[1]) { - spawnStub.withArgs(suite[0], scenario[0]).callsFake(() => { + spawnStub.withArgs(suite[0], scenario[0]).callsFake(function() { return new ChildProcessStub(scenario[1]); }); } @@ -325,7 +326,7 @@ describe('C2TestAdapter', function() { }); }) - after(() => { + after(function() { stubsResetToThrow(); }) @@ -365,18 +366,18 @@ describe('C2TestAdapter', function() { assert.deepStrictEqual(testStatesEvents, []); }); - afterEach(() => { + afterEach(function() { uniqueIdC.clear(); watchEvents.clear(); disposeAdapterAndSubscribers(); }); context('executables="execPath1"', function() { - before(() => { + before(function() { return updateConfig('executables', 'execPath1'); }); - after(() => { + after(function() { return updateConfig('executables', undefined); }); @@ -521,11 +522,11 @@ describe('C2TestAdapter', function() { }); context('with config: defaultRngSeed=2', function() { - before(() => { + before(function() { return updateConfig('defaultRngSeed', 2); }) - after(() => { + after(function() { return updateConfig('defaultRngSeed', undefined); }) @@ -553,663 +554,607 @@ describe('C2TestAdapter', function() { }) }) - async function testShouldRunS1AndS2AsAll() { - await adapter.run([root.id]); - - const running = {type: 'started', tests: [root.id]}; + context('suite1 and suite2 are used', function() { + beforeEach(function() { + assert.equal(root.children.length, 2); - const s1running = {type: 'suite', state: 'running', suite: suite1}; - const s1finished = {type: 'suite', state: 'completed', suite: suite1}; - assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); - assert.ok(testStatesEvI(s1running) < testStatesEvI(s1finished)); + assert.equal(root.children[0].type, 'suite'); + assert.equal(root.children[1].type, 'suite'); + suite1 = root.children[0]; + assert.equal(example1.suite1.outputs.length, 4 + 2 * 2); + assert.equal(example1.suite2.outputs.length, 4 + 2 * 3); + suite2 = root.children[1]; + if (suite2.children.length == 2) { + suite1 = root.children[1]; + suite2 = root.children[0]; + } - const s2running = {type: 'suite', state: 'running', suite: suite2}; - const s2finished = {type: 'suite', state: 'completed', suite: suite2}; - assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); - assert.ok(testStatesEvI(s2running) < testStatesEvI(s2finished)); + assert.equal(suite1.children.length, 2); + assert.equal(suite1.children[0].type, 'test'); + s1t1 = suite1.children[0]; + assert.equal(suite1.children[1].type, 'test'); + s1t2 = suite1.children[1]; - const s1t1running = {type: 'test', state: 'running', test: s1t1}; - assert.ok(testStatesEvI(s1running) < testStatesEvI(s1t1running)); + assert.equal(suite2.children.length, 3); + assert.equal(suite2.children[0].type, 'test'); + s2t1 = suite2.children[0]; + assert.equal(suite2.children[1].type, 'test'); + s2t2 = suite2.children[1]; + assert.equal(suite2.children[2].type, 'test'); + s2t3 = suite2.children[2]; + }) - const s1t1finished = { - type: 'test', - state: 'passed', - test: s1t1, - decorations: undefined, - message: 'Duration: 0.000132 second(s)\n' - }; - assert.ok(testStatesEvI(s1t1running) < testStatesEvI(s1t1finished)); - assert.ok(testStatesEvI(s1t1finished) < testStatesEvI(s1finished)); - - const s1t2running = {type: 'test', state: 'running', test: s1t2}; - assert.ok(testStatesEvI(s1running) < testStatesEvI(s1t2running)); - - const s1t2finished = { - type: 'test', - state: 'failed', - test: s1t2, - decorations: [{line: 14, message: 'Expanded: false'}], - message: - 'Duration: 0.000204 second(s)\n>>> s1t2(line: 13) REQUIRE (line: 15) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }; - assert.ok(testStatesEvI(s1t2running) < testStatesEvI(s1t2finished)); - assert.ok(testStatesEvI(s1t2finished) < testStatesEvI(s1finished)); - - const s2t1running = {type: 'test', state: 'running', test: s2t1}; - assert.ok(testStatesEvI(s2running) < testStatesEvI(s2t1running)); - - const s2t1finished = { - type: 'test', - state: 'passed', - test: s2t1, - decorations: undefined, - message: 'Duration: 0.00037 second(s)\n' - }; - assert.ok(testStatesEvI(s2t1running) < testStatesEvI(s2t1finished)); - assert.ok(testStatesEvI(s2t1finished) < testStatesEvI(s2finished)); - - const s2t2running = {type: 'test', state: 'running', test: s2t2}; - assert.ok(testStatesEvI(s2running) < testStatesEvI(s2t2running)); - - const s2t2finished = {type: 'test', state: 'skipped', test: s2t2}; - assert.ok(testStatesEvI(s2t2running) < testStatesEvI(s2t2finished)); - assert.ok(testStatesEvI(s2t2finished) < testStatesEvI(s2finished)); - - const s2t3running = {type: 'test', state: 'running', test: s2t3}; - assert.ok(testStatesEvI(s2running) < testStatesEvI(s2t3running)); - - const s2t3finished = { - type: 'test', - state: 'failed', - test: s2t3, - decorations: [{line: 20, message: 'Expanded: false'}], - message: - 'Duration: 0.000178 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }; - assert.ok(testStatesEvI(s2t3running) < testStatesEvI(s2t3finished)); - assert.ok(testStatesEvI(s2t3finished) < testStatesEvI(s2finished)); - - const finished = {type: 'finished'}; - assert.ok(testStatesEvI(s1finished) < testStatesEvI(finished)); - assert.ok(testStatesEvI(s2finished) < testStatesEvI(finished)); - - assert.equal(testStatesEvents.length, 16, inspect(testStatesEvents)); - } - - const testsForAdapterWithSuite1AndSuite2: - [string, Mocha.AsyncFunc|Mocha.Func][] = [ - [ - 'test variables are fine, suite1 and suite1 are loaded', - function() { - assert.equal(root.children.length, 2); - assert.ok(suite1 != undefined); - assert.ok(s1t1 != undefined); - assert.ok(s1t2 != undefined); - assert.ok(suite2 != undefined); - assert.ok(s2t1 != undefined); - assert.ok(s2t2 != undefined); - assert.ok(s2t3 != undefined); - } - ], - [ - 'should run all', - async function() { - assert.equal(root.children.length, 2); - await adapter.run([root.id]); - - const running = {type: 'started', tests: [root.id]}; - - const s1running = { - type: 'suite', - state: 'running', - suite: suite1 - }; - const s1finished = { - type: 'suite', - state: 'completed', - suite: suite1 - }; - assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); - assert.ok(testStatesEvI(s1running) < testStatesEvI(s1finished)); - - const s2running = { - type: 'suite', - state: 'running', - suite: suite2 - }; - const s2finished = { - type: 'suite', - state: 'completed', - suite: suite2 - }; - assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); - assert.ok(testStatesEvI(s2running) < testStatesEvI(s2finished)); - - const s1t1running = {type: 'test', state: 'running', test: s1t1}; - assert.ok(testStatesEvI(s1running) < testStatesEvI(s1t1running)); - - const s1t1finished = { - type: 'test', - state: 'passed', - test: s1t1, - decorations: undefined, - message: 'Duration: 0.000132 second(s)\n' - }; - assert.ok( - testStatesEvI(s1t1running) < testStatesEvI(s1t1finished)); - assert.ok( - testStatesEvI(s1t1finished) < testStatesEvI(s1finished)); - - const s1t2running = {type: 'test', state: 'running', test: s1t2}; - assert.ok(testStatesEvI(s1running) < testStatesEvI(s1t2running)); - - const s1t2finished = { - type: 'test', - state: 'failed', - test: s1t2, - decorations: [{line: 14, message: 'Expanded: false'}], - message: - 'Duration: 0.000204 second(s)\n>>> s1t2(line: 13) REQUIRE (line: 15) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }; - assert.ok( - testStatesEvI(s1t2running) < testStatesEvI(s1t2finished)); - assert.ok( - testStatesEvI(s1t2finished) < testStatesEvI(s1finished)); - - const s2t1running = {type: 'test', state: 'running', test: s2t1}; - assert.ok(testStatesEvI(s2running) < testStatesEvI(s2t1running)); - - const s2t1finished = { - type: 'test', - state: 'passed', - test: s2t1, - decorations: undefined, - message: 'Duration: 0.00037 second(s)\n' - }; - assert.ok( - testStatesEvI(s2t1running) < testStatesEvI(s2t1finished)); - assert.ok( - testStatesEvI(s2t1finished) < testStatesEvI(s2finished)); - - const s2t2running = {type: 'test', state: 'running', test: s2t2}; - assert.ok(testStatesEvI(s2running) < testStatesEvI(s2t2running)); - - const s2t2finished = {type: 'test', state: 'skipped', test: s2t2}; - assert.ok( - testStatesEvI(s2t2running) < testStatesEvI(s2t2finished)); - assert.ok( - testStatesEvI(s2t2finished) < testStatesEvI(s2finished)); - - const s2t3running = {type: 'test', state: 'running', test: s2t3}; - assert.ok(testStatesEvI(s2running) < testStatesEvI(s2t3running)); - - const s2t3finished = { - type: 'test', - state: 'failed', - test: s2t3, - decorations: [{line: 20, message: 'Expanded: false'}], - message: - 'Duration: 0.000178 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }; - assert.ok( - testStatesEvI(s2t3running) < testStatesEvI(s2t3finished)); - assert.ok( - testStatesEvI(s2t3finished) < testStatesEvI(s2finished)); - - const finished = {type: 'finished'}; - assert.ok(testStatesEvI(s1finished) < testStatesEvI(finished)); - assert.ok(testStatesEvI(s2finished) < testStatesEvI(finished)); - - assert.equal( - testStatesEvents.length, 16, inspect(testStatesEvents)); - } - ], - [ - 'should run with not existing test id', - async function() { - await adapter.run(['not existing id']); - - assert.deepStrictEqual(testStatesEvents, [ - {type: 'started', tests: ['not existing id']}, - {type: 'finished'}, - ]); - } - ], - [ - 'should run s1t1', - async function() { - await adapter.run([s1t1.id]); - const expected = [ - {type: 'started', tests: [s1t1.id]}, - {type: 'suite', state: 'running', suite: suite1}, - {type: 'test', state: 'running', test: s1t1}, - { - type: 'test', - state: 'passed', - test: s1t1, - decorations: undefined, - message: 'Duration: 0.000112 second(s)\n' - }, - {type: 'suite', state: 'completed', suite: suite1}, - {type: 'finished'}, - ]; - assert.deepStrictEqual(testStatesEvents, expected); - - await adapter.run([s1t1.id]); - assert.deepStrictEqual( - testStatesEvents, [...expected, ...expected]); - } - ], - [ - 'should run skipped s2t2', - async function() { - await adapter.run([s2t2.id]); - const expected = [ - {type: 'started', tests: [s2t2.id]}, - {type: 'suite', state: 'running', suite: suite2}, - {type: 'test', state: 'running', test: s2t2}, - { - type: 'test', - state: 'passed', - test: s2t2, - decorations: undefined, - message: 'Duration: 0.001294 second(s)\n' - }, - {type: 'suite', state: 'completed', suite: suite2}, - {type: 'finished'}, - ]; - assert.deepStrictEqual(testStatesEvents, expected); - - await adapter.run([s2t2.id]); - assert.deepStrictEqual( - testStatesEvents, [...expected, ...expected]); - } - ], - [ - 'should run failing test s2t3', - async function() { - await adapter.run([s2t3.id]); - const expected = [ - {type: 'started', tests: [s2t3.id]}, - {type: 'suite', state: 'running', suite: suite2}, - {type: 'test', state: 'running', test: s2t3}, - { - type: 'test', - state: 'failed', - test: s2t3, - decorations: [{line: 20, message: 'Expanded: false'}], - message: - 'Duration: 0.000596 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }, - {type: 'suite', state: 'completed', suite: suite2}, - {type: 'finished'}, - ]; - assert.deepStrictEqual(testStatesEvents, expected); - - await adapter.run([s2t3.id]); - assert.deepStrictEqual( - testStatesEvents, [...expected, ...expected]); - } - ], - [ - 'should run failing test s2t3 with chunks', - async function() { - const withArgs = spawnStub.withArgs( - example1.suite2.execPath, example1.suite2.t3.outputs[0][0]); - withArgs.onCall(withArgs.callCount) - .returns( - new ChildProcessStub(example1.suite2.t3.outputs[0][1])); - - await adapter.run([s2t3.id]); - const expected = [ - {type: 'started', tests: [s2t3.id]}, - {type: 'suite', state: 'running', suite: suite2}, - {type: 'test', state: 'running', test: s2t3}, - { + const testsForAdapterWithSuite1AndSuite2: + [string, Mocha.AsyncFunc|Mocha.Func][] = [ + [ + 'test variables are fine, suite1 and suite1 are loaded', + function() { + assert.equal(root.children.length, 2); + assert.ok(suite1 != undefined); + assert.ok(s1t1 != undefined); + assert.ok(s1t2 != undefined); + assert.ok(suite2 != undefined); + assert.ok(s2t1 != undefined); + assert.ok(s2t2 != undefined); + assert.ok(s2t3 != undefined); + } + ], + [ + 'should run all', + async function() { + assert.equal(root.children.length, 2); + await adapter.run([root.id]); + + const running = {type: 'started', tests: [root.id]}; + + const s1running = { + type: 'suite', + state: 'running', + suite: suite1 + }; + const s1finished = { + type: 'suite', + state: 'completed', + suite: suite1 + }; + assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); + assert.ok(testStatesEvI(s1running) < testStatesEvI(s1finished)); + + const s2running = { + type: 'suite', + state: 'running', + suite: suite2 + }; + const s2finished = { + type: 'suite', + state: 'completed', + suite: suite2 + }; + assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); + assert.ok(testStatesEvI(s2running) < testStatesEvI(s2finished)); + + const s1t1running = { type: 'test', - state: 'failed', - test: s2t3, - decorations: [{line: 20, message: 'Expanded: false'}], - message: - 'Duration: 0.000596 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }, - {type: 'suite', state: 'completed', suite: suite2}, - {type: 'finished'}, - ]; - assert.deepStrictEqual(testStatesEvents, expected); - - await adapter.run([s2t3.id]); - assert.deepStrictEqual( - testStatesEvents, [...expected, ...expected]); - } - ], - [ - 'should run suite1', - async function() { - await adapter.run([suite1.id]); - const expected = [ - {type: 'started', tests: [suite1.id]}, - {type: 'suite', state: 'running', suite: suite1}, - {type: 'test', state: 'running', test: s1t1}, - { + state: 'running', + test: s1t1 + }; + assert.ok( + testStatesEvI(s1running) < testStatesEvI(s1t1running)); + + const s1t1finished = { type: 'test', state: 'passed', test: s1t1, decorations: undefined, message: 'Duration: 0.000132 second(s)\n' - }, - {type: 'test', state: 'running', test: s1t2}, - { + }; + assert.ok( + testStatesEvI(s1t1running) < testStatesEvI(s1t1finished)); + assert.ok( + testStatesEvI(s1t1finished) < testStatesEvI(s1finished)); + + const s1t2running = { + type: 'test', + state: 'running', + test: s1t2 + }; + assert.ok( + testStatesEvI(s1running) < testStatesEvI(s1t2running)); + + const s1t2finished = { type: 'test', state: 'failed', test: s1t2, decorations: [{line: 14, message: 'Expanded: false'}], message: 'Duration: 0.000204 second(s)\n>>> s1t2(line: 13) REQUIRE (line: 15) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }, - {type: 'suite', state: 'completed', suite: suite1}, - {type: 'finished'}, - ]; - assert.deepStrictEqual(testStatesEvents, expected); - - await adapter.run([suite1.id]); - assert.deepStrictEqual( - testStatesEvents, [...expected, ...expected]); - } - ], - [ - 'should run with wrong xml', - async function() { - const m = - example1.suite1.t1.outputs[0][1].match(']+>'); - assert.notEqual(m, undefined); - assert.notEqual(m!.input, undefined); - assert.notEqual(m!.index, undefined); - const part = m!.input!.substr(0, m!.index! + m![0].length); - const withArgs = spawnStub.withArgs( - example1.suite1.execPath, example1.suite1.t1.outputs[0][0]); - withArgs.onCall(withArgs.callCount) - .returns(new ChildProcessStub(part)); - - await adapter.run([s1t1.id]); - - const expected = [ - {type: 'started', tests: [s1t1.id]}, - {type: 'suite', state: 'running', suite: suite1}, - {type: 'test', state: 'running', test: s1t1}, - { + }; + assert.ok( + testStatesEvI(s1t2running) < testStatesEvI(s1t2finished)); + assert.ok( + testStatesEvI(s1t2finished) < testStatesEvI(s1finished)); + + const s2t1running = { type: 'test', - state: 'failed', - test: s1t1, - message: 'Unexpected test error. (Is Catch2 crashed?)\n' - }, - {type: 'suite', state: 'completed', suite: suite1}, - {type: 'finished'}, - ]; - assert.deepStrictEqual(testStatesEvents, expected); - - // this tests the sinon stubs too - await adapter.run([s1t1.id]); - assert.deepStrictEqual(testStatesEvents, [ - ...expected, - {type: 'started', tests: [s1t1.id]}, - {type: 'suite', state: 'running', suite: suite1}, - {type: 'test', state: 'running', test: s1t1}, - { + state: 'running', + test: s2t1 + }; + assert.ok( + testStatesEvI(s2running) < testStatesEvI(s2t1running)); + + const s2t1finished = { type: 'test', state: 'passed', - test: s1t1, + test: s2t1, decorations: undefined, - message: 'Duration: 0.000112 second(s)\n' - }, - {type: 'suite', state: 'completed', suite: suite1}, - {type: 'finished'}, - ]); - } - ], - [ - 'should cancel without error', - function() { - adapter.cancel(); - } - ], - [ - 'cancel', - async function() { - let spyKill1: sinon.SinonSpy; - let spyKill2: sinon.SinonSpy; - { - const spawnEvent = - new ChildProcessStub(example1.suite1.outputs[2][1]); - spyKill1 = sinon.spy(spawnEvent, 'kill'); - const withArgs = spawnStub.withArgs( - example1.suite1.execPath, example1.suite1.outputs[2][0]); - withArgs.onCall(withArgs.callCount).returns(spawnEvent); + message: 'Duration: 0.00037 second(s)\n' + }; + assert.ok( + testStatesEvI(s2t1running) < testStatesEvI(s2t1finished)); + assert.ok( + testStatesEvI(s2t1finished) < testStatesEvI(s2finished)); + + const s2t2running = { + type: 'test', + state: 'running', + test: s2t2 + }; + assert.ok( + testStatesEvI(s2running) < testStatesEvI(s2t2running)); + + const s2t2finished = { + type: 'test', + state: 'skipped', + test: s2t2 + }; + assert.ok( + testStatesEvI(s2t2running) < testStatesEvI(s2t2finished)); + assert.ok( + testStatesEvI(s2t2finished) < testStatesEvI(s2finished)); + + const s2t3running = { + type: 'test', + state: 'running', + test: s2t3 + }; + assert.ok( + testStatesEvI(s2running) < testStatesEvI(s2t3running)); + + const s2t3finished = { + type: 'test', + state: 'failed', + test: s2t3, + decorations: [{line: 20, message: 'Expanded: false'}], + message: + 'Duration: 0.000178 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' + }; + assert.ok( + testStatesEvI(s2t3running) < testStatesEvI(s2t3finished)); + assert.ok( + testStatesEvI(s2t3finished) < testStatesEvI(s2finished)); + + const finished = {type: 'finished'}; + assert.ok(testStatesEvI(s1finished) < testStatesEvI(finished)); + assert.ok(testStatesEvI(s2finished) < testStatesEvI(finished)); + + assert.equal( + testStatesEvents.length, 16, inspect(testStatesEvents)); } - { - const spawnEvent = - new ChildProcessStub(example1.suite2.outputs[2][1]); - spyKill2 = sinon.spy(spawnEvent, 'kill'); - const withArgs = spawnStub.withArgs( - example1.suite2.execPath, example1.suite2.outputs[2][0]); - withArgs.onCall(withArgs.callCount).returns(spawnEvent); + ], + [ + 'should run with not existing test id', + async function() { + await adapter.run(['not existing id']); + + assert.deepStrictEqual(testStatesEvents, [ + {type: 'started', tests: ['not existing id']}, + {type: 'finished'}, + ]); } - const run = adapter.run([root.id]); - adapter.cancel(); - await run; - - assert.equal(spyKill1.callCount, 1); - assert.equal(spyKill2.callCount, 1); - - const running = {type: 'started', tests: [root.id]}; - - const s1running = { - type: 'suite', - state: 'running', - suite: suite1 - }; - const s1finished = { - type: 'suite', - state: 'completed', - suite: suite1 - }; - assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); - assert.ok(testStatesEvI(s1running) < testStatesEvI(s1finished)); - - const s2running = { - type: 'suite', - state: 'running', - suite: suite2 - }; - const s2finished = { - type: 'suite', - state: 'completed', - suite: suite2 - }; - assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); - assert.ok(testStatesEvI(s2running) < testStatesEvI(s2finished)); - - const s2t2running = {type: 'test', state: 'running', test: s2t2}; - assert.ok(testStatesEvI(s2running) < testStatesEvI(s2t2running)); - - const s2t2finished = {type: 'test', state: 'skipped', test: s2t2}; - assert.ok( - testStatesEvI(s2t2running) < testStatesEvI(s2t2finished)); - assert.ok( - testStatesEvI(s2t2finished) < testStatesEvI(s2finished)); - - const finished = {type: 'finished'}; - assert.ok(testStatesEvI(s1finished) < testStatesEvI(finished)); - assert.ok(testStatesEvI(s2finished) < testStatesEvI(finished)); - - assert.equal( - testStatesEvents.length, 8, inspect(testStatesEvents)); - } - ], - [ - 'cancel after run finished', - function() { - let spyKill1: sinon.SinonSpy; - let spyKill2: sinon.SinonSpy; - { - const spawnEvent = - new ChildProcessStub(example1.suite1.outputs[2][1]); - spyKill1 = sinon.spy(spawnEvent, 'kill'); + ], + [ + 'should run s1t1', + async function() { + await adapter.run([s1t1.id]); + const expected = [ + {type: 'started', tests: [s1t1.id]}, + {type: 'suite', state: 'running', suite: suite1}, + {type: 'test', state: 'running', test: s1t1}, + { + type: 'test', + state: 'passed', + test: s1t1, + decorations: undefined, + message: 'Duration: 0.000112 second(s)\n' + }, + {type: 'suite', state: 'completed', suite: suite1}, + {type: 'finished'}, + ]; + assert.deepStrictEqual(testStatesEvents, expected); + + await adapter.run([s1t1.id]); + assert.deepStrictEqual( + testStatesEvents, [...expected, ...expected]); + } + ], + [ + 'should run skipped s2t2', + async function() { + await adapter.run([s2t2.id]); + const expected = [ + {type: 'started', tests: [s2t2.id]}, + {type: 'suite', state: 'running', suite: suite2}, + {type: 'test', state: 'running', test: s2t2}, + { + type: 'test', + state: 'passed', + test: s2t2, + decorations: undefined, + message: 'Duration: 0.001294 second(s)\n' + }, + {type: 'suite', state: 'completed', suite: suite2}, + {type: 'finished'}, + ]; + assert.deepStrictEqual(testStatesEvents, expected); + + await adapter.run([s2t2.id]); + assert.deepStrictEqual( + testStatesEvents, [...expected, ...expected]); + } + ], + [ + 'should run failing test s2t3', + async function() { + await adapter.run([s2t3.id]); + const expected = [ + {type: 'started', tests: [s2t3.id]}, + {type: 'suite', state: 'running', suite: suite2}, + {type: 'test', state: 'running', test: s2t3}, + { + type: 'test', + state: 'failed', + test: s2t3, + decorations: [{line: 20, message: 'Expanded: false'}], + message: + 'Duration: 0.000596 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' + }, + {type: 'suite', state: 'completed', suite: suite2}, + {type: 'finished'}, + ]; + assert.deepStrictEqual(testStatesEvents, expected); + + await adapter.run([s2t3.id]); + assert.deepStrictEqual( + testStatesEvents, [...expected, ...expected]); + } + ], + [ + 'should run failing test s2t3 with chunks', + async function() { const withArgs = spawnStub.withArgs( - example1.suite1.execPath, example1.suite1.outputs[2][0]); - withArgs.onCall(withArgs.callCount).returns(spawnEvent); + example1.suite2.execPath, example1.suite2.t3.outputs[0][0]); + withArgs.onCall(withArgs.callCount) + .returns( + new ChildProcessStub(example1.suite2.t3.outputs[0][1])); + + await adapter.run([s2t3.id]); + const expected = [ + {type: 'started', tests: [s2t3.id]}, + {type: 'suite', state: 'running', suite: suite2}, + {type: 'test', state: 'running', test: s2t3}, + { + type: 'test', + state: 'failed', + test: s2t3, + decorations: [{line: 20, message: 'Expanded: false'}], + message: + 'Duration: 0.000596 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' + }, + {type: 'suite', state: 'completed', suite: suite2}, + {type: 'finished'}, + ]; + assert.deepStrictEqual(testStatesEvents, expected); + + await adapter.run([s2t3.id]); + assert.deepStrictEqual( + testStatesEvents, [...expected, ...expected]); + } + ], + [ + 'should run suite1', + async function() { + await adapter.run([suite1.id]); + const expected = [ + {type: 'started', tests: [suite1.id]}, + {type: 'suite', state: 'running', suite: suite1}, + {type: 'test', state: 'running', test: s1t1}, + { + type: 'test', + state: 'passed', + test: s1t1, + decorations: undefined, + message: 'Duration: 0.000132 second(s)\n' + }, + {type: 'test', state: 'running', test: s1t2}, + { + type: 'test', + state: 'failed', + test: s1t2, + decorations: [{line: 14, message: 'Expanded: false'}], + message: + 'Duration: 0.000204 second(s)\n>>> s1t2(line: 13) REQUIRE (line: 15) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' + }, + {type: 'suite', state: 'completed', suite: suite1}, + {type: 'finished'}, + ]; + assert.deepStrictEqual(testStatesEvents, expected); + + await adapter.run([suite1.id]); + assert.deepStrictEqual( + testStatesEvents, [...expected, ...expected]); } - { - const spawnEvent = - new ChildProcessStub(example1.suite2.outputs[2][1]); - spyKill2 = sinon.spy(spawnEvent, 'kill'); + ], + [ + 'should run with wrong xml', + async function() { + const m = + example1.suite1.t1.outputs[0][1].match(']+>'); + assert.notEqual(m, undefined); + assert.notEqual(m!.input, undefined); + assert.notEqual(m!.index, undefined); + const part = m!.input!.substr(0, m!.index! + m![0].length); const withArgs = spawnStub.withArgs( - example1.suite2.execPath, example1.suite2.outputs[2][0]); - withArgs.onCall(withArgs.callCount).returns(spawnEvent); + example1.suite1.execPath, example1.suite1.t1.outputs[0][0]); + withArgs.onCall(withArgs.callCount) + .returns(new ChildProcessStub(part)); + + await adapter.run([s1t1.id]); + + const expected = [ + {type: 'started', tests: [s1t1.id]}, + {type: 'suite', state: 'running', suite: suite1}, + {type: 'test', state: 'running', test: s1t1}, + { + type: 'test', + state: 'failed', + test: s1t1, + message: 'Unexpected test error. (Is Catch2 crashed?)\n' + }, + {type: 'suite', state: 'completed', suite: suite1}, + {type: 'finished'}, + ]; + assert.deepStrictEqual(testStatesEvents, expected); + + // this tests the sinon stubs too + await adapter.run([s1t1.id]); + assert.deepStrictEqual(testStatesEvents, [ + ...expected, + {type: 'started', tests: [s1t1.id]}, + {type: 'suite', state: 'running', suite: suite1}, + {type: 'test', state: 'running', test: s1t1}, + { + type: 'test', + state: 'passed', + test: s1t1, + decorations: undefined, + message: 'Duration: 0.000112 second(s)\n' + }, + {type: 'suite', state: 'completed', suite: suite1}, + {type: 'finished'}, + ]); } - const run = adapter.run([root.id]); - return run.then(() => { + ], + [ + 'should cancel without error', + function() { adapter.cancel(); - assert.equal(spyKill1.callCount, 0); - assert.equal(spyKill2.callCount, 0); - }); - } - ], - ]; - - context('executables=["execPath1", "${workspaceFolder}/execPath2"]', () => { - before(() => { - return updateConfig( - 'executables', ['execPath1', '${workspaceFolder}/execPath2']); - }); - - after(() => { - return updateConfig('executables', undefined); - }); - - beforeEach(async function() { - assert.deepStrictEqual( - getConfig().get('executables'), - ['execPath1', '${workspaceFolder}/execPath2']); - assert.equal(root.children.length, 2); + } + ], + [ + 'cancel', + async function() { + let spyKill1: sinon.SinonSpy; + let spyKill2: sinon.SinonSpy; + { + const spawnEvent = + new ChildProcessStub(example1.suite1.outputs[2][1]); + spyKill1 = sinon.spy(spawnEvent, 'kill'); + const withArgs = spawnStub.withArgs( + example1.suite1.execPath, example1.suite1.outputs[2][0]); + withArgs.onCall(withArgs.callCount).returns(spawnEvent); + } + { + const spawnEvent = + new ChildProcessStub(example1.suite2.outputs[2][1]); + spyKill2 = sinon.spy(spawnEvent, 'kill'); + const withArgs = spawnStub.withArgs( + example1.suite2.execPath, example1.suite2.outputs[2][0]); + withArgs.onCall(withArgs.callCount).returns(spawnEvent); + } + const run = adapter.run([root.id]); + adapter.cancel(); + await run; + + assert.equal(spyKill1.callCount, 1); + assert.equal(spyKill2.callCount, 1); + + const running = {type: 'started', tests: [root.id]}; + + const s1running = { + type: 'suite', + state: 'running', + suite: suite1 + }; + const s1finished = { + type: 'suite', + state: 'completed', + suite: suite1 + }; + assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); + assert.ok(testStatesEvI(s1running) < testStatesEvI(s1finished)); + + const s2running = { + type: 'suite', + state: 'running', + suite: suite2 + }; + const s2finished = { + type: 'suite', + state: 'completed', + suite: suite2 + }; + assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); + assert.ok(testStatesEvI(s2running) < testStatesEvI(s2finished)); + + const s2t2running = { + type: 'test', + state: 'running', + test: s2t2 + }; + assert.ok( + testStatesEvI(s2running) < testStatesEvI(s2t2running)); - assert.equal(root.children[0].type, 'suite'); - assert.equal(root.children[1].type, 'suite'); - suite1 = root.children[0]; - assert.equal(example1.suite1.outputs.length, 4 + 2 * 2); - suite2 = root.children[1]; - if (suite2.children.length == 2) { - suite1 = root.children[1]; - suite2 = root.children[0]; - } + const s2t2finished = { + type: 'test', + state: 'skipped', + test: s2t2 + }; + assert.ok( + testStatesEvI(s2t2running) < testStatesEvI(s2t2finished)); + assert.ok( + testStatesEvI(s2t2finished) < testStatesEvI(s2finished)); + + const finished = {type: 'finished'}; + assert.ok(testStatesEvI(s1finished) < testStatesEvI(finished)); + assert.ok(testStatesEvI(s2finished) < testStatesEvI(finished)); + + assert.equal( + testStatesEvents.length, 8, inspect(testStatesEvents)); + } + ], + [ + 'cancel after run finished', + function() { + let spyKill1: sinon.SinonSpy; + let spyKill2: sinon.SinonSpy; + { + const spawnEvent = + new ChildProcessStub(example1.suite1.outputs[2][1]); + spyKill1 = sinon.spy(spawnEvent, 'kill'); + const withArgs = spawnStub.withArgs( + example1.suite1.execPath, example1.suite1.outputs[2][0]); + withArgs.onCall(withArgs.callCount).returns(spawnEvent); + } + { + const spawnEvent = + new ChildProcessStub(example1.suite2.outputs[2][1]); + spyKill2 = sinon.spy(spawnEvent, 'kill'); + const withArgs = spawnStub.withArgs( + example1.suite2.execPath, example1.suite2.outputs[2][0]); + withArgs.onCall(withArgs.callCount).returns(spawnEvent); + } + const run = adapter.run([root.id]); + return run.then(function() { + adapter.cancel(); + assert.equal(spyKill1.callCount, 0); + assert.equal(spyKill2.callCount, 0); + }); + } + ], + ]; - example1.suite1.assert( - 'execPath1', ['s1t1', 's1t2'], suite1, uniqueIdC); - assert.equal(suite1.children.length, 2); - assert.equal(suite1.children[0].type, 'test'); - s1t1 = suite1.children[0]; - assert.equal(suite1.children[1].type, 'test'); - s1t2 = suite1.children[1]; + context( + 'executables=["execPath1", "${workspaceFolder}/execPath2"]', + function() { + before(function() { + return updateConfig( + 'executables', ['execPath1', '${workspaceFolder}/execPath2']); + }); - example1.suite2.assert( - path.join(workspaceFolderUri.path, 'execPath2'), - ['s2t1', 's2t2 [.]', 's2t3'], suite2, uniqueIdC); - assert.equal(suite2.children.length, 3); - assert.equal(suite2.children[0].type, 'test'); - s2t1 = suite2.children[0]; - assert.equal(suite2.children[1].type, 'test'); - s2t2 = suite2.children[1]; - assert.equal(suite2.children[2].type, 'test'); - s2t3 = suite2.children[2]; - }) + after(function() { + return updateConfig('executables', undefined); + }); - for (let t of testsForAdapterWithSuite1AndSuite2) it(t[0], t[1]); - }) + beforeEach(async function() { + example1.suite1.assert( + 'execPath1', ['s1t1', 's1t2'], suite1, uniqueIdC); + + example1.suite2.assert( + path.join(workspaceFolderUri.path, 'execPath2'), + ['s2t1', 's2t2 [.]', 's2t3'], suite2, uniqueIdC); + }) + + for (let t of testsForAdapterWithSuite1AndSuite2) it(t[0], t[1]); + }) + + context('executables=[{}] and env={...}', function() { + before(async function() { + await updateConfig('executables', [{ + name: '${dirname}: ${name} (${absDirname})', + path: '.', + regex: 'execPath(1|2)', + cwd: '${workspaceFolder}/cwd', + env: { + 'C2LOCALTESTENV': 'c2localtestenv', + 'C2OVERRIDETESTENV': 'c2overridetestenv-l', + } + }]); + await updateConfig('defaultEnv', { + 'C2GLOBALTESTENV': 'c2globaltestenv', + 'C2OVERRIDETESTENV': 'c2overridetestenv-g', + }); + }); - context('executables=[{}] and env={...}', function() { - before(async () => { - await updateConfig('executables', [{ - name: '${dirname}: ${name} (${absDirname})', - path: '.', - regex: 'execPath(1|2)', - cwd: '${workspaceFolder}/cwd', - env: { - 'C2LOCALTESTENV': 'c2localtestenv', - 'C2OVERRIDETESTENV': 'c2overridetestenv-l', - } - }]); - await updateConfig('defaultEnv', { - 'C2GLOBALTESTENV': 'c2globaltestenv', - 'C2OVERRIDETESTENV': 'c2overridetestenv-g', + after(async function() { + await updateConfig('executables', undefined); + await updateConfig('defaultEnv', undefined); }); - }); - after(async () => { - await updateConfig('executables', undefined); - await updateConfig('defaultEnv', undefined); - }); + beforeEach(async function() { + example1.suite1.assert( + ': execPath1 (' + workspaceFolderUri.path + ')', ['s1t1', 's1t2'], + suite1, uniqueIdC); - beforeEach(async function() { - assert.equal(root.children.length, 2); + example1.suite2.assert( + ': execPath2 (' + workspaceFolderUri.path + ')', + ['s2t1', 's2t2 [.]', 's2t3'], suite2, uniqueIdC); + }) - assert.equal(root.children[0].type, 'suite'); - assert.equal(root.children[1].type, 'suite'); - suite1 = root.children[0]; - suite2 = root.children[1]; + for (let t of testsForAdapterWithSuite1AndSuite2) it(t[0], t[1]); + + it('should get execution options', async function() { + spawnStub + .withArgs( + example1.suite1.execPath, sinon.match.any, sinon.match.any) + .callsFake((p: string, args: string[], ops: any) => { + assert.equal( + ops.cwd, path.join(workspaceFolderUri.path, 'cwd')); + assert.equal(ops.env.C2LOCALTESTENV, 'c2localtestenv'); + assert.ok(!ops.env.hasOwnProperty('C2GLOBALTESTENV')); + assert.equal(ops.env.C2OVERRIDETESTENV, 'c2overridetestenv-l'); + return new ChildProcessStub(example1.suite1.outputs[2][1]); + }); - example1.suite1.assert( - ': execPath1 (' + workspaceFolderUri.path + ')', ['s1t1', 's1t2'], - suite1, uniqueIdC); - assert.equal(suite1.children.length, 2); - assert.equal(suite1.children[0].type, 'test'); - s1t1 = suite1.children[0]; - assert.equal(suite1.children[1].type, 'test'); - s1t2 = suite1.children[1]; + let spawnCallCount = spawnStub.callCount; + await adapter.run([suite1.id]); + assert.equal(spawnStub.callCount, ++spawnCallCount); + + spawnStub + .withArgs( + example1.suite2.execPath, sinon.match.any, sinon.match.any) + .callsFake((p: string, args: string[], ops: any) => { + assert.equal( + ops.cwd, path.join(workspaceFolderUri.path, 'cwd')); + assert.equal(ops.env.C2LOCALTESTENV, 'c2localtestenv'); + assert.ok(!ops.env.hasOwnProperty('C2GLOBALTESTENV')); + assert.equal(ops.env.C2OVERRIDETESTENV, 'c2overridetestenv-l'); + return new ChildProcessStub(example1.suite2.outputs[2][1]); + }); - example1.suite2.assert( - ': execPath2 (' + workspaceFolderUri.path + ')', - ['s2t1', 's2t2 [.]', 's2t3'], suite2, uniqueIdC); - assert.equal(suite2.children.length, 3); - assert.equal(suite2.children[0].type, 'test'); - s2t1 = suite2.children[0]; - assert.equal(suite2.children[1].type, 'test'); - s2t2 = suite2.children[1]; - assert.equal(suite2.children[2].type, 'test'); - s2t3 = suite2.children[2]; + await adapter.run([suite2.id]); + assert.equal(spawnStub.callCount, ++spawnCallCount); + }); }) - - for (let t of testsForAdapterWithSuite1AndSuite2) it(t[0], t[1]); - - it('should get execution options', async function() { - spawnStub - .withArgs( - example1.suite1.execPath, sinon.match.any, sinon.match.any) - .callsFake((p: string, args: string[], ops: any) => { - assert.equal(ops.cwd, path.join(workspaceFolderUri.path, 'cwd')); - assert.equal(ops.env.C2LOCALTESTENV, 'c2localtestenv'); - assert.ok(!ops.env.hasOwnProperty('C2GLOBALTESTENV')); - assert.equal(ops.env.C2OVERRIDETESTENV, 'c2overridetestenv-l'); - return new ChildProcessStub(example1.suite1.outputs[2][1]); - }); - - let spawnCallCount = spawnStub.callCount; - await adapter.run([suite1.id]); - assert.equal(spawnStub.callCount, ++spawnCallCount); - - spawnStub - .withArgs( - example1.suite2.execPath, sinon.match.any, sinon.match.any) - .callsFake((p: string, args: string[], ops: any) => { - assert.equal(ops.cwd, path.join(workspaceFolderUri.path, 'cwd')); - assert.equal(ops.env.C2LOCALTESTENV, 'c2localtestenv'); - assert.ok(!ops.env.hasOwnProperty('C2GLOBALTESTENV')); - assert.equal(ops.env.C2OVERRIDETESTENV, 'c2overridetestenv-l'); - return new ChildProcessStub(example1.suite2.outputs[2][1]); - }); - - await adapter.run([suite2.id]); - assert.equal(spawnStub.callCount, ++spawnCallCount); - }); }) }) }) \ No newline at end of file From b8dd184e7cb74b026f9ebc74cf391a03410728e5 Mon Sep 17 00:00:00 2001 From: Mate Pek Date: Tue, 23 Oct 2018 01:19:39 +0200 Subject: [PATCH 05/18] clearer tests --- src/test/C2TestAdapter.test.ts | 62 ++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/src/test/C2TestAdapter.test.ts b/src/test/C2TestAdapter.test.ts index 5381e25a..b723b3e1 100644 --- a/src/test/C2TestAdapter.test.ts +++ b/src/test/C2TestAdapter.test.ts @@ -1123,36 +1123,38 @@ describe('C2TestAdapter', function() { for (let t of testsForAdapterWithSuite1AndSuite2) it(t[0], t[1]); it('should get execution options', async function() { - spawnStub - .withArgs( - example1.suite1.execPath, sinon.match.any, sinon.match.any) - .callsFake((p: string, args: string[], ops: any) => { - assert.equal( - ops.cwd, path.join(workspaceFolderUri.path, 'cwd')); - assert.equal(ops.env.C2LOCALTESTENV, 'c2localtestenv'); - assert.ok(!ops.env.hasOwnProperty('C2GLOBALTESTENV')); - assert.equal(ops.env.C2OVERRIDETESTENV, 'c2overridetestenv-l'); - return new ChildProcessStub(example1.suite1.outputs[2][1]); - }); - - let spawnCallCount = spawnStub.callCount; - await adapter.run([suite1.id]); - assert.equal(spawnStub.callCount, ++spawnCallCount); - - spawnStub - .withArgs( - example1.suite2.execPath, sinon.match.any, sinon.match.any) - .callsFake((p: string, args: string[], ops: any) => { - assert.equal( - ops.cwd, path.join(workspaceFolderUri.path, 'cwd')); - assert.equal(ops.env.C2LOCALTESTENV, 'c2localtestenv'); - assert.ok(!ops.env.hasOwnProperty('C2GLOBALTESTENV')); - assert.equal(ops.env.C2OVERRIDETESTENV, 'c2overridetestenv-l'); - return new ChildProcessStub(example1.suite2.outputs[2][1]); - }); - - await adapter.run([suite2.id]); - assert.equal(spawnStub.callCount, ++spawnCallCount); + { + const withArgs = spawnStub.withArgs( + example1.suite1.execPath, sinon.match.any, sinon.match.any); + withArgs.onCall(withArgs.callCount) + .callsFake((p: string, args: string[], ops: any) => { + assert.equal( + ops.cwd, path.join(workspaceFolderUri.path, 'cwd')); + assert.equal(ops.env.C2LOCALTESTENV, 'c2localtestenv'); + assert.ok(!ops.env.hasOwnProperty('C2GLOBALTESTENV')); + assert.equal( + ops.env.C2OVERRIDETESTENV, 'c2overridetestenv-l'); + return new ChildProcessStub(example1.suite1.outputs[2][1]); + }); + + await adapter.run([suite1.id]); + } + { + const withArgs = spawnStub.withArgs( + example1.suite2.execPath, sinon.match.any, sinon.match.any); + withArgs.onCall(withArgs.callCount) + .callsFake((p: string, args: string[], ops: any) => { + assert.equal( + ops.cwd, path.join(workspaceFolderUri.path, 'cwd')); + assert.equal(ops.env.C2LOCALTESTENV, 'c2localtestenv'); + assert.ok(!ops.env.hasOwnProperty('C2GLOBALTESTENV')); + assert.equal( + ops.env.C2OVERRIDETESTENV, 'c2overridetestenv-l'); + return new ChildProcessStub(example1.suite2.outputs[2][1]); + }); + + await adapter.run([suite2.id]); + } }); }) }) From 145005df5c91fcf5a72208a97c4e567c7869df31 Mon Sep 17 00:00:00 2001 From: Mate Pek Date: Tue, 23 Oct 2018 03:13:00 +0200 Subject: [PATCH 06/18] fswatcher fix and tests --- src/C2TestAdapter.ts | 23 ++++++++----- src/test/C2TestAdapter.test.ts | 61 +++++++++++++++++++++++++++++++--- 2 files changed, 71 insertions(+), 13 deletions(-) diff --git a/src/C2TestAdapter.ts b/src/C2TestAdapter.ts index 6e3a7692..0994f9c5 100644 --- a/src/C2TestAdapter.ts +++ b/src/C2TestAdapter.ts @@ -118,15 +118,22 @@ export class C2TestAdapter implements TestAdapter, vscode.Disposable { this.testsEmitter.fire({type: 'started'}); allTests.removeChild(suite); this.testsEmitter.fire({type: 'finished', suite: this.allTests}); - } else if (!fs.existsSync(suite.execPath)) { - setTimeout( - waitAndThenTry, delay, - [remainingIteration - 1, Math.max(delay * 2, 2000)]); } else { - this.testsEmitter.fire({type: 'started'}); - suite.reloadChildren().then(() => { - this.testsEmitter.fire({type: 'finished', suite: this.allTests}); - }); + fs.exists( + suite.execPath, + <(exists: boolean) => void>((err: any, exists: boolean) => { + if (!exists) { + setTimeout( + waitAndThenTry, delay, remainingIteration - 1, + Math.min(delay * 2, 2000)); + } else { + this.testsEmitter.fire({type: 'started'}); + suite.reloadChildren().then(() => { + this.testsEmitter.fire( + {type: 'finished', suite: this.allTests}); + }); + } + })); } }; diff --git a/src/test/C2TestAdapter.test.ts b/src/test/C2TestAdapter.test.ts index b723b3e1..1e216ee5 100644 --- a/src/test/C2TestAdapter.test.ts +++ b/src/test/C2TestAdapter.test.ts @@ -14,7 +14,7 @@ import * as sinon from 'sinon'; import {EventEmitter} from 'events'; import {TestEvent, TestLoadFinishedEvent, TestLoadStartedEvent, TestRunFinishedEvent, TestRunStartedEvent, TestSuiteEvent, TestSuiteInfo, TestInfo, TestAdapter} from 'vscode-test-adapter-api'; import {Log} from 'vscode-test-adapter-util'; -import {inspect} from 'util'; +import {inspect, promisify} from 'util'; import {C2TestAdapter} from '../C2TestAdapter'; import {example1} from './example1'; @@ -254,6 +254,8 @@ describe('C2TestAdapter', function() { }) describe('load example1', function() { + const watchers: Map = new Map(); + before(function() { for (let suite of example1.outputs) { for (let scenario of suite[1]) { @@ -280,7 +282,7 @@ describe('C2TestAdapter', function() { const ee = new class extends EventEmitter { close() {} }; - watchEvents.set(path, ee); + watchers.set(path, ee); return ee; } else { throw Error('File not found?'); @@ -330,8 +332,11 @@ describe('C2TestAdapter', function() { stubsResetToThrow(); }) + afterEach(function() { + watchers.clear(); + }) + const uniqueIdC = new Set(); - const watchEvents: Map = new Map(); let adapter: TestAdapter; let root: TestSuiteInfo; @@ -368,7 +373,6 @@ describe('C2TestAdapter', function() { afterEach(function() { uniqueIdC.clear(); - watchEvents.clear(); disposeAdapterAndSubscribers(); }); @@ -560,9 +564,9 @@ describe('C2TestAdapter', function() { assert.equal(root.children[0].type, 'suite'); assert.equal(root.children[1].type, 'suite'); - suite1 = root.children[0]; assert.equal(example1.suite1.outputs.length, 4 + 2 * 2); assert.equal(example1.suite2.outputs.length, 4 + 2 * 3); + suite1 = root.children[0]; suite2 = root.children[1]; if (suite2.children.length == 2) { suite1 = root.children[1]; @@ -1061,6 +1065,53 @@ describe('C2TestAdapter', function() { }); } ], + [ + 'reload because of fswatcher event', + async function(this: Mocha.Context) { + assert.equal(watchers.size, 2); + assert.ok(watchers.has(example1.suite1.execPath)); + const suite1Watcher = watchers.get(example1.suite1.execPath)!; + assert.equal(testsEvents.length, 0); + + const waitForReload = async(): Promise => { + let tryCount: number = 20; + while (testsEvents.length != 2 && --tryCount > 0) + await promisify(setTimeout)(20); + assert.equal(testsEvents.length, 2); + const e = testsEvents.pop()!; + testsEvents.pop(); + assert.equal(e.type, 'finished'); + assert.ok(e.suite != undefined); + return e.suite!; + }; + + const oldRootSuites = [...root.children]; + const oldSuite1Tests = [...suite1.children]; + suite1Watcher.emit( + 'change', 'dummyEvent', example1.suite1.execPath); + const newRoot = await waitForReload(); + + assert.deepStrictEqual(newRoot, root); + } + ], + [ + 'reload because of fswatcher event, file is deleted', + async function(this: Mocha.Context) { + + } + ], + [ + 'reload because of fswatcher event, new test in file', + async function(this: Mocha.Context) { + + } + ], + [ + 'reload because of fswatcher event, one test deleted from file', + async function(this: Mocha.Context) { + + } + ], ]; context( From 819cdcb1a11bf8ca8940d9bf7c07a0909dcdf65e Mon Sep 17 00:00:00 2001 From: Mate Pek Date: Tue, 23 Oct 2018 11:59:47 +0200 Subject: [PATCH 07/18] fswatcher fix and tests 2 --- src/C2TestAdapter.ts | 19 +- src/FsWrapper.ts | 5 +- src/test/C2TestAdapter.test.ts | 1738 +++++++++++++++++--------------- 3 files changed, 943 insertions(+), 819 deletions(-) diff --git a/src/C2TestAdapter.ts b/src/C2TestAdapter.ts index 0994f9c5..da13fadd 100644 --- a/src/C2TestAdapter.ts +++ b/src/C2TestAdapter.ts @@ -4,6 +4,7 @@ import * as fs from 'fs'; import * as path from 'path'; +import {inspect} from 'util'; import * as vscode from 'vscode'; import {TestAdapter, TestEvent, TestLoadFinishedEvent, TestLoadStartedEvent, TestRunFinishedEvent, TestRunStartedEvent, TestSuiteEvent} from 'vscode-test-adapter-api'; import * as util from 'vscode-test-adapter-util'; @@ -128,10 +129,17 @@ export class C2TestAdapter implements TestAdapter, vscode.Disposable { Math.min(delay * 2, 2000)); } else { this.testsEmitter.fire({type: 'started'}); - suite.reloadChildren().then(() => { - this.testsEmitter.fire( - {type: 'finished', suite: this.allTests}); - }); + suite.reloadChildren().then( + () => { + this.testsEmitter.fire( + {type: 'finished', suite: this.allTests}); + }, + (err: any) => { + this.log.warn(inspect(err)); + setTimeout( + waitAndThenTry, delay, remainingIteration - 1, + Math.min(delay * 2, 2000)); + }); } })); } @@ -145,7 +153,8 @@ export class C2TestAdapter implements TestAdapter, vscode.Disposable { } catch (e) { this.log.warn('watcher couldn\'t watch: ' + suite.execPath); } - return suite.reloadChildren().catch((e) => { + return suite.reloadChildren().catch((err: any) => { + this.log.warn(inspect(err)); this.allTests.removeChild(suite); }); } diff --git a/src/FsWrapper.ts b/src/FsWrapper.ts index d4c8b66a..f1f362f0 100644 --- a/src/FsWrapper.ts +++ b/src/FsWrapper.ts @@ -9,9 +9,8 @@ export function spawnAsync( cmd: string, args?: string[], options?: cp.SpawnOptions): Promise> { return new Promise((resolve) => { - const command = cp.spawn(cmd, args, options); const ret: cp.SpawnSyncReturns = { - pid: command.pid, + pid: 0, output: [], stdout: '', stderr: '', @@ -19,6 +18,8 @@ export function spawnAsync( signal: '', error: new Error() }; + const command = cp.spawn(cmd, args, options); + ret.pid = command.pid; command.stdout.on('data', function(data) { ret.stdout += data; ret.output.push(data); diff --git a/src/test/C2TestAdapter.test.ts b/src/test/C2TestAdapter.test.ts index 1e216ee5..a5ed78f8 100644 --- a/src/test/C2TestAdapter.test.ts +++ b/src/test/C2TestAdapter.test.ts @@ -126,27 +126,30 @@ describe('C2TestAdapter', function() { testStatesEvents = []; } - function stubsThrowByDefault() { + function stubsResetToMyDefault() { + spawnStub.reset(); + spawnStub.callThrough(); spawnStub.withArgs(workspaceFolderMatcher).callsFake((...args: any[]) => { throw new Error(inspect(['spawnStub', args])); }); + + fsWatchStub.reset(); + fsWatchStub.callThrough(); fsWatchStub.withArgs(workspaceFolderMatcher).callsFake((...args: any[]) => { throw new Error(inspect(['fsWatchStub', args])); }); + + fsExistsStub.reset(); + fsExistsStub.callThrough(); fsExistsStub.withArgs(workspaceFolderMatcher) - .callsFake((...args: any[]) => { - throw new Error(inspect(['fsExistsStub', args])); - }); - } + .callsFake((...args: any[]) => { + throw new Error(inspect(['fsExistsStub', args])); + }); - function stubsResetToThrow() { - spawnStub.reset(); - fsWatchStub.reset(); - fsExistsStub.reset(); c2fsReaddirSyncStub.reset(); + c2fsReaddirSyncStub.callThrough(); c2fsStatSyncStub.reset(); - stubsThrowByDefault(); - // TODO stub.callThrough(); + c2fsStatSyncStub.callThrough(); } before(function() { @@ -164,7 +167,7 @@ describe('C2TestAdapter', function() { c2fsStatSyncStub = sinonSandbox.stub(c2fs, 'statSync'); c2fsStatSyncStub.named('c2fsStatSyncStub'); - stubsResetToThrow(); + stubsResetToMyDefault(); // reset config can cause problem with fse.removeSync(dotVscodePath); return resetConfig(); @@ -253,7 +256,7 @@ describe('C2TestAdapter', function() { disposeAdapterAndSubscribers(); }) - describe('load example1', function() { + context('example1', function() { const watchers: Map = new Map(); before(function() { @@ -329,212 +332,181 @@ describe('C2TestAdapter', function() { }) after(function() { - stubsResetToThrow(); + stubsResetToMyDefault(); }) afterEach(function() { watchers.clear(); }) - const uniqueIdC = new Set(); - let adapter: TestAdapter; - - let root: TestSuiteInfo; - let suite1: TestSuiteInfo|any; - let s1t1: TestInfo|any; - let s1t2: TestInfo|any; - let suite2: TestSuiteInfo|any; - let s2t1: TestInfo|any; - let s2t2: TestInfo|any; - let s2t3: TestInfo|any; - - beforeEach(async function() { - adapter = createAdapterAndSubscribe(); - await adapter.load(); - - assert.equal(testsEvents.length, 2, inspect(testsEvents)); - assert.equal(testsEvents[1].type, 'finished'); - assert.ok((testsEvents[1]).suite); - root = (testsEvents[1]).suite!; - testsEvents.pop(); - testsEvents.pop(); - - suite1 = undefined; - s1t1 = undefined; - s1t2 = undefined; - suite2 = undefined; - s2t1 = undefined; - s2t2 = undefined; - s2t3 = undefined; - - example1.assertWithoutChildren(root, uniqueIdC); - assert.deepStrictEqual(testStatesEvents, []); - }); + describe('load', function() { + const uniqueIdC = new Set(); + let adapter: TestAdapter; - afterEach(function() { - uniqueIdC.clear(); - disposeAdapterAndSubscribers(); - }); + let root: TestSuiteInfo; + let suite1: TestSuiteInfo|any; + let s1t1: TestInfo|any; + let s1t2: TestInfo|any; + let suite2: TestSuiteInfo|any; + let s2t1: TestInfo|any; + let s2t2: TestInfo|any; + let s2t3: TestInfo|any; - context('executables="execPath1"', function() { - before(function() { - return updateConfig('executables', 'execPath1'); + beforeEach(async function() { + adapter = createAdapterAndSubscribe(); + await adapter.load(); + + assert.equal(testsEvents.length, 2, inspect(testsEvents)); + assert.equal(testsEvents[1].type, 'finished'); + assert.ok((testsEvents[1]).suite); + root = (testsEvents[1]).suite!; + testsEvents.pop(); + testsEvents.pop(); + + suite1 = undefined; + s1t1 = undefined; + s1t2 = undefined; + suite2 = undefined; + s2t1 = undefined; + s2t2 = undefined; + s2t3 = undefined; + + example1.assertWithoutChildren(root, uniqueIdC); + assert.deepStrictEqual(testStatesEvents, []); }); - after(function() { - return updateConfig('executables', undefined); + afterEach(function() { + uniqueIdC.clear(); + disposeAdapterAndSubscribers(); }); - beforeEach(async function() { - assert.deepStrictEqual( - getConfig().get('executables'), 'execPath1'); - assert.equal(root.children.length, 1); - assert.equal(root.children[0].type, 'suite'); - suite1 = root.children[0]; - example1.suite1.assert( - 'execPath1', ['s1t1', 's1t2'], suite1, uniqueIdC); - assert.equal(suite1.children.length, 2); - assert.equal(suite1.children[0].type, 'test'); - s1t1 = suite1.children[0]; - assert.equal(suite1.children[1].type, 'test'); - s1t2 = suite1.children[1]; - }); + context('executables="execPath1"', function() { + before(function() { + return updateConfig('executables', 'execPath1'); + }); - it('should run with not existing test id', async function() { - await adapter.run(['not existing id']); + after(function() { + return updateConfig('executables', undefined); + }); - assert.deepStrictEqual(testStatesEvents, [ - {type: 'started', tests: ['not existing id']}, - {type: 'finished'}, - ]); - }); + beforeEach(async function() { + assert.deepStrictEqual( + getConfig().get('executables'), 'execPath1'); + assert.equal(root.children.length, 1); + assert.equal(root.children[0].type, 'suite'); + suite1 = root.children[0]; + example1.suite1.assert( + 'execPath1', ['s1t1', 's1t2'], suite1, uniqueIdC); + assert.equal(suite1.children.length, 2); + assert.equal(suite1.children[0].type, 'test'); + s1t1 = suite1.children[0]; + assert.equal(suite1.children[1].type, 'test'); + s1t2 = suite1.children[1]; + }); - it('should run s1t1 with success', async function() { - assert.equal(getConfig().get('executables'), 'execPath1'); - await adapter.run([s1t1.id]); - const expected = [ - {type: 'started', tests: [s1t1.id]}, - {type: 'suite', state: 'running', suite: suite1}, - {type: 'test', state: 'running', test: s1t1}, - { - type: 'test', - state: 'passed', - test: s1t1, - decorations: undefined, - message: 'Duration: 0.000112 second(s)\n' - }, - {type: 'suite', state: 'completed', suite: suite1}, - {type: 'finished'}, - ]; - assert.deepStrictEqual(testStatesEvents, expected); - - await adapter.run([s1t1.id]); - assert.deepStrictEqual(testStatesEvents, [...expected, ...expected]); - }); + it('should run with not existing test id', async function() { + await adapter.run(['not existing id']); - it('should run suite1', async function() { - await adapter.run([suite1.id]); - const expected = [ - {type: 'started', tests: [suite1.id]}, - {type: 'suite', state: 'running', suite: suite1}, - {type: 'test', state: 'running', test: s1t1}, - { - type: 'test', - state: 'passed', - test: s1t1, - decorations: undefined, - message: 'Duration: 0.000132 second(s)\n' - }, - {type: 'test', state: 'running', test: s1t2}, - { - type: 'test', - state: 'failed', - test: s1t2, - decorations: [{line: 14, message: 'Expanded: false'}], - message: - 'Duration: 0.000204 second(s)\n>>> s1t2(line: 13) REQUIRE (line: 15) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }, - {type: 'suite', state: 'completed', suite: suite1}, - {type: 'finished'}, - ]; - assert.deepStrictEqual(testStatesEvents, expected); - - await adapter.run([suite1.id]); - assert.deepStrictEqual(testStatesEvents, [...expected, ...expected]); - }); + assert.deepStrictEqual(testStatesEvents, [ + {type: 'started', tests: ['not existing id']}, + {type: 'finished'}, + ]); + }); - it('should run all', async function() { - await adapter.run([root.id]); - const expected = [ - {type: 'started', tests: [root.id]}, - {type: 'suite', state: 'running', suite: suite1}, - {type: 'test', state: 'running', test: s1t1}, - { - type: 'test', - state: 'passed', - test: s1t1, - decorations: undefined, - message: 'Duration: 0.000132 second(s)\n' - }, - {type: 'test', state: 'running', test: s1t2}, - { - type: 'test', - state: 'failed', - test: s1t2, - decorations: [{line: 14, message: 'Expanded: false'}], - message: - 'Duration: 0.000204 second(s)\n>>> s1t2(line: 13) REQUIRE (line: 15) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }, - {type: 'suite', state: 'completed', suite: suite1}, - {type: 'finished'}, - ]; - assert.deepStrictEqual(testStatesEvents, expected); - - await adapter.run([root.id]); - assert.deepStrictEqual(testStatesEvents, [...expected, ...expected]); - }); + it('should run s1t1 with success', async function() { + assert.equal(getConfig().get('executables'), 'execPath1'); + await adapter.run([s1t1.id]); + const expected = [ + {type: 'started', tests: [s1t1.id]}, + {type: 'suite', state: 'running', suite: suite1}, + {type: 'test', state: 'running', test: s1t1}, + { + type: 'test', + state: 'passed', + test: s1t1, + decorations: undefined, + message: 'Duration: 0.000112 second(s)\n' + }, + {type: 'suite', state: 'completed', suite: suite1}, + {type: 'finished'}, + ]; + assert.deepStrictEqual(testStatesEvents, expected); - it('cancels without any problem', async function() { - adapter.cancel(); - assert.deepStrictEqual(testsEvents, []); - assert.deepStrictEqual(testStatesEvents, []); + await adapter.run([s1t1.id]); + assert.deepStrictEqual(testStatesEvents, [...expected, ...expected]); + }); - adapter.cancel(); - assert.deepStrictEqual(testsEvents, []); - assert.deepStrictEqual(testStatesEvents, []); + it('should run suite1', async function() { + await adapter.run([suite1.id]); + const expected = [ + {type: 'started', tests: [suite1.id]}, + {type: 'suite', state: 'running', suite: suite1}, + {type: 'test', state: 'running', test: s1t1}, + { + type: 'test', + state: 'passed', + test: s1t1, + decorations: undefined, + message: 'Duration: 0.000132 second(s)\n' + }, + {type: 'test', state: 'running', test: s1t2}, + { + type: 'test', + state: 'failed', + test: s1t2, + decorations: [{line: 14, message: 'Expanded: false'}], + message: + 'Duration: 0.000204 second(s)\n>>> s1t2(line: 13) REQUIRE (line: 15) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' + }, + {type: 'suite', state: 'completed', suite: suite1}, + {type: 'finished'}, + ]; + assert.deepStrictEqual(testStatesEvents, expected); - await adapter.run([s1t1.id]); - const expected = [ - {type: 'started', tests: [s1t1.id]}, - {type: 'suite', state: 'running', suite: suite1}, - {type: 'test', state: 'running', test: s1t1}, - { - type: 'test', - state: 'passed', - test: s1t1, - decorations: undefined, - message: 'Duration: 0.000112 second(s)\n' - }, - {type: 'suite', state: 'completed', suite: suite1}, - {type: 'finished'}, - ]; - assert.deepStrictEqual(testStatesEvents, expected); - - adapter.cancel(); - assert.deepStrictEqual(testsEvents, []); - assert.deepStrictEqual(testStatesEvents, expected); - }); + await adapter.run([suite1.id]); + assert.deepStrictEqual(testStatesEvents, [...expected, ...expected]); + }); - context('with config: defaultRngSeed=2', function() { - before(function() { - return updateConfig('defaultRngSeed', 2); - }) + it('should run all', async function() { + await adapter.run([root.id]); + const expected = [ + {type: 'started', tests: [root.id]}, + {type: 'suite', state: 'running', suite: suite1}, + {type: 'test', state: 'running', test: s1t1}, + { + type: 'test', + state: 'passed', + test: s1t1, + decorations: undefined, + message: 'Duration: 0.000132 second(s)\n' + }, + {type: 'test', state: 'running', test: s1t2}, + { + type: 'test', + state: 'failed', + test: s1t2, + decorations: [{line: 14, message: 'Expanded: false'}], + message: + 'Duration: 0.000204 second(s)\n>>> s1t2(line: 13) REQUIRE (line: 15) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' + }, + {type: 'suite', state: 'completed', suite: suite1}, + {type: 'finished'}, + ]; + assert.deepStrictEqual(testStatesEvents, expected); - after(function() { - return updateConfig('defaultRngSeed', undefined); - }) + await adapter.run([root.id]); + assert.deepStrictEqual(testStatesEvents, [...expected, ...expected]); + }); + + it('cancels without any problem', async function() { + adapter.cancel(); + assert.deepStrictEqual(testsEvents, []); + assert.deepStrictEqual(testStatesEvents, []); + + adapter.cancel(); + assert.deepStrictEqual(testsEvents, []); + assert.deepStrictEqual(testStatesEvents, []); - it('should run s1t1 with success', async function() { await adapter.run([s1t1.id]); const expected = [ {type: 'started', tests: [s1t1.id]}, @@ -545,669 +517,811 @@ describe('C2TestAdapter', function() { state: 'passed', test: s1t1, decorations: undefined, - message: 'Randomness seeded to: 2\nDuration: 0.000327 second(s)\n' + message: 'Duration: 0.000112 second(s)\n' }, {type: 'suite', state: 'completed', suite: suite1}, {type: 'finished'}, ]; assert.deepStrictEqual(testStatesEvents, expected); - await adapter.run([s1t1.id]); - assert.deepStrictEqual(testStatesEvents, [...expected, ...expected]); + adapter.cancel(); + assert.deepStrictEqual(testsEvents, []); + assert.deepStrictEqual(testStatesEvents, expected); + }); + + context('with config: defaultRngSeed=2', function() { + before(function() { + return updateConfig('defaultRngSeed', 2); + }) + + after(function() { + return updateConfig('defaultRngSeed', undefined); + }) + + it('should run s1t1 with success', async function() { + await adapter.run([s1t1.id]); + const expected = [ + {type: 'started', tests: [s1t1.id]}, + {type: 'suite', state: 'running', suite: suite1}, + {type: 'test', state: 'running', test: s1t1}, + { + type: 'test', + state: 'passed', + test: s1t1, + decorations: undefined, + message: + 'Randomness seeded to: 2\nDuration: 0.000327 second(s)\n' + }, + {type: 'suite', state: 'completed', suite: suite1}, + {type: 'finished'}, + ]; + assert.deepStrictEqual(testStatesEvents, expected); + + await adapter.run([s1t1.id]); + assert.deepStrictEqual( + testStatesEvents, [...expected, ...expected]); + }) }) }) - }) - context('suite1 and suite2 are used', function() { - beforeEach(function() { - assert.equal(root.children.length, 2); - - assert.equal(root.children[0].type, 'suite'); - assert.equal(root.children[1].type, 'suite'); - assert.equal(example1.suite1.outputs.length, 4 + 2 * 2); - assert.equal(example1.suite2.outputs.length, 4 + 2 * 3); - suite1 = root.children[0]; - suite2 = root.children[1]; - if (suite2.children.length == 2) { - suite1 = root.children[1]; - suite2 = root.children[0]; - } + context('suite1 and suite2 are used', function() { + beforeEach(function() { + assert.equal(root.children.length, 2); + + assert.equal(root.children[0].type, 'suite'); + assert.equal(root.children[1].type, 'suite'); + assert.equal(example1.suite1.outputs.length, 4 + 2 * 2); + assert.equal(example1.suite2.outputs.length, 4 + 2 * 3); + suite1 = root.children[0]; + suite2 = root.children[1]; + if (suite2.children.length == 2) { + suite1 = root.children[1]; + suite2 = root.children[0]; + } - assert.equal(suite1.children.length, 2); - assert.equal(suite1.children[0].type, 'test'); - s1t1 = suite1.children[0]; - assert.equal(suite1.children[1].type, 'test'); - s1t2 = suite1.children[1]; - - assert.equal(suite2.children.length, 3); - assert.equal(suite2.children[0].type, 'test'); - s2t1 = suite2.children[0]; - assert.equal(suite2.children[1].type, 'test'); - s2t2 = suite2.children[1]; - assert.equal(suite2.children[2].type, 'test'); - s2t3 = suite2.children[2]; - }) + assert.equal(suite1.children.length, 2); + assert.equal(suite1.children[0].type, 'test'); + s1t1 = suite1.children[0]; + assert.equal(suite1.children[1].type, 'test'); + s1t2 = suite1.children[1]; + + assert.equal(suite2.children.length, 3); + assert.equal(suite2.children[0].type, 'test'); + s2t1 = suite2.children[0]; + assert.equal(suite2.children[1].type, 'test'); + s2t2 = suite2.children[1]; + assert.equal(suite2.children[2].type, 'test'); + s2t3 = suite2.children[2]; + }) - const testsForAdapterWithSuite1AndSuite2: - [string, Mocha.AsyncFunc|Mocha.Func][] = [ - [ - 'test variables are fine, suite1 and suite1 are loaded', - function() { - assert.equal(root.children.length, 2); - assert.ok(suite1 != undefined); - assert.ok(s1t1 != undefined); - assert.ok(s1t2 != undefined); - assert.ok(suite2 != undefined); - assert.ok(s2t1 != undefined); - assert.ok(s2t2 != undefined); - assert.ok(s2t3 != undefined); - } - ], - [ - 'should run all', - async function() { - assert.equal(root.children.length, 2); - await adapter.run([root.id]); - - const running = {type: 'started', tests: [root.id]}; - - const s1running = { - type: 'suite', - state: 'running', - suite: suite1 - }; - const s1finished = { - type: 'suite', - state: 'completed', - suite: suite1 - }; - assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); - assert.ok(testStatesEvI(s1running) < testStatesEvI(s1finished)); - - const s2running = { - type: 'suite', - state: 'running', - suite: suite2 - }; - const s2finished = { - type: 'suite', - state: 'completed', - suite: suite2 - }; - assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); - assert.ok(testStatesEvI(s2running) < testStatesEvI(s2finished)); - - const s1t1running = { - type: 'test', - state: 'running', - test: s1t1 - }; - assert.ok( - testStatesEvI(s1running) < testStatesEvI(s1t1running)); - - const s1t1finished = { - type: 'test', - state: 'passed', - test: s1t1, - decorations: undefined, - message: 'Duration: 0.000132 second(s)\n' - }; - assert.ok( - testStatesEvI(s1t1running) < testStatesEvI(s1t1finished)); - assert.ok( - testStatesEvI(s1t1finished) < testStatesEvI(s1finished)); - - const s1t2running = { - type: 'test', - state: 'running', - test: s1t2 - }; - assert.ok( - testStatesEvI(s1running) < testStatesEvI(s1t2running)); - - const s1t2finished = { - type: 'test', - state: 'failed', - test: s1t2, - decorations: [{line: 14, message: 'Expanded: false'}], - message: - 'Duration: 0.000204 second(s)\n>>> s1t2(line: 13) REQUIRE (line: 15) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }; - assert.ok( - testStatesEvI(s1t2running) < testStatesEvI(s1t2finished)); - assert.ok( - testStatesEvI(s1t2finished) < testStatesEvI(s1finished)); - - const s2t1running = { - type: 'test', - state: 'running', - test: s2t1 - }; - assert.ok( - testStatesEvI(s2running) < testStatesEvI(s2t1running)); - - const s2t1finished = { - type: 'test', - state: 'passed', - test: s2t1, - decorations: undefined, - message: 'Duration: 0.00037 second(s)\n' - }; - assert.ok( - testStatesEvI(s2t1running) < testStatesEvI(s2t1finished)); - assert.ok( - testStatesEvI(s2t1finished) < testStatesEvI(s2finished)); - - const s2t2running = { - type: 'test', - state: 'running', - test: s2t2 - }; - assert.ok( - testStatesEvI(s2running) < testStatesEvI(s2t2running)); - - const s2t2finished = { - type: 'test', - state: 'skipped', - test: s2t2 - }; - assert.ok( - testStatesEvI(s2t2running) < testStatesEvI(s2t2finished)); - assert.ok( - testStatesEvI(s2t2finished) < testStatesEvI(s2finished)); - - const s2t3running = { - type: 'test', - state: 'running', - test: s2t3 - }; - assert.ok( - testStatesEvI(s2running) < testStatesEvI(s2t3running)); - - const s2t3finished = { - type: 'test', - state: 'failed', - test: s2t3, - decorations: [{line: 20, message: 'Expanded: false'}], - message: - 'Duration: 0.000178 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }; - assert.ok( - testStatesEvI(s2t3running) < testStatesEvI(s2t3finished)); - assert.ok( - testStatesEvI(s2t3finished) < testStatesEvI(s2finished)); - - const finished = {type: 'finished'}; - assert.ok(testStatesEvI(s1finished) < testStatesEvI(finished)); - assert.ok(testStatesEvI(s2finished) < testStatesEvI(finished)); - - assert.equal( - testStatesEvents.length, 16, inspect(testStatesEvents)); - } - ], - [ - 'should run with not existing test id', - async function() { - await adapter.run(['not existing id']); - - assert.deepStrictEqual(testStatesEvents, [ - {type: 'started', tests: ['not existing id']}, - {type: 'finished'}, - ]); - } - ], - [ - 'should run s1t1', - async function() { - await adapter.run([s1t1.id]); - const expected = [ - {type: 'started', tests: [s1t1.id]}, - {type: 'suite', state: 'running', suite: suite1}, - {type: 'test', state: 'running', test: s1t1}, - { - type: 'test', - state: 'passed', - test: s1t1, - decorations: undefined, - message: 'Duration: 0.000112 second(s)\n' - }, - {type: 'suite', state: 'completed', suite: suite1}, - {type: 'finished'}, - ]; - assert.deepStrictEqual(testStatesEvents, expected); - - await adapter.run([s1t1.id]); - assert.deepStrictEqual( - testStatesEvents, [...expected, ...expected]); - } - ], - [ - 'should run skipped s2t2', - async function() { - await adapter.run([s2t2.id]); - const expected = [ - {type: 'started', tests: [s2t2.id]}, - {type: 'suite', state: 'running', suite: suite2}, - {type: 'test', state: 'running', test: s2t2}, - { - type: 'test', - state: 'passed', - test: s2t2, - decorations: undefined, - message: 'Duration: 0.001294 second(s)\n' - }, - {type: 'suite', state: 'completed', suite: suite2}, - {type: 'finished'}, - ]; - assert.deepStrictEqual(testStatesEvents, expected); - - await adapter.run([s2t2.id]); - assert.deepStrictEqual( - testStatesEvents, [...expected, ...expected]); - } - ], - [ - 'should run failing test s2t3', - async function() { - await adapter.run([s2t3.id]); - const expected = [ - {type: 'started', tests: [s2t3.id]}, - {type: 'suite', state: 'running', suite: suite2}, - {type: 'test', state: 'running', test: s2t3}, - { - type: 'test', - state: 'failed', - test: s2t3, - decorations: [{line: 20, message: 'Expanded: false'}], - message: - 'Duration: 0.000596 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }, - {type: 'suite', state: 'completed', suite: suite2}, - {type: 'finished'}, - ]; - assert.deepStrictEqual(testStatesEvents, expected); - - await adapter.run([s2t3.id]); - assert.deepStrictEqual( - testStatesEvents, [...expected, ...expected]); - } - ], - [ - 'should run failing test s2t3 with chunks', - async function() { - const withArgs = spawnStub.withArgs( - example1.suite2.execPath, example1.suite2.t3.outputs[0][0]); - withArgs.onCall(withArgs.callCount) - .returns( - new ChildProcessStub(example1.suite2.t3.outputs[0][1])); - - await adapter.run([s2t3.id]); - const expected = [ - {type: 'started', tests: [s2t3.id]}, - {type: 'suite', state: 'running', suite: suite2}, - {type: 'test', state: 'running', test: s2t3}, - { + const testsForAdapterWithSuite1AndSuite2: + [string, Mocha.AsyncFunc|Mocha.Func][] = [ + [ + 'test variables are fine, suite1 and suite1 are loaded', + function() { + assert.equal(root.children.length, 2); + assert.ok(suite1 != undefined); + assert.ok(s1t1 != undefined); + assert.ok(s1t2 != undefined); + assert.ok(suite2 != undefined); + assert.ok(s2t1 != undefined); + assert.ok(s2t2 != undefined); + assert.ok(s2t3 != undefined); + } + ], + [ + 'should run all', + async function() { + assert.equal(root.children.length, 2); + await adapter.run([root.id]); + + const running = {type: 'started', tests: [root.id]}; + + const s1running = { + type: 'suite', + state: 'running', + suite: suite1 + }; + const s1finished = { + type: 'suite', + state: 'completed', + suite: suite1 + }; + assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); + assert.ok( + testStatesEvI(s1running) < testStatesEvI(s1finished)); + + const s2running = { + type: 'suite', + state: 'running', + suite: suite2 + }; + const s2finished = { + type: 'suite', + state: 'completed', + suite: suite2 + }; + assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); + assert.ok( + testStatesEvI(s2running) < testStatesEvI(s2finished)); + + const s1t1running = { type: 'test', - state: 'failed', - test: s2t3, - decorations: [{line: 20, message: 'Expanded: false'}], - message: - 'Duration: 0.000596 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }, - {type: 'suite', state: 'completed', suite: suite2}, - {type: 'finished'}, - ]; - assert.deepStrictEqual(testStatesEvents, expected); - - await adapter.run([s2t3.id]); - assert.deepStrictEqual( - testStatesEvents, [...expected, ...expected]); - } - ], - [ - 'should run suite1', - async function() { - await adapter.run([suite1.id]); - const expected = [ - {type: 'started', tests: [suite1.id]}, - {type: 'suite', state: 'running', suite: suite1}, - {type: 'test', state: 'running', test: s1t1}, - { + state: 'running', + test: s1t1 + }; + assert.ok( + testStatesEvI(s1running) < testStatesEvI(s1t1running)); + + const s1t1finished = { type: 'test', state: 'passed', test: s1t1, decorations: undefined, message: 'Duration: 0.000132 second(s)\n' - }, - {type: 'test', state: 'running', test: s1t2}, - { + }; + assert.ok( + testStatesEvI(s1t1running) < testStatesEvI(s1t1finished)); + assert.ok( + testStatesEvI(s1t1finished) < testStatesEvI(s1finished)); + + const s1t2running = { + type: 'test', + state: 'running', + test: s1t2 + }; + assert.ok( + testStatesEvI(s1running) < testStatesEvI(s1t2running)); + + const s1t2finished = { type: 'test', state: 'failed', test: s1t2, decorations: [{line: 14, message: 'Expanded: false'}], message: 'Duration: 0.000204 second(s)\n>>> s1t2(line: 13) REQUIRE (line: 15) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }, - {type: 'suite', state: 'completed', suite: suite1}, - {type: 'finished'}, - ]; - assert.deepStrictEqual(testStatesEvents, expected); - - await adapter.run([suite1.id]); - assert.deepStrictEqual( - testStatesEvents, [...expected, ...expected]); - } - ], - [ - 'should run with wrong xml', - async function() { - const m = - example1.suite1.t1.outputs[0][1].match(']+>'); - assert.notEqual(m, undefined); - assert.notEqual(m!.input, undefined); - assert.notEqual(m!.index, undefined); - const part = m!.input!.substr(0, m!.index! + m![0].length); - const withArgs = spawnStub.withArgs( - example1.suite1.execPath, example1.suite1.t1.outputs[0][0]); - withArgs.onCall(withArgs.callCount) - .returns(new ChildProcessStub(part)); - - await adapter.run([s1t1.id]); - - const expected = [ - {type: 'started', tests: [s1t1.id]}, - {type: 'suite', state: 'running', suite: suite1}, - {type: 'test', state: 'running', test: s1t1}, - { + }; + assert.ok( + testStatesEvI(s1t2running) < testStatesEvI(s1t2finished)); + assert.ok( + testStatesEvI(s1t2finished) < testStatesEvI(s1finished)); + + const s2t1running = { type: 'test', - state: 'failed', - test: s1t1, - message: 'Unexpected test error. (Is Catch2 crashed?)\n' - }, - {type: 'suite', state: 'completed', suite: suite1}, - {type: 'finished'}, - ]; - assert.deepStrictEqual(testStatesEvents, expected); - - // this tests the sinon stubs too - await adapter.run([s1t1.id]); - assert.deepStrictEqual(testStatesEvents, [ - ...expected, - {type: 'started', tests: [s1t1.id]}, - {type: 'suite', state: 'running', suite: suite1}, - {type: 'test', state: 'running', test: s1t1}, - { + state: 'running', + test: s2t1 + }; + assert.ok( + testStatesEvI(s2running) < testStatesEvI(s2t1running)); + + const s2t1finished = { type: 'test', state: 'passed', - test: s1t1, + test: s2t1, decorations: undefined, - message: 'Duration: 0.000112 second(s)\n' - }, - {type: 'suite', state: 'completed', suite: suite1}, - {type: 'finished'}, - ]); - } - ], - [ - 'should cancel without error', - function() { - adapter.cancel(); - } - ], - [ - 'cancel', - async function() { - let spyKill1: sinon.SinonSpy; - let spyKill2: sinon.SinonSpy; - { - const spawnEvent = - new ChildProcessStub(example1.suite1.outputs[2][1]); - spyKill1 = sinon.spy(spawnEvent, 'kill'); - const withArgs = spawnStub.withArgs( - example1.suite1.execPath, example1.suite1.outputs[2][0]); - withArgs.onCall(withArgs.callCount).returns(spawnEvent); + message: 'Duration: 0.00037 second(s)\n' + }; + assert.ok( + testStatesEvI(s2t1running) < testStatesEvI(s2t1finished)); + assert.ok( + testStatesEvI(s2t1finished) < testStatesEvI(s2finished)); + + const s2t2running = { + type: 'test', + state: 'running', + test: s2t2 + }; + assert.ok( + testStatesEvI(s2running) < testStatesEvI(s2t2running)); + + const s2t2finished = { + type: 'test', + state: 'skipped', + test: s2t2 + }; + assert.ok( + testStatesEvI(s2t2running) < testStatesEvI(s2t2finished)); + assert.ok( + testStatesEvI(s2t2finished) < testStatesEvI(s2finished)); + + const s2t3running = { + type: 'test', + state: 'running', + test: s2t3 + }; + assert.ok( + testStatesEvI(s2running) < testStatesEvI(s2t3running)); + + const s2t3finished = { + type: 'test', + state: 'failed', + test: s2t3, + decorations: [{line: 20, message: 'Expanded: false'}], + message: + 'Duration: 0.000178 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' + }; + assert.ok( + testStatesEvI(s2t3running) < testStatesEvI(s2t3finished)); + assert.ok( + testStatesEvI(s2t3finished) < testStatesEvI(s2finished)); + + const finished = {type: 'finished'}; + assert.ok( + testStatesEvI(s1finished) < testStatesEvI(finished)); + assert.ok( + testStatesEvI(s2finished) < testStatesEvI(finished)); + + assert.equal( + testStatesEvents.length, 16, inspect(testStatesEvents)); } - { - const spawnEvent = - new ChildProcessStub(example1.suite2.outputs[2][1]); - spyKill2 = sinon.spy(spawnEvent, 'kill'); - const withArgs = spawnStub.withArgs( - example1.suite2.execPath, example1.suite2.outputs[2][0]); - withArgs.onCall(withArgs.callCount).returns(spawnEvent); + ], + [ + 'should run with not existing test id', + async function() { + await adapter.run(['not existing id']); + + assert.deepStrictEqual(testStatesEvents, [ + {type: 'started', tests: ['not existing id']}, + {type: 'finished'}, + ]); + } + ], + [ + 'should run s1t1', + async function() { + await adapter.run([s1t1.id]); + const expected = [ + {type: 'started', tests: [s1t1.id]}, + {type: 'suite', state: 'running', suite: suite1}, + {type: 'test', state: 'running', test: s1t1}, + { + type: 'test', + state: 'passed', + test: s1t1, + decorations: undefined, + message: 'Duration: 0.000112 second(s)\n' + }, + {type: 'suite', state: 'completed', suite: suite1}, + {type: 'finished'}, + ]; + assert.deepStrictEqual(testStatesEvents, expected); + + await adapter.run([s1t1.id]); + assert.deepStrictEqual( + testStatesEvents, [...expected, ...expected]); + } + ], + [ + 'should run skipped s2t2', + async function() { + await adapter.run([s2t2.id]); + const expected = [ + {type: 'started', tests: [s2t2.id]}, + {type: 'suite', state: 'running', suite: suite2}, + {type: 'test', state: 'running', test: s2t2}, + { + type: 'test', + state: 'passed', + test: s2t2, + decorations: undefined, + message: 'Duration: 0.001294 second(s)\n' + }, + {type: 'suite', state: 'completed', suite: suite2}, + {type: 'finished'}, + ]; + assert.deepStrictEqual(testStatesEvents, expected); + + await adapter.run([s2t2.id]); + assert.deepStrictEqual( + testStatesEvents, [...expected, ...expected]); + } + ], + [ + 'should run failing test s2t3', + async function() { + await adapter.run([s2t3.id]); + const expected = [ + {type: 'started', tests: [s2t3.id]}, + {type: 'suite', state: 'running', suite: suite2}, + {type: 'test', state: 'running', test: s2t3}, + { + type: 'test', + state: 'failed', + test: s2t3, + decorations: [{line: 20, message: 'Expanded: false'}], + message: + 'Duration: 0.000596 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' + }, + {type: 'suite', state: 'completed', suite: suite2}, + {type: 'finished'}, + ]; + assert.deepStrictEqual(testStatesEvents, expected); + + await adapter.run([s2t3.id]); + assert.deepStrictEqual( + testStatesEvents, [...expected, ...expected]); } - const run = adapter.run([root.id]); - adapter.cancel(); - await run; - - assert.equal(spyKill1.callCount, 1); - assert.equal(spyKill2.callCount, 1); - - const running = {type: 'started', tests: [root.id]}; - - const s1running = { - type: 'suite', - state: 'running', - suite: suite1 - }; - const s1finished = { - type: 'suite', - state: 'completed', - suite: suite1 - }; - assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); - assert.ok(testStatesEvI(s1running) < testStatesEvI(s1finished)); - - const s2running = { - type: 'suite', - state: 'running', - suite: suite2 - }; - const s2finished = { - type: 'suite', - state: 'completed', - suite: suite2 - }; - assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); - assert.ok(testStatesEvI(s2running) < testStatesEvI(s2finished)); - - const s2t2running = { - type: 'test', - state: 'running', - test: s2t2 - }; - assert.ok( - testStatesEvI(s2running) < testStatesEvI(s2t2running)); - - const s2t2finished = { - type: 'test', - state: 'skipped', - test: s2t2 - }; - assert.ok( - testStatesEvI(s2t2running) < testStatesEvI(s2t2finished)); - assert.ok( - testStatesEvI(s2t2finished) < testStatesEvI(s2finished)); - - const finished = {type: 'finished'}; - assert.ok(testStatesEvI(s1finished) < testStatesEvI(finished)); - assert.ok(testStatesEvI(s2finished) < testStatesEvI(finished)); - - assert.equal( - testStatesEvents.length, 8, inspect(testStatesEvents)); - } - ], - [ - 'cancel after run finished', - function() { - let spyKill1: sinon.SinonSpy; - let spyKill2: sinon.SinonSpy; - { - const spawnEvent = - new ChildProcessStub(example1.suite1.outputs[2][1]); - spyKill1 = sinon.spy(spawnEvent, 'kill'); + ], + [ + 'should run failing test s2t3 with chunks', + async function() { const withArgs = spawnStub.withArgs( - example1.suite1.execPath, example1.suite1.outputs[2][0]); - withArgs.onCall(withArgs.callCount).returns(spawnEvent); + example1.suite2.execPath, + example1.suite2.t3.outputs[0][0]); + withArgs.onCall(withArgs.callCount) + .returns(new ChildProcessStub( + example1.suite2.t3.outputs[0][1])); + + await adapter.run([s2t3.id]); + const expected = [ + {type: 'started', tests: [s2t3.id]}, + {type: 'suite', state: 'running', suite: suite2}, + {type: 'test', state: 'running', test: s2t3}, + { + type: 'test', + state: 'failed', + test: s2t3, + decorations: [{line: 20, message: 'Expanded: false'}], + message: + 'Duration: 0.000596 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' + }, + {type: 'suite', state: 'completed', suite: suite2}, + {type: 'finished'}, + ]; + assert.deepStrictEqual(testStatesEvents, expected); + + await adapter.run([s2t3.id]); + assert.deepStrictEqual( + testStatesEvents, [...expected, ...expected]); } - { - const spawnEvent = - new ChildProcessStub(example1.suite2.outputs[2][1]); - spyKill2 = sinon.spy(spawnEvent, 'kill'); + ], + [ + 'should run suite1', + async function() { + await adapter.run([suite1.id]); + const expected = [ + {type: 'started', tests: [suite1.id]}, + {type: 'suite', state: 'running', suite: suite1}, + {type: 'test', state: 'running', test: s1t1}, + { + type: 'test', + state: 'passed', + test: s1t1, + decorations: undefined, + message: 'Duration: 0.000132 second(s)\n' + }, + {type: 'test', state: 'running', test: s1t2}, + { + type: 'test', + state: 'failed', + test: s1t2, + decorations: [{line: 14, message: 'Expanded: false'}], + message: + 'Duration: 0.000204 second(s)\n>>> s1t2(line: 13) REQUIRE (line: 15) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' + }, + {type: 'suite', state: 'completed', suite: suite1}, + {type: 'finished'}, + ]; + assert.deepStrictEqual(testStatesEvents, expected); + + await adapter.run([suite1.id]); + assert.deepStrictEqual( + testStatesEvents, [...expected, ...expected]); + } + ], + [ + 'should run with wrong xml', + async function() { + const m = + example1.suite1.t1.outputs[0][1].match(']+>'); + assert.notEqual(m, undefined); + assert.notEqual(m!.input, undefined); + assert.notEqual(m!.index, undefined); + const part = m!.input!.substr(0, m!.index! + m![0].length); const withArgs = spawnStub.withArgs( - example1.suite2.execPath, example1.suite2.outputs[2][0]); - withArgs.onCall(withArgs.callCount).returns(spawnEvent); + example1.suite1.execPath, + example1.suite1.t1.outputs[0][0]); + withArgs.onCall(withArgs.callCount) + .returns(new ChildProcessStub(part)); + + await adapter.run([s1t1.id]); + + const expected = [ + {type: 'started', tests: [s1t1.id]}, + {type: 'suite', state: 'running', suite: suite1}, + {type: 'test', state: 'running', test: s1t1}, + { + type: 'test', + state: 'failed', + test: s1t1, + message: 'Unexpected test error. (Is Catch2 crashed?)\n' + }, + {type: 'suite', state: 'completed', suite: suite1}, + {type: 'finished'}, + ]; + assert.deepStrictEqual(testStatesEvents, expected); + + // this tests the sinon stubs too + await adapter.run([s1t1.id]); + assert.deepStrictEqual(testStatesEvents, [ + ...expected, + {type: 'started', tests: [s1t1.id]}, + {type: 'suite', state: 'running', suite: suite1}, + {type: 'test', state: 'running', test: s1t1}, + { + type: 'test', + state: 'passed', + test: s1t1, + decorations: undefined, + message: 'Duration: 0.000112 second(s)\n' + }, + {type: 'suite', state: 'completed', suite: suite1}, + {type: 'finished'}, + ]); } - const run = adapter.run([root.id]); - return run.then(function() { + ], + [ + 'should cancel without error', + function() { adapter.cancel(); - assert.equal(spyKill1.callCount, 0); - assert.equal(spyKill2.callCount, 0); - }); - } - ], - [ - 'reload because of fswatcher event', - async function(this: Mocha.Context) { - assert.equal(watchers.size, 2); - assert.ok(watchers.has(example1.suite1.execPath)); - const suite1Watcher = watchers.get(example1.suite1.execPath)!; - assert.equal(testsEvents.length, 0); - - const waitForReload = async(): Promise => { - let tryCount: number = 20; - while (testsEvents.length != 2 && --tryCount > 0) - await promisify(setTimeout)(20); - assert.equal(testsEvents.length, 2); - const e = testsEvents.pop()!; - testsEvents.pop(); - assert.equal(e.type, 'finished'); - assert.ok(e.suite != undefined); - return e.suite!; - }; - - const oldRootSuites = [...root.children]; - const oldSuite1Tests = [...suite1.children]; - suite1Watcher.emit( - 'change', 'dummyEvent', example1.suite1.execPath); - const newRoot = await waitForReload(); - - assert.deepStrictEqual(newRoot, root); - } - ], - [ - 'reload because of fswatcher event, file is deleted', - async function(this: Mocha.Context) { - - } - ], - [ - 'reload because of fswatcher event, new test in file', - async function(this: Mocha.Context) { - - } - ], - [ - 'reload because of fswatcher event, one test deleted from file', - async function(this: Mocha.Context) { - - } - ], - ]; - - context( - 'executables=["execPath1", "${workspaceFolder}/execPath2"]', - function() { - before(function() { - return updateConfig( - 'executables', ['execPath1', '${workspaceFolder}/execPath2']); - }); - - after(function() { - return updateConfig('executables', undefined); - }); + } + ], + [ + 'cancel', + async function() { + let spyKill1: sinon.SinonSpy; + let spyKill2: sinon.SinonSpy; + { + const spawnEvent = + new ChildProcessStub(example1.suite1.outputs[2][1]); + spyKill1 = sinon.spy(spawnEvent, 'kill'); + const withArgs = spawnStub.withArgs( + example1.suite1.execPath, + example1.suite1.outputs[2][0]); + withArgs.onCall(withArgs.callCount).returns(spawnEvent); + } + { + const spawnEvent = + new ChildProcessStub(example1.suite2.outputs[2][1]); + spyKill2 = sinon.spy(spawnEvent, 'kill'); + const withArgs = spawnStub.withArgs( + example1.suite2.execPath, + example1.suite2.outputs[2][0]); + withArgs.onCall(withArgs.callCount).returns(spawnEvent); + } + const run = adapter.run([root.id]); + adapter.cancel(); + await run; + + assert.equal(spyKill1.callCount, 1); + assert.equal(spyKill2.callCount, 1); + + const running = {type: 'started', tests: [root.id]}; + + const s1running = { + type: 'suite', + state: 'running', + suite: suite1 + }; + const s1finished = { + type: 'suite', + state: 'completed', + suite: suite1 + }; + assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); + assert.ok( + testStatesEvI(s1running) < testStatesEvI(s1finished)); + + const s2running = { + type: 'suite', + state: 'running', + suite: suite2 + }; + const s2finished = { + type: 'suite', + state: 'completed', + suite: suite2 + }; + assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); + assert.ok( + testStatesEvI(s2running) < testStatesEvI(s2finished)); + + const s2t2running = { + type: 'test', + state: 'running', + test: s2t2 + }; + assert.ok( + testStatesEvI(s2running) < testStatesEvI(s2t2running)); - beforeEach(async function() { - example1.suite1.assert( - 'execPath1', ['s1t1', 's1t2'], suite1, uniqueIdC); + const s2t2finished = { + type: 'test', + state: 'skipped', + test: s2t2 + }; + assert.ok( + testStatesEvI(s2t2running) < testStatesEvI(s2t2finished)); + assert.ok( + testStatesEvI(s2t2finished) < testStatesEvI(s2finished)); + + const finished = {type: 'finished'}; + assert.ok( + testStatesEvI(s1finished) < testStatesEvI(finished)); + assert.ok( + testStatesEvI(s2finished) < testStatesEvI(finished)); - example1.suite2.assert( - path.join(workspaceFolderUri.path, 'execPath2'), - ['s2t1', 's2t2 [.]', 's2t3'], suite2, uniqueIdC); + assert.equal( + testStatesEvents.length, 8, inspect(testStatesEvents)); + } + ], + [ + 'cancel after run finished', + function() { + let spyKill1: sinon.SinonSpy; + let spyKill2: sinon.SinonSpy; + { + const spawnEvent = + new ChildProcessStub(example1.suite1.outputs[2][1]); + spyKill1 = sinon.spy(spawnEvent, 'kill'); + const withArgs = spawnStub.withArgs( + example1.suite1.execPath, + example1.suite1.outputs[2][0]); + withArgs.onCall(withArgs.callCount).returns(spawnEvent); + } + { + const spawnEvent = + new ChildProcessStub(example1.suite2.outputs[2][1]); + spyKill2 = sinon.spy(spawnEvent, 'kill'); + const withArgs = spawnStub.withArgs( + example1.suite2.execPath, + example1.suite2.outputs[2][0]); + withArgs.onCall(withArgs.callCount).returns(spawnEvent); + } + const run = adapter.run([root.id]); + return run.then(function() { + adapter.cancel(); + assert.equal(spyKill1.callCount, 0); + assert.equal(spyKill2.callCount, 0); + }); + } + ], + [ + 'reload because of fswatcher event', + async function(this: Mocha.Context) { + this.slow(150); + const doAndWaitForReload = + async function(action: Function): Promise { + const origCount = testsEvents.length; + await action(); + let tryCount: number = 20; + while (testsEvents.length != origCount + 2 && + --tryCount > 0) + await promisify(setTimeout)(20); + assert.equal(testsEvents.length, origCount + 2); + const e = + testsEvents[testsEvents.length - 1]!; + assert.equal(e.type, 'finished'); + assert.ok(e.suite != undefined); + return e.suite!; + }; + + assert.equal(watchers.size, 2); + assert.ok(watchers.has(example1.suite1.execPath)); + const suite1Watcher = watchers.get(example1.suite1.execPath)!; + + { // touch + const newRoot = await doAndWaitForReload(async () => { + suite1Watcher.emit( + 'change', 'dummyEvent', example1.suite1.execPath); + }); + assert.deepStrictEqual(newRoot, root); + } + + { // test added + const testListOutput = + example1.suite1.outputs[1][1].split('\n'); + assert.equal(testListOutput.length, 10); + testListOutput.splice( + 1, 0, ' s1t0', ' suite1.cpp:6', ' tag1'); + const withArgs = spawnStub.withArgs( + example1.suite1.execPath, + example1.suite1.outputs[1][0]); + withArgs.onCall(withArgs.callCount) + .returns( + new ChildProcessStub(testListOutput.join('\n'))); + + const oldRootChildren = [...root.children]; + const oldSuite1Children = [...suite1.children]; + const oldSuite2Children = [...suite2.children]; + + const newRoot = await doAndWaitForReload(async () => { + suite1Watcher.emit( + 'change', 'dummyEvent', example1.suite1.execPath); + }); + + assert.equal(newRoot, root); + assert.equal(root.children.length, oldRootChildren.length); + for (let i = 0; i < oldRootChildren.length; i++) { + assert.equal(root.children[i], oldRootChildren[i]); + } + + assert.equal( + suite1.children.length, oldSuite1Children.length + 1); + for (let i = 0; i < suite1.children.length; i++) { + assert.equal( + suite1.children[i + 1], oldSuite1Children[i]); + } + const newTest = suite1.children[0]; + assert.ok(!uniqueIdC.has(newTest.id)); + assert.equal(newTest.label, 's1t0'); + + assert.equal( + suite2.children.length, oldSuite2Children.length); + for (let i = 0; i < suite2.children.length; i++) { + assert.equal(suite2.children[i], oldSuite2Children[i]); + } + } + { // test deleted + const oldRootChildren = [...root.children]; + const oldSuite1Children = [...suite1.children]; + const oldSuite2Children = [...suite2.children]; + + const newRoot = await doAndWaitForReload(async () => { + suite1Watcher.emit( + 'change', 'dummyEvent', example1.suite1.execPath); + }); + + assert.equal(newRoot, root); + assert.equal(root.children.length, oldRootChildren.length); + for (let i = 0; i < oldRootChildren.length; i++) { + assert.equal(root.children[i], oldRootChildren[i]); + } + + assert.equal( + suite1.children.length + 1, oldSuite1Children.length); + for (let i = 0; i < suite1.children.length; i++) { + assert.equal( + suite1.children[i], oldSuite1Children[i + 1]); + } + const deletedTest = oldSuite1Children[0]; + assert.equal(deletedTest.label, 's1t0'); + + assert.equal( + suite2.children.length, oldSuite2Children.length); + for (let i = 0; i < suite2.children.length; i++) { + assert.equal(suite2.children[i], oldSuite2Children[i]); + } + } + } + ], + ]; + + context( + 'executables=["execPath1", "${workspaceFolder}/execPath2"]', + function() { + before(function() { + return updateConfig( + 'executables', + ['execPath1', '${workspaceFolder}/execPath2']); + }); + + after(function() { + return updateConfig('executables', undefined); + }); + + beforeEach(async function() { + example1.suite1.assert( + 'execPath1', ['s1t1', 's1t2'], suite1, uniqueIdC); + + example1.suite2.assert( + path.join(workspaceFolderUri.path, 'execPath2'), + ['s2t1', 's2t2 [.]', 's2t3'], suite2, uniqueIdC); + }) + + for (let t of testsForAdapterWithSuite1AndSuite2) it(t[0], t[1]); }) - for (let t of testsForAdapterWithSuite1AndSuite2) it(t[0], t[1]); - }) + context('executables=[{}] and env={...}', function() { + before(async function() { + await updateConfig('executables', [{ + name: '${dirname}: ${name} (${absDirname})', + path: '.', + regex: 'execPath(1|2)', + cwd: '${workspaceFolder}/cwd', + env: { + 'C2LOCALTESTENV': 'c2localtestenv', + 'C2OVERRIDETESTENV': 'c2overridetestenv-l', + } + }]); + await updateConfig('defaultEnv', { + 'C2GLOBALTESTENV': 'c2globaltestenv', + 'C2OVERRIDETESTENV': 'c2overridetestenv-g', + }); + }); - context('executables=[{}] and env={...}', function() { - before(async function() { - await updateConfig('executables', [{ - name: '${dirname}: ${name} (${absDirname})', - path: '.', - regex: 'execPath(1|2)', - cwd: '${workspaceFolder}/cwd', - env: { - 'C2LOCALTESTENV': 'c2localtestenv', - 'C2OVERRIDETESTENV': 'c2overridetestenv-l', - } - }]); - await updateConfig('defaultEnv', { - 'C2GLOBALTESTENV': 'c2globaltestenv', - 'C2OVERRIDETESTENV': 'c2overridetestenv-g', + after(async function() { + await updateConfig('executables', undefined); + await updateConfig('defaultEnv', undefined); }); - }); - after(async function() { - await updateConfig('executables', undefined); - await updateConfig('defaultEnv', undefined); - }); + beforeEach(async function() { + example1.suite1.assert( + ': execPath1 (' + workspaceFolderUri.path + ')', + ['s1t1', 's1t2'], suite1, uniqueIdC); - beforeEach(async function() { - example1.suite1.assert( - ': execPath1 (' + workspaceFolderUri.path + ')', ['s1t1', 's1t2'], - suite1, uniqueIdC); + example1.suite2.assert( + ': execPath2 (' + workspaceFolderUri.path + ')', + ['s2t1', 's2t2 [.]', 's2t3'], suite2, uniqueIdC); + }) - example1.suite2.assert( - ': execPath2 (' + workspaceFolderUri.path + ')', - ['s2t1', 's2t2 [.]', 's2t3'], suite2, uniqueIdC); + for (let t of testsForAdapterWithSuite1AndSuite2) it(t[0], t[1]); + + it('should get execution options', async function() { + { + const withArgs = spawnStub.withArgs( + example1.suite1.execPath, sinon.match.any, sinon.match.any); + withArgs.onCall(withArgs.callCount) + .callsFake((p: string, args: string[], ops: any) => { + assert.equal( + ops.cwd, path.join(workspaceFolderUri.path, 'cwd')); + assert.equal(ops.env.C2LOCALTESTENV, 'c2localtestenv'); + assert.ok(!ops.env.hasOwnProperty('C2GLOBALTESTENV')); + assert.equal( + ops.env.C2OVERRIDETESTENV, 'c2overridetestenv-l'); + return new ChildProcessStub(example1.suite1.outputs[2][1]); + }); + + await adapter.run([suite1.id]); + } + { + const withArgs = spawnStub.withArgs( + example1.suite2.execPath, sinon.match.any, sinon.match.any); + withArgs.onCall(withArgs.callCount) + .callsFake((p: string, args: string[], ops: any) => { + assert.equal( + ops.cwd, path.join(workspaceFolderUri.path, 'cwd')); + assert.equal(ops.env.C2LOCALTESTENV, 'c2localtestenv'); + assert.ok(!ops.env.hasOwnProperty('C2GLOBALTESTENV')); + assert.equal( + ops.env.C2OVERRIDETESTENV, 'c2overridetestenv-l'); + return new ChildProcessStub(example1.suite2.outputs[2][1]); + }); + + await adapter.run([suite2.id]); + } + }) }) + }) + }) - for (let t of testsForAdapterWithSuite1AndSuite2) it(t[0], t[1]); + specify('load executables=', async function() { + this.slow(300); + await updateConfig('executables', example1.suite1.execPath); + adapter = createAdapterAndSubscribe(); + await adapter.load(); + assert.equal(testsEvents.length, 2); + assert.equal( + (testsEvents[testsEvents.length - 1]) + .suite!.children.length, + 1); + await updateConfig('executables', undefined); + }) - it('should get execution options', async function() { - { - const withArgs = spawnStub.withArgs( - example1.suite1.execPath, sinon.match.any, sinon.match.any); - withArgs.onCall(withArgs.callCount) - .callsFake((p: string, args: string[], ops: any) => { - assert.equal( - ops.cwd, path.join(workspaceFolderUri.path, 'cwd')); - assert.equal(ops.env.C2LOCALTESTENV, 'c2localtestenv'); - assert.ok(!ops.env.hasOwnProperty('C2GLOBALTESTENV')); - assert.equal( - ops.env.C2OVERRIDETESTENV, 'c2overridetestenv-l'); - return new ChildProcessStub(example1.suite1.outputs[2][1]); - }); + specify( + 'load executables=["execPath1", "execPath2"] with error', + async function() { + this.slow(300); + await updateConfig('executables', ['execPath1', 'execPath2']) + adapter = createAdapterAndSubscribe(); - await adapter.run([suite1.id]); - } - { - const withArgs = spawnStub.withArgs( - example1.suite2.execPath, sinon.match.any, sinon.match.any); - withArgs.onCall(withArgs.callCount) - .callsFake((p: string, args: string[], ops: any) => { - assert.equal( - ops.cwd, path.join(workspaceFolderUri.path, 'cwd')); - assert.equal(ops.env.C2LOCALTESTENV, 'c2localtestenv'); - assert.ok(!ops.env.hasOwnProperty('C2GLOBALTESTENV')); - assert.equal( - ops.env.C2OVERRIDETESTENV, 'c2overridetestenv-l'); - return new ChildProcessStub(example1.suite2.outputs[2][1]); - }); + const withArgs = spawnStub.withArgs( + example1.suite2.execPath, example1.suite2.outputs[1][0]); + withArgs.onCall(withArgs.callCount).throws( + 'dummy error for testing (should be handled)'); - await adapter.run([suite2.id]); - } - }); - }) - }) + await adapter.load(); + + await updateConfig('executables', undefined); + }) }) }) \ No newline at end of file From 8d8e3e1635be85dafa2339653d5340053d1120a9 Mon Sep 17 00:00:00 2001 From: Mate Pek Date: Tue, 23 Oct 2018 14:45:12 +0200 Subject: [PATCH 08/18] more refactor --- src/test/C2TestAdapter.test.ts | 1275 ++++++++++++++++---------------- 1 file changed, 630 insertions(+), 645 deletions(-) diff --git a/src/test/C2TestAdapter.test.ts b/src/test/C2TestAdapter.test.ts index a5ed78f8..6c40fbc0 100644 --- a/src/test/C2TestAdapter.test.ts +++ b/src/test/C2TestAdapter.test.ts @@ -20,6 +20,7 @@ import {C2TestAdapter} from '../C2TestAdapter'; import {example1} from './example1'; import {ChildProcessStub} from './Helpers'; import * as c2fs from '../FsWrapper'; +import * as Mocha from 'mocha'; assert.notEqual(vscode.workspace.workspaceFolders, undefined); assert.equal(vscode.workspace.workspaceFolders!.length, 1); @@ -29,10 +30,6 @@ const workspaceFolderUri = vscode.workspace.workspaceFolders![0].uri; const workspaceFolder = vscode.workspace.getWorkspaceFolder(workspaceFolderUri)!; -const workspaceFolderMatcher = - sinon.match(new RegExp('out(/|\\\\)test')) - .and(sinon.match(new RegExp('^((?!\\.vscode).)*$'))); - const logger = new Log('Catch2TestAdapter', workspaceFolder, 'Catch2TestAdapter'); @@ -118,6 +115,20 @@ describe('C2TestAdapter', function() { return adapter!; } + async function doAndWaitForReloadEvent(action: Function): + Promise { + const origCount = testsEvents.length; + await action(); + let tryCount: number = 40; + while (testsEvents.length != origCount + 2 && --tryCount > 0) + await promisify(setTimeout)(10); + assert.equal(testsEvents.length, origCount + 2); + const e = testsEvents[testsEvents.length - 1]!; + assert.equal(e.type, 'finished'); + assert.ok(e.suite != undefined); + return e.suite!; + } + function disposeAdapterAndSubscribers() { adapter && adapter.dispose(); testsEventsConnection && testsEventsConnection.dispose(); @@ -129,23 +140,10 @@ describe('C2TestAdapter', function() { function stubsResetToMyDefault() { spawnStub.reset(); spawnStub.callThrough(); - spawnStub.withArgs(workspaceFolderMatcher).callsFake((...args: any[]) => { - throw new Error(inspect(['spawnStub', args])); - }); - fsWatchStub.reset(); fsWatchStub.callThrough(); - fsWatchStub.withArgs(workspaceFolderMatcher).callsFake((...args: any[]) => { - throw new Error(inspect(['fsWatchStub', args])); - }); - fsExistsStub.reset(); fsExistsStub.callThrough(); - fsExistsStub.withArgs(workspaceFolderMatcher) - .callsFake((...args: any[]) => { - throw new Error(inspect(['fsExistsStub', args])); - }); - c2fsReaddirSyncStub.reset(); c2fsReaddirSyncStub.callThrough(); c2fsStatSyncStub.reset(); @@ -193,42 +191,22 @@ describe('C2TestAdapter', function() { return resetConfig(); }) - describe('expectation to (re)load', function() { - afterEach(function() { - const waitForReloadAndAsser = (tryCount: number): Promise => { - if (testsEvents.length < 2) - return new Promise(r => setTimeout(r, 10)).then(function() { - waitForReloadAndAsser(tryCount - 1) - }); - else { - assert.equal(testsEvents.length, 2); - assert.equal(testsEvents[0].type, 'started'); - assert.equal(testsEvents[1].type, 'finished'); - const suite = (testsEvents[1]).suite; - assert.notEqual(suite, undefined); - assert.equal(suite!.children.length, 0); - - // cleanup - testsEvents.pop(); - testsEvents.pop(); - - return Promise.resolve(); - } - }; - return waitForReloadAndAsser(20); - }) - - it('workerMaxNumber', function() { + it('workerMaxNumber', function() { + return doAndWaitForReloadEvent(() => { return updateConfig('workerMaxNumber', 42); - }) + }); + }) - it('defaultEnv', function() { + it('defaultEnv', function() { + return doAndWaitForReloadEvent(() => { return updateConfig('defaultEnv', {'APPLE': 'apple'}); - }) + }); + }) - it('defaultCwd', function() { + it('defaultCwd', function() { + return doAndWaitForReloadEvent(() => { return updateConfig('defaultCwd', 'apple/peach'); - }) + }); }) it('enableSourceDecoration', function() { @@ -266,31 +244,18 @@ describe('C2TestAdapter', function() { return new ChildProcessStub(scenario[1]); }); } - } - - const exists = (path: string) => { - return example1.outputs.findIndex((v) => { - return v[0] == path; - }) != -1; - }; - - fsExistsStub.withArgs(workspaceFolderMatcher) - .callsFake(function( - path: string, cb: (err: any, exists: boolean) => void) { - cb(undefined, exists(path)); - }); - - fsWatchStub.withArgs(workspaceFolderMatcher).callsFake((path: string) => { - if (exists(path)) { - const ee = new class extends EventEmitter { + fsExistsStub.withArgs(suite[0]).callsFake(function( + path: string, cb: (err: any, exists: boolean) => void) { + cb(undefined, true); + }); + fsWatchStub.withArgs(suite[0]).callsFake((path: string) => { + const e = new class extends EventEmitter { close() {} }; - watchers.set(path, ee); - return ee; - } else { - throw Error('File not found?'); - } - }); + watchers.set(path, e); + return e; + }); + } const dirContent: Map = new Map(); for (let p of example1.outputs) { @@ -340,6 +305,8 @@ describe('C2TestAdapter', function() { }) describe('load', function() { + this.enableTimeouts(false); //TODO + const uniqueIdC = new Set(); let adapter: TestAdapter; @@ -564,7 +531,9 @@ describe('C2TestAdapter', function() { }) }) - context('suite1 and suite2 are used', function() { + context.only('suite1 and suite2 are used', function() { + let suite1Watcher: EventEmitter; + beforeEach(function() { assert.equal(root.children.length, 2); @@ -592,609 +561,585 @@ describe('C2TestAdapter', function() { s2t2 = suite2.children[1]; assert.equal(suite2.children[2].type, 'test'); s2t3 = suite2.children[2]; + + assert.equal(watchers.size, 2); + assert.ok(watchers.has(example1.suite1.execPath)); + suite1Watcher = watchers.get(example1.suite1.execPath)!; }) - const testsForAdapterWithSuite1AndSuite2: - [string, Mocha.AsyncFunc|Mocha.Func][] = [ - [ - 'test variables are fine, suite1 and suite1 are loaded', - function() { - assert.equal(root.children.length, 2); - assert.ok(suite1 != undefined); - assert.ok(s1t1 != undefined); - assert.ok(s1t2 != undefined); - assert.ok(suite2 != undefined); - assert.ok(s2t1 != undefined); - assert.ok(s2t2 != undefined); - assert.ok(s2t3 != undefined); - } - ], - [ - 'should run all', - async function() { - assert.equal(root.children.length, 2); - await adapter.run([root.id]); - - const running = {type: 'started', tests: [root.id]}; - - const s1running = { - type: 'suite', - state: 'running', - suite: suite1 - }; - const s1finished = { - type: 'suite', - state: 'completed', - suite: suite1 - }; - assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); - assert.ok( - testStatesEvI(s1running) < testStatesEvI(s1finished)); - - const s2running = { - type: 'suite', - state: 'running', - suite: suite2 - }; - const s2finished = { - type: 'suite', - state: 'completed', - suite: suite2 - }; - assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); - assert.ok( - testStatesEvI(s2running) < testStatesEvI(s2finished)); - - const s1t1running = { + const testsForAdapterWithSuite1AndSuite2: Mocha.Test[] = [ + new Mocha.Test( + 'test variables are fine, suite1 and suite1 are loaded', + function() { + assert.equal(root.children.length, 2); + assert.ok(suite1 != undefined); + assert.ok(s1t1 != undefined); + assert.ok(s1t2 != undefined); + assert.ok(suite2 != undefined); + assert.ok(s2t1 != undefined); + assert.ok(s2t2 != undefined); + assert.ok(s2t3 != undefined); + }), + new Mocha.Test( + 'should run all', + async function() { + assert.equal(root.children.length, 2); + await adapter.run([root.id]); + + const running = {type: 'started', tests: [root.id]}; + + const s1running = { + type: 'suite', + state: 'running', + suite: suite1 + }; + const s1finished = { + type: 'suite', + state: 'completed', + suite: suite1 + }; + assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); + assert.ok(testStatesEvI(s1running) < testStatesEvI(s1finished)); + + const s2running = { + type: 'suite', + state: 'running', + suite: suite2 + }; + const s2finished = { + type: 'suite', + state: 'completed', + suite: suite2 + }; + assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); + assert.ok(testStatesEvI(s2running) < testStatesEvI(s2finished)); + + const s1t1running = { + type: 'test', + state: 'running', + test: s1t1 + }; + assert.ok( + testStatesEvI(s1running) < testStatesEvI(s1t1running)); + + const s1t1finished = { + type: 'test', + state: 'passed', + test: s1t1, + decorations: undefined, + message: 'Duration: 0.000132 second(s)\n' + }; + assert.ok( + testStatesEvI(s1t1running) < testStatesEvI(s1t1finished)); + assert.ok( + testStatesEvI(s1t1finished) < testStatesEvI(s1finished)); + + const s1t2running = { + type: 'test', + state: 'running', + test: s1t2 + }; + assert.ok( + testStatesEvI(s1running) < testStatesEvI(s1t2running)); + + const s1t2finished = { + type: 'test', + state: 'failed', + test: s1t2, + decorations: [{line: 14, message: 'Expanded: false'}], + message: + 'Duration: 0.000204 second(s)\n>>> s1t2(line: 13) REQUIRE (line: 15) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' + }; + assert.ok( + testStatesEvI(s1t2running) < testStatesEvI(s1t2finished)); + assert.ok( + testStatesEvI(s1t2finished) < testStatesEvI(s1finished)); + + const s2t1running = { + type: 'test', + state: 'running', + test: s2t1 + }; + assert.ok( + testStatesEvI(s2running) < testStatesEvI(s2t1running)); + + const s2t1finished = { + type: 'test', + state: 'passed', + test: s2t1, + decorations: undefined, + message: 'Duration: 0.00037 second(s)\n' + }; + assert.ok( + testStatesEvI(s2t1running) < testStatesEvI(s2t1finished)); + assert.ok( + testStatesEvI(s2t1finished) < testStatesEvI(s2finished)); + + const s2t2running = { + type: 'test', + state: 'running', + test: s2t2 + }; + assert.ok( + testStatesEvI(s2running) < testStatesEvI(s2t2running)); + + const s2t2finished = { + type: 'test', + state: 'skipped', + test: s2t2 + }; + assert.ok( + testStatesEvI(s2t2running) < testStatesEvI(s2t2finished)); + assert.ok( + testStatesEvI(s2t2finished) < testStatesEvI(s2finished)); + + const s2t3running = { + type: 'test', + state: 'running', + test: s2t3 + }; + assert.ok( + testStatesEvI(s2running) < testStatesEvI(s2t3running)); + + const s2t3finished = { + type: 'test', + state: 'failed', + test: s2t3, + decorations: [{line: 20, message: 'Expanded: false'}], + message: + 'Duration: 0.000178 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' + }; + assert.ok( + testStatesEvI(s2t3running) < testStatesEvI(s2t3finished)); + assert.ok( + testStatesEvI(s2t3finished) < testStatesEvI(s2finished)); + + const finished = {type: 'finished'}; + assert.ok(testStatesEvI(s1finished) < testStatesEvI(finished)); + assert.ok(testStatesEvI(s2finished) < testStatesEvI(finished)); + + assert.equal( + testStatesEvents.length, 16, inspect(testStatesEvents)); + }), + new Mocha.Test( + 'should run with not existing test id', + async function() { + await adapter.run(['not existing id']); + + assert.deepStrictEqual(testStatesEvents, [ + {type: 'started', tests: ['not existing id']}, + {type: 'finished'}, + ]); + }), + new Mocha.Test( + 'should run s1t1', + async function() { + await adapter.run([s1t1.id]); + const expected = [ + {type: 'started', tests: [s1t1.id]}, + {type: 'suite', state: 'running', suite: suite1}, + {type: 'test', state: 'running', test: s1t1}, + { type: 'test', - state: 'running', - test: s1t1 - }; - assert.ok( - testStatesEvI(s1running) < testStatesEvI(s1t1running)); - - const s1t1finished = { + state: 'passed', + test: s1t1, + decorations: undefined, + message: 'Duration: 0.000112 second(s)\n' + }, + {type: 'suite', state: 'completed', suite: suite1}, + {type: 'finished'}, + ]; + assert.deepStrictEqual(testStatesEvents, expected); + + await adapter.run([s1t1.id]); + assert.deepStrictEqual( + testStatesEvents, [...expected, ...expected]); + }), + new Mocha.Test( + 'should run skipped s2t2', + async function() { + await adapter.run([s2t2.id]); + const expected = [ + {type: 'started', tests: [s2t2.id]}, + {type: 'suite', state: 'running', suite: suite2}, + {type: 'test', state: 'running', test: s2t2}, + { + type: 'test', + state: 'passed', + test: s2t2, + decorations: undefined, + message: 'Duration: 0.001294 second(s)\n' + }, + {type: 'suite', state: 'completed', suite: suite2}, + {type: 'finished'}, + ]; + assert.deepStrictEqual(testStatesEvents, expected); + + await adapter.run([s2t2.id]); + assert.deepStrictEqual( + testStatesEvents, [...expected, ...expected]); + }), + new Mocha.Test( + 'should run failing test s2t3', + async function() { + await adapter.run([s2t3.id]); + const expected = [ + {type: 'started', tests: [s2t3.id]}, + {type: 'suite', state: 'running', suite: suite2}, + {type: 'test', state: 'running', test: s2t3}, + { + type: 'test', + state: 'failed', + test: s2t3, + decorations: [{line: 20, message: 'Expanded: false'}], + message: + 'Duration: 0.000596 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' + }, + {type: 'suite', state: 'completed', suite: suite2}, + {type: 'finished'}, + ]; + assert.deepStrictEqual(testStatesEvents, expected); + + await adapter.run([s2t3.id]); + assert.deepStrictEqual( + testStatesEvents, [...expected, ...expected]); + }), + new Mocha.Test( + 'should run failing test s2t3 with chunks', + async function() { + const withArgs = spawnStub.withArgs( + example1.suite2.execPath, example1.suite2.t3.outputs[0][0]); + withArgs.onCall(withArgs.callCount) + .returns( + new ChildProcessStub(example1.suite2.t3.outputs[0][1])); + + await adapter.run([s2t3.id]); + const expected = [ + {type: 'started', tests: [s2t3.id]}, + {type: 'suite', state: 'running', suite: suite2}, + {type: 'test', state: 'running', test: s2t3}, + { + type: 'test', + state: 'failed', + test: s2t3, + decorations: [{line: 20, message: 'Expanded: false'}], + message: + 'Duration: 0.000596 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' + }, + {type: 'suite', state: 'completed', suite: suite2}, + {type: 'finished'}, + ]; + assert.deepStrictEqual(testStatesEvents, expected); + + await adapter.run([s2t3.id]); + assert.deepStrictEqual( + testStatesEvents, [...expected, ...expected]); + }), + new Mocha.Test( + 'should run suite1', + async function() { + await adapter.run([suite1.id]); + const expected = [ + {type: 'started', tests: [suite1.id]}, + {type: 'suite', state: 'running', suite: suite1}, + {type: 'test', state: 'running', test: s1t1}, + { type: 'test', state: 'passed', test: s1t1, decorations: undefined, message: 'Duration: 0.000132 second(s)\n' - }; - assert.ok( - testStatesEvI(s1t1running) < testStatesEvI(s1t1finished)); - assert.ok( - testStatesEvI(s1t1finished) < testStatesEvI(s1finished)); - - const s1t2running = { - type: 'test', - state: 'running', - test: s1t2 - }; - assert.ok( - testStatesEvI(s1running) < testStatesEvI(s1t2running)); - - const s1t2finished = { + }, + {type: 'test', state: 'running', test: s1t2}, + { type: 'test', state: 'failed', test: s1t2, decorations: [{line: 14, message: 'Expanded: false'}], message: 'Duration: 0.000204 second(s)\n>>> s1t2(line: 13) REQUIRE (line: 15) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }; - assert.ok( - testStatesEvI(s1t2running) < testStatesEvI(s1t2finished)); - assert.ok( - testStatesEvI(s1t2finished) < testStatesEvI(s1finished)); - - const s2t1running = { + }, + {type: 'suite', state: 'completed', suite: suite1}, + {type: 'finished'}, + ]; + assert.deepStrictEqual(testStatesEvents, expected); + + await adapter.run([suite1.id]); + assert.deepStrictEqual( + testStatesEvents, [...expected, ...expected]); + }), + new Mocha.Test( + 'should run with wrong xml', + async function() { + const m = + example1.suite1.t1.outputs[0][1].match(']+>'); + assert.notEqual(m, undefined); + assert.notEqual(m!.input, undefined); + assert.notEqual(m!.index, undefined); + const part = m!.input!.substr(0, m!.index! + m![0].length); + const withArgs = spawnStub.withArgs( + example1.suite1.execPath, example1.suite1.t1.outputs[0][0]); + withArgs.onCall(withArgs.callCount) + .returns(new ChildProcessStub(part)); + + await adapter.run([s1t1.id]); + + const expected = [ + {type: 'started', tests: [s1t1.id]}, + {type: 'suite', state: 'running', suite: suite1}, + {type: 'test', state: 'running', test: s1t1}, + { type: 'test', - state: 'running', - test: s2t1 - }; - assert.ok( - testStatesEvI(s2running) < testStatesEvI(s2t1running)); - - const s2t1finished = { + state: 'failed', + test: s1t1, + message: 'Unexpected test error. (Is Catch2 crashed?)\n' + }, + {type: 'suite', state: 'completed', suite: suite1}, + {type: 'finished'}, + ]; + assert.deepStrictEqual(testStatesEvents, expected); + + // this tests the sinon stubs too + await adapter.run([s1t1.id]); + assert.deepStrictEqual(testStatesEvents, [ + ...expected, + {type: 'started', tests: [s1t1.id]}, + {type: 'suite', state: 'running', suite: suite1}, + {type: 'test', state: 'running', test: s1t1}, + { type: 'test', state: 'passed', - test: s2t1, + test: s1t1, decorations: undefined, - message: 'Duration: 0.00037 second(s)\n' - }; - assert.ok( - testStatesEvI(s2t1running) < testStatesEvI(s2t1finished)); - assert.ok( - testStatesEvI(s2t1finished) < testStatesEvI(s2finished)); - - const s2t2running = { - type: 'test', - state: 'running', - test: s2t2 - }; - assert.ok( - testStatesEvI(s2running) < testStatesEvI(s2t2running)); - - const s2t2finished = { - type: 'test', - state: 'skipped', - test: s2t2 - }; - assert.ok( - testStatesEvI(s2t2running) < testStatesEvI(s2t2finished)); - assert.ok( - testStatesEvI(s2t2finished) < testStatesEvI(s2finished)); - - const s2t3running = { - type: 'test', - state: 'running', - test: s2t3 - }; - assert.ok( - testStatesEvI(s2running) < testStatesEvI(s2t3running)); - - const s2t3finished = { - type: 'test', - state: 'failed', - test: s2t3, - decorations: [{line: 20, message: 'Expanded: false'}], - message: - 'Duration: 0.000178 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }; - assert.ok( - testStatesEvI(s2t3running) < testStatesEvI(s2t3finished)); - assert.ok( - testStatesEvI(s2t3finished) < testStatesEvI(s2finished)); - - const finished = {type: 'finished'}; - assert.ok( - testStatesEvI(s1finished) < testStatesEvI(finished)); - assert.ok( - testStatesEvI(s2finished) < testStatesEvI(finished)); - - assert.equal( - testStatesEvents.length, 16, inspect(testStatesEvents)); - } - ], - [ - 'should run with not existing test id', - async function() { - await adapter.run(['not existing id']); - - assert.deepStrictEqual(testStatesEvents, [ - {type: 'started', tests: ['not existing id']}, - {type: 'finished'}, - ]); - } - ], - [ - 'should run s1t1', - async function() { - await adapter.run([s1t1.id]); - const expected = [ - {type: 'started', tests: [s1t1.id]}, - {type: 'suite', state: 'running', suite: suite1}, - {type: 'test', state: 'running', test: s1t1}, - { - type: 'test', - state: 'passed', - test: s1t1, - decorations: undefined, - message: 'Duration: 0.000112 second(s)\n' - }, - {type: 'suite', state: 'completed', suite: suite1}, - {type: 'finished'}, - ]; - assert.deepStrictEqual(testStatesEvents, expected); - - await adapter.run([s1t1.id]); - assert.deepStrictEqual( - testStatesEvents, [...expected, ...expected]); - } - ], - [ - 'should run skipped s2t2', - async function() { - await adapter.run([s2t2.id]); - const expected = [ - {type: 'started', tests: [s2t2.id]}, - {type: 'suite', state: 'running', suite: suite2}, - {type: 'test', state: 'running', test: s2t2}, - { - type: 'test', - state: 'passed', - test: s2t2, - decorations: undefined, - message: 'Duration: 0.001294 second(s)\n' - }, - {type: 'suite', state: 'completed', suite: suite2}, - {type: 'finished'}, - ]; - assert.deepStrictEqual(testStatesEvents, expected); - - await adapter.run([s2t2.id]); - assert.deepStrictEqual( - testStatesEvents, [...expected, ...expected]); - } - ], - [ - 'should run failing test s2t3', - async function() { - await adapter.run([s2t3.id]); - const expected = [ - {type: 'started', tests: [s2t3.id]}, - {type: 'suite', state: 'running', suite: suite2}, - {type: 'test', state: 'running', test: s2t3}, - { - type: 'test', - state: 'failed', - test: s2t3, - decorations: [{line: 20, message: 'Expanded: false'}], - message: - 'Duration: 0.000596 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }, - {type: 'suite', state: 'completed', suite: suite2}, - {type: 'finished'}, - ]; - assert.deepStrictEqual(testStatesEvents, expected); - - await adapter.run([s2t3.id]); - assert.deepStrictEqual( - testStatesEvents, [...expected, ...expected]); + message: 'Duration: 0.000112 second(s)\n' + }, + {type: 'suite', state: 'completed', suite: suite1}, + {type: 'finished'}, + ]); + }), + new Mocha.Test( + 'should cancel without error', + function() { + adapter.cancel(); + }), + new Mocha.Test( + 'cancel', + async function() { + let spyKill1: sinon.SinonSpy; + let spyKill2: sinon.SinonSpy; + { + const spawnEvent = + new ChildProcessStub(example1.suite1.outputs[2][1]); + spyKill1 = sinon.spy(spawnEvent, 'kill'); + const withArgs = spawnStub.withArgs( + example1.suite1.execPath, example1.suite1.outputs[2][0]); + withArgs.onCall(withArgs.callCount).returns(spawnEvent); } - ], - [ - 'should run failing test s2t3 with chunks', - async function() { + { + const spawnEvent = + new ChildProcessStub(example1.suite2.outputs[2][1]); + spyKill2 = sinon.spy(spawnEvent, 'kill'); const withArgs = spawnStub.withArgs( - example1.suite2.execPath, - example1.suite2.t3.outputs[0][0]); - withArgs.onCall(withArgs.callCount) - .returns(new ChildProcessStub( - example1.suite2.t3.outputs[0][1])); - - await adapter.run([s2t3.id]); - const expected = [ - {type: 'started', tests: [s2t3.id]}, - {type: 'suite', state: 'running', suite: suite2}, - {type: 'test', state: 'running', test: s2t3}, - { - type: 'test', - state: 'failed', - test: s2t3, - decorations: [{line: 20, message: 'Expanded: false'}], - message: - 'Duration: 0.000596 second(s)\n>>> s2t3(line: 19) REQUIRE (line: 21) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }, - {type: 'suite', state: 'completed', suite: suite2}, - {type: 'finished'}, - ]; - assert.deepStrictEqual(testStatesEvents, expected); - - await adapter.run([s2t3.id]); - assert.deepStrictEqual( - testStatesEvents, [...expected, ...expected]); + example1.suite2.execPath, example1.suite2.outputs[2][0]); + withArgs.onCall(withArgs.callCount).returns(spawnEvent); } - ], - [ - 'should run suite1', - async function() { - await adapter.run([suite1.id]); - const expected = [ - {type: 'started', tests: [suite1.id]}, - {type: 'suite', state: 'running', suite: suite1}, - {type: 'test', state: 'running', test: s1t1}, - { - type: 'test', - state: 'passed', - test: s1t1, - decorations: undefined, - message: 'Duration: 0.000132 second(s)\n' - }, - {type: 'test', state: 'running', test: s1t2}, - { - type: 'test', - state: 'failed', - test: s1t2, - decorations: [{line: 14, message: 'Expanded: false'}], - message: - 'Duration: 0.000204 second(s)\n>>> s1t2(line: 13) REQUIRE (line: 15) \n Original:\n std::false_type::value\n Expanded:\n false\n<<<\n' - }, - {type: 'suite', state: 'completed', suite: suite1}, - {type: 'finished'}, - ]; - assert.deepStrictEqual(testStatesEvents, expected); - - await adapter.run([suite1.id]); - assert.deepStrictEqual( - testStatesEvents, [...expected, ...expected]); + const run = adapter.run([root.id]); + adapter.cancel(); + await run; + + assert.equal(spyKill1.callCount, 1); + assert.equal(spyKill2.callCount, 1); + + const running = {type: 'started', tests: [root.id]}; + + const s1running = { + type: 'suite', + state: 'running', + suite: suite1 + }; + const s1finished = { + type: 'suite', + state: 'completed', + suite: suite1 + }; + assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); + assert.ok(testStatesEvI(s1running) < testStatesEvI(s1finished)); + + const s2running = { + type: 'suite', + state: 'running', + suite: suite2 + }; + const s2finished = { + type: 'suite', + state: 'completed', + suite: suite2 + }; + assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); + assert.ok(testStatesEvI(s2running) < testStatesEvI(s2finished)); + + const s2t2running = { + type: 'test', + state: 'running', + test: s2t2 + }; + assert.ok( + testStatesEvI(s2running) < testStatesEvI(s2t2running)); + + const s2t2finished = { + type: 'test', + state: 'skipped', + test: s2t2 + }; + assert.ok( + testStatesEvI(s2t2running) < testStatesEvI(s2t2finished)); + assert.ok( + testStatesEvI(s2t2finished) < testStatesEvI(s2finished)); + + const finished = {type: 'finished'}; + assert.ok(testStatesEvI(s1finished) < testStatesEvI(finished)); + assert.ok(testStatesEvI(s2finished) < testStatesEvI(finished)); + + assert.equal( + testStatesEvents.length, 8, inspect(testStatesEvents)); + }), + new Mocha.Test( + 'cancel after run finished', + function() { + let spyKill1: sinon.SinonSpy; + let spyKill2: sinon.SinonSpy; + { + const spawnEvent = + new ChildProcessStub(example1.suite1.outputs[2][1]); + spyKill1 = sinon.spy(spawnEvent, 'kill'); + const withArgs = spawnStub.withArgs( + example1.suite1.execPath, example1.suite1.outputs[2][0]); + withArgs.onCall(withArgs.callCount).returns(spawnEvent); } - ], - [ - 'should run with wrong xml', - async function() { - const m = - example1.suite1.t1.outputs[0][1].match(']+>'); - assert.notEqual(m, undefined); - assert.notEqual(m!.input, undefined); - assert.notEqual(m!.index, undefined); - const part = m!.input!.substr(0, m!.index! + m![0].length); + { + const spawnEvent = + new ChildProcessStub(example1.suite2.outputs[2][1]); + spyKill2 = sinon.spy(spawnEvent, 'kill'); const withArgs = spawnStub.withArgs( - example1.suite1.execPath, - example1.suite1.t1.outputs[0][0]); - withArgs.onCall(withArgs.callCount) - .returns(new ChildProcessStub(part)); - - await adapter.run([s1t1.id]); - - const expected = [ - {type: 'started', tests: [s1t1.id]}, - {type: 'suite', state: 'running', suite: suite1}, - {type: 'test', state: 'running', test: s1t1}, - { - type: 'test', - state: 'failed', - test: s1t1, - message: 'Unexpected test error. (Is Catch2 crashed?)\n' - }, - {type: 'suite', state: 'completed', suite: suite1}, - {type: 'finished'}, - ]; - assert.deepStrictEqual(testStatesEvents, expected); - - // this tests the sinon stubs too - await adapter.run([s1t1.id]); - assert.deepStrictEqual(testStatesEvents, [ - ...expected, - {type: 'started', tests: [s1t1.id]}, - {type: 'suite', state: 'running', suite: suite1}, - {type: 'test', state: 'running', test: s1t1}, - { - type: 'test', - state: 'passed', - test: s1t1, - decorations: undefined, - message: 'Duration: 0.000112 second(s)\n' - }, - {type: 'suite', state: 'completed', suite: suite1}, - {type: 'finished'}, - ]); + example1.suite2.execPath, example1.suite2.outputs[2][0]); + withArgs.onCall(withArgs.callCount).returns(spawnEvent); } - ], - [ - 'should cancel without error', - function() { + const run = adapter.run([root.id]); + return run.then(function() { adapter.cancel(); + assert.equal(spyKill1.callCount, 0); + assert.equal(spyKill2.callCount, 0); + }); + }), + new Mocha.Test( + 'reload because of fswatcher event: touch', + async function() { + const newRoot = await doAndWaitForReloadEvent(async () => { + suite1Watcher.emit( + 'change', 'dummyEvent', example1.suite1.execPath); + }); + assert.deepStrictEqual(newRoot, root); + }), + // new Mocha.Test( + // 'reload because of fswatcher event: touch, retry 5 times', + // async function() { + // const newRoot = await doAndWaitForReloadEvent(async () => { + // const w = fsExistsStub.withArgs(example1.suite1.execPath); + // for (let cc = 0; cc < 3; cc++) { + // w.onCall(w.callCount + cc) + // .callsFake(function( + // path: string, + // cb: (err: any, exists: boolean) => void) { + // assert.equal(path, example1.suite1.execPath); + // cb(undefined, false); + // }); + // } + // assert.ok(suite1Watcher.emit( + // 'change', 'dummyEvent', example1.suite1.execPath)); + // }); + // assert.deepStrictEqual(newRoot, root); + // }), + new Mocha.Test( + 'reload because of fswatcher event: test added', + async function(this: Mocha.Context) { + const testListOutput = + example1.suite1.outputs[1][1].split('\n'); + assert.equal(testListOutput.length, 10); + testListOutput.splice( + 1, 0, ' s1t0', ' suite1.cpp:6', ' tag1'); + const withArgs = spawnStub.withArgs( + example1.suite1.execPath, example1.suite1.outputs[1][0]); + withArgs.onCall(withArgs.callCount) + .returns(new ChildProcessStub(testListOutput.join('\n'))); + + const oldRootChildren = [...root.children]; + const oldSuite1Children = [...suite1.children]; + const oldSuite2Children = [...suite2.children]; + + const newRoot = await doAndWaitForReloadEvent(async () => { + suite1Watcher.emit( + 'change', 'dummyEvent', example1.suite1.execPath); + }); + + assert.equal(newRoot, root); + assert.equal(root.children.length, oldRootChildren.length); + for (let i = 0; i < oldRootChildren.length; i++) { + assert.equal(root.children[i], oldRootChildren[i]); } - ], - [ - 'cancel', - async function() { - let spyKill1: sinon.SinonSpy; - let spyKill2: sinon.SinonSpy; - { - const spawnEvent = - new ChildProcessStub(example1.suite1.outputs[2][1]); - spyKill1 = sinon.spy(spawnEvent, 'kill'); - const withArgs = spawnStub.withArgs( - example1.suite1.execPath, - example1.suite1.outputs[2][0]); - withArgs.onCall(withArgs.callCount).returns(spawnEvent); - } - { - const spawnEvent = - new ChildProcessStub(example1.suite2.outputs[2][1]); - spyKill2 = sinon.spy(spawnEvent, 'kill'); - const withArgs = spawnStub.withArgs( - example1.suite2.execPath, - example1.suite2.outputs[2][0]); - withArgs.onCall(withArgs.callCount).returns(spawnEvent); - } - const run = adapter.run([root.id]); - adapter.cancel(); - await run; - - assert.equal(spyKill1.callCount, 1); - assert.equal(spyKill2.callCount, 1); - - const running = {type: 'started', tests: [root.id]}; - - const s1running = { - type: 'suite', - state: 'running', - suite: suite1 - }; - const s1finished = { - type: 'suite', - state: 'completed', - suite: suite1 - }; - assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); - assert.ok( - testStatesEvI(s1running) < testStatesEvI(s1finished)); - - const s2running = { - type: 'suite', - state: 'running', - suite: suite2 - }; - const s2finished = { - type: 'suite', - state: 'completed', - suite: suite2 - }; - assert.ok(testStatesEvI(running) < testStatesEvI(s1running)); - assert.ok( - testStatesEvI(s2running) < testStatesEvI(s2finished)); - - const s2t2running = { - type: 'test', - state: 'running', - test: s2t2 - }; - assert.ok( - testStatesEvI(s2running) < testStatesEvI(s2t2running)); - const s2t2finished = { - type: 'test', - state: 'skipped', - test: s2t2 - }; - assert.ok( - testStatesEvI(s2t2running) < testStatesEvI(s2t2finished)); - assert.ok( - testStatesEvI(s2t2finished) < testStatesEvI(s2finished)); - - const finished = {type: 'finished'}; - assert.ok( - testStatesEvI(s1finished) < testStatesEvI(finished)); - assert.ok( - testStatesEvI(s2finished) < testStatesEvI(finished)); - - assert.equal( - testStatesEvents.length, 8, inspect(testStatesEvents)); - } - ], - [ - 'cancel after run finished', - function() { - let spyKill1: sinon.SinonSpy; - let spyKill2: sinon.SinonSpy; - { - const spawnEvent = - new ChildProcessStub(example1.suite1.outputs[2][1]); - spyKill1 = sinon.spy(spawnEvent, 'kill'); - const withArgs = spawnStub.withArgs( - example1.suite1.execPath, - example1.suite1.outputs[2][0]); - withArgs.onCall(withArgs.callCount).returns(spawnEvent); - } - { - const spawnEvent = - new ChildProcessStub(example1.suite2.outputs[2][1]); - spyKill2 = sinon.spy(spawnEvent, 'kill'); - const withArgs = spawnStub.withArgs( - example1.suite2.execPath, - example1.suite2.outputs[2][0]); - withArgs.onCall(withArgs.callCount).returns(spawnEvent); - } - const run = adapter.run([root.id]); - return run.then(function() { - adapter.cancel(); - assert.equal(spyKill1.callCount, 0); - assert.equal(spyKill2.callCount, 0); - }); + assert.equal( + suite1.children.length, oldSuite1Children.length + 1); + for (let i = 0; i < suite1.children.length; i++) { + assert.equal(suite1.children[i + 1], oldSuite1Children[i]); } - ], - [ - 'reload because of fswatcher event', - async function(this: Mocha.Context) { - this.slow(150); - const doAndWaitForReload = - async function(action: Function): Promise { - const origCount = testsEvents.length; - await action(); - let tryCount: number = 20; - while (testsEvents.length != origCount + 2 && - --tryCount > 0) - await promisify(setTimeout)(20); - assert.equal(testsEvents.length, origCount + 2); - const e = - testsEvents[testsEvents.length - 1]!; - assert.equal(e.type, 'finished'); - assert.ok(e.suite != undefined); - return e.suite!; - }; - - assert.equal(watchers.size, 2); - assert.ok(watchers.has(example1.suite1.execPath)); - const suite1Watcher = watchers.get(example1.suite1.execPath)!; - - { // touch - const newRoot = await doAndWaitForReload(async () => { - suite1Watcher.emit( - 'change', 'dummyEvent', example1.suite1.execPath); - }); - assert.deepStrictEqual(newRoot, root); - } - - { // test added - const testListOutput = - example1.suite1.outputs[1][1].split('\n'); - assert.equal(testListOutput.length, 10); - testListOutput.splice( - 1, 0, ' s1t0', ' suite1.cpp:6', ' tag1'); - const withArgs = spawnStub.withArgs( - example1.suite1.execPath, - example1.suite1.outputs[1][0]); - withArgs.onCall(withArgs.callCount) - .returns( - new ChildProcessStub(testListOutput.join('\n'))); - - const oldRootChildren = [...root.children]; - const oldSuite1Children = [...suite1.children]; - const oldSuite2Children = [...suite2.children]; - - const newRoot = await doAndWaitForReload(async () => { - suite1Watcher.emit( - 'change', 'dummyEvent', example1.suite1.execPath); - }); - - assert.equal(newRoot, root); - assert.equal(root.children.length, oldRootChildren.length); - for (let i = 0; i < oldRootChildren.length; i++) { - assert.equal(root.children[i], oldRootChildren[i]); - } - - assert.equal( - suite1.children.length, oldSuite1Children.length + 1); - for (let i = 0; i < suite1.children.length; i++) { - assert.equal( - suite1.children[i + 1], oldSuite1Children[i]); - } - const newTest = suite1.children[0]; - assert.ok(!uniqueIdC.has(newTest.id)); - assert.equal(newTest.label, 's1t0'); + const newTest = suite1.children[0]; + assert.ok(!uniqueIdC.has(newTest.id)); + assert.equal(newTest.label, 's1t0'); - assert.equal( - suite2.children.length, oldSuite2Children.length); - for (let i = 0; i < suite2.children.length; i++) { - assert.equal(suite2.children[i], oldSuite2Children[i]); - } - } - { // test deleted - const oldRootChildren = [...root.children]; - const oldSuite1Children = [...suite1.children]; - const oldSuite2Children = [...suite2.children]; - - const newRoot = await doAndWaitForReload(async () => { - suite1Watcher.emit( - 'change', 'dummyEvent', example1.suite1.execPath); - }); - - assert.equal(newRoot, root); - assert.equal(root.children.length, oldRootChildren.length); - for (let i = 0; i < oldRootChildren.length; i++) { - assert.equal(root.children[i], oldRootChildren[i]); - } + assert.equal(suite2.children.length, oldSuite2Children.length); + for (let i = 0; i < suite2.children.length; i++) { + assert.equal(suite2.children[i], oldSuite2Children[i]); + } + }), + new Mocha.Test( + 'reload because of fswatcher event: test deleted', + async function(this: Mocha.Context) { + const testListOutput = + example1.suite1.outputs[1][1].split('\n'); + assert.equal(testListOutput.length, 10); + testListOutput.splice(1, 3); + const withArgs = spawnStub.withArgs( + example1.suite1.execPath, example1.suite1.outputs[1][0]); + withArgs.onCall(withArgs.callCount) + .returns(new ChildProcessStub(testListOutput.join('\n'))); + + const oldRootChildren = [...root.children]; + const oldSuite1Children = [...suite1.children]; + const oldSuite2Children = [...suite2.children]; + + const newRoot = await doAndWaitForReloadEvent(async () => { + suite1Watcher.emit( + 'change', 'dummyEvent', example1.suite1.execPath); + }); + + assert.equal(newRoot, root); + assert.equal(root.children.length, oldRootChildren.length); + for (let i = 0; i < oldRootChildren.length; i++) { + assert.equal(root.children[i], oldRootChildren[i]); + } - assert.equal( - suite1.children.length + 1, oldSuite1Children.length); - for (let i = 0; i < suite1.children.length; i++) { - assert.equal( - suite1.children[i], oldSuite1Children[i + 1]); - } - const deletedTest = oldSuite1Children[0]; - assert.equal(deletedTest.label, 's1t0'); + assert.equal( + suite1.children.length + 1, oldSuite1Children.length); + for (let i = 0; i < suite1.children.length; i++) { + assert.equal(suite1.children[i], oldSuite1Children[i + 1]); + } - assert.equal( - suite2.children.length, oldSuite2Children.length); - for (let i = 0; i < suite2.children.length; i++) { - assert.equal(suite2.children[i], oldSuite2Children[i]); - } - } + assert.equal(suite2.children.length, oldSuite2Children.length); + for (let i = 0; i < suite2.children.length; i++) { + assert.equal(suite2.children[i], oldSuite2Children[i]); } - ], - ]; + }), + ]; context( 'executables=["execPath1", "${workspaceFolder}/execPath2"]', @@ -1218,7 +1163,8 @@ describe('C2TestAdapter', function() { ['s2t1', 's2t2 [.]', 's2t3'], suite2, uniqueIdC); }) - for (let t of testsForAdapterWithSuite1AndSuite2) it(t[0], t[1]); + for (let t of testsForAdapterWithSuite1AndSuite2) this.addTest( + t.clone()); }) context('executables=[{}] and env={...}', function() { @@ -1254,7 +1200,8 @@ describe('C2TestAdapter', function() { ['s2t1', 's2t2 [.]', 's2t3'], suite2, uniqueIdC); }) - for (let t of testsForAdapterWithSuite1AndSuite2) it(t[0], t[1]); + for (let t of testsForAdapterWithSuite1AndSuite2) this.addTest( + t.clone()); it('should get execution options', async function() { { @@ -1323,5 +1270,43 @@ describe('C2TestAdapter', function() { await updateConfig('executables', undefined); }) + + specify.skip( + 'load executables=["execPath1", "execPath2Copy"] and delete second because of fswatcher event', + async function() { + this.slow(300); + + const fullPath = path.join(workspaceFolderUri.path, 'execPath2Copy'); + + for (let o of example1.suite2.outputs) + spawnStub.withArgs(example1.suite2.outputs, o[0]).callsFake(() => { + return new ChildProcessStub(o[1]); + }); + + fsExistsStub.withArgs(fullPath).callsFake(function( + path: string, cb: (err: any, exists: boolean) => void) { + cb(undefined, true); + }); + + fsWatchStub.withArgs(fullPath).callsFake((path: string) => { + return new class extends EventEmitter { + close() {} + }; + }); + + await updateConfig('executables', ['execPath1', 'execPath2Copy']) + adapter = createAdapterAndSubscribe(); + + await adapter.load(); + + // not finished + // const withArgs = spawnStub.withArgs( + // example1.suite2.execPath, example1.suite2.outputs[1][0]); + // withArgs.onCall(withArgs.callCount).throws( + // 'dummy error for testing (should be handled)'); + + // restore + await updateConfig('executables', undefined); + }) }) }) \ No newline at end of file From c0327db993806bac399fb7fd80a09af1259f6f0b Mon Sep 17 00:00:00 2001 From: Mate Pek Date: Tue, 23 Oct 2018 18:20:28 +0200 Subject: [PATCH 09/18] something works gain --- package.json | 2 +- src/C2TestAdapter.ts | 74 +++++++++--------- src/C2TestSuiteInfo.ts | 8 +- src/FsWrapper.ts | 40 +++++++++- src/test/C2TestAdapter.test.ts | 134 ++++++++++++++++++--------------- src/test/FsWrapper.test.ts | 2 +- 6 files changed, 151 insertions(+), 109 deletions(-) diff --git a/package.json b/package.json index ad46f74c..76075bb2 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "scripts": { "postinstall": "node ./node_modules/vscode/bin/install", "reinstall": "rimraf node_modules package-lock.json && npm install", - "clean": "rimraf out vscode-google-test-adapter-*.vsix", + "clean": "rimraf out", "compile": "tsc -p ./", "watch": "tsc -watch -p ./", "rebuild": "npm run clean && npm run build", diff --git a/src/C2TestAdapter.ts b/src/C2TestAdapter.ts index da13fadd..fc0f35a0 100644 --- a/src/C2TestAdapter.ts +++ b/src/C2TestAdapter.ts @@ -2,9 +2,8 @@ // vscode-catch2-test-adapter was written by Mate Pek, and is placed in the // public domain. The author hereby disclaims copyright to this source code. -import * as fs from 'fs'; import * as path from 'path'; -import {inspect} from 'util'; +import {inspect, promisify} from 'util'; import * as vscode from 'vscode'; import {TestAdapter, TestEvent, TestLoadFinishedEvent, TestLoadStartedEvent, TestRunFinishedEvent, TestRunStartedEvent, TestSuiteEvent} from 'vscode-test-adapter-api'; import * as util from 'vscode-test-adapter-util'; @@ -21,7 +20,7 @@ export class C2TestAdapter implements TestAdapter, vscode.Disposable { TestSuiteEvent|TestEvent>(); private readonly autorunEmitter = new vscode.EventEmitter(); - private readonly watchers: Map = new Map(); + private readonly watchers: Map = new Map(); private isRunning: number = 0; private isDebugging: boolean = false; @@ -106,48 +105,51 @@ export class C2TestAdapter implements TestAdapter, vscode.Disposable { watcher.close(); } try { - watcher = fs.watch(suite.execPath); + watcher = c2fs.watch(suite.execPath); this.watchers.set(suite.execPath, watcher); const allTests = this.allTests; // alltest may has changed watcher.on('change', (eventType: string, filename: string) => { - // need some time here: - const waitAndThenTry = (remainingIteration: number, delay: number) => { - if (remainingIteration == 0) { - watcher!.close(); - this.watchers.delete(suite.execPath); - this.testsEmitter.fire({type: 'started'}); - allTests.removeChild(suite); - this.testsEmitter.fire({type: 'finished', suite: this.allTests}); - } else { - fs.exists( - suite.execPath, - <(exists: boolean) => void>((err: any, exists: boolean) => { - if (!exists) { - setTimeout( - waitAndThenTry, delay, remainingIteration - 1, - Math.min(delay * 2, 2000)); - } else { - this.testsEmitter.fire({type: 'started'}); - suite.reloadChildren().then( - () => { - this.testsEmitter.fire( - {type: 'finished', suite: this.allTests}); - }, - (err: any) => { - this.log.warn(inspect(err)); - setTimeout( - waitAndThenTry, delay, remainingIteration - 1, + const x = (exists: boolean, remainingIteration: number, delay: number): + Promise => { + if (remainingIteration <= 0) { + watcher!.close(); + this.watchers.delete(suite.execPath); + this.testsEmitter.fire({type: 'started'}); + allTests.removeChild(suite); + this.testsEmitter.fire( + {type: 'finished', suite: this.allTests}); + return Promise.resolve(); + } else if (exists) { + this.testsEmitter.fire({type: 'started'}); + return suite.reloadChildren().then( + () => { + this.testsEmitter.fire( + {type: 'finished', suite: this.allTests}); + }, + (err: any) => { + this.testsEmitter.fire( + {type: 'finished', suite: this.allTests}); + this.log.warn(inspect(err)); + return x( + false, remainingIteration - 1, + Math.min(delay * 2, 2000)); + }); + } + return promisify(setTimeout)(Math.min(delay * 2, 2000)) + .then(() => { + return c2fs.existsAsync(suite.execPath) + .then((exists: boolean) => { + return x( + exists, remainingIteration - 1, Math.min(delay * 2, 2000)); }); - } - })); - } - }; + }); + }; // change event can arrive during debug session on osx (why?) if (!this.isDebugging) { - waitAndThenTry(10, 128); + x(false, 10, 64); } }); } catch (e) { diff --git a/src/C2TestSuiteInfo.ts b/src/C2TestSuiteInfo.ts index 22a7c7f1..1acdfbf0 100644 --- a/src/C2TestSuiteInfo.ts +++ b/src/C2TestSuiteInfo.ts @@ -3,9 +3,7 @@ // public domain. The author hereby disclaims copyright to this source code. import {ChildProcess, spawn, SpawnOptions} from 'child_process'; -import * as fs from 'fs'; import * as path from 'path'; -import {promisify} from 'util'; import {TestEvent, TestSuiteEvent, TestSuiteInfo} from 'vscode-test-adapter-api'; import * as xml2js from 'xml2js'; @@ -266,10 +264,8 @@ export class C2TestSuiteInfo implements TestSuiteInfo { } reloadChildren(): Promise { - return promisify(fs.exists)(this.execPath).then((exists: boolean) => { - if (!exists) - throw Error('reloadSuiteChildren: Should exists: ' + this.execPath); - + return c2fs.existsAsync(this.execPath).then((exists: boolean) => { + if (!exists) throw new Error('Path not exists: ' + this.execPath); return c2fs .spawnAsync( this.execPath, diff --git a/src/FsWrapper.ts b/src/FsWrapper.ts index f1f362f0..cb3a261f 100644 --- a/src/FsWrapper.ts +++ b/src/FsWrapper.ts @@ -5,13 +5,15 @@ import * as cp from 'child_process'; import * as fs from 'fs'; +export type SpawnReturns = cp.SpawnSyncReturns; + export function spawnAsync( cmd: string, args?: string[], - options?: cp.SpawnOptions): Promise> { + options?: cp.SpawnOptions): Promise { return new Promise((resolve) => { - const ret: cp.SpawnSyncReturns = { + const ret: SpawnReturns = { pid: 0, - output: [], + output: ['', ''], stdout: '', stderr: '', status: 0, @@ -22,7 +24,7 @@ export function spawnAsync( ret.pid = command.pid; command.stdout.on('data', function(data) { ret.stdout += data; - ret.output.push(data); + ret.output[0] = ret.stdout; }); command.on('close', function(code) { ret.status = code; @@ -39,10 +41,40 @@ export function statSync(path: string): fs.Stats { return fs.statSync(path); } +export type Stats = fs.Stats; + +export function statAsync(path: string): Promise { + return new Promise((resolve, reject) => { + fs.stat(path, (err: NodeJS.ErrnoException, stats: fs.Stats) => { + if (err) + reject(err); + else + resolve(stats); + }); + }); +} + +export function existsAsync(path: string): Promise { + return statAsync(path).then( + () => { + return true; + }, + () => { + return false; + }); +} + + export function existsSync(path: string): boolean { return fs.existsSync(path); } export function readdirSync(path: string): string[] { return fs.readdirSync(path, 'utf8'); +} + +export type FSWatcher = fs.FSWatcher; + +export function watch(path: string): FSWatcher { + return fs.watch(path); } \ No newline at end of file diff --git a/src/test/C2TestAdapter.test.ts b/src/test/C2TestAdapter.test.ts index 6c40fbc0..8106d560 100644 --- a/src/test/C2TestAdapter.test.ts +++ b/src/test/C2TestAdapter.test.ts @@ -58,7 +58,7 @@ describe('C2TestAdapter', function() { let spawnStub: sinon.SinonStub; let fsWatchStub: sinon.SinonStub; - let fsExistsStub: sinon.SinonStub; + let c2fsStatStub: sinon.SinonStub; let c2fsReaddirSyncStub: sinon.SinonStub; let c2fsStatSyncStub: sinon.SinonStub; @@ -142,28 +142,25 @@ describe('C2TestAdapter', function() { spawnStub.callThrough(); fsWatchStub.reset(); fsWatchStub.callThrough(); - fsExistsStub.reset(); - fsExistsStub.callThrough(); + c2fsStatStub.reset(); + c2fsStatStub.callThrough(); c2fsReaddirSyncStub.reset(); - c2fsReaddirSyncStub.callThrough(); + c2fsReaddirSyncStub.throws('Test isnt set properly error.'); c2fsStatSyncStub.reset(); - c2fsStatSyncStub.callThrough(); + c2fsStatSyncStub.throws('Test isnt set properly error.'); } before(function() { fse.removeSync(dotVscodePath); adapter = undefined; - spawnStub = sinonSandbox.stub(child_process, 'spawn'); - spawnStub.named('spawnStub'); - fsWatchStub = sinonSandbox.stub(fs, 'watch'); - fsWatchStub.named('fsWatchStub'); - fsExistsStub = sinonSandbox.stub(fs, 'exists'); - fsExistsStub.named('fsExistsStub'); - c2fsReaddirSyncStub = sinonSandbox.stub(c2fs, 'readdirSync'); - c2fsReaddirSyncStub.named('c2fsReaddirSyncStub'); - c2fsStatSyncStub = sinonSandbox.stub(c2fs, 'statSync'); - c2fsStatSyncStub.named('c2fsStatSyncStub'); + spawnStub = sinonSandbox.stub(child_process, 'spawn').named('spawnStub'); + fsWatchStub = sinonSandbox.stub(fs, 'watch').named('fsWatchStub'); + c2fsStatStub = sinonSandbox.stub(fs, 'stat').named('fsStat'); + c2fsReaddirSyncStub = + sinonSandbox.stub(c2fs, 'readdirSync').named('c2fsReaddirSyncStub'); + c2fsStatSyncStub = + sinonSandbox.stub(c2fs, 'statSync').named('c2fsStatSyncStub'); stubsResetToMyDefault(); @@ -244,10 +241,21 @@ describe('C2TestAdapter', function() { return new ChildProcessStub(scenario[1]); }); } - fsExistsStub.withArgs(suite[0]).callsFake(function( - path: string, cb: (err: any, exists: boolean) => void) { - cb(undefined, true); - }); + + c2fsStatStub.withArgs(suite[0]).callsFake( + (path: string, + cb: (err: NodeJS.ErrnoException|undefined, stats: fs.Stats) => + void) => { + cb(undefined, { + isFile() { + return true; + }, + isDirectory() { + return false; + } + }); + }); + fsWatchStub.withArgs(suite[0]).callsFake((path: string) => { const e = new class extends EventEmitter { close() {} @@ -305,7 +313,7 @@ describe('C2TestAdapter', function() { }) describe('load', function() { - this.enableTimeouts(false); //TODO + this.enableTimeouts(false); // TODO const uniqueIdC = new Set(); let adapter: TestAdapter; @@ -531,7 +539,7 @@ describe('C2TestAdapter', function() { }) }) - context.only('suite1 and suite2 are used', function() { + context('suite1 and suite2 are used', function() { let suite1Watcher: EventEmitter; beforeEach(function() { @@ -1200,43 +1208,43 @@ describe('C2TestAdapter', function() { ['s2t1', 's2t2 [.]', 's2t3'], suite2, uniqueIdC); }) - for (let t of testsForAdapterWithSuite1AndSuite2) this.addTest( - t.clone()); - - it('should get execution options', async function() { - { - const withArgs = spawnStub.withArgs( - example1.suite1.execPath, sinon.match.any, sinon.match.any); - withArgs.onCall(withArgs.callCount) - .callsFake((p: string, args: string[], ops: any) => { - assert.equal( - ops.cwd, path.join(workspaceFolderUri.path, 'cwd')); - assert.equal(ops.env.C2LOCALTESTENV, 'c2localtestenv'); - assert.ok(!ops.env.hasOwnProperty('C2GLOBALTESTENV')); - assert.equal( - ops.env.C2OVERRIDETESTENV, 'c2overridetestenv-l'); - return new ChildProcessStub(example1.suite1.outputs[2][1]); - }); - - await adapter.run([suite1.id]); - } - { - const withArgs = spawnStub.withArgs( - example1.suite2.execPath, sinon.match.any, sinon.match.any); - withArgs.onCall(withArgs.callCount) - .callsFake((p: string, args: string[], ops: any) => { - assert.equal( - ops.cwd, path.join(workspaceFolderUri.path, 'cwd')); - assert.equal(ops.env.C2LOCALTESTENV, 'c2localtestenv'); - assert.ok(!ops.env.hasOwnProperty('C2GLOBALTESTENV')); - assert.equal( - ops.env.C2OVERRIDETESTENV, 'c2overridetestenv-l'); - return new ChildProcessStub(example1.suite2.outputs[2][1]); - }); - - await adapter.run([suite2.id]); - } - }) + //for (let t of testsForAdapterWithSuite1AndSuite2) this.addTest( + // t.clone()); + + // it('should get execution options', async function() { + // { + // const withArgs = spawnStub.withArgs( + // example1.suite1.execPath, sinon.match.any, sinon.match.any); + // withArgs.onCall(withArgs.callCount) + // .callsFake((p: string, args: string[], ops: any) => { + // assert.equal( + // ops.cwd, path.join(workspaceFolderUri.path, 'cwd')); + // assert.equal(ops.env.C2LOCALTESTENV, 'c2localtestenv'); + // assert.ok(!ops.env.hasOwnProperty('C2GLOBALTESTENV')); + // assert.equal( + // ops.env.C2OVERRIDETESTENV, 'c2overridetestenv-l'); + // return new ChildProcessStub(example1.suite1.outputs[2][1]); + // }); + + // await adapter.run([suite1.id]); + // } + // { + // const withArgs = spawnStub.withArgs( + // example1.suite2.execPath, sinon.match.any, sinon.match.any); + // withArgs.onCall(withArgs.callCount) + // .callsFake((p: string, args: string[], ops: any) => { + // assert.equal( + // ops.cwd, path.join(workspaceFolderUri.path, 'cwd')); + // assert.equal(ops.env.C2LOCALTESTENV, 'c2localtestenv'); + // assert.ok(!ops.env.hasOwnProperty('C2GLOBALTESTENV')); + // assert.equal( + // ops.env.C2OVERRIDETESTENV, 'c2overridetestenv-l'); + // return new ChildProcessStub(example1.suite2.outputs[2][1]); + // }); + + // await adapter.run([suite2.id]); + // } + // }) }) }) }) @@ -1283,9 +1291,13 @@ describe('C2TestAdapter', function() { return new ChildProcessStub(o[1]); }); - fsExistsStub.withArgs(fullPath).callsFake(function( - path: string, cb: (err: any, exists: boolean) => void) { - cb(undefined, true); + c2fsStatSyncStub.withArgs(fullPath).resolves({ + isFile() { + return true; + }, + isDirectory() { + return false; + } }); fsWatchStub.withArgs(fullPath).callsFake((path: string) => { diff --git a/src/test/FsWrapper.test.ts b/src/test/FsWrapper.test.ts index a6ea0b33..df25dbe4 100644 --- a/src/test/FsWrapper.test.ts +++ b/src/test/FsWrapper.test.ts @@ -5,7 +5,7 @@ describe('FsWrapper.spawnAsync', function() { it('echoes', async function() { const r = await spawnAsync('echo', ['apple']); assert.equal(r.stdout, 'apple\n'); - assert.equal(r.output.length, 1); + assert.equal(r.output.length, 2); assert.equal(r.output[0], 'apple\n'); assert.equal(r.status, 0); }) From 6a098296e8669b6e3d49c4f1c37366372df116e0 Mon Sep 17 00:00:00 2001 From: Mate Pek Date: Tue, 23 Oct 2018 18:33:25 +0200 Subject: [PATCH 10/18] before statsync remove --- src/test/C2TestAdapter.test.ts | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/test/C2TestAdapter.test.ts b/src/test/C2TestAdapter.test.ts index 8106d560..75fde38c 100644 --- a/src/test/C2TestAdapter.test.ts +++ b/src/test/C2TestAdapter.test.ts @@ -1175,7 +1175,7 @@ describe('C2TestAdapter', function() { t.clone()); }) - context('executables=[{}] and env={...}', function() { + context.only('executables=[{}] and env={...}', function() { before(async function() { await updateConfig('executables', [{ name: '${dirname}: ${name} (${absDirname})', @@ -1208,13 +1208,14 @@ describe('C2TestAdapter', function() { ['s2t1', 's2t2 [.]', 's2t3'], suite2, uniqueIdC); }) - //for (let t of testsForAdapterWithSuite1AndSuite2) this.addTest( - // t.clone()); + for (let t of testsForAdapterWithSuite1AndSuite2) this.addTest( + t.clone()); // it('should get execution options', async function() { // { // const withArgs = spawnStub.withArgs( - // example1.suite1.execPath, sinon.match.any, sinon.match.any); + // example1.suite1.execPath, sinon.match.any, + // sinon.match.any); // withArgs.onCall(withArgs.callCount) // .callsFake((p: string, args: string[], ops: any) => { // assert.equal( @@ -1223,14 +1224,16 @@ describe('C2TestAdapter', function() { // assert.ok(!ops.env.hasOwnProperty('C2GLOBALTESTENV')); // assert.equal( // ops.env.C2OVERRIDETESTENV, 'c2overridetestenv-l'); - // return new ChildProcessStub(example1.suite1.outputs[2][1]); + // return new + // ChildProcessStub(example1.suite1.outputs[2][1]); // }); // await adapter.run([suite1.id]); // } // { // const withArgs = spawnStub.withArgs( - // example1.suite2.execPath, sinon.match.any, sinon.match.any); + // example1.suite2.execPath, sinon.match.any, + // sinon.match.any); // withArgs.onCall(withArgs.callCount) // .callsFake((p: string, args: string[], ops: any) => { // assert.equal( @@ -1239,7 +1242,8 @@ describe('C2TestAdapter', function() { // assert.ok(!ops.env.hasOwnProperty('C2GLOBALTESTENV')); // assert.equal( // ops.env.C2OVERRIDETESTENV, 'c2overridetestenv-l'); - // return new ChildProcessStub(example1.suite2.outputs[2][1]); + // return new + // ChildProcessStub(example1.suite2.outputs[2][1]); // }); // await adapter.run([suite2.id]); From 039763980e11ccdb666b95e24b37482c12f62be2 Mon Sep 17 00:00:00 2001 From: Mate Pek Date: Tue, 23 Oct 2018 18:44:32 +0200 Subject: [PATCH 11/18] statSync removed --- src/C2TestAdapter.ts | 25 +++---- src/FsWrapper.ts | 4 -- src/test/C2TestAdapter.test.ts | 125 +++++++++++++-------------------- 3 files changed, 60 insertions(+), 94 deletions(-) diff --git a/src/C2TestAdapter.ts b/src/C2TestAdapter.ts index fc0f35a0..b6f2bba2 100644 --- a/src/C2TestAdapter.ts +++ b/src/C2TestAdapter.ts @@ -405,7 +405,7 @@ export class C2TestAdapter implements TestAdapter, vscode.Disposable { return config.get('enableSourceDecoration', true); } - private getExecutables(config: vscode.WorkspaceConfiguration): + private async getExecutables(config: vscode.WorkspaceConfiguration): Promise { const globalWorkingDirectory = this.getDefaultCwd(config); @@ -418,7 +418,7 @@ export class C2TestAdapter implements TestAdapter, vscode.Disposable { return path.isAbsolute(p) ? p : this.resolveRelPath(p); }; - const addObject = (o: Object): void => { + const addObject = async(o: Object): Promise => { const name: string = o.hasOwnProperty('name') ? (o)['name'] : '${dirname} : ${name}'; if (!o.hasOwnProperty('path') || (o)['path'] === null) { @@ -439,11 +439,12 @@ export class C2TestAdapter implements TestAdapter, vscode.Disposable { false; if (regex.length > 0) { - const recursiveAdd = (directory: string): void => { + const recursiveAdd = async(directory: string): Promise => { const children = c2fs.readdirSync(directory); - children.forEach(child => { + for (let i = 0; i < children.length; ++i) { + const child = children[i]; const childPath = path.resolve(directory, child); - const childStat = c2fs.statSync(childPath); + const childStat = await c2fs.statAsync(childPath); if (childPath.match(regex) && childStat.isFile()) { let resolvedName = name + ' : ' + child; let resolvedCwd = cwd; @@ -469,14 +470,14 @@ export class C2TestAdapter implements TestAdapter, vscode.Disposable { executables.push(new ExecutableConfig( resolvedName, childPath, regex, fullPath(resolvedCwd), env)); } else if (childStat.isDirectory() && regexRecursive) { - recursiveAdd(childPath); + await recursiveAdd(childPath); } - }); + } }; try { - const stat = c2fs.statSync(p); + const stat = await c2fs.statAsync(p); if (stat.isDirectory()) { - recursiveAdd(p); + await recursiveAdd(p); } else if (stat.isFile()) { executables.push(new ExecutableConfig(name, p, regex, cwd, env)); } else { @@ -510,16 +511,16 @@ export class C2TestAdapter implements TestAdapter, vscode.Disposable { '', globalWorkingDirectory, [])); } } else { - addObject(configExecs[i]); + await addObject(configExecs[i]); } } } else if (configExecs instanceof Object) { - addObject(configExecs); + await addObject(configExecs); } else { throw 'Catch2 config error: wrong type: executables'; } - return this.filterVerifiedCatch2TestExecutables(executables); + return this.filterVerifiedCatch2TestExecutables(await executables); } verifyIsCatch2TestExecutable(path: string): Promise { diff --git a/src/FsWrapper.ts b/src/FsWrapper.ts index cb3a261f..0868841d 100644 --- a/src/FsWrapper.ts +++ b/src/FsWrapper.ts @@ -37,10 +37,6 @@ export function spawnAsync( }) } -export function statSync(path: string): fs.Stats { - return fs.statSync(path); -} - export type Stats = fs.Stats; export function statAsync(path: string): Promise { diff --git a/src/test/C2TestAdapter.test.ts b/src/test/C2TestAdapter.test.ts index 75fde38c..6222459b 100644 --- a/src/test/C2TestAdapter.test.ts +++ b/src/test/C2TestAdapter.test.ts @@ -60,7 +60,6 @@ describe('C2TestAdapter', function() { let fsWatchStub: sinon.SinonStub; let c2fsStatStub: sinon.SinonStub; let c2fsReaddirSyncStub: sinon.SinonStub; - let c2fsStatSyncStub: sinon.SinonStub; function resetConfig(): Thenable { const packageJson = fse.readJSONSync( @@ -146,8 +145,6 @@ describe('C2TestAdapter', function() { c2fsStatStub.callThrough(); c2fsReaddirSyncStub.reset(); c2fsReaddirSyncStub.throws('Test isnt set properly error.'); - c2fsStatSyncStub.reset(); - c2fsStatSyncStub.throws('Test isnt set properly error.'); } before(function() { @@ -159,8 +156,6 @@ describe('C2TestAdapter', function() { c2fsStatStub = sinonSandbox.stub(fs, 'stat').named('fsStat'); c2fsReaddirSyncStub = sinonSandbox.stub(c2fs, 'readdirSync').named('c2fsReaddirSyncStub'); - c2fsStatSyncStub = - sinonSandbox.stub(c2fs, 'statSync').named('c2fsStatSyncStub'); stubsResetToMyDefault(); @@ -279,29 +274,6 @@ describe('C2TestAdapter', function() { dirContent.forEach((v: string[], k: string) => { c2fsReaddirSyncStub.withArgs(k).returns(v); }); - - c2fsStatSyncStub.callsFake((p: string) => { - if (dirContent.has(p)) - return { - isFile() { - return false; - }, - isDirectory() { - return true; - } - }; - const pa = dirContent.get(path.dirname(p)); - if (pa != undefined && pa.indexOf(path.basename(p)) != -1) - return { - isFile() { - return true; - }, - isDirectory() { - return false; - } - }; - throw Error(inspect(['c2fsStatSyncStub', p])); - }); }) after(function() { @@ -1041,7 +1013,8 @@ describe('C2TestAdapter', function() { }), new Mocha.Test( 'reload because of fswatcher event: touch', - async function() { + async function(this:Mocha.Context) { + this.slow(200); const newRoot = await doAndWaitForReloadEvent(async () => { suite1Watcher.emit( 'change', 'dummyEvent', example1.suite1.execPath); @@ -1050,7 +1023,7 @@ describe('C2TestAdapter', function() { }), // new Mocha.Test( // 'reload because of fswatcher event: touch, retry 5 times', - // async function() { + // async function(this:Mocha.Context) { // const newRoot = await doAndWaitForReloadEvent(async () => { // const w = fsExistsStub.withArgs(example1.suite1.execPath); // for (let cc = 0; cc < 3; cc++) { @@ -1070,6 +1043,7 @@ describe('C2TestAdapter', function() { new Mocha.Test( 'reload because of fswatcher event: test added', async function(this: Mocha.Context) { + this.slow(200); const testListOutput = example1.suite1.outputs[1][1].split('\n'); assert.equal(testListOutput.length, 10); @@ -1112,6 +1086,7 @@ describe('C2TestAdapter', function() { new Mocha.Test( 'reload because of fswatcher event: test deleted', async function(this: Mocha.Context) { + this.slow(200); const testListOutput = example1.suite1.outputs[1][1].split('\n'); assert.equal(testListOutput.length, 10); @@ -1175,7 +1150,7 @@ describe('C2TestAdapter', function() { t.clone()); }) - context.only('executables=[{}] and env={...}', function() { + context('executables=[{}] and env={...}', function() { before(async function() { await updateConfig('executables', [{ name: '${dirname}: ${name} (${absDirname})', @@ -1211,44 +1186,40 @@ describe('C2TestAdapter', function() { for (let t of testsForAdapterWithSuite1AndSuite2) this.addTest( t.clone()); - // it('should get execution options', async function() { - // { - // const withArgs = spawnStub.withArgs( - // example1.suite1.execPath, sinon.match.any, - // sinon.match.any); - // withArgs.onCall(withArgs.callCount) - // .callsFake((p: string, args: string[], ops: any) => { - // assert.equal( - // ops.cwd, path.join(workspaceFolderUri.path, 'cwd')); - // assert.equal(ops.env.C2LOCALTESTENV, 'c2localtestenv'); - // assert.ok(!ops.env.hasOwnProperty('C2GLOBALTESTENV')); - // assert.equal( - // ops.env.C2OVERRIDETESTENV, 'c2overridetestenv-l'); - // return new - // ChildProcessStub(example1.suite1.outputs[2][1]); - // }); - - // await adapter.run([suite1.id]); - // } - // { - // const withArgs = spawnStub.withArgs( - // example1.suite2.execPath, sinon.match.any, - // sinon.match.any); - // withArgs.onCall(withArgs.callCount) - // .callsFake((p: string, args: string[], ops: any) => { - // assert.equal( - // ops.cwd, path.join(workspaceFolderUri.path, 'cwd')); - // assert.equal(ops.env.C2LOCALTESTENV, 'c2localtestenv'); - // assert.ok(!ops.env.hasOwnProperty('C2GLOBALTESTENV')); - // assert.equal( - // ops.env.C2OVERRIDETESTENV, 'c2overridetestenv-l'); - // return new - // ChildProcessStub(example1.suite2.outputs[2][1]); - // }); - - // await adapter.run([suite2.id]); - // } - // }) + it('should get execution options', async function() { + { + const withArgs = spawnStub.withArgs( + example1.suite1.execPath, sinon.match.any, sinon.match.any); + withArgs.onCall(withArgs.callCount) + .callsFake((p: string, args: string[], ops: any) => { + assert.equal( + ops.cwd, path.join(workspaceFolderUri.path, 'cwd')); + assert.equal(ops.env.C2LOCALTESTENV, 'c2localtestenv'); + assert.ok(!ops.env.hasOwnProperty('C2GLOBALTESTENV')); + assert.equal( + ops.env.C2OVERRIDETESTENV, 'c2overridetestenv-l'); + return new ChildProcessStub(example1.suite1.outputs[2][1]); + }); + + await adapter.run([suite1.id]); + } + { + const withArgs = spawnStub.withArgs( + example1.suite2.execPath, sinon.match.any, sinon.match.any); + withArgs.onCall(withArgs.callCount) + .callsFake((p: string, args: string[], ops: any) => { + assert.equal( + ops.cwd, path.join(workspaceFolderUri.path, 'cwd')); + assert.equal(ops.env.C2LOCALTESTENV, 'c2localtestenv'); + assert.ok(!ops.env.hasOwnProperty('C2GLOBALTESTENV')); + assert.equal( + ops.env.C2OVERRIDETESTENV, 'c2overridetestenv-l'); + return new ChildProcessStub(example1.suite2.outputs[2][1]); + }); + + await adapter.run([suite2.id]); + } + }) }) }) }) @@ -1283,7 +1254,7 @@ describe('C2TestAdapter', function() { await updateConfig('executables', undefined); }) - specify.skip( + specify.skip( // TODO 'load executables=["execPath1", "execPath2Copy"] and delete second because of fswatcher event', async function() { this.slow(300); @@ -1295,14 +1266,12 @@ describe('C2TestAdapter', function() { return new ChildProcessStub(o[1]); }); - c2fsStatSyncStub.withArgs(fullPath).resolves({ - isFile() { - return true; - }, - isDirectory() { - return false; - } - }); + c2fsStatStub.withArgs(fullPath).callsFake( + (path: string, + cb: (err: NodeJS.ErrnoException|undefined, stats: fs.Stats|undefined) => + void) => { + //TODO cb({code: 'ENOENT', errno: -1}, undefined); + }); fsWatchStub.withArgs(fullPath).callsFake((path: string) => { return new class extends EventEmitter { From 5371f057f548d1ddd3bc68e466c2358859912ce9 Mon Sep 17 00:00:00 2001 From: Mate Pek Date: Tue, 23 Oct 2018 20:32:02 +0200 Subject: [PATCH 12/18] fswathcer test is ok --- src/C2TestAdapter.ts | 3 ++ src/FsWrapper.ts | 13 +++--- src/test/C2TestAdapter.test.ts | 74 +++++++++++++++++++++------------- src/test/FsWrapper.test.ts | 31 +++++++++++++- 4 files changed, 85 insertions(+), 36 deletions(-) diff --git a/src/C2TestAdapter.ts b/src/C2TestAdapter.ts index b6f2bba2..c8d602d1 100644 --- a/src/C2TestAdapter.ts +++ b/src/C2TestAdapter.ts @@ -80,6 +80,9 @@ export class C2TestAdapter implements TestAdapter, vscode.Disposable { this.disposables.forEach(d => { d.dispose(); }); + this.watchers.forEach((v) => { + v.close(); + }); } get testStates(): vscode.Event { return new Promise((resolve, reject) => { - fs.stat(path, (err: NodeJS.ErrnoException, stats: fs.Stats) => { - if (err) - reject(err); - else - resolve(stats); - }); + fs.stat( + path, (err: NodeJS.ErrnoException|null, stats: fs.Stats|undefined) => { + if (stats) + resolve(stats); + else + reject(err); + }); }); } diff --git a/src/test/C2TestAdapter.test.ts b/src/test/C2TestAdapter.test.ts index 6222459b..a8a41d97 100644 --- a/src/test/C2TestAdapter.test.ts +++ b/src/test/C2TestAdapter.test.ts @@ -118,7 +118,7 @@ describe('C2TestAdapter', function() { Promise { const origCount = testsEvents.length; await action(); - let tryCount: number = 40; + let tryCount: number = 5000; while (testsEvents.length != origCount + 2 && --tryCount > 0) await promisify(setTimeout)(10); assert.equal(testsEvents.length, origCount + 2); @@ -239,9 +239,9 @@ describe('C2TestAdapter', function() { c2fsStatStub.withArgs(suite[0]).callsFake( (path: string, - cb: (err: NodeJS.ErrnoException|undefined, stats: fs.Stats) => + cb: (err: NodeJS.ErrnoException|null, stats: fs.Stats|undefined) => void) => { - cb(undefined, { + cb(null, { isFile() { return true; }, @@ -1013,7 +1013,7 @@ describe('C2TestAdapter', function() { }), new Mocha.Test( 'reload because of fswatcher event: touch', - async function(this:Mocha.Context) { + async function(this: Mocha.Context) { this.slow(200); const newRoot = await doAndWaitForReloadEvent(async () => { suite1Watcher.emit( @@ -1021,25 +1021,35 @@ describe('C2TestAdapter', function() { }); assert.deepStrictEqual(newRoot, root); }), - // new Mocha.Test( - // 'reload because of fswatcher event: touch, retry 5 times', - // async function(this:Mocha.Context) { - // const newRoot = await doAndWaitForReloadEvent(async () => { - // const w = fsExistsStub.withArgs(example1.suite1.execPath); - // for (let cc = 0; cc < 3; cc++) { - // w.onCall(w.callCount + cc) - // .callsFake(function( - // path: string, - // cb: (err: any, exists: boolean) => void) { - // assert.equal(path, example1.suite1.execPath); - // cb(undefined, false); - // }); - // } - // assert.ok(suite1Watcher.emit( - // 'change', 'dummyEvent', example1.suite1.execPath)); - // }); - // assert.deepStrictEqual(newRoot, root); - // }), + new Mocha.Test( + 'reload because of fswatcher event: touch, retry 5 times', + async function(this: Mocha.Context) { + this.timeout(10000); + this.slow(6500); + const newRoot = await doAndWaitForReloadEvent(async () => { + const w = c2fsStatStub.withArgs(example1.suite1.execPath); + for (let cc = 0; cc < 5; cc++) { + w.onCall(w.callCount + cc) + .callsFake( + (path: string, + cb: ( + err: NodeJS.ErrnoException|null|any, + stats: fs.Stats|undefined) => void) => { + cb({ + code: 'ENOENT', + errno: -2, + message: 'ENOENT', + path: path, + syscall: 'stat' + }, + undefined); + }); + } + assert.ok(suite1Watcher.emit( + 'change', 'dummyEvent', example1.suite1.execPath)); + }); + assert.deepStrictEqual(newRoot, root); + }), new Mocha.Test( 'reload because of fswatcher event: test added', async function(this: Mocha.Context) { @@ -1267,11 +1277,19 @@ describe('C2TestAdapter', function() { }); c2fsStatStub.withArgs(fullPath).callsFake( - (path: string, - cb: (err: NodeJS.ErrnoException|undefined, stats: fs.Stats|undefined) => - void) => { - //TODO cb({code: 'ENOENT', errno: -1}, undefined); - }); + (path: string, + cb: ( + err: NodeJS.ErrnoException|null|any, + stats: fs.Stats|undefined) => void) => { + cb({ + code: 'ENOENT', + errno: -2, + message: 'ENOENT', + path: path, + syscall: 'stat' + }, + undefined); + }); fsWatchStub.withArgs(fullPath).callsFake((path: string) => { return new class extends EventEmitter { diff --git a/src/test/FsWrapper.test.ts b/src/test/FsWrapper.test.ts index df25dbe4..c4a9fa10 100644 --- a/src/test/FsWrapper.test.ts +++ b/src/test/FsWrapper.test.ts @@ -1,5 +1,13 @@ import * as assert from 'assert'; -import {spawnAsync} from '../FsWrapper'; +import * as path from 'path'; +import * as vscode from 'vscode'; + +import {spawnAsync, statAsync} from '../FsWrapper'; + +assert.notEqual(vscode.workspace.workspaceFolders, undefined); +assert.equal(vscode.workspace.workspaceFolders!.length, 1); + +const workspaceFolderUri = vscode.workspace.workspaceFolders![0].uri; describe('FsWrapper.spawnAsync', function() { it('echoes', async function() { @@ -20,4 +28,23 @@ describe('FsWrapper.spawnAsync', function() { assert.equal(r.status, 0); } }) -}); \ No newline at end of file +}) + +describe('FsWrapper.statAsync', function() { + it('doesnt exists', async function() { + try { + await statAsync('notexists'); + assert.ok(false); + } catch (e) { + assert.equal(e.code, 'ENOENT'); + assert.equal(e.errno, -2); + } + }) + + it('exists', async function() { + const res = await statAsync( + path.join(workspaceFolderUri.path, 'FsWrapper.test.js')); + assert.ok(res.isFile()); + assert.ok(!res.isDirectory()); + }) +}) \ No newline at end of file From a65307f64748f5c39b9969d39b7aabc38d31aa9b Mon Sep 17 00:00:00 2001 From: Mate Pek Date: Tue, 23 Oct 2018 21:16:46 +0200 Subject: [PATCH 13/18] deleted test timeout --- src/test/C2TestAdapter.test.ts | 87 +++++++++++++++++++++++----------- 1 file changed, 60 insertions(+), 27 deletions(-) diff --git a/src/test/C2TestAdapter.test.ts b/src/test/C2TestAdapter.test.ts index a8a41d97..a9d635a5 100644 --- a/src/test/C2TestAdapter.test.ts +++ b/src/test/C2TestAdapter.test.ts @@ -114,12 +114,13 @@ describe('C2TestAdapter', function() { return adapter!; } - async function doAndWaitForReloadEvent(action: Function): - Promise { + async function doAndWaitForReloadEvent( + action: Function, timeout: number = 1000): Promise { const origCount = testsEvents.length; await action(); - let tryCount: number = 5000; - while (testsEvents.length != origCount + 2 && --tryCount > 0) + const start = Date.now(); + while (testsEvents.length != origCount + 2 && + (Date.now() - start) < timeout) await promisify(setTimeout)(10); assert.equal(testsEvents.length, origCount + 2); const e = testsEvents[testsEvents.length - 1]!; @@ -1047,7 +1048,7 @@ describe('C2TestAdapter', function() { } assert.ok(suite1Watcher.emit( 'change', 'dummyEvent', example1.suite1.execPath)); - }); + }, 10000); assert.deepStrictEqual(newRoot, root); }), new Mocha.Test( @@ -1264,37 +1265,39 @@ describe('C2TestAdapter', function() { await updateConfig('executables', undefined); }) - specify.skip( // TODO + specify.only( 'load executables=["execPath1", "execPath2Copy"] and delete second because of fswatcher event', - async function() { - this.slow(300); - + async function(this: Mocha.Context) { + this.timeout(40000); const fullPath = path.join(workspaceFolderUri.path, 'execPath2Copy'); - for (let o of example1.suite2.outputs) - spawnStub.withArgs(example1.suite2.outputs, o[0]).callsFake(() => { - return new ChildProcessStub(o[1]); + for (let scenario of example1.suite2.outputs) { + spawnStub.withArgs(fullPath, scenario[0]).callsFake(function() { + return new ChildProcessStub(scenario[1]); }); + } c2fsStatStub.withArgs(fullPath).callsFake( (path: string, cb: ( - err: NodeJS.ErrnoException|null|any, + err: NodeJS.ErrnoException|null, stats: fs.Stats|undefined) => void) => { - cb({ - code: 'ENOENT', - errno: -2, - message: 'ENOENT', - path: path, - syscall: 'stat' - }, - undefined); + cb(null, { + isFile() { + return true; + }, + isDirectory() { + return false; + } + }); }); fsWatchStub.withArgs(fullPath).callsFake((path: string) => { - return new class extends EventEmitter { + const e = new class extends EventEmitter { close() {} }; + watchers.set(path, e); + return e; }); await updateConfig('executables', ['execPath1', 'execPath2Copy']) @@ -1302,13 +1305,43 @@ describe('C2TestAdapter', function() { await adapter.load(); - // not finished - // const withArgs = spawnStub.withArgs( - // example1.suite2.execPath, example1.suite2.outputs[1][0]); - // withArgs.onCall(withArgs.callCount).throws( - // 'dummy error for testing (should be handled)'); + assert.equal( + (testsEvents[1]).suite.children.length, 2); + assert.ok(watchers.has(fullPath)); + const watcher = watchers.get(fullPath)!; + const start = Date.now(); + + const newRoot = await doAndWaitForReloadEvent(async () => { + c2fsStatStub.withArgs(fullPath).callsFake( + (path: string, + cb: ( + err: NodeJS.ErrnoException|null|any, + stats: fs.Stats|undefined) => void) => { + cb({ + code: 'ENOENT', + errno: -2, + message: 'ENOENT', + path: path, + syscall: 'stat' + }, + undefined); + }); + assert.ok( + watcher.emit('change', 'dummyEvent', example1.suite1.execPath)); + }, 40000); + + const elapsed = Date.now() - start; + assert.equal(newRoot.children.length, 1); + assert.ok(25000 < elapsed, inspect(elapsed)); + assert.ok(elapsed < 35000, inspect(elapsed)); // restore + for (let scenario of example1.suite2.outputs) { + spawnStub.withArgs(fullPath, scenario[0]).throws(); + } + c2fsStatStub.withArgs(fullPath).throws(); + fsWatchStub.withArgs(fullPath).throws(); + disposeAdapterAndSubscribers(); await updateConfig('executables', undefined); }) }) From 9f4d2971fad77623bc4dd2d7fdea47932abbd20f Mon Sep 17 00:00:00 2001 From: Mate Pek Date: Tue, 23 Oct 2018 21:38:26 +0200 Subject: [PATCH 14/18] before fswatcher optionaliztion --- CHANGELOG.md | 6 ++++-- README.md | 1 + package.json | 10 +++++++++- src/C2TestAdapter.ts | 21 ++++++++++++++------- src/test/C2TestAdapter.test.ts | 14 ++++++++------ 5 files changed, 36 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7c74856..7ad85ff5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,9 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [1.1.3] +## [1.2.0] -Bugfix release +### Added + +- Configuration: `catch2TestExplorer.defaultExecWatchTimeout`: Test executables are being watched. In case of one compiles too much this variable can help with it. ## [1.1.2] diff --git a/README.md b/README.md index 9c077ca9..fdbb6a84 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ This adapter doesn't support everything. | `catch2TestExplorer.defaultEnv` | Default environment variables to be set when running the tests, if it isn't provided in 'executables'. (Resolves: ${workspaceFolder}) | | `catch2TestExplorer.defaultCwd` | The working directory where the test is run (relative to the workspace folder or absolue path), if it isn't provided in 'executables'. (Resolves: ${workspaceFolder}) | | `catch2TestExplorer.defaultRngSeed` | Specify a seed for the Random Number Generator. For details see [Catch2 documentation](https://github.com/catchorg/Catch2/blob/master/docs/command-line.md#rng-seed) | +| `catch2TestExplorer.defaultExecWatchTimeout` | Test executables are being watched. In case of one compiles too much this variable can help with it. | | `catch2TestExplorer.workerMaxNumber` | The variable maximize the number of the parallel test execution. | | `catch2TestExplorer.enableSourceDecoration` | Sets the source code decorations: Errored lines will be highlited. | | `catch2TestExplorer.debugConfigurationTemplate` | Set the necessary debug configuraitons and the debug button will work. Details: [below](#catch2TestExplorer.debugConfigurationTemplate) | diff --git a/package.json b/package.json index 76075bb2..ecc3471d 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "icon": "resources/icon.png", "author": "Mate Pek", "publisher": "matepek", - "version": "1.1.3", + "version": "1.2.0", "license": "Unlicense", "homepage": "https://github.com/matepek/vscode-catch2-test-adapter", "repository": { @@ -120,6 +120,14 @@ "default": null, "scope": "resource" }, + "catch2TestExplorer.defaultExecWatchTimeout": { + "description": "Test executables are being watched. In case of one compiles too much this variable can help with it.", + "type": [ + "number" + ], + "default": 10000, + "scope": "resource" + }, "catch2TestExplorer.workerMaxNumber": { "description": "The variable maximize the number of the parallel test execution.", "type": "number", diff --git a/src/C2TestAdapter.ts b/src/C2TestAdapter.ts index c8d602d1..118cf884 100644 --- a/src/C2TestAdapter.ts +++ b/src/C2TestAdapter.ts @@ -113,9 +113,10 @@ export class C2TestAdapter implements TestAdapter, vscode.Disposable { const allTests = this.allTests; // alltest may has changed watcher.on('change', (eventType: string, filename: string) => { - const x = (exists: boolean, remainingIteration: number, delay: number): - Promise => { - if (remainingIteration <= 0) { + const x = + (exists: boolean, startTime: number, timeout: number, + delay: number): Promise => { + if ((Date.now() - startTime) > timeout) { watcher!.close(); this.watchers.delete(suite.execPath); this.testsEmitter.fire({type: 'started'}); @@ -135,8 +136,7 @@ export class C2TestAdapter implements TestAdapter, vscode.Disposable { {type: 'finished', suite: this.allTests}); this.log.warn(inspect(err)); return x( - false, remainingIteration - 1, - Math.min(delay * 2, 2000)); + false, startTime, timeout, Math.min(delay * 2, 2000)); }); } return promisify(setTimeout)(Math.min(delay * 2, 2000)) @@ -144,7 +144,7 @@ export class C2TestAdapter implements TestAdapter, vscode.Disposable { return c2fs.existsAsync(suite.execPath) .then((exists: boolean) => { return x( - exists, remainingIteration - 1, + exists, startTime, timeout, Math.min(delay * 2, 2000)); }); }); @@ -152,7 +152,9 @@ export class C2TestAdapter implements TestAdapter, vscode.Disposable { // change event can arrive during debug session on osx (why?) if (!this.isDebugging) { - x(false, 10, 64); + // TODO filter multiple events and dont mess with 'load' + x(false, Date.now(), + this.getDefaultExecWatchTimeout(this.getConfiguration()), 64); } }); } catch (e) { @@ -380,6 +382,11 @@ export class C2TestAdapter implements TestAdapter, vscode.Disposable { return config.get('defaultRngSeed', null); } + private getDefaultExecWatchTimeout(config: vscode.WorkspaceConfiguration): + number { + return config.get('defaultExecWatchTimeout', 10000); + } + private getWorkerMaxNumber(config: vscode.WorkspaceConfiguration): number { return config.get('workerMaxNumber', 4); } diff --git a/src/test/C2TestAdapter.test.ts b/src/test/C2TestAdapter.test.ts index a9d635a5..0c6e82f7 100644 --- a/src/test/C2TestAdapter.test.ts +++ b/src/test/C2TestAdapter.test.ts @@ -286,8 +286,6 @@ describe('C2TestAdapter', function() { }) describe('load', function() { - this.enableTimeouts(false); // TODO - const uniqueIdC = new Set(); let adapter: TestAdapter; @@ -1265,10 +1263,13 @@ describe('C2TestAdapter', function() { await updateConfig('executables', undefined); }) - specify.only( + specify( 'load executables=["execPath1", "execPath2Copy"] and delete second because of fswatcher event', async function(this: Mocha.Context) { - this.timeout(40000); + const watchTimeout = 5000; + await updateConfig('defaultExecWatchTimeout', watchTimeout); + this.timeout(watchTimeout+ 2500/* because of 'delay' */); + this.slow(watchTimeout+ 2500/* because of 'delay' */); const fullPath = path.join(workspaceFolderUri.path, 'execPath2Copy'); for (let scenario of example1.suite2.outputs) { @@ -1332,8 +1333,8 @@ describe('C2TestAdapter', function() { const elapsed = Date.now() - start; assert.equal(newRoot.children.length, 1); - assert.ok(25000 < elapsed, inspect(elapsed)); - assert.ok(elapsed < 35000, inspect(elapsed)); + assert.ok(watchTimeout < elapsed, inspect(elapsed)); + assert.ok(elapsed < watchTimeout + 2400, inspect(elapsed)); // restore for (let scenario of example1.suite2.outputs) { @@ -1343,6 +1344,7 @@ describe('C2TestAdapter', function() { fsWatchStub.withArgs(fullPath).throws(); disposeAdapterAndSubscribers(); await updateConfig('executables', undefined); + await updateConfig('defaultExecWatchTimeout', undefined); }) }) }) \ No newline at end of file From 95b911ed3a341a1c86770f704459c71099c5511e Mon Sep 17 00:00:00 2001 From: Mate Pek Date: Tue, 23 Oct 2018 23:51:31 +0200 Subject: [PATCH 15/18] suite3 begins --- src/test/example1.ts | 1578 ++++++++++++++++++++++++++++++++++- src/test/suite3.cpp | 65 ++ src/test/suite3generator.sh | 77 ++ 3 files changed, 1719 insertions(+), 1 deletion(-) create mode 100644 src/test/suite3.cpp create mode 100755 src/test/suite3generator.sh diff --git a/src/test/example1.ts b/src/test/example1.ts index 50783198..fc6258c1 100644 --- a/src/test/example1.ts +++ b/src/test/example1.ts @@ -466,6 +466,1581 @@ export const example1 = new class { ]; }; + readonly suite3 = new class { + readonly execPath = path.join(workspaceFolderUri.path, 'execPath3'); + + readonly outputs: [string[], string][] = [ + + [ + ['--help'], ` +Catch v2.4.1 +usage: + suite3 [ ... ] options + +where options are: + -?, -h, --help display usage information + -l, --list-tests list all/matching test cases + -t, --list-tags list all/matching tags + -s, --success include successful tests in + output + -b, --break break into debugger on failure + -e, --nothrow skip exception tests + -i, --invisibles show invisibles (tabs, newlines) + -o, --out output filename + -r, --reporter reporter to use (defaults to + console) + -n, --name suite name + -a, --abort abort at first failure + -x, --abortx abort after x failures + -w, --warn enable warnings + -d, --durations show test durations + -f, --input-file load test names to run from a + file + -#, --filenames-as-tags adds a tag for the filename + -c, --section
specify section to run + -v, --verbosity set output verbosity + --list-test-names-only list all/matching test cases + names only + --list-reporters list all reporters + --order test case order (defaults to + decl) + --rng-seed <'time'|number> set a specific seed for random + numbers + --use-colour should output be colourised + --libidentify report name and version according + to libidentify standard + --wait-for-keypress waits for a keypress before + exiting + --benchmark-resolution-multiple multiple of clock resolution to + run benchmarks + +For more detailed usage please see the project docs + +` + ], + [ + ['[.],*', '--verbosity', 'high', '--list-tests', '--use-colour', 'no'], + ` ./suite3 [.],* --verbosity high --list-tests --use-colour no` + ], + [ + ['--reporter', 'xml', '--durations', 'yes'], + ` + + + + + + + + + +
+
+
+
+ + + std::false_type::value + + + false + + + +
+ +
+ +
+ +
+
+
+
+ +
+ +
+ +
+
+
+
+
+ + + std::false_type::value + + + false + + + +
+ +
+ +
+ +
+
+
+
+ +
+ +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+` + ], + [ + ['--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], + ` + + + + + + + + + + +
+
+
+
+ + + std::false_type::value + + + false + + + +
+ +
+ +
+ +
+
+
+
+ +
+ +
+ +
+
+
+
+
+ + + std::false_type::value + + + false + + + +
+ +
+ +
+ +
+
+
+
+ +
+ +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+` + ], + [ + ['test name\,with\,colon', '--reporter', 'xml', '--durations', 'yes'], + ` + + + + + + + + + +` + ], + [ + ['*test name with space ', '--reporter', 'xml', '--durations', 'yes'], + ` + + + + + + + + + +` + ], + [ + ['SECTION tree', '--reporter', 'xml', '--durations', 'yes'], + ` + + + +
+
+
+
+ + + std::false_type::value + + + false + + + +
+ +
+ +
+ +
+
+
+
+ +
+ +
+ +
+
+
+
+
+ + + std::false_type::value + + + false + + + +
+ +
+ +
+ +
+
+
+
+ +
+ +
+ +
+ +
+ +
+ +
+` + ], + [ + ['spec ! char', '--reporter', 'xml', '--durations', 'yes'], + ` + + + + + + + + + +` + ], + [ + ['spec @ char', '--reporter', 'xml', '--durations', 'yes'], + ` + + + + + + + + + +` + ], + [ + ['spec # char', '--reporter', 'xml', '--durations', 'yes'], + ` + + + + + + + + + +` + ], + [ + ['spec $ char', '--reporter', 'xml', '--durations', 'yes'], + ` + + + + + + + + + +` + ], + [ + ['spec % char', '--reporter', 'xml', '--durations', 'yes'], + ` + + + + + + + + + +` + ], + [ + ['spec ^ char', '--reporter', 'xml', '--durations', 'yes'], + ` + + + + + + + + + +` + ], + [ + ['spec & char', '--reporter', 'xml', '--durations', 'yes'], + ` + + + + + + + + + +` + ], + [ + ['spec * char', '--reporter', 'xml', '--durations', 'yes'], + ` + + + + + + + + + +` + ], + [ + ['spec \(a\) char', '--reporter', 'xml', '--durations', 'yes'], + ` + + + + + + + + + +` + ], + [ + ['spec {a} char', '--reporter', 'xml', '--durations', 'yes'], + ` + + + + + + + + + +` + ], + [ + ['spec \[a] char', '--reporter', 'xml', '--durations', 'yes'], + ` + + + + + + + + + +` + ], + [ + ['spec ; char', '--reporter', 'xml', '--durations', 'yes'], + ` + + + + + + + + + +` + ], + [ + ['spec \' char', '--reporter', 'xml', '--durations', 'yes'], + ` + + + + + + + + + +` + ], + [ + ['spec \\ char', '--reporter', 'xml', '--durations', 'yes'], + ` + + + + + + + + + +` + ], + [ + ['spec \, char', '--reporter', 'xml', '--durations', 'yes'], + ` + + + + + + + + + +` + ], + [ + ['spec . char', '--reporter', 'xml', '--durations', 'yes'], + ` + + + + + + + + + +` + ], + [ + ['spec / char', '--reporter', 'xml', '--durations', 'yes'], + ` + + + + + + + + + +` + ], + [ + ['spec < char', '--reporter', 'xml', '--durations', 'yes'], + ` + + + + + + + + + +` + ], + [ + ['spec > char', '--reporter', 'xml', '--durations', 'yes'], + ` + + + + + + + + + +` + ], + [ + ['spec ? char', '--reporter', 'xml', '--durations', 'yes'], + ` + + + + + + + + + +` + ], + [ + ['spec - char', '--reporter', 'xml', '--durations', 'yes'], + ` + + + + + + + + + +` + ], + [ + ['spec = char', '--reporter', 'xml', '--durations', 'yes'], + ` + + + + + + + + + +` + ], + [ + ['spec _ char', '--reporter', 'xml', '--durations', 'yes'], + ` + + + + + + + + + +` + ], + [ + ['spec + char', '--reporter', 'xml', '--durations', 'yes'], + ` + + + + + + + + + +` + ], + [ + ['spec ~ char', '--reporter', 'xml', '--durations', 'yes'], + ` + + + + + + + + + +` + ], + [ + ['spec \` char', '--reporter', 'xml', '--durations', 'yes'], + ` + + + + + + + + + +` + ], + [ + ['spec § char', '--reporter', 'xml', '--durations', 'yes'], + ` + + + + + + + + + +` + ], + [ + ['spec ± char', '--reporter', 'xml', '--durations', 'yes'], + ` + + + + + + + + + +` + ], + [ + ['spec " char', '--reporter', 'xml', '--durations', 'yes'], + ` + + + + + + + + + +` + ], + [ + ['spec | char', '--reporter', 'xml', '--durations', 'yes'], + ` + + + + + + + + + +` + ], + [ + [ + 'test name\,with\,colon', '--reporter', 'xml', '--durations', 'yes', + '--rng-seed', '2' + ], + ` + + + + + + + + + + +` + ], + [ + [ + '*test name with space ', '--reporter', 'xml', '--durations', 'yes', + '--rng-seed', '2' + ], + ` + + + + + + + + + + +` + ], + [ + [ + 'SECTION tree', '--reporter', 'xml', '--durations', 'yes', + '--rng-seed', '2' + ], + ` + + + + +
+
+
+
+ + + std::false_type::value + + + false + + + +
+ +
+ +
+ +
+
+
+
+ +
+ +
+ +
+
+
+
+
+ + + std::false_type::value + + + false + + + +
+ +
+ +
+ +
+
+
+
+ +
+ +
+ +
+ +
+ +
+ +
+` + ], + [ + [ + 'spec ! char', '--reporter', 'xml', '--durations', 'yes', + '--rng-seed', '2' + ], + ` + + + + + + + + + + +` + ], + [ + [ + 'spec @ char', '--reporter', 'xml', '--durations', 'yes', + '--rng-seed', '2' + ], + ` + + + + + + + + + + +` + ], + [ + [ + 'spec # char', '--reporter', 'xml', '--durations', 'yes', + '--rng-seed', '2' + ], + ` + + + + + + + + + + +` + ], + [ + [ + 'spec $ char', '--reporter', 'xml', '--durations', 'yes', + '--rng-seed', '2' + ], + ` + + + + + + + + + + +` + ], + [ + [ + 'spec % char', '--reporter', 'xml', '--durations', 'yes', + '--rng-seed', '2' + ], + ` + + + + + + + + + + +` + ], + [ + [ + 'spec ^ char', '--reporter', 'xml', '--durations', 'yes', + '--rng-seed', '2' + ], + ` + + + + + + + + + + +` + ], + [ + [ + 'spec & char', '--reporter', 'xml', '--durations', 'yes', + '--rng-seed', '2' + ], + ` + + + + + + + + + + +` + ], + [ + [ + 'spec * char', '--reporter', 'xml', '--durations', 'yes', + '--rng-seed', '2' + ], + ` + + + + + + + + + + +` + ], + [ + [ + 'spec \(a\) char', '--reporter', 'xml', '--durations', 'yes', + '--rng-seed', '2' + ], + ` + + + + + + + + + + +` + ], + [ + [ + 'spec {a} char', '--reporter', 'xml', '--durations', 'yes', + '--rng-seed', '2' + ], + ` + + + + + + + + + + +` + ], + [ + [ + 'spec \[a] char', '--reporter', 'xml', '--durations', 'yes', + '--rng-seed', '2' + ], + ` + + + + + + + + + + +` + ], + [ + [ + 'spec ; char', '--reporter', 'xml', '--durations', 'yes', + '--rng-seed', '2' + ], + ` + + + + + + + + + + +` + ], + [ + [ + 'spec \' char', '--reporter', 'xml', '--durations', 'yes', + '--rng-seed', '2' + ], + ` + + + + + + + + + + +` + ], + [ + [ + 'spec \\ char', '--reporter', 'xml', '--durations', 'yes', + '--rng-seed', '2' + ], + ` + + + + + + + + + + +` + ], + [ + [ + 'spec \, char', '--reporter', 'xml', '--durations', 'yes', + '--rng-seed', '2' + ], + ` + + + + + + + + + + +` + ], + [ + [ + 'spec . char', '--reporter', 'xml', '--durations', 'yes', + '--rng-seed', '2' + ], + ` + + + + + + + + + + +` + ], + [ + [ + 'spec / char', '--reporter', 'xml', '--durations', 'yes', + '--rng-seed', '2' + ], + ` + + + + + + + + + + +` + ], + [ + [ + 'spec < char', '--reporter', 'xml', '--durations', 'yes', + '--rng-seed', '2' + ], + ` + + + + + + + + + + +` + ], + [ + [ + 'spec > char', '--reporter', 'xml', '--durations', 'yes', + '--rng-seed', '2' + ], + ` + + + + + + + + + + +` + ], + [ + [ + 'spec ? char', '--reporter', 'xml', '--durations', 'yes', + '--rng-seed', '2' + ], + ` + + + + + + + + + + +` + ], + [ + [ + 'spec - char', '--reporter', 'xml', '--durations', 'yes', + '--rng-seed', '2' + ], + ` + + + + + + + + + + +` + ], + [ + [ + 'spec = char', '--reporter', 'xml', '--durations', 'yes', + '--rng-seed', '2' + ], + ` + + + + + + + + + + +` + ], + [ + [ + 'spec _ char', '--reporter', 'xml', '--durations', 'yes', + '--rng-seed', '2' + ], + ` + + + + + + + + + + +` + ], + [ + [ + 'spec + char', '--reporter', 'xml', '--durations', 'yes', + '--rng-seed', '2' + ], + ` + + + + + + + + + + +` + ], + [ + [ + 'spec ~ char', '--reporter', 'xml', '--durations', 'yes', + '--rng-seed', '2' + ], + ` + + + + + + + + + + +` + ], + [ + [ + 'spec \` char', '--reporter', 'xml', '--durations', 'yes', + '--rng-seed', '2' + ], + ` + + + + + + + + + + +` + ], + [ + [ + 'spec § char', '--reporter', 'xml', '--durations', 'yes', + '--rng-seed', '2' + ], + ` + + + + + + + + + + +` + ], + [ + [ + 'spec ± char', '--reporter', 'xml', '--durations', 'yes', + '--rng-seed', '2' + ], + ` + + + + + + + + + + +` + ], + [ + [ + 'spec " char', '--reporter', 'xml', '--durations', 'yes', + '--rng-seed', '2' + ], + ` + + + + + + + + + + +` + ], + [ + [ + 'spec | char', '--reporter', 'xml', '--durations', 'yes', + '--rng-seed', '2' + ], + ` + + + + + + + + + + +` + ], + + ]; + }; + assertWithoutChildren(root: TestSuiteInfo, uniqeIdContainer?: Set) { assert.equal(root.type, 'suite'); assert.equal(root.label, 'AllTests'); @@ -479,6 +2054,7 @@ export const example1 = new class { readonly outputs: [string, [string[], string][]][] = [ [this.suite1.execPath, this.suite1.outputs], - [this.suite2.execPath, this.suite2.outputs] + [this.suite2.execPath, this.suite2.outputs], + [this.suite3.execPath, this.suite3.outputs], ]; }; \ No newline at end of file diff --git a/src/test/suite3.cpp b/src/test/suite3.cpp new file mode 100644 index 00000000..596136ef --- /dev/null +++ b/src/test/suite3.cpp @@ -0,0 +1,65 @@ +#define CATCH_CONFIG_MAIN +#include + +// clang-format off +// c++ -x c++ -std=c++17 -I ../Catch2/single_include -O0 -g -o suite3 ../vscode-catch2-test-adapter/src/test/suite3.cpp +// clang-format on + +TEST_CASE("test name,with,colon", "tag1") { + // + REQUIRE(std::true_type::value); + // +} + +TEST_CASE(" test name with space ") { + // + REQUIRE(std::true_type::value); + // +} + +TEST_CASE("SECTION tree") { + SECTION("1") { + SECTION("2") { + SECTION("3") { + SECTION("4") { REQUIRE(std::false_type::value); } + } + } + SECTION("2-2") { + SECTION("3") { + SECTION("4") { REQUIRE(std::false_type::value); } + } + } + } +} + +TEST_CASE("name with * character") {} +TEST_CASE("spec ! char") {} +TEST_CASE("spec @ char") {} +TEST_CASE("spec # char") {} +TEST_CASE("spec $ char") {} +TEST_CASE("spec % char") {} +TEST_CASE("spec ^ char") {} +TEST_CASE("spec & char") {} +TEST_CASE("spec * char") {} +TEST_CASE("spec (a) char") {} +TEST_CASE("spec {a} char") {} +TEST_CASE("spec [a] char") {} +TEST_CASE("spec ; char") {} +TEST_CASE("spec ' char") {} +TEST_CASE("spec \\ char") {} +TEST_CASE("spec , char") {} +TEST_CASE("spec . char") {} +TEST_CASE("spec / char") {} +TEST_CASE("spec < char") {} +TEST_CASE("spec > char") {} +TEST_CASE("spec ? char") {} +TEST_CASE("spec - char") {} +TEST_CASE("spec = char") {} +TEST_CASE("spec _ char") {} +TEST_CASE("spec + char") {} +TEST_CASE("spec ~ char") {} +TEST_CASE("spec ` char") {} +TEST_CASE("spec § char") {} +TEST_CASE("spec ± char") {} +TEST_CASE("spec \" char") {} +TEST_CASE("spec | char") {} diff --git a/src/test/suite3generator.sh b/src/test/suite3generator.sh new file mode 100755 index 00000000..3bf4da01 --- /dev/null +++ b/src/test/suite3generator.sh @@ -0,0 +1,77 @@ + +echo "" >x.txt + +echo -n "[['--help'], \`" >>x.txt; ./suite3 "[.],*" --verbosity high --help >>x.txt; echo "\`]," >>x.txt; +echo -n "[['[.],*', '--verbosity', 'high', '--list-tests', '--use-colour', 'no'], \`" >>x.txt ./suite3 "[.],*" --verbosity high --list-tests --use-colour no >>x.txt; echo "\`]," >>x.txt ; + +echo -n "[['--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; + +echo -n "[['test name\,with\,colon', '--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 "test name\,with\,colon" --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['*test name with space ', '--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 "*test name with space " --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['SECTION tree', '--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 "SECTION tree" --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec ! char', '--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 "spec ! char" --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec @ char', '--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 "spec @ char" --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec # char', '--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 "spec # char" --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec $ char', '--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 "spec $ char" --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec % char', '--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 "spec % char" --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec ^ char', '--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 "spec ^ char" --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec & char', '--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 "spec & char" --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec * char', '--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 "spec * char" --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec \(a\) char', '--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 "spec (a) char" --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec {a} char', '--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 "spec {a} char" --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec \[a] char', '--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 "spec \[a] char" --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec ; char', '--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 "spec ; char" --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec \\' char', '--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 "spec ' char" --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec \\\\ char', '--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 "spec \\\ char" --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec \, char', '--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 "spec \, char" --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec . char', '--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 "spec . char" --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec / char', '--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 "spec / char" --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec < char', '--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 "spec < char" --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec > char', '--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 "spec > char" --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec ? char', '--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 "spec ? char" --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec - char', '--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 "spec - char" --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec = char', '--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 "spec = char" --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec _ char', '--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 "spec _ char" --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec + char', '--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 "spec + char" --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec ~ char', '--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 "spec ~ char" --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec \\\` char', '--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 "spec \` char" --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec § char', '--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 "spec § char" --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec ± char', '--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 "spec ± char" --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec \" char', '--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 "spec \" char" --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec | char', '--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 "spec | char" --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; + +echo -n "[['test name\,with\,colon', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 "test name\,with\,colon" --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['*test name with space ', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 "*test name with space " --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['SECTION tree', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 "SECTION tree" --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec ! char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 "spec ! char" --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec @ char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 "spec @ char" --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec # char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 "spec # char" --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec $ char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 "spec $ char" --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec % char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 "spec % char" --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec ^ char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 "spec ^ char" --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec & char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 "spec & char" --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec * char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 "spec * char" --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec \(a\) char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 "spec (a) char" --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec {a} char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 "spec {a} char" --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec \[a] char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 "spec \[a] char" --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec ; char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 "spec ; char" --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec \\' char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 "spec ' char" --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec \\\\ char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 "spec \\\ char" --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec \, char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 "spec \, char" --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec . char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 "spec . char" --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec / char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 "spec / char" --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec < char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 "spec < char" --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec > char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 "spec > char" --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec ? char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 "spec ? char" --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec - char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 "spec - char" --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec = char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 "spec = char" --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec _ char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 "spec _ char" --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec + char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 "spec + char" --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec ~ char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 "spec ~ char" --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec \\\` char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 "spec \` char" --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec § char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 "spec § char" --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec ± char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 "spec ± char" --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec \" char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 "spec \" char" --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['spec | char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 "spec | char" --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; + From fd041089f2b84ad38c7387e939bad2d9ad33e875 Mon Sep 17 00:00:00 2001 From: Mate Pek Date: Wed, 24 Oct 2018 01:44:35 +0200 Subject: [PATCH 16/18] suite3 passes --- src/C2AllTestSuiteInfo.ts | 5 +- src/C2TestInfo.ts | 7 +- src/C2TestSuiteInfo.ts | 22 +++--- src/test/C2TestAdapter.test.ts | 77 ++++++++++++++++++-- src/test/example1.ts | 128 ++++++++++++++++++++++++++++----- src/test/suite3generator.sh | 2 +- 6 files changed, 205 insertions(+), 36 deletions(-) diff --git a/src/C2AllTestSuiteInfo.ts b/src/C2AllTestSuiteInfo.ts index 029417be..de546efd 100644 --- a/src/C2AllTestSuiteInfo.ts +++ b/src/C2AllTestSuiteInfo.ts @@ -91,9 +91,10 @@ export class C2AllTestSuiteInfo implements TestSuiteInfo { } const ps: Promise[] = []; - this.children.forEach(child => { + for (let i = 0; i < this.children.length; i++) { + const child = this.children[i]; ps.push(child.run(testSet)); - }); + } if (testSet.size > 0) { this.adapter.log.error('Some tests have remained.'); diff --git a/src/C2TestInfo.ts b/src/C2TestInfo.ts index 0b4360b3..79a176cb 100644 --- a/src/C2TestInfo.ts +++ b/src/C2TestInfo.ts @@ -34,8 +34,11 @@ export class C2TestInfo implements TestInfo { } getEscapedTestName(): string { - let t = this.testNameFull.replace(',', '\\,').replace('[', '\\['); - if (t[0] == ' ') t = '*' + t.substr(1); + let t = this.testNameFull; + t = t.replace(/,/g, '\\,') + t = t.replace(/\[/g, '\\['); + t = t.replace(/\*/g, '\\*'); + if (t.startsWith(' ')) t = '*' + t.substr(1); return t; } diff --git a/src/C2TestSuiteInfo.ts b/src/C2TestSuiteInfo.ts index 1acdfbf0..a3535056 100644 --- a/src/C2TestSuiteInfo.ts +++ b/src/C2TestSuiteInfo.ts @@ -80,17 +80,19 @@ export class C2TestSuiteInfo implements TestSuiteInfo { this.proc = undefined; if (tests.delete(this.id)) { - this.children.forEach(c => { + for (let i = 0; i < this.children.length; i++) { + const c = this.children[i]; tests.delete(c.id); - }); + } return this.runInner('all'); } else { let childrenToRun: C2TestInfo[] = []; - this.children.forEach(c => { + for (let i = 0; i < this.children.length; i++) { + const c = this.children[i]; if (tests.delete(c.id)) childrenToRun.push(c); - }); + } if (childrenToRun.length == 0) return Promise.resolve(); @@ -113,18 +115,20 @@ export class C2TestSuiteInfo implements TestSuiteInfo { const execParams: string[] = []; if (childrenToRun != 'all') { let testNames: string[] = []; - childrenToRun.forEach(c => { + for (let i = 0; i < childrenToRun.length; i++) { + const c = childrenToRun[i]; /*',' has special meaning */ testNames.push(c.getEscapedTestName()); - }); + } execParams.push(testNames.join(',')); } else { - this.children.forEach(c => { + for (let i = 0; i < this.children.length; i++) { + const c = this.children[i]; if (c.skipped) { this.adapter.testStatesEmitter.fire(c.getStartEvent()); this.adapter.testStatesEmitter.fire(c.getSkippedEvent()); } - }); + } } execParams.push('--reporter'); execParams.push('xml'); @@ -164,7 +168,7 @@ export class C2TestSuiteInfo implements TestSuiteInfo { const b = data.buffer.indexOf(' { assert.equal( @@ -1210,11 +1210,13 @@ describe('C2TestAdapter', function() { return new ChildProcessStub(example1.suite1.outputs[2][1]); }); + const cc = withArgs.callCount; await adapter.run([suite1.id]); + assert.equal(withArgs.callCount, cc + 1) } { const withArgs = spawnStub.withArgs( - example1.suite2.execPath, sinon.match.any, sinon.match.any); + example1.suite2.execPath, example1.suite2.outputs[2][0]); withArgs.onCall(withArgs.callCount) .callsFake((p: string, args: string[], ops: any) => { assert.equal( @@ -1225,12 +1227,73 @@ describe('C2TestAdapter', function() { ops.env.C2OVERRIDETESTENV, 'c2overridetestenv-l'); return new ChildProcessStub(example1.suite2.outputs[2][1]); }); - + const cc = withArgs.callCount; await adapter.run([suite2.id]); + assert.equal(withArgs.callCount, cc + 1) } }) }) }) + + context( + 'executables=["execPath1", "execPath2", "execPath3"]', + async function() { + before(function() { + return updateConfig( + 'executables', ['execPath1', 'execPath2', 'execPath3']); + }); + + after(function() { + return updateConfig('executables', undefined); + }); + + it('run suite3 one-by-one', async function() { + this.slow(200); + assert.equal(root.children.length, 3); + assert.equal(root.children[0].type, 'suite'); + const suite3 = root.children[2]; + assert.equal(suite3.children.length, 33); + + spawnStub.withArgs(example1.suite3.execPath).throwsArg(1); + + const runAndCheckEvents = async (test: TestInfo) => { + assert.equal(testStatesEvents.length, 0); + + await adapter.run([test.id]); + + assert.equal(testStatesEvents.length, 6, inspect(test)); + + assert.deepStrictEqual( + {type: 'started', tests: [test.id]}, testStatesEvents[0]); + assert.deepStrictEqual( + {type: 'suite', state: 'running', suite: suite3}, + testStatesEvents[1]); + + assert.equal(testStatesEvents[2].type, 'test'); + assert.equal((testStatesEvents[2]).state, 'running'); + assert.equal((testStatesEvents[2]).test, test); + + assert.equal(testStatesEvents[3].type, 'test'); + assert.ok( + (testStatesEvents[3]).state == 'passed' || + (testStatesEvents[3]).state == 'skipped' || + (testStatesEvents[3]).state == 'failed'); + assert.equal((testStatesEvents[3]).test, test); + + assert.deepStrictEqual( + {type: 'suite', state: 'completed', suite: suite3}, + testStatesEvents[4]); + assert.deepStrictEqual({type: 'finished'}, testStatesEvents[5]); + + while (testStatesEvents.length) testStatesEvents.pop(); + }; + + for (let test of suite3.children) { + assert.equal(test.type, 'test'); + await runAndCheckEvents(test); + } + }) + }) }) specify('load executables=', async function() { @@ -1268,8 +1331,8 @@ describe('C2TestAdapter', function() { async function(this: Mocha.Context) { const watchTimeout = 5000; await updateConfig('defaultExecWatchTimeout', watchTimeout); - this.timeout(watchTimeout+ 2500/* because of 'delay' */); - this.slow(watchTimeout+ 2500/* because of 'delay' */); + this.timeout(watchTimeout + 2500 /* because of 'delay' */); + this.slow(watchTimeout + 2500 /* because of 'delay' */); const fullPath = path.join(workspaceFolderUri.path, 'execPath2Copy'); for (let scenario of example1.suite2.outputs) { @@ -1307,7 +1370,9 @@ describe('C2TestAdapter', function() { await adapter.load(); assert.equal( - (testsEvents[1]).suite.children.length, 2); + (testsEvents[testsEvents.length - 1]) + .suite!.children.length, + 2); assert.ok(watchers.has(fullPath)); const watcher = watchers.get(fullPath)!; const start = Date.now(); diff --git a/src/test/example1.ts b/src/test/example1.ts index fc6258c1..b20225c6 100644 --- a/src/test/example1.ts +++ b/src/test/example1.ts @@ -520,7 +520,109 @@ For more detailed usage please see the project docs ], [ ['[.],*', '--verbosity', 'high', '--list-tests', '--use-colour', 'no'], - ` ./suite3 [.],* --verbosity high --list-tests --use-colour no` + `Matching test cases: + test name,with,colon + ../vscode-catch2-test-adapter/src/test/suite3.cpp:8 + tag1 + test name with space + ../vscode-catch2-test-adapter/src/test/suite3.cpp:14 + (NO DESCRIPTION) + SECTION tree + ../vscode-catch2-test-adapter/src/test/suite3.cpp:20 + (NO DESCRIPTION) + spec ! char + ../vscode-catch2-test-adapter/src/test/suite3.cpp:36 + (NO DESCRIPTION) + spec @ char + ../vscode-catch2-test-adapter/src/test/suite3.cpp:37 + (NO DESCRIPTION) + spec # char + ../vscode-catch2-test-adapter/src/test/suite3.cpp:38 + (NO DESCRIPTION) + spec $ char + ../vscode-catch2-test-adapter/src/test/suite3.cpp:39 + (NO DESCRIPTION) + spec % char + ../vscode-catch2-test-adapter/src/test/suite3.cpp:40 + (NO DESCRIPTION) + spec ^ char + ../vscode-catch2-test-adapter/src/test/suite3.cpp:41 + (NO DESCRIPTION) + spec & char + ../vscode-catch2-test-adapter/src/test/suite3.cpp:42 + (NO DESCRIPTION) + spec * char + ../vscode-catch2-test-adapter/src/test/suite3.cpp:43 + (NO DESCRIPTION) + spec (a) char + ../vscode-catch2-test-adapter/src/test/suite3.cpp:44 + (NO DESCRIPTION) + spec {a} char + ../vscode-catch2-test-adapter/src/test/suite3.cpp:45 + (NO DESCRIPTION) + spec [a] char + ../vscode-catch2-test-adapter/src/test/suite3.cpp:46 + (NO DESCRIPTION) + spec ; char + ../vscode-catch2-test-adapter/src/test/suite3.cpp:47 + (NO DESCRIPTION) + spec ' char + ../vscode-catch2-test-adapter/src/test/suite3.cpp:48 + (NO DESCRIPTION) + spec \\ char + ../vscode-catch2-test-adapter/src/test/suite3.cpp:49 + (NO DESCRIPTION) + spec , char + ../vscode-catch2-test-adapter/src/test/suite3.cpp:50 + (NO DESCRIPTION) + spec . char + ../vscode-catch2-test-adapter/src/test/suite3.cpp:51 + (NO DESCRIPTION) + spec / char + ../vscode-catch2-test-adapter/src/test/suite3.cpp:52 + (NO DESCRIPTION) + spec < char + ../vscode-catch2-test-adapter/src/test/suite3.cpp:53 + (NO DESCRIPTION) + spec > char + ../vscode-catch2-test-adapter/src/test/suite3.cpp:54 + (NO DESCRIPTION) + spec ? char + ../vscode-catch2-test-adapter/src/test/suite3.cpp:55 + (NO DESCRIPTION) + spec - char + ../vscode-catch2-test-adapter/src/test/suite3.cpp:56 + (NO DESCRIPTION) + spec = char + ../vscode-catch2-test-adapter/src/test/suite3.cpp:57 + (NO DESCRIPTION) + spec _ char + ../vscode-catch2-test-adapter/src/test/suite3.cpp:58 + (NO DESCRIPTION) + spec + char + ../vscode-catch2-test-adapter/src/test/suite3.cpp:59 + (NO DESCRIPTION) + spec ~ char + ../vscode-catch2-test-adapter/src/test/suite3.cpp:60 + (NO DESCRIPTION) + spec \` char + ../vscode-catch2-test-adapter/src/test/suite3.cpp:61 + (NO DESCRIPTION) + spec § char + ../vscode-catch2-test-adapter/src/test/suite3.cpp:62 + (NO DESCRIPTION) + spec ± char + ../vscode-catch2-test-adapter/src/test/suite3.cpp:63 + (NO DESCRIPTION) + spec " char + ../vscode-catch2-test-adapter/src/test/suite3.cpp:64 + (NO DESCRIPTION) + spec | char + ../vscode-catch2-test-adapter/src/test/suite3.cpp:65 + (NO DESCRIPTION) +34 matching test cases + +` ], [ ['--reporter', 'xml', '--durations', 'yes'], @@ -594,9 +696,6 @@ For more detailed usage please see the project docs
- - - @@ -766,9 +865,6 @@ For more detailed usage please see the project docs - - - @@ -866,7 +962,7 @@ For more detailed usage please see the project docs ` ], [ - ['test name\,with\,colon', '--reporter', 'xml', '--durations', 'yes'], + ['test name\\,with\\,colon', '--reporter', 'xml', '--durations', 'yes'], ` @@ -1064,7 +1160,7 @@ For more detailed usage please see the project docs ` ], [ - ['spec * char', '--reporter', 'xml', '--durations', 'yes'], + ['spec \\* char', '--reporter', 'xml', '--durations', 'yes'], ` @@ -1106,7 +1202,7 @@ For more detailed usage please see the project docs ` ], [ - ['spec \[a] char', '--reporter', 'xml', '--durations', 'yes'], + ['spec \\[a] char', '--reporter', 'xml', '--durations', 'yes'], ` @@ -1152,7 +1248,7 @@ For more detailed usage please see the project docs ` - + @@ -1162,7 +1258,7 @@ For more detailed usage please see the project docs ` ], [ - ['spec \, char', '--reporter', 'xml', '--durations', 'yes'], + ['spec \\, char', '--reporter', 'xml', '--durations', 'yes'], ` @@ -1625,7 +1721,7 @@ For more detailed usage please see the project docs ], [ [ - 'spec * char', '--reporter', 'xml', '--durations', 'yes', + 'spec \\* char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2' ], ` @@ -1679,7 +1775,7 @@ For more detailed usage please see the project docs ], [ [ - 'spec \[a] char', '--reporter', 'xml', '--durations', 'yes', + 'spec \\[a] char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2' ], ` @@ -1733,7 +1829,7 @@ For more detailed usage please see the project docs ], [ [ - 'spec \\ char', '--reporter', 'xml', '--durations', 'yes', + 'spec \\\\ char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2' ], ` @@ -1751,7 +1847,7 @@ For more detailed usage please see the project docs ], [ [ - 'spec \, char', '--reporter', 'xml', '--durations', 'yes', + 'spec \\, char', '--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2' ], ` diff --git a/src/test/suite3generator.sh b/src/test/suite3generator.sh index 3bf4da01..5f80f6e5 100755 --- a/src/test/suite3generator.sh +++ b/src/test/suite3generator.sh @@ -2,7 +2,7 @@ echo "" >x.txt echo -n "[['--help'], \`" >>x.txt; ./suite3 "[.],*" --verbosity high --help >>x.txt; echo "\`]," >>x.txt; -echo -n "[['[.],*', '--verbosity', 'high', '--list-tests', '--use-colour', 'no'], \`" >>x.txt ./suite3 "[.],*" --verbosity high --list-tests --use-colour no >>x.txt; echo "\`]," >>x.txt ; +echo -n "[['[.],*', '--verbosity', 'high', '--list-tests', '--use-colour', 'no'], \`" >>x.txt; ./suite3 "[.],*" --verbosity high --list-tests --use-colour no >>x.txt; echo "\`]," >>x.txt ; echo -n "[['--reporter', 'xml', '--durations', 'yes'], \`" >>x.txt; ./suite3 --reporter xml --durations yes >>x.txt; echo "\`]," >>x.txt ; echo -n "[['--reporter', 'xml', '--durations', 'yes', '--rng-seed', '2'], \`" >>x.txt; ./suite3 --reporter xml --durations yes --rng-seed 2 >>x.txt; echo "\`]," >>x.txt ; From 8b71ce6e1457e0557b19b5cf41a2a19a3dde032b Mon Sep 17 00:00:00 2001 From: Mate Pek Date: Wed, 24 Oct 2018 01:56:13 +0200 Subject: [PATCH 17/18] package-lock --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index f21a8291..8b9f01d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "vscode-catch2-test-adapter", - "version": "1.1.2", + "version": "1.2.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index ecc3471d..d6c61b77 100644 --- a/package.json +++ b/package.json @@ -160,4 +160,4 @@ } } } -} \ No newline at end of file +} From d015f060d31309b47f113c187ccf4c62bf4870f2 Mon Sep 17 00:00:00 2001 From: Mate Pek Date: Wed, 24 Oct 2018 01:59:26 +0200 Subject: [PATCH 18/18] travis node_js:10 --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index b5f90aa4..f1e53a23 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,7 @@ sudo: false language: node_js +node_js: + - "10" os: - osx