Skip to content

Commit bd853e6

Browse files
committed
add test to rediscovery
1 parent 1f7ea00 commit bd853e6

File tree

1 file changed

+186
-112
lines changed

1 file changed

+186
-112
lines changed

test/internal/rediscovery.test.js

Lines changed: 186 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -17,176 +17,250 @@
1717
* limitations under the License.
1818
*/
1919

20+
import RawRoutingTable from '../../src/internal/routing-table-raw'
2021
import Rediscovery from '../../src/internal/rediscovery'
2122
import RoutingTable from '../../src/internal/routing-table'
2223
import ServerAddress from '../../src/internal/server-address'
24+
import FakeConnection from './fake-connection'
25+
import lolex from 'lolex'
26+
import { int } from '../../src/integer'
27+
import { newError, SERVICE_UNAVAILABLE } from '../../lib/error'
2328

24-
xdescribe('#unit Rediscovery', () => {
29+
const PROCEDURE_NOT_FOUND_CODE = 'Neo.ClientError.Procedure.ProcedureNotFound'
30+
const DATABASE_NOT_FOUND_CODE = 'Neo.ClientError.Database.DatabaseNotFound'
31+
32+
describe('#unit Rediscovery', () => {
2533
it('should return the routing table when it available', async () => {
26-
const expectedRoutingTable = new RoutingTable({
27-
database: 'db',
28-
expirationTime: 113,
29-
routers: [ServerAddress.fromUrl('bolt://localhost:7687')],
30-
writers: [ServerAddress.fromUrl('bolt://localhost:7686')],
31-
readers: [ServerAddress.fromUrl('bolt://localhost:7683')]
34+
runWithClockAt(Date.now(), async () => {
35+
const ttl = int(123)
36+
const routers = ['bolt://localhost:7687']
37+
const writers = ['bolt://localhost:7686']
38+
const readers = ['bolt://localhost:7683']
39+
const initialAddress = '127.0.0.1'
40+
const routingContext = { context: '1234 ' }
41+
const rawRoutingTable = RawRoutingTable.ofMessageResponse(
42+
newMetadata({ ttl, routers, readers, writers })
43+
)
44+
45+
const expectedRoutingTable = new RoutingTable({
46+
database: 'db',
47+
expirationTime: calculateExpirationTime(Date.now(), ttl),
48+
routers: [ServerAddress.fromUrl('bolt://localhost:7687')],
49+
writers: [ServerAddress.fromUrl('bolt://localhost:7686')],
50+
readers: [ServerAddress.fromUrl('bolt://localhost:7683')]
51+
})
52+
53+
const routingTable = await lookupRoutingTableOnRouter({
54+
initialAddress,
55+
routingContext,
56+
rawRoutingTable
57+
})
58+
59+
expect(routingTable).toEqual(expectedRoutingTable)
3260
})
33-
const routingTableGetter = new FakeRoutingTableGetter(
34-
Promise.resolve(expectedRoutingTable)
35-
)
61+
})
62+
63+
it('should return the routing table null when it is not available', async () => {
64+
const initialAddress = '127.0.0.1'
65+
const routingContext = { context: '1234 ' }
66+
const rawRoutingTable = RawRoutingTable.ofNull()
3667

3768
const routingTable = await lookupRoutingTableOnRouter({
38-
routingTableGetter
69+
initialAddress,
70+
routingContext,
71+
rawRoutingTable
3972
})
4073

41-
expect(routingTable).toBe(expectedRoutingTable)
74+
expect(routingTable).toEqual(null)
4275
})
4376

44-
it('should call getter once with correct arguments', async () => {
45-
const expectedRoutingTable = new RoutingTable()
46-
const connection = { connection: 'abc' }
47-
const database = 'adb'
48-
const session = new FakeSession(connection)
49-
const routerAddress = ServerAddress.fromUrl('bolt://localhost:7682')
50-
const routingTableGetter = new FakeRoutingTableGetter(
51-
Promise.resolve(expectedRoutingTable)
77+
it('should call requestRoutingInformation with the correct params', async () => {
78+
const ttl = int(123)
79+
const routers = ['bolt://localhost:7687']
80+
const writers = ['bolt://localhost:7686']
81+
const readers = ['bolt://localhost:7683']
82+
const initialAddress = '127.0.0.1:1245'
83+
const routingContext = { context: '1234 ' }
84+
const database = 'this db'
85+
const rawRoutingTable = RawRoutingTable.ofMessageResponse(
86+
newMetadata({ ttl, routers, readers, writers })
87+
)
88+
const connection = new FakeConnection().withRequestRoutingInformationMock(
89+
fakeOnError(rawRoutingTable)
5290
)
91+
const session = new FakeSession(connection)
5392

5493
await lookupRoutingTableOnRouter({
55-
routingTableGetter,
56-
connection,
57-
session,
5894
database,
59-
routerAddress
95+
connection,
96+
initialAddress,
97+
routingContext,
98+
rawRoutingTable
6099
})
61100

62-
expect(routingTableGetter._called).toEqual(1)
63-
expect(routingTableGetter._arguments).toEqual([
64-
connection,
65-
database,
66-
routerAddress,
67-
session
68-
])
101+
expect(connection.seenRequestRoutingInformation.length).toEqual(1)
102+
const requestParams = connection.seenRequestRoutingInformation[0]
103+
expect(requestParams.routingContext).toEqual(routingContext)
104+
expect(requestParams.databaseName).toEqual(database)
105+
expect(requestParams.initialAddress).toEqual(initialAddress)
106+
expect(requestParams.sessionContext).toEqual({
107+
bookmark: session._lastBookmark,
108+
mode: session._mode,
109+
database: session._database,
110+
afterComplete: session._onComplete
111+
})
69112
})
70113

71-
it('should acquire connection once', async () => {
72-
const expectedRoutingTable = new RoutingTable()
73-
const connection = { connection: 'abc' }
74-
const database = 'adb'
75-
const session = new FakeSession(connection)
76-
const routerAddress = ServerAddress.fromUrl('bolt://localhost:7682')
77-
const routingTableGetter = new FakeRoutingTableGetter(
78-
Promise.resolve(expectedRoutingTable)
79-
)
114+
it('should reject with DATABASE_NOT_FOUND_CODE when it happens ', async () => {
115+
const expectedError = newError('Laia', DATABASE_NOT_FOUND_CODE)
116+
try {
117+
const initialAddress = '127.0.0.1'
118+
const routingContext = { context: '1234 ' }
80119

81-
await lookupRoutingTableOnRouter({
82-
routingTableGetter,
83-
connection,
84-
session,
85-
database,
86-
routerAddress
87-
})
120+
const connection = new FakeConnection().withRequestRoutingInformationMock(
121+
fakeOnError(expectedError)
122+
)
123+
await lookupRoutingTableOnRouter({
124+
initialAddress,
125+
routingContext,
126+
connection
127+
})
88128

89-
expect(session._called).toEqual(1)
129+
fail('it should fail')
130+
} catch (error) {
131+
expect(error).toEqual(expectedError)
132+
}
90133
})
91134

92-
it('should create the routingTableGetter with the correct arguments', async () => {
93-
const routingTable = new RoutingTable()
94-
const connection = { connection: 'abc' }
95-
const routingTableGetter = new FakeRoutingTableGetter(
96-
Promise.resolve(routingTable)
135+
it('should reject with PROCEDURE_NOT_FOUND_CODE when it happens ', async () => {
136+
const routerAddress = ServerAddress.fromUrl('bolt://localhost:1235')
137+
const expectedError = newError(
138+
`Server at ${routerAddress.asHostPort()} can't perform routing. Make sure you are connecting to a causal cluster`,
139+
SERVICE_UNAVAILABLE
97140
)
98-
const factory = new FakeRoutingTableGetterFactory(routingTableGetter)
141+
try {
142+
const initialAddress = '127.0.0.1'
143+
const routingContext = { context: '1234 ' }
99144

100-
await lookupRoutingTableOnRouter({
101-
routingTableGetter,
102-
factory,
103-
connection
104-
})
145+
const connection = new FakeConnection().withRequestRoutingInformationMock(
146+
fakeOnError(newError('1de', PROCEDURE_NOT_FOUND_CODE))
147+
)
148+
await lookupRoutingTableOnRouter({
149+
initialAddress,
150+
routingContext,
151+
connection,
152+
routerAddress
153+
})
105154

106-
expect(factory._called).toEqual(1)
107-
expect(factory._arguments).toEqual([connection])
155+
fail('it should fail')
156+
} catch (error) {
157+
expect(error).toEqual(expectedError)
158+
}
108159
})
109160

110-
it('should return null when the getter resolves the table as null', async () => {
111-
const routingTableGetter = new FakeRoutingTableGetter(Promise.resolve(null))
161+
it('should return null when it happens an unexpected error ocorrus', async () => {
162+
const initialAddress = '127.0.0.1'
163+
const routingContext = { context: '1234 ' }
112164

165+
const connection = new FakeConnection().withRequestRoutingInformationMock(
166+
fakeOnError(newError('1de', 'abc'))
167+
)
113168
const routingTable = await lookupRoutingTableOnRouter({
114-
routingTableGetter
169+
initialAddress,
170+
routingContext,
171+
connection
115172
})
116173

117-
expect(routingTable).toBeNull()
174+
expect(routingTable).toEqual(null)
118175
})
176+
})
119177

120-
it('should fail when the getter fails', async () => {
121-
const expectedError = 'error'
122-
try {
123-
const routingTableGetter = new FakeRoutingTableGetter(
124-
Promise.reject(expectedError)
125-
)
126-
await lookupRoutingTableOnRouter({ routingTableGetter })
127-
fail('should not complete with success')
128-
} catch (error) {
129-
expect(error).toBe(expectedError)
178+
function newMetadata ({
179+
ttl = int(42),
180+
routers = [],
181+
readers = [],
182+
writers = [],
183+
extra = []
184+
} = {}) {
185+
const routersField = {
186+
role: 'ROUTE',
187+
addresses: routers
188+
}
189+
const readersField = {
190+
role: 'READ',
191+
addresses: readers
192+
}
193+
const writersField = {
194+
role: 'WRITE',
195+
addresses: writers
196+
}
197+
return {
198+
rt: {
199+
ttl,
200+
servers: [routersField, readersField, writersField, ...extra]
130201
}
131-
})
132-
})
202+
}
203+
}
204+
205+
async function runWithClockAt (currentTime, callback) {
206+
const clock = lolex.install()
207+
try {
208+
clock.setSystemTime(currentTime)
209+
return await callback(currentTime)
210+
} finally {
211+
clock.uninstall()
212+
}
213+
}
214+
215+
function calculateExpirationTime (currentTime, ttl) {
216+
return int(currentTime + ttl.toNumber() * 1000)
217+
}
133218

134219
function lookupRoutingTableOnRouter ({
135220
database = 'db',
136221
routerAddress = ServerAddress.fromUrl('bolt://localhost:7687'),
137-
routingTableGetter = new FakeRoutingTableGetter(
138-
Promise.resolve(new RoutingTable())
139-
),
222+
routingContext = {},
223+
initialAddress = 'localhost:1235',
140224
session,
141-
factory,
142-
connection = {}
225+
connection = new FakeConnection(),
226+
rawRoutingTable
143227
} = {}) {
144-
const _factory =
145-
factory || new FakeRoutingTableGetterFactory(routingTableGetter)
146228
const _session = session || new FakeSession(connection)
147-
const rediscovery = new Rediscovery(_factory)
229+
230+
if (connection && rawRoutingTable) {
231+
connection.withRequestRoutingInformationMock(
232+
fakeOnCompleted(rawRoutingTable)
233+
)
234+
}
235+
236+
const rediscovery = new Rediscovery(routingContext, initialAddress)
148237

149238
return rediscovery.lookupRoutingTableOnRouter(
150239
_session,
151240
database,
152241
routerAddress
153242
)
154243
}
155-
156-
class FakeRoutingTableGetter {
157-
constructor (result) {
158-
this._result = result
159-
this._called = 0
160-
}
161-
162-
get () {
163-
this._called++
164-
this._arguments = [...arguments]
165-
return this._result
166-
}
167-
}
168-
169-
class FakeRoutingTableGetterFactory {
170-
constructor (routingTableGetter) {
171-
this._routingTableGetter = routingTableGetter
172-
this._called = 0
173-
}
174-
175-
create () {
176-
this._called++
177-
this._arguments = [...arguments]
178-
return this._routingTableGetter
179-
}
180-
}
181-
182244
class FakeSession {
183245
constructor (connection) {
184246
this._connection = connection
185247
this._called = 0
248+
this._lastBookmark = 'lastBook'
249+
this._mode = 'READ'
250+
this._database = 'session db'
251+
this._onComplete = 'moked'
186252
}
187253

188254
_acquireConnection (callback) {
189255
this._called++
190256
return callback(this._connection)
191257
}
192258
}
259+
260+
function fakeOnCompleted (raw = null) {
261+
return ({ onCompleted }) => onCompleted(raw)
262+
}
263+
264+
function fakeOnError (error) {
265+
return ({ onError }) => onError(error)
266+
}

0 commit comments

Comments
 (0)