use std::time::Duration;
use crate::prelude::*;
use crate::testutil;
use crate::testutil::{noopfuture, DeterministicGroup, DeterministicGroup1, DeterministicGroup3};
#[test]
fn election_one() {
testutil::log_init();
let mut g = DeterministicGroup1::new();
assert_eq!(g.n.raft.debug(), "candidate");
g.n.start_election();
assert_eq!(g.n.raft.debug(), "leader");
}
#[test]
fn election_multi() {
testutil::log_init();
let mut g = DeterministicGroup3::new();
assert_eq!(g.n0.raft.debug(), "candidate");
g.n0.start_election();
assert_eq!(g.n0.raft.debug(), "candidate");
assert_eq!(g.n1.raft.debug(), "candidate");
assert_eq!(g.n2.raft.debug(), "candidate");
g.drain();
assert_eq!(g.n0.raft.debug(), "leader");
assert_eq!(g.n1.raft.debug(), "follower");
assert_eq!(g.n2.raft.debug(), "follower");
}
#[test]
fn tick() {
testutil::log_init();
let mut g = DeterministicGroup3::new();
g.n0.tick(Duration::from_nanos(0));
g.n1.tick(Duration::from_nanos(0));
g.n2.tick(Duration::from_nanos(0));
assert_eq!(g.n0.raft.current_term(), Term(1));
g.n0.tick(g.cfg().election_timeout);
assert_eq!(g.n0.raft.current_term(), Term(2));
g.drain();
assert_eq!(g.n0.raft.debug(), "leader");
assert_eq!(g.n1.raft.debug(), "follower");
assert_eq!(g.n2.raft.debug(), "follower");
g.n0.tick(g.cfg().heartbeat_interval);
g.n1.tick(g.cfg().heartbeat_interval);
g.n2.tick(g.cfg().heartbeat_interval);
g.drain();
assert_eq!(g.n0.raft.debug(), "leader");
assert_eq!(g.n1.raft.debug(), "follower");
assert_eq!(g.n2.raft.debug(), "follower");
g.n1.tick(g.cfg().election_timeout);
g.drain();
assert_eq!(g.n0.raft.debug(), "follower");
assert_eq!(g.n1.raft.debug(), "leader");
assert_eq!(g.n2.raft.debug(), "follower");
}
#[test]
fn write_future() {
testutil::log_init();
let mut g = DeterministicGroup3::new();
g.n0.start_election();
g.drain();
let payload = String::from("write_future").into_bytes();
let mut res = g.n0.write(WriteReq { payload: payload.clone() });
noopfuture::assert_pending(&mut res);
g.drain();
let res = noopfuture::assert_ready(&mut res).unwrap();
assert_eq!(g.n0.log.get(res.index), Some(&payload));
}
#[test]
fn read_future() {
testutil::log_init();
let mut g = DeterministicGroup3::new();
g.n0.start_election();
g.drain();
let payload = String::from("read_future").into_bytes();
g.n0.write(WriteReq { payload: payload.clone() });
let mut read = g.n0.read(ReadReq { payload: vec![] });
noopfuture::assert_pending(&mut read);
g.drain();
let read = noopfuture::assert_ready(&mut read).unwrap();
assert_eq!(read.payload, payload);
}
#[test]
fn leader_timeout() {
testutil::log_init();
let mut g = DeterministicGroup3::new();
g.n0.start_election();
g.drain();
assert_eq!(g.n0.raft.debug(), "leader");
let payload = String::from("leader_timeout").into_bytes();
let req = WriteReq { payload: payload };
let mut res = g.n0.write(req);
g.n1.tick(g.cfg().election_timeout * 2);
g.drain();
assert_eq!(g.n1.raft.debug(), "leader");
assert_eq!(
noopfuture::assert_ready(&mut res),
Err(ClientError::NotLeaderError(NotLeaderError::new(Some(g.n1.raft.id()))))
);
}
#[test]
fn overwrite_entries() {
testutil::log_init();
let mut g = DeterministicGroup3::new();
g.n0.start_election();
g.drain();
assert_eq!(g.n0.raft.debug(), "leader");
let mut res = g.n0.write(WriteReq { payload: String::from("1").into_bytes() });
g.drain();
let _ = noopfuture::assert_ready(&mut res);
g.n0.write(WriteReq { payload: String::from("2").into_bytes() });
g.n1.start_election();
g.drain();
assert_eq!(g.n1.raft.debug(), "leader");
let mut res = g.n1.write(WriteReq { payload: String::from("3").into_bytes() });
g.drain();
let _ = noopfuture::assert_ready(&mut res);
g.n0.start_election();
g.drain();
assert_eq!(g.n0.raft.debug(), "leader");
println!("\n\nWIP\n\n");
let mut res = g.n0.read(ReadReq { payload: vec![] });
g.drain();
let res = noopfuture::assert_ready(&mut res).unwrap();
assert_eq!(res.payload, String::from("13").into_bytes());
}
#[test]
fn regression_request_starts_election() {
testutil::log_init();
{
let mut g = DeterministicGroup3::new();
let mut res1 = g.n0.write(WriteReq { payload: String::from("1").into_bytes() });
assert_eq!(
noopfuture::assert_ready(&mut res1),
Err(ClientError::NotLeaderError(NotLeaderError::new(Some(g.n0.raft.id()))))
);
g.drain();
assert_eq!(g.n0.raft.debug(), "leader");
}
{
let mut g = DeterministicGroup1::new();
let mut res1 = g.n.write(WriteReq { payload: String::from("1").into_bytes() });
noopfuture::assert_pending(&mut res1);
g.drain();
assert_eq!(g.n.raft.debug(), "leader");
assert_eq!(
noopfuture::assert_ready(&mut res1),
Ok(WriteRes { term: Term(1), index: Index(1) }),
);
}
{
let mut g = DeterministicGroup3::new();
let mut res1 = g.n0.read(ReadReq { payload: String::from("1").into_bytes() });
assert_eq!(
noopfuture::assert_ready(&mut res1),
Err(ClientError::NotLeaderError(NotLeaderError::new(Some(g.n0.raft.id()))))
);
g.drain();
assert_eq!(g.n0.raft.debug(), "leader");
}
{
let mut g = DeterministicGroup1::new();
let mut res1 = g.n.read(ReadReq { payload: String::from("1").into_bytes() });
noopfuture::assert_pending(&mut res1);
g.drain();
assert_eq!(g.n.raft.debug(), "leader");
assert_eq!(
noopfuture::assert_ready(&mut res1),
Ok(ReadRes { term: Term(1), index: Index(0), payload: vec![] })
);
}
}
#[test]
fn regression_follower_write() {
testutil::log_init();
let mut g = DeterministicGroup3::new();
g.n0.start_election();
g.drain();
assert_eq!(g.n1.raft.debug(), "follower");
g.n1.write(WriteReq { payload: String::from("1").into_bytes() });
}