UNPKG

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