6.5840/src/kvraft1/rsm/test.go
Frans Kaashoek c8e7d779c2 update
2025-02-18 07:04:18 -05:00

149 lines
2.7 KiB
Go

package rsm
import (
//"log"
"testing"
"time"
"6.5840/kvsrv1/rpc"
"6.5840/labrpc"
"6.5840/raftapi"
"6.5840/tester1"
)
type Test struct {
*tester.Config
t *testing.T
g *tester.ServerGrp
maxraftstate int
srvs []*rsmSrv
leader int
}
const (
NSRV = 3
NSEC = 10
Gid = tester.GRP0
)
func makeTest(t *testing.T, maxraftstate int) *Test {
ts := &Test{
t: t,
maxraftstate: maxraftstate,
srvs: make([]*rsmSrv, NSRV),
}
ts.Config = tester.MakeConfig(t, NSRV, true, ts.mksrv)
ts.g = ts.Group(tester.GRP0)
return ts
}
func (ts *Test) cleanup() {
ts.End()
ts.Config.Cleanup()
ts.CheckTimeout()
}
func (ts *Test) mksrv(ends []*labrpc.ClientEnd, grp tester.Tgid, srv int, persister *tester.Persister) []tester.IService {
s := makeRsmSrv(ts, srv, ends, persister, false)
ts.srvs[srv] = s
return []tester.IService{s.rsm.Raft()}
}
func inPartition(s int, p []int) bool {
if p == nil {
return true
}
for _, i := range p {
if s == i {
return true
}
}
return false
}
func (ts *Test) oneIncPartition(p []int) *Rep {
// try all the servers, maybe one is the leader but give up after NSEC
t0 := time.Now()
for time.Since(t0).Seconds() < NSEC {
index := ts.leader
for range ts.srvs {
if ts.g.IsConnected(index) {
s := ts.srvs[index]
if s.rsm != nil && inPartition(index, p) {
err, rep := s.rsm.Submit(Inc{})
if err == rpc.OK {
ts.leader = index
//log.Printf("leader = %d", ts.leader)
return rep.(*Rep)
}
}
}
index = (index + 1) % len(ts.srvs)
}
time.Sleep(50 * time.Millisecond)
//log.Printf("try again: no leader")
}
ts.Fatalf("one: took too long")
return nil
}
func (ts *Test) oneInc() *Rep {
return ts.oneIncPartition(nil)
}
func (ts *Test) checkCounter(v int, nsrv int) {
to := 10 * time.Millisecond
n := 0
for iters := 0; iters < 30; iters++ {
n = ts.countValue(v)
if n >= nsrv {
return
}
time.Sleep(to)
if to < time.Second {
to *= 2
}
}
ts.Fatalf("checkCounter: only %d srvs have %v instead of %d", n, v, nsrv)
}
func (ts *Test) countValue(v int) int {
i := 0
for _, s := range ts.srvs {
s.mu.Lock()
if s.counter == v {
i += 1
}
s.mu.Unlock()
}
return i
}
func (ts *Test) disconnectLeader() int {
//log.Printf("disconnect %d", ts.leader)
ts.g.DisconnectAll(ts.leader)
return ts.leader
}
func (ts *Test) connect(i int) {
//log.Printf("connect %d", i)
ts.g.ConnectOne(i)
}
func Leader(cfg *tester.Config, gid tester.Tgid) (bool, int) {
for i, ss := range cfg.Group(gid).Services() {
for _, s := range ss {
switch r := s.(type) {
case raftapi.Raft:
_, isLeader := r.GetState()
if isLeader {
return true, i
}
default:
}
}
}
return false, 0
}