PageRenderTime 119ms CodeModel.GetById 2ms app.highlight 107ms RepoModel.GetById 1ms app.codeStats 0ms

/test/transports.websocket.test.js

https://github.com/felixge/socket.io
JavaScript | 1894 lines | 1619 code | 260 blank | 15 comment | 159 complexity | b3c4a913ba72c0cb0e97249801471bf8 MD5 | raw file
   1
   2/*!
   3 * socket.io-node
   4 * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
   5 * MIT Licensed
   6 */
   7
   8/**
   9 * Test dependencies.
  10 */
  11
  12var sio = require('../')
  13  , should = require('./common')
  14  , parser = sio.parser
  15  , ports = 15800;
  16
  17/**
  18 * Tests.
  19 */
  20
  21module.exports = {
  22  'websocket identifies as websocket': function (done) {
  23    var cl = client(++ports)
  24      , io = create(cl)
  25      , ws;
  26
  27    io.set('transports', ['websocket']);
  28    io.sockets.on('connection', function (socket) {
  29      socket.manager.transports[socket.id].name.should.equal('websocket');
  30      ws.finishClose();
  31      cl.end();
  32      io.server.close();
  33      done();
  34    });
  35    cl.handshake(function (sid) {
  36      ws = websocket(cl, sid);
  37    });
  38  },
  39
  40  'default websocket draft parser is used for unknown sec-websocket-version': function (done) {
  41    var cl = client(++ports)
  42      , io = create(cl)
  43      , ws;
  44
  45    io.set('transports', ['websocket']);
  46    io.sockets.on('connection', function (socket) {
  47      socket.manager.transports[socket.id].protocolVersion.should.equal('hixie-76');
  48      ws.finishClose();
  49      cl.end();
  50      io.server.close();
  51      done();
  52    });
  53
  54    cl.handshake(function (sid) {
  55      ws = websocket(cl, sid);
  56    });
  57  },
  58
  59  'hybi-07-12 websocket draft parser is used for sec-websocket-version: 8': function (done) {
  60    var cl = client(++ports)
  61      , io = create(cl);
  62
  63    io.set('transports', ['websocket']);
  64    io.sockets.on('connection', function (socket) {
  65      socket.manager.transports[socket.id].protocolVersion.should.equal('07-12');
  66      cl.end();
  67      io.server.close();
  68      done();
  69    });
  70
  71    var headers = {
  72      'sec-websocket-version': 8,
  73      'upgrade': 'websocket',
  74      'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ=='
  75    }
  76
  77    cl.get('/socket.io/{protocol}', {}, function (res, data) {
  78      var sid = data.split(':')[0];
  79      var url = '/socket.io/' + sio.protocol + '/websocket/' + sid;
  80      cl.get(url, {headers: headers}, function (res, data) {});
  81    });
  82  },
  83
  84  'hybi-16 websocket draft parser is used for sec-websocket-version: 13': function (done) {
  85    var cl = client(++ports)
  86      , io = create(cl)
  87
  88    io.set('transports', ['websocket']);
  89
  90    io.sockets.on('connection', function (socket) {
  91      socket.manager.transports[socket.id].protocolVersion.should.equal('16');
  92      cl.end();
  93      io.server.close();
  94      done();
  95    });
  96
  97    var headers = {
  98      'sec-websocket-version': 13,
  99      'upgrade': 'websocket',
 100      'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ=='
 101    }
 102
 103    cl.get('/socket.io/{protocol}', {}, function (res, data) {
 104      var sid = data.split(':')[0];
 105      var url = '/socket.io/' + sio.protocol + '/websocket/' + sid;
 106      cl.get(url, {headers: headers}, function (res, data) {});
 107    });
 108  },
 109
 110  'hybi-07-12 origin filter blocks access for mismatched sec-websocket-origin': function (done) {
 111    var cl = client(++ports)
 112      , io = create(cl)
 113
 114    io.set('transports', ['websocket']);
 115    io.set('origins', 'foo.bar.com:*');
 116    var notConnected = true;
 117    io.sockets.on('connection', function() {
 118        notConnected = false;
 119    });
 120
 121    var headers = {
 122      'sec-websocket-version': 8,
 123      'upgrade': 'websocket',
 124      'Sec-WebSocket-Origin': 'http://baz.bar.com',
 125      'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ=='
 126    }
 127
 128    // handshake uses correct origin -- we want to block the actual websocket call
 129    cl.get('/socket.io/{protocol}', {headers: {origin: 'http://foo.bar.com'}}, function (res, data) {
 130      var sid = data.split(':')[0];
 131      var url = '/socket.io/' + sio.protocol + '/websocket/' + sid;
 132      var req = cl.get(url, {headers: headers}, function (res, data) {});
 133      var closed = false;
 134      (req.socket || req).on('close', function() {
 135        if (closed) return;
 136        closed = true;
 137        notConnected.should.be.true;
 138        cl.end();
 139        try {
 140          io.server.close();
 141        }
 142        catch (e) {}
 143        done();
 144      });
 145    });
 146  },
 147
 148  'hybi-16 origin filter blocks access for mismatched sec-websocket-origin': function (done) {
 149    var cl = client(++ports)
 150      , io = create(cl);
 151
 152    io.set('transports', ['websocket']);
 153    io.set('origins', 'foo.bar.com:*');
 154    var notConnected = true;
 155    io.sockets.on('connection', function() {
 156        notConnected = false;
 157    });
 158
 159    var headers = {
 160      'sec-websocket-version': 13,
 161      'upgrade': 'websocket',
 162      'origin': 'http://baz.bar.com',
 163      'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ=='
 164    }
 165
 166    // handshake uses correct origin -- we want to block the actual websocket call
 167    cl.get('/socket.io/{protocol}', {headers: {origin: 'http://foo.bar.com'}}, function (res, data) {
 168      var sid = data.split(':')[0];
 169      var url = '/socket.io/' + sio.protocol + '/websocket/' + sid;
 170      var req = cl.get(url, {headers: headers}, function (res, data) {});
 171      var closed = false;
 172      (req.socket || req).on('close', function() {
 173        if (closed) return;
 174        closed = true;
 175        notConnected.should.be.true;
 176        cl.end();
 177        try {
 178          io.server.close();
 179        }
 180        catch (e) {}
 181        done();
 182      });
 183    });
 184  },
 185
 186  'hybi-07-12 origin filter accepts implicit port 80 for sec-websocket-origin': function (done) {
 187done();return;
 188    var cl = client(++ports)
 189      , io = create(cl)
 190
 191    io.set('transports', ['websocket']);
 192    io.set('origins', 'foo.bar.com:80');
 193
 194    var headers = {
 195      'sec-websocket-version': 8,
 196      'upgrade': 'websocket',
 197      'Sec-WebSocket-Origin': 'http://foo.bar.com',
 198      'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ=='
 199    }
 200
 201    io.sockets.on('connection', function() {
 202        cl.end();
 203        io.server.close();
 204        done();
 205    });
 206
 207    // handshake uses correct origin -- we want to block the actual websocket call
 208    cl.get('/socket.io/{protocol}', {headers: {origin: 'http://foo.bar.com'}}, function (res, data) {
 209      var sid = data.split(':')[0];
 210      var url = '/socket.io/' + sio.protocol + '/websocket/' + sid;
 211      cl.get(url, {headers: headers}, function (res, data) {});
 212    });
 213  },
 214
 215  'hybi-16 origin filter accepts implicit port 80 for sec-websocket-origin': function (done) {
 216    var cl = client(++ports)
 217      , io = create(cl)
 218
 219    io.set('transports', ['websocket']);
 220    io.set('origins', 'foo.bar.com:80');
 221
 222    var headers = {
 223      'sec-websocket-version': 13,
 224      'upgrade': 'websocket',
 225      'origin': 'http://foo.bar.com',
 226      'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ=='
 227    }
 228
 229    io.sockets.on('connection', function() {
 230        cl.end();
 231        io.server.close();
 232        done();
 233    });
 234
 235    // handshake uses correct origin -- we want to block the actual websocket call
 236    cl.get('/socket.io/{protocol}', {headers: {origin: 'http://foo.bar.com'}}, function (res, data) {
 237      var sid = data.split(':')[0];
 238      var url = '/socket.io/' + sio.protocol + '/websocket/' + sid;
 239      cl.get(url, {headers: headers}, function (res, data) {});
 240    });
 241  },
 242
 243  'test that not responding to a heartbeat drops client': function (done) {
 244    var cl = client(++ports)
 245      , io = create(cl)
 246      , messages = 0
 247      , ws;
 248
 249    io.configure(function () {
 250      io.set('heartbeat interval', .05);
 251      io.set('heartbeat timeout', .05);
 252      io.set('close timeout', 0);
 253    });
 254
 255    io.sockets.on('connection', function (socket) {
 256      socket.on('disconnect', function (reason) {
 257        beat.should.be.true;
 258        reason.should.eql('heartbeat timeout');
 259
 260        cl.end();
 261        ws.finishClose();
 262        io.server.close();
 263        done();
 264      });
 265    });
 266
 267    cl.handshake(function (sid) {
 268      ws = websocket(cl, sid);
 269      ws.on('message', function (packet) {
 270        if (++messages == 1) {
 271          packet.type.should.eql('connect');
 272        } else {
 273          packet.type.should.eql('heartbeat');
 274          beat = true;
 275        }
 276      });
 277    });
 278  },
 279
 280  'test that responding to a heartbeat maintains session': function (done) {
 281    var cl = client(++ports)
 282      , io = create(cl)
 283      , messages = 0
 284      , heartbeats = 0
 285      , ws;
 286
 287    io.configure(function () {
 288      io.set('heartbeat interval', .05);
 289      io.set('heartbeat timeout', .05);
 290      io.set('close timeout', 0);
 291    });
 292
 293    io.sockets.on('connection', function (socket) {
 294      socket.on('disconnect', function (reason) {
 295        heartbeats.should.eql(2);
 296        reason.should.eql('heartbeat timeout');
 297
 298        cl.end();
 299        ws.finishClose();
 300        io.server.close();
 301        done();
 302      });
 303    });
 304
 305    cl.handshake(function (sid) {
 306      ws = websocket(cl, sid);
 307      ws.on('message', function (packet) {
 308        if (++messages == 1) {
 309          packet.type.should.eql('connect');
 310        } else {
 311          packet.type.should.eql('heartbeat');
 312          heartbeats++;
 313
 314          if (heartbeats == 1) {
 315            ws.packet({ type: 'heartbeat' });
 316          }
 317        }
 318      });
 319    });
 320  },
 321
 322  'test sending deliverable volatile messages': function (done) {
 323    var cl = client(++ports)
 324      , io = create(cl)
 325      , messages = 0
 326      , messaged = false;
 327
 328    io.configure(function () {
 329      io.set('close timeout', .05);
 330    });
 331
 332    io.sockets.on('connection', function (socket) {
 333      socket.volatile.send('tobi');
 334
 335      socket.on('disconnect', function () {
 336        messaged.should.be.true;
 337        cl.end();
 338        io.server.close();
 339        done();
 340      });
 341    });
 342
 343    cl.handshake(function (sid) {
 344      var ws = websocket(cl, sid);
 345      ws.on('message', function (msg) {
 346        if (++messages == 1) {
 347          msg.type.should.eql('connect');
 348        } else {
 349          msg.should.eql({
 350              type: 'message'
 351            , data: 'tobi'
 352            , endpoint: ''
 353          });
 354          messaged = true;
 355          ws.finishClose();
 356        }
 357      });
 358    });
 359  },
 360
 361  'test sending deliverable volatile json': function (done) {
 362    var cl = client(++ports)
 363      , io = create(cl)
 364      , messaged = false;
 365
 366    io.configure(function () {
 367      io.set('close timeout', .05);
 368    });
 369
 370    io.sockets.on('connection', function (socket) {
 371      socket.volatile.json.send([1, 2, 3]);
 372
 373      socket.on('disconnect', function () {
 374        messaged.should.be.true;
 375        cl.end();
 376        io.server.close();
 377        done();
 378      });
 379    });
 380
 381    cl.handshake(function (sid) {
 382      var ws = websocket(cl, sid);
 383      ws.on('message', function (msg) {
 384        if (!ws.connected) {
 385          msg.type.should.eql('connect');
 386          ws.connected = true;
 387        } else {
 388          msg.should.eql({
 389              type: 'json'
 390            , data: [1, 2, 3]
 391            , endpoint: ''
 392          });
 393          messaged = true;
 394          ws.finishClose();
 395        }
 396      });
 397    });
 398  },
 399
 400  'test sending deliverable volatile events': function (done) {
 401    var cl = client(++ports)
 402      , io = create(cl)
 403      , messaged = false;
 404
 405    io.configure(function () {
 406      io.set('close timeout', .05);
 407    });
 408
 409    io.sockets.on('connection', function (socket) {
 410      socket.volatile.emit('tobi');
 411
 412      socket.on('disconnect', function () {
 413        messaged.should.be.true;
 414        cl.end();
 415        io.server.close();
 416        done();
 417      });
 418    });
 419
 420    cl.handshake(function (sid) {
 421      var ws = websocket(cl, sid);
 422      ws.on('message', function (msg) {
 423        if (!ws.connected) {
 424          msg.type.should.eql('connect');
 425          ws.connected = true;
 426        } else {
 427          msg.should.eql({
 428              type: 'event'
 429            , name: 'tobi'
 430            , endpoint: ''
 431            , args: []
 432          });
 433          messaged = true;
 434          ws.finishClose();
 435        }
 436      });
 437    });
 438  },
 439
 440  'test sending to all clients in a namespace': function (done) {
 441    var port = ++ports
 442      , cl1 = client(port)
 443      , cl2 = client(port)
 444      , io = create(cl1)
 445      , messages = 0
 446      , connections = 0
 447      , disconnections = 0;
 448
 449    io.configure(function () {
 450      io.set('close timeout', 0);
 451    });
 452
 453    io.sockets.on('connection', function (socket) {
 454      connections++;
 455
 456      if (connections == 2) {
 457        io.sockets.send('yup');
 458      }
 459
 460      socket.on('disconnect', function () {
 461        disconnections++;
 462
 463        if (disconnections == 2) {
 464          messages.should.eql(2);
 465          cl1.end();
 466          cl2.end();
 467          io.server.close();
 468          done();
 469        }
 470      });
 471    });
 472
 473    cl1.handshake(function (sid) {
 474      var ws1 = websocket(cl1, sid);
 475      ws1.on('message', function (msg) {
 476        if (!ws1.connected) {
 477          msg.type.should.eql('connect');
 478          ws1.connected = true;
 479        } else {
 480          msg.should.eql({
 481              type: 'message'
 482            , data: 'yup'
 483            , endpoint: ''
 484          });
 485
 486          messages++;
 487          ws1.finishClose();
 488        }
 489      });
 490    });
 491
 492    cl2.handshake(function (sid) {
 493      var ws2 = websocket(cl2, sid);
 494      ws2.on('message', function (msg) {
 495        if (!ws2.connected) {
 496          msg.type.should.eql('connect');
 497          ws2.connected = true;
 498        } else {
 499          msg.should.eql({
 500              type: 'message'
 501            , data: 'yup'
 502            , endpoint: ''
 503          });
 504
 505          messages++;
 506          ws2.finishClose();
 507        }
 508      });
 509    });
 510  },
 511
 512  'test sending json to all clients in a namespace': function (done) {
 513    var port = ++ports
 514      , cl1 = client(port)
 515      , cl2 = client(port)
 516      , io = create(cl1)
 517      , messages = 0
 518      , connections = 0
 519      , disconnections = 0;
 520
 521    io.configure(function () {
 522      io.set('close timeout', 0);
 523    });
 524
 525    io.sockets.on('connection', function (socket) {
 526      connections++;
 527
 528      if (connections == 2) {
 529        io.sockets.json.send({ a: 'b' });
 530      }
 531
 532      socket.on('disconnect', function () {
 533        disconnections++;
 534
 535        if (disconnections == 2) {
 536          messages.should.eql(2);
 537          cl1.end();
 538          cl2.end();
 539          io.server.close();
 540          done();
 541        }
 542      });
 543    });
 544
 545    cl1.handshake(function (sid) {
 546      var ws1 = websocket(cl1, sid);
 547      ws1.on('message', function (msg) {
 548        if (!ws1.connected) {
 549          msg.type.should.eql('connect');
 550          ws1.connected = true;
 551        } else {
 552          msg.should.eql({
 553              type: 'json'
 554            , data: { a: 'b' }
 555            , endpoint: ''
 556          });
 557
 558          messages++;
 559          ws1.finishClose();
 560        }
 561      });
 562    });
 563
 564    cl2.handshake(function (sid) {
 565      var ws2 = websocket(cl2, sid);
 566      ws2.on('message', function (msg) {
 567        if (!ws2.connected) {
 568          msg.type.should.eql('connect');
 569          ws2.connected = true;
 570        } else {
 571          msg.should.eql({
 572              type: 'json'
 573            , data: { a: 'b' }
 574            , endpoint: ''
 575          });
 576
 577          messages++;
 578          ws2.finishClose();
 579        }
 580      });
 581    });
 582  },
 583
 584  'test emitting to all clients in a namespace': function (done) {
 585    var port = ++ports
 586      , cl1 = client(port)
 587      , cl2 = client(port)
 588      , io = create(cl1)
 589      , messages = 0
 590      , connections = 0
 591      , disconnections = 0;
 592
 593    io.configure(function () {
 594      io.set('close timeout', 0);
 595    });
 596
 597    io.sockets.on('connection', function (socket) {
 598      connections++;
 599
 600      if (connections == 2) {
 601        io.sockets.emit('tobi', 'rapture');
 602      }
 603
 604      socket.on('disconnect', function () {
 605        disconnections++;
 606
 607        if (disconnections == 2) {
 608          messages.should.eql(2);
 609          cl1.end();
 610          cl2.end();
 611          io.server.close();
 612          done();
 613        }
 614      });
 615    });
 616
 617    cl1.handshake(function (sid) {
 618      var ws1 = websocket(cl1, sid);
 619      ws1.on('message', function (msg) {
 620        if (!ws1.connected) {
 621          msg.type.should.eql('connect');
 622          ws1.connected = true;
 623        } else {
 624          msg.should.eql({
 625              type: 'event'
 626            , name: 'tobi'
 627            , args: ['rapture']
 628            , endpoint: ''
 629          });
 630
 631          messages++;
 632          ws1.finishClose();
 633        }
 634      });
 635    });
 636
 637    cl2.handshake(function (sid) {
 638      var ws2 = websocket(cl2, sid);
 639      ws2.on('message', function (msg) {
 640        if (!ws2.connected) {
 641          msg.type.should.eql('connect');
 642          ws2.connected = true;
 643        } else {
 644          msg.should.eql({
 645              type: 'event'
 646            , name: 'tobi'
 647            , args: ['rapture']
 648            , endpoint: ''
 649          });
 650
 651          messages++;
 652          ws2.finishClose();
 653        }
 654      });
 655    });
 656  },
 657
 658  'test sending to all clients in a room': function (done) {
 659    var port = ++ports
 660      , cl1 = client(port)
 661      , cl2 = client(port)
 662      , cl3 = client(port)
 663      , io = create(cl1)
 664      , messages = 0
 665      , joins = 0
 666      , connections = 0
 667      , disconnections = 0;
 668
 669    io.configure(function () {
 670      io.set('close timeout', 0);
 671    });
 672
 673    io.sockets.on('connection', function (socket) {
 674      connections++;
 675
 676      if (connections != 3) {
 677        socket.join('woot');
 678        joins++;
 679
 680        if (joins == 2) {
 681          setTimeout(function () {
 682            connections.should.eql(3);
 683            io.sockets.in('woot').send('hahaha');
 684          }, 20);
 685        }
 686      }
 687
 688      socket.on('disconnect', function () {
 689        disconnections++;
 690
 691        if (disconnections == 3) {
 692          messages.should.eql(2);
 693          cl1.end();
 694          cl2.end();
 695          cl3.end();
 696          io.server.close();
 697          done();
 698        }
 699      });
 700    });
 701
 702    cl1.handshake(function (sid) {
 703      var ws1 = websocket(cl1, sid);
 704      ws1.on('message', function (msg) {
 705        if (!ws1.connected) {
 706          msg.type.should.eql('connect');
 707          ws1.connected = true;
 708        } else {
 709          msg.should.eql({
 710              type: 'message'
 711            , data: 'hahaha'
 712            , endpoint: ''
 713          });
 714
 715          messages++;
 716        }
 717      });
 718
 719      setTimeout(function () {
 720        ws1.finishClose();
 721      }, 50);
 722    });
 723
 724    cl2.handshake(function (sid) {
 725      var ws2 = websocket(cl2, sid);
 726      ws2.on('message', function (msg) {
 727        if (!ws2.connected) {
 728          msg.type.should.eql('connect');
 729          ws2.connected = true;
 730        } else {
 731          msg.should.eql({
 732              type: 'message'
 733            , data: 'hahaha'
 734            , endpoint: ''
 735          });
 736
 737          messages++;
 738        }
 739      });
 740
 741      setTimeout(function () {
 742        ws2.finishClose();
 743      }, 50);
 744    });
 745
 746    cl3.handshake(function (sid) {
 747      var ws3 = websocket(cl3, sid);
 748      ws3.on('message', function (msg) {
 749        if (!ws3.connected) {
 750          msg.type.should.eql('connect');
 751          ws3.connected = true;
 752        } else {
 753          msg.should.eql({
 754              type: 'message'
 755            , data: 'hahaha'
 756            , endpoint: ''
 757          });
 758
 759          messages++;
 760        }
 761      });
 762
 763      setTimeout(function () {
 764        ws3.finishClose();
 765      }, 50);
 766    });
 767  },
 768
 769  'test sending json to all clients in a room': function (done) {
 770    var port = ++ports
 771      , cl1 = client(port)
 772      , cl2 = client(port)
 773      , cl3 = client(port)
 774      , io = create(cl1)
 775      , messages = 0
 776      , joins = 0
 777      , connections = 0
 778      , disconnections = 0;
 779
 780    io.configure(function () {
 781      io.set('close timeout', 0);
 782    });
 783
 784    io.sockets.on('connection', function (socket) {
 785      connections++;
 786
 787      if (connections != 3) {
 788        socket.join('woot');
 789        joins++;
 790
 791        if (joins == 2) {
 792          setTimeout(function () {
 793            connections.should.eql(3);
 794            io.sockets.in('woot').json.send(123);
 795          }, 20);
 796        }
 797      }
 798
 799      socket.on('disconnect', function () {
 800        disconnections++;
 801
 802        if (disconnections == 3) {
 803          messages.should.eql(2);
 804          cl1.end();
 805          cl2.end();
 806          cl3.end();
 807          io.server.close();
 808          done();
 809        }
 810      });
 811    });
 812
 813    cl1.handshake(function (sid) {
 814      var ws1 = websocket(cl1, sid);
 815      ws1.on('message', function (msg) {
 816        if (!ws1.connected) {
 817          msg.type.should.eql('connect');
 818          ws1.connected = true;
 819        } else {
 820          msg.should.eql({
 821              type: 'json'
 822            , data: 123
 823            , endpoint: ''
 824          });
 825
 826          messages++;
 827        }
 828      });
 829
 830      setTimeout(function () {
 831        ws1.finishClose();
 832      }, 50);
 833    });
 834
 835    cl2.handshake(function (sid) {
 836      var ws2 = websocket(cl2, sid);
 837      ws2.on('message', function (msg) {
 838        if (!ws2.connected) {
 839          msg.type.should.eql('connect');
 840          ws2.connected = true;
 841        } else {
 842          msg.should.eql({
 843              type: 'json'
 844            , data: 123
 845            , endpoint: ''
 846          });
 847
 848          messages++;
 849        }
 850      });
 851
 852      setTimeout(function () {
 853        ws2.finishClose();
 854      }, 50);
 855    });
 856
 857    cl3.handshake(function (sid) {
 858      var ws3 = websocket(cl3, sid);
 859      ws3.on('message', function (msg) {
 860        if (!ws3.connected) {
 861          msg.type.should.eql('connect');
 862          ws3.connected = true;
 863        } else {
 864          msg.should.eql({
 865              type: 'json'
 866            , data: 123
 867            , endpoint: ''
 868          });
 869
 870          messages++;
 871        }
 872      });
 873
 874      setTimeout(function () {
 875        ws3.finishClose();
 876      }, 50);
 877    });
 878  },
 879
 880  'test emitting to all clients in a room': function (done) {
 881    var port = ++ports
 882      , cl1 = client(port)
 883      , cl2 = client(port)
 884      , cl3 = client(port)
 885      , io = create(cl1)
 886      , messages = 0
 887      , joins = 0
 888      , connections = 0
 889      , disconnections = 0;
 890
 891    io.configure(function () {
 892      io.set('close timeout', 0);
 893    });
 894
 895    io.sockets.on('connection', function (socket) {
 896      connections++;
 897
 898      if (connections != 3) {
 899        socket.join('woot');
 900        joins++;
 901
 902        if (joins == 2) {
 903          setTimeout(function () {
 904            connections.should.eql(3);
 905            io.sockets.in('woot').emit('locki');
 906          }, 20);
 907        }
 908      }
 909
 910      socket.on('disconnect', function () {
 911        disconnections++;
 912
 913        if (disconnections == 3) {
 914          messages.should.eql(2);
 915          cl1.end();
 916          cl2.end();
 917          cl3.end();
 918          io.server.close();
 919          done();
 920        }
 921      });
 922    });
 923
 924    cl1.handshake(function (sid) {
 925      var ws1 = websocket(cl1, sid);
 926      ws1.on('message', function (msg) {
 927        if (!ws1.connected) {
 928          msg.type.should.eql('connect');
 929          ws1.connected = true;
 930        } else {
 931          msg.should.eql({
 932              type: 'event'
 933            , name: 'locki'
 934            , args: []
 935            , endpoint: ''
 936          });
 937
 938          messages++;
 939        }
 940      });
 941
 942      setTimeout(function () {
 943        ws1.finishClose();
 944      }, 50);
 945    });
 946
 947    cl2.handshake(function (sid) {
 948      var ws2 = websocket(cl2, sid);
 949      ws2.on('message', function (msg) {
 950        if (!ws2.connected) {
 951          msg.type.should.eql('connect');
 952          ws2.connected = true;
 953        } else {
 954          msg.should.eql({
 955              type: 'event'
 956            , name: 'locki'
 957            , args: []
 958            , endpoint: ''
 959          });
 960
 961          messages++;
 962        }
 963      });
 964
 965      setTimeout(function () {
 966        ws2.finishClose();
 967      }, 50);
 968    });
 969
 970    cl3.handshake(function (sid) {
 971      var ws3 = websocket(cl3, sid);
 972      ws3.on('message', function (msg) {
 973        if (!ws3.connected) {
 974          msg.type.should.eql('connect');
 975          ws3.connected = true;
 976        } else {
 977          msg.should.eql({
 978              type: 'event'
 979            , name: 'locki'
 980            , args: []
 981            , endpoint: ''
 982          });
 983
 984          messages++;
 985        }
 986      });
 987
 988      setTimeout(function () {
 989        ws3.finishClose();
 990      }, 50);
 991    });
 992  },
 993
 994  'test leaving a room': function (done) {
 995    var port = ++ports
 996      , cl1 = client(port)
 997      , cl2 = client(port)
 998      , io = create(cl1)
 999      , joins = 0
1000      , disconnects = 0;
1001
1002    io.set('close timeout', 0);
1003
1004    io.sockets.on('connection', function (socket) {
1005      socket.join('foo');
1006      io.sockets.clients('foo').should.have.length(++joins);
1007
1008      socket.on('disconnect', function () {
1009        socket.leave('foo');
1010        socket.leave('foo');
1011        socket.leave('foo');
1012
1013        io.sockets.clients('foo').should.have.length(--joins);
1014
1015        if (++disconnects == 2) {
1016          io.server.close();
1017          cl1.end();
1018          cl2.end();
1019          done();
1020        }
1021      })
1022    });
1023
1024    cl1.handshake(function (sid) {
1025      var ws1 = websocket(cl1, sid);
1026      ws1.on('message', function (msg) {
1027        if (!ws1.connected) {
1028          msg.type.should.eql('connect');
1029          ws1.connected = true;
1030           ws1.finishClose();
1031        }
1032      });
1033    });
1034
1035    cl2.handshake(function (sid) {
1036      var ws2 = websocket(cl2, sid);
1037      ws2.on('message', function (msg) {
1038        if (!ws2.connected) {
1039          msg.type.should.eql('connect');
1040          ws2.connected = true;
1041          ws2.finishClose();
1042        }
1043      });
1044    });
1045  },
1046
1047  'test message with broadcast flag': function (done) {
1048    var port = ++ports
1049      , cl1 = client(port)
1050      , cl2 = client(port)
1051      , cl3 = client(port)
1052      , io = create(cl1)
1053      , messages = 0
1054      , disconnections = 0;
1055
1056    io.configure(function () {
1057      io.set('close timeout', 0);
1058    });
1059
1060    io.sockets.on('connection', function (socket) {
1061      socket.on('trigger broadcast', function () {
1062        socket.broadcast.send('boom');
1063      });
1064
1065      socket.on('disconnect', function () {
1066        disconnections++;
1067
1068        if (disconnections == 3) {
1069          messages.should.eql(2);
1070          cl1.end();
1071          cl2.end();
1072          cl3.end();
1073          io.server.close();
1074          done();
1075        }
1076      });
1077    });
1078
1079    cl1.handshake(function (sid) {
1080      var ws1 = websocket(cl1, sid);
1081      ws1.on('message', function (msg) {
1082        if (!ws1.connected) {
1083          msg.type.should.eql('connect');
1084          ws1.connected = true;
1085        } else {
1086          msg.should.eql({
1087              type: 'message'
1088            , data: 'boom'
1089            , endpoint: ''
1090          });
1091
1092          messages++;
1093          ws1.finishClose();
1094        }
1095      });
1096    });
1097
1098    cl2.handshake(function (sid) {
1099      var ws2 = websocket(cl2, sid);
1100      ws2.on('message', function (msg) {
1101        if (!ws2.connected) {
1102          msg.type.should.eql('connect');
1103          ws2.connected = true;
1104        } else {
1105          msg.should.eql({
1106              type: 'message'
1107            , data: 'boom'
1108            , endpoint: ''
1109          });
1110
1111          messages++;
1112          ws2.finishClose();
1113        }
1114      });
1115    });
1116
1117    cl3.handshake(function (sid) {
1118      var ws3 = websocket(cl3, sid);
1119      ws3.on('open', function () {
1120        ws3.packet({
1121            type: 'event'
1122          , name: 'trigger broadcast'
1123          , endpoint: ''
1124        });
1125
1126        setTimeout(function () {
1127          ws3.finishClose();
1128        }, 50);
1129      });
1130
1131      ws3.on('message', function (msg) {
1132        if (!ws3.connected) {
1133          msg.type.should.eql('connect');
1134          ws3.connected = true;
1135        } else {
1136          throw new Error('we shouldnt get a message here');
1137        }
1138      });
1139    });
1140  },
1141
1142  'test json with broadcast flag': function (done) {
1143    var port = ++ports
1144      , cl1 = client(port)
1145      , cl2 = client(port)
1146      , cl3 = client(port)
1147      , io = create(cl1)
1148      , messages = 0
1149      , disconnections = 0;
1150
1151    io.configure(function () {
1152      io.set('close timeout', 0);
1153    });
1154
1155    io.sockets.on('connection', function (socket) {
1156      socket.on('trigger broadcast', function () {
1157        socket.broadcast.json.send([1, 2, 3]);
1158      });
1159
1160      socket.on('disconnect', function () {
1161        disconnections++;
1162
1163        if (disconnections == 3) {
1164          messages.should.eql(2);
1165          cl1.end();
1166          cl2.end();
1167          cl3.end();
1168          io.server.close();
1169          done();
1170        }
1171      });
1172    });
1173
1174    cl1.handshake(function (sid) {
1175      var ws1 = websocket(cl1, sid);
1176      ws1.on('message', function (msg) {
1177        if (!ws1.connected) {
1178          msg.type.should.eql('connect');
1179          ws1.connected = true;
1180        } else {
1181          msg.should.eql({
1182              type: 'json'
1183            , data: [1, 2, 3]
1184            , endpoint: ''
1185          });
1186
1187          messages++;
1188          ws1.finishClose();
1189        }
1190      });
1191    });
1192
1193    cl2.handshake(function (sid) {
1194      var ws2 = websocket(cl2, sid);
1195      ws2.on('message', function (msg) {
1196        if (!ws2.connected) {
1197          msg.type.should.eql('connect');
1198          ws2.connected = true;
1199        } else {
1200          msg.should.eql({
1201              type: 'json'
1202            , data: [1, 2, 3]
1203            , endpoint: ''
1204          });
1205
1206          messages++;
1207          ws2.finishClose();
1208        }
1209      });
1210    });
1211
1212    cl3.handshake(function (sid) {
1213      var ws3 = websocket(cl3, sid);
1214      ws3.on('open', function () {
1215        ws3.packet({
1216            type: 'event'
1217          , name: 'trigger broadcast'
1218          , endpoint: ''
1219        });
1220
1221        setTimeout(function () {
1222          ws3.finishClose();
1223        }, 50);
1224      });
1225
1226      ws3.on('message', function (msg) {
1227        if (!ws3.connected) {
1228          msg.type.should.eql('connect');
1229          ws3.connected = true;
1230        } else {
1231          throw new Error('we shouldnt get a message here');
1232        }
1233      });
1234    });
1235  },
1236
1237  'test event with broadcast flag': function (done) {
1238    var port = ++ports
1239      , cl1 = client(port)
1240      , cl2 = client(port)
1241      , cl3 = client(port)
1242      , io = create(cl1)
1243      , messages = 0
1244      , disconnections = 0;
1245
1246    io.configure(function () {
1247      io.set('close timeout', 0);
1248    });
1249
1250    io.sockets.on('connection', function (socket) {
1251      socket.on('trigger broadcast', function () {
1252        socket.broadcast.emit('hey', 'arnold');
1253      });
1254
1255      socket.on('disconnect', function () {
1256        disconnections++;
1257
1258        if (disconnections == 3) {
1259          messages.should.eql(2);
1260          cl1.end();
1261          cl2.end();
1262          cl3.end();
1263          io.server.close();
1264          done();
1265        }
1266      });
1267    });
1268
1269    cl1.handshake(function (sid) {
1270      var ws1 = websocket(cl1, sid);
1271      ws1.on('message', function (msg) {
1272        if (!ws1.connected) {
1273          msg.type.should.eql('connect');
1274          ws1.connected = true;
1275        } else {
1276          msg.should.eql({
1277              type: 'event'
1278            , name: 'hey'
1279            , args: ['arnold']
1280            , endpoint: ''
1281          });
1282
1283          messages++;
1284          ws1.finishClose();
1285        }
1286      });
1287    });
1288
1289    cl2.handshake(function (sid) {
1290      var ws2 = websocket(cl2, sid);
1291      ws2.on('message', function (msg) {
1292        if (!ws2.connected) {
1293          msg.type.should.eql('connect');
1294          ws2.connected = true;
1295        } else {
1296          msg.should.eql({
1297              type: 'event'
1298            , name: 'hey'
1299            , args: ['arnold']
1300            , endpoint: ''
1301          });
1302
1303          messages++;
1304          ws2.finishClose();
1305        }
1306      });
1307    });
1308
1309    cl3.handshake(function (sid) {
1310      var ws3 = websocket(cl3, sid);
1311      ws3.on('open', function () {
1312        ws3.packet({
1313            type: 'event'
1314          , name: 'trigger broadcast'
1315          , endpoint: ''
1316        });
1317
1318        setTimeout(function () {
1319          ws3.finishClose();
1320        }, 50);
1321      });
1322
1323      ws3.on('message', function (msg) {
1324        if (!ws3.connected) {
1325          msg.type.should.eql('connect');
1326          ws3.connected = true;
1327        } else {
1328          throw new Error('we shouldnt get a message here');
1329        }
1330      });
1331    });
1332  },
1333
1334  'test message with broadcast flag and to()': function (done) {
1335    var port = ++ports
1336      , cl1 = client(port)
1337      , cl2 = client(port)
1338      , cl3 = client(port)
1339      , io = create(cl1)
1340      , messages = 0
1341      , connections = 0
1342      , disconnections = 0;
1343
1344    io.configure(function () {
1345      io.set('close timeout', 0);
1346    });
1347
1348    io.sockets.on('connection', function (socket) {
1349      connections++;
1350
1351      if (connections == 1) {
1352        socket.join('losers');
1353      }
1354
1355      socket.on('trigger broadcast', function () {
1356        socket.broadcast.to('losers').send('boom');
1357      });
1358
1359      socket.on('disconnect', function () {
1360        disconnections++;
1361
1362        if (disconnections == 3) {
1363          messages.should.eql(1);
1364          cl1.end();
1365          cl2.end();
1366          cl3.end();
1367          io.server.close();
1368          done();
1369        }
1370      });
1371    });
1372
1373    cl1.handshake(function (sid) {
1374      var ws1 = websocket(cl1, sid);
1375      ws1.on('message', function (msg) {
1376        if (!ws1.connected) {
1377          msg.type.should.eql('connect');
1378          ws1.connected = true;
1379        } else {
1380          msg.should.eql({
1381              type: 'message'
1382            , data: 'boom'
1383            , endpoint: ''
1384          });
1385
1386          messages++;
1387        }
1388      });
1389
1390      ws1.on('open', function () {
1391        cl2.handshake(function (sid) {
1392          var ws2 = websocket(cl2, sid);
1393          ws2.on('message', function (msg) {
1394            if (!ws2.connected) {
1395              msg.type.should.eql('connect');
1396              ws2.connected = true;
1397            } else {
1398              throw new Error('This socket shouldnt get a message');
1399            }
1400          });
1401
1402          ws2.on('open', function () {
1403            cl3.handshake(function (sid) {
1404              var ws3 = websocket(cl3, sid);
1405              ws3.on('open', function () {
1406                ws3.packet({
1407                    type: 'event'
1408                  , name: 'trigger broadcast'
1409                  , endpoint: ''
1410                });
1411
1412                setTimeout(function () {
1413                  ws1.finishClose();
1414                  ws2.finishClose();
1415                  ws3.finishClose();
1416                }, 50);
1417              });
1418
1419              ws3.on('message', function (msg) {
1420                if (!ws3.connected) {
1421                  msg.type.should.eql('connect');
1422                  ws3.connected = true;
1423                } else {
1424                  throw new Error('we shouldnt get a message here');
1425                }
1426              });
1427            });
1428          });
1429        });
1430      });
1431    });
1432  },
1433
1434  'test json with broadcast flag and to()': function (done) {
1435    var port = ++ports
1436      , cl1 = client(port)
1437      , cl2 = client(port)
1438      , cl3 = client(port)
1439      , io = create(cl1)
1440      , messages = 0
1441      , connections = 0
1442      , disconnections = 0;
1443
1444    io.configure(function () {
1445      io.set('close timeout', 0);
1446    });
1447
1448    io.sockets.on('connection', function (socket) {
1449      connections++;
1450
1451      if (connections == 1) {
1452        socket.join('losers');
1453      }
1454
1455      socket.on('trigger broadcast', function () {
1456        socket.broadcast.json.to('losers').send({ hello: 'world' });
1457      });
1458
1459      socket.on('disconnect', function () {
1460        disconnections++;
1461
1462        if (disconnections == 3) {
1463          messages.should.eql(1);
1464          cl1.end();
1465          cl2.end();
1466          cl3.end();
1467          io.server.close();
1468          done();
1469        }
1470      });
1471    });
1472
1473    cl1.handshake(function (sid) {
1474      var ws1 = websocket(cl1, sid);
1475      ws1.on('message', function (msg) {
1476        if (!ws1.connected) {
1477          msg.type.should.eql('connect');
1478          ws1.connected = true;
1479        } else {
1480          msg.should.eql({
1481              type: 'json'
1482            , data: { hello: 'world' }
1483            , endpoint: ''
1484          });
1485
1486          messages++;
1487        }
1488      });
1489
1490      ws1.on('open', function () {
1491        cl2.handshake(function (sid) {
1492          var ws2 = websocket(cl2, sid);
1493          ws2.on('message', function (msg) {
1494            if (!ws2.connected) {
1495              msg.type.should.eql('connect');
1496              ws2.connected = true;
1497            } else {
1498              throw new Error('This socket shouldnt get a message');
1499            }
1500          });
1501
1502          ws2.on('open', function () {
1503            cl3.handshake(function (sid) {
1504              var ws3 = websocket(cl3, sid);
1505              ws3.on('open', function () {
1506                ws3.packet({
1507                    type: 'event'
1508                  , name: 'trigger broadcast'
1509                  , endpoint: ''
1510                });
1511
1512                setTimeout(function () {
1513                  ws1.finishClose();
1514                  ws2.finishClose();
1515                  ws3.finishClose();
1516                }, 50);
1517              });
1518
1519              ws3.on('message', function (msg) {
1520                if (!ws3.connected) {
1521                  msg.type.should.eql('connect');
1522                  ws3.connected = true;
1523                } else {
1524                  throw new Error('we shouldnt get a message here');
1525                }
1526              });
1527            });
1528          });
1529        });
1530      });
1531    });
1532  },
1533
1534  'test event with broadcast flag and to()': function (done) {
1535    var port = ++ports
1536      , cl1 = client(port)
1537      , cl2 = client(port)
1538      , cl3 = client(port)
1539      , io = create(cl1)
1540      , messages = 0
1541      , connections = 0
1542      , disconnections = 0;
1543
1544    io.configure(function () {
1545      io.set('close timeout', 0);
1546    });
1547
1548    io.sockets.on('connection', function (socket) {
1549      connections++;
1550
1551      if (connections == 1) {
1552        socket.join('losers');
1553      }
1554
1555      socket.on('trigger broadcast', function () {
1556        socket.broadcast.to('losers').emit('victory');
1557      });
1558
1559      socket.on('disconnect', function () {
1560        disconnections++;
1561
1562        if (disconnections == 3) {
1563          messages.should.eql(1);
1564          cl1.end();
1565          cl2.end();
1566          cl3.end();
1567          io.server.close();
1568          done();
1569        }
1570      });
1571    });
1572
1573    cl1.handshake(function (sid) {
1574      var ws1 = websocket(cl1, sid);
1575      ws1.on('message', function (msg) {
1576        if (!ws1.connected) {
1577          msg.type.should.eql('connect');
1578          ws1.connected = true;
1579        } else {
1580          msg.should.eql({
1581              type: 'event'
1582            , name: 'victory'
1583            , args: []
1584            , endpoint: ''
1585          });
1586
1587          messages++;
1588        }
1589      });
1590
1591      ws1.on('open', function () {
1592        cl2.handshake(function (sid) {
1593          var ws2 = websocket(cl2, sid);
1594          ws2.on('message', function (msg) {
1595            if (!ws2.connected) {
1596              msg.type.should.eql('connect');
1597              ws2.connected = true;
1598            } else {
1599              throw new Error('This socket shouldnt get a message');
1600            };
1601          });
1602
1603          ws2.on('open', function () {
1604            cl3.handshake(function (sid) {
1605              var ws3 = websocket(cl3, sid);
1606              ws3.on('open', function () {
1607                ws3.packet({
1608                    type: 'event'
1609                  , name: 'trigger broadcast'
1610                  , endpoint: ''
1611                });
1612
1613                setTimeout(function () {
1614                  ws1.finishClose();
1615                  ws2.finishClose();
1616                  ws3.finishClose();
1617                }, 50);
1618              });
1619
1620              ws3.on('message', function (msg) {
1621                if (!ws3.connected) {
1622                  msg.type.should.eql('connect');
1623                  ws3.connected = true;
1624                } else {
1625                  throw new Error('we shouldnt get a message here');
1626                }
1627              });
1628            });
1629          });
1630        });
1631      });
1632    });
1633  },
1634
1635  'test accessing handshake data from sockets': function (done) {
1636    var cl = client(++ports)
1637      , io = create(cl)
1638      , ws;
1639
1640    io.sockets.on('connection', function (socket) {
1641      (!!socket.handshake.address.address).should.be.true;
1642      (!!socket.handshake.address.port).should.be.true;
1643      socket.handshake.headers.host.should.equal('localhost');
1644      socket.handshake.headers.connection.should.equal('keep-alive');
1645      socket.handshake.time.should.match(/GMT/);
1646
1647      socket.on('disconnect', function () {
1648        setTimeout(function () {
1649          ws.finishClose();
1650          cl.end();
1651          io.server.close();
1652          done();
1653        }, 10);
1654      });
1655
1656      socket.disconnect();
1657    });
1658
1659    cl.handshake(function (sid) {
1660      ws = websocket(cl, sid);
1661      ws.on('message', function (msg) {
1662        if (!ws.connected) {
1663          msg.type.should.eql('connect');
1664          ws.connected = true;
1665        }
1666      });
1667    });
1668  },
1669
1670  'test accessing the array of clients': function (done) {
1671    var port = ++ports
1672      , cl1 = client(port)
1673      , cl2 = client(port)
1674      , io = create(cl1)
1675      , total = 2
1676      , ws1, ws2;
1677
1678    io.sockets.on('connection', function (socket) {
1679      socket.on('join ferrets', function () {
1680        socket.join('ferrets');
1681        socket.send('done');
1682      });
1683    });
1684
1685    function check() {
1686      io.sockets.clients('ferrets').should.have.length(1);
1687      io.sockets.clients('ferrets')[0].should.be.an.instanceof(sio.Socket);
1688      io.sockets.clients('ferrets')[0].id.should.equal(ws1.sid);
1689      io.sockets.clients().should.have.length(2);
1690      io.sockets.clients()[0].should.be.an.instanceof(sio.Socket);
1691      io.sockets.clients()[0].id.should.equal(ws1.sid);
1692      io.sockets.clients()[1].should.be.an.instanceof(sio.Socket);
1693      io.sockets.clients()[1].id.should.equal(ws2.sid);
1694
1695      ws1.finishClose();
1696      ws2.finishClose();
1697      cl1.end();
1698      cl2.end();
1699      io.server.close();
1700      done();
1701    };
1702
1703    cl1.handshake(function (sid) {
1704      ws1 = websocket(cl1, sid);
1705      ws1.sid = sid;
1706      ws1.on('message', function (msg) {
1707        if (!ws1.connected) {
1708          msg.type.should.eql('connect');
1709          ws1.connected = true;
1710          ws1.packet({
1711              type: 'event'
1712            , name: 'join ferrets'
1713            , endpoint: ''
1714          });
1715        } else {
1716          cl2.handshake(function (sid) {
1717            ws2 = websocket(cl2, sid);
1718            ws2.sid = sid;
1719            ws2.on('message', function (msg) {
1720              if (!ws2.connected) {
1721                msg.type.should.eql('connect');
1722                ws2.connected = true;
1723                check();
1724              }
1725            });
1726          });
1727        }
1728      });
1729    });
1730  },
1731
1732  'test accessing handshake data from sockets on disconnect': function (done) {
1733    var cl = client(++ports)
1734      , io = create(cl)
1735      , ws;
1736
1737    io.sockets.on('connection', function (socket) {
1738      socket.on('disconnect', function () {
1739
1740      (!!socket.handshake.address.address).should.be.true;
1741      (!!socket.handshake.address.port).should.be.true;
1742      socket.handshake.headers.host.should.equal('localhost');
1743      socket.handshake.headers.connection.should.equal('keep-alive');
1744      socket.handshake.time.should.match(/GMT/);
1745
1746        setTimeout(function () {
1747          ws.finishClose();
1748          cl.end();
1749          io.server.close();
1750          done();
1751        }, 10);
1752      });
1753
1754      socket.disconnect();
1755    });
1756
1757    cl.handshake(function (sid) {
1758      ws = websocket(cl, sid);
1759      ws.on('message', function (msg) {
1760        if (!ws.connected) {
1761          msg.type.should.eql('connect');
1762          ws.connected = true;
1763        }
1764      });
1765    });
1766  },
1767
1768  'test for intentional and unintentional disconnects': function (done) {
1769    var cl = client(++ports)
1770      , io = create(cl)
1771      , calls = 0
1772      , ws;
1773
1774    function close () {
1775      cl.end();
1776      io.server.close();
1777      ws.finishClose();
1778      done();
1779    }
1780
1781    io.configure(function () {
1782      io.set('heartbeat interval', .05);
1783      io.set('heartbeat timeout', .05);
1784      io.set('close timeout', 0);
1785    });
1786
1787    io.of('/foo').on('connection', function (socket) {
1788      socket.on('disconnect', function (reason) {
1789       reason.should.equal('packet');
1790
1791       if (++calls == 2) close();
1792      });
1793    });
1794
1795    io.of('/bar').on('connection', function (socket) {
1796      socket.on('disconnect', function (reason) {
1797        reason.should.equal('socket end');
1798
1799        if (++calls == 2) close();
1800      });
1801    });
1802
1803    cl.handshake(function (sid) {
1804      var messages = 0;
1805      ws = websocket(cl, sid);
1806      ws.on('open', function () {
1807        ws.packet({
1808            type: 'connect'
1809          , endpoint: '/foo'
1810        });
1811        ws.packet({
1812            type: 'connect'
1813          , endpoint: '/bar'
1814        });
1815      });
1816
1817      ws.on('message', function (packet) {
1818        if (packet.type == 'connect') {
1819          if (++messages === 3) {
1820            ws.packet({ type: 'disconnect', endpoint:'/foo' });
1821            ws.finishClose();
1822          }
1823        }
1824      });
1825    });
1826  },
1827
1828  'test socket clean up': function (done) {
1829    var cl = client(++ports)
1830      , io = create(cl)
1831      , ws;
1832
1833    io.sockets.on('connection', function (socket) {
1834      var self = this
1835        , id = socket.id;
1836
1837      socket.on('disconnect', function () {
1838        setTimeout(function () {
1839          var available = !!self.sockets[id];
1840
1841          available.should.be.false;
1842          ws.finishClose();
1843          cl.end();
1844          io.server.close();
1845          done();
1846        }, 10);
1847      });
1848
1849      socket.disconnect();
1850    });
1851
1852    cl.handshake(function (sid) {
1853      ws = websocket(cl, sid);
1854      ws.on('message', function (msg) {
1855        if (!ws.connected) {
1856          msg.type.should.eql('connect');
1857          ws.connected = true;
1858        }
1859      });
1860    });
1861  },
1862
1863  'accessing the transport type': function (done) {
1864    var cl = client(++ports)
1865      , io = create(cl)
1866      , ws;
1867
1868    io.sockets.on('connection', function (socket) {
1869      socket.transport.should.equal('websocket');
1870
1871      socket.on('disconnect', function () {
1872        setTimeout(function () {
1873          ws.finishClose();
1874          cl.end();
1875          io.server.close();
1876          done();
1877        }, 10);
1878      });
1879
1880      socket.disconnect();
1881    });
1882
1883    cl.handshake(function (sid) {
1884      ws = websocket(cl, sid);
1885      ws.on('message', function (msg) {
1886        if (!ws.connected) {
1887          msg.type.should.eql('connect');
1888          ws.connected = true;
1889        }
1890      });
1891    });
1892  }
1893
1894};