123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- package test
- import (
- "fmt"
- "math/rand"
- "os"
- "strconv"
- "strings"
- "testing"
- "time"
- "github.com/coreos/etcd/third_party/github.com/coreos/go-etcd/etcd"
- )
- func increasePeerAddressPort(args []string, delta int) []string {
- for i, arg := range args {
- if !strings.Contains(arg, "peer-addr") {
- continue
- }
- splitArg := strings.Split(arg, ":")
- port, _ := strconv.Atoi(splitArg[len(splitArg)-1])
- args[i] = "-peer-addr=127.0.0.1:" + strconv.Itoa(port+delta)
- return args
- }
- return append(args, "-peer-addr=127.0.0.1:"+strconv.Itoa(7001+delta))
- }
- func increaseAddressPort(args []string, delta int) []string {
- for i, arg := range args {
- if !strings.HasPrefix(arg, "-addr") && !strings.HasPrefix(arg, "--addr") {
- continue
- }
- splitArg := strings.Split(arg, ":")
- port, _ := strconv.Atoi(splitArg[len(splitArg)-1])
- args[i] = "-addr=127.0.0.1:" + strconv.Itoa(port+delta)
- return args
- }
- return append(args, "-addr=127.0.0.1:"+strconv.Itoa(4001+delta))
- }
- func increaseDataDir(args []string, delta int) []string {
- for i, arg := range args {
- if !strings.Contains(arg, "-data-dir") {
- continue
- }
- splitArg := strings.Split(arg, "node")
- idx, _ := strconv.Atoi(splitArg[len(splitArg)-1])
- args[i] = "-data-dir=/tmp/node" + strconv.Itoa(idx+delta)
- return args
- }
- return args
- }
- // Create a five-node cluster
- // Random kill one of the nodes and restart it with different peer address
- func TestRejoinWithDifferentPeerAddress(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)
- time.Sleep(2 * time.Second)
- for i := 0; i < 10; i++ {
- num := rand.Int() % clusterSize
- fmt.Println("kill node", num+1)
- etcds[num].Kill()
- etcds[num].Release()
- time.Sleep(time.Second)
- argGroup[num] = increasePeerAddressPort(argGroup[num], clusterSize)
- // restart
- etcds[num], err = os.StartProcess(EtcdBinPath, argGroup[num], procAttr)
- if err != nil {
- panic(err)
- }
- time.Sleep(time.Second)
- }
- c := etcd.NewClient(nil)
- c.SyncCluster()
- result, err := c.Set("foo", "bar", 0)
- if err != nil || result.Node.Key != "/foo" || result.Node.Value != "bar" {
- t.Fatal("Failed to set value in etcd cluster")
- }
- }
- // Create a five-node cluster
- // Replace one of the nodes with different peer address
- func TestReplaceWithDifferentPeerAddress(t *testing.T) {
- // TODO(yichengq): find some way to avoid the error that will be
- // caused if some node joins the cluster with the collided name.
- // Possible solutions:
- // 1. Remove itself when executing a join command with the same name
- // and different peer address. However, it should find some way to
- // trigger that execution because the leader may update its address
- // and stop heartbeat.
- // 2. Remove the node with the same name before join each time.
- // But this way could be rather overkill.
- t.Skip("Unimplemented functionality")
- 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)
- time.Sleep(2 * time.Second)
- rand.Int()
- for i := 0; i < 10; i++ {
- num := rand.Int() % clusterSize
- fmt.Println("replace node", num+1)
- argGroup[num] = increasePeerAddressPort(argGroup[num], clusterSize)
- argGroup[num] = increaseAddressPort(argGroup[num], clusterSize)
- argGroup[num] = increaseDataDir(argGroup[num], clusterSize)
- // restart
- newEtcd, err := os.StartProcess(EtcdBinPath, append(argGroup[num], "-f"), procAttr)
- if err != nil {
- panic(err)
- }
- etcds[num].Wait()
- etcds[num] = newEtcd
- }
- c := etcd.NewClient(nil)
- c.SyncCluster()
- result, err := c.Set("foo", "bar", 0)
- if err != nil || result.Node.Key != "/foo" || result.Node.Value != "bar" {
- t.Fatal("Failed to set value in etcd cluster")
- }
- }
- // Create a five-node cluster
- // Let the sixth instance join with different name and existing peer address
- func TestRejoinWithDifferentName(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)
- time.Sleep(2 * time.Second)
- num := rand.Int() % clusterSize
- fmt.Println("join node 6 that collides with node", num+1)
- // kill
- etcds[num].Kill()
- etcds[num].Release()
- time.Sleep(time.Second)
- for i := 0; i < 2; i++ {
- // restart
- if i == 0 {
- etcds[num], err = os.StartProcess(EtcdBinPath, append(argGroup[num], "-name=node6", "-peers=127.0.0.1:7002"), procAttr)
- } else {
- etcds[num], err = os.StartProcess(EtcdBinPath, append(argGroup[num], "-f", "-name=node6", "-peers=127.0.0.1:7002"), procAttr)
- }
- if err != nil {
- t.Fatal("failed to start process:", err)
- }
- timer := time.AfterFunc(10*time.Second, func() {
- t.Fatal("new etcd should fail immediately")
- })
- etcds[num].Wait()
- etcds[num] = nil
- timer.Stop()
- }
- }
|