]>
git.proxmox.com Git - mirror_novnc.git/blob - tests/test.websock.js
1 const expect
= chai
. expect
;
3 import Websock
from '../core/websock.js' ;
4 import FakeWebSocket
from './fake.websocket.js' ;
6 describe ( 'Websock' , function () {
9 describe ( 'Queue methods' , function () {
11 const RQ_TEMPLATE
= new Uint8Array ([ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 ]);
13 beforeEach ( function () {
16 sock
. _allocateBuffers ();
17 sock
. _rQ
. set ( RQ_TEMPLATE
);
18 sock
. _rQlen
= RQ_TEMPLATE
. length
;
20 describe ( 'rQlen' , function () {
21 it ( 'should return the length of the receive queue' , function () {
24 expect ( sock
. rQlen
). to
. equal ( RQ_TEMPLATE
. length
);
27 it ( "should return the proper length if we read some from the receive queue" , function () {
30 expect ( sock
. rQlen
). to
. equal ( RQ_TEMPLATE
. length
- 1 );
34 describe ( 'rQpeek8' , function () {
35 it ( 'should peek at the next byte without poping it off the queue' , function () {
36 const befLen
= sock
. rQlen
;
37 const peek
= sock
. rQpeek8 ();
38 expect ( sock
. rQpeek8 ()). to
. equal ( peek
);
39 expect ( sock
. rQlen
). to
. equal ( befLen
);
43 describe ( 'rQshift8()' , function () {
44 it ( 'should pop a single byte from the receive queue' , function () {
45 const peek
= sock
. rQpeek8 ();
46 const befLen
= sock
. rQlen
;
47 expect ( sock
. rQshift8 ()). to
. equal ( peek
);
48 expect ( sock
. rQlen
). to
. equal ( befLen
- 1 );
52 describe ( 'rQshift16()' , function () {
53 it ( 'should pop two bytes from the receive queue and return a single number' , function () {
54 const befLen
= sock
. rQlen
;
55 const expected
= ( RQ_TEMPLATE
[ 0 ] << 8 ) + RQ_TEMPLATE
[ 1 ];
56 expect ( sock
. rQshift16 ()). to
. equal ( expected
);
57 expect ( sock
. rQlen
). to
. equal ( befLen
- 2 );
61 describe ( 'rQshift32()' , function () {
62 it ( 'should pop four bytes from the receive queue and return a single number' , function () {
63 const befLen
= sock
. rQlen
;
64 const expected
= ( RQ_TEMPLATE
[ 0 ] << 24 ) +
65 ( RQ_TEMPLATE
[ 1 ] << 16 ) +
66 ( RQ_TEMPLATE
[ 2 ] << 8 ) +
68 expect ( sock
. rQshift32 ()). to
. equal ( expected
);
69 expect ( sock
. rQlen
). to
. equal ( befLen
- 4 );
73 describe ( 'rQshiftStr' , function () {
74 it ( 'should shift the given number of bytes off of the receive queue and return a string' , function () {
75 const befLen
= sock
. rQlen
;
76 const befRQi
= sock
. rQi
;
77 const shifted
= sock
. rQshiftStr ( 3 );
78 expect ( shifted
). to
. be
. a ( 'string' );
79 expect ( shifted
). to
. equal ( String
. fromCharCode
. apply ( null , Array
. prototype . slice
. call ( new Uint8Array ( RQ_TEMPLATE
. buffer
, befRQi
, 3 ))));
80 expect ( sock
. rQlen
). to
. equal ( befLen
- 3 );
83 it ( 'should shift the entire rest of the queue off if no length is given' , function () {
85 expect ( sock
. rQlen
). to
. equal ( 0 );
88 it ( 'should be able to handle very large strings' , function () {
89 const BIG_LEN
= 500000 ;
90 const RQ_BIG
= new Uint8Array ( BIG_LEN
);
92 let letterCode
= 'a' . charCodeAt ( 0 );
93 for ( let i
= 0 ; i
< BIG_LEN
; i
++) {
94 RQ_BIG
[ i
] = letterCode
;
95 expected
+= String
. fromCharCode ( letterCode
);
97 if ( letterCode
< 'z' . charCodeAt ( 0 )) {
100 letterCode
= 'a' . charCodeAt ( 0 );
103 sock
. _rQ
. set ( RQ_BIG
);
104 sock
. _rQlen
= RQ_BIG
. length
;
106 const shifted
= sock
. rQshiftStr ();
108 expect ( shifted
). to
. be
. equal ( expected
);
109 expect ( sock
. rQlen
). to
. equal ( 0 );
113 describe ( 'rQshiftBytes' , function () {
114 it ( 'should shift the given number of bytes of the receive queue and return an array' , function () {
115 const befLen
= sock
. rQlen
;
116 const befRQi
= sock
. rQi
;
117 const shifted
= sock
. rQshiftBytes ( 3 );
118 expect ( shifted
). to
. be
. an
. instanceof ( Uint8Array
);
119 expect ( shifted
). to
. array
. equal ( new Uint8Array ( RQ_TEMPLATE
. buffer
, befRQi
, 3 ));
120 expect ( sock
. rQlen
). to
. equal ( befLen
- 3 );
123 it ( 'should shift the entire rest of the queue off if no length is given' , function () {
125 expect ( sock
. rQlen
). to
. equal ( 0 );
129 describe ( 'rQslice' , function () {
130 beforeEach ( function () {
134 it ( 'should not modify the receive queue' , function () {
135 const befLen
= sock
. rQlen
;
137 expect ( sock
. rQlen
). to
. equal ( befLen
);
140 it ( 'should return an array containing the given slice of the receive queue' , function () {
141 const sl
= sock
. rQslice ( 0 , 2 );
142 expect ( sl
). to
. be
. an
. instanceof ( Uint8Array
);
143 expect ( sl
). to
. array
. equal ( new Uint8Array ( RQ_TEMPLATE
. buffer
, 0 , 2 ));
146 it ( 'should use the rest of the receive queue if no end is given' , function () {
147 const sl
= sock
. rQslice ( 1 );
148 expect ( sl
). to
. have
. length ( RQ_TEMPLATE
. length
- 1 );
149 expect ( sl
). to
. array
. equal ( new Uint8Array ( RQ_TEMPLATE
. buffer
, 1 ));
152 it ( 'should take the current rQi in to account' , function () {
154 expect ( sock
. rQslice ( 0 , 2 )). to
. array
. equal ( new Uint8Array ( RQ_TEMPLATE
. buffer
, 1 , 2 ));
158 describe ( 'rQwait' , function () {
159 beforeEach ( function () {
163 it ( 'should return true if there are not enough bytes in the receive queue' , function () {
164 expect ( sock
. rQwait ( 'hi' , RQ_TEMPLATE
. length
+ 1 )). to
. be
. true ;
167 it ( 'should return false if there are enough bytes in the receive queue' , function () {
168 expect ( sock
. rQwait ( 'hi' , RQ_TEMPLATE
. length
)). to
. be
. false ;
171 it ( 'should return true and reduce rQi by "goback" if there are not enough bytes' , function () {
173 expect ( sock
. rQwait ( 'hi' , RQ_TEMPLATE
. length
, 4 )). to
. be
. true ;
174 expect ( sock
. rQi
). to
. equal ( 1 );
177 it ( 'should raise an error if we try to go back more than possible' , function () {
179 expect (() => sock
. rQwait ( 'hi' , RQ_TEMPLATE
. length
, 6 )). to
. throw ( Error
);
182 it ( 'should not reduce rQi if there are enough bytes' , function () {
184 sock
. rQwait ( 'hi' , 1 , 6 );
185 expect ( sock
. rQi
). to
. equal ( 5 );
189 describe ( 'flush' , function () {
190 beforeEach ( function () {
196 it ( 'should actually send on the websocket' , function () {
197 sock
. _websocket
. bufferedAmount
= 8 ;
198 sock
. _websocket
. readyState
= WebSocket
. OPEN
;
199 sock
. _sQ
= new Uint8Array ([ 1 , 2 , 3 ]);
201 const encoded
= sock
. _encodeMessage ();
204 expect ( sock
. _websocket
. send
). to
. have
. been
. calledOnce
;
205 expect ( sock
. _websocket
. send
). to
. have
. been
. calledWith ( encoded
);
208 it ( 'should not call send if we do not have anything queued up' , function () {
210 sock
. _websocket
. bufferedAmount
= 8 ;
214 expect ( sock
. _websocket
. send
). not
. to
. have
. been
. called
;
218 describe ( 'send' , function () {
219 beforeEach ( function () {
220 sock
. flush
= sinon
. spy ();
223 it ( 'should add to the send queue' , function () {
224 sock
. send ([ 1 , 2 , 3 ]);
226 expect ( new Uint8Array ( sq
. buffer
, sock
. _sQlen
- 3 , 3 )). to
. array
. equal ( new Uint8Array ([ 1 , 2 , 3 ]));
229 it ( 'should call flush' , function () {
230 sock
. send ([ 1 , 2 , 3 ]);
231 expect ( sock
. flush
). to
. have
. been
. calledOnce
;
235 describe ( 'sendString' , function () {
236 beforeEach ( function () {
237 sock
. send
= sinon
. spy ();
240 it ( 'should call send after converting the string to an array' , function () {
241 sock
. sendString ( " \x01\x02\x03 " );
242 expect ( sock
. send
). to
. have
. been
. calledWith ([ 1 , 2 , 3 ]);
247 describe ( 'lifecycle methods' , function () {
254 beforeEach ( function () {
255 sock
= new Websock ();
256 // eslint-disable-next-line no-global-assign
257 WebSocket
= sinon
. spy ( FakeWebSocket
);
260 describe ( 'opening' , function () {
261 it ( 'should pick the correct protocols if none are given' , function () {
265 it ( 'should open the actual websocket' , function () {
266 sock
. open ( 'ws://localhost:8675' , 'binary' );
267 expect ( WebSocket
). to
. have
. been
. calledWith ( 'ws://localhost:8675' , 'binary' );
270 // it('should initialize the event handlers')?
273 describe ( 'attaching' , function () {
274 it ( 'should attach to an existing websocket' , function () {
275 let ws
= new FakeWebSocket ( 'ws://localhost:8675' );
277 expect ( WebSocket
). to
. not
. have
. been
. called
;
281 describe ( 'closing' , function () {
282 beforeEach ( function () {
283 sock
. open ( 'ws://localhost' );
284 sock
. _websocket
. close
= sinon
. spy ();
287 it ( 'should close the actual websocket if it is open' , function () {
288 sock
. _websocket
. readyState
= WebSocket
. OPEN
;
290 expect ( sock
. _websocket
. close
). to
. have
. been
. calledOnce
;
293 it ( 'should close the actual websocket if it is connecting' , function () {
294 sock
. _websocket
. readyState
= WebSocket
. CONNECTING
;
296 expect ( sock
. _websocket
. close
). to
. have
. been
. calledOnce
;
299 it ( 'should not try to close the actual websocket if closing' , function () {
300 sock
. _websocket
. readyState
= WebSocket
. CLOSING
;
302 expect ( sock
. _websocket
. close
). not
. to
. have
. been
. called
;
305 it ( 'should not try to close the actual websocket if closed' , function () {
306 sock
. _websocket
. readyState
= WebSocket
. CLOSED
;
308 expect ( sock
. _websocket
. close
). not
. to
. have
. been
. called
;
311 it ( 'should reset onmessage to not call _recvMessage' , function () {
312 sinon
. spy ( sock
, '_recvMessage' );
314 sock
. _websocket
. onmessage ( null );
316 expect ( sock
. _recvMessage
). not
. to
. have
. been
. called
;
318 sock
. _recvMessage
. restore ();
323 describe ( 'event handlers' , function () {
324 beforeEach ( function () {
325 sock
. _recvMessage
= sinon
. spy ();
326 sock
. on ( 'open' , sinon
. spy ());
327 sock
. on ( 'close' , sinon
. spy ());
328 sock
. on ( 'error' , sinon
. spy ());
329 sock
. open ( 'ws://localhost' );
332 it ( 'should call _recvMessage on a message' , function () {
333 sock
. _websocket
. onmessage ( null );
334 expect ( sock
. _recvMessage
). to
. have
. been
. calledOnce
;
337 it ( 'should call the open event handler on opening' , function () {
338 sock
. _websocket
. onopen ();
339 expect ( sock
. _eventHandlers
. open
). to
. have
. been
. calledOnce
;
342 it ( 'should call the close event handler on closing' , function () {
343 sock
. _websocket
. onclose ();
344 expect ( sock
. _eventHandlers
. close
). to
. have
. been
. calledOnce
;
347 it ( 'should call the error event handler on error' , function () {
348 sock
. _websocket
. onerror ();
349 expect ( sock
. _eventHandlers
. error
). to
. have
. been
. calledOnce
;
353 describe ( 'ready state' , function () {
354 it ( 'should be "unused" after construction' , function () {
355 let sock
= new Websock ();
356 expect ( sock
. readyState
). to
. equal ( 'unused' );
359 it ( 'should be "connecting" if WebSocket is connecting' , function () {
360 let sock
= new Websock ();
361 let ws
= new FakeWebSocket ();
362 ws
. readyState
= WebSocket
. CONNECTING
;
364 expect ( sock
. readyState
). to
. equal ( 'connecting' );
367 it ( 'should be "open" if WebSocket is open' , function () {
368 let sock
= new Websock ();
369 let ws
= new FakeWebSocket ();
370 ws
. readyState
= WebSocket
. OPEN
;
372 expect ( sock
. readyState
). to
. equal ( 'open' );
375 it ( 'should be "closing" if WebSocket is closing' , function () {
376 let sock
= new Websock ();
377 let ws
= new FakeWebSocket ();
378 ws
. readyState
= WebSocket
. CLOSING
;
380 expect ( sock
. readyState
). to
. equal ( 'closing' );
383 it ( 'should be "closed" if WebSocket is closed' , function () {
384 let sock
= new Websock ();
385 let ws
= new FakeWebSocket ();
386 ws
. readyState
= WebSocket
. CLOSED
;
388 expect ( sock
. readyState
). to
. equal ( 'closed' );
391 it ( 'should be "unknown" if WebSocket state is unknown' , function () {
392 let sock
= new Websock ();
393 let ws
= new FakeWebSocket ();
396 expect ( sock
. readyState
). to
. equal ( 'unknown' );
399 it ( 'should be "connecting" if RTCDataChannel is connecting' , function () {
400 let sock
= new Websock ();
401 let ws
= new FakeWebSocket ();
402 ws
. readyState
= 'connecting' ;
404 expect ( sock
. readyState
). to
. equal ( 'connecting' );
407 it ( 'should be "open" if RTCDataChannel is open' , function () {
408 let sock
= new Websock ();
409 let ws
= new FakeWebSocket ();
410 ws
. readyState
= 'open' ;
412 expect ( sock
. readyState
). to
. equal ( 'open' );
415 it ( 'should be "closing" if RTCDataChannel is closing' , function () {
416 let sock
= new Websock ();
417 let ws
= new FakeWebSocket ();
418 ws
. readyState
= 'closing' ;
420 expect ( sock
. readyState
). to
. equal ( 'closing' );
423 it ( 'should be "closed" if RTCDataChannel is closed' , function () {
424 let sock
= new Websock ();
425 let ws
= new FakeWebSocket ();
426 ws
. readyState
= 'closed' ;
428 expect ( sock
. readyState
). to
. equal ( 'closed' );
431 it ( 'should be "unknown" if RTCDataChannel state is unknown' , function () {
432 let sock
= new Websock ();
433 let ws
= new FakeWebSocket ();
434 ws
. readyState
= 'foobar' ;
436 expect ( sock
. readyState
). to
. equal ( 'unknown' );
441 // eslint-disable-next-line no-global-assign
446 describe ( 'WebSocket Receiving' , function () {
448 beforeEach ( function () {
449 sock
= new Websock ();
450 sock
. _allocateBuffers ();
453 it ( 'should support adding binary Uint8Array data to the receive queue' , function () {
454 const msg
= { data
: new Uint8Array ([ 1 , 2 , 3 ]) };
455 sock
. _mode
= 'binary' ;
456 sock
. _recvMessage ( msg
);
457 expect ( sock
. rQshiftStr ( 3 )). to
. equal ( ' \x01\x02\x03 ' );
460 it ( 'should call the message event handler if present' , function () {
461 sock
. _eventHandlers
. message
= sinon
. spy ();
462 const msg
= { data
: new Uint8Array ([ 1 , 2 , 3 ]). buffer
};
463 sock
. _mode
= 'binary' ;
464 sock
. _recvMessage ( msg
);
465 expect ( sock
. _eventHandlers
. message
). to
. have
. been
. calledOnce
;
468 it ( 'should not call the message event handler if there is nothing in the receive queue' , function () {
469 sock
. _eventHandlers
. message
= sinon
. spy ();
470 const msg
= { data
: new Uint8Array ([]). buffer
};
471 sock
. _mode
= 'binary' ;
472 sock
. _recvMessage ( msg
);
473 expect ( sock
. _eventHandlers
. message
). not
. to
. have
. been
. called
;
476 it ( 'should compact the receive queue when a message handler empties it' , function () {
477 sock
. _eventHandlers
. message
= () => { sock
. rQi
= sock
. _rQlen
; };
478 sock
. _rQ
= new Uint8Array ([ 0 , 1 , 2 , 3 , 4 , 5 , 0 , 0 , 0 , 0 ]);
481 const msg
= { data
: new Uint8Array ([ 1 , 2 , 3 ]). buffer
};
482 sock
. _mode
= 'binary' ;
483 sock
. _recvMessage ( msg
);
484 expect ( sock
. _rQlen
). to
. equal ( 0 );
485 expect ( sock
. rQi
). to
. equal ( 0 );
488 it ( 'should compact the receive queue when we reach the end of the buffer' , function () {
489 sock
. _rQ
= new Uint8Array ( 20 );
490 sock
. _rQbufferSize
= 20 ;
493 const msg
= { data
: new Uint8Array ([ 1 , 2 ]). buffer
};
494 sock
. _mode
= 'binary' ;
495 sock
. _recvMessage ( msg
);
496 expect ( sock
. _rQlen
). to
. equal ( 12 );
497 expect ( sock
. rQi
). to
. equal ( 0 );
500 it ( 'should automatically resize the receive queue if the incoming message is larger than the buffer' , function () {
501 sock
. _rQ
= new Uint8Array ( 20 );
504 sock
. _rQbufferSize
= 20 ;
505 const msg
= { data
: new Uint8Array ( 30 ). buffer
};
506 sock
. _mode
= 'binary' ;
507 sock
. _recvMessage ( msg
);
508 expect ( sock
. _rQlen
). to
. equal ( 30 );
509 expect ( sock
. rQi
). to
. equal ( 0 );
510 expect ( sock
. _rQ
. length
). to
. equal ( 240 ); // keep the invariant that rQbufferSize / 8 >= rQlen
513 it ( 'should automatically resize the receive queue if the incoming message is larger than 1/8th of the buffer and we reach the end of the buffer' , function () {
514 sock
. _rQ
= new Uint8Array ( 20 );
517 sock
. _rQbufferSize
= 20 ;
518 const msg
= { data
: new Uint8Array ( 6 ). buffer
};
519 sock
. _mode
= 'binary' ;
520 sock
. _recvMessage ( msg
);
521 expect ( sock
. _rQlen
). to
. equal ( 6 );
522 expect ( sock
. rQi
). to
. equal ( 0 );
523 expect ( sock
. _rQ
. length
). to
. equal ( 48 );
527 describe ( 'Data encoding' , function () {
528 before ( function () { FakeWebSocket
. replace (); });
529 after ( function () { FakeWebSocket
. restore (); });
531 describe ( 'as binary data' , function () {
533 beforeEach ( function () {
534 sock
= new Websock ();
535 sock
. open ( 'ws://' , 'binary' );
536 sock
. _websocket
. _open ();
539 it ( 'should only send the send queue up to the send queue length' , function () {
540 sock
. _sQ
= new Uint8Array ([ 1 , 2 , 3 , 4 , 5 ]);
542 const res
= sock
. _encodeMessage ();
543 expect ( res
). to
. array
. equal ( new Uint8Array ([ 1 , 2 , 3 ]));
546 it ( 'should properly pass the encoded data off to the actual WebSocket' , function () {
547 sock
. send ([ 1 , 2 , 3 ]);
548 expect ( sock
. _websocket
. _getSentData ()). to
. array
. equal ( new Uint8Array ([ 1 , 2 , 3 ]));