// ----------------------------------------------------------------------
// File: raft-lease.cc
// Author: Georgios Bitzes - CERN
// ----------------------------------------------------------------------
/************************************************************************
* quarkdb - a redis-like highly available key-value store *
* Copyright (C) 2016 CERN/Switzerland *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see .*
************************************************************************/
#include "raft/RaftLease.hh"
#include
using namespace quarkdb;
using namespace std::chrono;
TEST(Raft_Lease, basic_sanity_with_2_endpoints) {
std::vector targets;
targets.emplace_back("localhost", 1234);
steady_clock::duration leaseDuration(seconds(1));
RaftLease lease(targets, leaseDuration);
RaftLastContact &t1 = lease.getHandler(RaftServer("localhost", 1234));
steady_clock::time_point p0; // 0 ms
steady_clock::time_point p1 = p0 + milliseconds(500);
t1.heartbeat(p1);
ASSERT_EQ(lease.getDeadline(), p1 + leaseDuration);
ASSERT_EQ(lease.getShakyQuorumDeadline(), p1 + leaseDuration);
steady_clock::time_point p2 = p0 + milliseconds(501);
t1.heartbeat(p2);
ASSERT_EQ(lease.getDeadline(), p2 + leaseDuration);
ASSERT_EQ(lease.getShakyQuorumDeadline(), p2 + leaseDuration);
}
TEST(Raft_Lease, basic_sanity_with_3_endpoints) {
std::vector targets;
targets.emplace_back("localhost", 1234);
targets.emplace_back("example.com", 5678);
steady_clock::duration leaseDuration(seconds(1));
RaftLease lease(targets, leaseDuration);
RaftLastContact &t1 = lease.getHandler(RaftServer("localhost", 1234));
RaftLastContact &t2 = lease.getHandler(RaftServer("example.com", 5678));
steady_clock::time_point p0; // 0 ms
steady_clock::time_point p1 = p0 + milliseconds(500);
steady_clock::time_point p2 = p0 + milliseconds(1000);
t1.heartbeat(p1);
t2.heartbeat(p2);
ASSERT_EQ(lease.getDeadline(), p2 + leaseDuration);
ASSERT_EQ(lease.getShakyQuorumDeadline(), p1 + leaseDuration);
t1.heartbeat(p0 + milliseconds(750));
ASSERT_EQ(lease.getDeadline(), p2 + leaseDuration);
ASSERT_EQ(lease.getShakyQuorumDeadline(), p0 + milliseconds(750) + leaseDuration);
steady_clock::time_point p3 = p0 + milliseconds(1500);
t1.heartbeat(p3);
ASSERT_EQ(lease.getDeadline(), p3 + leaseDuration);
ASSERT_EQ(lease.getShakyQuorumDeadline(), p2 + leaseDuration);
steady_clock::time_point p4 = p0 + milliseconds(2000);
t2.heartbeat(p4);
ASSERT_EQ(lease.getDeadline(), p4 + leaseDuration);
ASSERT_EQ(lease.getShakyQuorumDeadline(), p3 + leaseDuration);
}
TEST(Raft_Lease, basic_sanity_with_5_endpoints) {
std::vector targets;
targets.emplace_back("localhost", 1234);
targets.emplace_back("example.com", 5678);
targets.emplace_back("localhost", 9999);
targets.emplace_back("example.com", 9999);
steady_clock::duration leaseDuration(seconds(1));
RaftLease lease(targets, leaseDuration);
RaftLastContact &t1 = lease.getHandler(RaftServer("localhost", 1234));
RaftLastContact &t2 = lease.getHandler(RaftServer("example.com", 5678));
RaftLastContact &t3 = lease.getHandler(RaftServer("localhost", 9999));
RaftLastContact &t4 = lease.getHandler(RaftServer("example.com", 9999));
steady_clock::time_point p0; // 0 ms
steady_clock::time_point p1 = p0 + milliseconds(500);
steady_clock::time_point p2 = p0 + milliseconds(750);
steady_clock::time_point p3 = p0 + milliseconds(800);
steady_clock::time_point p4 = p0 + milliseconds(900);
t1.heartbeat(p1);
t2.heartbeat(p2);
t3.heartbeat(p3);
t4.heartbeat(p4);
ASSERT_EQ(lease.getDeadline(), p3 + leaseDuration);
t1.heartbeat(p0 + milliseconds(600));
ASSERT_EQ(lease.getDeadline(), p3 + leaseDuration);
ASSERT_EQ(lease.getShakyQuorumDeadline(), p2 + leaseDuration);
t1.heartbeat(p0 + milliseconds(700));
ASSERT_EQ(lease.getDeadline(), p3 + leaseDuration);
ASSERT_EQ(lease.getShakyQuorumDeadline(), p2 + leaseDuration);
steady_clock::time_point p5 = p0 + milliseconds(801);
t1.heartbeat(p5);
ASSERT_EQ(lease.getDeadline(), p5 + leaseDuration);
ASSERT_EQ(lease.getShakyQuorumDeadline(), p3 + leaseDuration);
steady_clock::time_point p6 = p0 + milliseconds(10000);
t2.heartbeat(p6);
ASSERT_EQ(lease.getDeadline(), p4 + leaseDuration);
ASSERT_EQ(lease.getShakyQuorumDeadline(), p5 + leaseDuration);
}