// NewRealTimeCluster a new cluster with n logs. // All logs use a real-time clock instead of a test clock. func NewRealTimeCluster(logN int, fsmFn func() raft.FSM) *Cluster { c := &Cluster{} t := NewTransport() for i := 0; i < logN; i++ { l := NewLog(&url.URL{Host: fmt.Sprintf("log%d", i)}) l.Log.FSM = fsmFn() l.Clock = nil l.Log.Clock = raft.NewClock() l.Transport = t c.Logs = append(c.Logs, l) t.register(l.Log) warnf("Log %s: %p", l.URL.String(), l.Log) } warn("") // Initialize leader. c.Logs[0].MustOpen() c.Logs[0].MustInitialize() // Join remaining nodes. for i := 1; i < logN; i++ { c.Logs[i].MustOpen() c.Logs[i].MustJoin(c.Logs[0].URL) } // Ensure nodes are ready. index, _ := c.Logs[0].LastLogIndexTerm() for i := 0; i < logN; i++ { c.Logs[i].MustWait(index) } return c }
// Ensure the AfterReconnectTimeout returns a channel that fires after the clock's reconnect interval. func TestClock_AfterReconnectTimeout(t *testing.T) { c := raft.NewClock() c.ReconnectTimeout = 10 * time.Millisecond t0 := time.Now() <-c.AfterReconnectTimeout() if d := time.Since(t0); d < c.ReconnectTimeout { t.Fatalf("channel fired too soon: %v", d) } }
// Ensure the AfterHeartbeatInterval returns a channel that fires after the clock's heartbeat interval. func TestClock_AfterHeartbeatInterval(t *testing.T) { c := raft.NewClock() c.HeartbeatInterval = 10 * time.Millisecond t0 := time.Now() <-c.AfterHeartbeatInterval() if d := time.Since(t0); d < c.HeartbeatInterval { t.Fatalf("channel fired too soon: %v", d) } }
// Ensure the clock can return the current time. func TestClock_Now(t *testing.T) { now := raft.NewClock().Now() if exp := time.Now(); exp.Sub(now) > 1*time.Second { t.Fatalf("clock time is different than wall time: exp=%v, got=%v", exp, now) } }