Merge pull request #133 from xiangli-cmu/master

add killAllAndRecovery test
release-0.4
Xiang Li 2013-08-19 10:51:18 -07:00
commit e7caa1475e
5 changed files with 84 additions and 15 deletions

View File

@ -118,17 +118,17 @@ func (c *WatchCommand) Apply(server *raft.Server) (interface{}, error) {
// JoinCommand
type JoinCommand struct {
RaftVersion string `json:"raftVersion"`
Name string `json:"name"`
RaftURL string `json:"raftURL"`
EtcdURL string `json:"etcdURL"`
Name string `json:"name"`
RaftURL string `json:"raftURL"`
EtcdURL string `json:"etcdURL"`
}
func newJoinCommand() *JoinCommand {
return &JoinCommand{
RaftVersion: r.version,
Name: r.name,
RaftURL: r.url,
EtcdURL: e.url,
Name: r.name,
RaftURL: r.url,
EtcdURL: e.url,
}
}

View File

@ -78,7 +78,7 @@ func TestInternalVersionFail(t *testing.T) {
procAttr := new(os.ProcAttr)
procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr}
args := []string{"etcd", "-n=node1", "-f", "-d=/tmp/node1", "-vv", "-C="+fakeURL.Host}
args := []string{"etcd", "-n=node1", "-f", "-d=/tmp/node1", "-vv", "-C=" + fakeURL.Host}
process, err := os.StartProcess("etcd", args, procAttr)
if err != nil {
@ -102,7 +102,6 @@ func TestInternalVersionFail(t *testing.T) {
}
}
// This test creates a single node and then set a value to it.
// Then this test kills the node and restart it and tries to get the value again.
func TestSingleNodeRecovery(t *testing.T) {
@ -214,9 +213,73 @@ func TestSimpleMultiNodeTls(t *testing.T) {
templateTestSimpleMultiNode(t, true)
}
// Create a five nodes
// Kill all the nodes and restart
func TestMultiNodeKillAllAndRecovery(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")
}
c := etcd.NewClient()
c.SyncCluster()
time.Sleep(time.Second)
// send 10 commands
for i := 0; i < 10; i++ {
// Test Set
_, err := c.Set("foo", "bar", 0)
if err != nil {
panic(err)
}
}
time.Sleep(time.Second)
// kill all
test.DestroyCluster(etcds)
time.Sleep(time.Second)
stop := make(chan bool)
leaderChan := make(chan string, 1)
all := make(chan bool, 1)
time.Sleep(time.Second)
for i := 0; i < clusterSize; i++ {
etcds[i], err = os.StartProcess("etcd", argGroup[i], procAttr)
}
go test.Monitor(clusterSize, 1, leaderChan, all, stop)
<-all
<-leaderChan
result, err := c.Set("foo", "bar", 0)
if err != nil {
panic(err)
}
if result.Index != 18 {
t.Fatalf("recovery failed! [%d/18]", result.Index)
}
// kill all
test.DestroyCluster(etcds)
}
// Create a five nodes
// Randomly kill one of the node and keep on sending set command to the cluster
func TestMultiNodeRecovery(t *testing.T) {
func TestMultiNodeKillOne(t *testing.T) {
procAttr := new(os.ProcAttr)
procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr}

View File

@ -8,8 +8,8 @@ import (
// we map node name to url
type nodeInfo struct {
raftVersion string
raftURL string
etcdURL string
raftURL string
etcdURL string
}
var namesMap = make(map[string]*nodeInfo)
@ -43,8 +43,8 @@ func nameToRaftURL(name string) (string, bool) {
func addNameToURL(name string, version string, raftURL string, etcdURL string) {
namesMap[name] = &nodeInfo{
raftVersion: raftVersion,
raftURL: raftURL,
etcdURL: etcdURL,
raftURL: raftURL,
etcdURL: etcdURL,
}
}

View File

@ -4,10 +4,10 @@ import (
"bytes"
"crypto/tls"
"encoding/json"
"io/ioutil"
"fmt"
etcdErr "github.com/coreos/etcd/error"
"github.com/coreos/go-raft"
"io/ioutil"
"net/http"
"net/url"
"time"

View File

@ -170,7 +170,13 @@ func (c *Client) getHttpPath(s ...string) string {
func (c *Client) updateLeader(httpPath string) {
u, _ := url.Parse(httpPath)
leader := u.Host
var leader string
if u.Scheme == "" {
leader = "http://" + u.Host
} else {
leader = u.Scheme + "://" + u.Host
}
logger.Debugf("update.leader[%s,%s]", c.cluster.Leader, leader)
c.cluster.Leader = leader