]>
git.proxmox.com Git - mirror_novnc.git/blob - tests/test.websock.js
1 /* jshint expr: true */
2 var assert
= chai
.assert
;
3 var expect
= chai
.expect
;
5 import Websock
from '../core/websock.js';
6 import FakeWebSocket
from './fake.websocket.js';
10 import sinonChai
from '../node_modules/sinon-chai/lib/sinon-chai.js'
13 describe('Websock', function() {
16 describe('Queue methods', function () {
18 var RQ_TEMPLATE
= new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7]);
20 beforeEach(function () {
23 sock
._allocate_buffers();
24 sock
._rQ
.set(RQ_TEMPLATE
);
25 sock
._rQlen
= RQ_TEMPLATE
.length
;
27 describe('rQlen', function () {
28 it('should return the length of the receive queue', function () {
31 expect(sock
.rQlen()).to
.equal(RQ_TEMPLATE
.length
);
34 it("should return the proper length if we read some from the receive queue", function () {
37 expect(sock
.rQlen()).to
.equal(RQ_TEMPLATE
.length
- 1);
41 describe('rQpeek8', function () {
42 it('should peek at the next byte without poping it off the queue', function () {
43 var bef_len
= sock
.rQlen();
44 var peek
= sock
.rQpeek8();
45 expect(sock
.rQpeek8()).to
.equal(peek
);
46 expect(sock
.rQlen()).to
.equal(bef_len
);
50 describe('rQshift8', function () {
51 it('should pop a single byte from the receive queue', function () {
52 var peek
= sock
.rQpeek8();
53 var bef_len
= sock
.rQlen();
54 expect(sock
.rQshift8()).to
.equal(peek
);
55 expect(sock
.rQlen()).to
.equal(bef_len
- 1);
59 describe('rQshift16', function () {
60 it('should pop two bytes from the receive queue and return a single number', function () {
61 var bef_len
= sock
.rQlen();
62 var expected
= (RQ_TEMPLATE
[0] << 8) + RQ_TEMPLATE
[1];
63 expect(sock
.rQshift16()).to
.equal(expected
);
64 expect(sock
.rQlen()).to
.equal(bef_len
- 2);
68 describe('rQshift32', function () {
69 it('should pop four bytes from the receive queue and return a single number', function () {
70 var bef_len
= sock
.rQlen();
71 var expected
= (RQ_TEMPLATE
[0] << 24) +
72 (RQ_TEMPLATE
[1] << 16) +
73 (RQ_TEMPLATE
[2] << 8) +
75 expect(sock
.rQshift32()).to
.equal(expected
);
76 expect(sock
.rQlen()).to
.equal(bef_len
- 4);
80 describe('rQshiftStr', function () {
81 it('should shift the given number of bytes off of the receive queue and return a string', function () {
82 var bef_len
= sock
.rQlen();
83 var bef_rQi
= sock
.get_rQi();
84 var shifted
= sock
.rQshiftStr(3);
85 expect(shifted
).to
.be
.a('string');
86 expect(shifted
).to
.equal(String
.fromCharCode
.apply(null, Array
.prototype.slice
.call(new Uint8Array(RQ_TEMPLATE
.buffer
, bef_rQi
, 3))));
87 expect(sock
.rQlen()).to
.equal(bef_len
- 3);
90 it('should shift the entire rest of the queue off if no length is given', function () {
92 expect(sock
.rQlen()).to
.equal(0);
96 describe('rQshiftBytes', function () {
97 it('should shift the given number of bytes of the receive queue and return an array', function () {
98 var bef_len
= sock
.rQlen();
99 var bef_rQi
= sock
.get_rQi();
100 var shifted
= sock
.rQshiftBytes(3);
101 expect(shifted
).to
.be
.an
.instanceof(Uint8Array
);
102 expect(shifted
).to
.array
.equal(new Uint8Array(RQ_TEMPLATE
.buffer
, bef_rQi
, 3));
103 expect(sock
.rQlen()).to
.equal(bef_len
- 3);
106 it('should shift the entire rest of the queue off if no length is given', function () {
108 expect(sock
.rQlen()).to
.equal(0);
112 describe('rQslice', function () {
113 beforeEach(function () {
117 it('should not modify the receive queue', function () {
118 var bef_len
= sock
.rQlen();
120 expect(sock
.rQlen()).to
.equal(bef_len
);
123 it('should return an array containing the given slice of the receive queue', function () {
124 var sl
= sock
.rQslice(0, 2);
125 expect(sl
).to
.be
.an
.instanceof(Uint8Array
);
126 expect(sl
).to
.array
.equal(new Uint8Array(RQ_TEMPLATE
.buffer
, 0, 2));
129 it('should use the rest of the receive queue if no end is given', function () {
130 var sl
= sock
.rQslice(1);
131 expect(sl
).to
.have
.length(RQ_TEMPLATE
.length
- 1);
132 expect(sl
).to
.array
.equal(new Uint8Array(RQ_TEMPLATE
.buffer
, 1));
135 it('should take the current rQi in to account', function () {
137 expect(sock
.rQslice(0, 2)).to
.array
.equal(new Uint8Array(RQ_TEMPLATE
.buffer
, 1, 2));
141 describe('rQwait', function () {
142 beforeEach(function () {
146 it('should return true if there are not enough bytes in the receive queue', function () {
147 expect(sock
.rQwait('hi', RQ_TEMPLATE
.length
+ 1)).to
.be
.true;
150 it('should return false if there are enough bytes in the receive queue', function () {
151 expect(sock
.rQwait('hi', RQ_TEMPLATE
.length
)).to
.be
.false;
154 it('should return true and reduce rQi by "goback" if there are not enough bytes', function () {
156 expect(sock
.rQwait('hi', RQ_TEMPLATE
.length
, 4)).to
.be
.true;
157 expect(sock
.get_rQi()).to
.equal(1);
160 it('should raise an error if we try to go back more than possible', function () {
162 expect(function () { sock
.rQwait('hi', RQ_TEMPLATE
.length
, 6); }).to
.throw(Error
);
165 it('should not reduce rQi if there are enough bytes', function () {
167 sock
.rQwait('hi', 1, 6);
168 expect(sock
.get_rQi()).to
.equal(5);
172 describe('flush', function () {
173 beforeEach(function () {
179 it('should actually send on the websocket', function () {
180 sock
._websocket
.bufferedAmount
= 8;
181 sock
._websocket
.readyState
= WebSocket
.OPEN
182 sock
._sQ
= new Uint8Array([1, 2, 3]);
184 var encoded
= sock
._encode_message();
187 expect(sock
._websocket
.send
).to
.have
.been
.calledOnce
;
188 expect(sock
._websocket
.send
).to
.have
.been
.calledWith(encoded
);
191 it('should not call send if we do not have anything queued up', function () {
193 sock
._websocket
.bufferedAmount
= 8;
197 expect(sock
._websocket
.send
).not
.to
.have
.been
.called
;
201 describe('send', function () {
202 beforeEach(function () {
203 sock
.flush
= sinon
.spy();
206 it('should add to the send queue', function () {
207 sock
.send([1, 2, 3]);
208 var sq
= sock
.get_sQ();
209 expect(new Uint8Array(sq
.buffer
, sock
._sQlen
- 3, 3)).to
.array
.equal(new Uint8Array([1, 2, 3]));
212 it('should call flush', function () {
213 sock
.send([1, 2, 3]);
214 expect(sock
.flush
).to
.have
.been
.calledOnce
;
218 describe('send_string', function () {
219 beforeEach(function () {
220 sock
.send
= sinon
.spy();
223 it('should call send after converting the string to an array', function () {
224 sock
.send_string("\x01\x02\x03");
225 expect(sock
.send
).to
.have
.been
.calledWith([1, 2, 3]);
230 describe('lifecycle methods', function () {
237 beforeEach(function () {
238 sock
= new Websock();
239 WebSocket
= sinon
.spy();
240 WebSocket
.OPEN
= old_WS
.OPEN
;
241 WebSocket
.CONNECTING
= old_WS
.CONNECTING
;
242 WebSocket
.CLOSING
= old_WS
.CLOSING
;
243 WebSocket
.CLOSED
= old_WS
.CLOSED
;
245 WebSocket
.prototype.binaryType
= 'arraybuffer';
248 describe('opening', function () {
249 it('should pick the correct protocols if none are given' , function () {
253 it('should open the actual websocket', function () {
254 sock
.open('ws://localhost:8675', 'binary');
255 expect(WebSocket
).to
.have
.been
.calledWith('ws://localhost:8675', 'binary');
258 // it('should initialize the event handlers')?
261 describe('closing', function () {
262 beforeEach(function () {
264 sock
._websocket
.close
= sinon
.spy();
267 it('should close the actual websocket if it is open', function () {
268 sock
._websocket
.readyState
= WebSocket
.OPEN
;
270 expect(sock
._websocket
.close
).to
.have
.been
.calledOnce
;
273 it('should close the actual websocket if it is connecting', function () {
274 sock
._websocket
.readyState
= WebSocket
.CONNECTING
;
276 expect(sock
._websocket
.close
).to
.have
.been
.calledOnce
;
279 it('should not try to close the actual websocket if closing', function () {
280 sock
._websocket
.readyState
= WebSocket
.CLOSING
;
282 expect(sock
._websocket
.close
).not
.to
.have
.been
.called
;
285 it('should not try to close the actual websocket if closed', function () {
286 sock
._websocket
.readyState
= WebSocket
.CLOSED
;
288 expect(sock
._websocket
.close
).not
.to
.have
.been
.called
;
291 it('should reset onmessage to not call _recv_message', function () {
292 sinon
.spy(sock
, '_recv_message');
294 sock
._websocket
.onmessage(null);
296 expect(sock
._recv_message
).not
.to
.have
.been
.called
;
298 sock
._recv_message
.restore();
303 describe('event handlers', function () {
304 beforeEach(function () {
305 sock
._recv_message
= sinon
.spy();
306 sock
.on('open', sinon
.spy());
307 sock
.on('close', sinon
.spy());
308 sock
.on('error', sinon
.spy());
312 it('should call _recv_message on a message', function () {
313 sock
._websocket
.onmessage(null);
314 expect(sock
._recv_message
).to
.have
.been
.calledOnce
;
317 it('should call the open event handler on opening', function () {
318 sock
._websocket
.onopen();
319 expect(sock
._eventHandlers
.open
).to
.have
.been
.calledOnce
;
322 it('should call the close event handler on closing', function () {
323 sock
._websocket
.onclose();
324 expect(sock
._eventHandlers
.close
).to
.have
.been
.calledOnce
;
327 it('should call the error event handler on error', function () {
328 sock
._websocket
.onerror();
329 expect(sock
._eventHandlers
.error
).to
.have
.been
.calledOnce
;
338 describe('WebSocket Receiving', function () {
340 beforeEach(function () {
341 sock
= new Websock();
342 sock
._allocate_buffers();
345 it('should support adding binary Uint8Array data to the receive queue', function () {
346 var msg
= { data
: new Uint8Array([1, 2, 3]) };
347 sock
._mode
= 'binary';
348 sock
._recv_message(msg
);
349 expect(sock
.rQshiftStr(3)).to
.equal('\x01\x02\x03');
352 it('should call the message event handler if present', function () {
353 sock
._eventHandlers
.message
= sinon
.spy();
354 var msg
= { data
: new Uint8Array([1, 2, 3]).buffer
};
355 sock
._mode
= 'binary';
356 sock
._recv_message(msg
);
357 expect(sock
._eventHandlers
.message
).to
.have
.been
.calledOnce
;
360 it('should not call the message event handler if there is nothing in the receive queue', function () {
361 sock
._eventHandlers
.message
= sinon
.spy();
362 var msg
= { data
: new Uint8Array([]).buffer
};
363 sock
._mode
= 'binary';
364 sock
._recv_message(msg
);
365 expect(sock
._eventHandlers
.message
).not
.to
.have
.been
.called
;
368 it('should compact the receive queue', function () {
369 // NB(sross): while this is an internal implementation detail, it's important to
370 // test, otherwise the receive queue could become very large very quickly
371 sock
._rQ
= new Uint8Array([0, 1, 2, 3, 4, 5, 0, 0, 0, 0]);
375 var msg
= { data
: new Uint8Array([1, 2, 3]).buffer
};
376 sock
._mode
= 'binary';
377 sock
._recv_message(msg
);
378 expect(sock
._rQlen
).to
.equal(3);
379 expect(sock
.get_rQi()).to
.equal(0);
382 it('should automatically resize the receive queue if the incoming message is too large', function () {
383 sock
._rQ
= new Uint8Array(20);
386 sock
._rQbufferSize
= 20;
388 var msg
= { data
: new Uint8Array(30).buffer
};
389 sock
._mode
= 'binary';
390 sock
._recv_message(msg
);
391 expect(sock
._rQlen
).to
.equal(30);
392 expect(sock
.get_rQi()).to
.equal(0);
393 expect(sock
._rQ
.length
).to
.equal(240); // keep the invariant that rQbufferSize / 8 >= rQlen
396 it('should call the error event handler on an exception', function () {
397 sock
._eventHandlers
.error
= sinon
.spy();
398 sock
._eventHandlers
.message
= sinon
.stub().throws();
399 var msg
= { data
: new Uint8Array([1, 2, 3]).buffer
};
400 sock
._mode
= 'binary';
401 sock
._recv_message(msg
);
402 expect(sock
._eventHandlers
.error
).to
.have
.been
.calledOnce
;
406 describe('Data encoding', function () {
407 before(function () { FakeWebSocket
.replace(); });
408 after(function () { FakeWebSocket
.restore(); });
410 describe('as binary data', function () {
412 beforeEach(function () {
413 sock
= new Websock();
414 sock
.open('ws://', 'binary');
415 sock
._websocket
._open();
418 it('should only send the send queue up to the send queue length', function () {
419 sock
._sQ
= new Uint8Array([1, 2, 3, 4, 5]);
421 var res
= sock
._encode_message();
422 expect(res
).to
.array
.equal(new Uint8Array([1, 2, 3]));
425 it('should properly pass the encoded data off to the actual WebSocket', function () {
426 sock
.send([1, 2, 3]);
427 expect(sock
._websocket
._get_sent_data()).to
.array
.equal(new Uint8Array([1, 2, 3]));