PageRenderTime 99ms CodeModel.GetById 5ms app.highlight 85ms RepoModel.GetById 1ms app.codeStats 0ms

/socket.io/test/transports.websocket.test.js

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