| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 391ff0d commit 5b3c606
9 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -8,9 +8,11 @@ const { | |||
| 8 | 8 | ArrayPrototypeSlice, | |
| 9 | 9 | ArrayPrototypeSome, | |
| 10 | 10 | ArrayPrototypeSort, | |
| 11 | + FunctionPrototypeCall, | ||
| 12 | + Number, | ||
| 11 | 13 | ObjectAssign, | |
| 14 | + ObjectKeys, | ||
| 12 | 15 | PromisePrototypeThen, | |
| 13 | - SafePromiseAll, | ||
| 14 | 16 | SafePromiseAllReturnVoid, | |
| 15 | 17 | SafePromiseAllSettledReturnVoid, | |
| 16 | 18 | SafeMap, | |
@@ -35,7 +37,14 @@ const { validateArray, validateBoolean } = require('internal/validators'); | |||
| 35 | 37 | const { getInspectPort, isUsingInspector, isInspectorMessage } = require('internal/util/inspector'); | |
| 36 | 38 | const { kEmptyObject } = require('internal/util'); | |
| 37 | 39 | const { createTestTree } = require('internal/test_runner/harness'); | |
| 38 | - const { kSubtestsFailed, Test } = require('internal/test_runner/test'); | ||
| 40 | + const { | ||
| 41 | + kAborted, | ||
| 42 | + kCancelledByParent, | ||
| 43 | + kSubtestsFailed, | ||
| 44 | + kTestCodeFailure, | ||
| 45 | + kTestTimeoutFailure, | ||
| 46 | + Test, | ||
| 47 | + } = require('internal/test_runner/test'); | ||
| 39 | 48 | const { TapParser } = require('internal/test_runner/tap_parser'); | |
| 40 | 49 | const { YAMLToJs } = require('internal/test_runner/yaml_to_js'); | |
| 41 | 50 | const { TokenKind } = require('internal/test_runner/tap_lexer'); | |
@@ -54,6 +63,9 @@ const kFilterArgs = ['--test', '--experimental-test-coverage', '--watch']; | |||
| 54 | 63 | const kFilterArgValues = ['--test-reporter', '--test-reporter-destination']; | |
| 55 | 64 | const kDiagnosticsFilterArgs = ['tests', 'pass', 'fail', 'cancelled', 'skipped', 'todo', 'duration_ms']; | |
| 56 | 65 | ||
| 66 | + const kCanceledTests = new SafeSet() | ||
| 67 | + .add(kCancelledByParent).add(kAborted).add(kTestTimeoutFailure); | ||
| 68 | + | ||
| 57 | 69 | // TODO(cjihrig): Replace this with recursive readdir once it lands. | |
| 58 | 70 | function processPath(path, testFiles, options) { | |
| 59 | 71 | const stats = statSync(path); | |
@@ -132,6 +144,11 @@ function getRunArgs({ path, inspectPort }) { | |||
| 132 | 144 | ||
| 133 | 145 | class FileTest extends Test { | |
| 134 | 146 | #buffer = []; | |
| 147 | + #counters = { __proto__: null, all: 0, failed: 0, passed: 0, cancelled: 0, skipped: 0, todo: 0, totalFailed: 0 }; | ||
| 148 | + failedSubtests = false; | ||
| 149 | + #skipReporting() { | ||
| 150 | + return this.#counters.all > 0 && (!this.error || this.error.failureType === kSubtestsFailed); | ||
| 151 | + } | ||
| 135 | 152 | #checkNestedComment({ comment }) { | |
| 136 | 153 | const firstSpaceIndex = StringPrototypeIndexOf(comment, ' '); | |
| 137 | 154 | if (firstSpaceIndex === -1) return false; | |
@@ -140,8 +157,6 @@ class FileTest extends Test { | |||
| 140 | 157 | ArrayPrototypeIncludes(kDiagnosticsFilterArgs, StringPrototypeSlice(comment, 0, firstSpaceIndex)); | |
| 141 | 158 | } | |
| 142 | 159 | #handleReportItem({ kind, node, comments, nesting = 0 }) { | |
| 143 | - nesting += 1; | ||
| 144 | - | ||
| 145 | 160 | if (comments) { | |
| 146 | 161 | ArrayPrototypeForEach(comments, (comment) => this.reporter.diagnostic(nesting, this.name, comment)); | |
| 147 | 162 | } | |
@@ -152,17 +167,20 @@ class FileTest extends Test { | |||
| 152 | 167 | break; | |
| 153 | 168 | ||
| 154 | 169 | case TokenKind.TAP_PLAN: | |
| 170 | + if (nesting === 0 && this.#skipReporting()) { | ||
| 171 | + break; | ||
| 172 | + } | ||
| 155 | 173 | this.reporter.plan(nesting, this.name, node.end - node.start + 1); | |
| 156 | 174 | break; | |
| 157 | 175 | ||
| 158 | 176 | case TokenKind.TAP_SUBTEST_POINT: | |
| 159 | 177 | this.reporter.start(nesting, this.name, node.name); | |
| 160 | 178 | break; | |
| 161 | 179 | ||
| 162 | - case TokenKind.TAP_TEST_POINT: | ||
| 163 | - // eslint-disable-next-line no-case-declarations | ||
| 180 | + case TokenKind.TAP_TEST_POINT: { | ||
| 181 | + | ||
| 164 | 182 | const { todo, skip, pass } = node.status; | |
| 165 | - // eslint-disable-next-line no-case-declarations | ||
| 183 | + | ||
| 166 | 184 | let directive; | |
| 167 | 185 | ||
| 168 | 186 | if (skip) { | |
@@ -173,29 +191,22 @@ class FileTest extends Test { | |||
| 173 | 191 | directive = kEmptyObject; | |
| 174 | 192 | } | |
| 175 | 193 | ||
| 176 | - if (pass) { | ||
| 177 | - this.reporter.ok( | ||
| 178 | - nesting, | ||
| 179 | - this.name, | ||
| 180 | - node.id, | ||
| 181 | - node.description, | ||
| 182 | - YAMLToJs(node.diagnostics), | ||
| 183 | - directive | ||
| 184 | - ); | ||
| 185 | - } else { | ||
| 186 | - this.reporter.fail( | ||
| 187 | - nesting, | ||
| 188 | - this.name, | ||
| 189 | - node.id, | ||
| 190 | - node.description, | ||
| 191 | - YAMLToJs(node.diagnostics), | ||
| 192 | - directive | ||
| 193 | - ); | ||
| 194 | + const diagnostics = YAMLToJs(node.diagnostics); | ||
| 195 | + const cancelled = kCanceledTests.has(diagnostics.error?.failureType); | ||
| 196 | + const testNumber = nesting === 0 ? (Number(node.id) + this.testNumber - 1) : node.id; | ||
| 197 | + const method = pass ? 'ok' : 'fail'; | ||
| 198 | + this.reporter[method](nesting, this.name, testNumber, node.description, diagnostics, directive); | ||
| 199 | + if (nesting === 0) { | ||
| 200 | + FunctionPrototypeCall(super.countSubtest, | ||
| 201 | + { finished: true, skipped: skip, isTodo: todo, passed: pass, cancelled }, | ||
| 202 | + this.#counters); | ||
| 203 | + this.failedSubtests ||= !pass; | ||
| 194 | 204 | } | |
| 195 | 205 | break; | |
| 196 | 206 | ||
| 207 | + } | ||
| 197 | 208 | case TokenKind.COMMENT: | |
| 198 | - if (nesting === 1 && this.#checkNestedComment(node)) { | ||
| 209 | + if (nesting === 0 && this.#checkNestedComment(node)) { | ||
| 199 | 210 | // Ignore file top level diagnostics | |
| 200 | 211 | break; | |
| 201 | 212 | } | |
@@ -215,10 +226,24 @@ class FileTest extends Test { | |||
| 215 | 226 | this.reportStarted(); | |
| 216 | 227 | this.#handleReportItem(ast); | |
| 217 | 228 | } | |
| 229 | + countSubtest(counters) { | ||
| 230 | + if (this.#counters.all === 0) { | ||
| 231 | + return super.countSubtest(counters); | ||
| 232 | + } | ||
| 233 | + ArrayPrototypeForEach(ObjectKeys(counters), (key) => { | ||
| 234 | + counters[key] += this.#counters[key]; | ||
| 235 | + }); | ||
| 236 | + } | ||
| 237 | + reportStarted() {} | ||
| 218 | 238 | report() { | |
| 219 | - this.reportStarted(); | ||
| 239 | + const skipReporting = this.#skipReporting(); | ||
| 240 | + if (!skipReporting) { | ||
| 241 | + super.reportStarted(); | ||
| 242 | + } | ||
| 220 | 243 | ArrayPrototypeForEach(this.#buffer, (ast) => this.#handleReportItem(ast)); | |
| 221 | - super.report(); | ||
| 244 | + if (!skipReporting) { | ||
| 245 | + super.report(); | ||
| 246 | + } | ||
| 222 | 247 | } | |
| 223 | 248 | } | |
| 224 | 249 | ||
@@ -273,16 +298,14 @@ function runTestFile(path, root, inspectPort, filesWatcher) { | |||
| 273 | 298 | subtest.addToReport(ast); | |
| 274 | 299 | }); | |
| 275 | 300 | ||
| 276 | - const { 0: { 0: code, 1: signal } } = await SafePromiseAll([ | ||
| 277 | - once(child, 'exit', { signal: t.signal }), | ||
| 278 | - child.stdout.toArray({ signal: t.signal }), | ||
| 279 | - ]); | ||
| 301 | + const { 0: code, 1: signal } = await once(child, 'exit', { signal: t.signal }); | ||
| 280 | 302 | ||
| 281 | 303 | runningProcesses.delete(path); | |
| 282 | 304 | runningSubtests.delete(path); | |
| 283 | 305 | if (code !== 0 || signal !== null) { | |
| 284 | 306 | if (!err) { | |
| 285 | - err = ObjectAssign(new ERR_TEST_FAILURE('test failed', kSubtestsFailed), { | ||
| 307 | + const failureType = subtest.failedSubtests ? kSubtestsFailed : kTestCodeFailure; | ||
| 308 | + err = ObjectAssign(new ERR_TEST_FAILURE('test failed', failureType), { | ||
| 286 | 309 | __proto__: null, | |
| 287 | 310 | exitCode: code, | |
| 288 | 311 | signal: signal, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -57,6 +57,7 @@ const { cpus } = require('os'); | |||
| 57 | 57 | const { bigint: hrtime } = process.hrtime; | |
| 58 | 58 | const kCallbackAndPromisePresent = 'callbackAndPromisePresent'; | |
| 59 | 59 | const kCancelledByParent = 'cancelledByParent'; | |
| 60 | + const kAborted = 'testAborted'; | ||
| 60 | 61 | const kParentAlreadyFinished = 'parentAlreadyFinished'; | |
| 61 | 62 | const kSubtestsFailed = 'subtestsFailed'; | |
| 62 | 63 | const kTestCodeFailure = 'testCodeFailure'; | |
@@ -390,10 +391,12 @@ class Test extends AsyncResource { | |||
| 390 | 391 | } | |
| 391 | 392 | ||
| 392 | 393 | #abortHandler = () => { | |
| 393 | - this.cancel(this.#outerSignal?.reason || new AbortError('The test was aborted')); | ||
| 394 | + const error = this.#outerSignal?.reason || new AbortError('The test was aborted'); | ||
| 395 | + error.failureType = kAborted; | ||
| 396 | + this.#cancel(error); | ||
| 394 | 397 | }; | |
| 395 | 398 | ||
| 396 | - cancel(error) { | ||
| 399 | + #cancel(error) { | ||
| 397 | 400 | if (this.endTime !== null) { | |
| 398 | 401 | return; | |
| 399 | 402 | } | |
@@ -470,7 +473,7 @@ class Test extends AsyncResource { | |||
| 470 | 473 | return true; | |
| 471 | 474 | } | |
| 472 | 475 | if (this.#outerSignal?.aborted) { | |
| 473 | - this.cancel(this.#outerSignal.reason || new AbortError('The test was aborted')); | ||
| 476 | + this.#abortHandler(); | ||
| 474 | 477 | return true; | |
| 475 | 478 | } | |
| 476 | 479 | } | |
@@ -563,7 +566,7 @@ class Test extends AsyncResource { | |||
| 563 | 566 | try { await afterEach(); } catch { /* test is already failing, let's the error */ } | |
| 564 | 567 | if (isTestFailureError(err)) { | |
| 565 | 568 | if (err.failureType === kTestTimeoutFailure) { | |
| 566 | - this.cancel(err); | ||
| 569 | + this.#cancel(err); | ||
| 567 | 570 | } else { | |
| 568 | 571 | this.fail(err); | |
| 569 | 572 | } | |
@@ -577,9 +580,31 @@ class Test extends AsyncResource { | |||
| 577 | 580 | this.postRun(); | |
| 578 | 581 | } | |
| 579 | 582 | ||
| 580 | - postRun(pendingSubtestsError) { | ||
| 581 | - const counters = { __proto__: null, failed: 0, passed: 0, cancelled: 0, skipped: 0, todo: 0, totalFailed: 0 }; | ||
| 583 | + countSubtest(counters) { | ||
| 584 | + // Check SKIP and TODO tests first, as those should not be counted as | ||
| 585 | + // failures. | ||
| 586 | + if (this.skipped) { | ||
| 587 | + counters.skipped++; | ||
| 588 | + } else if (this.isTodo) { | ||
| 589 | + counters.todo++; | ||
| 590 | + } else if (this.cancelled) { | ||
| 591 | + counters.cancelled++; | ||
| 592 | + } else if (!this.passed) { | ||
| 593 | + counters.failed++; | ||
| 594 | + } else { | ||
| 595 | + counters.passed++; | ||
| 596 | + } | ||
| 597 | + | ||
| 598 | + if (!this.passed) { | ||
| 599 | + counters.totalFailed++; | ||
| 600 | + } | ||
| 601 | + counters.all++; | ||
| 602 | + } | ||
| 582 | 603 | ||
| 604 | + postRun(pendingSubtestsError) { | ||
| 605 | + const counters = { | ||
| 606 | + __proto__: null, all: 0, failed: 0, passed: 0, cancelled: 0, skipped: 0, todo: 0, totalFailed: 0, | ||
| 607 | + }; | ||
| 583 | 608 | // If the test was failed before it even started, then the end time will | |
| 584 | 609 | // be earlier than the start time. Correct that here. | |
| 585 | 610 | if (this.endTime < this.startTime) { | |
@@ -594,27 +619,10 @@ class Test extends AsyncResource { | |||
| 594 | 619 | const subtest = this.subtests[i]; | |
| 595 | 620 | ||
| 596 | 621 | if (!subtest.finished) { | |
| 597 | - subtest.cancel(pendingSubtestsError); | ||
| 622 | + subtest.#cancel(pendingSubtestsError); | ||
| 598 | 623 | subtest.postRun(pendingSubtestsError); | |
| 599 | 624 | } | |
| 600 | - | ||
| 601 | - // Check SKIP and TODO tests first, as those should not be counted as | ||
| 602 | - // failures. | ||
| 603 | - if (subtest.skipped) { | ||
| 604 | - counters.skipped++; | ||
| 605 | - } else if (subtest.isTodo) { | ||
| 606 | - counters.todo++; | ||
| 607 | - } else if (subtest.cancelled) { | ||
| 608 | - counters.cancelled++; | ||
| 609 | - } else if (!subtest.passed) { | ||
| 610 | - counters.failed++; | ||
| 611 | - } else { | ||
| 612 | - counters.passed++; | ||
| 613 | - } | ||
| 614 | - | ||
| 615 | - if (!subtest.passed) { | ||
| 616 | - counters.totalFailed++; | ||
| 617 | - } | ||
| 625 | + subtest.countSubtest(counters); | ||
| 618 | 626 | } | |
| 619 | 627 | ||
| 620 | 628 | if ((this.passed || this.parent === null) && counters.totalFailed > 0) { | |
@@ -634,13 +642,13 @@ class Test extends AsyncResource { | |||
| 634 | 642 | this.parent.processPendingSubtests(); | |
| 635 | 643 | } else if (!this.reported) { | |
| 636 | 644 | this.reported = true; | |
| 637 | - this.reporter.plan(this.nesting, kFilename, this.subtests.length); | ||
| 645 | + this.reporter.plan(this.nesting, kFilename, counters.all); | ||
| 638 | 646 | ||
| 639 | 647 | for (let i = 0; i < this.diagnostics.length; i++) { | |
| 640 | 648 | this.reporter.diagnostic(this.nesting, kFilename, this.diagnostics[i]); | |
| 641 | 649 | } | |
| 642 | 650 | ||
| 643 | - this.reporter.diagnostic(this.nesting, kFilename, `tests ${this.subtests.length}`); | ||
| 651 | + this.reporter.diagnostic(this.nesting, kFilename, `tests ${counters.all}`); | ||
| 644 | 652 | this.reporter.diagnostic(this.nesting, kFilename, `pass ${counters.passed}`); | |
| 645 | 653 | this.reporter.diagnostic(this.nesting, kFilename, `fail ${counters.failed}`); | |
| 646 | 654 | this.reporter.diagnostic(this.nesting, kFilename, `cancelled ${counters.cancelled}`); | |
@@ -825,6 +833,8 @@ module.exports = { | |||
| 825 | 833 | kCancelledByParent, | |
| 826 | 834 | kSubtestsFailed, | |
| 827 | 835 | kTestCodeFailure, | |
| 836 | + kTestTimeoutFailure, | ||
| 837 | + kAborted, | ||
| 828 | 838 | kUnwrapErrors, | |
| 829 | 839 | Suite, | |
| 830 | 840 | Test, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -40,6 +40,7 @@ TAP version 13 | |||
| 40 | 40 | not ok 7 - not ok 3 | |
| 41 | 41 | --- | |
| 42 | 42 | duration_ms: * | |
| 43 | + failureType: 'testAborted' | ||
| 43 | 44 | error: 'This operation was aborted' | |
| 44 | 45 | code: 20 | |
| 45 | 46 | stack: |- | |
@@ -58,6 +59,7 @@ TAP version 13 | |||
| 58 | 59 | not ok 8 - not ok 4 | |
| 59 | 60 | --- | |
| 60 | 61 | duration_ms: * | |
| 62 | + failureType: 'testAborted' | ||
| 61 | 63 | error: 'This operation was aborted' | |
| 62 | 64 | code: 20 | |
| 63 | 65 | stack: |- | |
@@ -76,6 +78,7 @@ TAP version 13 | |||
| 76 | 78 | not ok 9 - not ok 5 | |
| 77 | 79 | --- | |
| 78 | 80 | duration_ms: * | |
| 81 | + failureType: 'testAborted' | ||
| 79 | 82 | error: 'This operation was aborted' | |
| 80 | 83 | code: 20 | |
| 81 | 84 | stack: |- | |
@@ -94,6 +97,7 @@ TAP version 13 | |||
| 94 | 97 | not ok 1 - promise timeout signal | |
| 95 | 98 | --- | |
| 96 | 99 | duration_ms: * | |
| 100 | + failureType: 'testAborted' | ||
| 97 | 101 | error: 'The operation was aborted due to timeout' | |
| 98 | 102 | code: 23 | |
| 99 | 103 | stack: |- | |
@@ -106,6 +110,7 @@ not ok 1 - promise timeout signal | |||
| 106 | 110 | not ok 2 - promise abort signal | |
| 107 | 111 | --- | |
| 108 | 112 | duration_ms: * | |
| 113 | + failureType: 'testAborted' | ||
| 109 | 114 | error: 'This operation was aborted' | |
| 110 | 115 | code: 20 | |
| 111 | 116 | stack: |- | |
@@ -160,6 +165,7 @@ not ok 2 - promise abort signal | |||
| 160 | 165 | not ok 7 - not ok 3 | |
| 161 | 166 | --- | |
| 162 | 167 | duration_ms: * | |
| 168 | + failureType: 'testAborted' | ||
| 163 | 169 | error: 'This operation was aborted' | |
| 164 | 170 | code: 20 | |
| 165 | 171 | stack: |- | |
@@ -178,6 +184,7 @@ not ok 2 - promise abort signal | |||
| 178 | 184 | not ok 8 - not ok 4 | |
| 179 | 185 | --- | |
| 180 | 186 | duration_ms: * | |
| 187 | + failureType: 'testAborted' | ||
| 181 | 188 | error: 'This operation was aborted' | |
| 182 | 189 | code: 20 | |
| 183 | 190 | stack: |- | |
@@ -196,6 +203,7 @@ not ok 2 - promise abort signal | |||
| 196 | 203 | not ok 9 - not ok 5 | |
| 197 | 204 | --- | |
| 198 | 205 | duration_ms: * | |
| 206 | + failureType: 'testAborted' | ||
| 199 | 207 | error: 'This operation was aborted' | |
| 200 | 208 | code: 20 | |
| 201 | 209 | stack: |- | |
@@ -214,6 +222,7 @@ not ok 2 - promise abort signal | |||
| 214 | 222 | not ok 3 - callback timeout signal | |
| 215 | 223 | --- | |
| 216 | 224 | duration_ms: * | |
| 225 | + failureType: 'testAborted' | ||
| 217 | 226 | error: 'The operation was aborted due to timeout' | |
| 218 | 227 | code: 23 | |
| 219 | 228 | stack: |- | |
@@ -226,6 +235,7 @@ not ok 3 - callback timeout signal | |||
| 226 | 235 | not ok 4 - callback abort signal | |
| 227 | 236 | --- | |
| 228 | 237 | duration_ms: * | |
| 238 | + failureType: 'testAborted' | ||
| 229 | 239 | error: 'This operation was aborted' | |
| 230 | 240 | code: 20 | |
| 231 | 241 | stack: |- | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -64,6 +64,7 @@ TAP version 13 | |||
| 64 | 64 | not ok 1 - describe timeout signal | |
| 65 | 65 | --- | |
| 66 | 66 | duration_ms: * | |
| 67 | + failureType: 'testAborted' | ||
| 67 | 68 | error: 'The operation was aborted due to timeout' | |
| 68 | 69 | code: 23 | |
| 69 | 70 | stack: |- | |
@@ -76,6 +77,7 @@ not ok 1 - describe timeout signal | |||
| 76 | 77 | not ok 2 - describe abort signal | |
| 77 | 78 | --- | |
| 78 | 79 | duration_ms: * | |
| 80 | + failureType: 'testAborted' | ||
| 79 | 81 | error: 'This operation was aborted' | |
| 80 | 82 | code: 20 | |
| 81 | 83 | stack: |- | |
| Back | FazBrowse Home | New Git URL |
0 commit comments