summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/hashicorp/memberlist/memberlist_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/hashicorp/memberlist/memberlist_test.go')
-rw-r--r--vendor/github.com/hashicorp/memberlist/memberlist_test.go1545
1 files changed, 0 insertions, 1545 deletions
diff --git a/vendor/github.com/hashicorp/memberlist/memberlist_test.go b/vendor/github.com/hashicorp/memberlist/memberlist_test.go
deleted file mode 100644
index ee2fc5d52..000000000
--- a/vendor/github.com/hashicorp/memberlist/memberlist_test.go
+++ /dev/null
@@ -1,1545 +0,0 @@
-package memberlist
-
-import (
- "bytes"
- "fmt"
- "io/ioutil"
- "log"
- "net"
- "os"
- "reflect"
- "strings"
- "sync"
- "testing"
- "time"
-
- "github.com/miekg/dns"
-)
-
-var bindLock sync.Mutex
-var bindNum byte = 10
-
-func getBindAddr() net.IP {
- bindLock.Lock()
- defer bindLock.Unlock()
-
- result := net.IPv4(127, 0, 0, bindNum)
- bindNum++
- if bindNum > 255 {
- bindNum = 10
- }
-
- return result
-}
-
-func testConfig() *Config {
- config := DefaultLANConfig()
- config.BindAddr = getBindAddr().String()
- config.Name = config.BindAddr
- return config
-}
-
-func yield() {
- time.Sleep(5 * time.Millisecond)
-}
-
-type MockDelegate struct {
- meta []byte
- msgs [][]byte
- broadcasts [][]byte
- state []byte
- remoteState []byte
-}
-
-func (m *MockDelegate) NodeMeta(limit int) []byte {
- return m.meta
-}
-
-func (m *MockDelegate) NotifyMsg(msg []byte) {
- cp := make([]byte, len(msg))
- copy(cp, msg)
- m.msgs = append(m.msgs, cp)
-}
-
-func (m *MockDelegate) GetBroadcasts(overhead, limit int) [][]byte {
- b := m.broadcasts
- m.broadcasts = nil
- return b
-}
-
-func (m *MockDelegate) LocalState(join bool) []byte {
- return m.state
-}
-
-func (m *MockDelegate) MergeRemoteState(s []byte, join bool) {
- m.remoteState = s
-}
-
-// Returns a new Memberlist on an open port by trying a range of port numbers
-// until something sticks.
-func NewMemberlistOnOpenPort(c *Config) (*Memberlist, error) {
- c.BindPort = 0
- return newMemberlist(c)
-}
-
-func GetMemberlistDelegate(t *testing.T) (*Memberlist, *MockDelegate) {
- d := &MockDelegate{}
-
- c := testConfig()
- c.Delegate = d
-
- m, err := NewMemberlistOnOpenPort(c)
- if err != nil {
- t.Fatalf("failed to start: %v", err)
- return nil, nil
- }
-
- return m, d
-}
-
-func GetMemberlist(t *testing.T) *Memberlist {
- c := testConfig()
-
- m, err := NewMemberlistOnOpenPort(c)
- if err != nil {
- t.Fatalf("failed to start: %v", err)
- return nil
- }
-
- return m
-}
-
-func TestDefaultLANConfig_protocolVersion(t *testing.T) {
- c := DefaultLANConfig()
- if c.ProtocolVersion != ProtocolVersion2Compatible {
- t.Fatalf("should be max: %d", c.ProtocolVersion)
- }
-}
-
-func TestCreate_protocolVersion(t *testing.T) {
- cases := []struct {
- version uint8
- err bool
- }{
- {ProtocolVersionMin, false},
- {ProtocolVersionMax, false},
- // TODO(mitchellh): uncommon when we're over 0
- //{ProtocolVersionMin - 1, true},
- {ProtocolVersionMax + 1, true},
- {ProtocolVersionMax - 1, false},
- }
-
- for _, tc := range cases {
- c := DefaultLANConfig()
- c.BindAddr = getBindAddr().String()
- c.ProtocolVersion = tc.version
- m, err := Create(c)
- if tc.err && err == nil {
- t.Errorf("Should've failed with version: %d", tc.version)
- } else if !tc.err && err != nil {
- t.Errorf("Version '%d' error: %s", tc.version, err)
- }
-
- if err == nil {
- m.Shutdown()
- }
- }
-}
-
-func TestCreate_secretKey(t *testing.T) {
- cases := []struct {
- key []byte
- err bool
- }{
- {make([]byte, 0), false},
- {[]byte("abc"), true},
- {make([]byte, 16), false},
- {make([]byte, 38), true},
- }
-
- for _, tc := range cases {
- c := DefaultLANConfig()
- c.BindAddr = getBindAddr().String()
- c.SecretKey = tc.key
- m, err := Create(c)
- if tc.err && err == nil {
- t.Errorf("Should've failed with key: %#v", tc.key)
- } else if !tc.err && err != nil {
- t.Errorf("Key '%#v' error: %s", tc.key, err)
- }
-
- if err == nil {
- m.Shutdown()
- }
- }
-}
-
-func TestCreate_secretKeyEmpty(t *testing.T) {
- c := DefaultLANConfig()
- c.BindAddr = getBindAddr().String()
- c.SecretKey = make([]byte, 0)
- m, err := Create(c)
- if err != nil {
- t.Fatalf("err: %s", err)
- }
- defer m.Shutdown()
-
- if m.config.EncryptionEnabled() {
- t.Fatalf("Expected encryption to be disabled")
- }
-}
-
-func TestCreate_keyringOnly(t *testing.T) {
- c := DefaultLANConfig()
- c.BindAddr = getBindAddr().String()
- keyring, err := NewKeyring(nil, make([]byte, 16))
- if err != nil {
- t.Fatalf("err: %s", err)
- }
- c.Keyring = keyring
-
- m, err := Create(c)
- if err != nil {
- t.Fatalf("err: %s", err)
- }
- defer m.Shutdown()
-
- if !m.config.EncryptionEnabled() {
- t.Fatalf("Expected encryption to be enabled")
- }
-}
-
-func TestCreate_keyringAndSecretKey(t *testing.T) {
- c := DefaultLANConfig()
- c.BindAddr = getBindAddr().String()
- keyring, err := NewKeyring(nil, make([]byte, 16))
- if err != nil {
- t.Fatalf("err: %s", err)
- }
- c.Keyring = keyring
- c.SecretKey = []byte{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
-
- m, err := Create(c)
- if err != nil {
- t.Fatalf("err: %s", err)
- }
- defer m.Shutdown()
-
- if !m.config.EncryptionEnabled() {
- t.Fatalf("Expected encryption to be enabled")
- }
-
- ringKeys := c.Keyring.GetKeys()
- if !bytes.Equal(c.SecretKey, ringKeys[0]) {
- t.Fatalf("Unexpected primary key %v", ringKeys[0])
- }
-}
-
-func TestCreate_invalidLoggerSettings(t *testing.T) {
- c := DefaultLANConfig()
- c.BindAddr = getBindAddr().String()
- c.Logger = log.New(ioutil.Discard, "", log.LstdFlags)
- c.LogOutput = ioutil.Discard
-
- _, err := Create(c)
- if err == nil {
- t.Fatal("Memberlist should not allow both LogOutput and Logger to be set, but it did not raise an error")
- }
-}
-
-func TestCreate(t *testing.T) {
- c := testConfig()
- c.ProtocolVersion = ProtocolVersionMin
- c.DelegateProtocolVersion = 13
- c.DelegateProtocolMin = 12
- c.DelegateProtocolMax = 24
-
- m, err := Create(c)
- if err != nil {
- t.Fatalf("err: %s", err)
- }
- defer m.Shutdown()
-
- yield()
-
- members := m.Members()
- if len(members) != 1 {
- t.Fatalf("bad number of members")
- }
-
- if members[0].PMin != ProtocolVersionMin {
- t.Fatalf("bad: %#v", members[0])
- }
-
- if members[0].PMax != ProtocolVersionMax {
- t.Fatalf("bad: %#v", members[0])
- }
-
- if members[0].PCur != c.ProtocolVersion {
- t.Fatalf("bad: %#v", members[0])
- }
-
- if members[0].DMin != c.DelegateProtocolMin {
- t.Fatalf("bad: %#v", members[0])
- }
-
- if members[0].DMax != c.DelegateProtocolMax {
- t.Fatalf("bad: %#v", members[0])
- }
-
- if members[0].DCur != c.DelegateProtocolVersion {
- t.Fatalf("bad: %#v", members[0])
- }
-}
-
-func TestMemberList_CreateShutdown(t *testing.T) {
- m := GetMemberlist(t)
- m.schedule()
- if err := m.Shutdown(); err != nil {
- t.Fatalf("failed to shutdown %v", err)
- }
-}
-
-func TestMemberList_ResolveAddr(t *testing.T) {
- m := GetMemberlist(t)
- if _, err := m.resolveAddr("localhost"); err != nil {
- t.Fatalf("Could not resolve localhost: %s", err)
- }
- if _, err := m.resolveAddr("[::1]:80"); err != nil {
- t.Fatalf("Could not understand ipv6 pair: %s", err)
- }
- if _, err := m.resolveAddr("[::1]"); err != nil {
- t.Fatalf("Could not understand ipv6 non-pair")
- }
- if _, err := m.resolveAddr(":80"); err == nil {
- t.Fatalf("Understood hostless port")
- }
- if _, err := m.resolveAddr("localhost:80"); err != nil {
- t.Fatalf("Could not understand hostname port combo: %s", err)
- }
- if _, err := m.resolveAddr("localhost:80000"); err == nil {
- t.Fatalf("Understood too high port")
- }
- if _, err := m.resolveAddr("127.0.0.1:80"); err != nil {
- t.Fatalf("Could not understand hostname port combo: %s", err)
- }
- if _, err := m.resolveAddr("[2001:db8:a0b:12f0::1]:80"); err != nil {
- t.Fatalf("Could not understand hostname port combo: %s", err)
- }
- if _, err := m.resolveAddr("127.0.0.1"); err != nil {
- t.Fatalf("Could not understand IPv4 only %s", err)
- }
- if _, err := m.resolveAddr("[2001:db8:a0b:12f0::1]"); err != nil {
- t.Fatalf("Could not understand IPv6 only %s", err)
- }
-}
-
-type dnsHandler struct {
- t *testing.T
-}
-
-func (h dnsHandler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
- if len(r.Question) != 1 {
- h.t.Fatalf("bad: %#v", r.Question)
- }
-
- name := "join.service.consul."
- question := r.Question[0]
- if question.Name != name || question.Qtype != dns.TypeANY {
- h.t.Fatalf("bad: %#v", question)
- }
-
- m := new(dns.Msg)
- m.SetReply(r)
- m.Authoritative = true
- m.RecursionAvailable = false
- m.Answer = append(m.Answer, &dns.A{
- Hdr: dns.RR_Header{
- Name: name,
- Rrtype: dns.TypeA,
- Class: dns.ClassINET},
- A: net.ParseIP("127.0.0.1"),
- })
- m.Answer = append(m.Answer, &dns.AAAA{
- Hdr: dns.RR_Header{
- Name: name,
- Rrtype: dns.TypeAAAA,
- Class: dns.ClassINET},
- AAAA: net.ParseIP("2001:db8:a0b:12f0::1"),
- })
- if err := w.WriteMsg(m); err != nil {
- h.t.Fatalf("err: %v", err)
- }
-}
-
-func TestMemberList_ResolveAddr_TCP_First(t *testing.T) {
- bind := "127.0.0.1:8600"
-
- var wg sync.WaitGroup
- wg.Add(1)
- server := &dns.Server{
- Addr: bind,
- Handler: dnsHandler{t},
- Net: "tcp",
- NotifyStartedFunc: wg.Done,
- }
- defer server.Shutdown()
-
- go func() {
- if err := server.ListenAndServe(); err != nil && !strings.Contains(err.Error(), "use of closed network connection") {
- t.Fatalf("err: %v", err)
- }
- }()
- wg.Wait()
-
- tmpFile, err := ioutil.TempFile("", "")
- if err != nil {
- t.Fatalf("err: %v", err)
- }
- defer os.Remove(tmpFile.Name())
-
- content := []byte(fmt.Sprintf("nameserver %s", bind))
- if _, err := tmpFile.Write(content); err != nil {
- t.Fatalf("err: %v", err)
- }
- if err := tmpFile.Close(); err != nil {
- t.Fatalf("err: %v", err)
- }
-
- m := GetMemberlist(t)
- m.config.DNSConfigPath = tmpFile.Name()
- m.setAlive()
- m.schedule()
- defer m.Shutdown()
-
- // Try with and without the trailing dot.
- hosts := []string{
- "join.service.consul.",
- "join.service.consul",
- }
- for _, host := range hosts {
- ips, err := m.resolveAddr(host)
- if err != nil {
- t.Fatalf("err: %v", err)
- }
- port := uint16(m.config.BindPort)
- expected := []ipPort{
- ipPort{net.ParseIP("127.0.0.1"), port},
- ipPort{net.ParseIP("2001:db8:a0b:12f0::1"), port},
- }
- if !reflect.DeepEqual(ips, expected) {
- t.Fatalf("bad: %#v expected: %#v", ips, expected)
- }
- }
-}
-
-func TestMemberList_Members(t *testing.T) {
- n1 := &Node{Name: "test"}
- n2 := &Node{Name: "test2"}
- n3 := &Node{Name: "test3"}
-
- m := &Memberlist{}
- nodes := []*nodeState{
- &nodeState{Node: *n1, State: stateAlive},
- &nodeState{Node: *n2, State: stateDead},
- &nodeState{Node: *n3, State: stateSuspect},
- }
- m.nodes = nodes
-
- members := m.Members()
- if !reflect.DeepEqual(members, []*Node{n1, n3}) {
- t.Fatalf("bad members")
- }
-}
-
-func TestMemberlist_Join(t *testing.T) {
- m1 := GetMemberlist(t)
- m1.setAlive()
- m1.schedule()
- defer m1.Shutdown()
-
- // Create a second node
- c := DefaultLANConfig()
- addr1 := getBindAddr()
- c.Name = addr1.String()
- c.BindAddr = addr1.String()
- c.BindPort = m1.config.BindPort
-
- m2, err := Create(c)
- if err != nil {
- t.Fatalf("unexpected err: %s", err)
- }
- defer m2.Shutdown()
-
- num, err := m2.Join([]string{m1.config.BindAddr})
- if num != 1 {
- t.Fatalf("unexpected 1: %d", num)
- }
- if err != nil {
- t.Fatalf("unexpected err: %s", err)
- }
-
- // Check the hosts
- if len(m2.Members()) != 2 {
- t.Fatalf("should have 2 nodes! %v", m2.Members())
- }
- if m2.estNumNodes() != 2 {
- t.Fatalf("should have 2 nodes! %v", m2.Members())
- }
-}
-
-type CustomMergeDelegate struct {
- invoked bool
-}
-
-func (c *CustomMergeDelegate) NotifyMerge(nodes []*Node) error {
- log.Printf("Cancel merge")
- c.invoked = true
- return fmt.Errorf("Custom merge canceled")
-}
-
-func TestMemberlist_Join_Cancel(t *testing.T) {
- m1 := GetMemberlist(t)
- merge1 := &CustomMergeDelegate{}
- m1.config.Merge = merge1
- m1.setAlive()
- m1.schedule()
- defer m1.Shutdown()
-
- // Create a second node
- c := DefaultLANConfig()
- addr1 := getBindAddr()
- c.Name = addr1.String()
- c.BindAddr = addr1.String()
- c.BindPort = m1.config.BindPort
-
- m2, err := Create(c)
- if err != nil {
- t.Fatalf("unexpected err: %s", err)
- }
- merge2 := &CustomMergeDelegate{}
- m2.config.Merge = merge2
- defer m2.Shutdown()
-
- num, err := m2.Join([]string{m1.config.BindAddr})
- if num != 0 {
- t.Fatalf("unexpected 0: %d", num)
- }
- if !strings.Contains(err.Error(), "Custom merge canceled") {
- t.Fatalf("unexpected err: %s", err)
- }
-
- // Check the hosts
- if len(m2.Members()) != 1 {
- t.Fatalf("should have 1 nodes! %v", m2.Members())
- }
- if len(m1.Members()) != 1 {
- t.Fatalf("should have 1 nodes! %v", m1.Members())
- }
-
- // Check delegate invocation
- if !merge1.invoked {
- t.Fatalf("should invoke delegate")
- }
- if !merge2.invoked {
- t.Fatalf("should invoke delegate")
- }
-}
-
-type CustomAliveDelegate struct {
- Ignore string
- count int
-}
-
-func (c *CustomAliveDelegate) NotifyAlive(peer *Node) error {
- c.count++
- if peer.Name == c.Ignore {
- return nil
- }
- log.Printf("Cancel alive")
- return fmt.Errorf("Custom alive canceled")
-}
-
-func TestMemberlist_Join_Cancel_Passive(t *testing.T) {
- m1 := GetMemberlist(t)
- alive1 := &CustomAliveDelegate{
- Ignore: m1.config.Name,
- }
- m1.config.Alive = alive1
- m1.setAlive()
- m1.schedule()
- defer m1.Shutdown()
-
- // Create a second node
- c := DefaultLANConfig()
- addr1 := getBindAddr()
- c.Name = addr1.String()
- c.BindAddr = addr1.String()
- c.BindPort = m1.config.BindPort
-
- m2, err := Create(c)
- if err != nil {
- t.Fatalf("unexpected err: %s", err)
- }
- alive2 := &CustomAliveDelegate{
- Ignore: c.Name,
- }
- m2.config.Alive = alive2
- defer m2.Shutdown()
-
- num, err := m2.Join([]string{m1.config.BindAddr})
- if num != 1 {
- t.Fatalf("unexpected 1: %d", num)
- }
- if err != nil {
- t.Fatalf("err: %s", err)
- }
-
- // Check the hosts
- if len(m2.Members()) != 1 {
- t.Fatalf("should have 1 nodes! %v", m2.Members())
- }
- if len(m1.Members()) != 1 {
- t.Fatalf("should have 1 nodes! %v", m1.Members())
- }
-
- // Check delegate invocation
- if alive1.count == 0 {
- t.Fatalf("should invoke delegate: %d", alive1.count)
- }
- if alive2.count == 0 {
- t.Fatalf("should invoke delegate: %d", alive2.count)
- }
-}
-
-func TestMemberlist_Join_protocolVersions(t *testing.T) {
- c1 := testConfig()
- c2 := testConfig()
- c3 := testConfig()
- c3.ProtocolVersion = ProtocolVersionMax
-
- m1, err := Create(c1)
- if err != nil {
- t.Fatalf("err: %s", err)
- }
- defer m1.Shutdown()
-
- m2, err := Create(c2)
- if err != nil {
- t.Fatalf("err: %s", err)
- }
- defer m2.Shutdown()
-
- m3, err := Create(c3)
- if err != nil {
- t.Fatalf("err: %s", err)
- }
- defer m3.Shutdown()
-
- _, err = m1.Join([]string{c2.BindAddr})
- if err != nil {
- t.Fatalf("err: %s", err)
- }
-
- yield()
-
- _, err = m1.Join([]string{c3.BindAddr})
- if err != nil {
- t.Fatalf("err: %s", err)
- }
-}
-
-func TestMemberlist_Leave(t *testing.T) {
- m1 := GetMemberlist(t)
- m1.setAlive()
- m1.schedule()
- defer m1.Shutdown()
-
- // Create a second node
- c := DefaultLANConfig()
- addr1 := getBindAddr()
- c.Name = addr1.String()
- c.BindAddr = addr1.String()
- c.BindPort = m1.config.BindPort
- c.GossipInterval = time.Millisecond
-
- m2, err := Create(c)
- if err != nil {
- t.Fatalf("unexpected err: %s", err)
- }
- defer m2.Shutdown()
-
- num, err := m2.Join([]string{m1.config.BindAddr})
- if num != 1 {
- t.Fatalf("unexpected 1: %d", num)
- }
- if err != nil {
- t.Fatalf("unexpected err: %s", err)
- }
-
- // Check the hosts
- if len(m2.Members()) != 2 {
- t.Fatalf("should have 2 nodes! %v", m2.Members())
- }
- if len(m1.Members()) != 2 {
- t.Fatalf("should have 2 nodes! %v", m2.Members())
- }
-
- // Leave
- m1.Leave(time.Second)
-
- // Wait for leave
- time.Sleep(10 * time.Millisecond)
-
- // m1 should think dead
- if len(m1.Members()) != 1 {
- t.Fatalf("should have 1 node")
- }
-
- if len(m2.Members()) != 1 {
- t.Fatalf("should have 1 node")
- }
-}
-
-func TestMemberlist_JoinShutdown(t *testing.T) {
- m1 := GetMemberlist(t)
- m1.setAlive()
- m1.schedule()
-
- // Create a second node
- c := DefaultLANConfig()
- addr1 := getBindAddr()
- c.Name = addr1.String()
- c.BindAddr = addr1.String()
- c.BindPort = m1.config.BindPort
- c.ProbeInterval = time.Millisecond
- c.ProbeTimeout = 100 * time.Microsecond
- c.SuspicionMaxTimeoutMult = 1
-
- m2, err := Create(c)
- if err != nil {
- t.Fatalf("unexpected err: %s", err)
- }
- defer m2.Shutdown()
-
- num, err := m2.Join([]string{m1.config.BindAddr})
- if num != 1 {
- t.Fatalf("unexpected 1: %d", num)
- }
- if err != nil {
- t.Fatalf("unexpected err: %s", err)
- }
-
- // Check the hosts
- if len(m2.Members()) != 2 {
- t.Fatalf("should have 2 nodes! %v", m2.Members())
- }
-
- m1.Shutdown()
-
- time.Sleep(10 * time.Millisecond)
-
- if len(m2.Members()) != 1 {
- t.Fatalf("should have 1 nodes! %v", m2.Members())
- }
-}
-
-func TestMemberlist_delegateMeta(t *testing.T) {
- c1 := testConfig()
- c2 := testConfig()
- c1.Delegate = &MockDelegate{meta: []byte("web")}
- c2.Delegate = &MockDelegate{meta: []byte("lb")}
-
- m1, err := Create(c1)
- if err != nil {
- t.Fatalf("err: %s", err)
- }
- defer m1.Shutdown()
-
- m2, err := Create(c2)
- if err != nil {
- t.Fatalf("err: %s", err)
- }
- defer m2.Shutdown()
-
- _, err = m1.Join([]string{c2.BindAddr})
- if err != nil {
- t.Fatalf("err: %s", err)
- }
-
- yield()
-
- var roles map[string]string
-
- // Check the roles of members of m1
- m1m := m1.Members()
- if len(m1m) != 2 {
- t.Fatalf("bad: %#v", m1m)
- }
-
- roles = make(map[string]string)
- for _, m := range m1m {
- roles[m.Name] = string(m.Meta)
- }
-
- if r := roles[c1.Name]; r != "web" {
- t.Fatalf("bad role for %s: %s", c1.Name, r)
- }
-
- if r := roles[c2.Name]; r != "lb" {
- t.Fatalf("bad role for %s: %s", c2.Name, r)
- }
-
- // Check the roles of members of m2
- m2m := m2.Members()
- if len(m2m) != 2 {
- t.Fatalf("bad: %#v", m2m)
- }
-
- roles = make(map[string]string)
- for _, m := range m2m {
- roles[m.Name] = string(m.Meta)
- }
-
- if r := roles[c1.Name]; r != "web" {
- t.Fatalf("bad role for %s: %s", c1.Name, r)
- }
-
- if r := roles[c2.Name]; r != "lb" {
- t.Fatalf("bad role for %s: %s", c2.Name, r)
- }
-}
-
-func TestMemberlist_delegateMeta_Update(t *testing.T) {
- c1 := testConfig()
- c2 := testConfig()
- mock1 := &MockDelegate{meta: []byte("web")}
- mock2 := &MockDelegate{meta: []byte("lb")}
- c1.Delegate = mock1
- c2.Delegate = mock2
-
- m1, err := Create(c1)
- if err != nil {
- t.Fatalf("err: %s", err)
- }
- defer m1.Shutdown()
-
- m2, err := Create(c2)
- if err != nil {
- t.Fatalf("err: %s", err)
- }
- defer m2.Shutdown()
-
- _, err = m1.Join([]string{c2.BindAddr})
- if err != nil {
- t.Fatalf("err: %s", err)
- }
-
- yield()
-
- // Update the meta data roles
- mock1.meta = []byte("api")
- mock2.meta = []byte("db")
-
- m1.UpdateNode(0)
- m2.UpdateNode(0)
- yield()
-
- // Check the updates have propagated
- var roles map[string]string
-
- // Check the roles of members of m1
- m1m := m1.Members()
- if len(m1m) != 2 {
- t.Fatalf("bad: %#v", m1m)
- }
-
- roles = make(map[string]string)
- for _, m := range m1m {
- roles[m.Name] = string(m.Meta)
- }
-
- if r := roles[c1.Name]; r != "api" {
- t.Fatalf("bad role for %s: %s", c1.Name, r)
- }
-
- if r := roles[c2.Name]; r != "db" {
- t.Fatalf("bad role for %s: %s", c2.Name, r)
- }
-
- // Check the roles of members of m2
- m2m := m2.Members()
- if len(m2m) != 2 {
- t.Fatalf("bad: %#v", m2m)
- }
-
- roles = make(map[string]string)
- for _, m := range m2m {
- roles[m.Name] = string(m.Meta)
- }
-
- if r := roles[c1.Name]; r != "api" {
- t.Fatalf("bad role for %s: %s", c1.Name, r)
- }
-
- if r := roles[c2.Name]; r != "db" {
- t.Fatalf("bad role for %s: %s", c2.Name, r)
- }
-}
-
-func TestMemberlist_UserData(t *testing.T) {
- m1, d1 := GetMemberlistDelegate(t)
- d1.state = []byte("something")
- m1.setAlive()
- m1.schedule()
- defer m1.Shutdown()
-
- // Create a second delegate with things to send
- d2 := &MockDelegate{}
- d2.broadcasts = [][]byte{
- []byte("test"),
- []byte("foobar"),
- }
- d2.state = []byte("my state")
-
- // Create a second node
- c := DefaultLANConfig()
- addr1 := getBindAddr()
- c.Name = addr1.String()
- c.BindAddr = addr1.String()
- c.BindPort = m1.config.BindPort
- c.GossipInterval = time.Millisecond
- c.PushPullInterval = time.Millisecond
- c.Delegate = d2
-
- m2, err := Create(c)
- if err != nil {
- t.Fatalf("unexpected err: %s", err)
- }
- num, err := m2.Join([]string{m1.config.BindAddr})
- if num != 1 {
- t.Fatalf("unexpected 1: %d", num)
- }
- if err != nil {
- t.Fatalf("unexpected err: %s", err)
- }
- defer m2.Shutdown()
-
- // Check the hosts
- if m2.NumMembers() != 2 {
- t.Fatalf("should have 2 nodes! %v", m2.Members())
- }
-
- // Wait for a little while
- time.Sleep(3 * time.Millisecond)
-
- // Ensure we got the messages
- if len(d1.msgs) != 2 {
- t.Fatalf("should have 2 messages!")
- }
- if !reflect.DeepEqual(d1.msgs[0], []byte("test")) {
- t.Fatalf("bad msg %v", d1.msgs[0])
- }
- if !reflect.DeepEqual(d1.msgs[1], []byte("foobar")) {
- t.Fatalf("bad msg %v", d1.msgs[1])
- }
-
- // Check the push/pull state
- if !reflect.DeepEqual(d1.remoteState, []byte("my state")) {
- t.Fatalf("bad state %s", d1.remoteState)
- }
- if !reflect.DeepEqual(d2.remoteState, []byte("something")) {
- t.Fatalf("bad state %s", d2.remoteState)
- }
-}
-
-func TestMemberlist_SendTo(t *testing.T) {
- m1, d1 := GetMemberlistDelegate(t)
- m1.setAlive()
- m1.schedule()
- defer m1.Shutdown()
-
- // Create a second delegate with things to send
- d2 := &MockDelegate{}
-
- // Create a second node
- c := DefaultLANConfig()
- addr1 := getBindAddr()
- c.Name = addr1.String()
- c.BindAddr = addr1.String()
- c.BindPort = m1.config.BindPort
- c.GossipInterval = time.Millisecond
- c.PushPullInterval = time.Millisecond
- c.Delegate = d2
-
- m2, err := Create(c)
- if err != nil {
- t.Fatalf("unexpected err: %s", err)
- }
- defer m2.Shutdown()
-
- num, err := m2.Join([]string{m1.config.BindAddr})
- if num != 1 {
- t.Fatalf("unexpected 1: %d", num)
- }
- if err != nil {
- t.Fatalf("unexpected err: %s", err)
- }
-
- // Check the hosts
- if m2.NumMembers() != 2 {
- t.Fatalf("should have 2 nodes! %v", m2.Members())
- }
-
- // Try to do a direct send
- m2Addr := &net.UDPAddr{IP: addr1,
- Port: c.BindPort}
- if err := m1.SendTo(m2Addr, []byte("ping")); err != nil {
- t.Fatalf("err: %v", err)
- }
-
- m1Addr := &net.UDPAddr{IP: net.ParseIP(m1.config.BindAddr),
- Port: m1.config.BindPort}
- if err := m2.SendTo(m1Addr, []byte("pong")); err != nil {
- t.Fatalf("err: %v", err)
- }
-
- // Wait for a little while
- time.Sleep(3 * time.Millisecond)
-
- // Ensure we got the messages
- if len(d1.msgs) != 1 {
- t.Fatalf("should have 1 messages!")
- }
- if !reflect.DeepEqual(d1.msgs[0], []byte("pong")) {
- t.Fatalf("bad msg %v", d1.msgs[0])
- }
-
- if len(d2.msgs) != 1 {
- t.Fatalf("should have 1 messages!")
- }
- if !reflect.DeepEqual(d2.msgs[0], []byte("ping")) {
- t.Fatalf("bad msg %v", d2.msgs[0])
- }
-}
-
-func TestMemberlistProtocolVersion(t *testing.T) {
- c := DefaultLANConfig()
- c.BindAddr = getBindAddr().String()
- c.ProtocolVersion = ProtocolVersionMax
- m, err := Create(c)
- if err != nil {
- t.Fatalf("err: %s", err)
- }
- defer m.Shutdown()
-
- result := m.ProtocolVersion()
- if result != ProtocolVersionMax {
- t.Fatalf("bad: %d", result)
- }
-}
-
-func TestMemberlist_Join_DeadNode(t *testing.T) {
- m1 := GetMemberlist(t)
- m1.config.TCPTimeout = 50 * time.Millisecond
- m1.setAlive()
- m1.schedule()
- defer m1.Shutdown()
-
- // Create a second "node", which is just a TCP listener that
- // does not ever respond. This is to test our deadliens
- addr1 := getBindAddr()
- list, err := net.Listen("tcp", fmt.Sprintf("%s:%d", addr1.String(), m1.config.BindPort))
- if err != nil {
- t.Fatalf("err: %v", err)
- }
- defer list.Close()
-
- // Ensure we don't hang forever
- timer := time.AfterFunc(100*time.Millisecond, func() {
- panic("should have timed out by now")
- })
- defer timer.Stop()
-
- num, err := m1.Join([]string{addr1.String()})
- if num != 0 {
- t.Fatalf("unexpected 0: %d", num)
- }
- if err == nil {
- t.Fatal("expect err")
- }
-}
-
-// Tests that nodes running different versions of the protocol can successfully
-// discover each other and add themselves to their respective member lists.
-func TestMemberlist_Join_Prototocol_Compatibility(t *testing.T) {
- testProtocolVersionPair := func(t *testing.T, pv1 uint8, pv2 uint8) {
- c1 := testConfig()
- c1.ProtocolVersion = pv1
- m1, err := NewMemberlistOnOpenPort(c1)
- if err != nil {
- t.Fatalf("failed to start: %v", err)
- }
- m1.setAlive()
- m1.schedule()
- defer m1.Shutdown()
-
- c2 := DefaultLANConfig()
- addr1 := getBindAddr()
- c2.Name = addr1.String()
- c2.BindAddr = addr1.String()
- c2.BindPort = m1.config.BindPort
- c2.ProtocolVersion = pv2
-
- m2, err := Create(c2)
- if err != nil {
- t.Fatalf("unexpected err: %s", err)
- }
- defer m2.Shutdown()
-
- num, err := m2.Join([]string{m1.config.BindAddr})
- if num != 1 {
- t.Fatalf("unexpected 1: %d", num)
- }
- if err != nil {
- t.Fatalf("unexpected err: %s", err)
- }
-
- // Check the hosts
- if len(m2.Members()) != 2 {
- t.Fatalf("should have 2 nodes! %v", m2.Members())
- }
-
- // Check the hosts
- if len(m1.Members()) != 2 {
- t.Fatalf("should have 2 nodes! %v", m1.Members())
- }
- }
-
- testProtocolVersionPair(t, 2, 1)
- testProtocolVersionPair(t, 2, 3)
- testProtocolVersionPair(t, 3, 2)
- testProtocolVersionPair(t, 3, 1)
-}
-
-func TestMemberlist_Join_IPv6(t *testing.T) {
- // Since this binds to all interfaces we need to exclude other tests
- // from grabbing an interface.
- bindLock.Lock()
- defer bindLock.Unlock()
-
- c1 := DefaultLANConfig()
- c1.Name = "A"
- c1.BindAddr = "[::1]"
- var m1 *Memberlist
- var err error
- for i := 0; i < 100; i++ {
- c1.BindPort = 23456 + i
- m1, err = Create(c1)
- if err == nil {
- break
- }
- }
- if err != nil {
- t.Fatalf("unexpected err: %s", err)
- }
- defer m1.Shutdown()
-
- // Create a second node
- c2 := DefaultLANConfig()
- c2.Name = "B"
- c2.BindAddr = "[::1]"
- var m2 *Memberlist
- for i := 0; i < 100; i++ {
- c2.BindPort = c1.BindPort + 1 + i
- m2, err = Create(c2)
- if err == nil {
- break
- }
- }
- if err != nil {
- t.Fatalf("unexpected err: %s", err)
- }
- defer m2.Shutdown()
-
- num, err := m2.Join([]string{fmt.Sprintf("%s:%d", m1.config.BindAddr, 23456)})
- if num != 1 {
- t.Fatalf("unexpected 1: %d", num)
- }
- if err != nil {
- t.Fatalf("unexpected err: %s", err)
- }
-
- // Check the hosts
- if len(m2.Members()) != 2 {
- t.Fatalf("should have 2 nodes! %v", m2.Members())
- }
-
- if len(m1.Members()) != 2 {
- t.Fatalf("should have 2 nodes! %v", m2.Members())
- }
-}
-
-func TestAdvertiseAddr(t *testing.T) {
- c := testConfig()
- c.AdvertiseAddr = "127.0.1.100"
- c.AdvertisePort = 23456
-
- m, err := Create(c)
- if err != nil {
- t.Fatalf("err: %s", err)
- }
- defer m.Shutdown()
-
- yield()
-
- members := m.Members()
- if len(members) != 1 {
- t.Fatalf("bad number of members")
- }
-
- if bytes.Compare(members[0].Addr, []byte{127, 0, 1, 100}) != 0 {
- t.Fatalf("bad: %#v", members[0])
- }
-
- if members[0].Port != 23456 {
- t.Fatalf("bad: %#v", members[0])
- }
-}
-
-type MockConflict struct {
- existing *Node
- other *Node
-}
-
-func (m *MockConflict) NotifyConflict(existing, other *Node) {
- m.existing = existing
- m.other = other
-}
-
-func TestMemberlist_conflictDelegate(t *testing.T) {
- c1 := testConfig()
- c2 := testConfig()
- mock := &MockConflict{}
- c1.Conflict = mock
-
- // Ensure name conflict
- c2.Name = c1.Name
-
- m1, err := Create(c1)
- if err != nil {
- t.Fatalf("err: %s", err)
- }
- defer m1.Shutdown()
-
- m2, err := Create(c2)
- if err != nil {
- t.Fatalf("err: %s", err)
- }
- defer m2.Shutdown()
-
- _, err = m1.Join([]string{c2.BindAddr})
- if err != nil {
- t.Fatalf("err: %s", err)
- }
-
- yield()
-
- // Ensure we were notified
- if mock.existing == nil || mock.other == nil {
- t.Fatalf("should get notified")
- }
- if mock.existing.Name != mock.other.Name {
- t.Fatalf("bad: %v %v", mock.existing, mock.other)
- }
-}
-
-type MockPing struct {
- other *Node
- rtt time.Duration
- payload []byte
-}
-
-func (m *MockPing) NotifyPingComplete(other *Node, rtt time.Duration, payload []byte) {
- m.other = other
- m.rtt = rtt
- m.payload = payload
-}
-
-const DEFAULT_PAYLOAD = "whatever"
-
-func (m *MockPing) AckPayload() []byte {
- return []byte(DEFAULT_PAYLOAD)
-}
-
-func TestMemberlist_PingDelegate(t *testing.T) {
- m1 := GetMemberlist(t)
- m1.config.Ping = &MockPing{}
- m1.setAlive()
- m1.schedule()
- defer m1.Shutdown()
-
- // Create a second node
- c := DefaultLANConfig()
- addr1 := getBindAddr()
- c.Name = addr1.String()
- c.BindAddr = addr1.String()
- c.BindPort = m1.config.BindPort
- c.ProbeInterval = time.Millisecond
- mock := &MockPing{}
- c.Ping = mock
-
- m2, err := Create(c)
- if err != nil {
- t.Fatalf("err: %s", err)
- }
- defer m2.Shutdown()
-
- _, err = m2.Join([]string{m1.config.BindAddr})
- if err != nil {
- t.Fatalf("err: %s", err)
- }
-
- yield()
-
- // Ensure we were notified
- if mock.other == nil {
- t.Fatalf("should get notified")
- }
-
- if !reflect.DeepEqual(mock.other, m1.LocalNode()) {
- t.Fatalf("not notified about the correct node; expected: %+v; actual: %+v",
- m2.LocalNode(), mock.other)
- }
-
- if mock.rtt <= 0 {
- t.Fatalf("rtt should be greater than 0")
- }
-
- if bytes.Compare(mock.payload, []byte(DEFAULT_PAYLOAD)) != 0 {
- t.Fatalf("incorrect payload. expected: %v; actual: %v", []byte(DEFAULT_PAYLOAD), mock.payload)
- }
-}
-
-func TestMemberlist_EncryptedGossipTransition(t *testing.T) {
- m1 := GetMemberlist(t)
- m1.setAlive()
- m1.schedule()
- defer m1.Shutdown()
-
- // Create a second node with the first stage of gossip transition settings
- conf2 := DefaultLANConfig()
- addr2 := getBindAddr()
- conf2.Name = addr2.String()
- conf2.BindAddr = addr2.String()
- conf2.BindPort = m1.config.BindPort
- conf2.GossipInterval = time.Millisecond
- conf2.SecretKey = []byte("Hi16ZXu2lNCRVwtr20khAg==")
- conf2.GossipVerifyIncoming = false
- conf2.GossipVerifyOutgoing = false
-
- m2, err := Create(conf2)
- if err != nil {
- t.Fatalf("unexpected err: %s", err)
- }
- defer m2.Shutdown()
-
- // Join the second node. m1 has no encryption while m2 has encryption configured and
- // can receive encrypted gossip, but will not encrypt outgoing gossip.
- num, err := m2.Join([]string{m1.config.BindAddr})
- if num != 1 {
- t.Fatalf("unexpected 1: %d", num)
- }
- if err != nil {
- t.Fatalf("unexpected err: %s", err)
- }
-
- // Check the hosts
- if len(m2.Members()) != 2 {
- t.Fatalf("should have 2 nodes! %v", m2.Members())
- }
- if m2.estNumNodes() != 2 {
- t.Fatalf("should have 2 nodes! %v", m2.Members())
- }
-
- // Leave with the first node
- m1.Leave(time.Second)
-
- // Wait for leave
- time.Sleep(10 * time.Millisecond)
-
- // Create a third node that has the second stage of gossip transition settings
- conf3 := DefaultLANConfig()
- addr3 := getBindAddr()
- conf3.Name = addr3.String()
- conf3.BindAddr = addr3.String()
- conf3.BindPort = m1.config.BindPort
- conf3.GossipInterval = time.Millisecond
- conf3.SecretKey = conf2.SecretKey
- conf3.GossipVerifyIncoming = false
-
- m3, err := Create(conf3)
- if err != nil {
- t.Fatalf("unexpected err: %s", err)
- }
- defer m3.Shutdown()
-
- // Join the third node to the second node. At this step, both nodes have encryption
- // configured but only m3 is sending encrypted gossip.
- num, err = m3.Join([]string{m2.config.BindAddr})
- if num != 1 {
- t.Fatalf("unexpected 1: %d", num)
- }
- if err != nil {
- t.Fatalf("unexpected err: %s", err)
- }
-
- // Check the hosts
- if len(m3.Members()) != 2 {
- t.Fatalf("should have 2 nodes! %v", m3.Members())
-
- }
- if m3.estNumNodes() != 2 {
- t.Fatalf("should have 2 nodes! %v", m3.Members())
- }
-
- // Leave with the second node
- m2.Leave(time.Second)
-
- // Wait for leave
- time.Sleep(10 * time.Millisecond)
-
- // Create a fourth node that has the second stage of gossip transition settings
- conf4 := DefaultLANConfig()
- addr4 := getBindAddr()
- conf4.Name = addr4.String()
- conf4.BindAddr = addr4.String()
- conf4.BindPort = m3.config.BindPort
- conf4.GossipInterval = time.Millisecond
- conf4.SecretKey = conf2.SecretKey
-
- m4, err := Create(conf4)
- if err != nil {
- t.Fatalf("unexpected err: %s", err)
- }
- defer m4.Shutdown()
-
- // Join the fourth node to the third node. At this step, both m3 and m4 are speaking
- // encrypted gossip and m3 is still accepting insecure gossip.
- num, err = m4.Join([]string{m3.config.BindAddr})
- if num != 1 {
- t.Fatalf("unexpected 1: %d", num)
- }
- if err != nil {
- t.Fatalf("unexpected err: %s", err)
- }
-
- // Check the hosts
- if len(m4.Members()) != 2 {
- t.Fatalf("should have 2 nodes! %v", m4.Members())
-
- }
- if m4.estNumNodes() != 2 {
- t.Fatalf("should have 2 nodes! %v", m4.Members())
- }
-}
-
-// Consul bug, rapid restart (before failure detection),
-// with an updated meta data. Should be at incarnation 1 for
-// both.
-//
-// This test is uncommented because it requires that either we
-// can rebind the socket (SO_REUSEPORT) which Go does not allow,
-// OR we must disable the address conflict checking in memberlist.
-// I just comment out that code to test this case.
-//
-//func TestMemberlist_Restart_delegateMeta_Update(t *testing.T) {
-// c1 := testConfig()
-// c2 := testConfig()
-// mock1 := &MockDelegate{meta: []byte("web")}
-// mock2 := &MockDelegate{meta: []byte("lb")}
-// c1.Delegate = mock1
-// c2.Delegate = mock2
-
-// m1, err := Create(c1)
-// if err != nil {
-// t.Fatalf("err: %s", err)
-// }
-// defer m1.Shutdown()
-
-// m2, err := Create(c2)
-// if err != nil {
-// t.Fatalf("err: %s", err)
-// }
-// defer m2.Shutdown()
-
-// _, err = m1.Join([]string{c2.BindAddr})
-// if err != nil {
-// t.Fatalf("err: %s", err)
-// }
-
-// yield()
-
-// // Recreate m1 with updated meta
-// m1.Shutdown()
-// c3 := testConfig()
-// c3.Name = c1.Name
-// c3.Delegate = mock1
-// c3.GossipInterval = time.Millisecond
-// mock1.meta = []byte("api")
-
-// m1, err = Create(c3)
-// if err != nil {
-// t.Fatalf("err: %s", err)
-// }
-// defer m1.Shutdown()
-
-// _, err = m1.Join([]string{c2.BindAddr})
-// if err != nil {
-// t.Fatalf("err: %s", err)
-// }
-
-// yield()
-// yield()
-
-// // Check the updates have propagated
-// var roles map[string]string
-
-// // Check the roles of members of m1
-// m1m := m1.Members()
-// if len(m1m) != 2 {
-// t.Fatalf("bad: %#v", m1m)
-// }
-
-// roles = make(map[string]string)
-// for _, m := range m1m {
-// roles[m.Name] = string(m.Meta)
-// }
-
-// if r := roles[c1.Name]; r != "api" {
-// t.Fatalf("bad role for %s: %s", c1.Name, r)
-// }
-
-// if r := roles[c2.Name]; r != "lb" {
-// t.Fatalf("bad role for %s: %s", c2.Name, r)
-// }
-
-// // Check the roles of members of m2
-// m2m := m2.Members()
-// if len(m2m) != 2 {
-// t.Fatalf("bad: %#v", m2m)
-// }
-
-// roles = make(map[string]string)
-// for _, m := range m2m {
-// roles[m.Name] = string(m.Meta)
-// }
-
-// if r := roles[c1.Name]; r != "api" {
-// t.Fatalf("bad role for %s: %s", c1.Name, r)
-// }
-
-// if r := roles[c2.Name]; r != "lb" {
-// t.Fatalf("bad role for %s: %s", c2.Name, r)
-// }
-//}