github.com/qorio/etcd@v0.1.2-0.20131003183127-5cc585af9618/test/test.go (about) 1 package test 2 3 import ( 4 "fmt" 5 "github.com/coreos/go-etcd/etcd" 6 "io/ioutil" 7 "net" 8 "net/http" 9 "os" 10 "strconv" 11 "time" 12 ) 13 14 var client = http.Client{ 15 Transport: &http.Transport{ 16 Dial: dialTimeoutFast, 17 }, 18 } 19 20 // Sending set commands 21 func Set(stop chan bool) { 22 23 stopSet := false 24 i := 0 25 c := etcd.NewClient() 26 for { 27 key := fmt.Sprintf("%s_%v", "foo", i) 28 29 result, err := c.Set(key, "bar", 0) 30 31 if err != nil || result.Key != "/"+key || result.Value != "bar" { 32 select { 33 case <-stop: 34 stopSet = true 35 36 default: 37 } 38 } 39 40 select { 41 case <-stop: 42 stopSet = true 43 44 default: 45 } 46 47 if stopSet { 48 break 49 } 50 51 i++ 52 } 53 stop <- true 54 } 55 56 // Create a cluster of etcd nodes 57 func CreateCluster(size int, procAttr *os.ProcAttr, ssl bool) ([][]string, []*os.Process, error) { 58 argGroup := make([][]string, size) 59 60 sslServer1 := []string{"-serverCAFile=./fixtures/ca/ca.crt", 61 "-serverCert=./fixtures/ca/server.crt", 62 "-serverKey=./fixtures/ca/server.key.insecure", 63 } 64 65 sslServer2 := []string{"-serverCAFile=./fixtures/ca/ca.crt", 66 "-serverCert=./fixtures/ca/server2.crt", 67 "-serverKey=./fixtures/ca/server2.key.insecure", 68 } 69 70 for i := 0; i < size; i++ { 71 if i == 0 { 72 argGroup[i] = []string{"etcd", "-d=/tmp/node1", "-n=node1"} 73 if ssl { 74 argGroup[i] = append(argGroup[i], sslServer1...) 75 } 76 } else { 77 strI := strconv.Itoa(i + 1) 78 argGroup[i] = []string{"etcd", "-n=node" + strI, "-c=127.0.0.1:400" + strI, "-s=127.0.0.1:700" + strI, "-d=/tmp/node" + strI, "-C=127.0.0.1:7001"} 79 if ssl { 80 argGroup[i] = append(argGroup[i], sslServer2...) 81 } 82 } 83 } 84 85 etcds := make([]*os.Process, size) 86 87 for i, _ := range etcds { 88 var err error 89 etcds[i], err = os.StartProcess("etcd", append(argGroup[i], "-f"), procAttr) 90 if err != nil { 91 return nil, nil, err 92 } 93 94 // TODOBP: Change this sleep to wait until the master is up. 95 // The problem is that if the master isn't up then the children 96 // have to retry. This retry can take upwards of 15 seconds 97 // which slows tests way down and some of them fail. 98 if i == 0 { 99 time.Sleep(time.Second * 2) 100 } 101 } 102 103 return argGroup, etcds, nil 104 } 105 106 // Destroy all the nodes in the cluster 107 func DestroyCluster(etcds []*os.Process) error { 108 for _, etcd := range etcds { 109 err := etcd.Kill() 110 if err != nil { 111 panic(err.Error()) 112 } 113 etcd.Release() 114 } 115 return nil 116 } 117 118 // 119 func Monitor(size int, allowDeadNum int, leaderChan chan string, all chan bool, stop chan bool) { 120 leaderMap := make(map[int]string) 121 baseAddrFormat := "http://0.0.0.0:400%d" 122 123 for { 124 knownLeader := "unknown" 125 dead := 0 126 var i int 127 128 for i = 0; i < size; i++ { 129 leader, err := getLeader(fmt.Sprintf(baseAddrFormat, i+1)) 130 131 if err == nil { 132 leaderMap[i] = leader 133 134 if knownLeader == "unknown" { 135 knownLeader = leader 136 } else { 137 if leader != knownLeader { 138 break 139 } 140 141 } 142 143 } else { 144 dead++ 145 if dead > allowDeadNum { 146 break 147 } 148 } 149 150 } 151 152 if i == size { 153 select { 154 case <-stop: 155 return 156 case <-leaderChan: 157 leaderChan <- knownLeader 158 default: 159 leaderChan <- knownLeader 160 } 161 162 } 163 if dead == 0 { 164 select { 165 case <-all: 166 all <- true 167 default: 168 all <- true 169 } 170 } 171 172 time.Sleep(time.Millisecond * 10) 173 } 174 175 } 176 177 func getLeader(addr string) (string, error) { 178 179 resp, err := client.Get(addr + "/v1/leader") 180 181 if err != nil { 182 return "", err 183 } 184 185 if resp.StatusCode != http.StatusOK { 186 resp.Body.Close() 187 return "", fmt.Errorf("no leader") 188 } 189 190 b, err := ioutil.ReadAll(resp.Body) 191 192 resp.Body.Close() 193 194 if err != nil { 195 return "", err 196 } 197 198 return string(b), nil 199 200 } 201 202 // Dial with timeout 203 func dialTimeoutFast(network, addr string) (net.Conn, error) { 204 return net.DialTimeout(network, addr, time.Millisecond*10) 205 }