From 177854c3e19947449a935147e2d6df8bccbe8030 Mon Sep 17 00:00:00 2001 From: Xiang Li Date: Wed, 14 Aug 2013 13:07:39 -0700 Subject: [PATCH] add test package. do not compile test codes with etcd --- .travis.yml | 2 +- etcd_long_test.go | 157 --------------------------------------- etcd_test.go | 160 ++++++++++++++++++++++++++++++++++++++-- test => test.sh | 0 test.go => test/test.go | 32 ++------ util.go | 25 +++++++ 6 files changed, 185 insertions(+), 191 deletions(-) delete mode 100644 etcd_long_test.go rename test => test.sh (100%) rename test.go => test/test.go (86%) diff --git a/.travis.yml b/.travis.yml index e4a847362..711ad5b5a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,4 +5,4 @@ install: - echo "Skip install" script: - - ./test + - .test/test diff --git a/etcd_long_test.go b/etcd_long_test.go deleted file mode 100644 index 467b41749..000000000 --- a/etcd_long_test.go +++ /dev/null @@ -1,157 +0,0 @@ -package main - -import ( - "fmt" - "math/rand" - "net/http" - "os" - "strconv" - "strings" - "testing" - "time" -) - -// This test will kill the current leader and wait for the etcd cluster to elect a new leader for 200 times. -// It will print out the election time and the average election time. -func TestKillLeader(t *testing.T) { - procAttr := new(os.ProcAttr) - procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr} - - clusterSize := 5 - argGroup, etcds, err := createCluster(clusterSize, procAttr, false) - - if err != nil { - t.Fatal("cannot create cluster") - } - - defer destroyCluster(etcds) - - stop := make(chan bool) - leaderChan := make(chan string, 1) - all := make(chan bool, 1) - - time.Sleep(time.Second) - - go monitor(clusterSize, 1, leaderChan, all, stop) - - var totalTime time.Duration - - leader := "http://127.0.0.1:7001" - - for i := 0; i < clusterSize; i++ { - fmt.Println("leader is ", leader) - port, _ := strconv.Atoi(strings.Split(leader, ":")[2]) - num := port - 7001 - fmt.Println("kill server ", num) - etcds[num].Kill() - etcds[num].Release() - - start := time.Now() - for { - newLeader := <-leaderChan - if newLeader != leader { - leader = newLeader - break - } - } - take := time.Now().Sub(start) - - totalTime += take - avgTime := totalTime / (time.Duration)(i+1) - - fmt.Println("Leader election time is ", take, "with election timeout", ElectionTimeout) - fmt.Println("Leader election time average is", avgTime, "with election timeout", ElectionTimeout) - etcds[num], err = os.StartProcess("etcd", argGroup[num], procAttr) - } - stop <- true -} - -// TestKillRandom kills random machines in the cluster and -// restart them after all other machines agree on the same leader -func TestKillRandom(t *testing.T) { - procAttr := new(os.ProcAttr) - procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr} - - clusterSize := 9 - argGroup, etcds, err := createCluster(clusterSize, procAttr, false) - - if err != nil { - t.Fatal("cannot create cluster") - } - - defer destroyCluster(etcds) - - stop := make(chan bool) - leaderChan := make(chan string, 1) - all := make(chan bool, 1) - - time.Sleep(3 * time.Second) - - go monitor(clusterSize, 4, leaderChan, all, stop) - - toKill := make(map[int]bool) - - for i := 0; i < 200; i++ { - fmt.Printf("TestKillRandom Round[%d/200]\n", i) - - j := 0 - for { - - r := rand.Int31n(9) - if _, ok := toKill[int(r)]; !ok { - j++ - toKill[int(r)] = true - } - - if j > 3 { - break - } - - } - - for num, _ := range toKill { - etcds[num].Kill() - etcds[num].Release() - } - - time.Sleep(ElectionTimeout) - - <-leaderChan - - for num, _ := range toKill { - etcds[num], err = os.StartProcess("etcd", argGroup[num], procAttr) - } - - toKill = make(map[int]bool) - <-all - } - - stop <- true -} - -func templateBenchmarkEtcdDirectCall(b *testing.B, tls bool) { - procAttr := new(os.ProcAttr) - procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr} - - clusterSize := 3 - _, etcds, _ := createCluster(clusterSize, procAttr, tls) - - defer destroyCluster(etcds) - - time.Sleep(time.Second) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - resp, _ := http.Get("http://127.0.0.1:4001/test/speed") - resp.Body.Close() - } - -} - -func BenchmarkEtcdDirectCall(b *testing.B) { - templateBenchmarkEtcdDirectCall(b, false) -} - -func BenchmarkEtcdDirectCallTls(b *testing.B) { - templateBenchmarkEtcdDirectCall(b, true) -} diff --git a/etcd_test.go b/etcd_test.go index 5cfbc07a0..596a16cb7 100644 --- a/etcd_test.go +++ b/etcd_test.go @@ -2,10 +2,13 @@ package main import ( "fmt" + "github.com/coreos/etcd/test" "github.com/coreos/go-etcd/etcd" "math/rand" + "net/http" "os" - //"strconv" + "strconv" + "strings" "testing" "time" ) @@ -116,13 +119,13 @@ func templateTestSimpleMultiNode(t *testing.T, tls bool) { clusterSize := 3 - _, etcds, err := createCluster(clusterSize, procAttr, tls) + _, etcds, err := test.CreateCluster(clusterSize, procAttr, tls) if err != nil { t.Fatal("cannot create cluster") } - defer destroyCluster(etcds) + defer test.DestroyCluster(etcds) time.Sleep(time.Second) @@ -169,13 +172,13 @@ func TestMultiNodeRecovery(t *testing.T) { procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr} clusterSize := 5 - argGroup, etcds, err := createCluster(clusterSize, procAttr, false) + argGroup, etcds, err := test.CreateCluster(clusterSize, procAttr, false) if err != nil { t.Fatal("cannot create cluster") } - defer destroyCluster(etcds) + defer test.DestroyCluster(etcds) time.Sleep(2 * time.Second) @@ -185,7 +188,7 @@ func TestMultiNodeRecovery(t *testing.T) { stop := make(chan bool) // Test Set - go set(stop) + go test.Set(stop) for i := 0; i < 10; i++ { num := rand.Int() % clusterSize @@ -207,3 +210,148 @@ func TestMultiNodeRecovery(t *testing.T) { stop <- true <-stop } + +// This test will kill the current leader and wait for the etcd cluster to elect a new leader for 200 times. +// It will print out the election time and the average election time. +func TestKillLeader(t *testing.T) { + procAttr := new(os.ProcAttr) + procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr} + + clusterSize := 5 + argGroup, etcds, err := test.CreateCluster(clusterSize, procAttr, false) + + if err != nil { + t.Fatal("cannot create cluster") + } + + defer test.DestroyCluster(etcds) + + stop := make(chan bool) + leaderChan := make(chan string, 1) + all := make(chan bool, 1) + + time.Sleep(time.Second) + + go test.Monitor(clusterSize, 1, leaderChan, all, stop) + + var totalTime time.Duration + + leader := "http://127.0.0.1:7001" + + for i := 0; i < clusterSize; i++ { + fmt.Println("leader is ", leader) + port, _ := strconv.Atoi(strings.Split(leader, ":")[2]) + num := port - 7001 + fmt.Println("kill server ", num) + etcds[num].Kill() + etcds[num].Release() + + start := time.Now() + for { + newLeader := <-leaderChan + if newLeader != leader { + leader = newLeader + break + } + } + take := time.Now().Sub(start) + + totalTime += take + avgTime := totalTime / (time.Duration)(i+1) + + fmt.Println("Leader election time is ", take, "with election timeout", ElectionTimeout) + fmt.Println("Leader election time average is", avgTime, "with election timeout", ElectionTimeout) + etcds[num], err = os.StartProcess("etcd", argGroup[num], procAttr) + } + stop <- true +} + +// TestKillRandom kills random machines in the cluster and +// restart them after all other machines agree on the same leader +func TestKillRandom(t *testing.T) { + procAttr := new(os.ProcAttr) + procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr} + + clusterSize := 9 + argGroup, etcds, err := test.CreateCluster(clusterSize, procAttr, false) + + if err != nil { + t.Fatal("cannot create cluster") + } + + defer test.DestroyCluster(etcds) + + stop := make(chan bool) + leaderChan := make(chan string, 1) + all := make(chan bool, 1) + + time.Sleep(3 * time.Second) + + go test.Monitor(clusterSize, 4, leaderChan, all, stop) + + toKill := make(map[int]bool) + + for i := 0; i < 200; i++ { + fmt.Printf("TestKillRandom Round[%d/200]\n", i) + + j := 0 + for { + + r := rand.Int31n(9) + if _, ok := toKill[int(r)]; !ok { + j++ + toKill[int(r)] = true + } + + if j > 3 { + break + } + + } + + for num, _ := range toKill { + etcds[num].Kill() + etcds[num].Release() + } + + time.Sleep(ElectionTimeout) + + <-leaderChan + + for num, _ := range toKill { + etcds[num], err = os.StartProcess("etcd", argGroup[num], procAttr) + } + + toKill = make(map[int]bool) + <-all + } + + stop <- true +} + +func templateBenchmarkEtcdDirectCall(b *testing.B, tls bool) { + procAttr := new(os.ProcAttr) + procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr} + + clusterSize := 3 + _, etcds, _ := test.CreateCluster(clusterSize, procAttr, tls) + + defer test.DestroyCluster(etcds) + + time.Sleep(time.Second) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + resp, _ := http.Get("http://127.0.0.1:4001/test/speed") + resp.Body.Close() + } + +} + +func BenchmarkEtcdDirectCall(b *testing.B) { + templateBenchmarkEtcdDirectCall(b, false) +} + +func BenchmarkEtcdDirectCallTls(b *testing.B) { + templateBenchmarkEtcdDirectCall(b, true) +} diff --git a/test b/test.sh similarity index 100% rename from test rename to test.sh diff --git a/test.go b/test/test.go similarity index 86% rename from test.go rename to test/test.go index 39a423d3b..afa1eeca0 100644 --- a/test.go +++ b/test/test.go @@ -1,4 +1,4 @@ -package main +package test import ( "fmt" @@ -18,7 +18,7 @@ var client = http.Client{ } // Sending set commands -func set(stop chan bool) { +func Set(stop chan bool) { stopSet := false i := 0 @@ -54,7 +54,7 @@ func set(stop chan bool) { } // Create a cluster of etcd nodes -func createCluster(size int, procAttr *os.ProcAttr, ssl bool) ([][]string, []*os.Process, error) { +func CreateCluster(size int, procAttr *os.ProcAttr, ssl bool) ([][]string, []*os.Process, error) { argGroup := make([][]string, size) sslServer1 := []string{"-serverCAFile=./fixtures/ca/ca.crt", @@ -104,7 +104,7 @@ func createCluster(size int, procAttr *os.ProcAttr, ssl bool) ([][]string, []*os } // Destroy all the nodes in the cluster -func destroyCluster(etcds []*os.Process) error { +func DestroyCluster(etcds []*os.Process) error { for _, etcd := range etcds { err := etcd.Kill() if err != nil { @@ -116,7 +116,7 @@ func destroyCluster(etcds []*os.Process) error { } // -func monitor(size int, allowDeadNum int, leaderChan chan string, all chan bool, stop chan bool) { +func Monitor(size int, allowDeadNum int, leaderChan chan string, all chan bool, stop chan bool) { leaderMap := make(map[int]string) baseAddrFormat := "http://0.0.0.0:400%d" @@ -199,28 +199,6 @@ func getLeader(addr string) (string, error) { } -func directSet() { - c := make(chan bool, 1000) - for i := 0; i < 1000; i++ { - go send(c) - } - - for i := 0; i < 1000; i++ { - <-c - } -} - -func send(c chan bool) { - for i := 0; i < 10; i++ { - command := &SetCommand{} - command.Key = "foo" - command.Value = "bar" - command.ExpireTime = time.Unix(0, 0) - raftServer.Do(command) - } - c <- true -} - // Dial with timeout func dialTimeoutFast(network, addr string) (net.Conn, error) { return net.DialTimeout(network, addr, time.Millisecond*10) diff --git a/util.go b/util.go index 4914a4a86..7642a2706 100644 --- a/util.go +++ b/util.go @@ -177,3 +177,28 @@ func runCPUProfile() { } }() } + +//-------------------------------------- +// Testing +//-------------------------------------- +func directSet() { + c := make(chan bool, 1000) + for i := 0; i < 1000; i++ { + go send(c) + } + + for i := 0; i < 1000; i++ { + <-c + } +} + +func send(c chan bool) { + for i := 0; i < 10; i++ { + command := &SetCommand{} + command.Key = "foo" + command.Value = "bar" + command.ExpireTime = time.Unix(0, 0) + raftServer.Do(command) + } + c <- true +}