diff options
Diffstat (limited to 'vendor/github.com/hashicorp/memberlist')
-rw-r--r-- | vendor/github.com/hashicorp/memberlist/awareness_test.go | 41 | ||||
-rw-r--r-- | vendor/github.com/hashicorp/memberlist/broadcast_test.go | 27 | ||||
-rw-r--r-- | vendor/github.com/hashicorp/memberlist/integ_test.go | 89 | ||||
-rw-r--r-- | vendor/github.com/hashicorp/memberlist/keyring_test.go | 154 | ||||
-rw-r--r-- | vendor/github.com/hashicorp/memberlist/logging_test.go | 47 | ||||
-rw-r--r-- | vendor/github.com/hashicorp/memberlist/memberlist_test.go | 1545 | ||||
-rw-r--r-- | vendor/github.com/hashicorp/memberlist/net_test.go | 814 | ||||
-rw-r--r-- | vendor/github.com/hashicorp/memberlist/queue_test.go | 172 | ||||
-rw-r--r-- | vendor/github.com/hashicorp/memberlist/security_test.go | 70 | ||||
-rw-r--r-- | vendor/github.com/hashicorp/memberlist/state_test.go | 1900 | ||||
-rw-r--r-- | vendor/github.com/hashicorp/memberlist/suspicion_test.go | 198 | ||||
-rwxr-xr-x | vendor/github.com/hashicorp/memberlist/test/setup_subnet.sh | 28 | ||||
-rw-r--r-- | vendor/github.com/hashicorp/memberlist/transport_test.go | 124 | ||||
-rw-r--r-- | vendor/github.com/hashicorp/memberlist/util_test.go | 358 |
14 files changed, 0 insertions, 5567 deletions
diff --git a/vendor/github.com/hashicorp/memberlist/awareness_test.go b/vendor/github.com/hashicorp/memberlist/awareness_test.go deleted file mode 100644 index c6ade10af..000000000 --- a/vendor/github.com/hashicorp/memberlist/awareness_test.go +++ /dev/null @@ -1,41 +0,0 @@ -package memberlist - -import ( - "testing" - "time" -) - -func TestAwareness(t *testing.T) { - cases := []struct { - delta int - score int - timeout time.Duration - }{ - {0, 0, 1 * time.Second}, - {-1, 0, 1 * time.Second}, - {-10, 0, 1 * time.Second}, - {1, 1, 2 * time.Second}, - {-1, 0, 1 * time.Second}, - {10, 7, 8 * time.Second}, - {-1, 6, 7 * time.Second}, - {-1, 5, 6 * time.Second}, - {-1, 4, 5 * time.Second}, - {-1, 3, 4 * time.Second}, - {-1, 2, 3 * time.Second}, - {-1, 1, 2 * time.Second}, - {-1, 0, 1 * time.Second}, - {-1, 0, 1 * time.Second}, - } - - a := newAwareness(8) - for i, c := range cases { - a.ApplyDelta(c.delta) - if a.GetHealthScore() != c.score { - t.Errorf("case %d: score mismatch %d != %d", i, a.score, c.score) - } - if timeout := a.ScaleTimeout(1 * time.Second); timeout != c.timeout { - t.Errorf("case %d: scaled timeout mismatch %9.6f != %9.6f", - i, timeout.Seconds(), c.timeout.Seconds()) - } - } -} diff --git a/vendor/github.com/hashicorp/memberlist/broadcast_test.go b/vendor/github.com/hashicorp/memberlist/broadcast_test.go deleted file mode 100644 index c6a7302cc..000000000 --- a/vendor/github.com/hashicorp/memberlist/broadcast_test.go +++ /dev/null @@ -1,27 +0,0 @@ -package memberlist - -import ( - "reflect" - "testing" -) - -func TestMemberlistBroadcast_Invalidates(t *testing.T) { - m1 := &memberlistBroadcast{"test", nil, nil} - m2 := &memberlistBroadcast{"foo", nil, nil} - - if m1.Invalidates(m2) || m2.Invalidates(m1) { - t.Fatalf("unexpected invalidation") - } - - if !m1.Invalidates(m1) { - t.Fatalf("expected invalidation") - } -} - -func TestMemberlistBroadcast_Message(t *testing.T) { - m1 := &memberlistBroadcast{"test", []byte("test"), nil} - msg := m1.Message() - if !reflect.DeepEqual(msg, []byte("test")) { - t.Fatalf("messages do not match") - } -} diff --git a/vendor/github.com/hashicorp/memberlist/integ_test.go b/vendor/github.com/hashicorp/memberlist/integ_test.go deleted file mode 100644 index f519c6baa..000000000 --- a/vendor/github.com/hashicorp/memberlist/integ_test.go +++ /dev/null @@ -1,89 +0,0 @@ -package memberlist - -import ( - "fmt" - "log" - "os" - "testing" - "time" -) - -// CheckInteg will skip a test if integration testing is not enabled. -func CheckInteg(t *testing.T) { - if !IsInteg() { - t.SkipNow() - } -} - -// IsInteg returns a boolean telling you if we're in integ testing mode. -func IsInteg() bool { - return os.Getenv("INTEG_TESTS") != "" -} - -// Tests the memberlist by creating a cluster of 100 nodes -// and checking that we get strong convergence of changes. -func TestMemberlist_Integ(t *testing.T) { - CheckInteg(t) - - num := 16 - var members []*Memberlist - - secret := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} - eventCh := make(chan NodeEvent, num) - - addr := "127.0.0.1" - for i := 0; i < num; i++ { - c := DefaultLANConfig() - c.Name = fmt.Sprintf("%s:%d", addr, 12345+i) - c.BindAddr = addr - c.BindPort = 12345 + i - c.ProbeInterval = 20 * time.Millisecond - c.ProbeTimeout = 100 * time.Millisecond - c.GossipInterval = 20 * time.Millisecond - c.PushPullInterval = 200 * time.Millisecond - c.SecretKey = secret - - if i == 0 { - c.Events = &ChannelEventDelegate{eventCh} - } - - m, err := Create(c) - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - members = append(members, m) - defer m.Shutdown() - - if i > 0 { - last := members[i-1] - num, err := m.Join([]string{last.config.Name}) - if num == 0 || err != nil { - t.Fatalf("unexpected err: %s", err) - } - } - } - - // Wait and print debug info - breakTimer := time.After(250 * time.Millisecond) -WAIT: - for { - select { - case e := <-eventCh: - if e.Event == NodeJoin { - log.Printf("[DEBUG] Node join: %v (%d)", *e.Node, members[0].NumMembers()) - } else { - log.Printf("[DEBUG] Node leave: %v (%d)", *e.Node, members[0].NumMembers()) - } - case <-breakTimer: - break WAIT - } - } - - for idx, m := range members { - got := m.NumMembers() - if got != num { - t.Errorf("bad num members at idx %d. Expected %d. Got %d.", - idx, num, got) - } - } -} diff --git a/vendor/github.com/hashicorp/memberlist/keyring_test.go b/vendor/github.com/hashicorp/memberlist/keyring_test.go deleted file mode 100644 index eec699fd0..000000000 --- a/vendor/github.com/hashicorp/memberlist/keyring_test.go +++ /dev/null @@ -1,154 +0,0 @@ -package memberlist - -import ( - "bytes" - "testing" -) - -var TestKeys [][]byte = [][]byte{ - []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - []byte{15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}, - []byte{8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7}, -} - -func TestKeyring_EmptyRing(t *testing.T) { - // Keyrings can be created with no encryption keys (disabled encryption) - keyring, err := NewKeyring(nil, nil) - if err != nil { - t.Fatalf("err: %s", err) - } - - keys := keyring.GetKeys() - if len(keys) != 0 { - t.Fatalf("Expected 0 keys but have %d", len(keys)) - } -} - -func TestKeyring_PrimaryOnly(t *testing.T) { - // Keyrings can be created using only a primary key - keyring, err := NewKeyring(nil, TestKeys[0]) - if err != nil { - t.Fatalf("err: %s", err) - } - - keys := keyring.GetKeys() - if len(keys) != 1 { - t.Fatalf("Expected 1 key but have %d", len(keys)) - } -} - -func TestKeyring_GetPrimaryKey(t *testing.T) { - keyring, err := NewKeyring(TestKeys, TestKeys[1]) - if err != nil { - t.Fatalf("err: %s", err) - } - - // GetPrimaryKey returns correct key - primaryKey := keyring.GetPrimaryKey() - if !bytes.Equal(primaryKey, TestKeys[1]) { - t.Fatalf("Unexpected primary key: %v", primaryKey) - } -} - -func TestKeyring_AddRemoveUse(t *testing.T) { - keyring, err := NewKeyring(nil, TestKeys[1]) - if err != nil { - t.Fatalf("err :%s", err) - } - - // Use non-existent key throws error - if err := keyring.UseKey(TestKeys[2]); err == nil { - t.Fatalf("Expected key not installed error") - } - - // Add key to ring - if err := keyring.AddKey(TestKeys[2]); err != nil { - t.Fatalf("err: %s", err) - } - - keys := keyring.GetKeys() - if !bytes.Equal(keys[0], TestKeys[1]) { - t.Fatalf("Unexpected primary key change") - } - - if len(keys) != 2 { - t.Fatalf("Expected 2 keys but have %d", len(keys)) - } - - // Use key that exists should succeed - if err := keyring.UseKey(TestKeys[2]); err != nil { - t.Fatalf("err: %s", err) - } - - primaryKey := keyring.GetPrimaryKey() - if !bytes.Equal(primaryKey, TestKeys[2]) { - t.Fatalf("Unexpected primary key: %v", primaryKey) - } - - // Removing primary key should fail - if err := keyring.RemoveKey(TestKeys[2]); err == nil { - t.Fatalf("Expected primary key removal error") - } - - // Removing non-primary key should succeed - if err := keyring.RemoveKey(TestKeys[1]); err != nil { - t.Fatalf("err: %s", err) - } - - keys = keyring.GetKeys() - if len(keys) != 1 { - t.Fatalf("Expected 1 key but have %d", len(keys)) - } -} - -func TestKeyRing_MultiKeyEncryptDecrypt(t *testing.T) { - plaintext := []byte("this is a plain text message") - extra := []byte("random data") - - keyring, err := NewKeyring(TestKeys, TestKeys[0]) - if err != nil { - t.Fatalf("err: %s", err) - } - - // First encrypt using the primary key and make sure we can decrypt - var buf bytes.Buffer - err = encryptPayload(1, TestKeys[0], plaintext, extra, &buf) - if err != nil { - t.Fatalf("err: %v", err) - } - - msg, err := decryptPayload(keyring.GetKeys(), buf.Bytes(), extra) - if err != nil { - t.Fatalf("err: %v", err) - } - - if !bytes.Equal(msg, plaintext) { - t.Fatalf("bad: %v", msg) - } - - // Now encrypt with a secondary key and try decrypting again. - buf.Reset() - err = encryptPayload(1, TestKeys[2], plaintext, extra, &buf) - if err != nil { - t.Fatalf("err: %v", err) - } - - msg, err = decryptPayload(keyring.GetKeys(), buf.Bytes(), extra) - if err != nil { - t.Fatalf("err: %v", err) - } - - if !bytes.Equal(msg, plaintext) { - t.Fatalf("bad: %v", msg) - } - - // Remove a key from the ring, and then try decrypting again - if err := keyring.RemoveKey(TestKeys[2]); err != nil { - t.Fatalf("err: %s", err) - } - - msg, err = decryptPayload(keyring.GetKeys(), buf.Bytes(), extra) - if err == nil { - t.Fatalf("Expected no keys to decrypt message") - } -} diff --git a/vendor/github.com/hashicorp/memberlist/logging_test.go b/vendor/github.com/hashicorp/memberlist/logging_test.go deleted file mode 100644 index cc04b8a91..000000000 --- a/vendor/github.com/hashicorp/memberlist/logging_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package memberlist - -import ( - "fmt" - "net" - "testing" -) - -func TestLogging_Address(t *testing.T) { - s := LogAddress(nil) - if s != "from=<unknown address>" { - t.Fatalf("bad: %s", s) - } - - addr, err := net.ResolveIPAddr("ip4", "127.0.0.1") - if err != nil { - t.Fatalf("err: %v", err) - } - - s = LogAddress(addr) - if s != "from=127.0.0.1" { - t.Fatalf("bad: %s", s) - } -} - -func TestLogging_Conn(t *testing.T) { - s := LogConn(nil) - if s != "from=<unknown address>" { - t.Fatalf("bad: %s", s) - } - - ln, err := net.Listen("tcp", ":0") - if err != nil { - t.Fatalf("err: %v", err) - } - - conn, err := net.Dial("tcp", ln.Addr().String()) - if err != nil { - t.Fatalf("err: %v", err) - } - defer conn.Close() - - s = LogConn(conn) - if s != fmt.Sprintf("from=%s", conn.RemoteAddr().String()) { - t.Fatalf("bad: %s", s) - } -} 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) -// } -//} diff --git a/vendor/github.com/hashicorp/memberlist/net_test.go b/vendor/github.com/hashicorp/memberlist/net_test.go deleted file mode 100644 index 860535855..000000000 --- a/vendor/github.com/hashicorp/memberlist/net_test.go +++ /dev/null @@ -1,814 +0,0 @@ -package memberlist - -import ( - "bytes" - "encoding/binary" - "fmt" - "io" - "log" - "net" - "reflect" - "strings" - "testing" - "time" - - "github.com/hashicorp/go-msgpack/codec" -) - -// As a regression we left this test very low-level and network-ey, even after -// we abstracted the transport. We added some basic network-free transport tests -// in transport_test.go to prove that we didn't hard code some network stuff -// outside of NetTransport. - -func TestHandleCompoundPing(t *testing.T) { - m := GetMemberlist(t) - m.config.EnableCompression = false - defer m.Shutdown() - - var udp *net.UDPConn - for port := 60000; port < 61000; port++ { - udpAddr := fmt.Sprintf("127.0.0.1:%d", port) - udpLn, err := net.ListenPacket("udp", udpAddr) - if err == nil { - udp = udpLn.(*net.UDPConn) - break - } - } - - if udp == nil { - t.Fatalf("no udp listener") - } - - // Encode a ping - ping := ping{SeqNo: 42} - buf, err := encode(pingMsg, ping) - if err != nil { - t.Fatalf("unexpected err %s", err) - } - - // Make a compound message - compound := makeCompoundMessage([][]byte{buf.Bytes(), buf.Bytes(), buf.Bytes()}) - - // Send compound version - addr := &net.UDPAddr{IP: net.ParseIP(m.config.BindAddr), Port: m.config.BindPort} - udp.WriteTo(compound.Bytes(), addr) - - // Wait for responses - doneCh := make(chan struct{}, 1) - go func() { - select { - case <-doneCh: - case <-time.After(2 * time.Second): - panic("timeout") - } - }() - - for i := 0; i < 3; i++ { - in := make([]byte, 1500) - n, _, err := udp.ReadFrom(in) - if err != nil { - t.Fatalf("unexpected err %s", err) - } - in = in[0:n] - - msgType := messageType(in[0]) - if msgType != ackRespMsg { - t.Fatalf("bad response %v", in) - } - - var ack ackResp - if err := decode(in[1:], &ack); err != nil { - t.Fatalf("unexpected err %s", err) - } - - if ack.SeqNo != 42 { - t.Fatalf("bad sequence no") - } - } - - doneCh <- struct{}{} -} - -func TestHandlePing(t *testing.T) { - m := GetMemberlist(t) - m.config.EnableCompression = false - defer m.Shutdown() - - var udp *net.UDPConn - for port := 60000; port < 61000; port++ { - udpAddr := fmt.Sprintf("127.0.0.1:%d", port) - udpLn, err := net.ListenPacket("udp", udpAddr) - if err == nil { - udp = udpLn.(*net.UDPConn) - break - } - } - - if udp == nil { - t.Fatalf("no udp listener") - } - - // Encode a ping - ping := ping{SeqNo: 42} - buf, err := encode(pingMsg, ping) - if err != nil { - t.Fatalf("unexpected err %s", err) - } - - // Send - addr := &net.UDPAddr{IP: net.ParseIP(m.config.BindAddr), Port: m.config.BindPort} - udp.WriteTo(buf.Bytes(), addr) - - // Wait for response - doneCh := make(chan struct{}, 1) - go func() { - select { - case <-doneCh: - case <-time.After(2 * time.Second): - panic("timeout") - } - }() - - in := make([]byte, 1500) - n, _, err := udp.ReadFrom(in) - if err != nil { - t.Fatalf("unexpected err %s", err) - } - in = in[0:n] - - msgType := messageType(in[0]) - if msgType != ackRespMsg { - t.Fatalf("bad response %v", in) - } - - var ack ackResp - if err := decode(in[1:], &ack); err != nil { - t.Fatalf("unexpected err %s", err) - } - - if ack.SeqNo != 42 { - t.Fatalf("bad sequence no") - } - - doneCh <- struct{}{} -} - -func TestHandlePing_WrongNode(t *testing.T) { - m := GetMemberlist(t) - m.config.EnableCompression = false - defer m.Shutdown() - - var udp *net.UDPConn - for port := 60000; port < 61000; port++ { - udpAddr := fmt.Sprintf("127.0.0.1:%d", port) - udpLn, err := net.ListenPacket("udp", udpAddr) - if err == nil { - udp = udpLn.(*net.UDPConn) - break - } - } - - if udp == nil { - t.Fatalf("no udp listener") - } - - // Encode a ping, wrong node! - ping := ping{SeqNo: 42, Node: m.config.Name + "-bad"} - buf, err := encode(pingMsg, ping) - if err != nil { - t.Fatalf("unexpected err %s", err) - } - - // Send - addr := &net.UDPAddr{IP: net.ParseIP(m.config.BindAddr), Port: m.config.BindPort} - udp.WriteTo(buf.Bytes(), addr) - - // Wait for response - udp.SetDeadline(time.Now().Add(50 * time.Millisecond)) - in := make([]byte, 1500) - _, _, err = udp.ReadFrom(in) - - // Should get an i/o timeout - if err == nil { - t.Fatalf("expected err %s", err) - } -} - -func TestHandleIndirectPing(t *testing.T) { - m := GetMemberlist(t) - m.config.EnableCompression = false - defer m.Shutdown() - - var udp *net.UDPConn - for port := 60000; port < 61000; port++ { - udpAddr := fmt.Sprintf("127.0.0.1:%d", port) - udpLn, err := net.ListenPacket("udp", udpAddr) - if err == nil { - udp = udpLn.(*net.UDPConn) - break - } - } - - if udp == nil { - t.Fatalf("no udp listener") - } - - // Encode an indirect ping - ind := indirectPingReq{ - SeqNo: 100, - Target: net.ParseIP(m.config.BindAddr), - Port: uint16(m.config.BindPort), - } - buf, err := encode(indirectPingMsg, &ind) - if err != nil { - t.Fatalf("unexpected err %s", err) - } - - // Send - addr := &net.UDPAddr{IP: net.ParseIP(m.config.BindAddr), Port: m.config.BindPort} - udp.WriteTo(buf.Bytes(), addr) - - // Wait for response - doneCh := make(chan struct{}, 1) - go func() { - select { - case <-doneCh: - case <-time.After(2 * time.Second): - panic("timeout") - } - }() - - in := make([]byte, 1500) - n, _, err := udp.ReadFrom(in) - if err != nil { - t.Fatalf("unexpected err %s", err) - } - in = in[0:n] - - msgType := messageType(in[0]) - if msgType != ackRespMsg { - t.Fatalf("bad response %v", in) - } - - var ack ackResp - if err := decode(in[1:], &ack); err != nil { - t.Fatalf("unexpected err %s", err) - } - - if ack.SeqNo != 100 { - t.Fatalf("bad sequence no") - } - - doneCh <- struct{}{} -} - -func TestTCPPing(t *testing.T) { - var tcp *net.TCPListener - var tcpAddr *net.TCPAddr - for port := 60000; port < 61000; port++ { - tcpAddr = &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: port} - tcpLn, err := net.ListenTCP("tcp", tcpAddr) - if err == nil { - tcp = tcpLn - break - } - } - if tcp == nil { - t.Fatalf("no tcp listener") - } - - // Note that tcp gets closed in the last test, so we avoid a deferred - // Close() call here. - - m := GetMemberlist(t) - defer m.Shutdown() - pingTimeout := m.config.ProbeInterval - pingTimeMax := m.config.ProbeInterval + 10*time.Millisecond - - // Do a normal round trip. - pingOut := ping{SeqNo: 23, Node: "mongo"} - go func() { - tcp.SetDeadline(time.Now().Add(pingTimeMax)) - conn, err := tcp.AcceptTCP() - if err != nil { - t.Fatalf("failed to connect: %s", err) - } - defer conn.Close() - - msgType, _, dec, err := m.readStream(conn) - if err != nil { - t.Fatalf("failed to read ping: %s", err) - } - - if msgType != pingMsg { - t.Fatalf("expecting ping, got message type (%d)", msgType) - } - - var pingIn ping - if err := dec.Decode(&pingIn); err != nil { - t.Fatalf("failed to decode ping: %s", err) - } - - if pingIn.SeqNo != pingOut.SeqNo { - t.Fatalf("sequence number isn't correct (%d) vs (%d)", pingIn.SeqNo, pingOut.SeqNo) - } - - if pingIn.Node != pingOut.Node { - t.Fatalf("node name isn't correct (%s) vs (%s)", pingIn.Node, pingOut.Node) - } - - ack := ackResp{pingIn.SeqNo, nil} - out, err := encode(ackRespMsg, &ack) - if err != nil { - t.Fatalf("failed to encode ack: %s", err) - } - - err = m.rawSendMsgStream(conn, out.Bytes()) - if err != nil { - t.Fatalf("failed to send ack: %s", err) - } - }() - deadline := time.Now().Add(pingTimeout) - didContact, err := m.sendPingAndWaitForAck(tcpAddr.String(), pingOut, deadline) - if err != nil { - t.Fatalf("error trying to ping: %s", err) - } - if !didContact { - t.Fatalf("expected successful ping") - } - - // Make sure a mis-matched sequence number is caught. - go func() { - tcp.SetDeadline(time.Now().Add(pingTimeMax)) - conn, err := tcp.AcceptTCP() - if err != nil { - t.Fatalf("failed to connect: %s", err) - } - defer conn.Close() - - _, _, dec, err := m.readStream(conn) - if err != nil { - t.Fatalf("failed to read ping: %s", err) - } - - var pingIn ping - if err := dec.Decode(&pingIn); err != nil { - t.Fatalf("failed to decode ping: %s", err) - } - - ack := ackResp{pingIn.SeqNo + 1, nil} - out, err := encode(ackRespMsg, &ack) - if err != nil { - t.Fatalf("failed to encode ack: %s", err) - } - - err = m.rawSendMsgStream(conn, out.Bytes()) - if err != nil { - t.Fatalf("failed to send ack: %s", err) - } - }() - deadline = time.Now().Add(pingTimeout) - didContact, err = m.sendPingAndWaitForAck(tcpAddr.String(), pingOut, deadline) - if err == nil || !strings.Contains(err.Error(), "Sequence number") { - t.Fatalf("expected an error from mis-matched sequence number") - } - if didContact { - t.Fatalf("expected failed ping") - } - - // Make sure an unexpected message type is handled gracefully. - go func() { - tcp.SetDeadline(time.Now().Add(pingTimeMax)) - conn, err := tcp.AcceptTCP() - if err != nil { - t.Fatalf("failed to connect: %s", err) - } - defer conn.Close() - - _, _, _, err = m.readStream(conn) - if err != nil { - t.Fatalf("failed to read ping: %s", err) - } - - bogus := indirectPingReq{} - out, err := encode(indirectPingMsg, &bogus) - if err != nil { - t.Fatalf("failed to encode bogus msg: %s", err) - } - - err = m.rawSendMsgStream(conn, out.Bytes()) - if err != nil { - t.Fatalf("failed to send bogus msg: %s", err) - } - }() - deadline = time.Now().Add(pingTimeout) - didContact, err = m.sendPingAndWaitForAck(tcpAddr.String(), pingOut, deadline) - if err == nil || !strings.Contains(err.Error(), "Unexpected msgType") { - t.Fatalf("expected an error from bogus message") - } - if didContact { - t.Fatalf("expected failed ping") - } - - // Make sure failed I/O respects the deadline. In this case we try the - // common case of the receiving node being totally down. - tcp.Close() - deadline = time.Now().Add(pingTimeout) - startPing := time.Now() - didContact, err = m.sendPingAndWaitForAck(tcpAddr.String(), pingOut, deadline) - pingTime := time.Now().Sub(startPing) - if err != nil { - t.Fatalf("expected no error during ping on closed socket, got: %s", err) - } - if didContact { - t.Fatalf("expected failed ping") - } - if pingTime > pingTimeMax { - t.Fatalf("took too long to fail ping, %9.6f", pingTime.Seconds()) - } -} - -func TestTCPPushPull(t *testing.T) { - m := GetMemberlist(t) - defer m.Shutdown() - m.nodes = append(m.nodes, &nodeState{ - Node: Node{ - Name: "Test 0", - Addr: net.ParseIP(m.config.BindAddr), - Port: uint16(m.config.BindPort), - }, - Incarnation: 0, - State: stateSuspect, - StateChange: time.Now().Add(-1 * time.Second), - }) - - addr := fmt.Sprintf("%s:%d", m.config.BindAddr, m.config.BindPort) - conn, err := net.Dial("tcp", addr) - if err != nil { - t.Fatalf("unexpected err %s", err) - } - defer conn.Close() - - localNodes := make([]pushNodeState, 3) - localNodes[0].Name = "Test 0" - localNodes[0].Addr = net.ParseIP(m.config.BindAddr) - localNodes[0].Port = uint16(m.config.BindPort) - localNodes[0].Incarnation = 1 - localNodes[0].State = stateAlive - localNodes[1].Name = "Test 1" - localNodes[1].Addr = net.ParseIP(m.config.BindAddr) - localNodes[1].Port = uint16(m.config.BindPort) - localNodes[1].Incarnation = 1 - localNodes[1].State = stateAlive - localNodes[2].Name = "Test 2" - localNodes[2].Addr = net.ParseIP(m.config.BindAddr) - localNodes[2].Port = uint16(m.config.BindPort) - localNodes[2].Incarnation = 1 - localNodes[2].State = stateAlive - - // Send our node state - header := pushPullHeader{Nodes: 3} - hd := codec.MsgpackHandle{} - enc := codec.NewEncoder(conn, &hd) - - // Send the push/pull indicator - conn.Write([]byte{byte(pushPullMsg)}) - - if err := enc.Encode(&header); err != nil { - t.Fatalf("unexpected err %s", err) - } - for i := 0; i < header.Nodes; i++ { - if err := enc.Encode(&localNodes[i]); err != nil { - t.Fatalf("unexpected err %s", err) - } - } - - // Read the message type - var msgType messageType - if err := binary.Read(conn, binary.BigEndian, &msgType); err != nil { - t.Fatalf("unexpected err %s", err) - } - - var bufConn io.Reader = conn - msghd := codec.MsgpackHandle{} - dec := codec.NewDecoder(bufConn, &msghd) - - // Check if we have a compressed message - if msgType == compressMsg { - var c compress - if err := dec.Decode(&c); err != nil { - t.Fatalf("unexpected err %s", err) - } - decomp, err := decompressBuffer(&c) - if err != nil { - t.Fatalf("unexpected err %s", err) - } - - // Reset the message type - msgType = messageType(decomp[0]) - - // Create a new bufConn - bufConn = bytes.NewReader(decomp[1:]) - - // Create a new decoder - dec = codec.NewDecoder(bufConn, &hd) - } - - // Quit if not push/pull - if msgType != pushPullMsg { - t.Fatalf("bad message type") - } - - if err := dec.Decode(&header); err != nil { - t.Fatalf("unexpected err %s", err) - } - - // Allocate space for the transfer - remoteNodes := make([]pushNodeState, header.Nodes) - - // Try to decode all the states - for i := 0; i < header.Nodes; i++ { - if err := dec.Decode(&remoteNodes[i]); err != nil { - t.Fatalf("unexpected err %s", err) - } - } - - if len(remoteNodes) != 1 { - t.Fatalf("bad response") - } - - n := &remoteNodes[0] - if n.Name != "Test 0" { - t.Fatalf("bad name") - } - if bytes.Compare(n.Addr, net.ParseIP(m.config.BindAddr)) != 0 { - t.Fatal("bad addr") - } - if n.Incarnation != 0 { - t.Fatal("bad incarnation") - } - if n.State != stateSuspect { - t.Fatal("bad state") - } -} - -func TestSendMsg_Piggyback(t *testing.T) { - m := GetMemberlist(t) - defer m.Shutdown() - - // Add a message to be broadcast - a := alive{ - Incarnation: 10, - Node: "rand", - Addr: []byte{127, 0, 0, 255}, - Meta: nil, - } - m.encodeAndBroadcast("rand", aliveMsg, &a) - - var udp *net.UDPConn - for port := 60000; port < 61000; port++ { - udpAddr := fmt.Sprintf("127.0.0.1:%d", port) - udpLn, err := net.ListenPacket("udp", udpAddr) - if err == nil { - udp = udpLn.(*net.UDPConn) - break - } - } - - // Encode a ping - ping := ping{SeqNo: 42} - buf, err := encode(pingMsg, ping) - if err != nil { - t.Fatalf("unexpected err %s", err) - } - - // Send - addr := &net.UDPAddr{IP: net.ParseIP(m.config.BindAddr), Port: m.config.BindPort} - udp.WriteTo(buf.Bytes(), addr) - - // Wait for response - doneCh := make(chan struct{}, 1) - go func() { - select { - case <-doneCh: - case <-time.After(2 * time.Second): - panic("timeout") - } - }() - - in := make([]byte, 1500) - n, _, err := udp.ReadFrom(in) - if err != nil { - t.Fatalf("unexpected err %s", err) - } - in = in[0:n] - - msgType := messageType(in[0]) - if msgType != compoundMsg { - t.Fatalf("bad response %v", in) - } - - // get the parts - trunc, parts, err := decodeCompoundMessage(in[1:]) - if trunc != 0 { - t.Fatalf("unexpected truncation") - } - if len(parts) != 2 { - t.Fatalf("unexpected parts %v", parts) - } - if err != nil { - t.Fatalf("unexpected err %s", err) - } - - var ack ackResp - if err := decode(parts[0][1:], &ack); err != nil { - t.Fatalf("unexpected err %s", err) - } - - if ack.SeqNo != 42 { - t.Fatalf("bad sequence no") - } - - var aliveout alive - if err := decode(parts[1][1:], &aliveout); err != nil { - t.Fatalf("unexpected err %s", err) - } - - if aliveout.Node != "rand" || aliveout.Incarnation != 10 { - t.Fatalf("bad mesg") - } - - doneCh <- struct{}{} -} - -func TestEncryptDecryptState(t *testing.T) { - state := []byte("this is our internal state...") - config := &Config{ - SecretKey: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - ProtocolVersion: ProtocolVersionMax, - } - - m, err := Create(config) - if err != nil { - t.Fatalf("err: %s", err) - } - defer m.Shutdown() - - crypt, err := m.encryptLocalState(state) - if err != nil { - t.Fatalf("err: %v", err) - } - - // Create reader, seek past the type byte - buf := bytes.NewReader(crypt) - buf.Seek(1, 0) - - plain, err := m.decryptRemoteState(buf) - if err != nil { - t.Fatalf("err: %v", err) - } - - if !reflect.DeepEqual(state, plain) { - t.Fatalf("Decrypt failed: %v", plain) - } -} - -func TestRawSendUdp_CRC(t *testing.T) { - m := GetMemberlist(t) - m.config.EnableCompression = false - defer m.Shutdown() - - var udp *net.UDPConn - for port := 60000; port < 61000; port++ { - udpAddr := fmt.Sprintf("127.0.0.1:%d", port) - udpLn, err := net.ListenPacket("udp", udpAddr) - if err == nil { - udp = udpLn.(*net.UDPConn) - break - } - } - - if udp == nil { - t.Fatalf("no udp listener") - } - - // Pass a nil node with no nodes registered, should result in no checksum - payload := []byte{3, 3, 3, 3} - m.rawSendMsgPacket(udp.LocalAddr().String(), nil, payload) - - in := make([]byte, 1500) - n, _, err := udp.ReadFrom(in) - if err != nil { - t.Fatalf("unexpected err %s", err) - } - in = in[0:n] - - if len(in) != 4 { - t.Fatalf("bad: %v", in) - } - - // Pass a non-nil node with PMax >= 5, should result in a checksum - m.rawSendMsgPacket(udp.LocalAddr().String(), &Node{PMax: 5}, payload) - - in = make([]byte, 1500) - n, _, err = udp.ReadFrom(in) - if err != nil { - t.Fatalf("unexpected err %s", err) - } - in = in[0:n] - - if len(in) != 9 { - t.Fatalf("bad: %v", in) - } - - // Register a node with PMax >= 5 to be looked up, should result in a checksum - m.nodeMap["127.0.0.1"] = &nodeState{ - Node: Node{PMax: 5}, - } - m.rawSendMsgPacket(udp.LocalAddr().String(), nil, payload) - - in = make([]byte, 1500) - n, _, err = udp.ReadFrom(in) - if err != nil { - t.Fatalf("unexpected err %s", err) - } - in = in[0:n] - - if len(in) != 9 { - t.Fatalf("bad: %v", in) - } -} - -func TestIngestPacket_CRC(t *testing.T) { - m := GetMemberlist(t) - m.config.EnableCompression = false - defer m.Shutdown() - - var udp *net.UDPConn - for port := 60000; port < 61000; port++ { - udpAddr := fmt.Sprintf("127.0.0.1:%d", port) - udpLn, err := net.ListenPacket("udp", udpAddr) - if err == nil { - udp = udpLn.(*net.UDPConn) - break - } - } - - if udp == nil { - t.Fatalf("no udp listener") - } - - // Get a message with a checksum - payload := []byte{3, 3, 3, 3} - m.rawSendMsgPacket(udp.LocalAddr().String(), &Node{PMax: 5}, payload) - - in := make([]byte, 1500) - n, _, err := udp.ReadFrom(in) - if err != nil { - t.Fatalf("unexpected err %s", err) - } - in = in[0:n] - - if len(in) != 9 { - t.Fatalf("bad: %v", in) - } - - // Corrupt the checksum - in[1] <<= 1 - - logs := &bytes.Buffer{} - logger := log.New(logs, "", 0) - m.logger = logger - m.ingestPacket(in, udp.LocalAddr(), time.Now()) - - if !strings.Contains(logs.String(), "invalid checksum") { - t.Fatalf("bad: %s", logs.String()) - } -} - -func TestGossip_MismatchedKeys(t *testing.T) { - c1 := testConfig() - c2 := testConfig() - - // Create two agents with different gossip keys - c1.SecretKey = []byte("4W6DGn2VQVqDEceOdmuRTQ==") - c2.SecretKey = []byte("XhX/w702/JKKK7/7OtM9Ww==") - - 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() - - // Make sure we get this error on the joining side - _, err = m2.Join([]string{c1.BindAddr}) - if err == nil || !strings.Contains(err.Error(), "No installed keys could decrypt the message") { - t.Fatalf("bad: %s", err) - } -} diff --git a/vendor/github.com/hashicorp/memberlist/queue_test.go b/vendor/github.com/hashicorp/memberlist/queue_test.go deleted file mode 100644 index 765a3b53d..000000000 --- a/vendor/github.com/hashicorp/memberlist/queue_test.go +++ /dev/null @@ -1,172 +0,0 @@ -package memberlist - -import ( - "testing" -) - -func TestTransmitLimited_Queue(t *testing.T) { - q := &TransmitLimitedQueue{RetransmitMult: 1, NumNodes: func() int { return 1 }} - q.QueueBroadcast(&memberlistBroadcast{"test", nil, nil}) - q.QueueBroadcast(&memberlistBroadcast{"foo", nil, nil}) - q.QueueBroadcast(&memberlistBroadcast{"bar", nil, nil}) - - if len(q.bcQueue) != 3 { - t.Fatalf("bad len") - } - if q.bcQueue[0].b.(*memberlistBroadcast).node != "test" { - t.Fatalf("missing test") - } - if q.bcQueue[1].b.(*memberlistBroadcast).node != "foo" { - t.Fatalf("missing foo") - } - if q.bcQueue[2].b.(*memberlistBroadcast).node != "bar" { - t.Fatalf("missing bar") - } - - // Should invalidate previous message - q.QueueBroadcast(&memberlistBroadcast{"test", nil, nil}) - - if len(q.bcQueue) != 3 { - t.Fatalf("bad len") - } - if q.bcQueue[0].b.(*memberlistBroadcast).node != "foo" { - t.Fatalf("missing foo") - } - if q.bcQueue[1].b.(*memberlistBroadcast).node != "bar" { - t.Fatalf("missing bar") - } - if q.bcQueue[2].b.(*memberlistBroadcast).node != "test" { - t.Fatalf("missing test") - } -} - -func TestTransmitLimited_GetBroadcasts(t *testing.T) { - q := &TransmitLimitedQueue{RetransmitMult: 3, NumNodes: func() int { return 10 }} - - // 18 bytes per message - q.QueueBroadcast(&memberlistBroadcast{"test", []byte("1. this is a test."), nil}) - q.QueueBroadcast(&memberlistBroadcast{"foo", []byte("2. this is a test."), nil}) - q.QueueBroadcast(&memberlistBroadcast{"bar", []byte("3. this is a test."), nil}) - q.QueueBroadcast(&memberlistBroadcast{"baz", []byte("4. this is a test."), nil}) - - // 2 byte overhead per message, should get all 4 messages - all := q.GetBroadcasts(2, 80) - if len(all) != 4 { - t.Fatalf("missing messages: %v", all) - } - - // 3 byte overhead, should only get 3 messages back - partial := q.GetBroadcasts(3, 80) - if len(partial) != 3 { - t.Fatalf("missing messages: %v", partial) - } -} - -func TestTransmitLimited_GetBroadcasts_Limit(t *testing.T) { - q := &TransmitLimitedQueue{RetransmitMult: 1, NumNodes: func() int { return 10 }} - - // 18 bytes per message - q.QueueBroadcast(&memberlistBroadcast{"test", []byte("1. this is a test."), nil}) - q.QueueBroadcast(&memberlistBroadcast{"foo", []byte("2. this is a test."), nil}) - q.QueueBroadcast(&memberlistBroadcast{"bar", []byte("3. this is a test."), nil}) - q.QueueBroadcast(&memberlistBroadcast{"baz", []byte("4. this is a test."), nil}) - - // 3 byte overhead, should only get 3 messages back - partial1 := q.GetBroadcasts(3, 80) - if len(partial1) != 3 { - t.Fatalf("missing messages: %v", partial1) - } - - partial2 := q.GetBroadcasts(3, 80) - if len(partial2) != 3 { - t.Fatalf("missing messages: %v", partial2) - } - - // Only two not expired - partial3 := q.GetBroadcasts(3, 80) - if len(partial3) != 2 { - t.Fatalf("missing messages: %v", partial3) - } - - // Should get nothing - partial5 := q.GetBroadcasts(3, 80) - if len(partial5) != 0 { - t.Fatalf("missing messages: %v", partial5) - } -} - -func TestTransmitLimited_Prune(t *testing.T) { - q := &TransmitLimitedQueue{RetransmitMult: 1, NumNodes: func() int { return 10 }} - - ch1 := make(chan struct{}, 1) - ch2 := make(chan struct{}, 1) - - // 18 bytes per message - q.QueueBroadcast(&memberlistBroadcast{"test", []byte("1. this is a test."), ch1}) - q.QueueBroadcast(&memberlistBroadcast{"foo", []byte("2. this is a test."), ch2}) - q.QueueBroadcast(&memberlistBroadcast{"bar", []byte("3. this is a test."), nil}) - q.QueueBroadcast(&memberlistBroadcast{"baz", []byte("4. this is a test."), nil}) - - // Keep only 2 - q.Prune(2) - - if q.NumQueued() != 2 { - t.Fatalf("bad len") - } - - // Should notify the first two - select { - case <-ch1: - default: - t.Fatalf("expected invalidation") - } - select { - case <-ch2: - default: - t.Fatalf("expected invalidation") - } - - if q.bcQueue[0].b.(*memberlistBroadcast).node != "bar" { - t.Fatalf("missing bar") - } - if q.bcQueue[1].b.(*memberlistBroadcast).node != "baz" { - t.Fatalf("missing baz") - } -} - -func TestLimitedBroadcastSort(t *testing.T) { - bc := limitedBroadcasts([]*limitedBroadcast{ - &limitedBroadcast{ - transmits: 0, - }, - &limitedBroadcast{ - transmits: 10, - }, - &limitedBroadcast{ - transmits: 3, - }, - &limitedBroadcast{ - transmits: 4, - }, - &limitedBroadcast{ - transmits: 7, - }, - }) - bc.Sort() - - if bc[0].transmits != 10 { - t.Fatalf("bad val %v", bc[0]) - } - if bc[1].transmits != 7 { - t.Fatalf("bad val %v", bc[7]) - } - if bc[2].transmits != 4 { - t.Fatalf("bad val %v", bc[2]) - } - if bc[3].transmits != 3 { - t.Fatalf("bad val %v", bc[3]) - } - if bc[4].transmits != 0 { - t.Fatalf("bad val %v", bc[4]) - } -} diff --git a/vendor/github.com/hashicorp/memberlist/security_test.go b/vendor/github.com/hashicorp/memberlist/security_test.go deleted file mode 100644 index 15fa4aa8e..000000000 --- a/vendor/github.com/hashicorp/memberlist/security_test.go +++ /dev/null @@ -1,70 +0,0 @@ -package memberlist - -import ( - "bytes" - "reflect" - "testing" -) - -func TestPKCS7(t *testing.T) { - for i := 0; i <= 255; i++ { - // Make a buffer of size i - buf := []byte{} - for j := 0; j < i; j++ { - buf = append(buf, byte(i)) - } - - // Copy to bytes buffer - inp := bytes.NewBuffer(nil) - inp.Write(buf) - - // Pad this out - pkcs7encode(inp, 0, 16) - - // Unpad - dec := pkcs7decode(inp.Bytes(), 16) - - // Ensure equivilence - if !reflect.DeepEqual(buf, dec) { - t.Fatalf("mismatch: %v %v", buf, dec) - } - } - -} - -func TestEncryptDecrypt_V0(t *testing.T) { - encryptDecryptVersioned(0, t) -} - -func TestEncryptDecrypt_V1(t *testing.T) { - encryptDecryptVersioned(1, t) -} - -func encryptDecryptVersioned(vsn encryptionVersion, t *testing.T) { - k1 := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} - plaintext := []byte("this is a plain text message") - extra := []byte("random data") - - var buf bytes.Buffer - err := encryptPayload(vsn, k1, plaintext, extra, &buf) - if err != nil { - t.Fatalf("err: %v", err) - } - - expLen := encryptedLength(vsn, len(plaintext)) - if buf.Len() != expLen { - t.Fatalf("output length is unexpected %d %d %d", len(plaintext), buf.Len(), expLen) - } - - msg, err := decryptPayload([][]byte{k1}, buf.Bytes(), extra) - if err != nil { - t.Fatalf("err: %v", err) - } - - cmp := bytes.Compare(msg, plaintext) - if cmp != 0 { - t.Errorf("len %d %v", len(msg), msg) - t.Errorf("len %d %v", len(plaintext), plaintext) - t.Fatalf("encrypt/decrypt failed! %d '%s' '%s'", cmp, msg, plaintext) - } -} diff --git a/vendor/github.com/hashicorp/memberlist/state_test.go b/vendor/github.com/hashicorp/memberlist/state_test.go deleted file mode 100644 index 71e93ca4e..000000000 --- a/vendor/github.com/hashicorp/memberlist/state_test.go +++ /dev/null @@ -1,1900 +0,0 @@ -package memberlist - -import ( - "bytes" - "fmt" - "net" - "testing" - "time" -) - -func HostMemberlist(host string, t *testing.T, f func(*Config)) *Memberlist { - c := DefaultLANConfig() - c.Name = host - c.BindAddr = host - if f != nil { - f(c) - } - - m, err := newMemberlist(c) - if err != nil { - t.Fatalf("failed to get memberlist: %s", err) - } - return m -} - -func TestMemberList_Probe(t *testing.T) { - addr1 := getBindAddr() - addr2 := getBindAddr() - m1 := HostMemberlist(addr1.String(), t, func(c *Config) { - c.ProbeTimeout = time.Millisecond - c.ProbeInterval = 10 * time.Millisecond - }) - m2 := HostMemberlist(addr2.String(), t, nil) - - a1 := alive{ - Node: addr1.String(), - Addr: []byte(addr1), - Port: uint16(m1.config.BindPort), - Incarnation: 1, - } - m1.aliveNode(&a1, nil, true) - a2 := alive{ - Node: addr2.String(), - Addr: []byte(addr2), - Port: uint16(m2.config.BindPort), - Incarnation: 1, - } - m1.aliveNode(&a2, nil, false) - - // should ping addr2 - m1.probe() - - // Should not be marked suspect - n := m1.nodeMap[addr2.String()] - if n.State != stateAlive { - t.Fatalf("Expect node to be alive") - } - - // Should increment seqno - if m1.sequenceNum != 1 { - t.Fatalf("bad seqno %v", m2.sequenceNum) - } -} - -func TestMemberList_ProbeNode_Suspect(t *testing.T) { - addr1 := getBindAddr() - addr2 := getBindAddr() - addr3 := getBindAddr() - addr4 := getBindAddr() - ip1 := []byte(addr1) - ip2 := []byte(addr2) - ip3 := []byte(addr3) - ip4 := []byte(addr4) - - m1 := HostMemberlist(addr1.String(), t, func(c *Config) { - c.ProbeTimeout = time.Millisecond - c.ProbeInterval = 10 * time.Millisecond - }) - m2 := HostMemberlist(addr2.String(), t, nil) - m3 := HostMemberlist(addr3.String(), t, nil) - - a1 := alive{Node: addr1.String(), Addr: ip1, Port: 7946, Incarnation: 1} - m1.aliveNode(&a1, nil, true) - a2 := alive{Node: addr2.String(), Addr: ip2, Port: 7946, Incarnation: 1} - m1.aliveNode(&a2, nil, false) - a3 := alive{Node: addr3.String(), Addr: ip3, Port: 7946, Incarnation: 1} - m1.aliveNode(&a3, nil, false) - a4 := alive{Node: addr4.String(), Addr: ip4, Port: 7946, Incarnation: 1} - m1.aliveNode(&a4, nil, false) - - n := m1.nodeMap[addr4.String()] - m1.probeNode(n) - - // Should be marked suspect. - if n.State != stateSuspect { - t.Fatalf("Expect node to be suspect") - } - time.Sleep(10 * time.Millisecond) - - // One of the peers should have attempted an indirect probe. - if m2.sequenceNum != 1 && m3.sequenceNum != 1 { - t.Fatalf("bad seqnos %v, %v", m2.sequenceNum, m3.sequenceNum) - } -} - -func TestMemberList_ProbeNode_Suspect_Dogpile(t *testing.T) { - cases := []struct { - numPeers int - confirmations int - expected time.Duration - }{ - {1, 0, 500 * time.Millisecond}, // n=2, k=3 (max timeout disabled) - {2, 0, 500 * time.Millisecond}, // n=3, k=3 - {3, 0, 500 * time.Millisecond}, // n=4, k=3 - {4, 0, 1000 * time.Millisecond}, // n=5, k=3 (max timeout starts to take effect) - {5, 0, 1000 * time.Millisecond}, // n=6, k=3 - {5, 1, 750 * time.Millisecond}, // n=6, k=3 (confirmations start to lower timeout) - {5, 2, 604 * time.Millisecond}, // n=6, k=3 - {5, 3, 500 * time.Millisecond}, // n=6, k=3 (timeout driven to nominal value) - {5, 4, 500 * time.Millisecond}, // n=6, k=3 - } - for i, c := range cases { - // Create the main memberlist under test. - addr := getBindAddr() - m := HostMemberlist(addr.String(), t, func(c *Config) { - c.ProbeTimeout = time.Millisecond - c.ProbeInterval = 100 * time.Millisecond - c.SuspicionMult = 5 - c.SuspicionMaxTimeoutMult = 2 - }) - a := alive{Node: addr.String(), Addr: []byte(addr), Port: 7946, Incarnation: 1} - m.aliveNode(&a, nil, true) - - // Make all but one peer be an real, alive instance. - var peers []*Memberlist - for j := 0; j < c.numPeers-1; j++ { - peerAddr := getBindAddr() - peers = append(peers, HostMemberlist(peerAddr.String(), t, nil)) - a = alive{Node: peerAddr.String(), Addr: []byte(peerAddr), Port: 7946, Incarnation: 1} - m.aliveNode(&a, nil, false) - } - - // Just use a bogus address for the last peer so it doesn't respond - // to pings, but tell the memberlist it's alive. - badPeerAddr := getBindAddr() - a = alive{Node: badPeerAddr.String(), Addr: []byte(badPeerAddr), Port: 7946, Incarnation: 1} - m.aliveNode(&a, nil, false) - - // Force a probe, which should start us into the suspect state. - n := m.nodeMap[badPeerAddr.String()] - m.probeNode(n) - if n.State != stateSuspect { - t.Fatalf("case %d: expected node to be suspect", i) - } - - // Add the requested number of confirmations. - for j := 0; j < c.confirmations; j++ { - from := fmt.Sprintf("peer%d", j) - s := suspect{Node: badPeerAddr.String(), Incarnation: 1, From: from} - m.suspectNode(&s) - } - - // Wait until right before the timeout and make sure the timer - // hasn't fired. - fudge := 25 * time.Millisecond - time.Sleep(c.expected - fudge) - if n.State != stateSuspect { - t.Fatalf("case %d: expected node to still be suspect", i) - } - - // Wait through the timeout and a little after to make sure the - // timer fires. - time.Sleep(2 * fudge) - if n.State != stateDead { - t.Fatalf("case %d: expected node to be dead", i) - } - } -} - -/* -func TestMemberList_ProbeNode_FallbackTCP(t *testing.T) { - addr1 := getBindAddr() - addr2 := getBindAddr() - addr3 := getBindAddr() - addr4 := getBindAddr() - ip1 := []byte(addr1) - ip2 := []byte(addr2) - ip3 := []byte(addr3) - ip4 := []byte(addr4) - - var probeTimeMax time.Duration - m1 := HostMemberlist(addr1.String(), t, func(c *Config) { - c.ProbeTimeout = 10 * time.Millisecond - c.ProbeInterval = 200 * time.Millisecond - probeTimeMax = c.ProbeInterval + 20*time.Millisecond - }) - defer m1.Shutdown() - - m2 := HostMemberlist(addr2.String(), t, nil) - defer m2.Shutdown() - - m3 := HostMemberlist(addr3.String(), t, nil) - defer m3.Shutdown() - - m4 := HostMemberlist(addr4.String(), t, nil) - defer m4.Shutdown() - - a1 := alive{Node: addr1.String(), Addr: ip1, Port: 7946, Incarnation: 1} - m1.aliveNode(&a1, nil, true) - a2 := alive{Node: addr2.String(), Addr: ip2, Port: 7946, Incarnation: 1} - m1.aliveNode(&a2, nil, false) - a3 := alive{Node: addr3.String(), Addr: ip3, Port: 7946, Incarnation: 1} - m1.aliveNode(&a3, nil, false) - - // Make sure m4 is configured with the same protocol version as m1 so - // the TCP fallback behavior is enabled. - a4 := alive{ - Node: addr4.String(), - Addr: ip4, - Port: 7946, - Incarnation: 1, - Vsn: []uint8{ - ProtocolVersionMin, - ProtocolVersionMax, - m1.config.ProtocolVersion, - m1.config.DelegateProtocolMin, - m1.config.DelegateProtocolMax, - m1.config.DelegateProtocolVersion, - }, - } - m1.aliveNode(&a4, nil, false) - - // Isolate m4 from UDP traffic by re-opening its listener on the wrong - // port. This should force the TCP fallback path to be used. - var err error - if err = m4.udpListener.Close(); err != nil { - t.Fatalf("err: %v", err) - } - udpAddr := &net.UDPAddr{IP: ip4, Port: 9999} - if m4.udpListener, err = net.ListenUDP("udp", udpAddr); err != nil { - t.Fatalf("err: %v", err) - } - - // Have node m1 probe m4. - n := m1.nodeMap[addr4.String()] - startProbe := time.Now() - m1.probeNode(n) - probeTime := time.Now().Sub(startProbe) - - // Should be marked alive because of the TCP fallback ping. - if n.State != stateAlive { - t.Fatalf("expect node to be alive") - } - - // Make sure TCP activity completed in a timely manner. - if probeTime > probeTimeMax { - t.Fatalf("took to long to probe, %9.6f", probeTime.Seconds()) - } - - // Confirm at least one of the peers attempted an indirect probe. - time.Sleep(probeTimeMax) - if m2.sequenceNum != 1 && m3.sequenceNum != 1 { - t.Fatalf("bad seqnos %v, %v", m2.sequenceNum, m3.sequenceNum) - } - - // Now shutdown all inbound TCP traffic to make sure the TCP fallback - // path properly fails when the node is really unreachable. - if err = m4.tcpListener.Close(); err != nil { - t.Fatalf("err: %v", err) - } - tcpAddr := &net.TCPAddr{IP: ip4, Port: 9999} - if m4.tcpListener, err = net.ListenTCP("tcp", tcpAddr); err != nil { - t.Fatalf("err: %v", err) - } - - // Probe again, this time there should be no contact. - startProbe = time.Now() - m1.probeNode(n) - probeTime = time.Now().Sub(startProbe) - - // Node should be reported suspect. - if n.State != stateSuspect { - t.Fatalf("expect node to be suspect") - } - - // Make sure TCP activity didn't cause us to wait too long before - // timing out. - if probeTime > probeTimeMax { - t.Fatalf("took to long to probe, %9.6f", probeTime.Seconds()) - } - - // Confirm at least one of the peers attempted an indirect probe. - time.Sleep(probeTimeMax) - if m2.sequenceNum != 2 && m3.sequenceNum != 2 { - t.Fatalf("bad seqnos %v, %v", m2.sequenceNum, m3.sequenceNum) - } -} - -func TestMemberList_ProbeNode_FallbackTCP_Disabled(t *testing.T) { - addr1 := getBindAddr() - addr2 := getBindAddr() - addr3 := getBindAddr() - addr4 := getBindAddr() - ip1 := []byte(addr1) - ip2 := []byte(addr2) - ip3 := []byte(addr3) - ip4 := []byte(addr4) - - var probeTimeMax time.Duration - m1 := HostMemberlist(addr1.String(), t, func(c *Config) { - c.ProbeTimeout = 10 * time.Millisecond - c.ProbeInterval = 200 * time.Millisecond - probeTimeMax = c.ProbeInterval + 20*time.Millisecond - }) - defer m1.Shutdown() - - m2 := HostMemberlist(addr2.String(), t, nil) - defer m2.Shutdown() - - m3 := HostMemberlist(addr3.String(), t, nil) - defer m3.Shutdown() - - m4 := HostMemberlist(addr4.String(), t, nil) - defer m4.Shutdown() - - a1 := alive{Node: addr1.String(), Addr: ip1, Port: 7946, Incarnation: 1} - m1.aliveNode(&a1, nil, true) - a2 := alive{Node: addr2.String(), Addr: ip2, Port: 7946, Incarnation: 1} - m1.aliveNode(&a2, nil, false) - a3 := alive{Node: addr3.String(), Addr: ip3, Port: 7946, Incarnation: 1} - m1.aliveNode(&a3, nil, false) - - // Make sure m4 is configured with the same protocol version as m1 so - // the TCP fallback behavior is enabled. - a4 := alive{ - Node: addr4.String(), - Addr: ip4, - Port: 7946, - Incarnation: 1, - Vsn: []uint8{ - ProtocolVersionMin, - ProtocolVersionMax, - m1.config.ProtocolVersion, - m1.config.DelegateProtocolMin, - m1.config.DelegateProtocolMax, - m1.config.DelegateProtocolVersion, - }, - } - m1.aliveNode(&a4, nil, false) - - // Isolate m4 from UDP traffic by re-opening its listener on the wrong - // port. This should force the TCP fallback path to be used. - var err error - if err = m4.udpListener.Close(); err != nil { - t.Fatalf("err: %v", err) - } - udpAddr := &net.UDPAddr{IP: ip4, Port: 9999} - if m4.udpListener, err = net.ListenUDP("udp", udpAddr); err != nil { - t.Fatalf("err: %v", err) - } - - // Disable the TCP pings using the config mechanism. - m1.config.DisableTcpPings = true - - // Have node m1 probe m4. - n := m1.nodeMap[addr4.String()] - startProbe := time.Now() - m1.probeNode(n) - probeTime := time.Now().Sub(startProbe) - - // Node should be reported suspect. - if n.State != stateSuspect { - t.Fatalf("expect node to be suspect") - } - - // Make sure TCP activity didn't cause us to wait too long before - // timing out. - if probeTime > probeTimeMax { - t.Fatalf("took to long to probe, %9.6f", probeTime.Seconds()) - } - - // Confirm at least one of the peers attempted an indirect probe. - time.Sleep(probeTimeMax) - if m2.sequenceNum != 1 && m3.sequenceNum != 1 { - t.Fatalf("bad seqnos %v, %v", m2.sequenceNum, m3.sequenceNum) - } -} - -func TestMemberList_ProbeNode_FallbackTCP_OldProtocol(t *testing.T) { - addr1 := getBindAddr() - addr2 := getBindAddr() - addr3 := getBindAddr() - addr4 := getBindAddr() - ip1 := []byte(addr1) - ip2 := []byte(addr2) - ip3 := []byte(addr3) - ip4 := []byte(addr4) - - var probeTimeMax time.Duration - m1 := HostMemberlist(addr1.String(), t, func(c *Config) { - c.ProbeTimeout = 10 * time.Millisecond - c.ProbeInterval = 200 * time.Millisecond - probeTimeMax = c.ProbeInterval + 20*time.Millisecond - }) - defer m1.Shutdown() - - m2 := HostMemberlist(addr2.String(), t, nil) - defer m2.Shutdown() - - m3 := HostMemberlist(addr3.String(), t, nil) - defer m3.Shutdown() - - m4 := HostMemberlist(addr4.String(), t, nil) - defer m4.Shutdown() - - a1 := alive{Node: addr1.String(), Addr: ip1, Port: 7946, Incarnation: 1} - m1.aliveNode(&a1, nil, true) - a2 := alive{Node: addr2.String(), Addr: ip2, Port: 7946, Incarnation: 1} - m1.aliveNode(&a2, nil, false) - a3 := alive{Node: addr3.String(), Addr: ip3, Port: 7946, Incarnation: 1} - m1.aliveNode(&a3, nil, false) - - // Set up m4 so that it doesn't understand a version of the protocol - // that supports TCP pings. - a4 := alive{ - Node: addr4.String(), - Addr: ip4, - Port: 7946, - Incarnation: 1, - Vsn: []uint8{ - ProtocolVersionMin, - ProtocolVersion2Compatible, - ProtocolVersion2Compatible, - m1.config.DelegateProtocolMin, - m1.config.DelegateProtocolMax, - m1.config.DelegateProtocolVersion, - }, - } - m1.aliveNode(&a4, nil, false) - - // Isolate m4 from UDP traffic by re-opening its listener on the wrong - // port. This should force the TCP fallback path to be used. - var err error - if err = m4.udpListener.Close(); err != nil { - t.Fatalf("err: %v", err) - } - udpAddr := &net.UDPAddr{IP: ip4, Port: 9999} - if m4.udpListener, err = net.ListenUDP("udp", udpAddr); err != nil { - t.Fatalf("err: %v", err) - } - - // Have node m1 probe m4. - n := m1.nodeMap[addr4.String()] - startProbe := time.Now() - m1.probeNode(n) - probeTime := time.Now().Sub(startProbe) - - // Node should be reported suspect. - if n.State != stateSuspect { - t.Fatalf("expect node to be suspect") - } - - // Make sure TCP activity didn't cause us to wait too long before - // timing out. - if probeTime > probeTimeMax { - t.Fatalf("took to long to probe, %9.6f", probeTime.Seconds()) - } - - // Confirm at least one of the peers attempted an indirect probe. - time.Sleep(probeTimeMax) - if m2.sequenceNum != 1 && m3.sequenceNum != 1 { - t.Fatalf("bad seqnos %v, %v", m2.sequenceNum, m3.sequenceNum) - } -} -*/ - -func TestMemberList_ProbeNode_Awareness_Degraded(t *testing.T) { - addr1 := getBindAddr() - addr2 := getBindAddr() - addr3 := getBindAddr() - addr4 := getBindAddr() - ip1 := []byte(addr1) - ip2 := []byte(addr2) - ip3 := []byte(addr3) - ip4 := []byte(addr4) - - var probeTimeMin time.Duration - m1 := HostMemberlist(addr1.String(), t, func(c *Config) { - c.ProbeTimeout = 10 * time.Millisecond - c.ProbeInterval = 200 * time.Millisecond - probeTimeMin = 2*c.ProbeInterval - 50*time.Millisecond - }) - defer m1.Shutdown() - - m2 := HostMemberlist(addr2.String(), t, func(c *Config) { - c.ProbeTimeout = 10 * time.Millisecond - c.ProbeInterval = 200 * time.Millisecond - }) - defer m2.Shutdown() - - m3 := HostMemberlist(addr3.String(), t, func(c *Config) { - c.ProbeTimeout = 10 * time.Millisecond - c.ProbeInterval = 200 * time.Millisecond - }) - defer m3.Shutdown() - - // This will enable nacks by invoking the latest protocol version. - vsn := []uint8{ - ProtocolVersionMin, - ProtocolVersionMax, - m1.config.ProtocolVersion, - m1.config.DelegateProtocolMin, - m1.config.DelegateProtocolMax, - m1.config.DelegateProtocolVersion, - } - - a1 := alive{Node: addr1.String(), Addr: ip1, Port: 7946, Incarnation: 1, Vsn: vsn} - m1.aliveNode(&a1, nil, true) - a2 := alive{Node: addr2.String(), Addr: ip2, Port: 7946, Incarnation: 1, Vsn: vsn} - m1.aliveNode(&a2, nil, false) - a3 := alive{Node: addr3.String(), Addr: ip3, Port: 7946, Incarnation: 1, Vsn: vsn} - m1.aliveNode(&a3, nil, false) - - // Node 4 never gets started. - a4 := alive{Node: addr4.String(), Addr: ip4, Port: 7946, Incarnation: 1, Vsn: vsn} - m1.aliveNode(&a4, nil, false) - - // Start the health in a degraded state. - m1.awareness.ApplyDelta(1) - if score := m1.GetHealthScore(); score != 1 { - t.Fatalf("bad: %d", score) - } - - // Have node m1 probe m4. - n := m1.nodeMap[addr4.String()] - startProbe := time.Now() - m1.probeNode(n) - probeTime := time.Now().Sub(startProbe) - - // Node should be reported suspect. - if n.State != stateSuspect { - t.Fatalf("expect node to be suspect") - } - - // Make sure we timed out approximately on time (note that we accounted - // for the slowed-down failure detector in the probeTimeMin calculation. - if probeTime < probeTimeMin { - t.Fatalf("probed too quickly, %9.6f", probeTime.Seconds()) - } - - // Confirm at least one of the peers attempted an indirect probe. - if m2.sequenceNum != 1 && m3.sequenceNum != 1 { - t.Fatalf("bad seqnos %v, %v", m2.sequenceNum, m3.sequenceNum) - } - - // We should have gotten all the nacks, so our score should remain the - // same, since we didn't get a successful probe. - if score := m1.GetHealthScore(); score != 1 { - t.Fatalf("bad: %d", score) - } -} - -func TestMemberList_ProbeNode_Awareness_Improved(t *testing.T) { - addr1 := getBindAddr() - addr2 := getBindAddr() - ip1 := []byte(addr1) - ip2 := []byte(addr2) - - m1 := HostMemberlist(addr1.String(), t, func(c *Config) { - c.ProbeTimeout = 10 * time.Millisecond - c.ProbeInterval = 200 * time.Millisecond - }) - defer m1.Shutdown() - - m2 := HostMemberlist(addr2.String(), t, nil) - defer m2.Shutdown() - - a1 := alive{Node: addr1.String(), Addr: ip1, Port: 7946, Incarnation: 1} - m1.aliveNode(&a1, nil, true) - a2 := alive{Node: addr2.String(), Addr: ip2, Port: 7946, Incarnation: 1} - m1.aliveNode(&a2, nil, false) - - // Start the health in a degraded state. - m1.awareness.ApplyDelta(1) - if score := m1.GetHealthScore(); score != 1 { - t.Fatalf("bad: %d", score) - } - - // Have node m1 probe m2. - n := m1.nodeMap[addr2.String()] - m1.probeNode(n) - - // Node should be reported alive. - if n.State != stateAlive { - t.Fatalf("expect node to be suspect") - } - - // Our score should have improved since we did a good probe. - if score := m1.GetHealthScore(); score != 0 { - t.Fatalf("bad: %d", score) - } -} - -func TestMemberList_ProbeNode_Awareness_MissedNack(t *testing.T) { - addr1 := getBindAddr() - addr2 := getBindAddr() - addr3 := getBindAddr() - addr4 := getBindAddr() - ip1 := []byte(addr1) - ip2 := []byte(addr2) - ip3 := []byte(addr3) - ip4 := []byte(addr4) - - var probeTimeMax time.Duration - m1 := HostMemberlist(addr1.String(), t, func(c *Config) { - c.ProbeTimeout = 10 * time.Millisecond - c.ProbeInterval = 200 * time.Millisecond - probeTimeMax = c.ProbeInterval + 50*time.Millisecond - }) - defer m1.Shutdown() - - m2 := HostMemberlist(addr2.String(), t, func(c *Config) { - c.ProbeTimeout = 10 * time.Millisecond - c.ProbeInterval = 200 * time.Millisecond - }) - defer m2.Shutdown() - - // This will enable nacks by invoking the latest protocol version. - vsn := []uint8{ - ProtocolVersionMin, - ProtocolVersionMax, - m1.config.ProtocolVersion, - m1.config.DelegateProtocolMin, - m1.config.DelegateProtocolMax, - m1.config.DelegateProtocolVersion, - } - - a1 := alive{Node: addr1.String(), Addr: ip1, Port: 7946, Incarnation: 1, Vsn: vsn} - m1.aliveNode(&a1, nil, true) - a2 := alive{Node: addr2.String(), Addr: ip2, Port: 7946, Incarnation: 1, Vsn: vsn} - m1.aliveNode(&a2, nil, false) - - // Node 3 and node 4 never get started. - a3 := alive{Node: addr3.String(), Addr: ip3, Port: 7946, Incarnation: 1, Vsn: vsn} - m1.aliveNode(&a3, nil, false) - a4 := alive{Node: addr4.String(), Addr: ip4, Port: 7946, Incarnation: 1, Vsn: vsn} - m1.aliveNode(&a4, nil, false) - - // Make sure health looks good. - if score := m1.GetHealthScore(); score != 0 { - t.Fatalf("bad: %d", score) - } - - // Have node m1 probe m4. - n := m1.nodeMap[addr4.String()] - startProbe := time.Now() - m1.probeNode(n) - probeTime := time.Now().Sub(startProbe) - - // Node should be reported suspect. - if n.State != stateSuspect { - t.Fatalf("expect node to be suspect") - } - - // Make sure we timed out approximately on time. - if probeTime > probeTimeMax { - t.Fatalf("took to long to probe, %9.6f", probeTime.Seconds()) - } - - // We should have gotten dinged for the missed nack. - time.Sleep(probeTimeMax) - if score := m1.GetHealthScore(); score != 1 { - t.Fatalf("bad: %d", score) - } -} - -func TestMemberList_ProbeNode_Awareness_OldProtocol(t *testing.T) { - addr1 := getBindAddr() - addr2 := getBindAddr() - addr3 := getBindAddr() - addr4 := getBindAddr() - ip1 := []byte(addr1) - ip2 := []byte(addr2) - ip3 := []byte(addr3) - ip4 := []byte(addr4) - - var probeTimeMax time.Duration - m1 := HostMemberlist(addr1.String(), t, func(c *Config) { - c.ProbeTimeout = 10 * time.Millisecond - c.ProbeInterval = 200 * time.Millisecond - probeTimeMax = c.ProbeInterval + 20*time.Millisecond - }) - defer m1.Shutdown() - - m2 := HostMemberlist(addr2.String(), t, nil) - defer m2.Shutdown() - - m3 := HostMemberlist(addr3.String(), t, nil) - defer m3.Shutdown() - - a1 := alive{Node: addr1.String(), Addr: ip1, Port: 7946, Incarnation: 1} - m1.aliveNode(&a1, nil, true) - a2 := alive{Node: addr2.String(), Addr: ip2, Port: 7946, Incarnation: 1} - m1.aliveNode(&a2, nil, false) - a3 := alive{Node: addr3.String(), Addr: ip3, Port: 7946, Incarnation: 1} - m1.aliveNode(&a3, nil, false) - - // Node 4 never gets started. - a4 := alive{Node: addr4.String(), Addr: ip4, Port: 7946, Incarnation: 1} - m1.aliveNode(&a4, nil, false) - - // Make sure health looks good. - if score := m1.GetHealthScore(); score != 0 { - t.Fatalf("bad: %d", score) - } - - // Have node m1 probe m4. - n := m1.nodeMap[addr4.String()] - startProbe := time.Now() - m1.probeNode(n) - probeTime := time.Now().Sub(startProbe) - - // Node should be reported suspect. - if n.State != stateSuspect { - t.Fatalf("expect node to be suspect") - } - - // Make sure we timed out approximately on time. - if probeTime > probeTimeMax { - t.Fatalf("took to long to probe, %9.6f", probeTime.Seconds()) - } - - // Confirm at least one of the peers attempted an indirect probe. - time.Sleep(probeTimeMax) - if m2.sequenceNum != 1 && m3.sequenceNum != 1 { - t.Fatalf("bad seqnos %v, %v", m2.sequenceNum, m3.sequenceNum) - } - - // Since we are using the old protocol here, we should have gotten dinged - // for a failed health check. - if score := m1.GetHealthScore(); score != 1 { - t.Fatalf("bad: %d", score) - } -} - -func TestMemberList_ProbeNode_Buddy(t *testing.T) { - addr1 := getBindAddr() - addr2 := getBindAddr() - ip1 := []byte(addr1) - ip2 := []byte(addr2) - - m1 := HostMemberlist(addr1.String(), t, func(c *Config) { - c.ProbeTimeout = time.Millisecond - c.ProbeInterval = 10 * time.Millisecond - }) - m2 := HostMemberlist(addr2.String(), t, nil) - - a1 := alive{Node: addr1.String(), Addr: ip1, Port: 7946, Incarnation: 1} - a2 := alive{Node: addr2.String(), Addr: ip2, Port: 7946, Incarnation: 1} - - m1.aliveNode(&a1, nil, true) - m1.aliveNode(&a2, nil, false) - m2.aliveNode(&a2, nil, true) - - // Force the state to suspect so we piggyback a suspect message with the ping. - // We should see this get refuted later, and the ping will succeed. - n := m1.nodeMap[addr2.String()] - n.State = stateSuspect - m1.probeNode(n) - - // Make sure a ping was sent. - if m1.sequenceNum != 1 { - t.Fatalf("bad seqno %v", m1.sequenceNum) - } - - // Check a broadcast is queued. - if num := m2.broadcasts.NumQueued(); num != 1 { - t.Fatalf("expected only one queued message: %d", num) - } - - // Should be alive msg. - if messageType(m2.broadcasts.bcQueue[0].b.Message()[0]) != aliveMsg { - t.Fatalf("expected queued alive msg") - } -} - -func TestMemberList_ProbeNode(t *testing.T) { - addr1 := getBindAddr() - addr2 := getBindAddr() - ip1 := []byte(addr1) - ip2 := []byte(addr2) - - m1 := HostMemberlist(addr1.String(), t, func(c *Config) { - c.ProbeTimeout = time.Millisecond - c.ProbeInterval = 10 * time.Millisecond - }) - _ = HostMemberlist(addr2.String(), t, nil) - - a1 := alive{Node: addr1.String(), Addr: ip1, Port: 7946, Incarnation: 1} - m1.aliveNode(&a1, nil, true) - a2 := alive{Node: addr2.String(), Addr: ip2, Port: 7946, Incarnation: 1} - m1.aliveNode(&a2, nil, false) - - n := m1.nodeMap[addr2.String()] - m1.probeNode(n) - - // Should be marked alive - if n.State != stateAlive { - t.Fatalf("Expect node to be alive") - } - - // Should increment seqno - if m1.sequenceNum != 1 { - t.Fatalf("bad seqno %v", m1.sequenceNum) - } -} - -func TestMemberList_Ping(t *testing.T) { - addr1 := getBindAddr() - addr2 := getBindAddr() - ip1 := []byte(addr1) - ip2 := []byte(addr2) - - m1 := HostMemberlist(addr1.String(), t, func(c *Config) { - c.ProbeTimeout = time.Millisecond - c.ProbeInterval = 10 * time.Second - }) - _ = HostMemberlist(addr2.String(), t, nil) - - a1 := alive{Node: addr1.String(), Addr: ip1, Port: 7946, Incarnation: 1} - m1.aliveNode(&a1, nil, true) - a2 := alive{Node: addr2.String(), Addr: ip2, Port: 7946, Incarnation: 1} - m1.aliveNode(&a2, nil, false) - - // Do a legit ping. - n := m1.nodeMap[addr2.String()] - addr, err := net.ResolveUDPAddr("udp", net.JoinHostPort(addr2.String(), "7946")) - if err != nil { - t.Fatalf("err: %v", err) - } - rtt, err := m1.Ping(n.Name, addr) - if err != nil { - t.Fatalf("err: %v", err) - } - if !(rtt > 0) { - t.Fatalf("bad: %v", rtt) - } - - // This ping has a bad node name so should timeout. - _, err = m1.Ping("bad", addr) - if _, ok := err.(NoPingResponseError); !ok || err == nil { - t.Fatalf("bad: %v", err) - } -} - -func TestMemberList_ResetNodes(t *testing.T) { - m := GetMemberlist(t) - a1 := alive{Node: "test1", Addr: []byte{127, 0, 0, 1}, Incarnation: 1} - m.aliveNode(&a1, nil, false) - a2 := alive{Node: "test2", Addr: []byte{127, 0, 0, 2}, Incarnation: 1} - m.aliveNode(&a2, nil, false) - a3 := alive{Node: "test3", Addr: []byte{127, 0, 0, 3}, Incarnation: 1} - m.aliveNode(&a3, nil, false) - d := dead{Node: "test2", Incarnation: 1} - m.deadNode(&d) - - m.config.GossipToTheDeadTime = 100 * time.Millisecond - m.resetNodes() - if len(m.nodes) != 3 { - t.Fatalf("Bad length") - } - if _, ok := m.nodeMap["test2"]; !ok { - t.Fatalf("test2 should not be unmapped") - } - - time.Sleep(200 * time.Millisecond) - m.resetNodes() - if len(m.nodes) != 2 { - t.Fatalf("Bad length") - } - if _, ok := m.nodeMap["test2"]; ok { - t.Fatalf("test2 should be unmapped") - } -} - -func TestMemberList_NextSeq(t *testing.T) { - m := &Memberlist{} - if m.nextSeqNo() != 1 { - t.Fatalf("bad sequence no") - } - if m.nextSeqNo() != 2 { - t.Fatalf("bad sequence no") - } -} - -func TestMemberList_setProbeChannels(t *testing.T) { - m := &Memberlist{ackHandlers: make(map[uint32]*ackHandler)} - - ch := make(chan ackMessage, 1) - m.setProbeChannels(0, ch, nil, 10*time.Millisecond) - - if _, ok := m.ackHandlers[0]; !ok { - t.Fatalf("missing handler") - } - time.Sleep(20 * time.Millisecond) - - if _, ok := m.ackHandlers[0]; ok { - t.Fatalf("non-reaped handler") - } -} - -func TestMemberList_setAckHandler(t *testing.T) { - m := &Memberlist{ackHandlers: make(map[uint32]*ackHandler)} - - f := func([]byte, time.Time) {} - m.setAckHandler(0, f, 10*time.Millisecond) - - if _, ok := m.ackHandlers[0]; !ok { - t.Fatalf("missing handler") - } - time.Sleep(20 * time.Millisecond) - - if _, ok := m.ackHandlers[0]; ok { - t.Fatalf("non-reaped handler") - } -} - -func TestMemberList_invokeAckHandler(t *testing.T) { - m := &Memberlist{ackHandlers: make(map[uint32]*ackHandler)} - - // Does nothing - m.invokeAckHandler(ackResp{}, time.Now()) - - var b bool - f := func(payload []byte, timestamp time.Time) { b = true } - m.setAckHandler(0, f, 10*time.Millisecond) - - // Should set b - m.invokeAckHandler(ackResp{0, nil}, time.Now()) - if !b { - t.Fatalf("b not set") - } - - if _, ok := m.ackHandlers[0]; ok { - t.Fatalf("non-reaped handler") - } -} - -func TestMemberList_invokeAckHandler_Channel_Ack(t *testing.T) { - m := &Memberlist{ackHandlers: make(map[uint32]*ackHandler)} - - ack := ackResp{0, []byte{0, 0, 0}} - - // Does nothing - m.invokeAckHandler(ack, time.Now()) - - ackCh := make(chan ackMessage, 1) - nackCh := make(chan struct{}, 1) - m.setProbeChannels(0, ackCh, nackCh, 10*time.Millisecond) - - // Should send message - m.invokeAckHandler(ack, time.Now()) - - select { - case v := <-ackCh: - if v.Complete != true { - t.Fatalf("Bad value") - } - if bytes.Compare(v.Payload, ack.Payload) != 0 { - t.Fatalf("wrong payload. expected: %v; actual: %v", ack.Payload, v.Payload) - } - - case <-nackCh: - t.Fatalf("should not get a nack") - - default: - t.Fatalf("message not sent") - } - - if _, ok := m.ackHandlers[0]; ok { - t.Fatalf("non-reaped handler") - } -} - -func TestMemberList_invokeAckHandler_Channel_Nack(t *testing.T) { - m := &Memberlist{ackHandlers: make(map[uint32]*ackHandler)} - - nack := nackResp{0} - - // Does nothing. - m.invokeNackHandler(nack) - - ackCh := make(chan ackMessage, 1) - nackCh := make(chan struct{}, 1) - m.setProbeChannels(0, ackCh, nackCh, 10*time.Millisecond) - - // Should send message. - m.invokeNackHandler(nack) - - select { - case <-ackCh: - t.Fatalf("should not get an ack") - - case <-nackCh: - // Good. - - default: - t.Fatalf("message not sent") - } - - // Getting a nack doesn't reap the handler so that we can still forward - // an ack up to the reap time, if we get one. - if _, ok := m.ackHandlers[0]; !ok { - t.Fatalf("handler should not be reaped") - } - - ack := ackResp{0, []byte{0, 0, 0}} - m.invokeAckHandler(ack, time.Now()) - - select { - case v := <-ackCh: - if v.Complete != true { - t.Fatalf("Bad value") - } - if bytes.Compare(v.Payload, ack.Payload) != 0 { - t.Fatalf("wrong payload. expected: %v; actual: %v", ack.Payload, v.Payload) - } - - case <-nackCh: - t.Fatalf("should not get a nack") - - default: - t.Fatalf("message not sent") - } - - if _, ok := m.ackHandlers[0]; ok { - t.Fatalf("non-reaped handler") - } -} - -func TestMemberList_AliveNode_NewNode(t *testing.T) { - ch := make(chan NodeEvent, 1) - m := GetMemberlist(t) - m.config.Events = &ChannelEventDelegate{ch} - - a := alive{Node: "test", Addr: []byte{127, 0, 0, 1}, Incarnation: 1} - m.aliveNode(&a, nil, false) - - if len(m.nodes) != 1 { - t.Fatalf("should add node") - } - - state, ok := m.nodeMap["test"] - if !ok { - t.Fatalf("should map node") - } - - if state.Incarnation != 1 { - t.Fatalf("bad incarnation") - } - if state.State != stateAlive { - t.Fatalf("bad state") - } - if time.Now().Sub(state.StateChange) > time.Second { - t.Fatalf("bad change delta") - } - - // Check for a join message - select { - case e := <-ch: - if e.Node.Name != "test" { - t.Fatalf("bad node name") - } - default: - t.Fatalf("no join message") - } - - // Check a broad cast is queued - if m.broadcasts.NumQueued() != 1 { - t.Fatalf("expected queued message") - } -} - -func TestMemberList_AliveNode_SuspectNode(t *testing.T) { - ch := make(chan NodeEvent, 1) - m := GetMemberlist(t) - - a := alive{Node: "test", Addr: []byte{127, 0, 0, 1}, Incarnation: 1} - m.aliveNode(&a, nil, false) - - // Listen only after first join - m.config.Events = &ChannelEventDelegate{ch} - - // Make suspect - state := m.nodeMap["test"] - state.State = stateSuspect - state.StateChange = state.StateChange.Add(-time.Hour) - - // Old incarnation number, should not change - m.aliveNode(&a, nil, false) - if state.State != stateSuspect { - t.Fatalf("update with old incarnation!") - } - - // Should reset to alive now - a.Incarnation = 2 - m.aliveNode(&a, nil, false) - if state.State != stateAlive { - t.Fatalf("no update with new incarnation!") - } - - if time.Now().Sub(state.StateChange) > time.Second { - t.Fatalf("bad change delta") - } - - // Check for a no join message - select { - case <-ch: - t.Fatalf("got bad join message") - default: - } - - // Check a broad cast is queued - if m.broadcasts.NumQueued() != 1 { - t.Fatalf("expected queued message") - } -} - -func TestMemberList_AliveNode_Idempotent(t *testing.T) { - ch := make(chan NodeEvent, 1) - m := GetMemberlist(t) - - a := alive{Node: "test", Addr: []byte{127, 0, 0, 1}, Incarnation: 1} - m.aliveNode(&a, nil, false) - - // Listen only after first join - m.config.Events = &ChannelEventDelegate{ch} - - // Make suspect - state := m.nodeMap["test"] - stateTime := state.StateChange - - // Should reset to alive now - a.Incarnation = 2 - m.aliveNode(&a, nil, false) - if state.State != stateAlive { - t.Fatalf("non idempotent") - } - - if stateTime != state.StateChange { - t.Fatalf("should not change state") - } - - // Check for a no join message - select { - case <-ch: - t.Fatalf("got bad join message") - default: - } - - // Check a broad cast is queued - if m.broadcasts.NumQueued() != 1 { - t.Fatalf("expected only one queued message") - } -} - -// Serf Bug: GH-58, Meta data does not update -func TestMemberList_AliveNode_ChangeMeta(t *testing.T) { - ch := make(chan NodeEvent, 1) - m := GetMemberlist(t) - - a := alive{ - Node: "test", - Addr: []byte{127, 0, 0, 1}, - Meta: []byte("val1"), - Incarnation: 1} - m.aliveNode(&a, nil, false) - - // Listen only after first join - m.config.Events = &ChannelEventDelegate{ch} - - // Make suspect - state := m.nodeMap["test"] - - // Should reset to alive now - a.Incarnation = 2 - a.Meta = []byte("val2") - m.aliveNode(&a, nil, false) - - // Check updates - if bytes.Compare(state.Meta, a.Meta) != 0 { - t.Fatalf("meta did not update") - } - - // Check for a NotifyUpdate - select { - case e := <-ch: - if e.Event != NodeUpdate { - t.Fatalf("bad event: %v", e) - } - if e.Node != &state.Node { - t.Fatalf("bad event: %v", e) - } - if bytes.Compare(e.Node.Meta, a.Meta) != 0 { - t.Fatalf("meta did not update") - } - default: - t.Fatalf("missing event!") - } - -} - -func TestMemberList_AliveNode_Refute(t *testing.T) { - m := GetMemberlist(t) - a := alive{Node: m.config.Name, Addr: []byte{127, 0, 0, 1}, Incarnation: 1} - m.aliveNode(&a, nil, true) - - // Clear queue - m.broadcasts.Reset() - - // Conflicting alive - s := alive{ - Node: m.config.Name, - Addr: []byte{127, 0, 0, 1}, - Incarnation: 2, - Meta: []byte("foo"), - } - m.aliveNode(&s, nil, false) - - state := m.nodeMap[m.config.Name] - if state.State != stateAlive { - t.Fatalf("should still be alive") - } - if state.Meta != nil { - t.Fatalf("meta should still be nil") - } - - // Check a broad cast is queued - if num := m.broadcasts.NumQueued(); num != 1 { - t.Fatalf("expected only one queued message: %d", - num) - } - - // Should be alive mesg - if messageType(m.broadcasts.bcQueue[0].b.Message()[0]) != aliveMsg { - t.Fatalf("expected queued alive msg") - } -} - -func TestMemberList_SuspectNode_NoNode(t *testing.T) { - m := GetMemberlist(t) - s := suspect{Node: "test", Incarnation: 1} - m.suspectNode(&s) - if len(m.nodes) != 0 { - t.Fatalf("don't expect nodes") - } -} - -func TestMemberList_SuspectNode(t *testing.T) { - m := GetMemberlist(t) - m.config.ProbeInterval = time.Millisecond - m.config.SuspicionMult = 1 - a := alive{Node: "test", Addr: []byte{127, 0, 0, 1}, Incarnation: 1} - m.aliveNode(&a, nil, false) - - state := m.nodeMap["test"] - state.StateChange = state.StateChange.Add(-time.Hour) - - s := suspect{Node: "test", Incarnation: 1} - m.suspectNode(&s) - - if state.State != stateSuspect { - t.Fatalf("Bad state") - } - - change := state.StateChange - if time.Now().Sub(change) > time.Second { - t.Fatalf("bad change delta") - } - - // Check a broad cast is queued - if m.broadcasts.NumQueued() != 1 { - t.Fatalf("expected only one queued message") - } - - // Check its a suspect message - if messageType(m.broadcasts.bcQueue[0].b.Message()[0]) != suspectMsg { - t.Fatalf("expected queued suspect msg") - } - - // Wait for the timeout - time.Sleep(10 * time.Millisecond) - - if state.State != stateDead { - t.Fatalf("Bad state") - } - - if time.Now().Sub(state.StateChange) > time.Second { - t.Fatalf("bad change delta") - } - if !state.StateChange.After(change) { - t.Fatalf("should increment time") - } - - // Check a broad cast is queued - if m.broadcasts.NumQueued() != 1 { - t.Fatalf("expected only one queued message") - } - - // Check its a suspect message - if messageType(m.broadcasts.bcQueue[0].b.Message()[0]) != deadMsg { - t.Fatalf("expected queued dead msg") - } -} - -func TestMemberList_SuspectNode_DoubleSuspect(t *testing.T) { - m := GetMemberlist(t) - a := alive{Node: "test", Addr: []byte{127, 0, 0, 1}, Incarnation: 1} - m.aliveNode(&a, nil, false) - - state := m.nodeMap["test"] - state.StateChange = state.StateChange.Add(-time.Hour) - - s := suspect{Node: "test", Incarnation: 1} - m.suspectNode(&s) - - if state.State != stateSuspect { - t.Fatalf("Bad state") - } - - change := state.StateChange - if time.Now().Sub(change) > time.Second { - t.Fatalf("bad change delta") - } - - // clear the broadcast queue - m.broadcasts.Reset() - - // Suspect again - m.suspectNode(&s) - - if state.StateChange != change { - t.Fatalf("unexpected state change") - } - - // Check a broad cast is queued - if m.broadcasts.NumQueued() != 0 { - t.Fatalf("expected only one queued message") - } - -} - -func TestMemberList_SuspectNode_OldSuspect(t *testing.T) { - m := GetMemberlist(t) - a := alive{Node: "test", Addr: []byte{127, 0, 0, 1}, Incarnation: 10} - m.aliveNode(&a, nil, false) - - state := m.nodeMap["test"] - state.StateChange = state.StateChange.Add(-time.Hour) - - // Clear queue - m.broadcasts.Reset() - - s := suspect{Node: "test", Incarnation: 1} - m.suspectNode(&s) - - if state.State != stateAlive { - t.Fatalf("Bad state") - } - - // Check a broad cast is queued - if m.broadcasts.NumQueued() != 0 { - t.Fatalf("expected only one queued message") - } -} - -func TestMemberList_SuspectNode_Refute(t *testing.T) { - m := GetMemberlist(t) - a := alive{Node: m.config.Name, Addr: []byte{127, 0, 0, 1}, Incarnation: 1} - m.aliveNode(&a, nil, true) - - // Clear queue - m.broadcasts.Reset() - - // Make sure health is in a good state - if score := m.GetHealthScore(); score != 0 { - t.Fatalf("bad: %d", score) - } - - s := suspect{Node: m.config.Name, Incarnation: 1} - m.suspectNode(&s) - - state := m.nodeMap[m.config.Name] - if state.State != stateAlive { - t.Fatalf("should still be alive") - } - - // Check a broad cast is queued - if m.broadcasts.NumQueued() != 1 { - t.Fatalf("expected only one queued message") - } - - // Should be alive mesg - if messageType(m.broadcasts.bcQueue[0].b.Message()[0]) != aliveMsg { - t.Fatalf("expected queued alive msg") - } - - // Health should have been dinged - if score := m.GetHealthScore(); score != 1 { - t.Fatalf("bad: %d", score) - } -} - -func TestMemberList_DeadNode_NoNode(t *testing.T) { - m := GetMemberlist(t) - d := dead{Node: "test", Incarnation: 1} - m.deadNode(&d) - if len(m.nodes) != 0 { - t.Fatalf("don't expect nodes") - } -} - -func TestMemberList_DeadNode(t *testing.T) { - ch := make(chan NodeEvent, 1) - m := GetMemberlist(t) - m.config.Events = &ChannelEventDelegate{ch} - a := alive{Node: "test", Addr: []byte{127, 0, 0, 1}, Incarnation: 1} - m.aliveNode(&a, nil, false) - - // Read the join event - <-ch - - state := m.nodeMap["test"] - state.StateChange = state.StateChange.Add(-time.Hour) - - d := dead{Node: "test", Incarnation: 1} - m.deadNode(&d) - - if state.State != stateDead { - t.Fatalf("Bad state") - } - - change := state.StateChange - if time.Now().Sub(change) > time.Second { - t.Fatalf("bad change delta") - } - - select { - case leave := <-ch: - if leave.Event != NodeLeave || leave.Node.Name != "test" { - t.Fatalf("bad node name") - } - default: - t.Fatalf("no leave message") - } - - // Check a broad cast is queued - if m.broadcasts.NumQueued() != 1 { - t.Fatalf("expected only one queued message") - } - - // Check its a suspect message - if messageType(m.broadcasts.bcQueue[0].b.Message()[0]) != deadMsg { - t.Fatalf("expected queued dead msg") - } -} - -func TestMemberList_DeadNode_Double(t *testing.T) { - ch := make(chan NodeEvent, 1) - m := GetMemberlist(t) - a := alive{Node: "test", Addr: []byte{127, 0, 0, 1}, Incarnation: 1} - m.aliveNode(&a, nil, false) - - state := m.nodeMap["test"] - state.StateChange = state.StateChange.Add(-time.Hour) - - d := dead{Node: "test", Incarnation: 1} - m.deadNode(&d) - - // Clear queue - m.broadcasts.Reset() - - // Notify after the first dead - m.config.Events = &ChannelEventDelegate{ch} - - // Should do nothing - d.Incarnation = 2 - m.deadNode(&d) - - select { - case <-ch: - t.Fatalf("should not get leave") - default: - } - - // Check a broad cast is queued - if m.broadcasts.NumQueued() != 0 { - t.Fatalf("expected only one queued message") - } -} - -func TestMemberList_DeadNode_OldDead(t *testing.T) { - m := GetMemberlist(t) - a := alive{Node: "test", Addr: []byte{127, 0, 0, 1}, Incarnation: 10} - m.aliveNode(&a, nil, false) - - state := m.nodeMap["test"] - state.StateChange = state.StateChange.Add(-time.Hour) - - d := dead{Node: "test", Incarnation: 1} - m.deadNode(&d) - - if state.State != stateAlive { - t.Fatalf("Bad state") - } -} - -func TestMemberList_DeadNode_AliveReplay(t *testing.T) { - m := GetMemberlist(t) - a := alive{Node: "test", Addr: []byte{127, 0, 0, 1}, Incarnation: 10} - m.aliveNode(&a, nil, false) - - d := dead{Node: "test", Incarnation: 10} - m.deadNode(&d) - - // Replay alive at same incarnation - m.aliveNode(&a, nil, false) - - // Should remain dead - state, ok := m.nodeMap["test"] - if ok && state.State != stateDead { - t.Fatalf("Bad state") - } -} - -func TestMemberList_DeadNode_Refute(t *testing.T) { - m := GetMemberlist(t) - a := alive{Node: m.config.Name, Addr: []byte{127, 0, 0, 1}, Incarnation: 1} - m.aliveNode(&a, nil, true) - - // Clear queue - m.broadcasts.Reset() - - // Make sure health is in a good state - if score := m.GetHealthScore(); score != 0 { - t.Fatalf("bad: %d", score) - } - - d := dead{Node: m.config.Name, Incarnation: 1} - m.deadNode(&d) - - state := m.nodeMap[m.config.Name] - if state.State != stateAlive { - t.Fatalf("should still be alive") - } - - // Check a broad cast is queued - if m.broadcasts.NumQueued() != 1 { - t.Fatalf("expected only one queued message") - } - - // Should be alive mesg - if messageType(m.broadcasts.bcQueue[0].b.Message()[0]) != aliveMsg { - t.Fatalf("expected queued alive msg") - } - - // We should have been dinged - if score := m.GetHealthScore(); score != 1 { - t.Fatalf("bad: %d", score) - } -} - -func TestMemberList_MergeState(t *testing.T) { - m := GetMemberlist(t) - a1 := alive{Node: "test1", Addr: []byte{127, 0, 0, 1}, Incarnation: 1} - m.aliveNode(&a1, nil, false) - a2 := alive{Node: "test2", Addr: []byte{127, 0, 0, 2}, Incarnation: 1} - m.aliveNode(&a2, nil, false) - a3 := alive{Node: "test3", Addr: []byte{127, 0, 0, 3}, Incarnation: 1} - m.aliveNode(&a3, nil, false) - - s := suspect{Node: "test1", Incarnation: 1} - m.suspectNode(&s) - - remote := []pushNodeState{ - pushNodeState{ - Name: "test1", - Addr: []byte{127, 0, 0, 1}, - Incarnation: 2, - State: stateAlive, - }, - pushNodeState{ - Name: "test2", - Addr: []byte{127, 0, 0, 2}, - Incarnation: 1, - State: stateSuspect, - }, - pushNodeState{ - Name: "test3", - Addr: []byte{127, 0, 0, 3}, - Incarnation: 1, - State: stateDead, - }, - pushNodeState{ - Name: "test4", - Addr: []byte{127, 0, 0, 4}, - Incarnation: 2, - State: stateAlive, - }, - } - - // Listen for changes - eventCh := make(chan NodeEvent, 1) - m.config.Events = &ChannelEventDelegate{eventCh} - - // Merge remote state - m.mergeState(remote) - - // Check the states - state := m.nodeMap["test1"] - if state.State != stateAlive || state.Incarnation != 2 { - t.Fatalf("Bad state %v", state) - } - - state = m.nodeMap["test2"] - if state.State != stateSuspect || state.Incarnation != 1 { - t.Fatalf("Bad state %v", state) - } - - state = m.nodeMap["test3"] - if state.State != stateSuspect { - t.Fatalf("Bad state %v", state) - } - - state = m.nodeMap["test4"] - if state.State != stateAlive || state.Incarnation != 2 { - t.Fatalf("Bad state %v", state) - } - - // Check the channels - select { - case e := <-eventCh: - if e.Event != NodeJoin || e.Node.Name != "test4" { - t.Fatalf("bad node %v", e) - } - default: - t.Fatalf("Expect join") - } - - select { - case e := <-eventCh: - t.Fatalf("Unexpect event: %v", e) - default: - } -} - -func TestMemberlist_Gossip(t *testing.T) { - ch := make(chan NodeEvent, 3) - - addr1 := getBindAddr() - addr2 := getBindAddr() - ip1 := []byte(addr1) - ip2 := []byte(addr2) - - m1 := HostMemberlist(addr1.String(), t, func(c *Config) { - c.GossipInterval = time.Millisecond - }) - m2 := HostMemberlist(addr2.String(), t, func(c *Config) { - c.Events = &ChannelEventDelegate{ch} - c.GossipInterval = time.Millisecond - }) - - defer m1.Shutdown() - defer m2.Shutdown() - - a1 := alive{Node: addr1.String(), Addr: ip1, Port: 7946, Incarnation: 1} - m1.aliveNode(&a1, nil, true) - a2 := alive{Node: addr2.String(), Addr: ip2, Port: 7946, Incarnation: 1} - m1.aliveNode(&a2, nil, false) - a3 := alive{Node: "172.0.0.1", Addr: []byte{172, 0, 0, 1}, Incarnation: 1} - m1.aliveNode(&a3, nil, false) - - // Gossip should send all this to m2 - m1.gossip() - - for i := 0; i < 3; i++ { - select { - case <-ch: - case <-time.After(50 * time.Millisecond): - t.Fatalf("timeout") - } - } -} - -func TestMemberlist_GossipToDead(t *testing.T) { - ch := make(chan NodeEvent, 2) - - addr1 := getBindAddr() - addr2 := getBindAddr() - ip1 := []byte(addr1) - ip2 := []byte(addr2) - - m1 := HostMemberlist(addr1.String(), t, func(c *Config) { - c.GossipInterval = time.Millisecond - c.GossipToTheDeadTime = 100 * time.Millisecond - }) - m2 := HostMemberlist(addr2.String(), t, func(c *Config) { - c.Events = &ChannelEventDelegate{ch} - }) - - defer m1.Shutdown() - defer m2.Shutdown() - - a1 := alive{Node: addr1.String(), Addr: ip1, Port: 7946, Incarnation: 1} - m1.aliveNode(&a1, nil, true) - a2 := alive{Node: addr2.String(), Addr: ip2, Port: 7946, Incarnation: 1} - m1.aliveNode(&a2, nil, false) - - // Shouldn't send anything to m2 here, node has been dead for 2x the GossipToTheDeadTime - m1.nodeMap[addr2.String()].State = stateDead - m1.nodeMap[addr2.String()].StateChange = time.Now().Add(-200 * time.Millisecond) - m1.gossip() - - select { - case <-ch: - t.Fatalf("shouldn't get gossip") - case <-time.After(50 * time.Millisecond): - } - - // Should gossip to m2 because its state has changed within GossipToTheDeadTime - m1.nodeMap[addr2.String()].StateChange = time.Now().Add(-20 * time.Millisecond) - m1.gossip() - - for i := 0; i < 2; i++ { - select { - case <-ch: - case <-time.After(50 * time.Millisecond): - t.Fatalf("timeout") - } - } -} - -func TestMemberlist_PushPull(t *testing.T) { - addr1 := getBindAddr() - addr2 := getBindAddr() - ip1 := []byte(addr1) - ip2 := []byte(addr2) - - ch := make(chan NodeEvent, 3) - - m1 := HostMemberlist(addr1.String(), t, func(c *Config) { - c.GossipInterval = 10 * time.Second - c.PushPullInterval = time.Millisecond - }) - m2 := HostMemberlist(addr2.String(), t, func(c *Config) { - c.GossipInterval = 10 * time.Second - c.Events = &ChannelEventDelegate{ch} - }) - - defer m1.Shutdown() - defer m2.Shutdown() - - a1 := alive{Node: addr1.String(), Addr: ip1, Port: 7946, Incarnation: 1} - m1.aliveNode(&a1, nil, true) - a2 := alive{Node: addr2.String(), Addr: ip2, Port: 7946, Incarnation: 1} - m1.aliveNode(&a2, nil, false) - - // Gossip should send all this to m2 - m1.pushPull() - - for i := 0; i < 2; i++ { - select { - case <-ch: - case <-time.After(10 * time.Millisecond): - t.Fatalf("timeout") - } - } -} - -func TestVerifyProtocol(t *testing.T) { - cases := []struct { - Anodes [][3]uint8 - Bnodes [][3]uint8 - expected bool - }{ - // Both running identical everything - { - Anodes: [][3]uint8{ - {0, 0, 0}, - }, - Bnodes: [][3]uint8{ - {0, 0, 0}, - }, - expected: true, - }, - - // One can understand newer, but speaking same protocol - { - Anodes: [][3]uint8{ - {0, 0, 0}, - }, - Bnodes: [][3]uint8{ - {0, 1, 0}, - }, - expected: true, - }, - - // One is speaking outside the range - { - Anodes: [][3]uint8{ - {0, 0, 0}, - }, - Bnodes: [][3]uint8{ - {1, 1, 1}, - }, - expected: false, - }, - - // Transitively outside the range - { - Anodes: [][3]uint8{ - {0, 1, 0}, - {0, 2, 1}, - }, - Bnodes: [][3]uint8{ - {1, 3, 1}, - }, - expected: false, - }, - - // Multi-node - { - Anodes: [][3]uint8{ - {0, 3, 2}, - {0, 2, 0}, - }, - Bnodes: [][3]uint8{ - {0, 2, 1}, - {0, 5, 0}, - }, - expected: true, - }, - } - - for _, tc := range cases { - aCore := make([][6]uint8, len(tc.Anodes)) - aApp := make([][6]uint8, len(tc.Anodes)) - for i, n := range tc.Anodes { - aCore[i] = [6]uint8{n[0], n[1], n[2], 0, 0, 0} - aApp[i] = [6]uint8{0, 0, 0, n[0], n[1], n[2]} - } - - bCore := make([][6]uint8, len(tc.Bnodes)) - bApp := make([][6]uint8, len(tc.Bnodes)) - for i, n := range tc.Bnodes { - bCore[i] = [6]uint8{n[0], n[1], n[2], 0, 0, 0} - bApp[i] = [6]uint8{0, 0, 0, n[0], n[1], n[2]} - } - - // Test core protocol verification - testVerifyProtocolSingle(t, aCore, bCore, tc.expected) - testVerifyProtocolSingle(t, bCore, aCore, tc.expected) - - // Test app protocol verification - testVerifyProtocolSingle(t, aApp, bApp, tc.expected) - testVerifyProtocolSingle(t, bApp, aApp, tc.expected) - } -} - -func testVerifyProtocolSingle(t *testing.T, A [][6]uint8, B [][6]uint8, expect bool) { - m := GetMemberlist(t) - defer m.Shutdown() - - m.nodes = make([]*nodeState, len(A)) - for i, n := range A { - m.nodes[i] = &nodeState{ - Node: Node{ - PMin: n[0], - PMax: n[1], - PCur: n[2], - DMin: n[3], - DMax: n[4], - DCur: n[5], - }, - } - } - - remote := make([]pushNodeState, len(B)) - for i, n := range B { - remote[i] = pushNodeState{ - Name: fmt.Sprintf("node %d", i), - Vsn: []uint8{n[0], n[1], n[2], n[3], n[4], n[5]}, - } - } - - err := m.verifyProtocol(remote) - if (err == nil) != expect { - t.Fatalf("bad:\nA: %v\nB: %v\nErr: %s", A, B, err) - } -} diff --git a/vendor/github.com/hashicorp/memberlist/suspicion_test.go b/vendor/github.com/hashicorp/memberlist/suspicion_test.go deleted file mode 100644 index 1b5ca8a5a..000000000 --- a/vendor/github.com/hashicorp/memberlist/suspicion_test.go +++ /dev/null @@ -1,198 +0,0 @@ -package memberlist - -import ( - "testing" - "time" -) - -func TestSuspicion_remainingSuspicionTime(t *testing.T) { - cases := []struct { - n int32 - k int32 - elapsed time.Duration - min time.Duration - max time.Duration - expected time.Duration - }{ - {0, 3, 0, 2 * time.Second, 30 * time.Second, 30 * time.Second}, - {1, 3, 2 * time.Second, 2 * time.Second, 30 * time.Second, 14 * time.Second}, - {2, 3, 3 * time.Second, 2 * time.Second, 30 * time.Second, 4810 * time.Millisecond}, - {3, 3, 4 * time.Second, 2 * time.Second, 30 * time.Second, -2 * time.Second}, - {4, 3, 5 * time.Second, 2 * time.Second, 30 * time.Second, -3 * time.Second}, - {5, 3, 10 * time.Second, 2 * time.Second, 30 * time.Second, -8 * time.Second}, - } - for i, c := range cases { - remaining := remainingSuspicionTime(c.n, c.k, c.elapsed, c.min, c.max) - if remaining != c.expected { - t.Errorf("case %d: remaining %9.6f != expected %9.6f", i, remaining.Seconds(), c.expected.Seconds()) - } - } -} - -func TestSuspicion_Timer(t *testing.T) { - const k = 3 - const min = 500 * time.Millisecond - const max = 2 * time.Second - - type pair struct { - from string - newInfo bool - } - cases := []struct { - numConfirmations int - from string - confirmations []pair - expected time.Duration - }{ - { - 0, - "me", - []pair{}, - max, - }, - { - 1, - "me", - []pair{ - pair{"me", false}, - pair{"foo", true}, - }, - 1250 * time.Millisecond, - }, - { - 1, - "me", - []pair{ - pair{"me", false}, - pair{"foo", true}, - pair{"foo", false}, - pair{"foo", false}, - }, - 1250 * time.Millisecond, - }, - { - 2, - "me", - []pair{ - pair{"me", false}, - pair{"foo", true}, - pair{"bar", true}, - }, - 810 * time.Millisecond, - }, - { - 3, - "me", - []pair{ - pair{"me", false}, - pair{"foo", true}, - pair{"bar", true}, - pair{"baz", true}, - }, - min, - }, - { - 3, - "me", - []pair{ - pair{"me", false}, - pair{"foo", true}, - pair{"bar", true}, - pair{"baz", true}, - pair{"zoo", false}, - }, - min, - }, - } - for i, c := range cases { - ch := make(chan time.Duration, 1) - start := time.Now() - f := func(numConfirmations int) { - if numConfirmations != c.numConfirmations { - t.Errorf("case %d: bad %d != %d", i, numConfirmations, c.numConfirmations) - } - - ch <- time.Now().Sub(start) - } - - // Create the timer and add the requested confirmations. Wait - // the fudge amount to help make sure we calculate the timeout - // overall, and don't accumulate extra time. - s := newSuspicion(c.from, k, min, max, f) - fudge := 25 * time.Millisecond - for _, p := range c.confirmations { - time.Sleep(fudge) - if s.Confirm(p.from) != p.newInfo { - t.Fatalf("case %d: newInfo mismatch for %s", i, p.from) - } - } - - // Wait until right before the timeout and make sure the - // timer hasn't fired. - already := time.Duration(len(c.confirmations)) * fudge - time.Sleep(c.expected - already - fudge) - select { - case d := <-ch: - t.Fatalf("case %d: should not have fired (%9.6f)", i, d.Seconds()) - default: - } - - // Wait through the timeout and a little after and make sure it - // fires. - time.Sleep(2 * fudge) - select { - case <-ch: - default: - t.Fatalf("case %d: should have fired", i) - } - - // Confirm after to make sure it handles a negative remaining - // time correctly and doesn't fire again. - s.Confirm("late") - time.Sleep(c.expected + 2*fudge) - select { - case d := <-ch: - t.Fatalf("case %d: should not have fired (%9.6f)", i, d.Seconds()) - default: - } - } -} - -func TestSuspicion_Timer_ZeroK(t *testing.T) { - ch := make(chan struct{}, 1) - f := func(int) { - ch <- struct{}{} - } - - // This should select the min time since there are no expected - // confirmations to accelerate the timer. - s := newSuspicion("me", 0, 25*time.Millisecond, 30*time.Second, f) - if s.Confirm("foo") { - t.Fatalf("should not provide new information") - } - - select { - case <-ch: - case <-time.After(50 * time.Millisecond): - t.Fatalf("should have fired") - } -} - -func TestSuspicion_Timer_Immediate(t *testing.T) { - ch := make(chan struct{}, 1) - f := func(int) { - ch <- struct{}{} - } - - // This should underflow the timeout and fire immediately. - s := newSuspicion("me", 1, 100*time.Millisecond, 30*time.Second, f) - time.Sleep(200 * time.Millisecond) - s.Confirm("foo") - - // Wait a little while since the function gets called in a goroutine. - select { - case <-ch: - case <-time.After(25 * time.Millisecond): - t.Fatalf("should have fired") - } -} diff --git a/vendor/github.com/hashicorp/memberlist/test/setup_subnet.sh b/vendor/github.com/hashicorp/memberlist/test/setup_subnet.sh deleted file mode 100755 index 6651c8ce4..000000000 --- a/vendor/github.com/hashicorp/memberlist/test/setup_subnet.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash -# -# This script makes sure that 127.0.0.x is routable. On Darwin, there -# is a bug that it isn't routable and this causes errors. -# - -# Check if loopback is setup -ping -c 1 -W 10 127.0.0.2 > /dev/null 2>&1 -if [ $? -eq 0 ] -then - exit -fi - -# If we're not on OS X, then error -case $OSTYPE in - darwin*) - ;; - *) - echo "Can't setup interfaces on non-Mac. Error!" - exit 1 - ;; -esac - -# Setup loopback -for ((i=2;i<256;i++)) -do - sudo ifconfig lo0 alias 127.0.0.$i up -done diff --git a/vendor/github.com/hashicorp/memberlist/transport_test.go b/vendor/github.com/hashicorp/memberlist/transport_test.go deleted file mode 100644 index b5249eb5f..000000000 --- a/vendor/github.com/hashicorp/memberlist/transport_test.go +++ /dev/null @@ -1,124 +0,0 @@ -package memberlist - -import ( - "bytes" - "testing" - "time" -) - -func TestTransport_Join(t *testing.T) { - net := &MockNetwork{} - - t1 := net.NewTransport() - - c1 := DefaultLANConfig() - c1.Name = "node1" - c1.Transport = t1 - m1, err := Create(c1) - if err != nil { - t.Fatalf("err: %v", err) - } - m1.setAlive() - m1.schedule() - defer m1.Shutdown() - - c2 := DefaultLANConfig() - c2.Name = "node2" - c2.Transport = net.NewTransport() - m2, err := Create(c2) - if err != nil { - t.Fatalf("err: %v", err) - } - m2.setAlive() - m2.schedule() - defer m2.Shutdown() - - num, err := m2.Join([]string{t1.addr.String()}) - if num != 1 { - t.Fatalf("bad: %d", num) - } - if err != nil { - t.Fatalf("err: %v", err) - } - - if len(m2.Members()) != 2 { - t.Fatalf("bad: %v", m2.Members()) - } - if m2.estNumNodes() != 2 { - t.Fatalf("bad: %v", m2.Members()) - } - -} - -func TestTransport_Send(t *testing.T) { - net := &MockNetwork{} - - t1 := net.NewTransport() - d1 := &MockDelegate{} - - c1 := DefaultLANConfig() - c1.Name = "node1" - c1.Transport = t1 - c1.Delegate = d1 - m1, err := Create(c1) - if err != nil { - t.Fatalf("err: %v", err) - } - m1.setAlive() - m1.schedule() - defer m1.Shutdown() - - c2 := DefaultLANConfig() - c2.Name = "node2" - c2.Transport = net.NewTransport() - m2, err := Create(c2) - if err != nil { - t.Fatalf("err: %v", err) - } - m2.setAlive() - m2.schedule() - defer m2.Shutdown() - - num, err := m2.Join([]string{t1.addr.String()}) - if num != 1 { - t.Fatalf("bad: %d", num) - } - if err != nil { - t.Fatalf("err: %v", err) - } - - if err := m2.SendTo(t1.addr, []byte("SendTo")); err != nil { - t.Fatalf("err: %v", err) - } - - var n1 *Node - for _, n := range m2.Members() { - if n.Name == c1.Name { - n1 = n - break - } - } - if n1 == nil { - t.Fatalf("bad") - } - - if err := m2.SendToUDP(n1, []byte("SendToUDP")); err != nil { - t.Fatalf("err: %v", err) - } - if err := m2.SendToTCP(n1, []byte("SendToTCP")); err != nil { - t.Fatalf("err: %v", err) - } - if err := m2.SendBestEffort(n1, []byte("SendBestEffort")); err != nil { - t.Fatalf("err: %v", err) - } - if err := m2.SendReliable(n1, []byte("SendReliable")); err != nil { - t.Fatalf("err: %v", err) - } - time.Sleep(100 * time.Millisecond) - - received := bytes.Join(d1.msgs, []byte("|")) - expected := []byte("SendTo|SendToUDP|SendToTCP|SendBestEffort|SendReliable") - if !bytes.Equal(received, expected) { - t.Fatalf("bad: %s", received) - } -} diff --git a/vendor/github.com/hashicorp/memberlist/util_test.go b/vendor/github.com/hashicorp/memberlist/util_test.go deleted file mode 100644 index b7f2b4199..000000000 --- a/vendor/github.com/hashicorp/memberlist/util_test.go +++ /dev/null @@ -1,358 +0,0 @@ -package memberlist - -import ( - "fmt" - "reflect" - "testing" - "time" -) - -func TestUtil_PortFunctions(t *testing.T) { - tests := []struct { - addr string - hasPort bool - ensurePort string - }{ - {"1.2.3.4", false, "1.2.3.4:8301"}, - {"1.2.3.4:1234", true, "1.2.3.4:1234"}, - {"2600:1f14:e22:1501:f9a:2e0c:a167:67e8", false, "[2600:1f14:e22:1501:f9a:2e0c:a167:67e8]:8301"}, - {"[2600:1f14:e22:1501:f9a:2e0c:a167:67e8]", false, "[2600:1f14:e22:1501:f9a:2e0c:a167:67e8]:8301"}, - {"[2600:1f14:e22:1501:f9a:2e0c:a167:67e8]:1234", true, "[2600:1f14:e22:1501:f9a:2e0c:a167:67e8]:1234"}, - {"localhost", false, "localhost:8301"}, - {"localhost:1234", true, "localhost:1234"}, - {"hashicorp.com", false, "hashicorp.com:8301"}, - {"hashicorp.com:1234", true, "hashicorp.com:1234"}, - } - for _, tt := range tests { - t.Run(tt.addr, func(t *testing.T) { - if got, want := hasPort(tt.addr), tt.hasPort; got != want { - t.Fatalf("got %v want %v", got, want) - } - if got, want := ensurePort(tt.addr, 8301), tt.ensurePort; got != want { - t.Fatalf("got %v want %v", got, want) - } - }) - } -} - -func TestEncodeDecode(t *testing.T) { - msg := &ping{SeqNo: 100} - buf, err := encode(pingMsg, msg) - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - var out ping - if err := decode(buf.Bytes()[1:], &out); err != nil { - t.Fatalf("unexpected err: %s", err) - } - if msg.SeqNo != out.SeqNo { - t.Fatalf("bad sequence no") - } -} - -func TestRandomOffset(t *testing.T) { - vals := make(map[int]struct{}) - for i := 0; i < 100; i++ { - offset := randomOffset(2 << 30) - if _, ok := vals[offset]; ok { - t.Fatalf("got collision") - } - vals[offset] = struct{}{} - } -} - -func TestRandomOffset_Zero(t *testing.T) { - offset := randomOffset(0) - if offset != 0 { - t.Fatalf("bad offset") - } -} - -func TestSuspicionTimeout(t *testing.T) { - timeouts := map[int]time.Duration{ - 5: 1000 * time.Millisecond, - 10: 1000 * time.Millisecond, - 50: 1698 * time.Millisecond, - 100: 2000 * time.Millisecond, - 500: 2698 * time.Millisecond, - 1000: 3000 * time.Millisecond, - } - for n, expected := range timeouts { - timeout := suspicionTimeout(3, n, time.Second) / 3 - if timeout != expected { - t.Fatalf("bad: %v, %v", expected, timeout) - } - } -} - -func TestRetransmitLimit(t *testing.T) { - lim := retransmitLimit(3, 0) - if lim != 0 { - t.Fatalf("bad val %v", lim) - } - lim = retransmitLimit(3, 1) - if lim != 3 { - t.Fatalf("bad val %v", lim) - } - lim = retransmitLimit(3, 99) - if lim != 6 { - t.Fatalf("bad val %v", lim) - } -} - -func TestShuffleNodes(t *testing.T) { - orig := []*nodeState{ - &nodeState{ - State: stateDead, - }, - &nodeState{ - State: stateAlive, - }, - &nodeState{ - State: stateAlive, - }, - &nodeState{ - State: stateDead, - }, - &nodeState{ - State: stateAlive, - }, - &nodeState{ - State: stateAlive, - }, - &nodeState{ - State: stateDead, - }, - &nodeState{ - State: stateAlive, - }, - } - nodes := make([]*nodeState, len(orig)) - copy(nodes[:], orig[:]) - - if !reflect.DeepEqual(nodes, orig) { - t.Fatalf("should match") - } - - shuffleNodes(nodes) - - if reflect.DeepEqual(nodes, orig) { - t.Fatalf("should not match") - } -} - -func TestPushPullScale(t *testing.T) { - sec := time.Second - for i := 0; i <= 32; i++ { - if s := pushPullScale(sec, i); s != sec { - t.Fatalf("Bad time scale: %v", s) - } - } - for i := 33; i <= 64; i++ { - if s := pushPullScale(sec, i); s != 2*sec { - t.Fatalf("Bad time scale: %v", s) - } - } - for i := 65; i <= 128; i++ { - if s := pushPullScale(sec, i); s != 3*sec { - t.Fatalf("Bad time scale: %v", s) - } - } -} - -func TestMoveDeadNodes(t *testing.T) { - nodes := []*nodeState{ - &nodeState{ - State: stateDead, - StateChange: time.Now().Add(-20 * time.Second), - }, - &nodeState{ - State: stateAlive, - StateChange: time.Now().Add(-20 * time.Second), - }, - // This dead node should not be moved, as its state changed - // less than the specified GossipToTheDead time ago - &nodeState{ - State: stateDead, - StateChange: time.Now().Add(-10 * time.Second), - }, - &nodeState{ - State: stateAlive, - StateChange: time.Now().Add(-20 * time.Second), - }, - &nodeState{ - State: stateDead, - StateChange: time.Now().Add(-20 * time.Second), - }, - &nodeState{ - State: stateAlive, - StateChange: time.Now().Add(-20 * time.Second), - }, - } - - idx := moveDeadNodes(nodes, (15 * time.Second)) - if idx != 4 { - t.Fatalf("bad index") - } - for i := 0; i < idx; i++ { - switch i { - case 2: - // Recently dead node remains at index 2, - // since nodes are swapped out to move to end. - if nodes[i].State != stateDead { - t.Fatalf("Bad state %d", i) - } - default: - if nodes[i].State != stateAlive { - t.Fatalf("Bad state %d", i) - } - } - } - for i := idx; i < len(nodes); i++ { - if nodes[i].State != stateDead { - t.Fatalf("Bad state %d", i) - } - } -} - -func TestKRandomNodes(t *testing.T) { - nodes := []*nodeState{} - for i := 0; i < 90; i++ { - // Half the nodes are in a bad state - state := stateAlive - switch i % 3 { - case 0: - state = stateAlive - case 1: - state = stateSuspect - case 2: - state = stateDead - } - nodes = append(nodes, &nodeState{ - Node: Node{ - Name: fmt.Sprintf("test%d", i), - }, - State: state, - }) - } - - filterFunc := func(n *nodeState) bool { - if n.Name == "test0" || n.State != stateAlive { - return true - } - return false - } - - s1 := kRandomNodes(3, nodes, filterFunc) - s2 := kRandomNodes(3, nodes, filterFunc) - s3 := kRandomNodes(3, nodes, filterFunc) - - if reflect.DeepEqual(s1, s2) { - t.Fatalf("unexpected equal") - } - if reflect.DeepEqual(s1, s3) { - t.Fatalf("unexpected equal") - } - if reflect.DeepEqual(s2, s3) { - t.Fatalf("unexpected equal") - } - - for _, s := range [][]*nodeState{s1, s2, s3} { - if len(s) != 3 { - t.Fatalf("bad len") - } - for _, n := range s { - if n.Name == "test0" { - t.Fatalf("Bad name") - } - if n.State != stateAlive { - t.Fatalf("Bad state") - } - } - } -} - -func TestMakeCompoundMessage(t *testing.T) { - msg := &ping{SeqNo: 100} - buf, err := encode(pingMsg, msg) - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - - msgs := [][]byte{buf.Bytes(), buf.Bytes(), buf.Bytes()} - compound := makeCompoundMessage(msgs) - - if compound.Len() != 3*buf.Len()+3*compoundOverhead+compoundHeaderOverhead { - t.Fatalf("bad len") - } -} - -func TestDecodeCompoundMessage(t *testing.T) { - msg := &ping{SeqNo: 100} - buf, err := encode(pingMsg, msg) - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - - msgs := [][]byte{buf.Bytes(), buf.Bytes(), buf.Bytes()} - compound := makeCompoundMessage(msgs) - - trunc, parts, err := decodeCompoundMessage(compound.Bytes()[1:]) - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - if trunc != 0 { - t.Fatalf("should not truncate") - } - if len(parts) != 3 { - t.Fatalf("bad parts") - } - for _, p := range parts { - if len(p) != buf.Len() { - t.Fatalf("bad part len") - } - } -} - -func TestDecodeCompoundMessage_Trunc(t *testing.T) { - msg := &ping{SeqNo: 100} - buf, err := encode(pingMsg, msg) - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - - msgs := [][]byte{buf.Bytes(), buf.Bytes(), buf.Bytes()} - compound := makeCompoundMessage(msgs) - - trunc, parts, err := decodeCompoundMessage(compound.Bytes()[1:38]) - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - if trunc != 1 { - t.Fatalf("truncate: %d", trunc) - } - if len(parts) != 2 { - t.Fatalf("bad parts") - } - for _, p := range parts { - if len(p) != buf.Len() { - t.Fatalf("bad part len") - } - } -} - -func TestCompressDecompressPayload(t *testing.T) { - buf, err := compressPayload([]byte("testing")) - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - - decomp, err := decompressPayload(buf.Bytes()[1:]) - if err != nil { - t.Fatalf("unexpected err: %s", err) - } - - if !reflect.DeepEqual(decomp, []byte("testing")) { - t.Fatalf("bad payload: %v", decomp) - } -} |