Commit 2373e395 authored by Sushant Mahajan's avatar Sushant Mahajan

completed implementation, added test cases

parent e0747868
package main
import (
"fmt"
"raft"
)
const (
SERVERS = 5
)
func main() {
dummyCh := make(chan bool, 1)
fmt.Println("Started")
for i := 1; i <= 5; i++ {
go raft.Start(i, true)
}
if <-dummyCh {
fmt.Println("khattam")
}
}
This diff is collapsed.
...@@ -216,7 +216,7 @@ func main() { ...@@ -216,7 +216,7 @@ func main() {
go initInterServerCommunication(server, rft, ch2) go initInterServerCommunication(server, rft, ch2)
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
rft.Loop() go rft.Loop()
for <-ch1 && <-ch2 { for <-ch1 && <-ch2 {
......
...@@ -20,34 +20,37 @@ const ( ...@@ -20,34 +20,37 @@ const (
) )
type Testpair struct { type Testpair struct {
to_server []byte test []byte
from_server []byte expected []byte
} }
var LeaderId int var LeaderId int
var Info *log.Logger var logger *log.Logger
var keyPrefix int
func getPrefix() int {
keyPrefix++
return keyPrefix
}
// //
func TestAll(t *testing.T) { func TestAll(t *testing.T) {
//start the servers //start the servers
initLogger() initTestLogger()
for i := 0; i < NUM_SERVERS; i++ { for i := 0; i < NUM_SERVERS; i++ {
go startServers(i, t) go startServers(i, t)
} }
//wait for some time so that servers are ready //wait for some time so that servers are ready
time.Sleep(5 * time.Second)
time.Sleep(8 * time.Second)
testPerformClientConnect(t) testPerformClientConnect(t)
testPerformSet(t, 1) testCommands(t)
testPerformSet(t, 2)
testPerformSet(t, 3)
testPerformSet(t, 4)
//testKillLeader(t)
killServers() killServers()
} }
//kill all servers, cleanup
func killServers() { func killServers() {
Info.Println("killing servers") logger.Println("killing servers")
cmd := exec.Command("sh", "-c", "for i in `netstat -ntlp|grep server|awk '{print $7}'`; do kill -9 ${i%%/*}; done") cmd := exec.Command("sh", "-c", "for i in `netstat -ntlp|grep server|awk '{print $7}'`; do kill -9 ${i%%/*}; done")
cmd.Run() cmd.Run()
} }
...@@ -66,6 +69,7 @@ func startServers(i int, t *testing.T) { ...@@ -66,6 +69,7 @@ func startServers(i int, t *testing.T) {
cmd.Run() cmd.Run()
} }
//check which server is the leader
func probeLeader(t *testing.T) (int, error) { func probeLeader(t *testing.T) (int, error) {
if conn, err := net.Dial("tcp", ":"+strconv.Itoa(9000)); err != nil { if conn, err := net.Dial("tcp", ":"+strconv.Itoa(9000)); err != nil {
t.Errorf("Could not connect") t.Errorf("Could not connect")
...@@ -87,6 +91,7 @@ func probeLeader(t *testing.T) (int, error) { ...@@ -87,6 +91,7 @@ func probeLeader(t *testing.T) (int, error) {
} }
} }
//returns a connection to the leader server
func getLeaderConn(t *testing.T) net.Conn { func getLeaderConn(t *testing.T) net.Conn {
if conn, err := net.Dial("tcp", ":"+strconv.Itoa(9000+LeaderId)); err != nil { if conn, err := net.Dial("tcp", ":"+strconv.Itoa(9000+LeaderId)); err != nil {
t.Errorf("Could not connect") t.Errorf("Could not connect")
...@@ -96,10 +101,10 @@ func getLeaderConn(t *testing.T) net.Conn { ...@@ -96,10 +101,10 @@ func getLeaderConn(t *testing.T) net.Conn {
} }
} }
func initLogger() { //initialize logger meant for test cases
// Logger Initializaion func initTestLogger() {
f, _ := os.OpenFile("test.log", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666) f, _ := os.OpenFile("test.log", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
Info = log.New(f, "INFO: ", log.Ldate|log.Lmicroseconds|log.Lshortfile) logger = log.New(f, "INFO: ", log.Ldate|log.Lmicroseconds|log.Lshortfile)
} }
func testPerformClientConnect(t *testing.T) { func testPerformClientConnect(t *testing.T) {
...@@ -109,24 +114,96 @@ func testPerformClientConnect(t *testing.T) { ...@@ -109,24 +114,96 @@ func testPerformClientConnect(t *testing.T) {
} else if id < 0 || id > 4 { } else if id < 0 || id > 4 {
t.Errorf("Invalid leader id") t.Errorf("Invalid leader id")
} }
Info.Println("Leader Id:", id) logger.Println("Leader Id:", id)
}
func testCommands(t *testing.T) {
testPerformMultipleSet(t, getPrefix(), 1) //check single set
testPerformMultipleSet(t, getPrefix(), 200)
testPerformCas(t)
testPerformMultipleCas(t, 200)
testPerformMultipleGet(t, 200)
testPerformMultipleGetm(t, 200)
testPerformMultipleDelete(t, 100)
}
func doTest(conn net.Conn, t *testing.T, test *Testpair) {
conn.Write(test.test)
buf := make([]byte, 1024)
time.Sleep(time.Millisecond * 20)
n, _ := conn.Read(buf)
if !bytes.Equal(test.expected, buf[:n]) {
logger.Println("test:", string(test.test), "got:", string(buf[:n]), "expected:", string(test.expected))
t.Errorf("invalid reply received", string(buf[:n]))
}
} }
func testPerformSet(t *testing.T, i int) { func testPerformMultipleSet(t *testing.T, start int, times int) {
if conn := getLeaderConn(t); conn != nil { if conn := getLeaderConn(t); conn != nil {
sending := []byte("set mykey" + strconv.Itoa(i) + " 100 3\r\nlul\r\n") defer conn.Close()
conn.Write(sending) for i := start; i < start+times; i++ {
buffer := make([]byte, 1024) test := &Testpair{[]byte("set mykey" + strconv.Itoa(i) + " 0 3\r\nlul\r\n"), []byte("OK 1\r\n")}
time.Sleep(time.Millisecond * 50) doTest(conn, t, test)
conn.Read(buffer) }
n := bytes.Index(buffer, []byte{0}) } else {
str := string(buffer[:n]) t.Errorf("could not get leader connection")
if strings.TrimSpace(str) != "OK "+strconv.Itoa(1) { }
t.Errorf("invalid reply received", str) }
} else {
Info.Println(str) func testPerformCas(t *testing.T) {
if conn := getLeaderConn(t); conn != nil {
defer conn.Close()
test := &Testpair{[]byte("cas mykey1 1000 1 3\r\nlul\r\n"), []byte("OK 2\r\n")}
doTest(conn, t, test)
} else {
t.Errorf("could not get leader connection")
}
}
func testPerformMultipleCas(t *testing.T, end int) {
if conn := getLeaderConn(t); conn != nil {
defer conn.Close()
for i := 0; i < end; i++ {
test := &Testpair{[]byte("cas mykey2 1000 " + strconv.Itoa(i+1) + " 3\r\nlul\r\n"), []byte("OK " + strconv.Itoa(i+2) + "\r\n")}
doTest(conn, t, test)
}
} else {
t.Errorf("could not get leader connection")
}
}
func testPerformMultipleGet(t *testing.T, end int) {
if conn := getLeaderConn(t); conn != nil {
defer conn.Close()
for i := 0; i < end; i++ {
test := &Testpair{[]byte("get mykey3\r\n"), []byte("VALUE 3\r\nlul\r\n")}
doTest(conn, t, test)
}
} else {
t.Errorf("could not get leader connection")
}
}
func testPerformMultipleGetm(t *testing.T, end int) {
if conn := getLeaderConn(t); conn != nil {
defer conn.Close()
for i := 0; i < end; i++ {
test := &Testpair{[]byte("getm mykey4\r\n"), []byte("VALUE 1 0 3\r\nlul\r\n")}
doTest(conn, t, test)
}
} else {
t.Errorf("could not get leader connection")
}
}
func testPerformMultipleDelete(t *testing.T, end int) {
if conn := getLeaderConn(t); conn != nil {
defer conn.Close()
for i := 0; i < end; i++ {
test := &Testpair{[]byte("delete mykey" + strconv.Itoa(i+1) + "\r\n"), []byte("DELETED\r\n")}
doTest(conn, t, test)
} }
conn.Close()
} else { } else {
t.Errorf("could not get leader connection") t.Errorf("could not get leader connection")
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment