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  }