1
- 'use strict' ;
2
-
3
- const mock = require ( '../tools/mongodb-mock/index' ) ;
4
- const { expect } = require ( 'chai' ) ;
5
- const { genClusterTime, sessionCleanupHandler } = require ( '../tools/common' ) ;
6
- const { Topology } = require ( '../../src/sdam/topology' ) ;
7
- const { ServerSessionPool, ServerSession, ClientSession } = require ( '../../src/sessions' ) ;
8
- const { now, isHello } = require ( '../../src/utils' ) ;
9
-
10
- let test = { } ;
11
-
12
- describe ( 'Sessions - unit/core' , function ( ) {
13
- describe ( 'ClientSession' , function ( ) {
14
- let session ;
15
- let sessionPool ;
1
+ import { expect } from 'chai' ;
2
+
3
+ import { Long } from '../../src/bson' ;
4
+ import { DEFAULT_OPTIONS } from '../../src/connection_string' ;
5
+ import { Topology } from '../../src/sdam/topology' ;
6
+ import { ClientSession , ServerSession , ServerSessionPool } from '../../src/sessions' ;
7
+ import { HostAddress , isHello , now } from '../../src/utils' ;
8
+ import { genClusterTime , sessionCleanupHandler } from '../tools/common' ;
9
+ import * as mock from '../tools/mongodb-mock/index' ;
10
+ import { getSymbolFrom } from '../tools/utils' ;
11
+
12
+ const test = {
13
+ client : null ,
14
+ server : null
15
+ } ;
16
+
17
+ // TODO(NODE-2149): MongoClient will have topology always defined on it and we can stop constructing topologies in here.
18
+ const topologyHost = 'iLoveJavaScript:123' ;
19
+ const topologyOptions = {
20
+ hosts : [ HostAddress . fromString ( topologyHost ) ] ,
21
+ retryReads : DEFAULT_OPTIONS . get ( 'retryReads' ) ,
22
+ retryWrites : DEFAULT_OPTIONS . get ( 'retryWrites' ) ,
23
+ serverSelectionTimeoutMS : DEFAULT_OPTIONS . get ( 'serverSelectionTimeoutMS' ) ,
24
+ directConnection : DEFAULT_OPTIONS . get ( 'directConnection' ) ,
25
+ loadBalanced : DEFAULT_OPTIONS . get ( 'loadBalanced' ) ,
26
+ metadata : DEFAULT_OPTIONS . get ( 'metadata' ) ,
27
+ monitorCommands : DEFAULT_OPTIONS . get ( 'monitorCommands' ) ,
28
+ tls : DEFAULT_OPTIONS . get ( 'tls' ) ,
29
+ maxPoolSize : DEFAULT_OPTIONS . get ( 'maxPoolSize' ) ,
30
+ minPoolSize : DEFAULT_OPTIONS . get ( 'minPoolSize' ) ,
31
+ waitQueueTimeoutMS : DEFAULT_OPTIONS . get ( 'waitQueueTimeoutMS' ) ,
32
+ connectionType : DEFAULT_OPTIONS . get ( 'connectionType' ) ,
33
+ connectTimeoutMS : DEFAULT_OPTIONS . get ( 'connectTimeoutMS' ) ,
34
+ maxIdleTimeMS : DEFAULT_OPTIONS . get ( 'maxIdleTimeMS' ) ,
35
+ heartbeatFrequencyMS : DEFAULT_OPTIONS . get ( 'heartbeatFrequencyMS' ) ,
36
+ minHeartbeatFrequencyMS : DEFAULT_OPTIONS . get ( 'minHeartbeatFrequencyMS' ) ,
37
+ srvMaxHosts : 0 ,
38
+ srvServiceName : 'mongodb'
39
+ } ;
40
+
41
+ describe ( 'Sessions - unit' , function ( ) {
42
+ describe ( 'new ClientSession()' , function ( ) {
43
+ let session : ClientSession ;
44
+ let sessionPool : ServerSessionPool ;
16
45
17
46
afterEach ( done => {
18
47
if ( sessionPool ) {
@@ -24,44 +53,69 @@ describe('Sessions - unit/core', function () {
24
53
25
54
it ( 'should throw errors with invalid parameters' , function ( ) {
26
55
expect ( ( ) => {
56
+ // @ts -expect-error: Client session has 3 required parameters
27
57
new ClientSession ( ) ;
28
58
} ) . to . throw ( / C l i e n t S e s s i o n r e q u i r e s a t o p o l o g y / ) ;
29
59
30
60
expect ( ( ) => {
61
+ // @ts -expect-error: Client session has 3 required parameters
31
62
new ClientSession ( { } ) ;
32
63
} ) . to . throw ( / C l i e n t S e s s i o n r e q u i r e s a S e r v e r S e s s i o n P o o l / ) ;
33
64
34
65
expect ( ( ) => {
66
+ // @ts -expect-error: Client session has 3 required parameters
35
67
new ClientSession ( { } , { } ) ;
36
68
} ) . to . throw ( / C l i e n t S e s s i o n r e q u i r e s a S e r v e r S e s s i o n P o o l / ) ;
37
69
} ) ;
38
70
39
71
it ( 'should throw an error if snapshot and causalConsistency options are both set to true' , function ( ) {
40
- const client = new Topology ( 'localhost:27017' , { } ) ;
72
+ const client = new Topology ( topologyHost , topologyOptions ) ;
41
73
sessionPool = client . s . sessionPool ;
42
74
expect (
43
75
( ) => new ClientSession ( client , sessionPool , { causalConsistency : true , snapshot : true } )
44
76
) . to . throw ( 'Properties "causalConsistency" and "snapshot" are mutually exclusive' ) ;
45
77
} ) ;
46
78
47
79
it ( 'should default to `null` for `clusterTime`' , function ( ) {
48
- const client = new Topology ( 'localhost:27017' , { } ) ;
80
+ const client = new Topology ( topologyHost , topologyOptions ) ;
49
81
sessionPool = client . s . sessionPool ;
50
- session = new ClientSession ( client , sessionPool ) ;
82
+ session = new ClientSession ( client , sessionPool , { } ) ;
51
83
expect ( session . clusterTime ) . to . not . exist ;
52
84
} ) ;
53
85
54
86
it ( 'should set the internal clusterTime to `initialClusterTime` if provided' , function ( ) {
55
87
const clusterTime = genClusterTime ( Date . now ( ) ) ;
56
- const client = new Topology ( 'localhost:27017' ) ;
88
+ const client = new Topology ( topologyHost , topologyOptions ) ;
57
89
sessionPool = client . s . sessionPool ;
58
90
session = new ClientSession ( client , sessionPool , { initialClusterTime : clusterTime } ) ;
59
91
expect ( session . clusterTime ) . to . eql ( clusterTime ) ;
60
92
} ) ;
61
93
94
+ it ( 'should not acquire a serverSession inside incrementTxnNumber' , ( ) => {
95
+ const client = new Topology ( topologyHost , topologyOptions ) ;
96
+ const sessionPool = client . s . sessionPool ;
97
+ const session = new ClientSession ( client , sessionPool , { } ) ;
98
+
99
+ const serverSessionSymbol = getSymbolFrom ( session , 'serverSession' ) ;
100
+ expect ( session ) . to . have . own . property ( serverSessionSymbol ) . that . is . null ;
101
+ session . incrementTransactionNumber ( ) ;
102
+ expect ( session ) . to . have . own . property ( serverSessionSymbol ) . that . is . null ;
103
+ } ) ;
104
+
105
+ it ( 'should acquire serverSession in getter' , ( ) => {
106
+ const client = new Topology ( topologyHost , topologyOptions ) ;
107
+ const sessionPool = client . s . sessionPool ;
108
+ const session = new ClientSession ( client , sessionPool , { } ) ;
109
+
110
+ const serverSessionSymbol = getSymbolFrom ( session , 'serverSession' ) ;
111
+ expect ( session ) . to . have . own . property ( serverSessionSymbol ) . that . is . null ;
112
+ const serverSession = session . serverSession ;
113
+ expect ( session ) . to . have . own . property ( serverSessionSymbol ) . that . equals ( serverSession ) ;
114
+ } ) ;
115
+
62
116
describe ( 'startTransaction()' , ( ) => {
63
117
it ( 'should throw an error if the session is snapshot enabled' , function ( ) {
64
- const client = new Topology ( 'localhost:27017' , { } ) ;
118
+ const client = new Topology ( topologyHost , topologyOptions ) ;
65
119
sessionPool = client . s . sessionPool ;
66
120
session = new ClientSession ( client , sessionPool , { snapshot : true } ) ;
67
121
expect ( session . snapshotEnabled ) . to . equal ( true ) ;
@@ -73,14 +127,15 @@ describe('Sessions - unit/core', function () {
73
127
74
128
describe ( 'advanceClusterTime()' , ( ) => {
75
129
beforeEach ( ( ) => {
76
- const client = new Topology ( 'localhost:27017' , { } ) ;
130
+ const client = new Topology ( topologyHost , topologyOptions ) ;
77
131
sessionPool = client . s . sessionPool ;
78
132
session = new ClientSession ( client , sessionPool , { } ) ;
79
133
} ) ;
80
134
81
135
it ( 'should throw an error if the input cluster time is not an object' , function ( ) {
82
136
const invalidInputs = [ undefined , null , 3 , 'a' ] ;
83
137
for ( const input of invalidInputs ) {
138
+ // @ts -expect-error: Testing for a runtime type assertion
84
139
expect ( ( ) => session . advanceClusterTime ( input ) ) . to . throw (
85
140
'input cluster time must be an object'
86
141
) ;
@@ -94,8 +149,11 @@ describe('Sessions - unit/core', function () {
94
149
95
150
delete invalidInputs [ 0 ] . clusterTime ;
96
151
invalidInputs [ 1 ] . clusterTime = null ;
152
+ // @ts -expect-error: Testing for a runtime type assertion
97
153
invalidInputs [ 2 ] . clusterTime = 5 ;
154
+ // @ts -expect-error: Testing for a runtime type assertion
98
155
invalidInputs [ 3 ] . clusterTime = 'not a timestamp' ;
156
+ // @ts -expect-error: Testing for a runtime type assertion
99
157
invalidInputs [ 4 ] . clusterTime = new Date ( '1' ) ;
100
158
101
159
for ( const input of invalidInputs ) {
@@ -120,9 +178,13 @@ describe('Sessions - unit/core', function () {
120
178
// invalid non-null types
121
179
// keyId must be number or BSON long
122
180
// hash must be BSON binary
181
+ // @ts -expect-error: Testing for a runtime type assertion
123
182
invalidInputs [ 5 ] . signature . keyId = { } ;
183
+ // @ts -expect-error: Testing for a runtime type assertion
124
184
invalidInputs [ 6 ] . signature . keyId = 'not BSON Long' ;
185
+ // @ts -expect-error: Testing for a runtime type assertion
125
186
invalidInputs [ 7 ] . signature . hash = 123 ;
187
+ // @ts -expect-error: Testing for a runtime type assertion
126
188
invalidInputs [ 8 ] . signature . hash = 'not BSON Binary' ;
127
189
128
190
for ( const input of invalidInputs ) {
@@ -148,7 +210,7 @@ describe('Sessions - unit/core', function () {
148
210
149
211
// extra test case for valid alternative keyId type in signature
150
212
const alsoValidTime = genClusterTime ( 200 ) ;
151
- alsoValidTime . signature . keyId = 10 ;
213
+ alsoValidTime . signature . keyId = Long . fromNumber ( 10 ) ;
152
214
session . clusterTime = null ;
153
215
expect ( session ) . property ( 'clusterTime' ) . to . be . null ;
154
216
session . advanceClusterTime ( alsoValidTime ) ;
@@ -183,7 +245,7 @@ describe('Sessions - unit/core', function () {
183
245
} ) ;
184
246
} ) ;
185
247
186
- describe ( 'ServerSessionPool' , function ( ) {
248
+ describe ( 'new ServerSessionPool() ' , function ( ) {
187
249
afterEach ( ( ) => {
188
250
test . client . close ( ) ;
189
251
return mock . cleanup ( ) ;
@@ -195,14 +257,14 @@ describe('Sessions - unit/core', function () {
195
257
. then ( server => {
196
258
test . server = server ;
197
259
test . server . setMessageHandler ( request => {
198
- var doc = request . document ;
260
+ const doc = request . document ;
199
261
if ( isHello ( doc ) ) {
200
262
request . reply ( Object . assign ( { } , mock . HELLO , { logicalSessionTimeoutMinutes : 10 } ) ) ;
201
263
}
202
264
} ) ;
203
265
} )
204
266
. then ( ( ) => {
205
- test . client = new Topology ( test . server . hostAddress ( ) ) ;
267
+ test . client = new Topology ( test . server . hostAddress ( ) , topologyOptions ) ;
206
268
207
269
return new Promise ( ( resolve , reject ) => {
208
270
test . client . once ( 'error' , reject ) ;
@@ -214,6 +276,7 @@ describe('Sessions - unit/core', function () {
214
276
215
277
it ( 'should throw errors with invalid parameters' , function ( ) {
216
278
expect ( ( ) => {
279
+ // @ts -expect-error: checking for a runtime type assertion
217
280
new ServerSessionPool ( ) ;
218
281
} ) . to . throw ( / S e r v e r S e s s i o n P o o l r e q u i r e s a t o p o l o g y / ) ;
219
282
} ) ;
0 commit comments