Skip to content

Commit 0ea43c6

Browse files
chore(NODE-4348): enhance skip reason filtering in unified runner (#3303)
Co-authored-by: Neal Beeken <[email protected]>
1 parent fb2b4a5 commit 0ea43c6

File tree

6 files changed

+108
-80
lines changed

6 files changed

+108
-80
lines changed

test/integration/collection-management/collection_management.spec.test.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,7 @@ const { runUnifiedSuite } = require('../../tools/unified-spec-runner/runner');
77
const SKIPPED_TESTS = ['modifyCollection to changeStreamPreAndPostImages enabled'];
88

99
describe('Collection management unified spec tests', function () {
10-
runUnifiedSuite(loadSpecTests('collection-management'), SKIPPED_TESTS);
10+
runUnifiedSuite(loadSpecTests('collection-management'), ({ description }) =>
11+
SKIPPED_TESTS.includes(description) ? `the Node driver does not have a collMod helper.` : false
12+
);
1113
});

test/integration/command-monitoring/command_monitoring.spec.test.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,7 @@ import { runUnifiedSuite } from '../../tools/unified-spec-runner/runner';
1212
const SKIP = ['A successful unordered bulk write with an unacknowledged write concern'];
1313

1414
describe('Command Monitoring Spec (unified)', () => {
15-
runUnifiedSuite(loadSpecTests(path.join('command-monitoring', 'unified')), SKIP);
15+
runUnifiedSuite(loadSpecTests(path.join('command-monitoring', 'unified')), ({ description }) =>
16+
SKIP.includes(description) ? `TODO(NODE-4261): support skip reasons in unified tests` : false
17+
);
1618
});

test/integration/load-balancers/load_balancers.spec.test.js

Lines changed: 40 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -3,63 +3,50 @@ const path = require('path');
33
const { loadSpecTests } = require('../../spec/index');
44
const { runUnifiedSuite } = require('../../tools/unified-spec-runner/runner');
55

6-
const SKIP = [
7-
// Verified they use the same connection but the Node implementation executes
8-
// a getMore before the killCursors even though the stream is immediately
9-
// closed.
10-
// TODO(NODE-3970): implement and reference a node specific integration test for this
11-
'change streams pin to a connection',
6+
const filter = ({ description }) => {
7+
if (description === 'change streams pin to a connection') {
8+
// Verified they use the same connection but the Node implementation executes
9+
// a getMore before the killCursors even though the stream is immediately
10+
// closed.
11+
// TODO(NODE-3970): implement and reference a node specific integration test for this
12+
return 'TODO(NODE-3970): implement and reference a node specific integration test for this';
13+
}
1214

13-
// TODO(DRIVERS-1847): The following three tests are skipped pending a decision made on DRIVERS-1847,
14-
// since pinning the connection on any getMore error is very awkward in node and likely results
15-
// in sub-optimal pinning.
16-
'pinned connections are not returned after an network error during getMore',
17-
'pinned connections are not returned to the pool after a non-network error on getMore',
18-
'stale errors are ignored',
15+
if (
16+
[
17+
'pinned connections are not returned after an network error during getMore',
18+
'pinned connections are not returned to the pool after a non-network error on getMore',
19+
'stale errors are ignored'
20+
].includes(description)
21+
) {
22+
// TODO(DRIVERS-1847): The above three tests are skipped pending a decision made in DRIVERS-1847
23+
// since pinning the connection on any getMore error is very awkward in node and likely results
24+
// in sub-optimal pinning.
25+
return 'TODO(DRIVERS-1847): Skipped pending a decision made on DRIVERS-1847';
26+
}
1927

20-
// This test is skipped because it assumes drivers attempt connections on the first operation,
21-
// but Node has a connect() method that is called before the first operation is ever run.
22-
// TODO(NODE-2149): Refactor connect()
23-
'errors during the initial connection hello are ignored',
28+
if (description === 'errors during the initial connection hello are ignored') {
29+
// This test is skipped because it assumes drivers attempt connections on the first operation,
30+
// but Node has a connect() method that is called before the first operation is ever run.
31+
return 'TODO(NODE-2149): Refactor connect()';
32+
}
2433

25-
...(process.env.SERVERLESS
26-
? [
27-
// TODO(NODE-2471): Unskip these when there isn't a ping command sent when credentials are defined
28-
'no connection is pinned if all documents are returned in the initial batch',
29-
'pinned connections are returned when the cursor is drained',
30-
'pinned connections are returned to the pool when the cursor is closed',
31-
'pinned connections are returned after a network error during a killCursors request',
32-
'aggregate pins the cursor to a connection',
33-
'errors during the initial connection hello are ignored',
34-
'all operations go to the same mongos',
35-
'transaction can be committed multiple times',
36-
'pinned connection is not released after a non-transient CRUD error',
37-
'pinned connection is not released after a non-transient commit error',
38-
'pinned connection is released after a non-transient abort error',
39-
'pinned connection is released after a transient network commit error',
40-
'pinned connection is released after a transient non-network abort error',
41-
'pinned connection is released after a transient network abort error',
42-
'pinned connection is released on successful abort',
43-
'pinned connection is returned when a new transaction is started',
44-
'pinned connection is returned when a non-transaction operation uses the session',
45-
'a connection can be shared by a transaction and a cursor',
46-
'wait queue timeout errors include cursor statistics',
47-
'wait queue timeout errors include transaction statistics'
48-
]
49-
: []),
34+
if (
35+
process.env.AUTH === 'auth' &&
36+
[
37+
'errors during authentication are processed',
38+
'wait queue timeout errors include cursor statistics',
39+
'wait queue timeout errors include transaction statistics',
40+
'operations against non-load balanced clusters fail if URI contains loadBalanced=true',
41+
'operations against non-load balanced clusters succeed if URI contains loadBalanced=false'
42+
].includes(description)
43+
) {
44+
return 'TODO(NODE-3891): fix tests broken when AUTH enabled';
45+
}
5046

51-
// TODO: NODE-3891 - fix tests broken when AUTH enabled
52-
...(process.env.AUTH === 'auth'
53-
? [
54-
'errors during authentication are processed',
55-
'wait queue timeout errors include cursor statistics',
56-
'wait queue timeout errors include transaction statistics',
57-
'operations against non-load balanced clusters fail if URI contains loadBalanced=true',
58-
'operations against non-load balanced clusters succeed if URI contains loadBalanced=false'
59-
]
60-
: [])
61-
];
47+
return false;
48+
};
6249

6350
describe('Load Balancer Unified Tests', function () {
64-
runUnifiedSuite(loadSpecTests(path.join('load-balancers')), SKIP);
51+
runUnifiedSuite(loadSpecTests(path.join('load-balancers')), filter);
6552
});
Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,46 @@
11
import { loadSpecTests } from '../../spec/index';
22
import { runUnifiedSuite } from '../../tools/unified-spec-runner/runner';
3+
import { TestFilter } from '../../tools/unified-spec-runner/schema';
34

4-
// TODO: NODE-3891 - fix tests broken when AUTH enabled
5-
const FAILING_TESTS_AUTH_ENABLED = [
6-
'FindOneAndUpdate is committed on first attempt',
7-
'FindOneAndUpdate is not committed on first attempt',
8-
'FindOneAndUpdate is never committed',
9-
'eventType defaults to command if unset',
10-
'events are captured during an operation',
11-
'eventType can be set to command and cmap'
12-
];
5+
const filter: TestFilter = ({ description }) => {
6+
if (description === 'unpin after transient error within a transaction and commit') {
7+
// OLD COMMENT: commitTransaction retry seems to be swallowed by mongos in this case
8+
// TODO(NODE-3943):
9+
return `TODO(NODE-3943): commitTransaction retry seems to be swallowed by mongos in this case`;
10+
}
1311

14-
const SKIPPED_TESTS = [
15-
// TODO(NODE-3943):
16-
// OLD COMMENT: commitTransaction retry seems to be swallowed by mongos in this case
17-
'unpin after transient error within a transaction and commit',
12+
if (description === 'Client side error in command starting transaction') {
13+
// TODO(NODE-2034): Will be implemented as part of NODE-2034
14+
return 'TODO(NODE-2034): Specify effect of client-side errors on in-progress transactions';
15+
}
1816

19-
// TODO(NODE-2034): Will be implemented as part of NODE-2034
20-
'Client side error in command starting transaction',
17+
if (description === 'Dirty explicit session is discarded') {
18+
// TODO(NODE-3951): investigate why this is failing while the legacy version is passing
19+
return 'TODO(NODE-3951): investigate why this is failing while the legacy version is passing';
20+
}
2121

22-
// TODO(NODE-3308):
23-
'A successful find event with a getmore and the server kills the cursor',
22+
if (description === 'A successful find event with a getmore and the server kills the cursor') {
23+
return 'TODO(NODE-3308): failures due unnecessary getMore and killCursors calls in 5.0';
24+
}
2425

25-
// TODO(NODE-4125): Fix change streams resume logic when used in iterator mode
26-
'Test consecutive resume'
27-
].concat(process.env.AUTH === 'auth' ? FAILING_TESTS_AUTH_ENABLED : []);
26+
if (
27+
process.env.AUTH === 'auth' &&
28+
[
29+
'FindOneAndUpdate is committed on first attempt',
30+
'FindOneAndUpdate is not committed on first attempt',
31+
'FindOneAndUpdate is never committed',
32+
'eventType defaults to command if unset',
33+
'events are captured during an operation',
34+
'eventType can be set to command and cmap'
35+
].includes(description)
36+
) {
37+
return 'TODO(NODE-3891): fix tests broken when AUTH enabled';
38+
}
39+
40+
return false;
41+
};
2842

2943
describe('Unified test format runner', function unifiedTestRunner() {
3044
// Valid tests that should pass
31-
runUnifiedSuite(loadSpecTests('unified-test-format/valid-pass'), SKIPPED_TESTS);
45+
runUnifiedSuite(loadSpecTests('unified-test-format/valid-pass'), filter);
3246
});

test/tools/unified-spec-runner/runner.ts

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,15 @@ async function terminateOpenTransactions(client: MongoClient) {
3636
}
3737
}
3838

39+
/*
40+
* @param skipFilter - a function that returns null if the test should be run,
41+
* or a skip reason if the test should be skipped
42+
*/
3943
export async function runUnifiedTest(
4044
ctx: Mocha.Context,
4145
unifiedSuite: uni.UnifiedSuite,
4246
test: uni.Test,
43-
testsToSkip?: string[]
47+
skipFilter: uni.TestFilter = () => false
4448
): Promise<void> {
4549
// Some basic expectations we can catch early
4650
expect(test).to.exist;
@@ -58,7 +62,13 @@ export async function runUnifiedTest(
5862
ctx.skip();
5963
}
6064

61-
if (testsToSkip?.includes(test.description)) {
65+
const skipReason = skipFilter(test);
66+
67+
if (typeof skipReason === 'string') {
68+
if (skipReason.length === 0) {
69+
expect.fail(`Test was skipped with an empty skip reason: ${test.description}`);
70+
}
71+
ctx.skipReason = skipReason;
6272
ctx.skip();
6373
}
6474

@@ -236,12 +246,20 @@ export async function runUnifiedTest(
236246
}
237247
}
238248

239-
export function runUnifiedSuite(specTests: uni.UnifiedSuite[], testsToSkip?: string[]): void {
249+
/**
250+
*
251+
* @param skipFilter - a function that returns null if the test should be run,
252+
* or a skip reason if the test should be skipped
253+
*/
254+
export function runUnifiedSuite(
255+
specTests: uni.UnifiedSuite[],
256+
skipFilter: uni.TestFilter = () => false
257+
): void {
240258
for (const unifiedSuite of specTests) {
241259
context(String(unifiedSuite.description), function () {
242260
for (const test of unifiedSuite.tests) {
243261
it(String(test.description), async function () {
244-
await runUnifiedTest(this, unifiedSuite, test, testsToSkip);
262+
await runUnifiedTest(this, unifiedSuite, test, skipFilter);
245263
});
246264
}
247265
});

test/tools/unified-spec-runner/schema.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,3 +236,8 @@ export interface ExpectedError {
236236
errorLabelsOmit?: string[];
237237
expectResult?: unknown;
238238
}
239+
240+
/**
241+
* A type that represents the test filter provided to the unifed runner.
242+
*/
243+
export type TestFilter = (test: Test) => string | false;

0 commit comments

Comments
 (0)