dd-trace 5.104.0 → 5.106.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE-3rdparty.csv +90 -102
- package/index.d.ts +82 -3
- package/package.json +15 -15
- package/packages/datadog-core/src/storage.js +1 -1
- package/packages/datadog-instrumentations/src/aerospike.js +1 -1
- package/packages/datadog-instrumentations/src/ai.js +8 -7
- package/packages/datadog-instrumentations/src/aws-sdk.js +16 -2
- package/packages/datadog-instrumentations/src/azure-cosmos.js +7 -0
- package/packages/datadog-instrumentations/src/azure-functions.js +3 -0
- package/packages/datadog-instrumentations/src/cucumber-worker-threads.js +19 -0
- package/packages/datadog-instrumentations/src/cucumber.js +390 -157
- package/packages/datadog-instrumentations/src/dns.js +54 -18
- package/packages/datadog-instrumentations/src/fastify.js +142 -82
- package/packages/datadog-instrumentations/src/graphql.js +188 -62
- package/packages/datadog-instrumentations/src/helpers/ai-messages.js +322 -14
- package/packages/datadog-instrumentations/src/helpers/hooks.js +4 -0
- package/packages/datadog-instrumentations/src/helpers/instrument.js +2 -1
- package/packages/datadog-instrumentations/src/helpers/openai-ai-guard.js +269 -0
- package/packages/datadog-instrumentations/src/helpers/promise-instrumentor.js +42 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +2 -3
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/azure-cosmos.js +50 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/langgraph.js +4 -2
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/playwright.js +85 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +37 -236
- package/packages/datadog-instrumentations/src/hono.js +54 -3
- package/packages/datadog-instrumentations/src/http/server.js +9 -4
- package/packages/datadog-instrumentations/src/jest/coverage-backfill.js +163 -0
- package/packages/datadog-instrumentations/src/jest.js +360 -150
- package/packages/datadog-instrumentations/src/kafkajs.js +120 -16
- package/packages/datadog-instrumentations/src/mocha/main.js +128 -17
- package/packages/datadog-instrumentations/src/nats.js +182 -0
- package/packages/datadog-instrumentations/src/nyc.js +38 -1
- package/packages/datadog-instrumentations/src/openai.js +33 -18
- package/packages/datadog-instrumentations/src/oracledb.js +6 -1
- package/packages/datadog-instrumentations/src/pino.js +17 -5
- package/packages/datadog-instrumentations/src/playwright.js +515 -292
- package/packages/datadog-instrumentations/src/router.js +76 -32
- package/packages/datadog-instrumentations/src/stripe.js +1 -1
- package/packages/datadog-plugin-avsc/src/schema_iterator.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/tracing.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/utils.js +218 -4
- package/packages/datadog-plugin-azure-cosmos/src/index.js +144 -0
- package/packages/datadog-plugin-azure-event-hubs/src/producer.js +1 -1
- package/packages/datadog-plugin-azure-functions/src/index.js +5 -2
- package/packages/datadog-plugin-azure-service-bus/src/producer.js +1 -1
- package/packages/datadog-plugin-bunyan/src/index.js +28 -0
- package/packages/datadog-plugin-cucumber/src/index.js +17 -3
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +199 -28
- package/packages/datadog-plugin-cypress/src/support.js +69 -1
- package/packages/datadog-plugin-dns/src/lookup.js +8 -6
- package/packages/datadog-plugin-google-cloud-pubsub/src/pubsub-push-subscription.js +1 -1
- package/packages/datadog-plugin-graphql/src/execute.js +2 -0
- package/packages/datadog-plugin-graphql/src/resolve.js +64 -67
- package/packages/datadog-plugin-http/src/server.js +40 -15
- package/packages/datadog-plugin-jest/src/index.js +11 -3
- package/packages/datadog-plugin-jest/src/util.js +15 -8
- package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +1 -1
- package/packages/datadog-plugin-kafkajs/src/producer.js +3 -0
- package/packages/datadog-plugin-langgraph/src/stream.js +1 -1
- package/packages/datadog-plugin-mocha/src/index.js +19 -4
- package/packages/datadog-plugin-mongodb-core/src/index.js +281 -40
- package/packages/datadog-plugin-nats/src/consumer.js +43 -0
- package/packages/datadog-plugin-nats/src/index.js +20 -0
- package/packages/datadog-plugin-nats/src/producer.js +62 -0
- package/packages/datadog-plugin-nats/src/util.js +33 -0
- package/packages/datadog-plugin-next/src/index.js +5 -3
- package/packages/datadog-plugin-openai/src/tracing.js +15 -2
- package/packages/datadog-plugin-oracledb/src/index.js +13 -2
- package/packages/datadog-plugin-pino/src/index.js +42 -0
- package/packages/datadog-plugin-playwright/src/index.js +4 -4
- package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +1 -1
- package/packages/datadog-plugin-rhea/src/producer.js +1 -1
- package/packages/datadog-plugin-router/src/index.js +33 -44
- package/packages/datadog-plugin-selenium/src/index.js +1 -1
- package/packages/datadog-plugin-vitest/src/index.js +5 -13
- package/packages/datadog-plugin-winston/src/index.js +30 -0
- package/packages/datadog-shimmer/src/shimmer.js +33 -40
- package/packages/dd-trace/src/aiguard/index.js +1 -1
- package/packages/dd-trace/src/aiguard/sdk.js +1 -1
- package/packages/dd-trace/src/appsec/api_security_sampler.js +1 -1
- package/packages/dd-trace/src/appsec/index.js +1 -1
- package/packages/dd-trace/src/appsec/reporter.js +5 -6
- package/packages/dd-trace/src/appsec/sdk/user_blocking.js +1 -1
- package/packages/dd-trace/src/appsec/sdk/utils.js +1 -1
- package/packages/dd-trace/src/appsec/user_tracking.js +5 -4
- package/packages/dd-trace/src/baggage.js +7 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +0 -1
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +25 -13
- package/packages/dd-trace/src/ci-visibility/test-optimization-cache.js +70 -6
- package/packages/dd-trace/src/config/generated-config-types.d.ts +6 -2
- package/packages/dd-trace/src/config/supported-configurations.json +27 -8
- package/packages/dd-trace/src/datastreams/writer.js +2 -4
- package/packages/dd-trace/src/debugger/devtools_client/condition.js +5 -8
- package/packages/dd-trace/src/encode/0.4.js +124 -108
- package/packages/dd-trace/src/encode/0.5.js +114 -26
- package/packages/dd-trace/src/encode/agentless-ci-visibility.js +31 -23
- package/packages/dd-trace/src/encode/agentless-json.js +4 -2
- package/packages/dd-trace/src/encode/coverage-ci-visibility.js +32 -13
- package/packages/dd-trace/src/encode/span-stats.js +16 -16
- package/packages/dd-trace/src/encode/tags-processors.js +16 -0
- package/packages/dd-trace/src/id.js +15 -0
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +92 -6
- package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +43 -21
- package/packages/dd-trace/src/llmobs/plugins/genai/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +9 -7
- package/packages/dd-trace/src/llmobs/plugins/langgraph/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/openai/index.js +1 -1
- package/packages/dd-trace/src/llmobs/sdk.js +0 -16
- package/packages/dd-trace/src/llmobs/span_processor.js +3 -3
- package/packages/dd-trace/src/llmobs/tagger.js +9 -1
- package/packages/dd-trace/src/llmobs/telemetry.js +1 -1
- package/packages/dd-trace/src/llmobs/util.js +66 -3
- package/packages/dd-trace/src/log/index.js +1 -1
- package/packages/dd-trace/src/msgpack/chunk.js +394 -10
- package/packages/dd-trace/src/msgpack/index.js +96 -2
- package/packages/dd-trace/src/openfeature/encoding.js +70 -0
- package/packages/dd-trace/src/openfeature/flagging_provider.js +20 -0
- package/packages/dd-trace/src/openfeature/span-enrichment-hook.js +143 -0
- package/packages/dd-trace/src/openfeature/span-enrichment.js +149 -0
- package/packages/dd-trace/src/opentelemetry/span-helpers.js +4 -3
- package/packages/dd-trace/src/opentelemetry/span.js +1 -1
- package/packages/dd-trace/src/opentelemetry/trace/otlp_transformer.js +22 -3
- package/packages/dd-trace/src/opentracing/propagation/log.js +18 -7
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +64 -77
- package/packages/dd-trace/src/opentracing/span.js +59 -19
- package/packages/dd-trace/src/opentracing/span_context.js +50 -3
- package/packages/dd-trace/src/plugins/ci_plugin.js +20 -20
- package/packages/dd-trace/src/plugins/database.js +7 -6
- package/packages/dd-trace/src/plugins/index.js +4 -0
- package/packages/dd-trace/src/plugins/log_injection.js +56 -0
- package/packages/dd-trace/src/plugins/log_plugin.js +3 -48
- package/packages/dd-trace/src/plugins/outbound.js +1 -1
- package/packages/dd-trace/src/plugins/plugin.js +15 -17
- package/packages/dd-trace/src/plugins/tracing.js +43 -5
- package/packages/dd-trace/src/plugins/util/test.js +236 -13
- package/packages/dd-trace/src/plugins/util/web.js +79 -65
- package/packages/dd-trace/src/priority_sampler.js +2 -2
- package/packages/dd-trace/src/profiling/config.js +10 -23
- package/packages/dd-trace/src/profiling/exporters/agent.js +11 -10
- package/packages/dd-trace/src/profiling/profiler.js +21 -11
- package/packages/dd-trace/src/profiling/profilers/wall.js +12 -7
- package/packages/dd-trace/src/sampling_rule.js +7 -7
- package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +10 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +8 -0
- package/packages/dd-trace/src/service-naming/source-resolver.js +46 -0
- package/packages/dd-trace/src/span_format.js +190 -58
- package/packages/dd-trace/src/spanleak.js +1 -1
- package/packages/dd-trace/src/standalone/index.js +3 -3
- package/packages/dd-trace/src/tagger.js +0 -2
- package/vendor/dist/@apm-js-collab/code-transformer/index.js +70 -39
- package/vendor/dist/@datadog/sketches-js/LICENSE +10 -36
- package/vendor/dist/@datadog/sketches-js/index.js +1 -1
- package/vendor/dist/protobufjs/index.js +1 -1
- package/vendor/dist/protobufjs/minimal/index.js +1 -1
- package/packages/dd-trace/src/msgpack/encoder.js +0 -308
- package/packages/dd-trace/src/plugins/structured_log_plugin.js +0 -9
|
@@ -7,24 +7,31 @@ const shimmer = require('../../datadog-shimmer')
|
|
|
7
7
|
const log = require('../../dd-trace/src/log')
|
|
8
8
|
const { getEnvironmentVariable } = require('../../dd-trace/src/config/helper')
|
|
9
9
|
const {
|
|
10
|
-
|
|
10
|
+
getCoveredFilesFromCoverage,
|
|
11
|
+
getExecutableFilesFromCoverage,
|
|
11
12
|
resetCoverage,
|
|
12
13
|
mergeCoverage,
|
|
13
14
|
fromCoverageMapToCoverage,
|
|
14
15
|
getTestSuitePath,
|
|
16
|
+
getRelativeCoverageFiles,
|
|
15
17
|
CUCUMBER_WORKER_TRACE_PAYLOAD_CODE,
|
|
16
18
|
getIsFaultyEarlyFlakeDetection,
|
|
17
19
|
getEfdRetryCount,
|
|
18
20
|
getMaxEfdRetryCount,
|
|
21
|
+
applySkippedCoverageToCoverage,
|
|
22
|
+
getTestCoverageLinesPercentage,
|
|
19
23
|
recordAttemptToFixExecution,
|
|
20
24
|
collectAttemptToFixExecutionsFromTraces,
|
|
21
25
|
logAttemptToFixTestExecution,
|
|
22
26
|
logTestOptimizationSummary,
|
|
23
27
|
getTestOptimizationRequestResults,
|
|
24
28
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
29
|
+
const { writeCoverageBackfillToCache } = require('../../dd-trace/src/ci-visibility/test-optimization-cache')
|
|
25
30
|
const satisfies = require('../../../vendor/dist/semifies')
|
|
26
31
|
const { addHook, channel } = require('./helpers/instrument')
|
|
27
32
|
|
|
33
|
+
const cucumberWorkerThreadsPatchModule = require.resolve('./cucumber-worker-threads')
|
|
34
|
+
|
|
28
35
|
const testStartCh = channel('ci:cucumber:test:start')
|
|
29
36
|
const testRetryCh = channel('ci:cucumber:test:retry')
|
|
30
37
|
const testFinishCh = channel('ci:cucumber:test:finish') // used for test steps too
|
|
@@ -64,6 +71,7 @@ const originalCoverageMap = createCoverageMap()
|
|
|
64
71
|
|
|
65
72
|
// TODO: remove in a later major version
|
|
66
73
|
const patched = new WeakSet()
|
|
74
|
+
const patchedCucumberWorkers = new WeakSet()
|
|
67
75
|
|
|
68
76
|
const lastStatusByPickleId = new Map()
|
|
69
77
|
/** For ATR: statuses keyed by stable scenario id (uri:name) so retries accumulate correctly */
|
|
@@ -86,10 +94,14 @@ let pickleByFile = {}
|
|
|
86
94
|
const pickleResultByFile = {}
|
|
87
95
|
|
|
88
96
|
let skippableSuites = []
|
|
97
|
+
let skippableSuitesCoverage = {}
|
|
98
|
+
let skippedSuitesCoverage = {}
|
|
89
99
|
let itrCorrelationId = ''
|
|
90
100
|
let isForcedToRun = false
|
|
91
101
|
let isUnskippable = false
|
|
102
|
+
let isItrEnabled = false
|
|
92
103
|
let isSuitesSkippingEnabled = false
|
|
104
|
+
let isCoverageReportUploadEnabled = false
|
|
93
105
|
let isEarlyFlakeDetectionEnabled = false
|
|
94
106
|
let earlyFlakeDetectionNumRetries = 0
|
|
95
107
|
let earlyFlakeDetectionSlowTestRetries = {}
|
|
@@ -106,11 +118,55 @@ let numTestRetries = 0
|
|
|
106
118
|
let knownTests = {}
|
|
107
119
|
let skippedSuites = []
|
|
108
120
|
let isSuitesSkipped = false
|
|
121
|
+
let repositoryRoot
|
|
109
122
|
|
|
110
123
|
function isValidKnownTests (receivedKnownTests) {
|
|
111
124
|
return !!receivedKnownTests.cucumber
|
|
112
125
|
}
|
|
113
126
|
|
|
127
|
+
function hasSkippableSuitesCoverage () {
|
|
128
|
+
return skippableSuitesCoverage &&
|
|
129
|
+
typeof skippableSuitesCoverage === 'object' &&
|
|
130
|
+
Object.keys(skippableSuitesCoverage).length > 0
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function isTiaCoverageBackfillEnabled () {
|
|
134
|
+
return isItrEnabled && isCoverageReportUploadEnabled
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function getCoverageRootDir () {
|
|
138
|
+
return repositoryRoot || process.cwd()
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function shouldReportCodeCoverageLinesPct (hasBackfilledCoverage) {
|
|
142
|
+
return !isSuitesSkipped || hasBackfilledCoverage
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function getSkippedSuitesCoverageForRun () {
|
|
146
|
+
return isSuitesSkipped && isTiaCoverageBackfillEnabled() && hasSkippableSuitesCoverage()
|
|
147
|
+
? skippableSuitesCoverage
|
|
148
|
+
: {}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function applySkippedCoverageToCucumberCoverageMap () {
|
|
152
|
+
if (!isTiaCoverageBackfillEnabled()) return false
|
|
153
|
+
return applySkippedCoverageToCoverage(originalCoverageMap, skippedSuitesCoverage, getCoverageRootDir())
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function getCucumberTestSessionCoverageFiles () {
|
|
157
|
+
return getRelativeCoverageFiles(getExecutableFilesFromCoverage(originalCoverageMap), getCoverageRootDir())
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function resetSuiteSkippingRunState () {
|
|
161
|
+
skippableSuites = []
|
|
162
|
+
skippableSuitesCoverage = {}
|
|
163
|
+
skippedSuitesCoverage = {}
|
|
164
|
+
skippedSuites = []
|
|
165
|
+
isSuitesSkipped = false
|
|
166
|
+
repositoryRoot = undefined
|
|
167
|
+
writeCoverageBackfillToCache({})
|
|
168
|
+
}
|
|
169
|
+
|
|
114
170
|
function getSuiteStatusFromTestStatuses (testStatuses) {
|
|
115
171
|
if (testStatuses.includes('fail')) {
|
|
116
172
|
return 'fail'
|
|
@@ -127,22 +183,270 @@ function getConfiguredEfdRetryCount () {
|
|
|
127
183
|
}
|
|
128
184
|
|
|
129
185
|
function publishWorkerEfdRetryCount (pickle, retryCount) {
|
|
130
|
-
|
|
186
|
+
const message = {
|
|
187
|
+
[DD_EFD_RETRY_COUNT_MESSAGE]: {
|
|
188
|
+
pickleId: pickle.id,
|
|
189
|
+
retryCount,
|
|
190
|
+
testFileAbsolutePath: pickle.uri,
|
|
191
|
+
testName: pickle.name,
|
|
192
|
+
},
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (typeof process.send === 'function') {
|
|
196
|
+
try {
|
|
197
|
+
process.send(message)
|
|
198
|
+
} catch {
|
|
199
|
+
// ignore IPC errors
|
|
200
|
+
}
|
|
201
|
+
return
|
|
202
|
+
}
|
|
131
203
|
|
|
132
204
|
try {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
testFileAbsolutePath: pickle.uri,
|
|
138
|
-
testName: pickle.name,
|
|
139
|
-
},
|
|
140
|
-
})
|
|
205
|
+
const { isMainThread, parentPort } = require('node:worker_threads')
|
|
206
|
+
if (isMainThread || !parentPort) return
|
|
207
|
+
|
|
208
|
+
parentPort.postMessage(message)
|
|
141
209
|
} catch {
|
|
142
210
|
// ignore IPC errors
|
|
143
211
|
}
|
|
144
212
|
}
|
|
145
213
|
|
|
214
|
+
function configureParallelWorkerWorldParameters (options) {
|
|
215
|
+
options.worldParameters ??= {}
|
|
216
|
+
|
|
217
|
+
if (isKnownTestsEnabled && isValidKnownTests(knownTests)) {
|
|
218
|
+
options.worldParameters._ddIsKnownTestsEnabled = true
|
|
219
|
+
options.worldParameters._ddIsEarlyFlakeDetectionEnabled = isEarlyFlakeDetectionEnabled
|
|
220
|
+
options.worldParameters._ddKnownTests = knownTests
|
|
221
|
+
options.worldParameters._ddEarlyFlakeDetectionNumRetries = earlyFlakeDetectionNumRetries
|
|
222
|
+
options.worldParameters._ddEarlyFlakeDetectionSlowTestRetries = earlyFlakeDetectionSlowTestRetries
|
|
223
|
+
} else {
|
|
224
|
+
isEarlyFlakeDetectionEnabled = false
|
|
225
|
+
isKnownTestsEnabled = false
|
|
226
|
+
options.worldParameters._ddIsEarlyFlakeDetectionEnabled = false
|
|
227
|
+
options.worldParameters._ddIsKnownTestsEnabled = false
|
|
228
|
+
options.worldParameters._ddEarlyFlakeDetectionNumRetries = 0
|
|
229
|
+
options.worldParameters._ddEarlyFlakeDetectionSlowTestRetries = {}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (isImpactedTestsEnabled) {
|
|
233
|
+
options.worldParameters._ddImpactedTestsEnabled = isImpactedTestsEnabled
|
|
234
|
+
options.worldParameters._ddModifiedFiles = modifiedFiles
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
options.worldParameters._ddIsFlakyTestRetriesEnabled = isFlakyTestRetriesEnabled
|
|
238
|
+
options.worldParameters._ddNumTestRetries = numTestRetries
|
|
239
|
+
|
|
240
|
+
if (isTestManagementTestsEnabled) {
|
|
241
|
+
options.worldParameters._ddIsTestManagementTestsEnabled = true
|
|
242
|
+
options.worldParameters._ddTestManagementTests = testManagementTests
|
|
243
|
+
options.worldParameters._ddTestManagementAttemptToFixRetries = testManagementAttemptToFixRetries
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function readParallelWorkerWorldParameters (options) {
|
|
248
|
+
const worldParameters = options?.worldParameters
|
|
249
|
+
if (!worldParameters) return
|
|
250
|
+
|
|
251
|
+
isKnownTestsEnabled = !!worldParameters._ddIsKnownTestsEnabled
|
|
252
|
+
if (isKnownTestsEnabled) {
|
|
253
|
+
knownTests = worldParameters._ddKnownTests
|
|
254
|
+
// if for whatever reason the worker does not receive valid known tests, we disable EFD and known tests
|
|
255
|
+
if (!isValidKnownTests(knownTests)) {
|
|
256
|
+
isKnownTestsEnabled = false
|
|
257
|
+
knownTests = {}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
isEarlyFlakeDetectionEnabled = !!worldParameters._ddIsEarlyFlakeDetectionEnabled
|
|
261
|
+
if (isEarlyFlakeDetectionEnabled) {
|
|
262
|
+
earlyFlakeDetectionNumRetries = worldParameters._ddEarlyFlakeDetectionNumRetries
|
|
263
|
+
earlyFlakeDetectionSlowTestRetries = worldParameters._ddEarlyFlakeDetectionSlowTestRetries ?? {}
|
|
264
|
+
}
|
|
265
|
+
isImpactedTestsEnabled = !!worldParameters._ddImpactedTestsEnabled
|
|
266
|
+
if (isImpactedTestsEnabled) {
|
|
267
|
+
modifiedFiles = worldParameters._ddModifiedFiles
|
|
268
|
+
}
|
|
269
|
+
isFlakyTestRetriesEnabled = !!worldParameters._ddIsFlakyTestRetriesEnabled
|
|
270
|
+
numTestRetries = worldParameters._ddNumTestRetries ?? 0
|
|
271
|
+
isTestManagementTestsEnabled = !!worldParameters._ddIsTestManagementTestsEnabled
|
|
272
|
+
if (isTestManagementTestsEnabled) {
|
|
273
|
+
testManagementTests = worldParameters._ddTestManagementTests
|
|
274
|
+
testManagementAttemptToFixRetries = worldParameters._ddTestManagementAttemptToFixRetries
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function handleDdWorkerMessage (message) {
|
|
279
|
+
if (Array.isArray(message)) {
|
|
280
|
+
const [messageCode, payload] = message
|
|
281
|
+
if (messageCode === CUCUMBER_WORKER_TRACE_PAYLOAD_CODE) {
|
|
282
|
+
collectAttemptToFixExecutionsFromTraces(payload, attemptToFixExecutions)
|
|
283
|
+
workerReportTraceCh.publish(payload)
|
|
284
|
+
return true
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (message?.[DD_EFD_RETRY_COUNT_MESSAGE]) {
|
|
289
|
+
handleEfdRetryCountMessage(message[DD_EFD_RETRY_COUNT_MESSAGE])
|
|
290
|
+
return true
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
return false
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function onCucumberWorkerThreadMessage (message) {
|
|
297
|
+
if (!testSuiteFinishCh.hasSubscribers) return
|
|
298
|
+
|
|
299
|
+
handleDdWorkerMessage(message)
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function registerWorkerThreadMessageHandlers (workers) {
|
|
303
|
+
if (!workers) return
|
|
304
|
+
|
|
305
|
+
for (const worker of workers) {
|
|
306
|
+
worker.workerThread.on('message', onCucumberWorkerThreadMessage)
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
function registerWorkerThreadPatchModule (supportCodeLibrary) {
|
|
311
|
+
const requireModules = supportCodeLibrary?.originalCoordinates?.requireModules
|
|
312
|
+
if (!Array.isArray(requireModules) || requireModules.includes(cucumberWorkerThreadsPatchModule)) return
|
|
313
|
+
|
|
314
|
+
requireModules.unshift(cucumberWorkerThreadsPatchModule)
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function getRunningAssembledTestCase (adapter, worker) {
|
|
318
|
+
const command = adapter.running?.get(worker)
|
|
319
|
+
return command?.assembledTestCase
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
function maybeStartParallelSuite (pickle) {
|
|
323
|
+
if (!pickle) return
|
|
324
|
+
|
|
325
|
+
const testFileAbsolutePath = pickle.uri
|
|
326
|
+
if (pickleResultByFile[testFileAbsolutePath]) return
|
|
327
|
+
|
|
328
|
+
pickleResultByFile[testFileAbsolutePath] = []
|
|
329
|
+
testSuiteStartCh.publish({
|
|
330
|
+
testFileAbsolutePath,
|
|
331
|
+
})
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
function handleParallelTestCaseFinished (pickle, worstTestStepResult) {
|
|
335
|
+
const { status } = getStatusFromResultLatest(worstTestStepResult)
|
|
336
|
+
let isNew = false
|
|
337
|
+
|
|
338
|
+
if (isKnownTestsEnabled) {
|
|
339
|
+
isNew = isNewTest(pickle.uri, pickle.name)
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
const testFileAbsolutePath = pickle.uri
|
|
343
|
+
const finished = pickleResultByFile[testFileAbsolutePath] || (pickleResultByFile[testFileAbsolutePath] = [])
|
|
344
|
+
|
|
345
|
+
if (isEarlyFlakeDetectionEnabled && isNew) {
|
|
346
|
+
const testFullname = `${pickle.uri}:${pickle.name}`
|
|
347
|
+
let testStatuses = newTestsByTestFullname.get(testFullname)
|
|
348
|
+
if (testStatuses) {
|
|
349
|
+
testStatuses.push(status)
|
|
350
|
+
} else {
|
|
351
|
+
testStatuses = [status]
|
|
352
|
+
newTestsByTestFullname.set(testFullname, testStatuses)
|
|
353
|
+
}
|
|
354
|
+
let efdRetryCount = efdRetryCountByPickleId.get(pickle.id)
|
|
355
|
+
if (efdRetryCount === undefined) {
|
|
356
|
+
efdRetryCount = status === 'skip'
|
|
357
|
+
? 0
|
|
358
|
+
: getConfiguredEfdRetryCount()
|
|
359
|
+
efdRetryCountByPickleId.set(pickle.id, efdRetryCount)
|
|
360
|
+
if (efdRetryCount === 0 && status !== 'skip') {
|
|
361
|
+
efdSlowAbortedPickleIds.add(pickle.id)
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
maybeRecordFinalParallelEfdStatus({ pickleId: pickle.id, testFileAbsolutePath, testFullname })
|
|
365
|
+
} else if (
|
|
366
|
+
isTestManagementTestsEnabled &&
|
|
367
|
+
getTestProperties(getTestSuitePath(testFileAbsolutePath, process.cwd()), pickle.name).attemptToFix
|
|
368
|
+
) {
|
|
369
|
+
const testFullname = `${pickle.uri}:${pickle.name}`
|
|
370
|
+
let testStatuses = attemptToFixTestsByTestFullname.get(testFullname)
|
|
371
|
+
if (testStatuses) {
|
|
372
|
+
testStatuses.push(status)
|
|
373
|
+
} else {
|
|
374
|
+
testStatuses = [status]
|
|
375
|
+
attemptToFixTestsByTestFullname.set(testFullname, testStatuses)
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
if (status === 'skip' || testStatuses.length === testManagementAttemptToFixRetries + 1) {
|
|
379
|
+
finished.push(getTestStatusFromAttemptToFixExecutions(testStatuses))
|
|
380
|
+
attemptToFixTestsByTestFullname.delete(testFullname)
|
|
381
|
+
}
|
|
382
|
+
} else {
|
|
383
|
+
// TODO: can we get error message?
|
|
384
|
+
finished.push(status)
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
finishParallelSuiteIfDone(testFileAbsolutePath)
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
function getWrappedHandleWorkerThreadEvent (handleEventFromWorker) {
|
|
391
|
+
return function (worker, event) {
|
|
392
|
+
if (!testSuiteFinishCh.hasSubscribers) {
|
|
393
|
+
return handleEventFromWorker.apply(this, arguments)
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
if (handleDdWorkerMessage(event)) return
|
|
397
|
+
|
|
398
|
+
const envelope = event?.type === 'ENVELOPE' && event.envelope
|
|
399
|
+
if (!envelope) {
|
|
400
|
+
return handleEventFromWorker.apply(this, arguments)
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
const assembledTestCase = getRunningAssembledTestCase(this, worker)
|
|
404
|
+
|
|
405
|
+
if (envelope.testCaseStarted) {
|
|
406
|
+
maybeStartParallelSuite(assembledTestCase?.pickle)
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
const result = handleEventFromWorker.apply(this, arguments)
|
|
410
|
+
|
|
411
|
+
if (envelope.testCaseFinished && assembledTestCase?.pickle && eventDataCollector) {
|
|
412
|
+
const worstTestStepResult =
|
|
413
|
+
eventDataCollector.getTestCaseAttempt(envelope.testCaseFinished.testCaseStartedId).worstTestStepResult
|
|
414
|
+
handleParallelTestCaseFinished(assembledTestCase.pickle, worstTestStepResult)
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
return result
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
function getWrappedWorkerThreadsSetup (setup) {
|
|
422
|
+
return async function () {
|
|
423
|
+
if (testSuiteFinishCh.hasSubscribers) {
|
|
424
|
+
configureParallelWorkerWorldParameters(this.options)
|
|
425
|
+
registerWorkerThreadPatchModule(this.supportCodeLibrary)
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
const result = await setup.apply(this, arguments)
|
|
429
|
+
|
|
430
|
+
if (testSuiteFinishCh.hasSubscribers) {
|
|
431
|
+
registerWorkerThreadMessageHandlers(this.workers)
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
return result
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
function getWrappedWorkerThreadsTeardown (teardown) {
|
|
439
|
+
return function () {
|
|
440
|
+
if (testSuiteFinishCh.hasSubscribers && this.workers) {
|
|
441
|
+
for (const worker of this.workers) {
|
|
442
|
+
worker.workerThread.removeListener('message', onCucumberWorkerThreadMessage)
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
return teardown.apply(this, arguments)
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
146
450
|
function finishParallelSuiteIfDone (testFileAbsolutePath) {
|
|
147
451
|
const finished = pickleResultByFile[testFileAbsolutePath]
|
|
148
452
|
const expectedPickles = pickleByFile[testFileAbsolutePath]
|
|
@@ -683,6 +987,7 @@ function getWrappedStart (start, frameworkVersion, isParallel = false, isCoordin
|
|
|
683
987
|
if (!libraryConfigurationCh.hasSubscribers) {
|
|
684
988
|
return start.apply(this, arguments)
|
|
685
989
|
}
|
|
990
|
+
resetSuiteSkippingRunState()
|
|
686
991
|
const options = getCucumberOptions(this)
|
|
687
992
|
|
|
688
993
|
if (!isParallel && this.adapter?.options) {
|
|
@@ -692,11 +997,14 @@ function getWrappedStart (start, frameworkVersion, isParallel = false, isCoordin
|
|
|
692
997
|
|
|
693
998
|
const configurationResponse = await getChannelPromise(libraryConfigurationCh, frameworkVersion)
|
|
694
999
|
|
|
1000
|
+
repositoryRoot = configurationResponse.repositoryRoot
|
|
1001
|
+
isItrEnabled = configurationResponse.libraryConfig?.isItrEnabled
|
|
695
1002
|
isEarlyFlakeDetectionEnabled = configurationResponse.libraryConfig?.isEarlyFlakeDetectionEnabled
|
|
696
1003
|
earlyFlakeDetectionNumRetries = configurationResponse.libraryConfig?.earlyFlakeDetectionNumRetries
|
|
697
1004
|
earlyFlakeDetectionSlowTestRetries = configurationResponse.libraryConfig?.earlyFlakeDetectionSlowTestRetries ?? {}
|
|
698
1005
|
earlyFlakeDetectionFaultyThreshold = configurationResponse.libraryConfig?.earlyFlakeDetectionFaultyThreshold
|
|
699
|
-
isSuitesSkippingEnabled = configurationResponse.libraryConfig?.isSuitesSkippingEnabled
|
|
1006
|
+
isSuitesSkippingEnabled = isItrEnabled && configurationResponse.libraryConfig?.isSuitesSkippingEnabled
|
|
1007
|
+
isCoverageReportUploadEnabled = configurationResponse.libraryConfig?.isCoverageReportUploadEnabled
|
|
700
1008
|
isFlakyTestRetriesEnabled = configurationResponse.libraryConfig?.isFlakyTestRetriesEnabled
|
|
701
1009
|
const configRetryCount = configurationResponse.libraryConfig?.flakyTestRetriesCount
|
|
702
1010
|
numTestRetries = (typeof configRetryCount === 'number' && configRetryCount > 0) ? configRetryCount : 0
|
|
@@ -733,6 +1041,7 @@ function getWrappedStart (start, frameworkVersion, isParallel = false, isCoordin
|
|
|
733
1041
|
|
|
734
1042
|
errorSkippableRequest = skippableResponse.err
|
|
735
1043
|
skippableSuites = skippableResponse.skippableSuites ?? []
|
|
1044
|
+
skippableSuitesCoverage = skippableResponse.skippableSuitesCoverage ?? {}
|
|
736
1045
|
|
|
737
1046
|
if (!errorSkippableRequest) {
|
|
738
1047
|
const filteredPickles = isCoordinator
|
|
@@ -753,6 +1062,8 @@ function getWrappedStart (start, frameworkVersion, isParallel = false, isCoordin
|
|
|
753
1062
|
}
|
|
754
1063
|
|
|
755
1064
|
skippedSuites = [...filteredPickles.skippedSuites]
|
|
1065
|
+
skippedSuitesCoverage = getSkippedSuitesCoverageForRun()
|
|
1066
|
+
writeCoverageBackfillToCache(skippedSuitesCoverage, getCoverageRootDir())
|
|
756
1067
|
itrCorrelationId = skippableResponse.itrCorrelationId
|
|
757
1068
|
}
|
|
758
1069
|
}
|
|
@@ -816,13 +1127,25 @@ function getWrappedStart (start, frameworkVersion, isParallel = false, isCoordin
|
|
|
816
1127
|
}
|
|
817
1128
|
|
|
818
1129
|
let testCodeCoverageLinesTotal
|
|
1130
|
+
let testSessionCoverageFiles
|
|
819
1131
|
|
|
820
|
-
if (global.__coverage__) {
|
|
1132
|
+
if (global.__coverage__ || untestedCoverage) {
|
|
821
1133
|
try {
|
|
1134
|
+
let hasBackfilledCoverage = false
|
|
822
1135
|
if (untestedCoverage) {
|
|
823
1136
|
originalCoverageMap.merge(fromCoverageMapToCoverage(untestedCoverage))
|
|
824
1137
|
}
|
|
825
|
-
|
|
1138
|
+
hasBackfilledCoverage = applySkippedCoverageToCucumberCoverageMap()
|
|
1139
|
+
if (shouldReportCodeCoverageLinesPct(hasBackfilledCoverage)) {
|
|
1140
|
+
testCodeCoverageLinesTotal = getTestCoverageLinesPercentage(
|
|
1141
|
+
originalCoverageMap,
|
|
1142
|
+
undefined,
|
|
1143
|
+
getCoverageRootDir()
|
|
1144
|
+
)
|
|
1145
|
+
}
|
|
1146
|
+
if (isTiaCoverageBackfillEnabled()) {
|
|
1147
|
+
testSessionCoverageFiles = getCucumberTestSessionCoverageFiles()
|
|
1148
|
+
}
|
|
826
1149
|
} catch {
|
|
827
1150
|
// ignore errors
|
|
828
1151
|
}
|
|
@@ -834,6 +1157,7 @@ function getWrappedStart (start, frameworkVersion, isParallel = false, isCoordin
|
|
|
834
1157
|
status: success ? 'pass' : 'fail',
|
|
835
1158
|
isSuitesSkipped,
|
|
836
1159
|
testCodeCoverageLinesTotal,
|
|
1160
|
+
testSessionCoverageFiles,
|
|
837
1161
|
numSkippedSuites: skippedSuites.length,
|
|
838
1162
|
hasUnskippableSuites: isUnskippable,
|
|
839
1163
|
hasForcedToRunSuites: isForcedToRun,
|
|
@@ -856,6 +1180,9 @@ function getWrappedRunTestCase (runTestCaseFunction, isNewerCucumberVersion = fa
|
|
|
856
1180
|
if (!testSuiteFinishCh.hasSubscribers) {
|
|
857
1181
|
return runTestCaseFunction.apply(this, arguments)
|
|
858
1182
|
}
|
|
1183
|
+
if (isWorker) {
|
|
1184
|
+
readParallelWorkerWorldParameters(this.options)
|
|
1185
|
+
}
|
|
859
1186
|
const pickle = isNewerCucumberVersion
|
|
860
1187
|
? arguments[0].pickle
|
|
861
1188
|
: this.eventDataCollector.getPickle(arguments[0])
|
|
@@ -1008,7 +1335,7 @@ function getWrappedRunTestCase (runTestCaseFunction, isNewerCucumberVersion = fa
|
|
|
1008
1335
|
// last test in suite
|
|
1009
1336
|
const testSuiteStatus = getSuiteStatusFromTestStatuses(pickleResultByFile[testFileAbsolutePath])
|
|
1010
1337
|
if (global.__coverage__) {
|
|
1011
|
-
const coverageFiles =
|
|
1338
|
+
const coverageFiles = getCoveredFilesFromCoverage(global.__coverage__)
|
|
1012
1339
|
|
|
1013
1340
|
testSuiteCodeCoverageCh.publish({
|
|
1014
1341
|
coverageFiles,
|
|
@@ -1040,26 +1367,25 @@ function getWrappedRunTestCase (runTestCaseFunction, isNewerCucumberVersion = fa
|
|
|
1040
1367
|
}
|
|
1041
1368
|
}
|
|
1042
1369
|
|
|
1370
|
+
function patchCucumberWorkerRunTestCase (workerPackage, isWorker) {
|
|
1371
|
+
const workerPrototype = workerPackage?.Worker?.prototype
|
|
1372
|
+
if (!workerPrototype || patchedCucumberWorkers.has(workerPrototype)) return
|
|
1373
|
+
|
|
1374
|
+
patchedCucumberWorkers.add(workerPrototype)
|
|
1375
|
+
shimmer.wrap(
|
|
1376
|
+
workerPrototype,
|
|
1377
|
+
'runTestCase',
|
|
1378
|
+
runTestCase => getWrappedRunTestCase(runTestCase, true, isWorker)
|
|
1379
|
+
)
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1043
1382
|
function getWrappedParseWorkerMessage (parseWorkerMessageFunction, isNewVersion) {
|
|
1044
1383
|
return function (worker, message) {
|
|
1045
1384
|
if (!testSuiteFinishCh.hasSubscribers) {
|
|
1046
1385
|
return parseWorkerMessageFunction.apply(this, arguments)
|
|
1047
1386
|
}
|
|
1048
|
-
// If
|
|
1049
|
-
|
|
1050
|
-
// TODO: identify the message better
|
|
1051
|
-
if (Array.isArray(message)) {
|
|
1052
|
-
const [messageCode, payload] = message
|
|
1053
|
-
if (messageCode === CUCUMBER_WORKER_TRACE_PAYLOAD_CODE) {
|
|
1054
|
-
collectAttemptToFixExecutionsFromTraces(payload, attemptToFixExecutions)
|
|
1055
|
-
workerReportTraceCh.publish(payload)
|
|
1056
|
-
return
|
|
1057
|
-
}
|
|
1058
|
-
}
|
|
1059
|
-
if (message[DD_EFD_RETRY_COUNT_MESSAGE]) {
|
|
1060
|
-
handleEfdRetryCountMessage(message[DD_EFD_RETRY_COUNT_MESSAGE])
|
|
1061
|
-
return
|
|
1062
|
-
}
|
|
1387
|
+
// If it's a dd-trace message, stop cucumber processing or cucumber will throw an error.
|
|
1388
|
+
if (handleDdWorkerMessage(message)) return
|
|
1063
1389
|
|
|
1064
1390
|
const envelope = isNewVersion ? message.envelope : message.jsonEnvelope
|
|
1065
1391
|
|
|
@@ -1076,10 +1402,7 @@ function getWrappedParseWorkerMessage (parseWorkerMessageFunction, isNewVersion)
|
|
|
1076
1402
|
return parseWorkerMessageFunction.apply(this, arguments)
|
|
1077
1403
|
}
|
|
1078
1404
|
}
|
|
1079
|
-
if (parsed
|
|
1080
|
-
handleEfdRetryCountMessage(parsed[DD_EFD_RETRY_COUNT_MESSAGE])
|
|
1081
|
-
return
|
|
1082
|
-
}
|
|
1405
|
+
if (handleDdWorkerMessage(parsed)) return
|
|
1083
1406
|
let pickle
|
|
1084
1407
|
|
|
1085
1408
|
if (parsed.testCaseStarted) {
|
|
@@ -1089,15 +1412,7 @@ function getWrappedParseWorkerMessage (parseWorkerMessageFunction, isNewVersion)
|
|
|
1089
1412
|
const { pickleId } = this.eventDataCollector.testCaseMap[parsed.testCaseStarted.testCaseId]
|
|
1090
1413
|
pickle = this.eventDataCollector.getPickle(pickleId)
|
|
1091
1414
|
}
|
|
1092
|
-
|
|
1093
|
-
const testFileAbsolutePath = pickle.uri
|
|
1094
|
-
// First test in suite
|
|
1095
|
-
if (!pickleResultByFile[testFileAbsolutePath]) {
|
|
1096
|
-
pickleResultByFile[testFileAbsolutePath] = []
|
|
1097
|
-
testSuiteStartCh.publish({
|
|
1098
|
-
testFileAbsolutePath,
|
|
1099
|
-
})
|
|
1100
|
-
}
|
|
1415
|
+
maybeStartParallelSuite(pickle)
|
|
1101
1416
|
}
|
|
1102
1417
|
|
|
1103
1418
|
const parseWorkerResponse = parseWorkerMessageFunction.apply(this, arguments)
|
|
@@ -1115,66 +1430,15 @@ function getWrappedParseWorkerMessage (parseWorkerMessageFunction, isNewVersion)
|
|
|
1115
1430
|
pickle = testCase.pickle
|
|
1116
1431
|
}
|
|
1117
1432
|
|
|
1118
|
-
|
|
1119
|
-
let isNew = false
|
|
1120
|
-
|
|
1121
|
-
if (isKnownTestsEnabled) {
|
|
1122
|
-
isNew = isNewTest(pickle.uri, pickle.name)
|
|
1123
|
-
}
|
|
1124
|
-
|
|
1125
|
-
const testFileAbsolutePath = pickle.uri
|
|
1126
|
-
const finished = pickleResultByFile[testFileAbsolutePath]
|
|
1127
|
-
|
|
1128
|
-
if (isEarlyFlakeDetectionEnabled && isNew) {
|
|
1129
|
-
const testFullname = `${pickle.uri}:${pickle.name}`
|
|
1130
|
-
let testStatuses = newTestsByTestFullname.get(testFullname)
|
|
1131
|
-
if (testStatuses) {
|
|
1132
|
-
testStatuses.push(status)
|
|
1133
|
-
} else {
|
|
1134
|
-
testStatuses = [status]
|
|
1135
|
-
newTestsByTestFullname.set(testFullname, testStatuses)
|
|
1136
|
-
}
|
|
1137
|
-
let efdRetryCount = efdRetryCountByPickleId.get(pickle.id)
|
|
1138
|
-
if (efdRetryCount === undefined) {
|
|
1139
|
-
efdRetryCount = status === 'skip'
|
|
1140
|
-
? 0
|
|
1141
|
-
: getConfiguredEfdRetryCount()
|
|
1142
|
-
efdRetryCountByPickleId.set(pickle.id, efdRetryCount)
|
|
1143
|
-
if (efdRetryCount === 0 && status !== 'skip') {
|
|
1144
|
-
efdSlowAbortedPickleIds.add(pickle.id)
|
|
1145
|
-
}
|
|
1146
|
-
}
|
|
1147
|
-
maybeRecordFinalParallelEfdStatus({ pickleId: pickle.id, testFileAbsolutePath, testFullname })
|
|
1148
|
-
} else if (
|
|
1149
|
-
isTestManagementTestsEnabled &&
|
|
1150
|
-
getTestProperties(getTestSuitePath(testFileAbsolutePath, process.cwd()), pickle.name).attemptToFix
|
|
1151
|
-
) {
|
|
1152
|
-
const testFullname = `${pickle.uri}:${pickle.name}`
|
|
1153
|
-
let testStatuses = attemptToFixTestsByTestFullname.get(testFullname)
|
|
1154
|
-
if (testStatuses) {
|
|
1155
|
-
testStatuses.push(status)
|
|
1156
|
-
} else {
|
|
1157
|
-
testStatuses = [status]
|
|
1158
|
-
attemptToFixTestsByTestFullname.set(testFullname, testStatuses)
|
|
1159
|
-
}
|
|
1160
|
-
|
|
1161
|
-
if (status === 'skip' || testStatuses.length === testManagementAttemptToFixRetries + 1) {
|
|
1162
|
-
finished.push(getTestStatusFromAttemptToFixExecutions(testStatuses))
|
|
1163
|
-
attemptToFixTestsByTestFullname.delete(testFullname)
|
|
1164
|
-
}
|
|
1165
|
-
} else {
|
|
1166
|
-
// TODO: can we get error message?
|
|
1167
|
-
const finished = pickleResultByFile[testFileAbsolutePath]
|
|
1168
|
-
finished.push(status)
|
|
1169
|
-
}
|
|
1170
|
-
|
|
1171
|
-
finishParallelSuiteIfDone(testFileAbsolutePath)
|
|
1433
|
+
handleParallelTestCaseFinished(pickle, worstTestStepResult)
|
|
1172
1434
|
}
|
|
1173
1435
|
|
|
1174
1436
|
return parseWorkerResponse
|
|
1175
1437
|
}
|
|
1176
1438
|
}
|
|
1177
1439
|
|
|
1440
|
+
module.exports.patchCucumberWorkerRunTestCase = patchCucumberWorkerRunTestCase
|
|
1441
|
+
|
|
1178
1442
|
// Test start / finish for older versions. The only hook executed in workers when in parallel mode
|
|
1179
1443
|
addHook({
|
|
1180
1444
|
name: '@cucumber/cucumber',
|
|
@@ -1246,11 +1510,7 @@ addHook({
|
|
|
1246
1510
|
versions: ['>=11.0.0'],
|
|
1247
1511
|
file: 'lib/runtime/worker.js',
|
|
1248
1512
|
}, (workerPackage) => {
|
|
1249
|
-
|
|
1250
|
-
workerPackage.Worker.prototype,
|
|
1251
|
-
'runTestCase',
|
|
1252
|
-
runTestCase => getWrappedRunTestCase(runTestCase, true, !!getEnvironmentVariable('CUCUMBER_WORKER_ID'))
|
|
1253
|
-
)
|
|
1513
|
+
patchCucumberWorkerRunTestCase(workerPackage, !!getEnvironmentVariable('CUCUMBER_WORKER_ID'))
|
|
1254
1514
|
return workerPackage
|
|
1255
1515
|
})
|
|
1256
1516
|
|
|
@@ -1286,7 +1546,7 @@ addHook({
|
|
|
1286
1546
|
// In `startWorker` we pass early flake detection info to the worker.
|
|
1287
1547
|
addHook({
|
|
1288
1548
|
name: '@cucumber/cucumber',
|
|
1289
|
-
versions: ['>=11.0.0'],
|
|
1549
|
+
versions: ['>=11.0.0 <13.0.0'],
|
|
1290
1550
|
file: 'lib/runtime/parallel/adapter.js',
|
|
1291
1551
|
}, (adapterPackage) => {
|
|
1292
1552
|
shimmer.wrap(
|
|
@@ -1296,46 +1556,43 @@ addHook({
|
|
|
1296
1556
|
)
|
|
1297
1557
|
// EFD in parallel mode only supported in >=11.0.0
|
|
1298
1558
|
shimmer.wrap(adapterPackage.ChildProcessAdapter.prototype, 'startWorker', startWorker => function (...args) {
|
|
1299
|
-
|
|
1300
|
-
this.options.worldParameters._ddIsKnownTestsEnabled = true
|
|
1301
|
-
this.options.worldParameters._ddIsEarlyFlakeDetectionEnabled = isEarlyFlakeDetectionEnabled
|
|
1302
|
-
this.options.worldParameters._ddKnownTests = knownTests
|
|
1303
|
-
this.options.worldParameters._ddEarlyFlakeDetectionNumRetries = earlyFlakeDetectionNumRetries
|
|
1304
|
-
this.options.worldParameters._ddEarlyFlakeDetectionSlowTestRetries = earlyFlakeDetectionSlowTestRetries
|
|
1305
|
-
} else {
|
|
1306
|
-
isEarlyFlakeDetectionEnabled = false
|
|
1307
|
-
isKnownTestsEnabled = false
|
|
1308
|
-
this.options.worldParameters._ddIsEarlyFlakeDetectionEnabled = false
|
|
1309
|
-
this.options.worldParameters._ddIsKnownTestsEnabled = false
|
|
1310
|
-
this.options.worldParameters._ddEarlyFlakeDetectionNumRetries = 0
|
|
1311
|
-
this.options.worldParameters._ddEarlyFlakeDetectionSlowTestRetries = {}
|
|
1312
|
-
}
|
|
1313
|
-
|
|
1314
|
-
if (isImpactedTestsEnabled) {
|
|
1315
|
-
this.options.worldParameters._ddImpactedTestsEnabled = isImpactedTestsEnabled
|
|
1316
|
-
this.options.worldParameters._ddModifiedFiles = modifiedFiles
|
|
1317
|
-
}
|
|
1318
|
-
|
|
1319
|
-
this.options.worldParameters._ddIsFlakyTestRetriesEnabled = isFlakyTestRetriesEnabled
|
|
1320
|
-
this.options.worldParameters._ddNumTestRetries = numTestRetries
|
|
1321
|
-
|
|
1322
|
-
if (isTestManagementTestsEnabled) {
|
|
1323
|
-
this.options.worldParameters._ddIsTestManagementTestsEnabled = true
|
|
1324
|
-
this.options.worldParameters._ddTestManagementTests = testManagementTests
|
|
1325
|
-
this.options.worldParameters._ddTestManagementAttemptToFixRetries = testManagementAttemptToFixRetries
|
|
1326
|
-
}
|
|
1327
|
-
|
|
1559
|
+
configureParallelWorkerWorldParameters(this.options)
|
|
1328
1560
|
return startWorker.apply(this, args)
|
|
1329
1561
|
})
|
|
1330
1562
|
return adapterPackage
|
|
1331
1563
|
})
|
|
1332
1564
|
|
|
1565
|
+
// Only executed in parallel mode for >=13, in the main process.
|
|
1566
|
+
// Cucumber v13 uses worker_threads and receives worker events via MessagePort.
|
|
1567
|
+
addHook({
|
|
1568
|
+
name: '@cucumber/cucumber',
|
|
1569
|
+
versions: ['>=13.0.0'],
|
|
1570
|
+
file: 'lib/runtime/parallel/adapter.js',
|
|
1571
|
+
}, (adapterPackage) => {
|
|
1572
|
+
shimmer.wrap(
|
|
1573
|
+
adapterPackage.WorkerThreadsAdapter.prototype,
|
|
1574
|
+
'setup',
|
|
1575
|
+
setup => getWrappedWorkerThreadsSetup(setup)
|
|
1576
|
+
)
|
|
1577
|
+
shimmer.wrap(
|
|
1578
|
+
adapterPackage.WorkerThreadsAdapter.prototype,
|
|
1579
|
+
'handleEventFromWorker',
|
|
1580
|
+
handleEventFromWorker => getWrappedHandleWorkerThreadEvent(handleEventFromWorker)
|
|
1581
|
+
)
|
|
1582
|
+
shimmer.wrap(
|
|
1583
|
+
adapterPackage.WorkerThreadsAdapter.prototype,
|
|
1584
|
+
'teardown',
|
|
1585
|
+
teardown => getWrappedWorkerThreadsTeardown(teardown)
|
|
1586
|
+
)
|
|
1587
|
+
return adapterPackage
|
|
1588
|
+
})
|
|
1589
|
+
|
|
1333
1590
|
// Hook executed in the worker process when in parallel mode.
|
|
1334
1591
|
// In this hook we read the information passed in `worldParameters` and make it available for
|
|
1335
1592
|
// `getWrappedRunTestCase`.
|
|
1336
1593
|
addHook({
|
|
1337
1594
|
name: '@cucumber/cucumber',
|
|
1338
|
-
versions: ['>=11.0.0'],
|
|
1595
|
+
versions: ['>=11.0.0 <13.0.0'],
|
|
1339
1596
|
file: 'lib/runtime/parallel/worker.js',
|
|
1340
1597
|
}, (workerPackage) => {
|
|
1341
1598
|
shimmer.wrap(
|
|
@@ -1343,31 +1600,7 @@ addHook({
|
|
|
1343
1600
|
'initialize',
|
|
1344
1601
|
initialize => async function () {
|
|
1345
1602
|
await initialize.apply(this, arguments)
|
|
1346
|
-
|
|
1347
|
-
if (isKnownTestsEnabled) {
|
|
1348
|
-
knownTests = this.options.worldParameters._ddKnownTests
|
|
1349
|
-
// if for whatever reason the worker does not receive valid known tests, we disable EFD and known tests
|
|
1350
|
-
if (!isValidKnownTests(knownTests)) {
|
|
1351
|
-
isKnownTestsEnabled = false
|
|
1352
|
-
knownTests = {}
|
|
1353
|
-
}
|
|
1354
|
-
}
|
|
1355
|
-
isEarlyFlakeDetectionEnabled = !!this.options.worldParameters._ddIsEarlyFlakeDetectionEnabled
|
|
1356
|
-
if (isEarlyFlakeDetectionEnabled) {
|
|
1357
|
-
earlyFlakeDetectionNumRetries = this.options.worldParameters._ddEarlyFlakeDetectionNumRetries
|
|
1358
|
-
earlyFlakeDetectionSlowTestRetries = this.options.worldParameters._ddEarlyFlakeDetectionSlowTestRetries ?? {}
|
|
1359
|
-
}
|
|
1360
|
-
isImpactedTestsEnabled = !!this.options.worldParameters._ddImpactedTestsEnabled
|
|
1361
|
-
if (isImpactedTestsEnabled) {
|
|
1362
|
-
modifiedFiles = this.options.worldParameters._ddModifiedFiles
|
|
1363
|
-
}
|
|
1364
|
-
isFlakyTestRetriesEnabled = !!this.options.worldParameters._ddIsFlakyTestRetriesEnabled
|
|
1365
|
-
numTestRetries = this.options.worldParameters._ddNumTestRetries ?? 0
|
|
1366
|
-
isTestManagementTestsEnabled = !!this.options.worldParameters._ddIsTestManagementTestsEnabled
|
|
1367
|
-
if (isTestManagementTestsEnabled) {
|
|
1368
|
-
testManagementTests = this.options.worldParameters._ddTestManagementTests
|
|
1369
|
-
testManagementAttemptToFixRetries = this.options.worldParameters._ddTestManagementAttemptToFixRetries
|
|
1370
|
-
}
|
|
1603
|
+
readParallelWorkerWorldParameters(this.options)
|
|
1371
1604
|
}
|
|
1372
1605
|
)
|
|
1373
1606
|
return workerPackage
|