| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -765,7 +765,13 @@ class Test extends AsyncResource { | |||
| 765 | 765 | loc: [child.line, child.column, child.file], | |
| 766 | 766 | }, noop); | |
| 767 | 767 | t.endTime = t.startTime = hrtime(); | |
| 768 | - t.start(); | ||
| 768 | + // For suites, Suite.run() starts the subtests via SafePromiseAll. | ||
| 769 | + // Starting them here as well would run them twice, re-invoking the | ||
| 770 | + // synthetic children-creator against a now-incremented disambiguator | ||
| 771 | + // and producing spurious failures. | ||
| 772 | + if (this.reportedType !== 'suite') { | ||
| 773 | + t.start(); | ||
| 774 | + } | ||
| 769 | 775 | } | |
| 770 | 776 | }; | |
| 771 | 777 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -46,3 +46,22 @@ describe('describe rerun', { timeout: 1000, concurrency: 1000 }, () => { | |||
| 46 | 46 | }); | |
| 47 | 47 | test('a'); | |
| 48 | 48 | }); | |
| 49 | + | ||
| 50 | + | ||
| 51 | + // Shared helper creates subtests at the same source location each time it's | ||
| 52 | + // called, producing ambiguous test identifiers (disambiguated with ":(N)" | ||
| 53 | + // suffixes in the rerun state file). Regression coverage for a bug where the | ||
| 54 | + // suite's synthetic rerun fn double-started its direct children, which then | ||
| 55 | + // re-invoked the synthetic descendant-creator against an already-incremented | ||
| 56 | + // disambiguator map and emitted spurious failures. | ||
| 57 | + function ambiguousHelper(t) { | ||
| 58 | + return Promise.all([ | ||
| 59 | + t.test('shared sub A', () => {}), | ||
| 60 | + t.test('shared sub B', () => {}), | ||
| 61 | + ]); | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + describe('rerun with ambiguous shared helper', { timeout: 1000, concurrency: 1000 }, () => { | ||
| 65 | + test('first caller', (t) => ambiguousHelper(t)); | ||
| 66 | + test('second caller', (t) => ambiguousHelper(t)); | ||
| 67 | + }); | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -27,6 +27,13 @@ const expectedStateFile = [ | |||
| 27 | 27 | 'test/fixtures/test-runner/rerun.js:44:3': { passed_on_attempt: 0, name: 'passed on first attempt' }, | |
| 28 | 28 | 'test/fixtures/test-runner/rerun.js:47:3': { passed_on_attempt: 0, name: 'a' }, | |
| 29 | 29 | 'test/fixtures/test-runner/rerun.js:43:1': { passed_on_attempt: 0, name: 'describe rerun' }, | |
| 30 | + 'test/fixtures/test-runner/rerun.js:59:7': { passed_on_attempt: 0, name: 'shared sub A' }, | ||
| 31 | + 'test/fixtures/test-runner/rerun.js:60:7': { passed_on_attempt: 0, name: 'shared sub B' }, | ||
| 32 | + 'test/fixtures/test-runner/rerun.js:65:3': { passed_on_attempt: 0, name: 'first caller' }, | ||
| 33 | + 'test/fixtures/test-runner/rerun.js:59:7:(1)': { passed_on_attempt: 0, name: 'shared sub A' }, | ||
| 34 | + 'test/fixtures/test-runner/rerun.js:60:7:(1)': { passed_on_attempt: 0, name: 'shared sub B' }, | ||
| 35 | + 'test/fixtures/test-runner/rerun.js:66:3': { passed_on_attempt: 0, name: 'second caller' }, | ||
| 36 | + 'test/fixtures/test-runner/rerun.js:64:1': { passed_on_attempt: 0, name: 'rerun with ambiguous shared helper' }, | ||
| 30 | 37 | }, | |
| 31 | 38 | { | |
| 32 | 39 | 'test/fixtures/test-runner/rerun.js:9:1': { passed_on_attempt: 0, name: 'ok' }, | |
@@ -38,11 +45,17 @@ const expectedStateFile = [ | |||
| 38 | 45 | 'test/fixtures/test-runner/rerun.js:39:1': { passed_on_attempt: 0, name: 'nested ambiguous (expectedAttempts=0)' }, | |
| 39 | 46 | 'test/fixtures/test-runner/rerun.js:30:16:(1)': { passed_on_attempt: 0, name: '2 levels deep' }, | |
| 40 | 47 | 'test/fixtures/test-runner/rerun.js:35:13:(1)': { passed_on_attempt: 0, name: 'ok' }, | |
| 41 | - 'test/fixtures/test-runner/rerun.js:43:1': { passed_on_attempt: 0, name: 'describe rerun' }, | ||
| 42 | - 'test/fixtures/test-runner/rerun.js:44:3': { passed_on_attempt: 0, name: 'passed on first attempt' }, | ||
| 43 | 48 | 'test/fixtures/test-runner/rerun.js:45:13': { passed_on_attempt: 0, name: 'nested' }, | |
| 44 | - 'test/fixtures/test-runner/rerun.js:45:13:(1)': { passed_on_attempt: 1, name: 'nested' }, | ||
| 49 | + 'test/fixtures/test-runner/rerun.js:44:3': { passed_on_attempt: 0, name: 'passed on first attempt' }, | ||
| 45 | 50 | 'test/fixtures/test-runner/rerun.js:47:3': { passed_on_attempt: 0, name: 'a' }, | |
| 51 | + 'test/fixtures/test-runner/rerun.js:43:1': { passed_on_attempt: 0, name: 'describe rerun' }, | ||
| 52 | + 'test/fixtures/test-runner/rerun.js:59:7': { passed_on_attempt: 0, name: 'shared sub A' }, | ||
| 53 | + 'test/fixtures/test-runner/rerun.js:60:7': { passed_on_attempt: 0, name: 'shared sub B' }, | ||
| 54 | + 'test/fixtures/test-runner/rerun.js:65:3': { passed_on_attempt: 0, name: 'first caller' }, | ||
| 55 | + 'test/fixtures/test-runner/rerun.js:59:7:(1)': { passed_on_attempt: 0, name: 'shared sub A' }, | ||
| 56 | + 'test/fixtures/test-runner/rerun.js:60:7:(1)': { passed_on_attempt: 0, name: 'shared sub B' }, | ||
| 57 | + 'test/fixtures/test-runner/rerun.js:66:3': { passed_on_attempt: 0, name: 'second caller' }, | ||
| 58 | + 'test/fixtures/test-runner/rerun.js:64:1': { passed_on_attempt: 0, name: 'rerun with ambiguous shared helper' }, | ||
| 46 | 59 | }, | |
| 47 | 60 | { | |
| 48 | 61 | 'test/fixtures/test-runner/rerun.js:3:1': { passed_on_attempt: 2, name: 'should fail on first two attempts' }, | |
@@ -53,15 +66,21 @@ const expectedStateFile = [ | |||
| 53 | 66 | 'test/fixtures/test-runner/rerun.js:29:13': { passed_on_attempt: 0, name: 'nested' }, | |
| 54 | 67 | 'test/fixtures/test-runner/rerun.js:35:13': { passed_on_attempt: 0, name: 'ok' }, | |
| 55 | 68 | 'test/fixtures/test-runner/rerun.js:39:1': { passed_on_attempt: 0, name: 'nested ambiguous (expectedAttempts=0)' }, | |
| 56 | - 'test/fixtures/test-runner/rerun.js:29:13:(1)': { passed_on_attempt: 2, name: 'nested' }, | ||
| 57 | 69 | 'test/fixtures/test-runner/rerun.js:30:16:(1)': { passed_on_attempt: 0, name: '2 levels deep' }, | |
| 70 | + 'test/fixtures/test-runner/rerun.js:29:13:(1)': { passed_on_attempt: 2, name: 'nested' }, | ||
| 58 | 71 | 'test/fixtures/test-runner/rerun.js:35:13:(1)': { passed_on_attempt: 0, name: 'ok' }, | |
| 59 | 72 | 'test/fixtures/test-runner/rerun.js:40:1': { passed_on_attempt: 2, name: 'nested ambiguous (expectedAttempts=1)' }, | |
| 60 | - 'test/fixtures/test-runner/rerun.js:43:1': { passed_on_attempt: 0, name: 'describe rerun' }, | ||
| 61 | - 'test/fixtures/test-runner/rerun.js:44:3': { passed_on_attempt: 0, name: 'passed on first attempt' }, | ||
| 62 | 73 | 'test/fixtures/test-runner/rerun.js:45:13': { passed_on_attempt: 0, name: 'nested' }, | |
| 63 | - 'test/fixtures/test-runner/rerun.js:45:13:(1)': { passed_on_attempt: 1, name: 'nested' }, | ||
| 74 | + 'test/fixtures/test-runner/rerun.js:44:3': { passed_on_attempt: 0, name: 'passed on first attempt' }, | ||
| 64 | 75 | 'test/fixtures/test-runner/rerun.js:47:3': { passed_on_attempt: 0, name: 'a' }, | |
| 76 | + 'test/fixtures/test-runner/rerun.js:43:1': { passed_on_attempt: 0, name: 'describe rerun' }, | ||
| 77 | + 'test/fixtures/test-runner/rerun.js:59:7': { passed_on_attempt: 0, name: 'shared sub A' }, | ||
| 78 | + 'test/fixtures/test-runner/rerun.js:60:7': { passed_on_attempt: 0, name: 'shared sub B' }, | ||
| 79 | + 'test/fixtures/test-runner/rerun.js:65:3': { passed_on_attempt: 0, name: 'first caller' }, | ||
| 80 | + 'test/fixtures/test-runner/rerun.js:59:7:(1)': { passed_on_attempt: 0, name: 'shared sub A' }, | ||
| 81 | + 'test/fixtures/test-runner/rerun.js:60:7:(1)': { passed_on_attempt: 0, name: 'shared sub B' }, | ||
| 82 | + 'test/fixtures/test-runner/rerun.js:66:3': { passed_on_attempt: 0, name: 'second caller' }, | ||
| 83 | + 'test/fixtures/test-runner/rerun.js:64:1': { passed_on_attempt: 0, name: 'rerun with ambiguous shared helper' }, | ||
| 65 | 84 | }, | |
| 66 | 85 | ]; | |
| 67 | 86 | ||
@@ -81,26 +100,26 @@ test('test should pass on third rerun', async () => { | |||
| 81 | 100 | let { code, stdout, signal } = await common.spawnPromisified(process.execPath, args); | |
| 82 | 101 | assert.strictEqual(code, 1); | |
| 83 | 102 | assert.strictEqual(signal, null); | |
| 84 | - assert.match(stdout, /pass 11/); | ||
| 103 | + assert.match(stdout, /pass 17/); | ||
| 85 | 104 | assert.match(stdout, /fail 4/); | |
| 86 | - assert.match(stdout, /suites 1/); | ||
| 105 | + assert.match(stdout, /suites 2/); | ||
| 87 | 106 | assert.deepStrictEqual(await getStateFile(), expectedStateFile.slice(0, 1)); | |
| 88 | 107 | ||
| 89 | 108 | ({ code, stdout, signal } = await common.spawnPromisified(process.execPath, args)); | |
| 90 | 109 | assert.strictEqual(code, 1); | |
| 91 | 110 | assert.strictEqual(signal, null); | |
| 92 | - assert.match(stdout, /pass 13/); | ||
| 111 | + assert.match(stdout, /pass 18/); | ||
| 93 | 112 | assert.match(stdout, /fail 3/); | |
| 94 | - assert.match(stdout, /suites 1/); | ||
| 113 | + assert.match(stdout, /suites 2/); | ||
| 95 | 114 | assert.deepStrictEqual(await getStateFile(), expectedStateFile.slice(0, 2)); | |
| 96 | 115 | ||
| 97 | 116 | ||
| 98 | 117 | ({ code, stdout, signal } = await common.spawnPromisified(process.execPath, args)); | |
| 99 | 118 | assert.strictEqual(code, 0); | |
| 100 | 119 | assert.strictEqual(signal, null); | |
| 101 | - assert.match(stdout, /pass 18/); | ||
| 120 | + assert.match(stdout, /pass 21/); | ||
| 102 | 121 | assert.match(stdout, /fail 0/); | |
| 103 | - assert.match(stdout, /suites 1/); | ||
| 122 | + assert.match(stdout, /suites 2/); | ||
| 104 | 123 | assert.deepStrictEqual(await getStateFile(), expectedStateFile); | |
| 105 | 124 | }); | |
| 106 | 125 | ||
@@ -110,32 +129,32 @@ test('test should pass on third rerun with `--test`', async () => { | |||
| 110 | 129 | let { code, stdout, signal } = await common.spawnPromisified(process.execPath, args); | |
| 111 | 130 | assert.strictEqual(code, 1); | |
| 112 | 131 | assert.strictEqual(signal, null); | |
| 113 | - assert.match(stdout, /pass 11/); | ||
| 132 | + assert.match(stdout, /pass 17/); | ||
| 114 | 133 | assert.match(stdout, /fail 4/); | |
| 115 | - assert.match(stdout, /suites 1/); | ||
| 134 | + assert.match(stdout, /suites 2/); | ||
| 116 | 135 | assert.deepStrictEqual(await getStateFile(), expectedStateFile.slice(0, 1)); | |
| 117 | 136 | ||
| 118 | 137 | ({ code, stdout, signal } = await common.spawnPromisified(process.execPath, args)); | |
| 119 | 138 | assert.strictEqual(code, 1); | |
| 120 | 139 | assert.strictEqual(signal, null); | |
| 121 | - assert.match(stdout, /pass 13/); | ||
| 140 | + assert.match(stdout, /pass 18/); | ||
| 122 | 141 | assert.match(stdout, /fail 3/); | |
| 123 | - assert.match(stdout, /suites 1/); | ||
| 142 | + assert.match(stdout, /suites 2/); | ||
| 124 | 143 | assert.deepStrictEqual(await getStateFile(), expectedStateFile.slice(0, 2)); | |
| 125 | 144 | ||
| 126 | 145 | ||
| 127 | 146 | ({ code, stdout, signal } = await common.spawnPromisified(process.execPath, args)); | |
| 128 | 147 | assert.strictEqual(code, 0); | |
| 129 | 148 | assert.strictEqual(signal, null); | |
| 130 | - assert.match(stdout, /pass 18/); | ||
| 149 | + assert.match(stdout, /pass 21/); | ||
| 131 | 150 | assert.match(stdout, /fail 0/); | |
| 132 | - assert.match(stdout, /suites 1/); | ||
| 151 | + assert.match(stdout, /suites 2/); | ||
| 133 | 152 | assert.deepStrictEqual(await getStateFile(), expectedStateFile); | |
| 134 | 153 | }); | |
| 135 | 154 | ||
| 136 | 155 | test('using `run` api', async () => { | |
| 137 | 156 | let stream = run({ files: [fixture], rerunFailuresFilePath: stateFile }); | |
| 138 | - stream.on('test:pass', common.mustCall(12)); | ||
| 157 | + stream.on('test:pass', common.mustCall(19)); | ||
| 139 | 158 | stream.on('test:fail', common.mustCall(4)); | |
| 140 | 159 | ||
| 141 | 160 | // eslint-disable-next-line no-unused-vars | |
@@ -145,7 +164,7 @@ test('using `run` api', async () => { | |||
| 145 | 164 | ||
| 146 | 165 | ||
| 147 | 166 | stream = run({ files: [fixture], rerunFailuresFilePath: stateFile }); | |
| 148 | - stream.on('test:pass', common.mustCall(14)); | ||
| 167 | + stream.on('test:pass', common.mustCall(20)); | ||
| 149 | 168 | stream.on('test:fail', common.mustCall(3)); | |
| 150 | 169 | ||
| 151 | 170 | // eslint-disable-next-line no-unused-vars | |
@@ -155,7 +174,7 @@ test('using `run` api', async () => { | |||
| 155 | 174 | ||
| 156 | 175 | ||
| 157 | 176 | stream = run({ files: [fixture], rerunFailuresFilePath: stateFile }); | |
| 158 | - stream.on('test:pass', common.mustCall(19)); | ||
| 177 | + stream.on('test:pass', common.mustCall(23)); | ||
| 159 | 178 | stream.on('test:fail', common.mustNotCall()); | |
| 160 | 179 | ||
| 161 | 180 | // eslint-disable-next-line no-unused-vars | |
| Back | FazBrowse Home | New Git URL |
0 commit comments