dd-trace 5.105.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/package.json +1 -1
- package/packages/datadog-instrumentations/src/aws-sdk.js +3 -2
- package/packages/datadog-instrumentations/src/cucumber-worker-threads.js +19 -0
- package/packages/datadog-instrumentations/src/cucumber.js +312 -152
- 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/dd-trace/src/id.js +15 -0
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +91 -5
- package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +43 -21
- package/packages/dd-trace/src/opentelemetry/trace/otlp_transformer.js +22 -3
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +2 -10
- package/packages/dd-trace/src/opentracing/span_context.js +1 -3
- 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 +19 -9
- package/packages/dd-trace/src/profiling/profilers/wall.js +2 -3
package/package.json
CHANGED
|
@@ -233,13 +233,14 @@ function wrapSmithySend (send) {
|
|
|
233
233
|
}
|
|
234
234
|
|
|
235
235
|
function handleCompletion (result, ctx, channels) {
|
|
236
|
-
const
|
|
236
|
+
const streamable = result?.body ?? result?.stream
|
|
237
|
+
const iterator = streamable?.[Symbol.asyncIterator]
|
|
237
238
|
if (!iterator) {
|
|
238
239
|
channels.complete.publish(ctx)
|
|
239
240
|
return
|
|
240
241
|
}
|
|
241
242
|
|
|
242
|
-
shimmer.wrap(
|
|
243
|
+
shimmer.wrap(streamable, Symbol.asyncIterator, function (asyncIterator) {
|
|
243
244
|
return function (...args) {
|
|
244
245
|
const iterator = asyncIterator.apply(this, args)
|
|
245
246
|
shimmer.wrap(iterator, 'next', function (next) {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { createRequire } = require('node:module')
|
|
4
|
+
const path = require('node:path')
|
|
5
|
+
|
|
6
|
+
const { patchCucumberWorkerRunTestCase } = require('./cucumber')
|
|
7
|
+
|
|
8
|
+
const appRequire = createRequire(path.join(process.cwd(), 'package.json'))
|
|
9
|
+
|
|
10
|
+
try {
|
|
11
|
+
// Cucumber v13 parallel workers start from an ESM worker.mjs entrypoint, which
|
|
12
|
+
// statically imports the internal runtime Worker before it runs support-code
|
|
13
|
+
// requireModules. The regular module hook does not patch that internal worker
|
|
14
|
+
// import, so this preload is injected into requireModules to patch the cached Worker
|
|
15
|
+
// prototype before Cucumber constructs the worker instance.
|
|
16
|
+
patchCucumberWorkerRunTestCase(appRequire('@cucumber/cucumber/lib/runtime/worker'), true)
|
|
17
|
+
} catch {
|
|
18
|
+
// Ignore preload failures so cucumber can keep running if its internals change.
|
|
19
|
+
}
|
|
@@ -30,6 +30,8 @@ const { writeCoverageBackfillToCache } = require('../../dd-trace/src/ci-visibili
|
|
|
30
30
|
const satisfies = require('../../../vendor/dist/semifies')
|
|
31
31
|
const { addHook, channel } = require('./helpers/instrument')
|
|
32
32
|
|
|
33
|
+
const cucumberWorkerThreadsPatchModule = require.resolve('./cucumber-worker-threads')
|
|
34
|
+
|
|
33
35
|
const testStartCh = channel('ci:cucumber:test:start')
|
|
34
36
|
const testRetryCh = channel('ci:cucumber:test:retry')
|
|
35
37
|
const testFinishCh = channel('ci:cucumber:test:finish') // used for test steps too
|
|
@@ -69,6 +71,7 @@ const originalCoverageMap = createCoverageMap()
|
|
|
69
71
|
|
|
70
72
|
// TODO: remove in a later major version
|
|
71
73
|
const patched = new WeakSet()
|
|
74
|
+
const patchedCucumberWorkers = new WeakSet()
|
|
72
75
|
|
|
73
76
|
const lastStatusByPickleId = new Map()
|
|
74
77
|
/** For ATR: statuses keyed by stable scenario id (uri:name) so retries accumulate correctly */
|
|
@@ -180,22 +183,270 @@ function getConfiguredEfdRetryCount () {
|
|
|
180
183
|
}
|
|
181
184
|
|
|
182
185
|
function publishWorkerEfdRetryCount (pickle, retryCount) {
|
|
183
|
-
|
|
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
|
+
}
|
|
184
203
|
|
|
185
204
|
try {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
testFileAbsolutePath: pickle.uri,
|
|
191
|
-
testName: pickle.name,
|
|
192
|
-
},
|
|
193
|
-
})
|
|
205
|
+
const { isMainThread, parentPort } = require('node:worker_threads')
|
|
206
|
+
if (isMainThread || !parentPort) return
|
|
207
|
+
|
|
208
|
+
parentPort.postMessage(message)
|
|
194
209
|
} catch {
|
|
195
210
|
// ignore IPC errors
|
|
196
211
|
}
|
|
197
212
|
}
|
|
198
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
|
+
|
|
199
450
|
function finishParallelSuiteIfDone (testFileAbsolutePath) {
|
|
200
451
|
const finished = pickleResultByFile[testFileAbsolutePath]
|
|
201
452
|
const expectedPickles = pickleByFile[testFileAbsolutePath]
|
|
@@ -929,6 +1180,9 @@ function getWrappedRunTestCase (runTestCaseFunction, isNewerCucumberVersion = fa
|
|
|
929
1180
|
if (!testSuiteFinishCh.hasSubscribers) {
|
|
930
1181
|
return runTestCaseFunction.apply(this, arguments)
|
|
931
1182
|
}
|
|
1183
|
+
if (isWorker) {
|
|
1184
|
+
readParallelWorkerWorldParameters(this.options)
|
|
1185
|
+
}
|
|
932
1186
|
const pickle = isNewerCucumberVersion
|
|
933
1187
|
? arguments[0].pickle
|
|
934
1188
|
: this.eventDataCollector.getPickle(arguments[0])
|
|
@@ -1113,26 +1367,25 @@ function getWrappedRunTestCase (runTestCaseFunction, isNewerCucumberVersion = fa
|
|
|
1113
1367
|
}
|
|
1114
1368
|
}
|
|
1115
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
|
+
|
|
1116
1382
|
function getWrappedParseWorkerMessage (parseWorkerMessageFunction, isNewVersion) {
|
|
1117
1383
|
return function (worker, message) {
|
|
1118
1384
|
if (!testSuiteFinishCh.hasSubscribers) {
|
|
1119
1385
|
return parseWorkerMessageFunction.apply(this, arguments)
|
|
1120
1386
|
}
|
|
1121
|
-
// If
|
|
1122
|
-
|
|
1123
|
-
// TODO: identify the message better
|
|
1124
|
-
if (Array.isArray(message)) {
|
|
1125
|
-
const [messageCode, payload] = message
|
|
1126
|
-
if (messageCode === CUCUMBER_WORKER_TRACE_PAYLOAD_CODE) {
|
|
1127
|
-
collectAttemptToFixExecutionsFromTraces(payload, attemptToFixExecutions)
|
|
1128
|
-
workerReportTraceCh.publish(payload)
|
|
1129
|
-
return
|
|
1130
|
-
}
|
|
1131
|
-
}
|
|
1132
|
-
if (message[DD_EFD_RETRY_COUNT_MESSAGE]) {
|
|
1133
|
-
handleEfdRetryCountMessage(message[DD_EFD_RETRY_COUNT_MESSAGE])
|
|
1134
|
-
return
|
|
1135
|
-
}
|
|
1387
|
+
// If it's a dd-trace message, stop cucumber processing or cucumber will throw an error.
|
|
1388
|
+
if (handleDdWorkerMessage(message)) return
|
|
1136
1389
|
|
|
1137
1390
|
const envelope = isNewVersion ? message.envelope : message.jsonEnvelope
|
|
1138
1391
|
|
|
@@ -1149,10 +1402,7 @@ function getWrappedParseWorkerMessage (parseWorkerMessageFunction, isNewVersion)
|
|
|
1149
1402
|
return parseWorkerMessageFunction.apply(this, arguments)
|
|
1150
1403
|
}
|
|
1151
1404
|
}
|
|
1152
|
-
if (parsed
|
|
1153
|
-
handleEfdRetryCountMessage(parsed[DD_EFD_RETRY_COUNT_MESSAGE])
|
|
1154
|
-
return
|
|
1155
|
-
}
|
|
1405
|
+
if (handleDdWorkerMessage(parsed)) return
|
|
1156
1406
|
let pickle
|
|
1157
1407
|
|
|
1158
1408
|
if (parsed.testCaseStarted) {
|
|
@@ -1162,15 +1412,7 @@ function getWrappedParseWorkerMessage (parseWorkerMessageFunction, isNewVersion)
|
|
|
1162
1412
|
const { pickleId } = this.eventDataCollector.testCaseMap[parsed.testCaseStarted.testCaseId]
|
|
1163
1413
|
pickle = this.eventDataCollector.getPickle(pickleId)
|
|
1164
1414
|
}
|
|
1165
|
-
|
|
1166
|
-
const testFileAbsolutePath = pickle.uri
|
|
1167
|
-
// First test in suite
|
|
1168
|
-
if (!pickleResultByFile[testFileAbsolutePath]) {
|
|
1169
|
-
pickleResultByFile[testFileAbsolutePath] = []
|
|
1170
|
-
testSuiteStartCh.publish({
|
|
1171
|
-
testFileAbsolutePath,
|
|
1172
|
-
})
|
|
1173
|
-
}
|
|
1415
|
+
maybeStartParallelSuite(pickle)
|
|
1174
1416
|
}
|
|
1175
1417
|
|
|
1176
1418
|
const parseWorkerResponse = parseWorkerMessageFunction.apply(this, arguments)
|
|
@@ -1188,66 +1430,15 @@ function getWrappedParseWorkerMessage (parseWorkerMessageFunction, isNewVersion)
|
|
|
1188
1430
|
pickle = testCase.pickle
|
|
1189
1431
|
}
|
|
1190
1432
|
|
|
1191
|
-
|
|
1192
|
-
let isNew = false
|
|
1193
|
-
|
|
1194
|
-
if (isKnownTestsEnabled) {
|
|
1195
|
-
isNew = isNewTest(pickle.uri, pickle.name)
|
|
1196
|
-
}
|
|
1197
|
-
|
|
1198
|
-
const testFileAbsolutePath = pickle.uri
|
|
1199
|
-
const finished = pickleResultByFile[testFileAbsolutePath]
|
|
1200
|
-
|
|
1201
|
-
if (isEarlyFlakeDetectionEnabled && isNew) {
|
|
1202
|
-
const testFullname = `${pickle.uri}:${pickle.name}`
|
|
1203
|
-
let testStatuses = newTestsByTestFullname.get(testFullname)
|
|
1204
|
-
if (testStatuses) {
|
|
1205
|
-
testStatuses.push(status)
|
|
1206
|
-
} else {
|
|
1207
|
-
testStatuses = [status]
|
|
1208
|
-
newTestsByTestFullname.set(testFullname, testStatuses)
|
|
1209
|
-
}
|
|
1210
|
-
let efdRetryCount = efdRetryCountByPickleId.get(pickle.id)
|
|
1211
|
-
if (efdRetryCount === undefined) {
|
|
1212
|
-
efdRetryCount = status === 'skip'
|
|
1213
|
-
? 0
|
|
1214
|
-
: getConfiguredEfdRetryCount()
|
|
1215
|
-
efdRetryCountByPickleId.set(pickle.id, efdRetryCount)
|
|
1216
|
-
if (efdRetryCount === 0 && status !== 'skip') {
|
|
1217
|
-
efdSlowAbortedPickleIds.add(pickle.id)
|
|
1218
|
-
}
|
|
1219
|
-
}
|
|
1220
|
-
maybeRecordFinalParallelEfdStatus({ pickleId: pickle.id, testFileAbsolutePath, testFullname })
|
|
1221
|
-
} else if (
|
|
1222
|
-
isTestManagementTestsEnabled &&
|
|
1223
|
-
getTestProperties(getTestSuitePath(testFileAbsolutePath, process.cwd()), pickle.name).attemptToFix
|
|
1224
|
-
) {
|
|
1225
|
-
const testFullname = `${pickle.uri}:${pickle.name}`
|
|
1226
|
-
let testStatuses = attemptToFixTestsByTestFullname.get(testFullname)
|
|
1227
|
-
if (testStatuses) {
|
|
1228
|
-
testStatuses.push(status)
|
|
1229
|
-
} else {
|
|
1230
|
-
testStatuses = [status]
|
|
1231
|
-
attemptToFixTestsByTestFullname.set(testFullname, testStatuses)
|
|
1232
|
-
}
|
|
1233
|
-
|
|
1234
|
-
if (status === 'skip' || testStatuses.length === testManagementAttemptToFixRetries + 1) {
|
|
1235
|
-
finished.push(getTestStatusFromAttemptToFixExecutions(testStatuses))
|
|
1236
|
-
attemptToFixTestsByTestFullname.delete(testFullname)
|
|
1237
|
-
}
|
|
1238
|
-
} else {
|
|
1239
|
-
// TODO: can we get error message?
|
|
1240
|
-
const finished = pickleResultByFile[testFileAbsolutePath]
|
|
1241
|
-
finished.push(status)
|
|
1242
|
-
}
|
|
1243
|
-
|
|
1244
|
-
finishParallelSuiteIfDone(testFileAbsolutePath)
|
|
1433
|
+
handleParallelTestCaseFinished(pickle, worstTestStepResult)
|
|
1245
1434
|
}
|
|
1246
1435
|
|
|
1247
1436
|
return parseWorkerResponse
|
|
1248
1437
|
}
|
|
1249
1438
|
}
|
|
1250
1439
|
|
|
1440
|
+
module.exports.patchCucumberWorkerRunTestCase = patchCucumberWorkerRunTestCase
|
|
1441
|
+
|
|
1251
1442
|
// Test start / finish for older versions. The only hook executed in workers when in parallel mode
|
|
1252
1443
|
addHook({
|
|
1253
1444
|
name: '@cucumber/cucumber',
|
|
@@ -1319,11 +1510,7 @@ addHook({
|
|
|
1319
1510
|
versions: ['>=11.0.0'],
|
|
1320
1511
|
file: 'lib/runtime/worker.js',
|
|
1321
1512
|
}, (workerPackage) => {
|
|
1322
|
-
|
|
1323
|
-
workerPackage.Worker.prototype,
|
|
1324
|
-
'runTestCase',
|
|
1325
|
-
runTestCase => getWrappedRunTestCase(runTestCase, true, !!getEnvironmentVariable('CUCUMBER_WORKER_ID'))
|
|
1326
|
-
)
|
|
1513
|
+
patchCucumberWorkerRunTestCase(workerPackage, !!getEnvironmentVariable('CUCUMBER_WORKER_ID'))
|
|
1327
1514
|
return workerPackage
|
|
1328
1515
|
})
|
|
1329
1516
|
|
|
@@ -1359,7 +1546,7 @@ addHook({
|
|
|
1359
1546
|
// In `startWorker` we pass early flake detection info to the worker.
|
|
1360
1547
|
addHook({
|
|
1361
1548
|
name: '@cucumber/cucumber',
|
|
1362
|
-
versions: ['>=11.0.0'],
|
|
1549
|
+
versions: ['>=11.0.0 <13.0.0'],
|
|
1363
1550
|
file: 'lib/runtime/parallel/adapter.js',
|
|
1364
1551
|
}, (adapterPackage) => {
|
|
1365
1552
|
shimmer.wrap(
|
|
@@ -1369,46 +1556,43 @@ addHook({
|
|
|
1369
1556
|
)
|
|
1370
1557
|
// EFD in parallel mode only supported in >=11.0.0
|
|
1371
1558
|
shimmer.wrap(adapterPackage.ChildProcessAdapter.prototype, 'startWorker', startWorker => function (...args) {
|
|
1372
|
-
|
|
1373
|
-
this.options.worldParameters._ddIsKnownTestsEnabled = true
|
|
1374
|
-
this.options.worldParameters._ddIsEarlyFlakeDetectionEnabled = isEarlyFlakeDetectionEnabled
|
|
1375
|
-
this.options.worldParameters._ddKnownTests = knownTests
|
|
1376
|
-
this.options.worldParameters._ddEarlyFlakeDetectionNumRetries = earlyFlakeDetectionNumRetries
|
|
1377
|
-
this.options.worldParameters._ddEarlyFlakeDetectionSlowTestRetries = earlyFlakeDetectionSlowTestRetries
|
|
1378
|
-
} else {
|
|
1379
|
-
isEarlyFlakeDetectionEnabled = false
|
|
1380
|
-
isKnownTestsEnabled = false
|
|
1381
|
-
this.options.worldParameters._ddIsEarlyFlakeDetectionEnabled = false
|
|
1382
|
-
this.options.worldParameters._ddIsKnownTestsEnabled = false
|
|
1383
|
-
this.options.worldParameters._ddEarlyFlakeDetectionNumRetries = 0
|
|
1384
|
-
this.options.worldParameters._ddEarlyFlakeDetectionSlowTestRetries = {}
|
|
1385
|
-
}
|
|
1386
|
-
|
|
1387
|
-
if (isImpactedTestsEnabled) {
|
|
1388
|
-
this.options.worldParameters._ddImpactedTestsEnabled = isImpactedTestsEnabled
|
|
1389
|
-
this.options.worldParameters._ddModifiedFiles = modifiedFiles
|
|
1390
|
-
}
|
|
1391
|
-
|
|
1392
|
-
this.options.worldParameters._ddIsFlakyTestRetriesEnabled = isFlakyTestRetriesEnabled
|
|
1393
|
-
this.options.worldParameters._ddNumTestRetries = numTestRetries
|
|
1394
|
-
|
|
1395
|
-
if (isTestManagementTestsEnabled) {
|
|
1396
|
-
this.options.worldParameters._ddIsTestManagementTestsEnabled = true
|
|
1397
|
-
this.options.worldParameters._ddTestManagementTests = testManagementTests
|
|
1398
|
-
this.options.worldParameters._ddTestManagementAttemptToFixRetries = testManagementAttemptToFixRetries
|
|
1399
|
-
}
|
|
1400
|
-
|
|
1559
|
+
configureParallelWorkerWorldParameters(this.options)
|
|
1401
1560
|
return startWorker.apply(this, args)
|
|
1402
1561
|
})
|
|
1403
1562
|
return adapterPackage
|
|
1404
1563
|
})
|
|
1405
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
|
+
|
|
1406
1590
|
// Hook executed in the worker process when in parallel mode.
|
|
1407
1591
|
// In this hook we read the information passed in `worldParameters` and make it available for
|
|
1408
1592
|
// `getWrappedRunTestCase`.
|
|
1409
1593
|
addHook({
|
|
1410
1594
|
name: '@cucumber/cucumber',
|
|
1411
|
-
versions: ['>=11.0.0'],
|
|
1595
|
+
versions: ['>=11.0.0 <13.0.0'],
|
|
1412
1596
|
file: 'lib/runtime/parallel/worker.js',
|
|
1413
1597
|
}, (workerPackage) => {
|
|
1414
1598
|
shimmer.wrap(
|
|
@@ -1416,31 +1600,7 @@ addHook({
|
|
|
1416
1600
|
'initialize',
|
|
1417
1601
|
initialize => async function () {
|
|
1418
1602
|
await initialize.apply(this, arguments)
|
|
1419
|
-
|
|
1420
|
-
if (isKnownTestsEnabled) {
|
|
1421
|
-
knownTests = this.options.worldParameters._ddKnownTests
|
|
1422
|
-
// if for whatever reason the worker does not receive valid known tests, we disable EFD and known tests
|
|
1423
|
-
if (!isValidKnownTests(knownTests)) {
|
|
1424
|
-
isKnownTestsEnabled = false
|
|
1425
|
-
knownTests = {}
|
|
1426
|
-
}
|
|
1427
|
-
}
|
|
1428
|
-
isEarlyFlakeDetectionEnabled = !!this.options.worldParameters._ddIsEarlyFlakeDetectionEnabled
|
|
1429
|
-
if (isEarlyFlakeDetectionEnabled) {
|
|
1430
|
-
earlyFlakeDetectionNumRetries = this.options.worldParameters._ddEarlyFlakeDetectionNumRetries
|
|
1431
|
-
earlyFlakeDetectionSlowTestRetries = this.options.worldParameters._ddEarlyFlakeDetectionSlowTestRetries ?? {}
|
|
1432
|
-
}
|
|
1433
|
-
isImpactedTestsEnabled = !!this.options.worldParameters._ddImpactedTestsEnabled
|
|
1434
|
-
if (isImpactedTestsEnabled) {
|
|
1435
|
-
modifiedFiles = this.options.worldParameters._ddModifiedFiles
|
|
1436
|
-
}
|
|
1437
|
-
isFlakyTestRetriesEnabled = !!this.options.worldParameters._ddIsFlakyTestRetriesEnabled
|
|
1438
|
-
numTestRetries = this.options.worldParameters._ddNumTestRetries ?? 0
|
|
1439
|
-
isTestManagementTestsEnabled = !!this.options.worldParameters._ddIsTestManagementTestsEnabled
|
|
1440
|
-
if (isTestManagementTestsEnabled) {
|
|
1441
|
-
testManagementTests = this.options.worldParameters._ddTestManagementTests
|
|
1442
|
-
testManagementAttemptToFixRetries = this.options.worldParameters._ddTestManagementAttemptToFixRetries
|
|
1443
|
-
}
|
|
1603
|
+
readParallelWorkerWorldParameters(this.options)
|
|
1444
1604
|
}
|
|
1445
1605
|
)
|
|
1446
1606
|
return workerPackage
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const BaseAwsSdkPlugin = require('../../base')
|
|
4
4
|
const { parseModelId } = require('./utils')
|
|
5
5
|
|
|
6
|
-
const enabledOperations = new Set(['invokeModel', 'invokeModelWithResponseStream'])
|
|
6
|
+
const enabledOperations = new Set(['invokeModel', 'invokeModelWithResponseStream', 'converse', 'converseStream'])
|
|
7
7
|
|
|
8
8
|
class BedrockRuntime extends BaseAwsSdkPlugin {
|
|
9
9
|
static id = 'bedrockruntime'
|