Skip to content

Commit 32ed3df

Browse files
chore: update additional tests to use new stacktrace comparison
1 parent c6a8429 commit 32ed3df

File tree

5 files changed

+59
-49
lines changed

5 files changed

+59
-49
lines changed

packages/test/src/helpers.ts

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as net from 'net';
33
import path from 'path';
44
import * as grpc from '@grpc/grpc-js';
55
import asyncRetry from 'async-retry';
6-
import ava, { TestFn } from 'ava';
6+
import ava, { TestFn, ExecutionContext } from 'ava';
77
import StackUtils from 'stack-utils';
88
import { v4 as uuid4 } from 'uuid';
99
import { Client, Connection } from '@temporalio/client';
@@ -54,7 +54,7 @@ export async function waitUntil(
5454
intervalMs: number = 100
5555
): Promise<void> {
5656
const endTime = Date.now() + timeoutMs;
57-
for (;;) {
57+
for (; ;) {
5858
if (await condition()) {
5959
return;
6060
} else if (Date.now() >= endTime) {
@@ -98,6 +98,21 @@ export function cleanStackTrace(ostack: string): string {
9898
return normalizedStack ? `${firstLine}\n${normalizedStack}` : firstLine;
9999
}
100100

101+
/**
102+
* Compare stack traces using $CLASS keyword to match any inconsistent identifiers
103+
*
104+
* As of Node 24.6.0 type names are now present on source mapped stack traces which leads
105+
* to different stack traces depending on Node version.
106+
* See [f33e0fcc83954f728fcfd2ef6ae59435bc4af059](https://github.com/nodejs/node/commit/f33e0fcc83954f728fcfd2ef6ae59435bc4af059)
107+
*/
108+
export function compareFailureStackTrace<T>(t: ExecutionContext<T>, actual: string, expected: string) {
109+
const escapedTrace = expected
110+
.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&')
111+
.replace(/-/g, '\\x2d')
112+
.replaceAll('\\$CLASS', '(?:[A-Za-z]+)');
113+
t.regex(actual, RegExp(`^${escapedTrace}$`));
114+
}
115+
101116
function noopTest(): void {
102117
// eslint: this function body is empty and it's okay.
103118
}
@@ -168,11 +183,11 @@ export class ByteSkewerPayloadCodec implements PayloadCodec {
168183
if (inWorkflowContext()) {
169184
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
170185
// @ts-ignore
171-
worker.Worker = class {}; // eslint-disable-line import/namespace
186+
worker.Worker = class { }; // eslint-disable-line import/namespace
172187

173188
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
174189
// @ts-ignore
175-
RealTestWorkflowEnvironment = class {}; // eslint-disable-line import/namespace
190+
RealTestWorkflowEnvironment = class { }; // eslint-disable-line import/namespace
176191
}
177192

178193
export class Worker extends worker.Worker {
@@ -190,15 +205,15 @@ export class TestWorkflowEnvironment extends RealTestWorkflowEnvironment {
190205
...opts,
191206
...(TESTS_CLI_VERSION
192207
? {
193-
server: {
194-
...opts?.server,
195-
executable: {
196-
...opts?.server?.executable,
197-
type: 'cached-download',
198-
version: TESTS_CLI_VERSION,
199-
},
208+
server: {
209+
...opts?.server,
210+
executable: {
211+
...opts?.server?.executable,
212+
type: 'cached-download',
213+
version: TESTS_CLI_VERSION,
200214
},
201-
}
215+
},
216+
}
202217
: undefined),
203218
});
204219
}
@@ -208,15 +223,15 @@ export class TestWorkflowEnvironment extends RealTestWorkflowEnvironment {
208223
...opts,
209224
...(TESTS_TIME_SKIPPING_SERVER_VERSION
210225
? {
211-
server: {
212-
...opts?.server,
213-
executable: {
214-
...opts?.server?.executable,
215-
type: 'cached-download',
216-
version: TESTS_TIME_SKIPPING_SERVER_VERSION,
217-
},
226+
server: {
227+
...opts?.server,
228+
executable: {
229+
...opts?.server?.executable,
230+
type: 'cached-download',
231+
version: TESTS_TIME_SKIPPING_SERVER_VERSION,
218232
},
219-
}
233+
},
234+
}
220235
: undefined),
221236
});
222237
}

packages/test/src/test-integration-split-one.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import {
3636
} from '@temporalio/workflow';
3737
import { configurableHelpers, createTestWorkflowBundle } from './helpers-integration';
3838
import * as activities from './activities';
39-
import { cleanOptionalStackTrace, u8, Worker } from './helpers';
39+
import { cleanOptionalStackTrace, compareFailureStackTrace, u8, Worker } from './helpers';
4040
import { configMacro, makeTestFn } from './helpers-integration-multi-codec';
4141
import * as workflows from './workflows';
4242

@@ -204,11 +204,12 @@ test.serial('activity-failure with ApplicationFailure', configMacro, async (t, c
204204
t.is(err.cause.cause.message, 'Fail me');
205205
t.is(err.cause.cause.type, 'Error');
206206
t.deepEqual(err.cause.cause.details, ['details', 123, false]);
207-
t.is(
208-
cleanOptionalStackTrace(err.cause.cause.stack),
207+
compareFailureStackTrace(
208+
t,
209+
cleanOptionalStackTrace(err.cause.cause.stack)!,
209210
dedent`
210211
ApplicationFailure: Fail me
211-
at Function.nonRetryable (common/src/failure.ts)
212+
at $CLASS.nonRetryable (common/src/failure.ts)
212213
at throwAnError (test/src/activities/index.ts)
213214
`
214215
);
@@ -258,11 +259,12 @@ test.serial('child-workflow-failure', configMacro, async (t, config) => {
258259
return t.fail('Expected err.cause.cause to be an instance of ApplicationFailure');
259260
}
260261
t.is(err.cause.cause.message, 'failure');
261-
t.is(
262-
cleanOptionalStackTrace(err.cause.cause.stack),
262+
compareFailureStackTrace(
263+
t,
264+
cleanOptionalStackTrace(err.cause.cause.stack)!,
263265
dedent`
264266
ApplicationFailure: failure
265-
at Function.nonRetryable (common/src/failure.ts)
267+
at $CLASS.nonRetryable (common/src/failure.ts)
266268
at throwAsync (test/src/workflows/throw-async.ts)
267269
`
268270
);
@@ -694,8 +696,8 @@ test.serial('Workflow can upsert Search Attributes', configMacro, async (t, conf
694696
}
695697
t.true(
696698
typeof checksum === 'string' &&
697-
checksum.includes(`@temporalio/worker@${pkg.version}+`) &&
698-
/\+[a-f0-9]{64}$/.test(checksum) // bundle checksum
699+
checksum.includes(`@temporalio/worker@${pkg.version}+`) &&
700+
/\+[a-f0-9]{64}$/.test(checksum) // bundle checksum
699701
);
700702
});
701703

packages/test/src/test-interceptors.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { WorkflowClient, WorkflowFailedError } from '@temporalio/client';
1212
import { ApplicationFailure, TerminatedFailure } from '@temporalio/common';
1313
import { DefaultLogger, Runtime } from '@temporalio/worker';
1414
import { defaultPayloadConverter, WorkflowInfo } from '@temporalio/workflow';
15-
import { cleanOptionalStackTrace, RUN_INTEGRATION_TESTS, Worker } from './helpers';
15+
import { cleanOptionalStackTrace, compareFailureStackTrace, RUN_INTEGRATION_TESTS, Worker } from './helpers';
1616
import { defaultOptions } from './mock-native-worker';
1717
import {
1818
continueAsNewToDifferentWorkflow,
@@ -241,11 +241,12 @@ if (RUN_INTEGRATION_TESTS) {
241241
return;
242242
}
243243
t.deepEqual(err.cause.message, 'Expected anything other than 1');
244-
t.is(
245-
cleanOptionalStackTrace(err.cause.stack),
244+
compareFailureStackTrace(
245+
t,
246+
cleanOptionalStackTrace(err.cause.stack)!,
246247
dedent`
247248
ApplicationFailure: Expected anything other than 1
248-
at Function.nonRetryable (common/src/failure.ts)
249+
at $CLASS.nonRetryable (common/src/failure.ts)
249250
at Object.continueAsNew (test/src/workflows/interceptor-example.ts)
250251
at workflow/src/workflow.ts
251252
at continueAsNewToDifferentWorkflow (test/src/workflows/continue-as-new-to-different-workflow.ts)

packages/test/src/test-nexus-handler.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {
1919
convertWorkflowEventLinkToNexusLink,
2020
convertNexusLinkToWorkflowEventLink,
2121
} from '@temporalio/nexus/lib/link-converter';
22-
import { cleanStackTrace, getRandomPort } from './helpers';
22+
import { cleanStackTrace, compareFailureStackTrace, getRandomPort } from './helpers';
2323

2424
export interface Context {
2525
httpPort: number;
@@ -314,10 +314,11 @@ test('start Operation Handler errors', async (t) => {
314314
});
315315
t.true(err instanceof ApplicationFailure);
316316
t.is(err.message, '');
317-
t.is(
317+
compareFailureStackTrace(
318+
t,
318319
cleanStackTrace(err.stack!),
319320
`ApplicationFailure: deliberate failure
320-
at Function.create (common/src/failure.ts)
321+
at $CLASS.create (common/src/failure.ts)
321322
at op (test/src/test-nexus-handler.ts)
322323
at Object.start (nexus-rpc/src/handler/operation-handler.ts)
323324
at ServiceRegistry.start (nexus-rpc/src/handler/service-registry.ts)`
@@ -460,10 +461,11 @@ test('cancel Operation Handler errors', async (t) => {
460461
});
461462
t.true(err instanceof ApplicationFailure);
462463
t.is(err.message, '');
463-
t.is(
464+
compareFailureStackTrace(
465+
t,
464466
cleanStackTrace(err.stack!),
465467
`ApplicationFailure: deliberate failure
466-
at Function.create (common/src/failure.ts)
468+
at $CLASS.create (common/src/failure.ts)
467469
at Object.cancel (test/src/test-nexus-handler.ts)
468470
at ServiceRegistry.cancel (nexus-rpc/src/handler/service-registry.ts)`
469471
);

packages/test/src/test-workflows.ts

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import { SdkFlag, SdkFlags } from '@temporalio/workflow/lib/flags';
2222
import { ReusableVMWorkflow, ReusableVMWorkflowCreator } from '@temporalio/worker/lib/workflow/reusable-vm';
2323
import { parseWorkflowCode } from '@temporalio/worker/lib/worker';
2424
import * as activityFunctions from './activities';
25-
import { cleanStackTrace, REUSE_V8_CONTEXT, u8 } from './helpers';
25+
import { cleanStackTrace, compareFailureStackTrace, REUSE_V8_CONTEXT, u8 } from './helpers';
2626
import { ProcessedSignal } from './workflows';
2727

2828
export interface Context {
@@ -172,16 +172,6 @@ function compareCompletion(
172172
);
173173
}
174174

175-
// Compare stack traces while handling $CLASS keyword to match any identifier that isn't consistent across Node versions.
176-
// As of Node 24.6.0 type names are now present on source mapped stack traces
177-
// See [f33e0fcc83954f728fcfd2ef6ae59435bc4af059](https://github.com/nodejs/node/commit/f33e0fcc83954f728fcfd2ef6ae59435bc4af059)
178-
function compareFailureStackTrace(t: ExecutionContext<Context>, actual: string, expected: string) {
179-
const escapedTrace = expected
180-
.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&')
181-
.replace(/-/g, '\\x2d')
182-
.replaceAll('\\$CLASS', '(?:[A-Za-z]+)');
183-
t.regex(actual, RegExp(`^${escapedTrace}$`));
184-
}
185175

186176
function makeSuccess(
187177
commands: coresdk.workflow_commands.IWorkflowCommand[] = [makeCompleteWorkflowExecution()],

0 commit comments

Comments
 (0)