github.imxd.top/hashicorp/consul@v1.4.5/agent/router/manager_test.go (about)

     1  package router_test
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"math/rand"
     7  	"net"
     8  	"os"
     9  	"strings"
    10  	"testing"
    11  
    12  	"github.com/hashicorp/consul/agent/metadata"
    13  	"github.com/hashicorp/consul/agent/router"
    14  )
    15  
    16  type fauxAddr struct {
    17  	addr string
    18  }
    19  
    20  func (a *fauxAddr) Network() string {
    21  	return "faux"
    22  }
    23  
    24  func (a *fauxAddr) String() string {
    25  	return a.addr
    26  }
    27  
    28  type fauxConnPool struct {
    29  	// failPct between 0.0 and 1.0 == pct of time a Ping should fail.
    30  	failPct float64
    31  
    32  	// failAddr fail whenever we see this address.
    33  	failAddr net.Addr
    34  }
    35  
    36  func (cp *fauxConnPool) Ping(dc string, addr net.Addr, version int, useTLS bool) (bool, error) {
    37  	var success bool
    38  
    39  	successProb := rand.Float64()
    40  	if successProb > cp.failPct {
    41  		success = true
    42  	}
    43  
    44  	if cp.failAddr != nil && addr.String() == cp.failAddr.String() {
    45  		success = false
    46  	}
    47  
    48  	return success, nil
    49  }
    50  
    51  type fauxSerf struct {
    52  }
    53  
    54  func (s *fauxSerf) NumNodes() int {
    55  	return 16384
    56  }
    57  
    58  func testManager() (m *router.Manager) {
    59  	logger := log.New(os.Stderr, "", log.LstdFlags)
    60  	shutdownCh := make(chan struct{})
    61  	m = router.New(logger, shutdownCh, &fauxSerf{}, &fauxConnPool{})
    62  	return m
    63  }
    64  
    65  func testManagerFailProb(failPct float64) (m *router.Manager) {
    66  	logger := log.New(os.Stderr, "", log.LstdFlags)
    67  	shutdownCh := make(chan struct{})
    68  	m = router.New(logger, shutdownCh, &fauxSerf{}, &fauxConnPool{failPct: failPct})
    69  	return m
    70  }
    71  
    72  func testManagerFailAddr(failAddr net.Addr) (m *router.Manager) {
    73  	logger := log.New(os.Stderr, "", log.LstdFlags)
    74  	shutdownCh := make(chan struct{})
    75  	m = router.New(logger, shutdownCh, &fauxSerf{}, &fauxConnPool{failAddr: failAddr})
    76  	return m
    77  }
    78  
    79  // func (m *Manager) AddServer(server *metadata.Server) {
    80  func TestServers_AddServer(t *testing.T) {
    81  	m := testManager()
    82  	var num int
    83  	num = m.NumServers()
    84  	if num != 0 {
    85  		t.Fatalf("Expected zero servers to start")
    86  	}
    87  
    88  	s1 := &metadata.Server{Name: "s1"}
    89  	m.AddServer(s1)
    90  	num = m.NumServers()
    91  	if num != 1 {
    92  		t.Fatalf("Expected one server")
    93  	}
    94  
    95  	m.AddServer(s1)
    96  	num = m.NumServers()
    97  	if num != 1 {
    98  		t.Fatalf("Expected one server (still)")
    99  	}
   100  
   101  	s2 := &metadata.Server{Name: "s2"}
   102  	m.AddServer(s2)
   103  	num = m.NumServers()
   104  	if num != 2 {
   105  		t.Fatalf("Expected two servers")
   106  	}
   107  }
   108  
   109  // func (m *Manager) IsOffline() bool {
   110  func TestServers_IsOffline(t *testing.T) {
   111  	m := testManager()
   112  	if !m.IsOffline() {
   113  		t.Fatalf("bad")
   114  	}
   115  
   116  	s1 := &metadata.Server{Name: "s1"}
   117  	m.AddServer(s1)
   118  	if m.IsOffline() {
   119  		t.Fatalf("bad")
   120  	}
   121  	m.RebalanceServers()
   122  	if m.IsOffline() {
   123  		t.Fatalf("bad")
   124  	}
   125  	m.RemoveServer(s1)
   126  	m.RebalanceServers()
   127  	if !m.IsOffline() {
   128  		t.Fatalf("bad")
   129  	}
   130  
   131  	const failPct = 0.5
   132  	m = testManagerFailProb(failPct)
   133  	m.AddServer(s1)
   134  	var on, off int
   135  	for i := 0; i < 100; i++ {
   136  		m.RebalanceServers()
   137  		if m.IsOffline() {
   138  			off++
   139  		} else {
   140  			on++
   141  		}
   142  	}
   143  	if on == 0 || off == 0 {
   144  		t.Fatalf("bad: %d %d", on, off)
   145  	}
   146  }
   147  
   148  // func (m *Manager) FindServer() (server *metadata.Server) {
   149  func TestServers_FindServer(t *testing.T) {
   150  	m := testManager()
   151  
   152  	if m.FindServer() != nil {
   153  		t.Fatalf("Expected nil return")
   154  	}
   155  
   156  	m.AddServer(&metadata.Server{Name: "s1"})
   157  	if m.NumServers() != 1 {
   158  		t.Fatalf("Expected one server")
   159  	}
   160  
   161  	s1 := m.FindServer()
   162  	if s1 == nil {
   163  		t.Fatalf("Expected non-nil server")
   164  	}
   165  	if s1.Name != "s1" {
   166  		t.Fatalf("Expected s1 server")
   167  	}
   168  
   169  	s1 = m.FindServer()
   170  	if s1 == nil || s1.Name != "s1" {
   171  		t.Fatalf("Expected s1 server (still)")
   172  	}
   173  
   174  	m.AddServer(&metadata.Server{Name: "s2"})
   175  	if m.NumServers() != 2 {
   176  		t.Fatalf("Expected two servers")
   177  	}
   178  	s1 = m.FindServer()
   179  	if s1 == nil || s1.Name != "s1" {
   180  		t.Fatalf("Expected s1 server (still)")
   181  	}
   182  
   183  	m.NotifyFailedServer(s1)
   184  	s2 := m.FindServer()
   185  	if s2 == nil || s2.Name != "s2" {
   186  		t.Fatalf("Expected s2 server")
   187  	}
   188  
   189  	m.NotifyFailedServer(s2)
   190  	s1 = m.FindServer()
   191  	if s1 == nil || s1.Name != "s1" {
   192  		t.Fatalf("Expected s1 server")
   193  	}
   194  }
   195  
   196  // func New(logger *log.Logger, shutdownCh chan struct{}) (m *Manager) {
   197  func TestServers_New(t *testing.T) {
   198  	logger := log.New(os.Stderr, "", log.LstdFlags)
   199  	shutdownCh := make(chan struct{})
   200  	m := router.New(logger, shutdownCh, &fauxSerf{}, &fauxConnPool{})
   201  	if m == nil {
   202  		t.Fatalf("Manager nil")
   203  	}
   204  }
   205  
   206  // func (m *Manager) NotifyFailedServer(server *metadata.Server) {
   207  func TestServers_NotifyFailedServer(t *testing.T) {
   208  	m := testManager()
   209  
   210  	if m.NumServers() != 0 {
   211  		t.Fatalf("Expected zero servers to start")
   212  	}
   213  
   214  	s1 := &metadata.Server{Name: "s1"}
   215  	s2 := &metadata.Server{Name: "s2"}
   216  
   217  	// Try notifying for a server that is not managed by Manager
   218  	m.NotifyFailedServer(s1)
   219  	if m.NumServers() != 0 {
   220  		t.Fatalf("Expected zero servers to start")
   221  	}
   222  	m.AddServer(s1)
   223  
   224  	// Test again w/ a server not in the list
   225  	m.NotifyFailedServer(s2)
   226  	if m.NumServers() != 1 {
   227  		t.Fatalf("Expected one server")
   228  	}
   229  
   230  	m.AddServer(s2)
   231  	if m.NumServers() != 2 {
   232  		t.Fatalf("Expected two servers")
   233  	}
   234  
   235  	s1 = m.FindServer()
   236  	if s1 == nil || s1.Name != "s1" {
   237  		t.Fatalf("Expected s1 server")
   238  	}
   239  
   240  	m.NotifyFailedServer(s2)
   241  	s1 = m.FindServer()
   242  	if s1 == nil || s1.Name != "s1" {
   243  		t.Fatalf("Expected s1 server (still)")
   244  	}
   245  
   246  	m.NotifyFailedServer(s1)
   247  	s2 = m.FindServer()
   248  	if s2 == nil || s2.Name != "s2" {
   249  		t.Fatalf("Expected s2 server")
   250  	}
   251  
   252  	m.NotifyFailedServer(s2)
   253  	s1 = m.FindServer()
   254  	if s1 == nil || s1.Name != "s1" {
   255  		t.Fatalf("Expected s1 server")
   256  	}
   257  }
   258  
   259  // func (m *Manager) NumServers() (numServers int) {
   260  func TestServers_NumServers(t *testing.T) {
   261  	m := testManager()
   262  	var num int
   263  	num = m.NumServers()
   264  	if num != 0 {
   265  		t.Fatalf("Expected zero servers to start")
   266  	}
   267  
   268  	s := &metadata.Server{}
   269  	m.AddServer(s)
   270  	num = m.NumServers()
   271  	if num != 1 {
   272  		t.Fatalf("Expected one server after AddServer")
   273  	}
   274  }
   275  
   276  // func (m *Manager) RebalanceServers() {
   277  func TestServers_RebalanceServers(t *testing.T) {
   278  	const failPct = 0.5
   279  	m := testManagerFailProb(failPct)
   280  	const maxServers = 100
   281  	const numShuffleTests = 100
   282  	const uniquePassRate = 0.5
   283  
   284  	// Make a huge list of nodes.
   285  	for i := 0; i < maxServers; i++ {
   286  		nodeName := fmt.Sprintf("s%02d", i)
   287  		m.AddServer(&metadata.Server{Name: nodeName})
   288  	}
   289  
   290  	// Keep track of how many unique shuffles we get.
   291  	uniques := make(map[string]struct{}, maxServers)
   292  	for i := 0; i < numShuffleTests; i++ {
   293  		m.RebalanceServers()
   294  
   295  		var names []string
   296  		for j := 0; j < maxServers; j++ {
   297  			server := m.FindServer()
   298  			m.NotifyFailedServer(server)
   299  			names = append(names, server.Name)
   300  		}
   301  		key := strings.Join(names, "|")
   302  		uniques[key] = struct{}{}
   303  	}
   304  
   305  	// We have to allow for the fact that there won't always be a unique
   306  	// shuffle each pass, so we just look for smell here without the test
   307  	// being flaky.
   308  	if len(uniques) < int(maxServers*uniquePassRate) {
   309  		t.Fatalf("unique shuffle ratio too low: %d/%d", len(uniques), maxServers)
   310  	}
   311  }
   312  
   313  func TestServers_RebalanceServers_AvoidFailed(t *testing.T) {
   314  	// Do a large number of rebalances with one failed server in the
   315  	// list and make sure we never have that one selected afterwards.
   316  	// This was added when fixing #3463, when we were just doing the
   317  	// shuffle and not actually cycling servers. We do a large number
   318  	// of trials with a small number of servers to try to make sure
   319  	// the shuffle alone won't give the right answer.
   320  	servers := []*metadata.Server{
   321  		&metadata.Server{Name: "s1", Addr: &fauxAddr{"s1"}},
   322  		&metadata.Server{Name: "s2", Addr: &fauxAddr{"s2"}},
   323  		&metadata.Server{Name: "s3", Addr: &fauxAddr{"s3"}},
   324  	}
   325  	for i := 0; i < 100; i++ {
   326  		m := testManagerFailAddr(&fauxAddr{"s2"})
   327  		for _, s := range servers {
   328  			m.AddServer(s)
   329  		}
   330  
   331  		m.RebalanceServers()
   332  		if front := m.FindServer().Name; front == "s2" {
   333  			t.Fatalf("should have avoided the failed server")
   334  		}
   335  	}
   336  }
   337  
   338  // func (m *Manager) RemoveServer(server *metadata.Server) {
   339  func TestManager_RemoveServer(t *testing.T) {
   340  	const nodeNameFmt = "s%02d"
   341  	m := testManager()
   342  
   343  	if m.NumServers() != 0 {
   344  		t.Fatalf("Expected zero servers to start")
   345  	}
   346  
   347  	// Test removing server before its added
   348  	nodeName := fmt.Sprintf(nodeNameFmt, 1)
   349  	s1 := &metadata.Server{Name: nodeName}
   350  	m.RemoveServer(s1)
   351  	m.AddServer(s1)
   352  
   353  	nodeName = fmt.Sprintf(nodeNameFmt, 2)
   354  	s2 := &metadata.Server{Name: nodeName}
   355  	m.RemoveServer(s2)
   356  	m.AddServer(s2)
   357  
   358  	const maxServers = 19
   359  	servers := make([]*metadata.Server, maxServers)
   360  	// Already added two servers above
   361  	for i := maxServers; i > 2; i-- {
   362  		nodeName := fmt.Sprintf(nodeNameFmt, i)
   363  		server := &metadata.Server{Name: nodeName}
   364  		servers = append(servers, server)
   365  		m.AddServer(server)
   366  	}
   367  	if m.NumServers() != maxServers {
   368  		t.Fatalf("Expected %d servers, received %d", maxServers, m.NumServers())
   369  	}
   370  
   371  	m.RebalanceServers()
   372  
   373  	if m.NumServers() != maxServers {
   374  		t.Fatalf("Expected %d servers, received %d", maxServers, m.NumServers())
   375  	}
   376  
   377  	findServer := func(server *metadata.Server) bool {
   378  		for i := m.NumServers(); i > 0; i-- {
   379  			s := m.FindServer()
   380  			if s == server {
   381  				return true
   382  			}
   383  		}
   384  		return false
   385  	}
   386  
   387  	expectedNumServers := maxServers
   388  	removedServers := make([]*metadata.Server, 0, maxServers)
   389  
   390  	// Remove servers from the front of the list
   391  	for i := 3; i > 0; i-- {
   392  		server := m.FindServer()
   393  		if server == nil {
   394  			t.Fatalf("FindServer returned nil")
   395  		}
   396  		m.RemoveServer(server)
   397  		expectedNumServers--
   398  		if m.NumServers() != expectedNumServers {
   399  			t.Fatalf("Expected %d servers (got %d)", expectedNumServers, m.NumServers())
   400  		}
   401  		if findServer(server) == true {
   402  			t.Fatalf("Did not expect to find server %s after removal from the front", server.Name)
   403  		}
   404  		removedServers = append(removedServers, server)
   405  	}
   406  
   407  	// Remove server from the end of the list
   408  	for i := 3; i > 0; i-- {
   409  		server := m.FindServer()
   410  		m.NotifyFailedServer(server)
   411  		m.RemoveServer(server)
   412  		expectedNumServers--
   413  		if m.NumServers() != expectedNumServers {
   414  			t.Fatalf("Expected %d servers (got %d)", expectedNumServers, m.NumServers())
   415  		}
   416  		if findServer(server) == true {
   417  			t.Fatalf("Did not expect to find server %s", server.Name)
   418  		}
   419  		removedServers = append(removedServers, server)
   420  	}
   421  
   422  	// Remove server from the middle of the list
   423  	for i := 3; i > 0; i-- {
   424  		server := m.FindServer()
   425  		m.NotifyFailedServer(server)
   426  		server2 := m.FindServer()
   427  		m.NotifyFailedServer(server2) // server2 now at end of the list
   428  
   429  		m.RemoveServer(server)
   430  		expectedNumServers--
   431  		if m.NumServers() != expectedNumServers {
   432  			t.Fatalf("Expected %d servers (got %d)", expectedNumServers, m.NumServers())
   433  		}
   434  		if findServer(server) == true {
   435  			t.Fatalf("Did not expect to find server %s", server.Name)
   436  		}
   437  		removedServers = append(removedServers, server)
   438  	}
   439  
   440  	if m.NumServers()+len(removedServers) != maxServers {
   441  		t.Fatalf("Expected %d+%d=%d servers", m.NumServers(), len(removedServers), maxServers)
   442  	}
   443  
   444  	// Drain the remaining servers from the middle
   445  	for i := m.NumServers(); i > 0; i-- {
   446  		server := m.FindServer()
   447  		m.NotifyFailedServer(server)
   448  		server2 := m.FindServer()
   449  		m.NotifyFailedServer(server2) // server2 now at end of the list
   450  		m.RemoveServer(server)
   451  		removedServers = append(removedServers, server)
   452  	}
   453  
   454  	if m.NumServers() != 0 {
   455  		t.Fatalf("Expected an empty server list")
   456  	}
   457  	if len(removedServers) != maxServers {
   458  		t.Fatalf("Expected all servers to be in removed server list")
   459  	}
   460  }
   461  
   462  // func (m *Manager) Start() {