go.etcd.io/etcd@v3.3.27+incompatible/etcdserver/util_test.go (about) 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 15 package etcdserver 16 17 import ( 18 "net/http" 19 "testing" 20 "time" 21 22 "github.com/coreos/etcd/etcdserver/membership" 23 "github.com/coreos/etcd/pkg/types" 24 "github.com/coreos/etcd/raft/raftpb" 25 "github.com/coreos/etcd/rafthttp" 26 "github.com/coreos/etcd/snap" 27 ) 28 29 func TestLongestConnected(t *testing.T) { 30 umap, err := types.NewURLsMap("mem1=http://10.1:2379,mem2=http://10.2:2379,mem3=http://10.3:2379") 31 if err != nil { 32 t.Fatal(err) 33 } 34 clus, err := membership.NewClusterFromURLsMap("test", umap) 35 if err != nil { 36 t.Fatal(err) 37 } 38 memberIDs := clus.MemberIDs() 39 40 tr := newNopTransporterWithActiveTime(memberIDs) 41 transferee, ok := longestConnected(tr, memberIDs) 42 if !ok { 43 t.Fatalf("unexpected ok %v", ok) 44 } 45 if memberIDs[0] != transferee { 46 t.Fatalf("expected first member %s to be transferee, got %s", memberIDs[0], transferee) 47 } 48 49 // make all members non-active 50 amap := make(map[types.ID]time.Time) 51 for _, id := range memberIDs { 52 amap[id] = time.Time{} 53 } 54 tr.(*nopTransporterWithActiveTime).reset(amap) 55 56 _, ok2 := longestConnected(tr, memberIDs) 57 if ok2 { 58 t.Fatalf("unexpected ok %v", ok) 59 } 60 } 61 62 type nopTransporterWithActiveTime struct { 63 activeMap map[types.ID]time.Time 64 } 65 66 // newNopTransporterWithActiveTime creates nopTransporterWithActiveTime with the first member 67 // being the most stable (longest active-since time). 68 func newNopTransporterWithActiveTime(memberIDs []types.ID) rafthttp.Transporter { 69 am := make(map[types.ID]time.Time) 70 for i, id := range memberIDs { 71 am[id] = time.Now().Add(time.Duration(i) * time.Second) 72 } 73 return &nopTransporterWithActiveTime{activeMap: am} 74 } 75 76 func (s *nopTransporterWithActiveTime) Start() error { return nil } 77 func (s *nopTransporterWithActiveTime) Handler() http.Handler { return nil } 78 func (s *nopTransporterWithActiveTime) Send(m []raftpb.Message) {} 79 func (s *nopTransporterWithActiveTime) SendSnapshot(m snap.Message) {} 80 func (s *nopTransporterWithActiveTime) AddRemote(id types.ID, us []string) {} 81 func (s *nopTransporterWithActiveTime) AddPeer(id types.ID, us []string) {} 82 func (s *nopTransporterWithActiveTime) RemovePeer(id types.ID) {} 83 func (s *nopTransporterWithActiveTime) RemoveAllPeers() {} 84 func (s *nopTransporterWithActiveTime) UpdatePeer(id types.ID, us []string) {} 85 func (s *nopTransporterWithActiveTime) ActiveSince(id types.ID) time.Time { return s.activeMap[id] } 86 func (s *nopTransporterWithActiveTime) ActivePeers() int { return 0 } 87 func (s *nopTransporterWithActiveTime) Stop() {} 88 func (s *nopTransporterWithActiveTime) Pause() {} 89 func (s *nopTransporterWithActiveTime) Resume() {} 90 func (s *nopTransporterWithActiveTime) reset(am map[types.ID]time.Time) { s.activeMap = am }