github.com/unionj-cloud/go-doudou/v2@v2.3.5/toolkit/memberlist/memberlist_test.go (about) 1 package memberlist_test 2 3 import ( 4 "bytes" 5 "fmt" 6 "github.com/golang/mock/gomock" 7 "github.com/unionj-cloud/go-doudou/v2/toolkit/memberlist" 8 memmock "github.com/unionj-cloud/go-doudou/v2/toolkit/memberlist/mock" 9 "io/ioutil" 10 "log" 11 "net" 12 "os" 13 "reflect" 14 "runtime" 15 "strconv" 16 "strings" 17 "sync" 18 "testing" 19 "time" 20 21 "github.com/miekg/dns" 22 "github.com/stretchr/testify/require" 23 ) 24 25 func retry(t *testing.T, n int, w time.Duration, fn func(func(string, ...interface{}))) { 26 t.Helper() 27 for try := 1; try <= n; try++ { 28 failed := false 29 failFormat := "" 30 failArgs := []interface{}{} 31 failf := func(format string, args ...interface{}) { 32 failed = true 33 failFormat = format 34 failArgs = args 35 } 36 37 fn(failf) 38 39 if !failed { 40 return 41 } 42 if try == n { 43 t.Fatalf(failFormat, failArgs...) 44 } 45 time.Sleep(w) 46 } 47 } 48 49 var bindLock sync.Mutex 50 var bindNum byte = 10 51 52 func getBindAddrNet(network byte) net.IP { 53 bindLock.Lock() 54 defer bindLock.Unlock() 55 56 //result := net.IPv4(127, 0, network, bindNum) 57 //bindNum++ 58 //if bindNum > 255 { 59 // bindNum = 10 60 //} 61 62 result := net.IPv4(127, 0, 0, 1) 63 64 return result 65 } 66 67 func getBindAddr() net.IP { 68 return getBindAddrNet(0) 69 } 70 71 func testConfigNet(tb testing.TB, network byte) *memberlist.Config { 72 tb.Helper() 73 74 config := memberlist.DefaultLANConfig() 75 config.BindAddr = getBindAddrNet(network).String() 76 config.Name = config.BindAddr 77 config.BindPort = 0 // choose free port 78 config.RequireNodeNames = true 79 config.Logger = log.New(os.Stderr, config.Name, log.LstdFlags) 80 return config 81 } 82 83 func testConfig(tb testing.TB) *memberlist.Config { 84 return testConfigNet(tb, 0) 85 } 86 87 func yield() { 88 time.Sleep(250 * time.Millisecond) 89 } 90 91 type MockDelegate struct { 92 mu sync.Mutex 93 meta []byte 94 msgs [][]byte 95 broadcasts [][]byte 96 state []byte 97 remoteState []byte 98 } 99 100 func (m *MockDelegate) setMeta(meta []byte) { 101 m.mu.Lock() 102 defer m.mu.Unlock() 103 m.meta = meta 104 } 105 106 func (m *MockDelegate) setState(state []byte) { 107 m.mu.Lock() 108 defer m.mu.Unlock() 109 m.state = state 110 } 111 112 func (m *MockDelegate) setBroadcasts(broadcasts [][]byte) { 113 m.mu.Lock() 114 defer m.mu.Unlock() 115 m.broadcasts = broadcasts 116 } 117 118 func (m *MockDelegate) getRemoteState() []byte { 119 m.mu.Lock() 120 defer m.mu.Unlock() 121 122 out := make([]byte, len(m.remoteState)) 123 copy(out, m.remoteState) 124 return out 125 } 126 127 func (m *MockDelegate) getMessages() [][]byte { 128 m.mu.Lock() 129 defer m.mu.Unlock() 130 131 out := make([][]byte, len(m.msgs)) 132 for i, msg := range m.msgs { 133 out[i] = make([]byte, len(msg)) 134 copy(out[i], msg) 135 } 136 return out 137 } 138 139 func (m *MockDelegate) NodeMeta(limit int) []byte { 140 m.mu.Lock() 141 defer m.mu.Unlock() 142 143 return m.meta 144 } 145 146 func (m *MockDelegate) NotifyMsg(msg []byte) { 147 m.mu.Lock() 148 defer m.mu.Unlock() 149 150 cp := make([]byte, len(msg)) 151 copy(cp, msg) 152 m.msgs = append(m.msgs, cp) 153 } 154 155 func (m *MockDelegate) GetBroadcasts(overhead, limit int) [][]byte { 156 m.mu.Lock() 157 defer m.mu.Unlock() 158 159 b := m.broadcasts 160 m.broadcasts = nil 161 return b 162 } 163 164 func (m *MockDelegate) LocalState(join bool) []byte { 165 m.mu.Lock() 166 defer m.mu.Unlock() 167 168 return m.state 169 } 170 171 func (m *MockDelegate) MergeRemoteState(s []byte, join bool) { 172 m.mu.Lock() 173 defer m.mu.Unlock() 174 175 m.remoteState = s 176 } 177 178 func TestDefaultLANConfig_protocolVersion(t *testing.T) { 179 c := memberlist.DefaultLANConfig() 180 if c.ProtocolVersion != memberlist.ProtocolVersion2Compatible { 181 t.Fatalf("should be max: %d", c.ProtocolVersion) 182 } 183 } 184 185 func TestCreate_protocolVersion(t *testing.T) { 186 cases := []struct { 187 name string 188 version uint8 189 err bool 190 }{ 191 {"min", memberlist.ProtocolVersionMin, false}, 192 {"max", memberlist.ProtocolVersionMax, false}, 193 {"max+1", memberlist.ProtocolVersionMax + 1, true}, 194 {"min-1", memberlist.ProtocolVersionMax - 1, false}, 195 } 196 197 for _, tc := range cases { 198 t.Run(tc.name, func(t *testing.T) { 199 c := memberlist.DefaultLANConfig() 200 c.BindAddr = getBindAddr().String() 201 c.ProtocolVersion = tc.version 202 203 m, err := memberlist.Create(c) 204 if err == nil { 205 require.NoError(t, m.Shutdown()) 206 } 207 208 if tc.err && err == nil { 209 t.Fatalf("Should've failed with version: %d", tc.version) 210 } else if !tc.err && err != nil { 211 t.Fatalf("Version '%d' error: %s", tc.version, err) 212 } 213 }) 214 } 215 } 216 217 func TestCreate_secretKey(t *testing.T) { 218 cases := []struct { 219 name string 220 key []byte 221 err bool 222 }{ 223 {"size-0", make([]byte, 0), false}, 224 {"abc", []byte("abc"), true}, 225 {"size-16", make([]byte, 16), false}, 226 {"size-38", make([]byte, 38), true}, 227 } 228 229 for _, tc := range cases { 230 t.Run(tc.name, func(t *testing.T) { 231 c := memberlist.DefaultLANConfig() 232 c.BindAddr = getBindAddr().String() 233 c.SecretKey = tc.key 234 235 m, err := memberlist.Create(c) 236 if err == nil { 237 require.NoError(t, m.Shutdown()) 238 } 239 240 if tc.err && err == nil { 241 t.Fatalf("Should've failed with key: %#v", tc.key) 242 } else if !tc.err && err != nil { 243 t.Fatalf("Key '%#v' error: %s", tc.key, err) 244 } 245 }) 246 } 247 } 248 249 func TestCreate_secretKeyEmpty(t *testing.T) { 250 c := memberlist.DefaultLANConfig() 251 c.BindAddr = getBindAddr().String() 252 c.SecretKey = make([]byte, 0) 253 254 m, err := memberlist.Create(c) 255 require.NoError(t, err) 256 defer m.Shutdown() 257 258 if m.Config().EncryptionEnabled() { 259 t.Fatalf("Expected encryption to be disabled") 260 } 261 } 262 263 func TestCreate_keyringOnly(t *testing.T) { 264 c := memberlist.DefaultLANConfig() 265 c.BindAddr = getBindAddr().String() 266 267 keyring, err := memberlist.NewKeyring(nil, make([]byte, 16)) 268 require.NoError(t, err) 269 c.Keyring = keyring 270 271 m, err := memberlist.Create(c) 272 require.NoError(t, err) 273 defer m.Shutdown() 274 } 275 276 func TestCreate_keyringAndSecretKey(t *testing.T) { 277 c := memberlist.DefaultLANConfig() 278 c.BindAddr = getBindAddr().String() 279 280 keyring, err := memberlist.NewKeyring(nil, make([]byte, 16)) 281 require.NoError(t, err) 282 c.Keyring = keyring 283 c.SecretKey = []byte{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} 284 285 m, err := memberlist.Create(c) 286 require.NoError(t, err) 287 defer m.Shutdown() 288 289 ringKeys := c.Keyring.GetKeys() 290 if !bytes.Equal(c.SecretKey, ringKeys[0]) { 291 t.Fatalf("Unexpected primary key %v", ringKeys[0]) 292 } 293 } 294 295 func TestCreate_invalidLoggerSettings(t *testing.T) { 296 c := memberlist.DefaultLANConfig() 297 c.BindAddr = getBindAddr().String() 298 c.Logger = log.New(ioutil.Discard, "", log.LstdFlags) 299 c.LogOutput = ioutil.Discard 300 301 m, err := memberlist.Create(c) 302 if err == nil { 303 require.NoError(t, m.Shutdown()) 304 t.Fatal("Memberlist should not allow both LogOutput and Logger to be set, but it did not raise an error") 305 } 306 } 307 308 func TestCreate(t *testing.T) { 309 c := testConfig(t) 310 c.ProtocolVersion = memberlist.ProtocolVersionMin 311 c.DelegateProtocolVersion = 13 312 c.DelegateProtocolMin = 12 313 c.DelegateProtocolMax = 24 314 315 m, err := memberlist.Create(c) 316 require.NoError(t, err) 317 defer m.Shutdown() 318 319 yield() 320 321 members := m.Members() 322 if len(members) != 1 { 323 t.Fatalf("bad number of members") 324 } 325 326 if members[0].PMin != memberlist.ProtocolVersionMin { 327 t.Fatalf("bad: %#v", members[0]) 328 } 329 330 if members[0].PMax != memberlist.ProtocolVersionMax { 331 t.Fatalf("bad: %#v", members[0]) 332 } 333 334 if members[0].PCur != c.ProtocolVersion { 335 t.Fatalf("bad: %#v", members[0]) 336 } 337 338 if members[0].DMin != c.DelegateProtocolMin { 339 t.Fatalf("bad: %#v", members[0]) 340 } 341 342 if members[0].DMax != c.DelegateProtocolMax { 343 t.Fatalf("bad: %#v", members[0]) 344 } 345 346 if members[0].DCur != c.DelegateProtocolVersion { 347 t.Fatalf("bad: %#v", members[0]) 348 } 349 } 350 351 func GetMemberlist(tb testing.TB, f func(c *memberlist.Config)) *memberlist.Memberlist { 352 c := testConfig(tb) 353 c.BindPort = 0 354 if f != nil { 355 f(c) 356 } 357 358 m, err := memberlist.NewMemberlist(c) 359 require.NoError(tb, err) 360 return m 361 } 362 363 func TestMemberList_ResolveAddr(t *testing.T) { 364 m := GetMemberlist(t, nil) 365 defer m.Shutdown() 366 367 defaultPort := uint16(m.Config().BindPort) 368 369 type testCase struct { 370 name string 371 in string 372 expectErr bool 373 ignoreExpectIP bool 374 expect []memberlist.IpPort 375 } 376 377 baseCases := []testCase{ 378 { 379 name: "localhost", 380 in: "localhost", 381 ignoreExpectIP: true, 382 expect: []memberlist.IpPort{ 383 memberlist.NewIpPort("", defaultPort, ""), 384 }, 385 }, 386 { 387 name: "ipv6 pair", 388 in: "[::1]:80", 389 expect: []memberlist.IpPort{ 390 memberlist.NewIpPort(net.IPv6loopback.String(), 80, ""), 391 }, 392 }, 393 { 394 name: "ipv6 non-pair", 395 in: "[::1]", 396 expect: []memberlist.IpPort{ 397 memberlist.NewIpPort(net.IPv6loopback.String(), defaultPort, ""), 398 }, 399 }, 400 { 401 name: "hostless port", 402 in: ":80", 403 expectErr: true, 404 }, 405 { 406 name: "hostname port combo", 407 in: "localhost:80", 408 ignoreExpectIP: true, 409 expect: []memberlist.IpPort{ 410 memberlist.NewIpPort("", 80, ""), 411 }, 412 }, 413 { 414 name: "too high port", 415 in: "localhost:80000", 416 expectErr: true, 417 }, 418 { 419 name: "ipv4 port combo", 420 in: "127.0.0.1:80", 421 expect: []memberlist.IpPort{ 422 memberlist.NewIpPort(net.IPv4(127, 0, 0, 1).String(), 80, ""), 423 }, 424 }, 425 { 426 name: "ipv6 port combo", 427 in: "[2001:db8:a0b:12f0::1]:80", 428 expect: []memberlist.IpPort{ 429 memberlist.NewIpPort(net.IP{0x20, 0x01, 0x0d, 0xb8, 0x0a, 0x0b, 0x12, 0xf0, 0, 0, 0, 0, 0, 0, 0, 0x1}.String(), 80, ""), 430 }, 431 }, 432 { 433 name: "ipv4 port combo with empty tag", 434 in: "/127.0.0.1:80", 435 expectErr: true, 436 }, 437 { 438 name: "ipv4 only", 439 in: "127.0.0.1", 440 expect: []memberlist.IpPort{ 441 memberlist.NewIpPort(net.IPv4(127, 0, 0, 1).String(), defaultPort, ""), 442 }, 443 }, 444 { 445 name: "ipv6 only", 446 in: "[2001:db8:a0b:12f0::1]", 447 expect: []memberlist.IpPort{ 448 memberlist.NewIpPort(net.IP{0x20, 0x01, 0x0d, 0xb8, 0x0a, 0x0b, 0x12, 0xf0, 0, 0, 0, 0, 0, 0, 0, 0x1}.String(), defaultPort, ""), 449 }, 450 }, 451 } 452 453 // explode the cases to include tagged versions of everything 454 var cases []testCase 455 for _, tc := range baseCases { 456 cases = append(cases, tc) 457 if !strings.Contains(tc.in, "/") { // don't double tag already tagged cases 458 tc2 := testCase{ 459 name: tc.name + " (tagged)", 460 in: "foo.bar/" + tc.in, 461 expectErr: tc.expectErr, 462 ignoreExpectIP: tc.ignoreExpectIP, 463 } 464 for _, ipp := range tc.expect { 465 tc2.expect = append(tc2.expect, memberlist.NewIpPort(ipp.Ip(), ipp.Port(), "foo.bar")) 466 } 467 cases = append(cases, tc2) 468 } 469 } 470 471 for _, tc := range cases { 472 tc := tc 473 t.Run(tc.name, func(t *testing.T) { 474 t.Parallel() 475 got, err := m.ResolveAddr(tc.in) 476 if tc.expectErr { 477 require.Error(t, err) 478 } else { 479 require.NoError(t, err) 480 if tc.ignoreExpectIP { 481 if len(got) > 1 { 482 got = got[0:1] 483 } 484 for i := 0; i < len(got); i++ { 485 got[i].SetIp("") 486 } 487 } 488 require.Equal(t, tc.expect, got) 489 } 490 }) 491 } 492 } 493 494 type dnsHandler struct { 495 t *testing.T 496 } 497 498 func (h dnsHandler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) { 499 if len(r.Question) != 1 { 500 h.t.Fatalf("bad: %#v", r.Question) 501 } 502 503 name := "join.service.consul." 504 question := r.Question[0] 505 if question.Name != name || question.Qtype != dns.TypeANY { 506 h.t.Fatalf("bad: %#v", question) 507 } 508 509 m := new(dns.Msg) 510 m.SetReply(r) 511 m.Authoritative = true 512 m.RecursionAvailable = false 513 m.Answer = append(m.Answer, &dns.A{ 514 Hdr: dns.RR_Header{ 515 Name: name, 516 Rrtype: dns.TypeA, 517 Class: dns.ClassINET}, 518 A: net.ParseIP("127.0.0.1"), 519 }) 520 m.Answer = append(m.Answer, &dns.AAAA{ 521 Hdr: dns.RR_Header{ 522 Name: name, 523 Rrtype: dns.TypeAAAA, 524 Class: dns.ClassINET}, 525 AAAA: net.ParseIP("2001:db8:a0b:12f0::1"), 526 }) 527 if err := w.WriteMsg(m); err != nil { 528 h.t.Fatalf("err: %v", err) 529 } 530 } 531 532 func TestMemberList_Members(t *testing.T) { 533 n1 := &memberlist.Node{Name: "test"} 534 n2 := &memberlist.Node{Name: "test2"} 535 n3 := &memberlist.Node{Name: "test3"} 536 537 m := &memberlist.Memberlist{} 538 m.SetNodes( 539 memberlist.NewNodeState(*n1, memberlist.StateAlive), 540 memberlist.NewNodeState(*n2, memberlist.StateDead), 541 memberlist.NewNodeState(*n3, memberlist.StateSuspect), 542 ) 543 544 members := m.Members() 545 if !reflect.DeepEqual(members, []*memberlist.Node{n1, n3}) { 546 t.Fatalf("bad members") 547 } 548 } 549 550 func TestMemberlist_Join(t *testing.T) { 551 c1 := testConfig(t) 552 c1.BindPort = 55111 553 c1.AdvertisePort = 55111 554 c1.Name = "m1" 555 m1, err := memberlist.Create(c1) 556 require.NoError(t, err) 557 defer m1.Shutdown() 558 559 // Create a second node 560 c2 := testConfig(t) 561 c2.BindPort = 55112 562 c2.AdvertisePort = 55112 563 c2.Name = "m2" 564 565 m2, err := memberlist.Create(c2) 566 require.NoError(t, err) 567 defer m2.Shutdown() 568 569 joinUrl := fmt.Sprintf("%s/%s:%d", m1.Config().Name, m1.AdvertiseAddr(), m1.AdvertisePort()) 570 num, err := m2.Join([]string{joinUrl}) 571 if num != 1 { 572 t.Fatalf("unexpected 1: %d", num) 573 } 574 if err != nil { 575 t.Fatalf("unexpected err: %s", err) 576 } 577 578 // Check the hosts 579 if len(m2.Members()) != 2 { 580 t.Fatalf("should have 2 nodes! %v", m2.Members()) 581 } 582 } 583 584 func TestMemberlist_JoinDifferentNetworksUniqueMask(t *testing.T) { 585 c1 := testConfigNet(t, 0) 586 c1.BindPort = 55113 587 c1.AdvertisePort = 55113 588 c1.Name = "m1" 589 c1.CIDRsAllowed, _ = memberlist.ParseCIDRs([]string{"127.0.0.0/8"}) 590 m1, err := memberlist.Create(c1) 591 require.NoError(t, err) 592 defer m1.Shutdown() 593 594 // Create a second node 595 c2 := testConfigNet(t, 1) 596 c2.CIDRsAllowed, _ = memberlist.ParseCIDRs([]string{"127.0.0.0/8"}) 597 c2.BindPort = 55114 598 c2.AdvertisePort = 55114 599 c2.Name = "m2" 600 601 m2, err := memberlist.Create(c2) 602 require.NoError(t, err) 603 defer m2.Shutdown() 604 605 joinUrl := fmt.Sprintf("%s/%s:%d", m1.Config().Name, m1.AdvertiseAddr(), m1.AdvertisePort()) 606 num, err := m2.Join([]string{joinUrl}) 607 if num != 1 { 608 t.Fatalf("unexpected 1: %d", num) 609 } 610 if err != nil { 611 t.Fatalf("unexpected err: %s", err) 612 } 613 614 // Check the hosts 615 if len(m2.Members()) != 2 { 616 t.Fatalf("should have 2 nodes! %v", m2.Members()) 617 } 618 } 619 620 func TestMemberlist_JoinDifferentNetworksMultiMasks(t *testing.T) { 621 c1 := testConfigNet(t, 0) 622 c1.BindPort = 55115 623 c1.AdvertisePort = 55115 624 c1.Name = "m1" 625 c1.CIDRsAllowed, _ = memberlist.ParseCIDRs([]string{"127.0.0.0/24", "127.0.1.0/24"}) 626 m1, err := memberlist.Create(c1) 627 require.NoError(t, err) 628 defer m1.Shutdown() 629 630 // Create a second node 631 c2 := testConfigNet(t, 1) 632 c2.CIDRsAllowed, _ = memberlist.ParseCIDRs([]string{"127.0.0.0/24", "127.0.1.0/24"}) 633 c2.BindPort = 55116 634 c2.AdvertisePort = 55116 635 c2.Name = "m2" 636 637 m2, err := memberlist.Create(c2) 638 require.NoError(t, err) 639 defer m2.Shutdown() 640 641 joinUrl := fmt.Sprintf("%s/%s:%d", m1.Config().Name, m1.AdvertiseAddr(), m1.AdvertisePort()) 642 err = joinAndTestMemberShip(t, m2, []string{joinUrl}, 2) 643 if err != nil { 644 t.Fatalf("unexpected err: %s", err) 645 } 646 } 647 648 type CustomMergeDelegate struct { 649 invoked bool 650 t *testing.T 651 } 652 653 func (c *CustomMergeDelegate) NotifyMerge(nodes []*memberlist.Node) error { 654 c.t.Logf("Cancel merge") 655 c.invoked = true 656 return fmt.Errorf("Custom merge canceled") 657 } 658 659 func TestMemberlist_Join_Cancel(t *testing.T) { 660 c1 := testConfig(t) 661 c1.BindPort = 55117 662 c1.AdvertisePort = 55117 663 c1.Name = "m1" 664 merge1 := &CustomMergeDelegate{t: t} 665 c1.Merge = merge1 666 667 m1, err := memberlist.Create(c1) 668 require.NoError(t, err) 669 defer m1.Shutdown() 670 671 // Create a second node 672 c2 := testConfig(t) 673 c2.BindPort = 55118 674 c2.AdvertisePort = 55118 675 c2.Name = "m2" 676 merge2 := &CustomMergeDelegate{t: t} 677 c2.Merge = merge2 678 679 m2, err := memberlist.Create(c2) 680 require.NoError(t, err) 681 defer m2.Shutdown() 682 683 joinUrl := fmt.Sprintf("%s/%s:%d", m1.Config().Name, m1.AdvertiseAddr(), m1.AdvertisePort()) 684 num, err := m2.Join([]string{joinUrl}) 685 if num != 0 { 686 t.Fatalf("unexpected 0: %d", num) 687 } 688 if !strings.Contains(err.Error(), "Custom merge canceled") { 689 t.Fatalf("unexpected err: %s", err) 690 } 691 692 // Check the hosts 693 if len(m2.Members()) != 1 { 694 t.Fatalf("should have 1 nodes! %v", m2.Members()) 695 } 696 if len(m1.Members()) != 1 { 697 t.Fatalf("should have 1 nodes! %v", m1.Members()) 698 } 699 700 // Check delegate invocation 701 if !merge1.invoked { 702 t.Fatalf("should invoke delegate") 703 } 704 if !merge2.invoked { 705 t.Fatalf("should invoke delegate") 706 } 707 } 708 709 type CustomAliveDelegate struct { 710 Ignore string 711 count int 712 713 t *testing.T 714 } 715 716 func (c *CustomAliveDelegate) NotifyAlive(peer *memberlist.Node) error { 717 c.count++ 718 if peer.Name == c.Ignore { 719 return nil 720 } 721 c.t.Logf("Cancel alive") 722 return fmt.Errorf("Custom alive canceled") 723 } 724 725 func TestMemberlist_Join_Cancel_Passive(t *testing.T) { 726 c1 := testConfig(t) 727 c1.BindPort = 55119 728 c1.AdvertisePort = 55119 729 c1.Name = "m1" 730 alive1 := &CustomAliveDelegate{ 731 Ignore: c1.Name, 732 t: t, 733 } 734 c1.Alive = alive1 735 736 m1, err := memberlist.Create(c1) 737 require.NoError(t, err) 738 defer m1.Shutdown() 739 740 // Create a second node 741 c2 := testConfig(t) 742 c2.BindPort = 55120 743 c2.AdvertisePort = 55120 744 c2.Name = "m2" 745 alive2 := &CustomAliveDelegate{ 746 Ignore: c2.Name, 747 t: t, 748 } 749 c2.Alive = alive2 750 751 m2, err := memberlist.Create(c2) 752 require.NoError(t, err) 753 defer m2.Shutdown() 754 755 joinUrl := fmt.Sprintf("%s/%s:%d", m1.Config().Name, m1.AdvertiseAddr(), m1.AdvertisePort()) 756 num, err := m2.Join([]string{joinUrl}) 757 if num != 1 { 758 t.Fatalf("unexpected 1: %d", num) 759 } 760 if err != nil { 761 t.Fatalf("err: %s", err) 762 } 763 764 // Check the hosts 765 if len(m2.Members()) != 1 { 766 t.Fatalf("should have 1 nodes! %v", m2.Members()) 767 } 768 if len(m1.Members()) != 1 { 769 t.Fatalf("should have 1 nodes! %v", m1.Members()) 770 } 771 772 // Check delegate invocation 773 if alive1.count == 0 { 774 t.Fatalf("should invoke delegate: %d", alive1.count) 775 } 776 if alive2.count == 0 { 777 t.Fatalf("should invoke delegate: %d", alive2.count) 778 } 779 } 780 781 func TestMemberlist_Join_protocolVersions(t *testing.T) { 782 c1 := testConfig(t) 783 c1.BindPort = 55121 784 c1.AdvertisePort = 55121 785 c1.Name = "m1" 786 m1, err := memberlist.Create(c1) 787 require.NoError(t, err) 788 defer m1.Shutdown() 789 790 c2 := testConfig(t) 791 c2.BindPort = 55110 792 c2.AdvertisePort = 55110 793 c2.Name = "m2" 794 795 m2, err := memberlist.Create(c2) 796 require.NoError(t, err) 797 defer m2.Shutdown() 798 799 c3 := testConfig(t) 800 c3.BindPort = 55109 801 c3.AdvertisePort = 55109 802 c3.Name = "m3" 803 c3.ProtocolVersion = memberlist.ProtocolVersionMax 804 805 m3, err := memberlist.Create(c3) 806 require.NoError(t, err) 807 defer m3.Shutdown() 808 809 _, err = m1.Join([]string{c2.Name + "/" + c2.BindAddr}) 810 require.NoError(t, err) 811 812 yield() 813 814 _, err = m1.Join([]string{c3.Name + "/" + c3.BindAddr}) 815 require.NoError(t, err) 816 } 817 818 func joinAndTestMemberShip(t *testing.T, self *memberlist.Memberlist, membersToJoin []string, expectedMembers int) error { 819 t.Helper() 820 num, err := self.Join(membersToJoin) 821 if err != nil { 822 return err 823 } 824 if num != len(membersToJoin) { 825 t.Fatalf("unexpected %d, was expecting %d to be joined", num, len(membersToJoin)) 826 } 827 if err != nil { 828 t.Fatalf("unexpected err: %s", err) 829 } 830 // Check the hosts 831 if len(self.Members()) != expectedMembers { 832 t.Fatalf("should have 2 nodes! %v", self.Members()) 833 } 834 if len(self.Members()) != expectedMembers { 835 t.Fatalf("should have 2 nodes! %v", self.Members()) 836 } 837 return nil 838 } 839 840 func TestMemberlist_Leave(t *testing.T) { 841 newConfig := func() *memberlist.Config { 842 c := testConfig(t) 843 c.GossipInterval = time.Millisecond 844 return c 845 } 846 847 c1 := newConfig() 848 c1.BindPort = 55108 849 c1.AdvertisePort = 55108 850 c1.Name = "m1" 851 852 m1, err := memberlist.Create(c1) 853 require.NoError(t, err) 854 defer m1.Shutdown() 855 856 // Create a second node 857 c2 := newConfig() 858 c2.BindPort = 55107 859 c2.AdvertisePort = 55107 860 c2.Name = "m2" 861 862 m2, err := memberlist.Create(c2) 863 require.NoError(t, err) 864 defer m2.Shutdown() 865 866 joinUrl := fmt.Sprintf("%s/%s:%d", m1.Config().Name, m1.AdvertiseAddr(), m1.AdvertisePort()) 867 err = joinAndTestMemberShip(t, m2, []string{joinUrl}, 2) 868 if err != nil { 869 t.Fatalf("unexpected err: %s", err) 870 } 871 872 // Leave 873 err = m1.Leave(time.Second) 874 require.NoError(t, err) 875 876 // Wait for leave 877 time.Sleep(10 * time.Millisecond) 878 879 // m1 should think dead 880 if len(m1.Members()) != 1 { 881 t.Fatalf("should have 1 node") 882 } 883 884 if len(m2.Members()) != 1 { 885 t.Fatalf("should have 1 node") 886 } 887 888 if m2.NodeMap()[c1.Name].State != memberlist.StateLeft { 889 t.Fatalf("bad state") 890 } 891 } 892 893 func TestMemberlist_JoinShutdown(t *testing.T) { 894 newConfig := func() *memberlist.Config { 895 c := testConfig(t) 896 c.ProbeInterval = time.Millisecond 897 c.ProbeTimeout = 100 * time.Microsecond 898 c.SuspicionMaxTimeoutMult = 1 899 return c 900 } 901 902 c1 := newConfig() 903 c1.BindPort = 55106 904 c1.AdvertisePort = 55106 905 c1.Name = "m1" 906 907 m1, err := memberlist.Create(c1) 908 require.NoError(t, err) 909 defer m1.Shutdown() 910 911 // Create a second node 912 c2 := newConfig() 913 c2.BindPort = 55105 914 c2.AdvertisePort = 55105 915 c2.Name = "m2" 916 917 m2, err := memberlist.Create(c2) 918 require.NoError(t, err) 919 defer m2.Shutdown() 920 921 joinUrl := fmt.Sprintf("%s/%s:%d", m1.Config().Name, m1.AdvertiseAddr(), m1.AdvertisePort()) 922 num, err := m2.Join([]string{joinUrl}) 923 if num != 1 { 924 t.Fatalf("unexpected 1: %d", num) 925 } 926 if err != nil { 927 t.Fatalf("unexpected err: %s", err) 928 } 929 930 // Check the hosts 931 if len(m2.Members()) != 2 { 932 t.Fatalf("should have 2 nodes! %v", m2.Members()) 933 } 934 935 require.NoError(t, m1.Shutdown()) 936 937 waitForCondition(t, func() (bool, string) { 938 n := len(m2.Members()) 939 return n == 1, fmt.Sprintf("expected 1 node, got %d", n) 940 }) 941 } 942 943 func TestMemberlist_delegateMeta(t *testing.T) { 944 c1 := testConfig(t) 945 c1.Delegate = &MockDelegate{meta: []byte("web")} 946 c1.BindPort = 55104 947 c1.AdvertisePort = 55104 948 c1.Name = "c1" 949 950 m1, err := memberlist.Create(c1) 951 require.NoError(t, err) 952 defer m1.Shutdown() 953 954 c2 := testConfig(t) 955 c2.BindPort = 55103 956 c2.AdvertisePort = 55103 957 c2.Name = "c2" 958 c2.Delegate = &MockDelegate{meta: []byte("lb")} 959 960 m2, err := memberlist.Create(c2) 961 require.NoError(t, err) 962 defer m2.Shutdown() 963 964 joinUrl := fmt.Sprintf("%s/%s:%d", m2.Config().Name, m2.AdvertiseAddr(), m2.AdvertisePort()) 965 _, err = m1.Join([]string{joinUrl}) 966 require.NoError(t, err) 967 968 yield() 969 970 var roles map[string]string 971 972 // Check the roles of members of m1 973 m1m := m1.Members() 974 if len(m1m) != 2 { 975 t.Fatalf("bad: %#v", m1m) 976 } 977 978 roles = make(map[string]string) 979 for _, m := range m1m { 980 roles[m.Name] = string(m.Meta) 981 } 982 983 if r := roles[c1.Name]; r != "web" { 984 t.Fatalf("bad role for %s: %s", c1.Name, r) 985 } 986 987 if r := roles[c2.Name]; r != "lb" { 988 t.Fatalf("bad role for %s: %s", c2.Name, r) 989 } 990 991 // Check the roles of members of m2 992 m2m := m2.Members() 993 if len(m2m) != 2 { 994 t.Fatalf("bad: %#v", m2m) 995 } 996 997 roles = make(map[string]string) 998 for _, m := range m2m { 999 roles[m.Name] = string(m.Meta) 1000 } 1001 1002 if r := roles[c1.Name]; r != "web" { 1003 t.Fatalf("bad role for %s: %s", c1.Name, r) 1004 } 1005 1006 if r := roles[c2.Name]; r != "lb" { 1007 t.Fatalf("bad role for %s: %s", c2.Name, r) 1008 } 1009 } 1010 1011 func TestMemberlist_delegateMeta_Update(t *testing.T) { 1012 c1 := testConfig(t) 1013 c1.BindPort = 55122 1014 c1.AdvertisePort = 55122 1015 c1.Name = "m1" 1016 mock1 := &MockDelegate{meta: []byte("web")} 1017 c1.Delegate = mock1 1018 1019 m1, err := memberlist.Create(c1) 1020 require.NoError(t, err) 1021 defer m1.Shutdown() 1022 1023 c2 := testConfig(t) 1024 c2.BindPort = 55123 1025 c2.AdvertisePort = 55123 1026 c2.Name = "m2" 1027 mock2 := &MockDelegate{meta: []byte("lb")} 1028 c2.Delegate = mock2 1029 1030 m2, err := memberlist.Create(c2) 1031 require.NoError(t, err) 1032 defer m2.Shutdown() 1033 1034 joinUrl := fmt.Sprintf("%s/%s:%d", m2.Config().Name, m2.AdvertiseAddr(), m2.AdvertisePort()) 1035 _, err = m1.Join([]string{joinUrl}) 1036 1037 require.NoError(t, err) 1038 1039 yield() 1040 1041 // Update the meta data roles 1042 mock1.setMeta([]byte("api")) 1043 mock2.setMeta([]byte("db")) 1044 1045 err = m1.UpdateNode(0) 1046 require.NoError(t, err) 1047 err = m2.UpdateNode(0) 1048 require.NoError(t, err) 1049 1050 yield() 1051 1052 // Check the updates have propagated 1053 var roles map[string]string 1054 1055 // Check the roles of members of m1 1056 m1m := m1.Members() 1057 if len(m1m) != 2 { 1058 t.Fatalf("bad: %#v", m1m) 1059 } 1060 1061 roles = make(map[string]string) 1062 for _, m := range m1m { 1063 roles[m.Name] = string(m.Meta) 1064 } 1065 1066 if r := roles[c1.Name]; r != "api" { 1067 t.Fatalf("bad role for %s: %s", c1.Name, r) 1068 } 1069 1070 if r := roles[c2.Name]; r != "db" { 1071 t.Fatalf("bad role for %s: %s", c2.Name, r) 1072 } 1073 1074 // Check the roles of members of m2 1075 m2m := m2.Members() 1076 if len(m2m) != 2 { 1077 t.Fatalf("bad: %#v", m2m) 1078 } 1079 1080 roles = make(map[string]string) 1081 for _, m := range m2m { 1082 roles[m.Name] = string(m.Meta) 1083 } 1084 1085 if r := roles[c1.Name]; r != "api" { 1086 t.Fatalf("bad role for %s: %s", c1.Name, r) 1087 } 1088 1089 if r := roles[c2.Name]; r != "db" { 1090 t.Fatalf("bad role for %s: %s", c2.Name, r) 1091 } 1092 } 1093 1094 func TestMemberlist_UserData(t *testing.T) { 1095 newConfig := func() (*memberlist.Config, *MockDelegate) { 1096 d := &MockDelegate{} 1097 c := testConfig(t) 1098 // Set the gossip/pushpull intervals fast enough to get a reasonable test, 1099 // but slow enough to avoid "sendto: operation not permitted" 1100 c.GossipInterval = 100 * time.Millisecond 1101 c.PushPullInterval = 100 * time.Millisecond 1102 c.Delegate = d 1103 return c, d 1104 } 1105 1106 c1, d1 := newConfig() 1107 c1.BindPort = 55133 1108 c1.AdvertisePort = 55133 1109 c1.Name = "m1" 1110 d1.setState([]byte("something")) 1111 1112 m1, err := memberlist.Create(c1) 1113 require.NoError(t, err) 1114 defer m1.Shutdown() 1115 1116 bcasts := [][]byte{ 1117 []byte("test"), 1118 []byte("foobar"), 1119 } 1120 1121 // Create a second node 1122 c2, d2 := newConfig() 1123 c2.BindPort = 55134 1124 c2.AdvertisePort = 55134 1125 c2.Name = "m2" 1126 1127 // Second delegate has things to send 1128 d2.setBroadcasts(bcasts) 1129 d2.setState([]byte("my state")) 1130 1131 m2, err := memberlist.Create(c2) 1132 require.NoError(t, err) 1133 defer m2.Shutdown() 1134 1135 joinUrl := fmt.Sprintf("%s/%s:%d", m1.Config().Name, m1.AdvertiseAddr(), m1.AdvertisePort()) 1136 num, err := m2.Join([]string{joinUrl}) 1137 if num != 1 { 1138 t.Fatalf("unexpected 1: %d", num) 1139 } 1140 require.NoError(t, err) 1141 1142 // Check the hosts 1143 if m2.NumMembers() != 2 { 1144 t.Fatalf("should have 2 nodes! %v", m2.Members()) 1145 } 1146 } 1147 1148 func TestMemberlist_SendTo(t *testing.T) { 1149 newConfig := func() (*memberlist.Config, *MockDelegate, net.IP) { 1150 d := &MockDelegate{} 1151 c := testConfig(t) 1152 c.GossipInterval = time.Millisecond 1153 c.PushPullInterval = time.Millisecond 1154 c.Delegate = d 1155 return c, d, net.ParseIP(c.BindAddr) 1156 } 1157 1158 c1, d1, _ := newConfig() 1159 c1.BindPort = 55144 1160 c1.AdvertisePort = 55144 1161 c1.Name = "m1" 1162 1163 m1, err := memberlist.Create(c1) 1164 require.NoError(t, err) 1165 defer m1.Shutdown() 1166 1167 c2, d2, addr2 := newConfig() 1168 c2.BindPort = 55145 1169 c2.AdvertisePort = 55145 1170 c2.Name = "m2" 1171 1172 m2, err := memberlist.Create(c2) 1173 require.NoError(t, err) 1174 defer m2.Shutdown() 1175 1176 joinUrl := fmt.Sprintf("%s/%s:%d", m1.Config().Name, m1.AdvertiseAddr(), m1.AdvertisePort()) 1177 num, err := m2.Join([]string{joinUrl}) 1178 require.NoError(t, err) 1179 require.Equal(t, 1, num) 1180 1181 // Check the hosts 1182 require.Equal(t, 2, m2.NumMembers(), "should have 2 nodes! %v", m2.Members()) 1183 1184 // Try to do a direct send 1185 m2Addr := &net.UDPAddr{ 1186 IP: addr2, 1187 Port: int(m2.AdvertisePort()), 1188 } 1189 m2Address := memberlist.Address{ 1190 Addr: m2Addr.String(), 1191 Name: m2.Config().Name, 1192 } 1193 if err := m1.SendToAddress(m2Address, []byte("ping")); err != nil { 1194 t.Fatalf("err: %v", err) 1195 } 1196 1197 m1Addr := &net.UDPAddr{ 1198 IP: net.ParseIP(m1.Config().BindAddr), 1199 Port: int(m1.AdvertisePort()), 1200 } 1201 m1Address := memberlist.Address{ 1202 Addr: m1Addr.String(), 1203 Name: m1.Config().Name, 1204 } 1205 if err := m2.SendToAddress(m1Address, []byte("pong")); err != nil { 1206 t.Fatalf("err: %v", err) 1207 } 1208 1209 waitForCondition(t, func() (bool, string) { 1210 msgs := d1.getMessages() 1211 return len(msgs) == 1, fmt.Sprintf("expected 1 message, got %d", len(msgs)) 1212 }) 1213 1214 msgs1 := d1.getMessages() 1215 if !reflect.DeepEqual(msgs1[0], []byte("pong")) { 1216 t.Fatalf("bad msg %v", msgs1[0]) 1217 } 1218 1219 waitForCondition(t, func() (bool, string) { 1220 msgs := d2.getMessages() 1221 return len(msgs) == 1, fmt.Sprintf("expected 1 message, got %d", len(msgs)) 1222 }) 1223 msgs2 := d2.getMessages() 1224 if !reflect.DeepEqual(msgs2[0], []byte("ping")) { 1225 t.Fatalf("bad msg %v", msgs2[0]) 1226 } 1227 } 1228 1229 func waitForCondition(t *testing.T, fn func() (bool, string)) { 1230 start := time.Now() 1231 1232 var msg string 1233 for time.Since(start) < 20*time.Second { 1234 var done bool 1235 done, msg = fn() 1236 if done { 1237 return 1238 } 1239 time.Sleep(5 * time.Millisecond) 1240 } 1241 t.Fatalf("timeout waiting for condition: %v", msg) 1242 } 1243 1244 func TestMemberlistProtocolVersion(t *testing.T) { 1245 c := testConfig(t) 1246 c.ProtocolVersion = memberlist.ProtocolVersionMax 1247 1248 m, err := memberlist.Create(c) 1249 require.NoError(t, err) 1250 defer m.Shutdown() 1251 1252 result := m.ProtocolVersion() 1253 if result != memberlist.ProtocolVersionMax { 1254 t.Fatalf("bad: %d", result) 1255 } 1256 } 1257 1258 func TestMemberlist_Join_DeadNode(t *testing.T) { 1259 c1 := testConfig(t) 1260 c1.TCPTimeout = 50 * time.Millisecond 1261 c1.BindPort = 55155 1262 c1.AdvertisePort = 55155 1263 c1.Name = "m1" 1264 1265 m1, err := memberlist.Create(c1) 1266 require.NoError(t, err) 1267 defer m1.Shutdown() 1268 1269 // Create a second "node", which is just a TCP listener that 1270 // does not ever respond. This is to test our deadlines 1271 addr2 := getBindAddr() 1272 list, err := net.Listen("tcp", net.JoinHostPort(addr2.String(), strconv.Itoa(56156))) 1273 if err != nil { 1274 t.Fatalf("err: %v", err) 1275 } 1276 defer list.Close() 1277 1278 // Ensure we don't hang forever 1279 timer := time.AfterFunc(100*time.Millisecond, func() { 1280 panic("should have timed out by now") 1281 }) 1282 defer timer.Stop() 1283 1284 num, err := m1.Join([]string{fmt.Sprintf("%s/%s:%d", "fake", addr2.String(), 56156)}) 1285 if num != 0 { 1286 t.Fatalf("unexpected 0: %d", num) 1287 } 1288 if err == nil { 1289 t.Fatal("expect err") 1290 } 1291 } 1292 1293 // Tests that nodes running different versions of the protocol can successfully 1294 // discover each other and add themselves to their respective member lists. 1295 func TestMemberlist_Join_Protocol_Compatibility(t *testing.T) { 1296 testProtocolVersionPair := func(t *testing.T, pv1 uint8, pv2 uint8) { 1297 t.Helper() 1298 1299 c1 := testConfig(t) 1300 c1.ProtocolVersion = pv1 1301 c1.BindPort = 55166 1302 c1.AdvertisePort = 55166 1303 c1.Name = "m1" 1304 1305 m1, err := memberlist.Create(c1) 1306 require.NoError(t, err) 1307 defer m1.Shutdown() 1308 1309 c2 := testConfig(t) 1310 c2.BindPort = 55167 1311 c2.AdvertisePort = 55167 1312 c2.ProtocolVersion = pv2 1313 c1.Name = "m2" 1314 1315 m2, err := memberlist.Create(c2) 1316 require.NoError(t, err) 1317 defer m2.Shutdown() 1318 1319 joinUrl := fmt.Sprintf("%s/%s:%d", m1.Config().Name, m1.AdvertiseAddr(), m1.AdvertisePort()) 1320 _, err = m2.Join([]string{joinUrl}) 1321 1322 require.NoError(t, err) 1323 //require.Equal(t, 1, num) 1324 1325 // Check the hosts 1326 //if len(m2.Members()) != 2 { 1327 // t.Fatalf("should have 2 nodes! %v", m2.Members()) 1328 //} 1329 // 1330 // Check the hosts 1331 //if len(m1.Members()) != 2 { 1332 // t.Fatalf("should have 2 nodes! %v", m1.Members()) 1333 //} 1334 } 1335 1336 t.Run("2,1", func(t *testing.T) { 1337 testProtocolVersionPair(t, 2, 1) 1338 }) 1339 t.Run("2,3", func(t *testing.T) { 1340 testProtocolVersionPair(t, 2, 3) 1341 }) 1342 t.Run("3,2", func(t *testing.T) { 1343 testProtocolVersionPair(t, 3, 2) 1344 }) 1345 t.Run("3,1", func(t *testing.T) { 1346 testProtocolVersionPair(t, 3, 1) 1347 }) 1348 } 1349 1350 var ( 1351 ipv6LoopbackAvailableOnce sync.Once 1352 ipv6LoopbackAvailable bool 1353 ) 1354 1355 func isIPv6LoopbackAvailable(t *testing.T) bool { 1356 const ipv6LoopbackAddress = "::1" 1357 ipv6LoopbackAvailableOnce.Do(func() { 1358 ifaces, err := net.Interfaces() 1359 require.NoError(t, err) 1360 1361 for _, iface := range ifaces { 1362 if iface.Flags&net.FlagLoopback == 0 { 1363 continue 1364 } 1365 addrs, err := iface.Addrs() 1366 require.NoError(t, err) 1367 1368 for _, addr := range addrs { 1369 ipaddr := addr.(*net.IPNet) 1370 if ipaddr.IP.String() == ipv6LoopbackAddress { 1371 ipv6LoopbackAvailable = true 1372 return 1373 } 1374 } 1375 } 1376 ipv6LoopbackAvailable = false 1377 t.Logf("IPv6 loopback address %q not found, disabling tests that require it", ipv6LoopbackAddress) 1378 }) 1379 1380 return ipv6LoopbackAvailable 1381 } 1382 1383 func TestMemberlist_Join_IPv6(t *testing.T) { 1384 if !isIPv6LoopbackAvailable(t) { 1385 t.SkipNow() 1386 return 1387 } 1388 // Since this binds to all interfaces we need to exclude other tests 1389 // from grabbing an interface. 1390 bindLock.Lock() 1391 defer bindLock.Unlock() 1392 1393 c1 := memberlist.DefaultLANConfig() 1394 c1.Name = "A" 1395 c1.BindAddr = "[::1]" 1396 c1.BindPort = 0 // choose free 1397 c1.Logger = log.New(os.Stderr, c1.Name, log.LstdFlags) 1398 1399 m1, err := memberlist.Create(c1) 1400 require.NoError(t, err) 1401 defer m1.Shutdown() 1402 1403 // Create a second node 1404 c2 := memberlist.DefaultLANConfig() 1405 c2.Name = "B" 1406 c2.BindAddr = "[::1]" 1407 c2.BindPort = 0 // choose free 1408 c2.Logger = log.New(os.Stderr, c2.Name, log.LstdFlags) 1409 1410 m2, err := memberlist.Create(c2) 1411 require.NoError(t, err) 1412 defer m2.Shutdown() 1413 1414 num, err := m2.Join([]string{fmt.Sprintf("%s/%s:%d", m1.Config().Name, m1.Config().BindAddr, m1.Config().BindPort)}) 1415 require.NoError(t, err) 1416 require.Equal(t, 1, num) 1417 1418 // Check the hosts 1419 if len(m2.Members()) != 2 { 1420 t.Fatalf("should have 2 nodes! %v", m2.Members()) 1421 } 1422 1423 if len(m1.Members()) != 2 { 1424 t.Fatalf("should have 2 nodes! %v", m2.Members()) 1425 } 1426 } 1427 1428 func reservePort(t *testing.T, ip net.IP, purpose string) int { 1429 for i := 0; i < 10; i++ { 1430 tcpAddr := &net.TCPAddr{IP: ip, Port: 0} 1431 tcpLn, err := net.ListenTCP("tcp", tcpAddr) 1432 if err != nil { 1433 if strings.Contains(err.Error(), "address already in use") { 1434 continue 1435 } 1436 t.Fatalf("unexpected error: %v", err) 1437 } 1438 1439 port := tcpLn.Addr().(*net.TCPAddr).Port 1440 1441 udpAddr := &net.UDPAddr{IP: ip, Port: port} 1442 udpLn, err := net.ListenUDP("udp", udpAddr) 1443 if err != nil { 1444 _ = tcpLn.Close() 1445 if strings.Contains(err.Error(), "address already in use") { 1446 continue 1447 } 1448 t.Fatalf("unexpected error: %v", err) 1449 } 1450 1451 t.Logf("Using dynamic bind port %d for %s", port, purpose) 1452 _ = tcpLn.Close() 1453 _ = udpLn.Close() 1454 return port 1455 } 1456 1457 t.Fatalf("could not find a free TCP+UDP port to listen on for %s", purpose) 1458 panic("IMPOSSIBLE") 1459 } 1460 1461 func TestAdvertiseAddr(t *testing.T) { 1462 bindAddr := getBindAddr() 1463 advertiseAddr := getBindAddr() 1464 1465 bindPort := reservePort(t, bindAddr, "BIND") 1466 advertisePort := reservePort(t, advertiseAddr, "ADVERTISE") 1467 1468 c := memberlist.DefaultLANConfig() 1469 c.BindAddr = bindAddr.String() 1470 c.BindPort = bindPort 1471 c.Name = c.BindAddr 1472 1473 c.AdvertiseAddr = advertiseAddr.String() 1474 c.AdvertisePort = advertisePort 1475 1476 m, err := memberlist.Create(c) 1477 require.NoError(t, err) 1478 defer m.Shutdown() 1479 1480 yield() 1481 1482 members := m.Members() 1483 require.Equal(t, 1, len(members)) 1484 1485 require.Equal(t, advertiseAddr.String(), members[0].Addr) 1486 require.Equal(t, advertisePort, int(members[0].Port)) 1487 } 1488 1489 type MockConflict struct { 1490 existing *memberlist.Node 1491 other *memberlist.Node 1492 } 1493 1494 func (m *MockConflict) NotifyConflict(existing, other *memberlist.Node) { 1495 m.existing = existing 1496 m.other = other 1497 } 1498 1499 func TestMemberlist_conflictDelegate(t *testing.T) { 1500 c1 := testConfig(t) 1501 c1.BindPort = 55177 1502 c1.AdvertisePort = 55177 1503 mock := &MockConflict{} 1504 c1.Conflict = mock 1505 1506 m1, err := memberlist.Create(c1) 1507 require.NoError(t, err) 1508 defer m1.Shutdown() 1509 1510 // Ensure name conflict 1511 c2 := testConfig(t) 1512 c2.Name = c1.Name 1513 c2.BindPort = 55178 1514 c2.AdvertisePort = 55178 1515 1516 m2, err := memberlist.Create(c2) 1517 require.NoError(t, err) 1518 defer m2.Shutdown() 1519 1520 joinUrl := fmt.Sprintf("%s/%s:%d", m2.Config().Name, m2.AdvertiseAddr(), m2.AdvertisePort()) 1521 num, err := m1.Join([]string{joinUrl}) 1522 require.NoError(t, err) 1523 require.Equal(t, 1, num) 1524 1525 yield() 1526 1527 // Ensure we were notified 1528 if mock.existing == nil || mock.other == nil { 1529 t.Fatalf("should get notified mock.existing=%v VS mock.other=%v", mock.existing, mock.other) 1530 } 1531 if mock.existing.Name != mock.other.Name { 1532 t.Fatalf("bad: %v %v", mock.existing, mock.other) 1533 } 1534 } 1535 1536 type MockPing struct { 1537 mu sync.Mutex 1538 other *memberlist.Node 1539 rtt time.Duration 1540 payload []byte 1541 } 1542 1543 func (m *MockPing) NotifyPingComplete(other *memberlist.Node, rtt time.Duration, payload []byte) { 1544 m.mu.Lock() 1545 defer m.mu.Unlock() 1546 1547 m.other = other 1548 m.rtt = rtt 1549 m.payload = payload 1550 } 1551 1552 func (m *MockPing) getContents() (*memberlist.Node, time.Duration, []byte) { 1553 m.mu.Lock() 1554 defer m.mu.Unlock() 1555 return m.other, m.rtt, m.payload 1556 } 1557 1558 const DEFAULT_PAYLOAD = "whatever" 1559 1560 func (m *MockPing) AckPayload() []byte { 1561 return []byte(DEFAULT_PAYLOAD) 1562 } 1563 1564 func TestMemberlist_PingDelegate(t *testing.T) { 1565 newConfig := func() *memberlist.Config { 1566 c := testConfig(t) 1567 c.ProbeInterval = 100 * time.Millisecond 1568 c.Ping = &MockPing{} 1569 return c 1570 } 1571 1572 c1 := newConfig() 1573 c1.BindPort = 55199 1574 c1.AdvertisePort = 55199 1575 c1.Name = "m1" 1576 1577 m1, err := memberlist.Create(c1) 1578 require.NoError(t, err) 1579 defer m1.Shutdown() 1580 1581 // Create a second node 1582 c2 := newConfig() 1583 c2.BindPort = 55200 1584 c2.AdvertisePort = 55200 1585 c2.Name = "m2" 1586 mock := c2.Ping.(*MockPing) 1587 1588 m2, err := memberlist.Create(c2) 1589 require.NoError(t, err) 1590 defer m2.Shutdown() 1591 1592 joinUrl := fmt.Sprintf("%s/%s:%d", m1.Config().Name, m1.AdvertiseAddr(), m1.AdvertisePort()) 1593 num, err := m2.Join([]string{joinUrl}) 1594 require.NoError(t, err) 1595 require.Equal(t, 1, num) 1596 1597 waitUntilSize(t, m1, 2) 1598 waitUntilSize(t, m2, 2) 1599 1600 time.Sleep(2 * c1.ProbeInterval) 1601 1602 require.NoError(t, m1.Shutdown()) 1603 require.NoError(t, m2.Shutdown()) 1604 1605 mOther, mRTT, _ := mock.getContents() 1606 1607 // Ensure we were notified 1608 if mOther == nil { 1609 t.Fatalf("should get notified") 1610 } 1611 1612 //if !reflect.DeepEqual(mOther, m1.LocalNode()) { 1613 // t.Fatalf("not notified about the correct node; expected: %+v; actual: %+v", 1614 // m2.LocalNode(), mOther) 1615 //} 1616 1617 if mRTT <= 0 { 1618 t.Fatalf("rtt should be greater than 0") 1619 } 1620 1621 //if bytes.Compare(mPayload, []byte(DEFAULT_PAYLOAD)) != 0 { 1622 // t.Fatalf("incorrect payload. expected: %v; actual: %v", 1623 // []byte(DEFAULT_PAYLOAD), mPayload) 1624 //} 1625 } 1626 1627 func waitUntilSize(t *testing.T, m *memberlist.Memberlist, expected int) { 1628 t.Helper() 1629 retry(t, 15, 500*time.Millisecond, func(failf func(string, ...interface{})) { 1630 t.Helper() 1631 1632 if m.NumMembers() != expected { 1633 failf("%s expected to have %d members but had: %v", m.Config().Name, expected, m.Members()) 1634 } 1635 }) 1636 } 1637 1638 func isPortFree(t *testing.T, addr string, port int) error { 1639 t.Helper() 1640 1641 ip := net.ParseIP(addr) 1642 tcpAddr := &net.TCPAddr{IP: ip, Port: port} 1643 tcpLn, err := net.ListenTCP("tcp", tcpAddr) 1644 if err != nil { 1645 return err 1646 } 1647 if err := tcpLn.Close(); err != nil { 1648 return err 1649 } 1650 1651 udpAddr := &net.UDPAddr{IP: ip, Port: port} 1652 udpLn, err := net.ListenUDP("udp", udpAddr) 1653 if err != nil { 1654 return err 1655 } 1656 1657 return udpLn.Close() 1658 } 1659 1660 func waitUntilPortIsFree(t *testing.T, m *memberlist.Memberlist) { 1661 t.Helper() 1662 1663 // wait until we know for certain that m1 is dead dead 1664 addr := m.Config().BindAddr 1665 port := m.Config().BindPort 1666 1667 retry(t, 15, 250*time.Millisecond, func(failf func(string, ...interface{})) { 1668 t.Helper() 1669 1670 if err := isPortFree(t, addr, port); err != nil { 1671 failf("%s port is not yet free", m.Config().Name) 1672 } 1673 }) 1674 } 1675 1676 // This test should follow the recommended upgrade guide: 1677 // https://www.consul.io/docs/agent/encryption.html#configuring-gossip-encryption-on-an-existing-cluster 1678 // 1679 // We will use two nodes for this: m0 and m1 1680 // 1681 // 0. Start with nodes without encryption. 1682 // 1. Set an encryption key and set GossipVerifyIncoming=false and GossipVerifyOutgoing=false to all nodes. 1683 // 2. Change GossipVerifyOutgoing=true to all nodes. 1684 // 3. Change GossipVerifyIncoming=true to all nodes. 1685 //func TestMemberlist_EncryptedGossipTransition(t *testing.T) { 1686 // // ensure these all get the same general set of customizations 1687 // pretty := make(map[string]string) // addr->shortName 1688 // newConfig := func(shortName string, addr string) *memberlist.Config { 1689 // t.Helper() 1690 // 1691 // conf := memberlist.DefaultLANConfig() 1692 // if addr == "" { 1693 // addr = getBindAddr().String() 1694 // } 1695 // conf.Name = addr 1696 // // conf.Name = shortName 1697 // conf.BindAddr = addr 1698 // conf.BindPort = 0 1699 // // Set the gossip interval fast enough to get a reasonable test, 1700 // // but slow enough to avoid "sendto: operation not permitted" 1701 // conf.GossipInterval = 100 * time.Millisecond 1702 // conf.Logger = log.New(os.Stderr, shortName, log.LstdFlags) 1703 // 1704 // pretty[conf.Name] = shortName 1705 // return conf 1706 // } 1707 // 1708 // var bindPort int 1709 // createOK := func(conf *memberlist.Config) *Memberlist { 1710 // t.Helper() 1711 // 1712 // if bindPort > 0 { 1713 // conf.BindPort = bindPort 1714 // } else { 1715 // // try a range of port numbers until something sticks 1716 // } 1717 // m, err := memberlist.Create(conf) 1718 // require.NoError(t, err) 1719 // 1720 // if bindPort == 0 { 1721 // bindPort = m.config.BindPort 1722 // } 1723 // return m 1724 // } 1725 // 1726 // joinOK := func(src, dst *Memberlist, numNodes int) { 1727 // t.Helper() 1728 // 1729 // srcName, dstName := pretty[src.Config().Name], pretty[dst.Config().Name] 1730 // t.Logf("Node %s[%s] joining node %s[%s]", srcName, src.Config().Name, dstName, dst.Config().Name) 1731 // 1732 // num, err := src.Join([]string{dst.Config().Name + "/" + dst.config.BindAddr}) 1733 // require.NoError(t, err) 1734 // require.Equal(t, 1, num) 1735 // 1736 // waitUntilSize(t, src, numNodes) 1737 // waitUntilSize(t, dst, numNodes) 1738 // 1739 // // Check the hosts 1740 // require.Equal(t, numNodes, len(src.Members()), "nodes: %v", src.Members()) 1741 // require.Equal(t, numNodes, src.estNumNodes(), "nodes: %v", src.Members()) 1742 // require.Equal(t, numNodes, len(dst.Members()), "nodes: %v", dst.Members()) 1743 // require.Equal(t, numNodes, dst.estNumNodes(), "nodes: %v", dst.Members()) 1744 // } 1745 // 1746 // leaveOK := func(m *Memberlist, why string) { 1747 // t.Helper() 1748 // 1749 // name := pretty[m.Config().Name] 1750 // t.Logf("Node %s[%s] is leaving %s", name, m.Config().Name, why) 1751 // err := m.Leave(time.Second) 1752 // require.NoError(t, err) 1753 // } 1754 // 1755 // shutdownOK := func(m *Memberlist, why string) { 1756 // t.Helper() 1757 // 1758 // name := pretty[m.Config().Name] 1759 // t.Logf("Node %s[%s] is shutting down %s", name, m.Config().Name, why) 1760 // err := m.Shutdown() 1761 // require.NoError(t, err) 1762 // 1763 // // Double check that it genuinely shutdown. 1764 // waitUntilPortIsFree(t, m) 1765 // } 1766 // 1767 // leaveAndShutdown := func(leaver, bystander *Memberlist, why string) { 1768 // t.Helper() 1769 // 1770 // leaveOK(leaver, why) 1771 // waitUntilSize(t, bystander, 1) 1772 // shutdownOK(leaver, why) 1773 // waitUntilSize(t, bystander, 1) 1774 // } 1775 // 1776 // // ==== STEP 0 ==== 1777 // 1778 // // Create a first cluster of 2 nodes with no gossip encryption settings. 1779 // conf0 := newConfig("m0", "") 1780 // m0 := memberlist.CreateOK(conf0) 1781 // defer m0.Shutdown() 1782 // 1783 // conf1 := newConfig("m1", "") 1784 // m1 := memberlist.CreateOK(conf1) 1785 // defer m1.Shutdown() 1786 // 1787 // joinOK(m1, m0, 2) 1788 // 1789 // t.Logf("==== STEP 0 complete: two node unencrypted cluster ====") 1790 // 1791 // // ==== STEP 1 ==== 1792 // 1793 // // Take down m0, upgrade to first stage of gossip transition settings. 1794 // leaveAndShutdown(m0, m1, "to upgrade gossip to first stage") 1795 // 1796 // // Resurrect the first node with the first stage of gossip transition settings. 1797 // conf0 = newConfig("m0", m0.config.BindAddr) 1798 // conf0.SecretKey = []byte("Hi16ZXu2lNCRVwtr20khAg==") 1799 // conf0.GossipVerifyIncoming = false 1800 // conf0.GossipVerifyOutgoing = false 1801 // m0 = createOK(conf0) 1802 // defer m0.Shutdown() 1803 // 1804 // // Join the second node. m1 has no encryption while m0 has encryption configured and 1805 // // can receive encrypted gossip, but will not encrypt outgoing gossip. 1806 // joinOK(m0, m1, 2) 1807 // 1808 // leaveAndShutdown(m1, m0, "to upgrade gossip to first stage") 1809 // 1810 // // Resurrect the second node with the first stage of gossip transition settings. 1811 // conf1 = newConfig("m1", m1.config.BindAddr) 1812 // conf1.SecretKey = []byte("Hi16ZXu2lNCRVwtr20khAg==") 1813 // conf1.GossipVerifyIncoming = false 1814 // conf1.GossipVerifyOutgoing = false 1815 // m1 = createOK(conf1) 1816 // defer m1.Shutdown() 1817 // 1818 // // Join the first node. Both have encryption configured and can receive 1819 // // encrypted gossip, but will not encrypt outgoing gossip. 1820 // joinOK(m1, m0, 2) 1821 // 1822 // t.Logf("==== STEP 1 complete: two node encryption-aware cluster ====") 1823 // 1824 // // ==== STEP 2 ==== 1825 // 1826 // // Take down m0, upgrade to second stage of gossip transition settings. 1827 // leaveAndShutdown(m0, m1, "to upgrade gossip to second stage") 1828 // 1829 // // Resurrect the first node with the second stage of gossip transition settings. 1830 // conf0 = newConfig("m0", m0.config.BindAddr) 1831 // conf0.SecretKey = []byte("Hi16ZXu2lNCRVwtr20khAg==") 1832 // conf0.GossipVerifyIncoming = false 1833 // m0 = createOK(conf0) 1834 // defer m0.Shutdown() 1835 // 1836 // // Join the second node. At this step, both nodes have encryption 1837 // // configured but only m0 is sending encrypted gossip. 1838 // joinOK(m0, m1, 2) 1839 // 1840 // leaveAndShutdown(m1, m0, "to upgrade gossip to second stage") 1841 // 1842 // // Resurrect the second node with the second stage of gossip transition settings. 1843 // conf1 = newConfig("m1", m1.config.BindAddr) 1844 // conf1.SecretKey = []byte("Hi16ZXu2lNCRVwtr20khAg==") 1845 // conf1.GossipVerifyIncoming = false 1846 // m1 = createOK(conf1) 1847 // defer m1.Shutdown() 1848 // 1849 // // Join the first node. Both have encryption configured and can receive 1850 // // encrypted gossip, and encrypt outgoing gossip, but aren't forcing 1851 // // incoming gossip is encrypted. 1852 // joinOK(m1, m0, 2) 1853 // 1854 // t.Logf("==== STEP 2 complete: two node encryption-aware cluster being encrypted ====") 1855 // 1856 // // ==== STEP 3 ==== 1857 // 1858 // // Take down m0, upgrade to final stage of gossip transition settings. 1859 // leaveAndShutdown(m0, m1, "to upgrade gossip to final stage") 1860 // 1861 // // Resurrect the first node with the final stage of gossip transition settings. 1862 // conf0 = newConfig("m0", m0.config.BindAddr) 1863 // conf0.SecretKey = []byte("Hi16ZXu2lNCRVwtr20khAg==") 1864 // m0 = createOK(conf0) 1865 // defer m0.Shutdown() 1866 // 1867 // // Join the second node. At this step, both nodes have encryption 1868 // // configured and are sending it, bu tonly m0 is verifying inbound gossip 1869 // // is encrypted. 1870 // joinOK(m0, m1, 2) 1871 // 1872 // leaveAndShutdown(m1, m0, "to upgrade gossip to final stage") 1873 // 1874 // // Resurrect the second node with the final stage of gossip transition settings. 1875 // conf1 = newConfig("m1", m1.config.BindAddr) 1876 // conf1.SecretKey = []byte("Hi16ZXu2lNCRVwtr20khAg==") 1877 // m1 = createOK(conf1) 1878 // defer m1.Shutdown() 1879 // 1880 // // Join the first node. Both have encryption configured and fully in 1881 // // enforcement. 1882 // joinOK(m1, m0, 2) 1883 // 1884 // t.Logf("==== STEP 3 complete: two node encrypted cluster locked down ====") 1885 //} 1886 1887 // Consul bug, rapid restart (before failure detection), 1888 // with an updated meta data. Should be at incarnation 1 for 1889 // both. 1890 // 1891 // This test is uncommented because it requires that either we 1892 // can rebind the socket (SO_REUSEPORT) which Go does not allow, 1893 // OR we must disable the address conflict checking in memberlist. 1894 // I just comment out that code to test this case. 1895 // 1896 //func TestMemberlist_Restart_delegateMeta_Update(t *testing.T) { 1897 // c1 := testConfig() 1898 // c2 := testConfig() 1899 // mock1 := &MockDelegate{meta: []byte("web")} 1900 // mock2 := &MockDelegate{meta: []byte("lb")} 1901 // c1.Delegate = mock1 1902 // c2.Delegate = mock2 1903 1904 // m1, err := memberlist.Create(c1) 1905 // if err != nil { 1906 // t.Fatalf("err: %s", err) 1907 // } 1908 // defer m1.Shutdown() 1909 1910 // m2, err := memberlist.Create(c2) 1911 // if err != nil { 1912 // t.Fatalf("err: %s", err) 1913 // } 1914 // defer m2.Shutdown() 1915 1916 // _, err = m1.Join([]string{c2.BindAddr}) 1917 // if err != nil { 1918 // t.Fatalf("err: %s", err) 1919 // } 1920 1921 // yield() 1922 1923 // // Recreate m1 with updated meta 1924 // m1.Shutdown() 1925 // c3 := testConfig() 1926 // c3.Name = c1.Name 1927 // c3.Delegate = mock1 1928 // c3.GossipInterval = time.Millisecond 1929 // mock1.meta = []byte("api") 1930 1931 // m1, err = Create(c3) 1932 // if err != nil { 1933 // t.Fatalf("err: %s", err) 1934 // } 1935 // defer m1.Shutdown() 1936 1937 // _, err = m1.Join([]string{c2.BindAddr}) 1938 // if err != nil { 1939 // t.Fatalf("err: %s", err) 1940 // } 1941 1942 // yield() 1943 // yield() 1944 1945 // // Check the updates have propagated 1946 // var roles map[string]string 1947 1948 // // Check the roles of members of m1 1949 // m1m := m1.Members() 1950 // if len(m1m) != 2 { 1951 // t.Fatalf("bad: %#v", m1m) 1952 // } 1953 1954 // roles = make(map[string]string) 1955 // for _, m := range m1m { 1956 // roles[m.Name] = string(m.Meta) 1957 // } 1958 1959 // if r := roles[c1.Name]; r != "api" { 1960 // t.Fatalf("bad role for %s: %s", c1.Name, r) 1961 // } 1962 1963 // if r := roles[c2.Name]; r != "lb" { 1964 // t.Fatalf("bad role for %s: %s", c2.Name, r) 1965 // } 1966 1967 // // Check the roles of members of m2 1968 // m2m := m2.Members() 1969 // if len(m2m) != 2 { 1970 // t.Fatalf("bad: %#v", m2m) 1971 // } 1972 1973 // roles = make(map[string]string) 1974 // for _, m := range m2m { 1975 // roles[m.Name] = string(m.Meta) 1976 // } 1977 1978 // if r := roles[c1.Name]; r != "api" { 1979 // t.Fatalf("bad role for %s: %s", c1.Name, r) 1980 // } 1981 1982 // if r := roles[c2.Name]; r != "lb" { 1983 // t.Fatalf("bad role for %s: %s", c2.Name, r) 1984 // } 1985 //} 1986 1987 // Failer is an interface compatible with testing.T. 1988 type Failer interface { 1989 // Log is called for the final test output 1990 Log(args ...interface{}) 1991 1992 // FailNow is called when the retrying is abandoned. 1993 FailNow() 1994 } 1995 1996 // R provides context for the retryer. 1997 type R struct { 1998 fail bool 1999 output []string 2000 } 2001 2002 func (r *R) FailNow() { 2003 r.fail = true 2004 runtime.Goexit() 2005 } 2006 2007 func (r *R) Fatal(args ...interface{}) { 2008 r.log(fmt.Sprint(args...)) 2009 r.FailNow() 2010 } 2011 2012 func (r *R) Fatalf(format string, args ...interface{}) { 2013 r.log(fmt.Sprintf(format, args...)) 2014 r.FailNow() 2015 } 2016 2017 func (r *R) Error(args ...interface{}) { 2018 r.log(fmt.Sprint(args...)) 2019 r.fail = true 2020 } 2021 2022 func (r *R) Errorf(format string, args ...interface{}) { 2023 r.log(fmt.Sprintf(format, args...)) 2024 r.fail = true 2025 } 2026 2027 func (r *R) Check(err error) { 2028 if err != nil { 2029 r.log(err.Error()) 2030 r.FailNow() 2031 } 2032 } 2033 2034 func (r *R) log(s string) { 2035 r.output = append(r.output, decorate(s)) 2036 } 2037 2038 func decorate(s string) string { 2039 _, file, line, ok := runtime.Caller(3) 2040 if ok { 2041 n := strings.LastIndex(file, "/") 2042 if n >= 0 { 2043 file = file[n+1:] 2044 } 2045 } else { 2046 file = "???" 2047 line = 1 2048 } 2049 return fmt.Sprintf("%s:%d: %s", file, line, s) 2050 } 2051 2052 func Run(t Failer, f func(r *R)) { 2053 run(DefaultFailer(), t, f) 2054 } 2055 2056 func RunWith(r Retryer, t Failer, f func(r *R)) { 2057 run(r, t, f) 2058 } 2059 2060 func dedup(a []string) string { 2061 if len(a) == 0 { 2062 return "" 2063 } 2064 m := map[string]int{} 2065 for _, s := range a { 2066 m[s] = m[s] + 1 2067 } 2068 var b bytes.Buffer 2069 for _, s := range a { 2070 if _, ok := m[s]; ok { 2071 b.WriteString(s) 2072 b.WriteRune('\n') 2073 delete(m, s) 2074 } 2075 } 2076 return b.String() 2077 } 2078 2079 func run(r Retryer, t Failer, f func(r *R)) { 2080 rr := &R{} 2081 fail := func() { 2082 out := dedup(rr.output) 2083 if out != "" { 2084 t.Log(out) 2085 } 2086 t.FailNow() 2087 } 2088 for r.NextOr(fail) { 2089 var wg sync.WaitGroup 2090 wg.Add(1) 2091 go func() { 2092 defer wg.Done() 2093 f(rr) 2094 }() 2095 wg.Wait() 2096 if rr.fail { 2097 rr.fail = false 2098 continue 2099 } 2100 break 2101 } 2102 } 2103 2104 // DefaultFailer provides default retry.Run() behavior for unit tests. 2105 func DefaultFailer() *Timer { 2106 return &Timer{Timeout: 7 * time.Second, Wait: 25 * time.Millisecond} 2107 } 2108 2109 // TwoSeconds repeats an operation for two seconds and waits 25ms in between. 2110 func TwoSeconds() *Timer { 2111 return &Timer{Timeout: 2 * time.Second, Wait: 25 * time.Millisecond} 2112 } 2113 2114 // ThreeTimes repeats an operation three times and waits 25ms in between. 2115 func ThreeTimes() *Counter { 2116 return &Counter{Count: 3, Wait: 25 * time.Millisecond} 2117 } 2118 2119 // Retryer provides an interface for repeating operations 2120 // until they succeed or an exit condition is met. 2121 type Retryer interface { 2122 // NextOr returns true if the operation should be repeated. 2123 // Otherwise, it calls fail and returns false. 2124 NextOr(fail func()) bool 2125 } 2126 2127 // Counter repeats an operation a given number of 2128 // times and waits between subsequent operations. 2129 type Counter struct { 2130 Count int 2131 Wait time.Duration 2132 2133 count int 2134 } 2135 2136 func (r *Counter) NextOr(fail func()) bool { 2137 if r.count == r.Count { 2138 fail() 2139 return false 2140 } 2141 if r.count > 0 { 2142 time.Sleep(r.Wait) 2143 } 2144 r.count++ 2145 return true 2146 } 2147 2148 // Timer repeats an operation for a given amount 2149 // of time and waits between subsequent operations. 2150 type Timer struct { 2151 Timeout time.Duration 2152 Wait time.Duration 2153 2154 // stop is the timeout deadline. 2155 // Set on the first invocation of Next(). 2156 stop time.Time 2157 } 2158 2159 func (r *Timer) NextOr(fail func()) bool { 2160 if r.stop.IsZero() { 2161 r.stop = time.Now().Add(r.Timeout) 2162 return true 2163 } 2164 if time.Now().After(r.stop) { 2165 fail() 2166 return false 2167 } 2168 time.Sleep(r.Wait) 2169 return true 2170 } 2171 2172 // delta defines the time band a test run should complete in. 2173 var delta = 25 * time.Millisecond 2174 2175 func TestRetryer(t *testing.T) { 2176 tests := []struct { 2177 desc string 2178 r Retryer 2179 }{ 2180 {"counter", &Counter{Count: 3, Wait: 100 * time.Millisecond}}, 2181 {"timer", &Timer{Timeout: 200 * time.Millisecond, Wait: 100 * time.Millisecond}}, 2182 } 2183 2184 for _, tt := range tests { 2185 t.Run(tt.desc, func(t *testing.T) { 2186 var iters, fails int 2187 fail := func() { fails++ } 2188 start := time.Now() 2189 for tt.r.NextOr(fail) { 2190 iters++ 2191 } 2192 dur := time.Since(start) 2193 if got, want := iters, 3; got != want { 2194 t.Fatalf("got %d retries want %d", got, want) 2195 } 2196 if got, want := fails, 1; got != want { 2197 t.Fatalf("got %d FailNow calls want %d", got, want) 2198 } 2199 // since the first iteration happens immediately 2200 // the retryer waits only twice for three iterations. 2201 // order of events: (true, (wait) true, (wait) true, false) 2202 if got, want := dur, 200*time.Millisecond; got < (want-delta) || got > (want+delta) { 2203 t.Fatalf("loop took %v want %v (+/- %v)", got, want, delta) 2204 } 2205 }) 2206 } 2207 } 2208 2209 func TestMemberlist_LocalNode(t *testing.T) { 2210 m, err := memberlist.Create(memberlist.DefaultWANConfig()) 2211 require.NoError(t, err) 2212 defer m.Shutdown() 2213 require.NotNil(t, m.LocalNode()) 2214 } 2215 2216 func TestMemberlist_SendBestEffort(t *testing.T) { 2217 m := GetMemberlist(t, nil) 2218 defer m.Shutdown() 2219 err := m.SendBestEffort(&memberlist.Node{ 2220 Name: "testNode", 2221 Addr: "127.0.0.1", 2222 Port: 7946, 2223 }, []byte("test message")) 2224 require.NoError(t, err) 2225 } 2226 2227 // userMsgHeader is used to encapsulate a userMsg 2228 type userMsgHeader struct { 2229 UserMsgLen int // Encodes the byte lengh of user state 2230 } 2231 2232 func TestMemberlist_SendReliable(t *testing.T) { 2233 node := &memberlist.Node{ 2234 Name: "testNode", 2235 Addr: "127.0.0.1", 2236 Port: 7946, 2237 } 2238 ctrl := gomock.NewController(t) 2239 defer ctrl.Finish() 2240 2241 //bufConn := bytes.NewBuffer(nil) 2242 //err := bufConn.WriteByte(byte(8)) 2243 //require.NoError(t, err) 2244 // 2245 //msg := []byte("test message") 2246 //header := userMsgHeader{UserMsgLen: len(msg)} 2247 //hd := codec.MsgpackHandle{} 2248 //enc := codec.NewEncoder(bufConn, &hd) 2249 //err = enc.Encode(&header) 2250 //require.NoError(t, err) 2251 //_, err = bufConn.Write(msg) 2252 //require.NoError(t, err) 2253 2254 conn := memmock.NewMockConn(ctrl) 2255 conn. 2256 EXPECT(). 2257 Write(gomock.Any()). 2258 AnyTimes(). 2259 Return(26, nil) 2260 conn. 2261 EXPECT(). 2262 Close(). 2263 AnyTimes(). 2264 Return(nil) 2265 2266 nat := memmock.NewMockNodeAwareTransport(ctrl) 2267 nat. 2268 EXPECT(). 2269 DialAddressTimeout(node.FullAddress(), gomock.Any()). 2270 AnyTimes(). 2271 Return(conn, nil) 2272 nat. 2273 EXPECT(). 2274 FinalAdvertiseAddr(gomock.Any(), gomock.Any()). 2275 AnyTimes(). 2276 Return("localhost", 7946, nil) 2277 nat. 2278 EXPECT(). 2279 PacketCh(). 2280 AnyTimes(). 2281 Return(make(chan *memberlist.Packet)) 2282 nat. 2283 EXPECT(). 2284 StreamCh(). 2285 AnyTimes(). 2286 Return(make(<-chan net.Conn)) 2287 nat. 2288 EXPECT(). 2289 Shutdown(). 2290 AnyTimes(). 2291 Return(nil) 2292 2293 m := GetMemberlist(t, func(c *memberlist.Config) { 2294 c.Transport = nat 2295 c.EnableCompression = false 2296 }) 2297 defer m.Shutdown() 2298 err := m.SendReliable(node, []byte("test message")) 2299 require.NoError(t, err) 2300 } 2301 2302 func TestMemberlist_SendReliable_Fail(t *testing.T) { 2303 m := GetMemberlist(t, nil) 2304 defer m.Shutdown() 2305 err := m.SendReliable(&memberlist.Node{ 2306 Name: "testNode", 2307 Addr: "127.0.0.1", 2308 Port: 7946, 2309 }, []byte("test message")) 2310 require.Error(t, err) 2311 } 2312 2313 func TestMemberlist_SendReliable_Fail2(t *testing.T) { 2314 node := &memberlist.Node{ 2315 Name: "testNode", 2316 Addr: "127.0.0.1", 2317 Port: 7946, 2318 } 2319 ctrl := gomock.NewController(t) 2320 defer ctrl.Finish() 2321 conn := memmock.NewMockConn(ctrl) 2322 conn. 2323 EXPECT(). 2324 Write(gomock.Any()). 2325 AnyTimes(). 2326 Return(12, nil) 2327 conn. 2328 EXPECT(). 2329 Close(). 2330 AnyTimes(). 2331 Return(nil) 2332 2333 nat := memmock.NewMockNodeAwareTransport(ctrl) 2334 nat. 2335 EXPECT(). 2336 DialAddressTimeout(node.FullAddress(), gomock.Any()). 2337 AnyTimes(). 2338 Return(conn, nil) 2339 nat. 2340 EXPECT(). 2341 FinalAdvertiseAddr(gomock.Any(), gomock.Any()). 2342 AnyTimes(). 2343 Return("localhost", 7946, nil) 2344 nat. 2345 EXPECT(). 2346 PacketCh(). 2347 AnyTimes(). 2348 Return(make(chan *memberlist.Packet)) 2349 nat. 2350 EXPECT(). 2351 StreamCh(). 2352 AnyTimes(). 2353 Return(make(<-chan net.Conn)) 2354 nat. 2355 EXPECT(). 2356 Shutdown(). 2357 AnyTimes(). 2358 Return(nil) 2359 2360 m := GetMemberlist(t, func(c *memberlist.Config) { 2361 c.Transport = nat 2362 }) 2363 defer m.Shutdown() 2364 2365 err := m.SendReliable(node, []byte("test message")) 2366 require.Error(t, err) 2367 }