diff --git a/.evergreen/config.yml b/.evergreen/config.yml index 604c871e247..218f6bebd8c 100644 --- a/.evergreen/config.yml +++ b/.evergreen/config.yml @@ -2199,7 +2199,7 @@ tasks: - func: bootstrap kms servers - func: run custom csfle tests vars: - CSFLE_GIT_REF: 5745f374109346a2597405f2251a178d463a14e1 + CSFLE_GIT_REF: ddb19ae22dc4a5f8b9208096f69fc23e19bae6c9 - name: run-custom-csfle-tests-5.0-master tags: - run-custom-dependency-tests @@ -2229,7 +2229,7 @@ tasks: - func: bootstrap kms servers - func: run custom csfle tests vars: - CSFLE_GIT_REF: 5745f374109346a2597405f2251a178d463a14e1 + CSFLE_GIT_REF: ddb19ae22dc4a5f8b9208096f69fc23e19bae6c9 - name: run-custom-csfle-tests-rapid-master tags: - run-custom-dependency-tests @@ -2259,7 +2259,7 @@ tasks: - func: bootstrap kms servers - func: run custom csfle tests vars: - CSFLE_GIT_REF: 5745f374109346a2597405f2251a178d463a14e1 + CSFLE_GIT_REF: ddb19ae22dc4a5f8b9208096f69fc23e19bae6c9 - name: run-custom-csfle-tests-latest-master tags: - run-custom-dependency-tests @@ -2863,10 +2863,13 @@ buildvariants: - test-3.6-sharded_cluster - test-latest-server-v1-api - test-atlas-connectivity + - test-atlas-data-lake - test-5.0-load-balanced - test-6.0-load-balanced - test-latest-load-balanced - test-auth-ldap + - test-socks5 + - test-socks5-tls - test-tls-support-latest - test-tls-support-6.0 - test-tls-support-5.0 @@ -2905,10 +2908,12 @@ buildvariants: - test-3.6-sharded_cluster - test-latest-server-v1-api - test-atlas-connectivity + - test-atlas-data-lake - test-5.0-load-balanced - test-6.0-load-balanced - test-latest-load-balanced - test-auth-ldap + - test-socks5-tls - test-tls-support-latest - test-tls-support-6.0 - test-tls-support-5.0 @@ -3070,6 +3075,9 @@ buildvariants: - test-3.6-replica_set - test-3.6-sharded_cluster - test-latest-server-v1-api + - test-atlas-data-lake + - test-socks5 + - test-socks5-tls - test-tls-support-latest - test-tls-support-6.0 - test-tls-support-5.0 diff --git a/.evergreen/generate_evergreen_tasks.js b/.evergreen/generate_evergreen_tasks.js index 71f26d1dca1..26e9d7e3ecf 100644 --- a/.evergreen/generate_evergreen_tasks.js +++ b/.evergreen/generate_evergreen_tasks.js @@ -623,7 +623,7 @@ const oneOffFuncAsTasks = oneOffFuncs.map(oneOffFunc => ({ })); for (const version of ['5.0', 'rapid', 'latest']) { - for (const ref of ['5745f374109346a2597405f2251a178d463a14e1', 'master']) { + for (const ref of ['ddb19ae22dc4a5f8b9208096f69fc23e19bae6c9', 'master']) { oneOffFuncAsTasks.push({ name: `run-custom-csfle-tests-${version}-${ref === 'master' ? ref : 'pinned-commit'}`, tags: ['run-custom-dependency-tests'], @@ -704,41 +704,28 @@ BUILD_VARIANTS.push({ // TODO(NODE-4575): unskip zstd and snappy on node 16 for (const variant of BUILD_VARIANTS.filter( - variant => variant.expansions && variant.expansions.NODE_LTS_NAME === 'gallium' + variant => variant.expansions && ['gallium', 'hydrogen', 'latest'].includes(variant.expansions.NODE_LTS_NAME) )) { variant.tasks = variant.tasks.filter( name => !['test-zstd-compression', 'test-snappy-compression'].includes(name) ); } -// TODO(NODE-4667): debug failing tests on Node18 +// TODO(NODE-4894): fix kerberos tests on Node18 for (const variant of BUILD_VARIANTS.filter( - variant => variant.expansions && variant.expansions.NODE_LTS_NAME === 'hydrogen' + variant => variant.expansions && ['hydrogen', 'latest'].includes(variant.expansions.NODE_LTS_NAME) )) { variant.tasks = variant.tasks.filter( - name => ![ - 'test-zstd-compression', - 'test-snappy-compression', - 'test-atlas-data-lake', - 'test-socks5', - 'test-socks5-tls', - 'test-auth-kerberos' - ].includes(name) + name => !['test-auth-kerberos'].includes(name) ); } -// TODO(NODE-4667): debug failing tests on Node18 -// latest is currently Node19, so these tests fail -for (const variant of BUILD_VARIANTS.filter(({ name }) => name.includes('node-latest'))) { +// TODO(NODE-4897): Debug socks5 tests on node latest +for (const variant of BUILD_VARIANTS.filter( + variant => variant.expansions && ['latest'].includes(variant.expansions.NODE_LTS_NAME) +)) { variant.tasks = variant.tasks.filter( - name => ![ - 'test-zstd-compression', - 'test-snappy-compression', - 'test-atlas-data-lake', - 'test-socks5', - 'test-socks5-tls', - 'test-auth-kerberos' - ].includes(name) + name => !['test-socks5'].includes(name) ); } diff --git a/.evergreen/run-kms-servers.sh b/.evergreen/run-kms-servers.sh index 76ef6ac258e..a349e9f407a 100644 --- a/.evergreen/run-kms-servers.sh +++ b/.evergreen/run-kms-servers.sh @@ -2,6 +2,6 @@ cd ${DRIVERS_TOOLS}/.evergreen/csfle . ./activate_venv.sh # by default it always runs on port 5698 ./kmstlsvenv/bin/python3 -u kms_kmip_server.py & -./kmstlsvenv/bin/python3 -u kms_http_server.py --ca_file ../x509gen/ca.pem --cert_file ../x509gen/expired.pem --port 8000 & -./kmstlsvenv/bin/python3 -u kms_http_server.py --ca_file ../x509gen/ca.pem --cert_file ../x509gen/wrong-host.pem --port 8001 & +./kmstlsvenv/bin/python3 -u kms_http_server.py --ca_file ../x509gen/ca.pem --cert_file ../x509gen/expired.pem --port 8000 & +./kmstlsvenv/bin/python3 -u kms_http_server.py --ca_file ../x509gen/ca.pem --cert_file ../x509gen/wrong-host.pem --port 8001 & ./kmstlsvenv/bin/python3 -u kms_http_server.py --ca_file ../x509gen/ca.pem --cert_file ../x509gen/server.pem --port 8002 --require_client_cert & diff --git a/test/integration/client-side-encryption/client_side_encryption.prose.corpus.test.js b/test/integration/client-side-encryption/client_side_encryption.prose.corpus.test.js index 154b52b73ba..e08e08cf60f 100644 --- a/test/integration/client-side-encryption/client_side_encryption.prose.corpus.test.js +++ b/test/integration/client-side-encryption/client_side_encryption.prose.corpus.test.js @@ -8,7 +8,7 @@ const BSON = require('bson'); const { EJSON } = require('bson'); const { expect } = require('chai'); const { getEncryptExtraOptions } = require('../../tools/utils'); -const { installNode18DNSHooks } = require('../../tools/runner/hooks/configuration'); +const { installNodeDNSWorkaroundHooks } = require('../../tools/runner/hooks/configuration'); describe('Client Side Encryption Prose Corpus Test', function () { const metadata = { @@ -148,7 +148,7 @@ describe('Client Side Encryption Prose Corpus Test', function () { } } - installNode18DNSHooks(); + installNodeDNSWorkaroundHooks(); before(function () { // 1. Create a MongoClient without encryption enabled (referred to as ``client``). diff --git a/test/integration/client-side-encryption/client_side_encryption.prose.deadlock.js b/test/integration/client-side-encryption/client_side_encryption.prose.deadlock.js index ea43a620411..28f8b87ce4a 100644 --- a/test/integration/client-side-encryption/client_side_encryption.prose.deadlock.js +++ b/test/integration/client-side-encryption/client_side_encryption.prose.deadlock.js @@ -7,7 +7,7 @@ const util = require('util'); const fs = require('fs'); const path = require('path'); const { getEncryptExtraOptions } = require('../../tools/utils'); -const { installNode18DNSHooks } = require('../../tools/runner/hooks/configuration'); +const { installNodeDNSWorkaroundHooks } = require('../../tools/runner/hooks/configuration'); /* REFERENCE: (note commit hash) */ /* https://github.com/mongodb/specifications/blob/b3beada72ae1c992294ae6a8eea572003a274c35/source/client-side-encryption/tests/README.rst#deadlock-tests */ @@ -93,8 +93,7 @@ function deadlockTests(_metadata) { const metadata = { ..._metadata, requires: { ..._metadata.requires, auth: 'disabled' } }; metadata.skipReason = 'TODO: NODE-3891 - fix tests broken when AUTH enabled'; describe('Connection Pool Deadlock Prevention', function () { - installNode18DNSHooks(); - + installNodeDNSWorkaroundHooks(); beforeEach(function () { try { const mongodbClientEncryption = this.configuration.mongodbClientEncryption; diff --git a/test/integration/client-side-encryption/client_side_encryption.prose.test.js b/test/integration/client-side-encryption/client_side_encryption.prose.test.js index 20b0cc8f725..319f6f95b58 100644 --- a/test/integration/client-side-encryption/client_side_encryption.prose.test.js +++ b/test/integration/client-side-encryption/client_side_encryption.prose.test.js @@ -11,7 +11,7 @@ const { EJSON, Binary } = BSON; const { LEGACY_HELLO_COMMAND } = require('../../../src/constants'); const { MongoNetworkError, MongoServerError } = require('../../../src/error'); const { getEncryptExtraOptions } = require('../../tools/utils'); -const { installNode18DNSHooks } = require('../../tools/runner/hooks/configuration'); +const { installNodeDNSWorkaroundHooks } = require('../../tools/runner/hooks/configuration'); const getKmsProviders = (localKey, kmipEndpoint, azureEndpoint, gcpEndpoint) => { const result = BSON.EJSON.parse(process.env.CSFLE_KMS_PROVIDERS || '{}'); @@ -70,7 +70,7 @@ describe('Client Side Encryption Prose Tests', metadata, function () { 'base64' ); - installNode18DNSHooks(); + installNodeDNSWorkaroundHooks(); describe('Data key and double encryption', function () { // Data key and double encryption diff --git a/test/integration/client-side-encryption/client_side_encryption.spec.test.ts b/test/integration/client-side-encryption/client_side_encryption.spec.test.ts index e7dc6ba8dcc..f727e975462 100644 --- a/test/integration/client-side-encryption/client_side_encryption.spec.test.ts +++ b/test/integration/client-side-encryption/client_side_encryption.spec.test.ts @@ -1,7 +1,7 @@ import * as path from 'path'; import { loadSpecTests } from '../../spec'; -import { installNode18DNSHooks } from '../../tools/runner/hooks/configuration'; +import { installNodeDNSWorkaroundHooks } from '../../tools/runner/hooks/configuration'; import { gatherTestSuites, generateTopologyTests, @@ -73,8 +73,7 @@ describe('Client Side Encryption (Legacy)', function () { testContext ); - installNode18DNSHooks(); - + installNodeDNSWorkaroundHooks(); after(() => testContext.teardown()); before(function () { return testContext.setup(this.configuration); @@ -98,7 +97,7 @@ describe('Client Side Encryption (Legacy)', function () { }); describe('Client Side Encryption (Unified)', function () { - installNode18DNSHooks(); + installNodeDNSWorkaroundHooks(); runUnifiedSuite(loadSpecTests(path.join('client-side-encryption', 'tests', 'unified')), () => isServerless ? 'Unified CSFLE tests to not run on serverless' : false ); diff --git a/test/integration/client-side-encryption/driver.test.ts b/test/integration/client-side-encryption/driver.test.ts index 8dc714acc25..963c39a8e6f 100644 --- a/test/integration/client-side-encryption/driver.test.ts +++ b/test/integration/client-side-encryption/driver.test.ts @@ -4,7 +4,7 @@ import * as crypto from 'crypto'; import { Collection, CommandStartedEvent, MongoClient } from '../../../src'; import * as BSON from '../../../src/bson'; -import { installNode18DNSHooks } from '../../tools/runner/hooks/configuration'; +import { installNodeDNSWorkaroundHooks } from '../../tools/runner/hooks/configuration'; import { ClientEncryption } from '../../tools/unified-spec-runner/schema'; import { getEncryptExtraOptions } from '../../tools/utils'; @@ -22,7 +22,7 @@ describe('Client Side Encryption Functional', function () { const keyVaultCollName = 'datakeys'; const keyVaultNamespace = `${keyVaultDbName}.${keyVaultCollName}`; - installNode18DNSHooks(); + installNodeDNSWorkaroundHooks(); it('CSFLE_KMS_PROVIDERS should be valid EJSON', function () { const CSFLE_KMS_PROVIDERS = process.env.CSFLE_KMS_PROVIDERS; diff --git a/test/integration/server-selection/server_selection.prose.operation_count.test.ts b/test/integration/server-selection/server_selection.prose.operation_count.test.ts index 1fbd6f610a8..5256c2866bc 100644 --- a/test/integration/server-selection/server_selection.prose.operation_count.test.ts +++ b/test/integration/server-selection/server_selection.prose.operation_count.test.ts @@ -4,7 +4,7 @@ import { on } from 'events'; import { CommandStartedEvent } from '../../../src'; import { Collection } from '../../../src/collection'; import { MongoClient } from '../../../src/mongo_client'; -import { installNode18DNSHooks } from '../../tools/runner/hooks/configuration'; +import { HostAddress } from '../../../src/utils'; import { sleep } from '../../tools/utils'; const failPoint = { @@ -45,13 +45,13 @@ describe('operationCount-based Selection Within Latency Window - Prose Test', fu let seeds: Array; let counts: Record = {}; const updateCount = ({ address }: CommandStartedEvent) => { - const mongosPort = address.split(':')[1]; - const count = counts[mongosPort] ?? 0; - counts[mongosPort] = count + 1; + const hostAddress = HostAddress.fromString(address); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const port = hostAddress.port!.toString(); + const count = counts[port] ?? 0; + counts[port] = count + 1; }; - installNode18DNSHooks(); - beforeEach(async function () { // Step 3: Create a client with both mongoses' addresses in its seed list, appName="loadBalancingTest", and localThresholdMS=30000. const uri = this.configuration.url({ diff --git a/test/manual/atlas-data-lake-testing/atlas_data_lake_testing.prose.js b/test/manual/atlas-data-lake-testing/atlas_data_lake_testing.prose.js index 2d61252f2f0..cb3e5376088 100644 --- a/test/manual/atlas-data-lake-testing/atlas_data_lake_testing.prose.js +++ b/test/manual/atlas-data-lake-testing/atlas_data_lake_testing.prose.js @@ -4,6 +4,7 @@ const { MongoClient } = require('../../../src'); // TODO(NODE-3880): These tests are not fully implemented per the spec describe('Atlas Data Lake - prose', function () { let client; + beforeEach(function () { client = null; }); @@ -30,7 +31,8 @@ describe('Atlas Data Lake - prose', function () { * If a driver constructs and issues killCursors commands in other ways (e.g. public API), this test MUST be adapted to test all such code paths. */ it('1. Test that the driver properly constructs and issues a killCursors command to Atlas Data Lake.', async function () { - client = new MongoClient('mongodb://mhuser:pencil@localhost'); + // TODO(NODE-4884): once happy eyeballs support is added, we no longer need to set the default dns resolution order for CI + client = new MongoClient('mongodb://mhuser:pencil@localhost', { family: 4 }); const db = client.db('admin'); await db.command({ killCursors: 'kill_cursor_collection' }); }); @@ -39,7 +41,8 @@ describe('Atlas Data Lake - prose', function () { * For these tests, create a MongoClient using a valid connection string without auth credentials and execute a ping command. */ it('2. Test that the driver can establish a connection with Atlas Data Lake without authentication.', async function () { - client = new MongoClient('mongodb://localhost'); + // TODO(NODE-4884): once happy eyeballs support is added, we no longer need to set the default dns resolution order for CI + client = new MongoClient('mongodb://localhost', { family: 4 }); const db = client.db('admin'); await db.command({ ping: 1 }); }); @@ -49,7 +52,10 @@ describe('Atlas Data Lake - prose', function () { * from the drivers-evergreen-tools ADL configuration and execute a ping command. */ it('3a. Test that the driver can establish a connection with Atlas Data Lake with authentication. (SCRAM-SHA-1)', async function () { - client = new MongoClient('mongodb://mhuser:pencil@localhost?authMechanism=SCRAM-SHA-1'); + // TODO(NODE-4884): once happy eyeballs support is added, we no longer need to set the default dns resolution order for CI + client = new MongoClient('mongodb://mhuser:pencil@localhost?authMechanism=SCRAM-SHA-1', { + family: 4 + }); const db = client.db('admin'); await db.command({ ping: 1 }); await db.command({ killCursors: 'kill_cursor_collection' }); @@ -59,7 +65,10 @@ describe('Atlas Data Lake - prose', function () { * Repeat the authentication test using SCRAM-SHA-256. */ it('3b. Test that the driver can establish a connection with Atlas Data Lake with authentication. (SCRAM-SHA-256)', async function () { - client = new MongoClient('mongodb://mhuser:pencil@localhost?authMechanism=SCRAM-SHA-256'); + // TODO(NODE-4884): once happy eyeballs support is added, we no longer need to set the default dns resolution order for CI + client = new MongoClient('mongodb://mhuser:pencil@localhost?authMechanism=SCRAM-SHA-256', { + family: 4 + }); const db = client.db('admin'); await db.command({ ping: 1 }); await db.command({ killCursors: 'kill_cursor_collection' }); diff --git a/test/manual/atlas-data-lake-testing/atlas_data_lake_testing.spec.js b/test/manual/atlas-data-lake-testing/atlas_data_lake_testing.spec.js index 9ef22def8f9..ecf96cc60db 100644 --- a/test/manual/atlas-data-lake-testing/atlas_data_lake_testing.spec.js +++ b/test/manual/atlas-data-lake-testing/atlas_data_lake_testing.spec.js @@ -1,5 +1,6 @@ 'use strict'; const path = require('path'); +const { installNodeDNSWorkaroundHooks } = require('../../tools/runner/hooks/configuration'); const { TestRunnerContext, gatherTestSuites, @@ -19,11 +20,19 @@ describe('Atlas Data Lake - spec', function () { path.resolve(__dirname, '../../spec/atlas-data-lake-testing') ); - after(() => testContext.teardown()); + // These tests timeout connecting to on localhost mongohoused in CI on Node18+. + // Manually setting the ip address resolution is safe for testing purposes + // because in production, mongohoused will never be running on localhost. + installNodeDNSWorkaroundHooks(); + before(function () { return testContext.setup(this.configuration); }); + after(() => { + testContext.teardown(); + }); + for (const suite of testSuites) suite.runOn = []; // patched in for the spec runner generateTopologyTests(testSuites, testContext); diff --git a/test/manual/socks5.test.ts b/test/manual/socks5.test.ts index 0a1d51b69f5..98170312687 100644 --- a/test/manual/socks5.test.ts +++ b/test/manual/socks5.test.ts @@ -4,6 +4,7 @@ import ConnectionString from 'mongodb-connection-string-url'; import { MongoClient } from '../../src'; import { LEGACY_HELLO_COMMAND } from '../../src/constants'; import { MongoParseError } from '../../src/error'; +import { installNodeDNSWorkaroundHooks } from '../tools/runner/hooks/configuration'; /** * The SOCKS5_CONFIG environment variable is either a JSON 4-tuple @@ -34,6 +35,8 @@ describe('Socks5 Connectivity', function () { rsConnectionString.searchParams.set('serverSelectionTimeoutMS', '2000'); singleConnectionString.searchParams.set('serverSelectionTimeoutMS', '2000'); + installNodeDNSWorkaroundHooks(); + context((proxyUsername ? 'with' : 'without') + ' Socks5 auth required', function () { context('with missing required Socks5 auth configuration', function () { if (!proxyUsername) { @@ -302,9 +305,12 @@ async function testConnection(connectionString, clientOptions) { let topologyType; client.on('topologyDescriptionChanged', ev => (topologyType = ev.newDescription.type)); - await client.connect(); - await client.db('admin').command({ hello: 1 }); - await client.db('test').collection('test').findOne({}); - await client.close(); + try { + await client.connect(); + await client.db('admin').command({ hello: 1 }); + await client.db('test').collection('test').findOne({}); + } finally { + await client.close(); + } return topologyType; } diff --git a/test/tools/runner/hooks/configuration.js b/test/tools/runner/hooks/configuration.js index a4f4993e821..2793e4c96a4 100644 --- a/test/tools/runner/hooks/configuration.js +++ b/test/tools/runner/hooks/configuration.js @@ -100,7 +100,10 @@ const skipBrokenAuthTestBeforeEachHook = function ({ skippedTests } = { skippedT const testConfigBeforeHook = async function () { const client = new MongoClient(loadBalanced ? SINGLE_MONGOS_LB_URI : MONGODB_URI, { - ...getEnvironmentalOptions() + ...getEnvironmentalOptions(), + // TODO(NODE-4884): once happy eyeballs support is added, we no longer need to set + // the default dns resolution order for CI + family: 4 }); await client.db('test').command({ ping: 1 }); @@ -167,12 +170,23 @@ const beforeAllPluginImports = () => { require('mocha-sinon'); }; -function installNode18DNSHooks() { +/** + * @remarks TODO(NODE-4884): once happy eyeballs support is added, we no longer need to set + * the default dns resolution order for CI + */ +function installNodeDNSWorkaroundHooks() { if ( process.version.startsWith('v18') || process.version.startsWith('v19') || process.version.startsWith('v20') ) { + // We set before hooks because some tests connect in before hooks + before(() => { + setDefaultResultOrder('ipv4first'); + }); + + // We set beforeEach hooks to make this resilient to test ordering and + // ensure each affected test has the correct ip address resolution setting beforeEach(() => { setDefaultResultOrder('ipv4first'); }); @@ -189,5 +203,5 @@ module.exports = { afterAll: [cleanUpMocksAfterHook] }, skipBrokenAuthTestBeforeEachHook, - installNode18DNSHooks + installNodeDNSWorkaroundHooks };