1// Copyright 2015 The etcd Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package integration
16
17import (
18	"context"
19	"fmt"
20	"io/ioutil"
21	"reflect"
22	"testing"
23
24	"github.com/stretchr/testify/assert"
25	"go.etcd.io/etcd/client/v2"
26)
27
28func TestPauseMember(t *testing.T) {
29	BeforeTest(t)
30
31	c := NewCluster(t, 5)
32	c.Launch(t)
33	defer c.Terminate(t)
34
35	for i := 0; i < 5; i++ {
36		c.Members[i].Pause()
37		membs := append([]*member{}, c.Members[:i]...)
38		membs = append(membs, c.Members[i+1:]...)
39		c.waitLeader(t, membs)
40		clusterMustProgress(t, membs)
41		c.Members[i].Resume()
42	}
43	c.waitLeader(t, c.Members)
44	clusterMustProgress(t, c.Members)
45}
46
47func TestRestartMember(t *testing.T) {
48	BeforeTest(t)
49	c := NewCluster(t, 3)
50	c.Launch(t)
51	defer c.Terminate(t)
52
53	for i := 0; i < 3; i++ {
54		c.Members[i].Stop(t)
55		membs := append([]*member{}, c.Members[:i]...)
56		membs = append(membs, c.Members[i+1:]...)
57		c.waitLeader(t, membs)
58		clusterMustProgress(t, membs)
59		err := c.Members[i].Restart(t)
60		if err != nil {
61			t.Fatal(err)
62		}
63	}
64	c.waitLeader(t, c.Members)
65	clusterMustProgress(t, c.Members)
66}
67
68func TestLaunchDuplicateMemberShouldFail(t *testing.T) {
69	BeforeTest(t)
70	size := 3
71	c := NewCluster(t, size)
72	m := c.Members[0].Clone(t)
73	var err error
74	m.DataDir, err = ioutil.TempDir(t.TempDir(), "etcd")
75	if err != nil {
76		t.Fatal(err)
77	}
78	c.Launch(t)
79	defer c.Terminate(t)
80
81	if err := m.Launch(); err == nil {
82		t.Errorf("unexpect successful launch")
83	} else {
84		t.Logf("launch failed as expected: %v", err)
85		assert.Contains(t, err.Error(), "has already been bootstrapped")
86	}
87}
88
89func TestSnapshotAndRestartMember(t *testing.T) {
90	BeforeTest(t)
91	m := mustNewMember(t, memberConfig{name: "snapAndRestartTest"})
92	m.SnapshotCount = 100
93	m.Launch()
94	defer m.Terminate(t)
95	m.WaitOK(t)
96
97	resps := make([]*client.Response, 120)
98	var err error
99	for i := 0; i < 120; i++ {
100		cc := MustNewHTTPClient(t, []string{m.URL()}, nil)
101		kapi := client.NewKeysAPI(cc)
102		ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
103		key := fmt.Sprintf("foo%d", i)
104		resps[i], err = kapi.Create(ctx, "/"+key, "bar")
105		if err != nil {
106			t.Fatalf("#%d: create on %s error: %v", i, m.URL(), err)
107		}
108		cancel()
109	}
110	m.Stop(t)
111	m.Restart(t)
112
113	m.WaitOK(t)
114	for i := 0; i < 120; i++ {
115		cc := MustNewHTTPClient(t, []string{m.URL()}, nil)
116		kapi := client.NewKeysAPI(cc)
117		ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
118		key := fmt.Sprintf("foo%d", i)
119		resp, err := kapi.Get(ctx, "/"+key, nil)
120		if err != nil {
121			t.Fatalf("#%d: get on %s error: %v", i, m.URL(), err)
122		}
123		cancel()
124
125		if !reflect.DeepEqual(resp.Node, resps[i].Node) {
126			t.Errorf("#%d: node = %v, want %v", i, resp.Node, resps[i].Node)
127		}
128	}
129}
130