startThaliServer().then(function() {
   largerHashStateMachine = new LargerHashStateMachine(thaliApp, bigHash);
   smallerHashStateMachine =
     new SmallerHashStateMachine(new TRMMock(),
       retrySamePortConnectionTable(thePeerId, t, true), thePeerId, bigHash, smallHash);
   largerHashStateMachine.start();
   largerHashStateMachine.exchangeIdentity(smallHash);
   smallerHashStateMachine.on(SmallerHashStateMachine.Events.Exited, function(error) {
     if (exitCalled) {
       return t.fail("We should only have been called here once.");
     }
     exitCalled = true;
     t.equal(error, SmallerHashStateMachine.ExitBecauseGotValidationCode);
     checkDone();
   });
   smallerHashStateMachine.on(SmallerHashStateMachine.Events.ValidationCode, function(validationCode) {
     if (smallerValidationCode) {
       return t.fail("We should have only gotten called here once");
     }
     smallerValidationCode = validationCode;
     checkDone();
   });
   largerHashStateMachine.on(LargerHashStateMachine.Events.ValidationCodeGenerated, function (validationCode) {
     if (largerValidationCode) {
       return t.fail("We should have only gotten called here once");
     }
     largerValidationCode = validationCode;
     checkDone();
   });
   smallerHashStateMachine.start();
 })
test('start - Make sure we start when our hash is smaller', function(t) {
  smallerHashStateMachine =
    new SmallerHashStateMachine(new TRMMock(), new MockConnectionTable(), null, bigHash, smallHash);
  smallerHashStateMachine.on(SmallerHashStateMachine.Events.SearchStarted, function() {
    t.equal(smallerHashStateMachine.smallHashStateMachine.current, "GetPeerIdPort");
    t.end();
  });
  smallerHashStateMachine.start();
});
test('Test race conditions', function(t) {
  smallerHashStateMachine = new SmallerHashStateMachine(new TRMMock(),
    retrySamePortConnectionTable(thePeerId, t), thePeerId, bigHash, smallHash);
  smallerHashStateMachine.start();
  setImmediate(function() {
    smallerHashStateMachine.stop();
    t.throws(function() { smallerHashStateMachine.start() });
    t.end();
  });
});
test('start - Make sure we exit when our hash is bigger', function (t) {
  smallerHashStateMachine =
    new SmallerHashStateMachine(new TRMMock(), new MockConnectionTable(), null, smallHash, bigHash);
  smallerHashStateMachine.once(SmallerHashStateMachine.Events.Exited, function(error) {
    t.equal(error, SmallerHashStateMachine.ExitBecauseNotNeededError);
    t.equal(smallerHashStateMachine.smallHashStateMachine.current, "Exit");
    t.end();
  });
  smallerHashStateMachine.start();
});
 startThaliServer().then(function() {
   largerHashStateMachine = new LargerHashStateMachine(thaliApp, bigHash);
   smallerHashStateMachine =
     new SmallerHashStateMachine(new TRMMock(),
       retrySamePortConnectionTable(thePeerId, t, true), thePeerId, bigHash, smallHash);
   largerHashStateMachine.start();
   largerHashStateMachine.exchangeIdentity(crypto.randomBytes(identityExchangeUtils.pkBufferLength));
   smallerHashStateMachine.on(SmallerHashStateMachine.Events.WrongPeer, function() {
     smallerHashStateMachine.stop();
     t.end();
   });
   smallerHashStateMachine.start();
 })
 startThaliServer().then(function() {
   largerHashStateMachine = new LargerHashStateMachine(thaliApp, bigHash);
   smallerHashStateMachine =
     new SmallerHashStateMachine(new TRMMock(),
       endlessMockConnectionTableLoop(t, thePeerId, thaliServerPort), thePeerId, bigHash, smallHash);
   smallerHashStateMachine.on(SmallerHashStateMachine.Events.FourOhFour, function() {
     // We need to get rid of largerHashStateMachine because otherwise teardown will call stop
     // and we (intentionally) never called start!
     largerHashStateMachine = null;
     t.end();
   });
   smallerHashStateMachine.start();
 });
 disableIfJxCore(t, function(t) {
   testServer
     .post(identityExchangeUtils.cbPath)
     .reply(500, {});
   smallerHashStateMachine =
     new SmallerHashStateMachine(new TRMMock(), endlessMockConnectionTableLoop(t, thePeerId, port),
       thePeerId, bigHash, smallHash);
   smallerHashStateMachine.on(SmallerHashStateMachine.Events.GotUnclassifiedError, function(path) {
     t.equal(path, identityExchangeUtils.cbPath);
     t.end();
   });
   smallerHashStateMachine.start();
 });
 startThaliServer().then(function() {
   largerHashStateMachine = new LargerHashStateMachine(thaliApp, bigHash);
   smallerHashStateMachine =
     new SmallerHashStateMachine(new TRMMock(),
       endlessMockConnectionTableLoop(t, thePeerId, thaliServerPort, true), thePeerId, bigHash, smallHash);
   smallerHashStateMachine.once(SmallerHashStateMachine.Events.GotNotDoingIdentityExchange, function(path) {
     t.equals(path, identityExchangeUtils.cbPath);
     largerHashStateMachine.exchangeIdentity(smallHash);
   });
   smallerHashStateMachine.once(SmallerHashStateMachine.Events.ValidationCode, function() {
     t.end();
   });
   largerHashStateMachine.start();
   smallerHashStateMachine.start();
 })
 disableIfJxCore(t, function(t) {
   testServer
     .post(identityExchangeUtils.cbPath)
     .reply(200, goodCbMockResponse())
     .post(identityExchangeUtils.rnMinePath)
     .reply(404, "");
   var smallerHashStateMachine =
     new SmallerHashStateMachine(new TRMMock(), endlessMockConnectionTableLoop(t, thePeerId, port), thePeerId, bigHash,
       smallHash);
   smallerHashStateMachine.on(SmallerHashStateMachine.Events.FourOhFour, function() {
     smallerHashStateMachine.stop();
     t.end();
   });
   smallerHashStateMachine.start();
 });
function runBad200Test(t, requestPath, numberEvents) {
  smallerHashStateMachine =
    new SmallerHashStateMachine(new TRMMock(), endlessMockConnectionTableLoop(t, thePeerId, port), thePeerId,
      bigHash, smallHash);

  var bad200EventCount = 0;

  smallerHashStateMachine.on(SmallerHashStateMachine.Events.BadRequestBody, function(path) {
    t.equal(requestPath, path);
    bad200EventCount += 1;
    if (bad200EventCount == numberEvents) {
      t.end();
    }
  });

  smallerHashStateMachine.start();
}
t.throws(function() { smallerHashStateMachine.start() });
test('onFoundPeerPort - bad peer port', function(t) {
  var badPortMockTable = mockConnectionTableGenerator(t, thePeerId, [10101, 10101]);
  var smallerHashStateMachine =
    new SmallerHashStateMachine(new TRMMock(), badPortMockTable, thePeerId, bigHash, smallHash);
  smallerHashStateMachine.start();
});