Skip to content

Commit 4e3a1ba

Browse files
committed
test(NODE-3049): drivers atlas testing
1 parent a17b0af commit 4e3a1ba

File tree

6 files changed

+113
-2
lines changed

6 files changed

+113
-2
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@
143143
"check:unit": "mocha test/unit",
144144
"check:ts": "node ./node_modules/typescript/bin/tsc -v && node ./node_modules/typescript/bin/tsc --noEmit",
145145
"check:atlas": "mocha --config test/manual/mocharc.json test/manual/atlas_connectivity.test.js",
146+
"check:drivers-atlas-testing": "mocha --config test/mocha_mongodb.json test/atlas/drivers_atlas_testing.test.ts",
146147
"check:adl": "mocha --config test/mocha_mongodb.json test/manual/atlas-data-lake-testing",
147148
"check:aws": "nyc mocha --config test/mocha_mongodb.json test/integration/auth/mongodb_aws.test.ts",
148149
"check:oidc": "mocha --config test/mocha_mongodb.json test/manual/mongodb_oidc.prose.test.ts",
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { runUnifiedSuite } from '../tools/unified-spec-runner/runner';
2+
3+
describe('Node Driver Atlas Testing', async function () {
4+
console.log('process.env', process.env);
5+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
6+
const spec = JSON.parse(process.env.WORKLOAD_SPECIFICATION!);
7+
runUnifiedSuite([spec]);
8+
});

test/tools/runner/config.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,11 @@ export class TestConfiguration {
159159
}
160160

161161
newClient(dbOptions?: string | Record<string, any>, serverOptions?: Record<string, any>) {
162+
if (process.env.DRIVERS_ATLAS_TESTING_URI) {
163+
console.log('Using drivers Atlas testing URI', process.env.DRIVERS_ATLAS_TESTING_URI);
164+
return new MongoClient(process.env.DRIVERS_ATLAS_TESTING_URI);
165+
}
166+
162167
serverOptions = Object.assign({}, getEnvironmentalOptions(), serverOptions);
163168

164169
// support MongoClient constructor form (url, options) for `newClient`
@@ -258,6 +263,11 @@ export class TestConfiguration {
258263
...options
259264
};
260265

266+
if (process.env.DRIVERS_ATLAS_TESTING_URI) {
267+
console.log('Using drivers Atlas testing URI', process.env.DRIVERS_ATLAS_TESTING_URI);
268+
return process.env.DRIVERS_ATLAS_TESTING_URI;
269+
}
270+
261271
const FILLER_HOST = 'fillerHost';
262272

263273
const protocol = this.isServerless ? 'mongodb+srv' : 'mongodb';

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

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import {
2222
type ConnectionPoolReadyEvent,
2323
type ConnectionReadyEvent,
2424
Db,
25-
type Document,
25+
Document,
2626
GridFSBucket,
2727
type HostAddress,
2828
type Log,
@@ -357,8 +357,10 @@ export type Entity =
357357
| AbstractCursor
358358
| UnifiedChangeStream
359359
| GridFSBucket
360+
| Document
360361
| ClientEncryption
361362
| TopologyDescription // From recordTopologyDescription operation
363+
| number
362364
| Document; // Results from operations
363365

364366
export type EntityCtor =
@@ -370,6 +372,8 @@ export type EntityCtor =
370372
| typeof AbstractCursor
371373
| typeof GridFSBucket
372374
| typeof UnifiedThread
375+
| typeof Document
376+
| typeof Number
373377
| ClientEncryption;
374378

375379
export type EntityTypeId =
@@ -381,7 +385,12 @@ export type EntityTypeId =
381385
| 'thread'
382386
| 'cursor'
383387
| 'stream'
384-
| 'clientEncryption';
388+
| 'clientEncryption'
389+
| 'iterations'
390+
| 'successes'
391+
| 'errors'
392+
| 'failures'
393+
| 'events';
385394

386395
const ENTITY_CTORS = new Map<EntityTypeId, EntityCtor>();
387396
ENTITY_CTORS.set('client', UnifiedMongoClient);
@@ -392,6 +401,11 @@ ENTITY_CTORS.set('bucket', GridFSBucket);
392401
ENTITY_CTORS.set('thread', UnifiedThread);
393402
ENTITY_CTORS.set('cursor', AbstractCursor);
394403
ENTITY_CTORS.set('stream', ChangeStream);
404+
ENTITY_CTORS.set('iterations', Number);
405+
ENTITY_CTORS.set('successes', Number);
406+
ENTITY_CTORS.set('errors', Document);
407+
ENTITY_CTORS.set('failures', Document);
408+
ENTITY_CTORS.set('events', Document);
395409

396410
export class EntitiesMap<E = Entity> extends Map<string, E> {
397411
failPoints: FailPointMap;
@@ -435,6 +449,11 @@ export class EntitiesMap<E = Entity> extends Map<string, E> {
435449
getEntity(type: 'thread', key: string, assertExists?: boolean): UnifiedThread;
436450
getEntity(type: 'cursor', key: string, assertExists?: boolean): AbstractCursor;
437451
getEntity(type: 'stream', key: string, assertExists?: boolean): UnifiedChangeStream;
452+
getEntity(type: 'iterations', key: string, assertExists?: boolean): number;
453+
getEntity(type: 'successes', key: string, assertExists?: boolean): number;
454+
getEntity(type: 'errors', key: string, assertExists?: boolean): Document[];
455+
getEntity(type: 'failures', key: string, assertExists?: boolean): Document[];
456+
getEntity(type: 'events', key: string, assertExists?: boolean): Document[];
438457
getEntity(type: 'clientEncryption', key: string, assertExists?: boolean): ClientEncryption;
439458
getEntity(type: EntityTypeId, key: string, assertExists = true): Entity | undefined {
440459
const entity = this.get(key);

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

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,53 @@ operations.set('listIndexes', async ({ entities, operation }) => {
377377
return collection.listIndexes(operation.arguments!).toArray();
378378
});
379379

380+
operations.set('loop', async ({ entities, operation, client, testConfig }) => {
381+
const controller = new AbortController();
382+
process.on('SIGINT', () => {
383+
controller.abort('Process received SIGINT, aborting operation loop.');
384+
});
385+
const args = operation.arguments!;
386+
const storeIterationsAsEntity = args.storeIterationsAsEntity;
387+
const storeSuccessesAsEntity = args.storeSuccessesAsEntity;
388+
const storeErrorsAsEntity = args.storeErrorsAsEntity;
389+
const storeFailuresAsEntity = args.storeFailuresAsEntity;
390+
391+
if (storeErrorsAsEntity) {
392+
entities.set(storeErrorsAsEntity, []);
393+
}
394+
if (storeFailuresAsEntity) {
395+
entities.set(storeFailuresAsEntity, []);
396+
}
397+
let iterations = 0;
398+
let successes = 0;
399+
while (!controller.signal.aborted) {
400+
if (storeIterationsAsEntity) {
401+
entities.set(storeIterationsAsEntity, iterations++);
402+
}
403+
for (const op of args.operations) {
404+
console.log('op', op);
405+
try {
406+
await executeOperationAndCheck(op, entities, client, testConfig);
407+
if (storeSuccessesAsEntity) {
408+
entities.set(storeSuccessesAsEntity, successes++);
409+
}
410+
} catch (error) {
411+
console.log('error', error);
412+
if (storeErrorsAsEntity) {
413+
entities
414+
.getEntity('errors', storeErrorsAsEntity)
415+
.push({ error: error.message, time: Date.now() });
416+
}
417+
if (storeFailuresAsEntity) {
418+
entities
419+
.getEntity('failures', storeFailuresAsEntity)
420+
.push({ error: error.message, time: Date.now() });
421+
}
422+
}
423+
}
424+
}
425+
});
426+
380427
operations.set('replaceOne', async ({ entities, operation }) => {
381428
const collection = entities.getEntity('collection', operation.object);
382429
const { filter, replacement, ...opts } = operation.arguments!;

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
/* eslint-disable @typescript-eslint/no-non-null-assertion */
2+
import { writeFile } from 'node:fs/promises';
3+
24
import { expect } from 'chai';
5+
import * as path from 'path';
36
import { gte as semverGte, satisfies as semverSatisfies } from 'semver';
47

58
import type { MongoClient } from '../../mongodb';
@@ -255,6 +258,29 @@ async function runUnifiedTest(
255258
}
256259
} finally {
257260
await utilClient.close();
261+
// For astrolabe testing we need to write the entities to files.
262+
if (process.env.WORKLOAD_SPECIFICATION) {
263+
// Write the events.json to the execution directory.
264+
const errors = entities?.getEntity('errors', 'errors');
265+
const failures = entities?.getEntity('failures', 'failures');
266+
const events = entities?.getEntity('events', 'events');
267+
const iterations = entities?.getEntity('iterations', 'events');
268+
const successes = entities?.getEntity('successes', 'events');
269+
await writeFile(
270+
path.join(process.env.OUTPUT_DIRECTORY ?? '', 'events.json'),
271+
JSON.stringify({ events: events, errors: errors, failures: failures })
272+
);
273+
// Write the results.json to the execution directory.
274+
await writeFile(
275+
path.join(process.env.OUTPUT_DIRECTORY ?? '', 'results.json'),
276+
JSON.stringify({
277+
numErrors: errors?.length,
278+
numFailures: failures?.length,
279+
numSuccesses: successes,
280+
numIterations: iterations
281+
})
282+
);
283+
}
258284
await entities?.cleanup();
259285
}
260286
}

0 commit comments

Comments
 (0)