github.com/sym3tri/etcd@v0.2.1-0.20140422215517-a563d82f95d6/tests/functional/proxy_test.go (about)

     1  package test
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"os"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/coreos/etcd/server"
    11  	"github.com/coreos/etcd/tests"
    12  	"github.com/coreos/etcd/third_party/github.com/coreos/go-etcd/etcd"
    13  	"github.com/coreos/etcd/third_party/github.com/stretchr/testify/assert"
    14  )
    15  
    16  // Create a full cluster and then add extra an extra standby node.
    17  func TestStandby(t *testing.T) {
    18  	clusterSize := 10 // DefaultActiveSize + 1
    19  	_, etcds, err := CreateCluster(clusterSize, &os.ProcAttr{Files: []*os.File{nil, os.Stdout, os.Stderr}}, false)
    20  	assert.NoError(t, err)
    21  	defer DestroyCluster(etcds)
    22  
    23  	if err != nil {
    24  		t.Fatal("cannot create cluster")
    25  	}
    26  
    27  	c := etcd.NewClient(nil)
    28  	c.SyncCluster()
    29  
    30  	// Set key.
    31  	time.Sleep(time.Second)
    32  	if _, err := c.Set("foo", "bar", 0); err != nil {
    33  		panic(err)
    34  	}
    35  	time.Sleep(time.Second)
    36  
    37  	// Check that all peers and standbys have the value.
    38  	for i := range etcds {
    39  		resp, err := tests.Get(fmt.Sprintf("http://localhost:%d/v2/keys/foo", 4000+(i+1)))
    40  		if assert.NoError(t, err) {
    41  			body := tests.ReadBodyJSON(resp)
    42  			if node, _ := body["node"].(map[string]interface{}); assert.NotNil(t, node) {
    43  				assert.Equal(t, node["value"], "bar")
    44  			}
    45  		}
    46  	}
    47  
    48  	// Verify that we have one standby.
    49  	result, err := c.Get("_etcd/standbys", false, true)
    50  	assert.NoError(t, err)
    51  	assert.Equal(t, len(result.Node.Nodes), 1)
    52  
    53  	// Reconfigure with larger active size (10 nodes) and wait for promotion.
    54  	resp, _ := tests.Put("http://localhost:7001/v2/admin/config", "application/json", bytes.NewBufferString(`{"activeSize":10, "promoteDelay":1800}`))
    55  	if !assert.Equal(t, resp.StatusCode, 200) {
    56  		t.FailNow()
    57  	}
    58  
    59  	time.Sleep(server.ActiveMonitorTimeout + (1 * time.Second))
    60  
    61  	// Verify that the standby node is now a peer.
    62  	result, err = c.Get("_etcd/standbys", false, true)
    63  	assert.NoError(t, err)
    64  	assert.Equal(t, len(result.Node.Nodes), 0)
    65  
    66  	// Reconfigure with a smaller active size (8 nodes).
    67  	resp, _ = tests.Put("http://localhost:7001/v2/admin/config", "application/json", bytes.NewBufferString(`{"activeSize":8, "promoteDelay":1800}`))
    68  	if !assert.Equal(t, resp.StatusCode, 200) {
    69  		t.FailNow()
    70  	}
    71  
    72  	// Wait for two monitor cycles before checking for demotion.
    73  	time.Sleep((2 * server.ActiveMonitorTimeout) + (1 * time.Second))
    74  
    75  	// Verify that we now have eight peers.
    76  	result, err = c.Get("_etcd/machines", false, true)
    77  	assert.NoError(t, err)
    78  	assert.Equal(t, len(result.Node.Nodes), 8)
    79  
    80  	// Verify that we now have two standbys.
    81  	result, err = c.Get("_etcd/standbys", false, true)
    82  	assert.NoError(t, err)
    83  	assert.Equal(t, len(result.Node.Nodes), 2)
    84  }
    85  
    86  // Create a full cluster, disconnect a peer, wait for autodemotion, wait for autopromotion.
    87  func TestStandbyAutoPromote(t *testing.T) {
    88  	clusterSize := 10 // DefaultActiveSize + 1
    89  	_, etcds, err := CreateCluster(clusterSize, &os.ProcAttr{Files: []*os.File{nil, os.Stdout, os.Stderr}}, false)
    90  	if err != nil {
    91  		t.Fatal("cannot create cluster")
    92  	}
    93  	defer func() {
    94  		// Wrap this in a closure so that it picks up the updated version of
    95  		// the "etcds" variable.
    96  		DestroyCluster(etcds)
    97  	}()
    98  
    99  	c := etcd.NewClient(nil)
   100  	c.SyncCluster()
   101  
   102  	time.Sleep(1 * time.Second)
   103  
   104  	// Verify that we have one standby.
   105  	result, err := c.Get("_etcd/standbys", false, true)
   106  	assert.NoError(t, err)
   107  	assert.Equal(t, len(result.Node.Nodes), 1)
   108  
   109  	// Reconfigure with a short promote delay (2 second).
   110  	resp, _ := tests.Put("http://localhost:7001/v2/admin/config", "application/json", bytes.NewBufferString(`{"activeSize":9, "promoteDelay":2}`))
   111  	if !assert.Equal(t, resp.StatusCode, 200) {
   112  		t.FailNow()
   113  	}
   114  
   115  	// Remove peer.
   116  	etcd := etcds[1]
   117  	etcds = append(etcds[:1], etcds[2:]...)
   118  	if err := etcd.Kill(); err != nil {
   119  		panic(err.Error())
   120  	}
   121  	etcd.Release()
   122  
   123  	// Wait for it to get dropped.
   124  	time.Sleep(server.PeerActivityMonitorTimeout + (2 * time.Second))
   125  
   126  	// Wait for the standby to be promoted.
   127  	time.Sleep(server.ActiveMonitorTimeout + (2 * time.Second))
   128  
   129  	// Verify that we have 9 peers.
   130  	result, err = c.Get("_etcd/machines", true, true)
   131  	assert.NoError(t, err)
   132  	assert.Equal(t, len(result.Node.Nodes), 9)
   133  
   134  	// Verify that node10 is one of those peers.
   135  	result, err = c.Get("_etcd/machines/node10", false, false)
   136  	assert.NoError(t, err)
   137  
   138  	// Verify that there are no more standbys.
   139  	result, err = c.Get("_etcd/standbys", false, true)
   140  	assert.NoError(t, err)
   141  	if assert.Equal(t, len(result.Node.Nodes), 1) {
   142  		assert.Equal(t, result.Node.Nodes[0].Key, "/_etcd/standbys/node2")
   143  	}
   144  }