UNPKG

11.7 kBJavaScriptView Raw
1'use strict'
2/* eslint-env mocha */
3/*eslint no-proto: 0*/
4
5const Promise = require('bluebird')
6const { expect } = require('chai')
7
8const { cleanup, clientConnect, closeInstance, nextTick,
9 parallel, setCustomCleanup, startService } = require('./testutils')
10
11const { cleanupTimeout, user1, roomName1 } = require('./config')
12
13module.exports = function () {
14 let instance1, socket1, socket2, socket3
15
16 afterEach(function (cb) {
17 this.timeout(cleanupTimeout)
18 cleanup([instance1], [socket1, socket2, socket3], cb)
19 instance1 = socket1 = socket2 = socket3 = null
20 })
21
22 it('should recover from rollback room join errors', function (done) {
23 instance1 = startService()
24 instance1.addRoom(roomName1, null, () => {
25 socket1 = clientConnect(user1)
26 socket1.on('loginConfirmed', (userName, { id }) => {
27 instance1.state.getUser(user1).then(user => {
28 let orig1 = user.userState.removeSocketFromRoom
29 let orig2 = user.userState.addSocketToRoom
30 setCustomCleanup(cb => {
31 user.userState.__proto__.removeSocketFromRoom = orig1
32 user.userState.__proto__.addSocketToRoom = orig2
33 closeInstance(instance1).asCallback(cb)
34 })
35 user.userState.__proto__.removeSocketFromRoom = function () {
36 return Promise.reject(new Error())
37 }
38 user.userState.__proto__.addSocketToRoom = function () {
39 return Promise.reject(
40 new Error('This is an error mockup for testing.'))
41 }
42 parallel([
43 cb => socket1.emit('roomJoin', roomName1, (error, data) => {
44 expect(error).ok
45 cb()
46 }),
47 cb => instance1.on('storeConsistencyFailure', (error, data) => {
48 nextTick(() => {
49 expect(error).ok
50 expect(data).an('Object')
51 expect(data).include.keys('roomName', 'userName', 'opType')
52 expect(data.roomName).equal(roomName1)
53 expect(data.userName).equal(user1)
54 expect(data.opType).equal('userRooms')
55 cb()
56 })
57 })
58 ], error => {
59 expect(error).not.ok
60 user.userState.__proto__.removeSocketFromRoom = orig1
61 user.userState.__proto__.addSocketToRoom = orig2
62 instance1.roomStateSync(roomName1)
63 .then(() => Promise.join(
64 instance1.execUserCommand(user1, 'listOwnSockets'),
65 instance1.execUserCommand(
66 true, 'roomGetAccessList', roomName1, 'userlist'),
67 (sockets, [list]) => {
68 expect(sockets[id]).an.array
69 expect(sockets[id]).empty
70 expect(list).empty
71 }).asCallback(done))
72 })
73 })
74 })
75 })
76 })
77
78 it('should recover from leave room errors', function (done) {
79 instance1 = startService()
80 instance1.addRoom(roomName1, null, () => {
81 socket1 = clientConnect(user1)
82 socket1.on('loginConfirmed', (userName, { id }) => {
83 socket1.emit('roomJoin', roomName1, () => {
84 instance1.state.getRoom(roomName1).then(room => {
85 let orig = room.leave
86 setCustomCleanup(cb => {
87 room.__proto__.leave = orig
88 closeInstance(instance1).asCallback(cb)
89 })
90 room.__proto__.leave = function () {
91 return Promise.reject(new Error())
92 }
93 parallel([
94 cb => socket1.emit('roomLeave', roomName1, (error, data) => {
95 expect(error).not.ok
96 cb()
97 }),
98 cb => instance1.on('storeConsistencyFailure', (error, data) => {
99 nextTick(() => {
100 expect(error).ok
101 expect(data).an('Object')
102 expect(data).include.keys('roomName', 'userName', 'opType')
103 expect(data.roomName).equal(roomName1)
104 expect(data.userName).equal(user1)
105 expect(data.opType).equal('roomUserlist')
106 cb()
107 })
108 })
109 ], error => {
110 expect(error).not.ok
111 room.__proto__.leave = orig
112 instance1.roomStateSync(roomName1)
113 .then(() => Promise.join(
114 instance1.execUserCommand(user1, 'listOwnSockets'),
115 instance1.execUserCommand(
116 true, 'roomGetAccessList', roomName1, 'userlist'),
117 ([sockets], [list]) => {
118 expect(sockets[id]).an.array
119 expect(sockets[id]).empty
120 expect(list).empty
121 }).asCallback(done))
122 })
123 })
124 })
125 })
126 })
127 })
128
129 it('should recover from remove socket errors', function (done) {
130 instance1 = startService()
131 instance1.addRoom(roomName1, null, () => {
132 socket1 = clientConnect(user1)
133 socket1.on('loginConfirmed', (userName, { id }) => {
134 socket1.emit('roomJoin', roomName1, () => {
135 instance1.state.getUser(user1).then(user => {
136 let orig = user.userState.removeSocket
137 setCustomCleanup(cb => {
138 user.userState.__proto__.removeSocket = orig
139 closeInstance(instance1).asCallback(cb)
140 })
141 user.userState.__proto__.removeSocket = function () {
142 return Promise.reject(new Error())
143 }
144 socket1.disconnect()
145 instance1.on('storeConsistencyFailure', (error, data) => {
146 nextTick(() => {
147 user.userState.__proto__.removeSocket = orig
148 expect(error).ok
149 expect(data).an('Object')
150 expect(data).include.keys('userName', 'id', 'opType')
151 expect(data.userName).equal(user1)
152 expect(data.id).equal(id)
153 expect(data.opType).equal('userSockets')
154 instance1.userStateSync(user1)
155 .then(() =>
156 instance1.execUserCommand(user1, 'listOwnSockets'))
157 .spread(sockets => expect(sockets).empty)
158 .asCallback(done)
159 })
160 })
161 })
162 })
163 })
164 })
165 })
166
167 it('should recover from remove from room errors', function (done) {
168 instance1 = startService()
169 instance1.addRoom(roomName1, null, () => {
170 socket1 = clientConnect(user1)
171 socket1.on('loginConfirmed', (userName, { id }) => {
172 socket1.emit('roomJoin', roomName1, () => {
173 instance1.state.getUser(user1).then(user => {
174 let orig = user.userState.removeAllSocketsFromRoom
175 setCustomCleanup(cb => {
176 user.userState.__proto__.removeAllSocketsFromRoom = orig
177 closeInstance(instance1).asCallback(cb)
178 })
179 user.userState.__proto__.removeAllSocketsFromRoom = function () {
180 return Promise.reject(new Error())
181 }
182 instance1.execUserCommand(
183 true, 'roomAddToList', roomName1, 'blacklist', [user1],
184 error => expect(error).not.ok)
185 instance1.on('storeConsistencyFailure', (error, data) => {
186 nextTick(() => {
187 user.userState.__proto__.removeAllSocketsFromRoom = orig
188 expect(error).ok
189 expect(data).an('Object')
190 expect(data).include.keys('roomName', 'userName', 'opType')
191 expect(data.roomName).equal(roomName1)
192 expect(data.userName).equal(user1)
193 expect(data.opType).equal('roomUserlist')
194 instance1.userStateSync(user1).then(() => {
195 return Promise.join(
196 instance1.execUserCommand(user1, 'listOwnSockets'),
197 instance1.execUserCommand(
198 true, 'roomGetAccessList', roomName1, 'userlist'),
199 ([sockets], [list]) => {
200 expect(sockets[id]).an.array
201 expect(sockets[id]).empty
202 expect(list).empty
203 })
204 }).asCallback(done)
205 })
206 })
207 })
208 })
209 })
210 })
211 })
212
213 it('should recover from room access check errors', function (done) {
214 instance1 = startService()
215 instance1.addRoom(roomName1, null, () => {
216 instance1.state.getRoom(roomName1).then(room => {
217 socket1 = clientConnect(user1)
218 socket1.on('loginConfirmed', (userName, { id }) => {
219 socket1.emit('roomJoin', roomName1, () => {
220 let orig = room.roomState.hasInList
221 room.roomState.__proto__.hasInList = function () {
222 return Promise.reject(new Error())
223 }
224 setCustomCleanup(cb => {
225 room.roomState.__proto__.hasInList = orig
226 closeInstance(instance1).asCallback(cb)
227 })
228 parallel([
229 cb => instance1.execUserCommand(
230 true, 'roomAddToList', roomName1, 'blacklist', [user1],
231 error => {
232 expect(error).not.ok
233 cb()
234 }),
235 cb => instance1.once('storeConsistencyFailure', (error, data) => {
236 nextTick(() => {
237 room.roomState.__proto__.hasInList = orig
238 expect(error).ok
239 expect(data).an('Object')
240 expect(data).include.keys('roomName', 'userName', 'opType')
241 expect(data.roomName).equal(roomName1)
242 expect(data.userName).equal(user1)
243 expect(data.opType).equal('roomUserlist')
244 return instance1.roomStateSync(roomName1).then(() => {
245 return instance1.execUserCommand(
246 true, 'roomGetAccessList', roomName1, 'userlist')
247 }).spread(list => {
248 expect(list).an('Array')
249 expect(list).empty
250 }).asCallback(cb)
251 })
252 })
253 ], done)
254 })
255 })
256 })
257 })
258 })
259
260 it('should emit consistencyFailure on leave channel errors', function (done) {
261 instance1 = startService()
262 let orig = instance1.transport.leaveChannel
263 instance1.transport.__proto__.leaveChannel = function () {
264 return Promise.reject(new Error())
265 }
266 setCustomCleanup(cb => {
267 instance1.transport.__proto__.leaveChannel = orig
268 closeInstance(instance1).asCallback(cb)
269 })
270 instance1.addRoom(roomName1, null, () => {
271 socket1 = clientConnect(user1)
272 socket1.on('loginConfirmed', (userName, { id }) => {
273 socket1.emit('roomJoin', roomName1, error => {
274 expect(error).not.ok
275 parallel([
276 cb => socket1.emit('roomLeave', roomName1, error => {
277 expect(error).not.ok
278 cb()
279 }),
280 cb => instance1.on('transportConsistencyFailure', (error, data) => {
281 nextTick(() => {
282 expect(error).ok
283 expect(data).an('Object')
284 expect(data).include.keys('roomName', 'userName'
285 , 'id', 'opType')
286 expect(data.roomName).equal(roomName1)
287 expect(data.userName).equal(user1)
288 expect(data.id).equal(id)
289 expect(data.opType).equal('transportChannel')
290 cb()
291 })
292 })
293 ], done)
294 })
295 })
296 })
297 })
298}