@@ -92,16 +92,16 @@ describe('Transactions (spec)', function() {
92
92
} )
93
93
) ;
94
94
95
- after ( ( ) => testContext . client . close ( ) ) ;
95
+ after ( ( ) => testContext . sharedClient . close ( ) ) ;
96
96
before ( function ( ) {
97
97
// create a shared client for admin tasks
98
98
const config = this . configuration ;
99
99
testContext . url = `mongodb://${ config . host } :${ config . port } /${ testContext . dbName } ?replicaSet=${
100
100
config . replicasetName
101
101
} `;
102
102
103
- testContext . client = new MongoClient ( testContext . url ) ;
104
- return testContext . client . connect ( ) ;
103
+ testContext . sharedClient = new MongoClient ( testContext . url ) ;
104
+ return testContext . sharedClient . connect ( ) ;
105
105
} ) ;
106
106
107
107
testSuites . forEach ( testSuite => {
@@ -111,14 +111,23 @@ describe('Transactions (spec)', function() {
111
111
beforeEach ( ( ) => prepareDatabaseForSuite ( testSuite , testContext ) ) ;
112
112
afterEach ( ( ) => cleanupAfterSuite ( testContext ) ) ;
113
113
114
- testSuite . tests . forEach ( testData => runTestSuiteTest ( testData , testContext ) ) ;
114
+ testSuite . tests . forEach ( testData => {
115
+ const maybeSkipIt = testData . skipReason ? it . skip : it ;
116
+ maybeSkipIt ( testData . description , function ( ) {
117
+ let testPromise = Promise . resolve ( ) ;
118
+ testPromise = testPromise . then ( ( ) => runTestSuiteTest ( testData , testContext ) ) ;
119
+
120
+ return testPromise ;
121
+ } ) ;
122
+ } ) ;
115
123
}
116
124
} ) ;
117
125
} ) ;
118
126
} ) ;
119
127
128
+ // Test runner helpers
120
129
function prepareDatabaseForSuite ( suite , context ) {
121
- const db = context . client . db ( ) ;
130
+ const db = context . sharedClient . db ( ) ;
122
131
const coll = db . collection ( context . collectionName ) ;
123
132
124
133
return db
@@ -146,126 +155,131 @@ function cleanupAfterSuite(context) {
146
155
}
147
156
148
157
let displayCommands = false ;
149
-
150
158
function runTestSuiteTest ( testData , context ) {
151
- const maybeSkipIt = testData . skipReason ? it . skip : it ;
152
- maybeSkipIt ( testData . description , function ( ) {
153
- const commandEvents = [ ] ;
154
- const clientOptions = translateClientOptions (
155
- Object . assign ( { monitorCommands : true } , testData . clientOptions )
159
+ const commandEvents = [ ] ;
160
+ const clientOptions = translateClientOptions (
161
+ Object . assign ( { monitorCommands : true } , testData . clientOptions )
162
+ ) ;
163
+
164
+ return MongoClient . connect ( context . url , clientOptions ) . then ( client => {
165
+ context . testClient = client ;
166
+ client . on ( 'commandStarted' , event => {
167
+ if (
168
+ event . databaseName === context . dbName ||
169
+ [ 'startTransaction' , 'commitTransaction' , 'abortTransaction' ] . includes ( event . commandName )
170
+ ) {
171
+ commandEvents . push ( event ) ;
172
+ }
173
+
174
+ // very useful for debugging
175
+ if ( displayCommands ) {
176
+ console . dir ( event , { depth : 5 } ) ;
177
+ }
178
+ } ) ;
179
+
180
+ const sessionOptions = Object . assign ( { } , testData . transactionOptions ) ;
181
+
182
+ testData . sessionOptions = testData . sessionOptions || { } ;
183
+ const database = client . db ( ) ;
184
+ const session0 = client . startSession (
185
+ Object . assign ( { } , sessionOptions , testData . sessionOptions . session0 )
186
+ ) ;
187
+ const session1 = client . startSession (
188
+ Object . assign ( { } , sessionOptions , testData . sessionOptions . session1 )
156
189
) ;
157
190
158
- return MongoClient . connect ( context . url , clientOptions ) . then ( client => {
159
- context . testClient = client ;
160
- client . on ( 'commandStarted' , event => {
161
- if (
162
- event . databaseName === context . dbName ||
163
- [ 'startTransaction' , 'commitTransaction' , 'abortTransaction' ] . includes ( event . commandName )
164
- ) {
165
- commandEvents . push ( event ) ;
166
- }
191
+ // enable to see useful APM debug information at the time of actual test run
192
+ // displayCommands = true;
167
193
168
- // very useful for debugging
169
- if ( displayCommands ) {
170
- console . dir ( event , { depth : 5 } ) ;
171
- }
172
- } ) ;
194
+ const operationContext = { database, session0, session1 } ;
173
195
174
- const sessionOptions = Object . assign ( { } , testData . transactionOptions ) ;
196
+ let testPromise = Promise . resolve ( ) ;
197
+ return testPromise
198
+ . then ( ( ) => testOperations ( client , testData , operationContext ) )
199
+ . catch ( err => {
200
+ // If the driver throws an exception / returns an error while executing this series
201
+ // of operations, store the error message.
202
+ throw err ;
203
+ } )
204
+ . then ( ( ) => {
205
+ session0 . endSession ( ) ;
206
+ session1 . endSession ( ) ;
175
207
176
- testData . sessionOptions = testData . sessionOptions || { } ;
177
- const database = client . db ( ) ;
178
- const session0 = client . startSession (
179
- Object . assign ( { } , sessionOptions , testData . sessionOptions . session0 )
180
- ) ;
181
- const session1 = client . startSession (
182
- Object . assign ( { } , sessionOptions , testData . sessionOptions . session1 )
183
- ) ;
208
+ return validateExpectations ( commandEvents , testData , context , operationContext ) ;
209
+ } ) ;
210
+ } ) ;
211
+ }
184
212
185
- // enable to see useful APM debug information at the time of actual test run
186
- // displayCommands = true;
213
+ function validateExpectations ( commandEvents , testData , testContext , operationContext ) {
214
+ const session0 = operationContext . session0 ;
215
+ const session1 = operationContext . session1 ;
216
+
217
+ if (
218
+ testData . expectations &&
219
+ Array . isArray ( testData . expectations ) &&
220
+ testData . expectations . length > 0
221
+ ) {
222
+ const actualEvents = normalizeCommandShapes ( commandEvents ) ;
223
+ const rawExpectedEvents = testData . expectations . map ( x =>
224
+ linkSessionData ( x . command_started_event , { session0, session1 } )
225
+ ) ;
187
226
188
- let testPromise = Promise . resolve ( ) ;
189
- return testPromise
190
- . then ( ( ) => testOperations ( client , testData , { database, session0, session1 } ) )
191
- . catch ( err => {
192
- // If the driver throws an exception / returns an error while executing this series
193
- // of operations, store the error message.
194
- throw err ;
195
- } )
196
- . then ( ( ) => {
197
- session0 . endSession ( ) ;
198
- session1 . endSession ( ) ;
199
-
200
- if (
201
- testData . expectations &&
202
- Array . isArray ( testData . expectations ) &&
203
- testData . expectations . length > 0
204
- ) {
205
- const actualEvents = normalizeCommandShapes ( commandEvents ) ;
206
- const rawExpectedEvents = testData . expectations . map ( x =>
207
- linkSessionData ( x . command_started_event , { session0, session1 } )
208
- ) ;
209
-
210
- const expectedEventPlaceholders = rawExpectedEvents . map ( event =>
211
- findPlaceholders ( event . command )
212
- ) ;
213
-
214
- const expectedEvents = normalizeCommandShapes ( rawExpectedEvents ) ;
215
- expect ( actualEvents ) . to . have . length ( expectedEvents . length ) ;
216
-
217
- expectedEvents . forEach ( ( expected , idx ) => {
218
- const actual = actualEvents [ idx ] ;
219
- const placeHolders = expectedEventPlaceholders [ idx ] ; // eslint-disable-line
220
-
221
- expect ( actual . commandName ) . to . equal ( expected . commandName ) ;
222
- expect ( actual . databaseName ) . to . equal ( expected . databaseName ) ;
223
-
224
- const actualCommand = actual . command ;
225
- const expectedCommand = expected . command ;
226
-
227
- // handle validation of placeholder values
228
- // placeHolders.forEach(placeholder => {
229
- // const parsedActual = EJSON.parse(JSON.stringify(actualCommand), {
230
- // relaxed: true
231
- // });
232
-
233
- // if (placeholder.type === null) {
234
- // expect(parsedActual).to.not.have.all.nested.property(placeholder.path);
235
- // } else if (placeholder.type === 'string') {
236
- // expect(parsedActual).nested.property(placeholder.path).to.exist;
237
- // expect(parsedActual)
238
- // .nested.property(placeholder.path)
239
- // .to.have.length.greaterThan(0);
240
- // } else if (placeholder.type === 'number') {
241
- // expect(parsedActual).nested.property(placeholder.path).to.exist;
242
- // expect(parsedActual)
243
- // .nested.property(placeholder.path)
244
- // .to.be.greaterThan(0);
245
- // }
246
- // });
247
-
248
- // compare the command
249
- expect ( actualCommand ) . to . containSubset ( expectedCommand ) ;
250
- } ) ;
251
- }
227
+ const expectedEventPlaceholders = rawExpectedEvents . map ( event =>
228
+ findPlaceholders ( event . command )
229
+ ) ;
252
230
253
- if ( testData . outcome ) {
254
- if ( testData . outcome . collection ) {
255
- // use the client without transactions to verify
256
- return context . client
257
- . db ( )
258
- . collection ( context . collectionName )
259
- . find ( { } )
260
- . toArray ( )
261
- . then ( docs => {
262
- expect ( docs ) . to . eql ( testData . outcome . collection . data ) ;
263
- } ) ;
264
- }
265
- }
266
- } ) ;
231
+ const expectedEvents = normalizeCommandShapes ( rawExpectedEvents ) ;
232
+ expect ( actualEvents ) . to . have . length ( expectedEvents . length ) ;
233
+
234
+ expectedEvents . forEach ( ( expected , idx ) => {
235
+ const actual = actualEvents [ idx ] ;
236
+ const placeHolders = expectedEventPlaceholders [ idx ] ; // eslint-disable-line
237
+
238
+ expect ( actual . commandName ) . to . equal ( expected . commandName ) ;
239
+ expect ( actual . databaseName ) . to . equal ( expected . databaseName ) ;
240
+
241
+ const actualCommand = actual . command ;
242
+ const expectedCommand = expected . command ;
243
+
244
+ // handle validation of placeholder values
245
+ // placeHolders.forEach(placeholder => {
246
+ // const parsedActual = EJSON.parse(JSON.stringify(actualCommand), {
247
+ // relaxed: true
248
+ // });
249
+
250
+ // if (placeholder.type === null) {
251
+ // expect(parsedActual).to.not.have.all.nested.property(placeholder.path);
252
+ // } else if (placeholder.type === 'string') {
253
+ // expect(parsedActual).nested.property(placeholder.path).to.exist;
254
+ // expect(parsedActual)
255
+ // .nested.property(placeholder.path)
256
+ // .to.have.length.greaterThan(0);
257
+ // } else if (placeholder.type === 'number') {
258
+ // expect(parsedActual).nested.property(placeholder.path).to.exist;
259
+ // expect(parsedActual)
260
+ // .nested.property(placeholder.path)
261
+ // .to.be.greaterThan(0);
262
+ // }
263
+ // });
264
+
265
+ // compare the command
266
+ expect ( actualCommand ) . to . containSubset ( expectedCommand ) ;
267
267
} ) ;
268
- } ) ;
268
+ }
269
+
270
+ if ( testData . outcome ) {
271
+ if ( testData . outcome . collection ) {
272
+ // use the client without transactions to verify
273
+ return testContext . sharedClient
274
+ . db ( )
275
+ . collection ( testContext . collectionName )
276
+ . find ( { } )
277
+ . toArray ( )
278
+ . then ( docs => {
279
+ expect ( docs ) . to . eql ( testData . outcome . collection . data ) ;
280
+ } ) ;
281
+ }
282
+ }
269
283
}
270
284
271
285
function linkSessionData ( command , context ) {
0 commit comments