// A single contender gets elected automatically.
TEST_F(ZooKeeperMasterContenderDetectorTest, MasterContender)
{
  Try<zookeeper::URL> url = zookeeper::URL::parse(
      "zk://" + server->connectString() + "/mesos");

  ASSERT_SOME(url);

  Owned<zookeeper::Group> group(
      new Group(url.get(), MASTER_CONTENDER_ZK_SESSION_TIMEOUT));

  ZooKeeperMasterContender* contender = new ZooKeeperMasterContender(group);

  PID<Master> pid;
  pid.node.ip = 10000000;
  pid.node.port = 10000;
  MasterInfo master = internal::protobuf::createMasterInfo(pid);

  contender->initialize(master);
  Future<Future<Nothing> > contended = contender->contend();
  AWAIT_READY(contended);

  ZooKeeperMasterDetector detector(url.get());

  Future<Option<MasterInfo> > leader = detector.detect();

  AWAIT_READY(leader);
  EXPECT_SOME_EQ(master, leader.get());

  leader = detector.detect(leader.get());

  // No change to leadership.
  ASSERT_TRUE(leader.isPending());

  // Ensure we can discard the future.
  leader.discard();

  AWAIT_DISCARDED(leader);

  // After the discard, we can re-detect correctly.
  leader = detector.detect(None());

  AWAIT_READY(leader);
  EXPECT_SOME_EQ(master, leader.get());

  // Now test that a session expiration causes candidacy to be lost
  // and the future to become ready.
  Future<Nothing> lostCandidacy = contended.get();
  leader = detector.detect(leader.get());

  Future<Option<int64_t> > sessionId = group.get()->session();
  AWAIT_READY(sessionId);
  server->expireSession(sessionId.get().get());

  AWAIT_READY(lostCandidacy);
  AWAIT_READY(leader);
  EXPECT_NONE(leader.get());
}
// A single contender gets elected automatically.
TEST_F(ZooKeeperMasterContenderDetectorTest, MasterContender)
{
  Try<zookeeper::URL> url = zookeeper::URL::parse(
      "zk://" + server->connectString() + "/mesos");

  ASSERT_SOME(url);

  Owned<zookeeper::Group> group(
      new Group(url.get(), MASTER_CONTENDER_ZK_SESSION_TIMEOUT));

  ZooKeeperMasterContender* contender = new ZooKeeperMasterContender(group);

  PID<Master> pid;
  pid.ip = 10000000;
  pid.port = 10000;
  MasterInfo master = internal::protobuf::createMasterInfo(pid);

  contender->initialize(master);
  Future<Future<Nothing> > contended = contender->contend();
  AWAIT_READY(contended);

  ZooKeeperMasterDetector detector(url.get());

  Future<Option<MasterInfo> > leader = detector.detect();
  EXPECT_SOME_EQ(master, leader.get());
  Future<Nothing> lostCandidacy = contended.get();
  leader = detector.detect(leader.get());

  Future<Option<int64_t> > sessionId = group.get()->session();
  AWAIT_READY(sessionId);
  server->expireSession(sessionId.get().get());

  // Session expiration causes candidacy to be lost and the
  // Future<Nothing> to be fulfilled.
  AWAIT_READY(lostCandidacy);
  AWAIT_READY(leader);
  EXPECT_NONE(leader.get());
}