1// Copyright 2016 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 "reflect" 19 "testing" 20 21 "github.com/coreos/etcd/integration" 22 "github.com/coreos/etcd/pkg/testutil" 23 "github.com/coreos/etcd/pkg/types" 24 25 "golang.org/x/net/context" 26) 27 28func TestMemberList(t *testing.T) { 29 defer testutil.AfterTest(t) 30 31 clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) 32 defer clus.Terminate(t) 33 34 capi := clus.RandClient() 35 36 resp, err := capi.MemberList(context.Background()) 37 if err != nil { 38 t.Fatalf("failed to list member %v", err) 39 } 40 41 if len(resp.Members) != 3 { 42 t.Errorf("number of members = %d, want %d", len(resp.Members), 3) 43 } 44} 45 46func TestMemberAdd(t *testing.T) { 47 defer testutil.AfterTest(t) 48 49 clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) 50 defer clus.Terminate(t) 51 52 capi := clus.RandClient() 53 54 urls := []string{"http://127.0.0.1:1234"} 55 resp, err := capi.MemberAdd(context.Background(), urls) 56 if err != nil { 57 t.Fatalf("failed to add member %v", err) 58 } 59 60 if !reflect.DeepEqual(resp.Member.PeerURLs, urls) { 61 t.Errorf("urls = %v, want %v", urls, resp.Member.PeerURLs) 62 } 63} 64 65func TestMemberRemove(t *testing.T) { 66 defer testutil.AfterTest(t) 67 68 clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) 69 defer clus.Terminate(t) 70 71 capi := clus.Client(1) 72 resp, err := capi.MemberList(context.Background()) 73 if err != nil { 74 t.Fatalf("failed to list member %v", err) 75 } 76 77 rmvID := resp.Members[0].ID 78 // indexes in capi member list don't necessarily match cluster member list; 79 // find member that is not the client to remove 80 for _, m := range resp.Members { 81 mURLs, _ := types.NewURLs(m.PeerURLs) 82 if !reflect.DeepEqual(mURLs, clus.Members[1].ServerConfig.PeerURLs) { 83 rmvID = m.ID 84 break 85 } 86 } 87 88 _, err = capi.MemberRemove(context.Background(), rmvID) 89 if err != nil { 90 t.Fatalf("failed to remove member %v", err) 91 } 92 93 resp, err = capi.MemberList(context.Background()) 94 if err != nil { 95 t.Fatalf("failed to list member %v", err) 96 } 97 98 if len(resp.Members) != 2 { 99 t.Errorf("number of members = %d, want %d", len(resp.Members), 2) 100 } 101} 102 103func TestMemberUpdate(t *testing.T) { 104 defer testutil.AfterTest(t) 105 106 clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) 107 defer clus.Terminate(t) 108 109 capi := clus.RandClient() 110 resp, err := capi.MemberList(context.Background()) 111 if err != nil { 112 t.Fatalf("failed to list member %v", err) 113 } 114 115 urls := []string{"http://127.0.0.1:1234"} 116 _, err = capi.MemberUpdate(context.Background(), resp.Members[0].ID, urls) 117 if err != nil { 118 t.Fatalf("failed to update member %v", err) 119 } 120 121 resp, err = capi.MemberList(context.Background()) 122 if err != nil { 123 t.Fatalf("failed to list member %v", err) 124 } 125 126 if !reflect.DeepEqual(resp.Members[0].PeerURLs, urls) { 127 t.Errorf("urls = %v, want %v", urls, resp.Members[0].PeerURLs) 128 } 129} 130 131func TestMemberAddUpdateWrongURLs(t *testing.T) { 132 defer testutil.AfterTest(t) 133 134 clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) 135 defer clus.Terminate(t) 136 137 capi := clus.RandClient() 138 tt := [][]string{ 139 // missing protocol scheme 140 {"://127.0.0.1:2379"}, 141 // unsupported scheme 142 {"mailto://127.0.0.1:2379"}, 143 // not conform to host:port 144 {"http://127.0.0.1"}, 145 // contain a path 146 {"http://127.0.0.1:2379/path"}, 147 // first path segment in URL cannot contain colon 148 {"127.0.0.1:1234"}, 149 // URL scheme must be http, https, unix, or unixs 150 {"localhost:1234"}, 151 } 152 for i := range tt { 153 _, err := capi.MemberAdd(context.Background(), tt[i]) 154 if err == nil { 155 t.Errorf("#%d: MemberAdd err = nil, but error", i) 156 } 157 _, err = capi.MemberUpdate(context.Background(), 0, tt[i]) 158 if err == nil { 159 t.Errorf("#%d: MemberUpdate err = nil, but error", i) 160 } 161 } 162} 163