163 lines
3.7 KiB
Go
163 lines
3.7 KiB
Go
package kvsrv
|
|
|
|
import (
|
|
// "log"
|
|
"runtime"
|
|
"testing"
|
|
"time"
|
|
|
|
"6.5840/kvsrv1/rpc"
|
|
"6.5840/kvtest1"
|
|
)
|
|
|
|
// Test Put with a single client and a reliable network
|
|
func TestReliablePut(t *testing.T) {
|
|
const Val = "6.5840"
|
|
const Ver = 0
|
|
|
|
ts := MakeTestKV(t, true)
|
|
defer ts.Cleanup()
|
|
|
|
ts.Begin("One client and reliable Put")
|
|
|
|
ck := ts.MakeClerk()
|
|
if err := ck.Put("k", Val, Ver); err != rpc.OK {
|
|
t.Fatalf("Put err %v", err)
|
|
}
|
|
|
|
if val, ver, err := ck.Get("k"); err != rpc.OK {
|
|
t.Fatalf("Get err %v; expected OK", err)
|
|
} else if val != Val {
|
|
t.Fatalf("Get value err %v; expected %v", val, Val)
|
|
} else if ver != Ver+1 {
|
|
t.Fatalf("Get wrong version %v; expected %v", ver, Ver+1)
|
|
}
|
|
|
|
if err := ck.Put("k", Val, 0); err != rpc.ErrVersion {
|
|
t.Fatalf("expected Put to fail with ErrVersion; got err=%v", err)
|
|
}
|
|
|
|
if err := ck.Put("y", Val, rpc.Tversion(1)); err != rpc.ErrNoKey {
|
|
t.Fatalf("expected Put to fail with ErrNoKey; got err=%v", err)
|
|
}
|
|
|
|
if _, _, err := ck.Get("y"); err != rpc.ErrNoKey {
|
|
t.Fatalf("expected Get to fail with ErrNoKey; got err=%v", err)
|
|
}
|
|
}
|
|
|
|
// Many clients putting on same key.
|
|
func TestPutConcurrentReliable(t *testing.T) {
|
|
const (
|
|
PORCUPINETIME = 10 * time.Second
|
|
NCLNT = 10
|
|
NSEC = 1
|
|
)
|
|
|
|
ts := MakeTestKV(t, true)
|
|
defer ts.Cleanup()
|
|
|
|
ts.Begin("Test: many clients racing to put values to the same key")
|
|
|
|
rs := ts.SpawnClientsAndWait(NCLNT, NSEC*time.Second, func(me int, ck kvtest.IKVClerk, done chan struct{}) kvtest.ClntRes {
|
|
return ts.OneClientPut(me, ck, []string{"k"}, done)
|
|
})
|
|
ck := ts.MakeClerk()
|
|
ts.CheckPutConcurrent(ck, "k", rs, &kvtest.ClntRes{})
|
|
ts.CheckPorcupineT(PORCUPINETIME)
|
|
}
|
|
|
|
// Check if memory used on server is reasonable
|
|
func TestMemPutManyClientsReliable(t *testing.T) {
|
|
const (
|
|
NCLIENT = 100_000
|
|
MEM = 1000
|
|
)
|
|
|
|
ts := MakeTestKV(t, true)
|
|
defer ts.Cleanup()
|
|
|
|
v := kvtest.RandValue(MEM)
|
|
|
|
cks := make([]kvtest.IKVClerk, NCLIENT)
|
|
for i, _ := range cks {
|
|
cks[i] = ts.MakeClerk()
|
|
}
|
|
|
|
// force allocation of ends for server in each client
|
|
for i := 0; i < NCLIENT; i++ {
|
|
if err := cks[i].Put("k", "", 1); err != rpc.ErrNoKey {
|
|
t.Fatalf("Put failed %v", err)
|
|
}
|
|
}
|
|
|
|
ts.Begin("Test: memory use many put clients")
|
|
|
|
// allow threads started by labrpc to start
|
|
time.Sleep(1 * time.Second)
|
|
|
|
runtime.GC()
|
|
runtime.GC()
|
|
|
|
var st runtime.MemStats
|
|
runtime.ReadMemStats(&st)
|
|
m0 := st.HeapAlloc
|
|
|
|
for i := 0; i < NCLIENT; i++ {
|
|
if err := cks[i].Put("k", v, rpc.Tversion(i)); err != rpc.OK {
|
|
t.Fatalf("Put failed %v", err)
|
|
}
|
|
}
|
|
|
|
runtime.GC()
|
|
time.Sleep(1 * time.Second)
|
|
runtime.GC()
|
|
|
|
runtime.ReadMemStats(&st)
|
|
m1 := st.HeapAlloc
|
|
f := (float64(m1) - float64(m0)) / NCLIENT
|
|
if m1 > m0+(NCLIENT*200) {
|
|
t.Fatalf("error: server using too much memory %d %d (%.2f per client)\n", m0, m1, f)
|
|
}
|
|
}
|
|
|
|
// Test with one client and unreliable network. If Clerk.Put returns
|
|
// ErrMaybe, the Put must have happened, since the test uses only one
|
|
// client.
|
|
func TestUnreliableNet(t *testing.T) {
|
|
const NTRY = 100
|
|
|
|
ts := MakeTestKV(t, false)
|
|
defer ts.Cleanup()
|
|
|
|
ts.Begin("One client")
|
|
|
|
ck := ts.MakeClerk()
|
|
|
|
retried := false
|
|
for try := 0; try < NTRY; try++ {
|
|
for i := 0; true; i++ {
|
|
if err := ts.PutJson(ck, "k", i, rpc.Tversion(try), 0); err != rpc.ErrMaybe {
|
|
if i > 0 && err != rpc.ErrVersion {
|
|
t.Fatalf("Put shouldn't have happen more than once %v", err)
|
|
}
|
|
break
|
|
}
|
|
// Try put again; it should fail with ErrVersion
|
|
retried = true
|
|
}
|
|
v := 0
|
|
if ver := ts.GetJson(ck, "k", 0, &v); ver != rpc.Tversion(try+1) {
|
|
t.Fatalf("Wrong version %d expect %d", ver, try+1)
|
|
}
|
|
if v != 0 {
|
|
t.Fatalf("Wrong value %d expect %d", v, 0)
|
|
}
|
|
}
|
|
if !retried {
|
|
t.Fatalf("Clerk.Put never returned ErrMaybe")
|
|
}
|
|
|
|
ts.CheckPorcupine()
|
|
}
|