github.com/mattyr/nomad@v0.3.3-0.20160919021406-3485a065154a/client/rpcproxy/rpcproxy_test.go (about) 1 package rpcproxy 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "fmt" 7 "log" 8 "math/rand" 9 "net" 10 "os" 11 "strings" 12 "sync/atomic" 13 "testing" 14 "time" 15 ) 16 17 const ( 18 ipv4len = 4 19 nodeNameFmt = "s%03d" 20 defaultNomadPort = "4647" 21 22 // Poached from RFC2544 and RFC3330 23 testingNetworkCidr = "198.18.0.0/15" 24 testingNetworkUint32 = 3323068416 25 ) 26 27 var ( 28 localLogger *log.Logger 29 localLogBuffer *bytes.Buffer 30 serverCount uint32 31 validIp uint32 32 ) 33 34 func init() { 35 localLogBuffer = new(bytes.Buffer) 36 localLogger = log.New(localLogBuffer, "", 0) 37 } 38 39 func makeServerEndpointName() string { 40 serverNum := atomic.AddUint32(&serverCount, 1) 41 validIp := testingNetworkUint32 + serverNum 42 ipv4 := make(net.IP, ipv4len) 43 binary.BigEndian.PutUint32(ipv4, validIp) 44 return net.JoinHostPort(ipv4.String(), defaultNomadPort) 45 } 46 47 func GetBufferedLogger() *log.Logger { 48 return localLogger 49 } 50 51 type fauxConnPool struct { 52 // failPct between 0.0 and 1.0 == pct of time a Ping should fail 53 failPct float64 54 } 55 56 func (cp *fauxConnPool) PingNomadServer(region string, majorVersion int, s *ServerEndpoint) (bool, error) { 57 var success bool 58 successProb := rand.Float64() 59 if successProb > cp.failPct { 60 success = true 61 } 62 return success, nil 63 } 64 65 type fauxSerf struct { 66 datacenter string 67 numNodes int 68 region string 69 rpcMinorVersion int 70 rpcMajorVersion int 71 } 72 73 func (s *fauxSerf) NumNodes() int { 74 return s.numNodes 75 } 76 77 func (s *fauxSerf) Region() string { 78 return s.region 79 } 80 81 func (s *fauxSerf) Datacenter() string { 82 return s.datacenter 83 } 84 85 func (s *fauxSerf) RPCMajorVersion() int { 86 return s.rpcMajorVersion 87 } 88 89 func (s *fauxSerf) RPCMinorVersion() int { 90 return s.rpcMinorVersion 91 } 92 93 func testRPCProxy() (p *RPCProxy) { 94 logger := GetBufferedLogger() 95 logger = log.New(os.Stderr, "", log.LstdFlags) 96 shutdownCh := make(chan struct{}) 97 p = NewRPCProxy(logger, shutdownCh, &fauxSerf{numNodes: 16384}, &fauxConnPool{}) 98 return p 99 } 100 101 func testRPCProxyFailProb(failPct float64) (p *RPCProxy) { 102 logger := GetBufferedLogger() 103 logger = log.New(os.Stderr, "", log.LstdFlags) 104 shutdownCh := make(chan struct{}) 105 p = NewRPCProxy(logger, shutdownCh, &fauxSerf{}, &fauxConnPool{failPct: failPct}) 106 return p 107 } 108 109 // func (p *RPCProxy) AddPrimaryServer(server *ServerEndpoint) { 110 func TestRPCProxy_AddPrimaryServer(t *testing.T) { 111 p := testRPCProxy() 112 var num int 113 num = p.NumServers() 114 if num != 0 { 115 t.Fatalf("Expected zero servers to start") 116 } 117 118 s1Endpoint := makeServerEndpointName() 119 s1 := p.AddPrimaryServer(s1Endpoint) 120 num = p.NumServers() 121 if num != 1 { 122 t.Fatalf("Expected one server") 123 } 124 if s1 == nil { 125 t.Fatalf("bad") 126 } 127 if s1.Name != s1Endpoint { 128 t.Fatalf("bad") 129 } 130 131 s1 = p.AddPrimaryServer(s1Endpoint) 132 num = p.NumServers() 133 if num != 1 { 134 t.Fatalf("Expected one server (still)") 135 } 136 if s1 == nil { 137 t.Fatalf("bad") 138 } 139 if s1.Name != s1Endpoint { 140 t.Fatalf("bad") 141 } 142 143 s2Endpoint := makeServerEndpointName() 144 s2 := p.AddPrimaryServer(s2Endpoint) 145 num = p.NumServers() 146 if num != 2 { 147 t.Fatalf("Expected two servers") 148 } 149 if s2 == nil { 150 t.Fatalf("bad") 151 } 152 if s2.Name != s2Endpoint { 153 t.Fatalf("bad") 154 } 155 } 156 157 // func (p *RPCProxy) FindServer() (server *ServerEndpoint) { 158 func TestRPCProxy_FindServer(t *testing.T) { 159 p := testRPCProxy() 160 161 if p.FindServer() != nil { 162 t.Fatalf("Expected nil return") 163 } 164 165 s1Endpoint := makeServerEndpointName() 166 p.AddPrimaryServer(s1Endpoint) 167 if p.NumServers() != 1 { 168 t.Fatalf("Expected one server") 169 } 170 171 s1 := p.FindServer() 172 if s1 == nil { 173 t.Fatalf("Expected non-nil server") 174 } 175 if s1.Name != s1Endpoint { 176 t.Fatalf("Expected s1 server") 177 } 178 179 s1 = p.FindServer() 180 if s1 == nil || s1.Name != s1Endpoint { 181 t.Fatalf("Expected s1 server (still)") 182 } 183 184 s2Endpoint := makeServerEndpointName() 185 p.AddPrimaryServer(s2Endpoint) 186 if p.NumServers() != 2 { 187 t.Fatalf("Expected two servers") 188 } 189 s1 = p.FindServer() 190 if s1 == nil || s1.Name != s1Endpoint { 191 t.Fatalf("Expected s1 server (still)") 192 } 193 194 p.NotifyFailedServer(s1) 195 s2 := p.FindServer() 196 if s2 == nil || s2.Name != s2Endpoint { 197 t.Fatalf("Expected s2 server") 198 } 199 200 p.NotifyFailedServer(s2) 201 s1 = p.FindServer() 202 if s1 == nil || s1.Name != s1Endpoint { 203 t.Fatalf("Expected s1 server") 204 } 205 } 206 207 // func New(logger *log.Logger, shutdownCh chan struct{}) (p *RPCProxy) { 208 func TestRPCProxy_New(t *testing.T) { 209 logger := GetBufferedLogger() 210 logger = log.New(os.Stderr, "", log.LstdFlags) 211 shutdownCh := make(chan struct{}) 212 p := NewRPCProxy(logger, shutdownCh, &fauxSerf{}, &fauxConnPool{}) 213 if p == nil { 214 t.Fatalf("RPCProxy nil") 215 } 216 } 217 218 // func (p *RPCProxy) NotifyFailedServer(server *ServerEndpoint) { 219 func TestRPCProxy_NotifyFailedServer(t *testing.T) { 220 p := testRPCProxy() 221 222 if p.NumServers() != 0 { 223 t.Fatalf("Expected zero servers to start") 224 } 225 226 // Try notifying for a server that is not managed by RPCProxy 227 s1Endpoint := makeServerEndpointName() 228 s1 := p.AddPrimaryServer(s1Endpoint) 229 if s1 == nil { 230 t.Fatalf("bad") 231 } 232 if p.NumServers() != 1 { 233 t.Fatalf("bad") 234 } 235 p.RemoveServer(s1) 236 if p.NumServers() != 0 { 237 t.Fatalf("bad") 238 } 239 p.NotifyFailedServer(s1) 240 s1 = p.AddPrimaryServer(s1Endpoint) 241 242 // Test again w/ a server not in the list 243 s2Endpoint := makeServerEndpointName() 244 s2 := p.AddPrimaryServer(s2Endpoint) 245 if s2 == nil { 246 t.Fatalf("bad") 247 } 248 if p.NumServers() != 2 { 249 t.Fatalf("bad") 250 } 251 p.RemoveServer(s2) 252 if p.NumServers() != 1 { 253 t.Fatalf("bad") 254 } 255 p.NotifyFailedServer(s2) 256 if p.NumServers() != 1 { 257 t.Fatalf("Expected one server") 258 } 259 260 // Re-add s2 so there are two servers in the RPCProxy server list 261 s2 = p.AddPrimaryServer(s2Endpoint) 262 if p.NumServers() != 2 { 263 t.Fatalf("Expected two servers") 264 } 265 266 // Find the first server, it should be s1 267 s1 = p.FindServer() 268 if s1 == nil || s1.Name != s1Endpoint { 269 t.Fatalf("Expected s1 server") 270 } 271 272 // Notify s2 as failed, s1 should still be first 273 p.NotifyFailedServer(s2) 274 s1 = p.FindServer() 275 if s1 == nil || s1.Name != s1Endpoint { 276 t.Fatalf("Expected s1 server (still)") 277 } 278 279 // Fail s1, s2 should be first 280 p.NotifyFailedServer(s1) 281 s2 = p.FindServer() 282 if s2 == nil || s2.Name != s2Endpoint { 283 t.Fatalf("Expected s2 server") 284 } 285 286 // Fail s2, s1 should be first 287 p.NotifyFailedServer(s2) 288 s1 = p.FindServer() 289 if s1 == nil || s1.Name != s1Endpoint { 290 t.Fatalf("Expected s1 server") 291 } 292 } 293 294 // func (p *RPCProxy) NumServers() (numServers int) { 295 func TestRPCProxy_NumServers(t *testing.T) { 296 p := testRPCProxy() 297 const maxNumServers = 100 298 serverList := make([]*ServerEndpoint, 0, maxNumServers) 299 300 // Add some servers 301 for i := 0; i < maxNumServers; i++ { 302 num := p.NumServers() 303 if num != i { 304 t.Fatalf("%d: Expected %d servers", i, num) 305 } 306 serverName := makeServerEndpointName() 307 s := p.AddPrimaryServer(serverName) 308 if s == nil { 309 t.Fatalf("Expected server from %+q", serverName) 310 } 311 serverList = append(serverList, s) 312 313 num = p.NumServers() 314 if num != i+1 { 315 t.Fatalf("%d: Expected %d servers", i, num+1) 316 } 317 } 318 319 // Remove some servers 320 for i := maxNumServers; i > 0; i-- { 321 num := p.NumServers() 322 if num != i { 323 t.Fatalf("%d: Expected %d servers", i, num) 324 } 325 p.RemoveServer(serverList[i-1]) 326 num = p.NumServers() 327 if num != i-1 { 328 t.Fatalf("%d: Expected %d servers", i, num-1) 329 } 330 } 331 } 332 333 // func (p *RPCProxy) RebalanceServers() { 334 func TestRPCProxy_RebalanceServers(t *testing.T) { 335 const failPct = 0.5 336 p := testRPCProxyFailProb(failPct) 337 const maxServers = 100 338 const numShuffleTests = 100 339 const uniquePassRate = 0.5 340 341 // Make a huge list of nodes. 342 for i := 0; i < maxServers; i++ { 343 p.AddPrimaryServer(makeServerEndpointName()) 344 } 345 346 // Keep track of how many unique shuffles we get. 347 uniques := make(map[string]struct{}, maxServers) 348 for i := 0; i < numShuffleTests; i++ { 349 p.RebalanceServers() 350 351 var names []string 352 for j := 0; j < maxServers; j++ { 353 server := p.FindServer() 354 p.NotifyFailedServer(server) 355 names = append(names, server.Name) 356 } 357 key := strings.Join(names, "|") 358 uniques[key] = struct{}{} 359 } 360 361 // We have to allow for the fact that there won't always be a unique 362 // shuffle each pass, so we just look for smell here without the test 363 // being flaky. 364 if len(uniques) < int(maxServers*uniquePassRate) { 365 t.Fatalf("unique shuffle ratio too low: %d/%d", len(uniques), maxServers) 366 } 367 } 368 369 // func (p *RPCProxy) RemoveServer(server *ServerEndpoint) { 370 func TestRPCProxy_RemoveServer(t *testing.T) { 371 p := testRPCProxy() 372 if p.NumServers() != 0 { 373 t.Fatalf("Expected zero servers to start") 374 } 375 376 // Test removing server before its added 377 s1Endpoint := makeServerEndpointName() 378 s1 := p.AddPrimaryServer(s1Endpoint) 379 if p.NumServers() != 1 { 380 t.Fatalf("bad") 381 } 382 if s1 == nil || s1.Name != s1Endpoint { 383 t.Fatalf("Expected s1 server: %+q", s1.Name) 384 } 385 s1 = p.FindServer() 386 if s1 == nil || s1.Name != s1Endpoint { 387 t.Fatalf("Expected s1 server: %+q", s1.Name) 388 } 389 p.RemoveServer(s1) 390 if p.NumServers() != 0 { 391 t.Fatalf("bad") 392 } 393 // Remove it a second time now that it doesn't exist 394 p.RemoveServer(s1) 395 if p.NumServers() != 0 { 396 t.Fatalf("bad") 397 } 398 p.AddPrimaryServer(s1Endpoint) 399 if p.NumServers() != 1 { 400 t.Fatalf("bad") 401 } 402 403 s2Endpoint := makeServerEndpointName() 404 s2 := p.AddPrimaryServer(s2Endpoint) 405 if p.NumServers() != 2 { 406 t.Fatalf("bad") 407 } 408 if s2 == nil || s2.Name != s2Endpoint { 409 t.Fatalf("Expected s2 server: %+q", s2.Name) 410 } 411 s1 = p.FindServer() 412 if s1 == nil || s1.Name != s1Endpoint { 413 t.Fatalf("Expected s1 to be the front of the list: %+q==%+q", s1.Name, s1Endpoint) 414 } 415 // Move s1 to the back of the server list 416 p.NotifyFailedServer(s1) 417 s2 = p.FindServer() 418 if s2 == nil || s2.Name != s2Endpoint { 419 t.Fatalf("Expected s2 server: %+q", s2Endpoint) 420 } 421 p.RemoveServer(s2) 422 if p.NumServers() != 1 { 423 t.Fatalf("bad") 424 } 425 p.RemoveServer(s2) 426 if p.NumServers() != 1 { 427 t.Fatalf("bad") 428 } 429 p.AddPrimaryServer(s2Endpoint) 430 431 const maxServers = 19 432 servers := make([]*ServerEndpoint, 0, maxServers) 433 servers = append(servers, s1) 434 servers = append(servers, s2) 435 // Already added two servers above 436 for i := maxServers; i > 2; i-- { 437 server := p.AddPrimaryServer(makeServerEndpointName()) 438 servers = append(servers, server) 439 } 440 if p.NumServers() != maxServers { 441 t.Fatalf("Expected %d servers, received %d", maxServers, p.NumServers()) 442 } 443 444 p.RebalanceServers() 445 446 if p.NumServers() != maxServers { 447 t.Fatalf("Expected %d servers, received %d", maxServers, p.NumServers()) 448 } 449 450 findServer := func(server *ServerEndpoint) bool { 451 for i := p.NumServers(); i > 0; i-- { 452 s := p.FindServer() 453 if s == server { 454 return true 455 } 456 } 457 return false 458 } 459 460 expectedNumServers := maxServers 461 removedServers := make([]*ServerEndpoint, 0, maxServers) 462 463 // Remove servers from the front of the list 464 for i := 3; i > 0; i-- { 465 server := p.FindServer() 466 if server == nil { 467 t.Fatalf("FindServer returned nil") 468 } 469 p.RemoveServer(server) 470 expectedNumServers-- 471 if p.NumServers() != expectedNumServers { 472 t.Fatalf("Expected %d servers (got %d)", expectedNumServers, p.NumServers()) 473 } 474 if findServer(server) == true { 475 t.Fatalf("Did not expect to find server %s after removal from the front", server.Name) 476 } 477 removedServers = append(removedServers, server) 478 } 479 480 // Remove server from the end of the list 481 for i := 3; i > 0; i-- { 482 server := p.FindServer() 483 p.NotifyFailedServer(server) 484 p.RemoveServer(server) 485 expectedNumServers-- 486 if p.NumServers() != expectedNumServers { 487 t.Fatalf("Expected %d servers (got %d)", expectedNumServers, p.NumServers()) 488 } 489 if findServer(server) == true { 490 t.Fatalf("Did not expect to find server %s", server.Name) 491 } 492 removedServers = append(removedServers, server) 493 } 494 495 // Remove server from the middle of the list 496 for i := 3; i > 0; i-- { 497 server := p.FindServer() 498 p.NotifyFailedServer(server) 499 server2 := p.FindServer() 500 p.NotifyFailedServer(server2) // server2 now at end of the list 501 502 p.RemoveServer(server) 503 expectedNumServers-- 504 if p.NumServers() != expectedNumServers { 505 t.Fatalf("Expected %d servers (got %d)", expectedNumServers, p.NumServers()) 506 } 507 if findServer(server) == true { 508 t.Fatalf("Did not expect to find server %s", server.Name) 509 } 510 removedServers = append(removedServers, server) 511 } 512 513 if p.NumServers()+len(removedServers) != maxServers { 514 t.Fatalf("Expected %d+%d=%d servers", p.NumServers(), len(removedServers), maxServers) 515 } 516 517 // Drain the remaining servers from the middle 518 for i := p.NumServers(); i > 0; i-- { 519 server := p.FindServer() 520 p.NotifyFailedServer(server) 521 server2 := p.FindServer() 522 p.NotifyFailedServer(server2) // server2 now at end of the list 523 p.RemoveServer(server) 524 removedServers = append(removedServers, server) 525 } 526 527 if p.NumServers() != 0 { 528 t.Fatalf("Expected an empty server list") 529 } 530 if len(removedServers) != maxServers { 531 t.Fatalf("Expected all servers to be in removed server list") 532 } 533 } 534 535 // func (p *RPCProxy) Start() { 536 537 // func (l *serverList) cycleServer() (servers []*Server) { 538 func TestRPCProxyInternal_cycleServer(t *testing.T) { 539 p := testRPCProxy() 540 l := p.getServerList() 541 542 server0 := &ServerEndpoint{Name: "server1"} 543 server1 := &ServerEndpoint{Name: "server2"} 544 server2 := &ServerEndpoint{Name: "server3"} 545 l.L = append(l.L, server0, server1, server2) 546 p.saveServerList(l) 547 548 l = p.getServerList() 549 if len(l.L) != 3 { 550 t.Fatalf("server length incorrect: %d/3", len(l.L)) 551 } 552 if l.L[0] != server0 && 553 l.L[1] != server1 && 554 l.L[2] != server2 { 555 t.Fatalf("initial server ordering not correct") 556 } 557 558 l.L = l.cycleServer() 559 if len(l.L) != 3 { 560 t.Fatalf("server length incorrect: %d/3", len(l.L)) 561 } 562 if l.L[0] != server1 && 563 l.L[1] != server2 && 564 l.L[2] != server0 { 565 t.Fatalf("server ordering after one cycle not correct") 566 } 567 568 l.L = l.cycleServer() 569 if len(l.L) != 3 { 570 t.Fatalf("server length incorrect: %d/3", len(l.L)) 571 } 572 if l.L[0] != server2 && 573 l.L[1] != server0 && 574 l.L[2] != server1 { 575 t.Fatalf("server ordering after two cycles not correct") 576 } 577 578 l.L = l.cycleServer() 579 if len(l.L) != 3 { 580 t.Fatalf("server length incorrect: %d/3", len(l.L)) 581 } 582 if l.L[0] != server0 && 583 l.L[1] != server1 && 584 l.L[2] != server2 { 585 t.Fatalf("server ordering after three cycles not correct") 586 } 587 } 588 589 // func (p *RPCProxy) getServerList() serverList { 590 func TestRPCProxyInternal_getServerList(t *testing.T) { 591 p := testRPCProxy() 592 l := p.getServerList() 593 if l.L == nil { 594 t.Fatalf("serverList.servers nil") 595 } 596 597 if len(l.L) != 0 { 598 t.Fatalf("serverList.servers length not zero") 599 } 600 } 601 602 func TestRPCProxyInternal_New(t *testing.T) { 603 p := testRPCProxy() 604 if p == nil { 605 t.Fatalf("bad") 606 } 607 608 if p.logger == nil { 609 t.Fatalf("bad") 610 } 611 612 if p.shutdownCh == nil { 613 t.Fatalf("bad") 614 } 615 } 616 617 // func (p *RPCProxy) reconcileServerList(l *serverList) bool { 618 func TestRPCProxyInternal_reconcileServerList(t *testing.T) { 619 tests := []int{0, 1, 2, 3, 4, 5, 10, 100} 620 for _, n := range tests { 621 ok, err := test_reconcileServerList(n) 622 if !ok { 623 t.Errorf("Expected %d to pass: %v", n, err) 624 } 625 } 626 } 627 628 func test_reconcileServerList(maxServers int) (bool, error) { 629 // Build a server list, reconcile, verify the missing servers are 630 // missing, the added have been added, and the original server is 631 // present. 632 const failPct = 0.5 633 p := testRPCProxyFailProb(failPct) 634 635 var failedServers, healthyServers []*ServerEndpoint 636 for i := 0; i < maxServers; i++ { 637 nodeName := fmt.Sprintf("s%02d", i) 638 639 node := &ServerEndpoint{Name: nodeName} 640 // Add 66% of servers to RPCProxy 641 if rand.Float64() > 0.33 { 642 p.activateEndpoint(node) 643 644 // Of healthy servers, (ab)use connPoolPinger to 645 // failPct of the servers for the reconcile. This 646 // allows for the selected server to no longer be 647 // healthy for the reconcile below. 648 if ok, _ := p.connPoolPinger.PingNomadServer(p.configInfo.Region(), p.configInfo.RPCMajorVersion(), node); ok { 649 // Will still be present 650 healthyServers = append(healthyServers, node) 651 } else { 652 // Will be missing 653 failedServers = append(failedServers, node) 654 } 655 } else { 656 // Will be added from the call to reconcile 657 healthyServers = append(healthyServers, node) 658 } 659 } 660 661 // Randomize RPCProxy's server list 662 p.RebalanceServers() 663 selectedServer := p.FindServer() 664 665 var selectedServerFailed bool 666 for _, s := range failedServers { 667 if selectedServer.Key().Equal(s.Key()) { 668 selectedServerFailed = true 669 break 670 } 671 } 672 673 // Update RPCProxy's server list to be "healthy" based on Serf. 674 // Reconcile this with origServers, which is shuffled and has a live 675 // connection, but possibly out of date. 676 origServers := p.getServerList() 677 p.saveServerList(serverList{L: healthyServers}) 678 679 // This should always succeed with non-zero server lists 680 if !selectedServerFailed && !p.reconcileServerList(&origServers) && 681 len(p.getServerList().L) != 0 && 682 len(origServers.L) != 0 { 683 // If the random gods are unfavorable and we end up with zero 684 // length lists, expect things to fail and retry the test. 685 return false, fmt.Errorf("Expected reconcile to succeed: %v %d %d", 686 selectedServerFailed, 687 len(p.getServerList().L), 688 len(origServers.L)) 689 } 690 691 // If we have zero-length server lists, test succeeded in degenerate 692 // case. 693 if len(p.getServerList().L) == 0 && 694 len(origServers.L) == 0 { 695 // Failed as expected w/ zero length list 696 return true, nil 697 } 698 699 resultingServerMap := make(map[EndpointKey]bool) 700 for _, s := range p.getServerList().L { 701 resultingServerMap[*s.Key()] = true 702 } 703 704 // Test to make sure no failed servers are in the RPCProxy's 705 // list. Error if there are any failedServers in l.servers 706 for _, s := range failedServers { 707 _, ok := resultingServerMap[*s.Key()] 708 if ok { 709 return false, fmt.Errorf("Found failed server %v in merged list %v", s, resultingServerMap) 710 } 711 } 712 713 // Test to make sure all healthy servers are in the healthy list. 714 if len(healthyServers) != len(p.getServerList().L) { 715 return false, fmt.Errorf("Expected healthy map and servers to match: %d/%d", len(healthyServers), len(healthyServers)) 716 } 717 718 // Test to make sure all healthy servers are in the resultingServerMap list. 719 for _, s := range healthyServers { 720 _, ok := resultingServerMap[*s.Key()] 721 if !ok { 722 return false, fmt.Errorf("Server %v missing from healthy map after merged lists", s) 723 } 724 } 725 return true, nil 726 } 727 728 // func (l *serverList) refreshServerRebalanceTimer() { 729 func TestRPCProxyInternal_refreshServerRebalanceTimer(t *testing.T) { 730 type clusterSizes struct { 731 numNodes int 732 numServers int 733 minRebalance time.Duration 734 } 735 clusters := []clusterSizes{ 736 {0, 3, 10 * time.Minute}, 737 {1, 0, 10 * time.Minute}, // partitioned cluster 738 {1, 3, 10 * time.Minute}, 739 {2, 3, 10 * time.Minute}, 740 {100, 0, 10 * time.Minute}, // partitioned 741 {100, 1, 10 * time.Minute}, // partitioned 742 {100, 3, 10 * time.Minute}, 743 {1024, 1, 10 * time.Minute}, // partitioned 744 {1024, 3, 10 * time.Minute}, // partitioned 745 {1024, 5, 10 * time.Minute}, 746 {16384, 1, 10 * time.Minute}, // partitioned 747 {16384, 2, 10 * time.Minute}, // partitioned 748 {16384, 3, 10 * time.Minute}, // partitioned 749 {16384, 5, 10 * time.Minute}, 750 {65535, 0, 10 * time.Minute}, // partitioned 751 {65535, 1, 10 * time.Minute}, // partitioned 752 {65535, 2, 10 * time.Minute}, // partitioned 753 {65535, 3, 10 * time.Minute}, // partitioned 754 {65535, 5, 10 * time.Minute}, // partitioned 755 {65535, 7, 10 * time.Minute}, 756 {1000000, 1, 10 * time.Minute}, // partitioned 757 {1000000, 2, 10 * time.Minute}, // partitioned 758 {1000000, 3, 10 * time.Minute}, // partitioned 759 {1000000, 5, 10 * time.Minute}, // partitioned 760 {1000000, 11, 10 * time.Minute}, // partitioned 761 {1000000, 19, 10 * time.Minute}, 762 } 763 764 logger := log.New(os.Stderr, "", log.LstdFlags) 765 shutdownCh := make(chan struct{}) 766 767 for i, s := range clusters { 768 p := NewRPCProxy(logger, shutdownCh, &fauxSerf{numNodes: s.numNodes}, &fauxConnPool{}) 769 for i := 0; i < s.numServers; i++ { 770 nodeName := fmt.Sprintf("s%02d", i) 771 p.activateEndpoint(&ServerEndpoint{Name: nodeName}) 772 } 773 774 d := p.refreshServerRebalanceTimer() 775 if d < s.minRebalance { 776 t.Errorf("[%d] duration too short for cluster of size %d and %d servers (%s < %s)", i, s.numNodes, s.numServers, d, s.minRebalance) 777 } 778 } 779 } 780 781 // func (p *RPCProxy) saveServerList(l serverList) { 782 func TestRPCProxyInternal_saveServerList(t *testing.T) { 783 p := testRPCProxy() 784 785 // Initial condition 786 func() { 787 l := p.getServerList() 788 if len(l.L) != 0 { 789 t.Fatalf("RPCProxy.saveServerList failed to load init config") 790 } 791 792 newServer := new(ServerEndpoint) 793 l.L = append(l.L, newServer) 794 p.saveServerList(l) 795 }() 796 797 // Test that save works 798 func() { 799 l1 := p.getServerList() 800 t1NumServers := len(l1.L) 801 if t1NumServers != 1 { 802 t.Fatalf("RPCProxy.saveServerList failed to save mutated config") 803 } 804 }() 805 806 // Verify mutation w/o a save doesn't alter the original 807 func() { 808 newServer := new(ServerEndpoint) 809 l := p.getServerList() 810 l.L = append(l.L, newServer) 811 812 l_orig := p.getServerList() 813 origNumServers := len(l_orig.L) 814 if origNumServers >= len(l.L) { 815 t.Fatalf("RPCProxy.saveServerList unsaved config overwrote original") 816 } 817 }() 818 }