get.pme.sh/pnats@v0.0.0-20240304004023-26bb5a137ed0/test/route_discovery_test.go (about) 1 // Copyright 2015-2019 The NATS Authors 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package test 15 16 import ( 17 "bufio" 18 "encoding/json" 19 "fmt" 20 "io" 21 "net" 22 "net/http" 23 "runtime" 24 "strconv" 25 "strings" 26 "testing" 27 "time" 28 29 "get.pme.sh/pnats/server" 30 ) 31 32 func runSeedServer(t *testing.T) (*server.Server, *server.Options) { 33 return RunServerWithConfig("./configs/seed.conf") 34 } 35 36 func runAuthSeedServer(t *testing.T) (*server.Server, *server.Options) { 37 return RunServerWithConfig("./configs/auth_seed.conf") 38 } 39 40 func TestSeedFirstRouteInfo(t *testing.T) { 41 s, opts := runSeedServer(t) 42 defer s.Shutdown() 43 44 rc := createRouteConn(t, opts.Cluster.Host, opts.Cluster.Port) 45 defer rc.Close() 46 47 _, routeExpect := setupRoute(t, rc, opts) 48 buf := routeExpect(infoRe) 49 50 info := server.Info{} 51 if err := json.Unmarshal(buf[4:], &info); err != nil { 52 t.Fatalf("Could not unmarshal route info: %v", err) 53 } 54 55 if info.ID != s.ID() { 56 t.Fatalf("Expected seed's ID %q, got %q", s.ID(), info.ID) 57 } 58 } 59 60 func TestSeedMultipleRouteInfo(t *testing.T) { 61 s, opts := runSeedServer(t) 62 defer s.Shutdown() 63 64 rc1 := createRouteConn(t, opts.Cluster.Host, opts.Cluster.Port) 65 defer rc1.Close() 66 67 rc1ID := "2222" 68 rc1Port := 22 69 rc1Host := "127.0.0.1" 70 71 routeSend1, route1Expect := setupRouteEx(t, rc1, opts, rc1ID) 72 route1Expect(infoRe) 73 74 // register ourselves via INFO 75 r1Info := server.Info{ID: rc1ID, Host: rc1Host, Port: rc1Port} 76 b, _ := json.Marshal(r1Info) 77 infoJSON := fmt.Sprintf(server.InfoProto, b) 78 routeSend1(infoJSON) 79 routeSend1("PING\r\n") 80 route1Expect(pongRe) 81 82 rc2 := createRouteConn(t, opts.Cluster.Host, opts.Cluster.Port) 83 defer rc2.Close() 84 85 rc2ID := "2224" 86 rc2Port := 24 87 rc2Host := "127.0.0.1" 88 89 routeSend2, route2Expect := setupRouteEx(t, rc2, opts, rc2ID) 90 91 hp2 := fmt.Sprintf("nats-route://%s/", net.JoinHostPort(rc2Host, strconv.Itoa(rc2Port))) 92 93 // register ourselves via INFO 94 r2Info := server.Info{ID: rc2ID, Host: rc2Host, Port: rc2Port} 95 b, _ = json.Marshal(r2Info) 96 infoJSON = fmt.Sprintf(server.InfoProto, b) 97 routeSend2(infoJSON) 98 99 // Now read back the second INFO route1 should receive letting 100 // it know about route2 101 buf := route1Expect(infoRe) 102 103 info := server.Info{} 104 if err := json.Unmarshal(buf[4:], &info); err != nil { 105 t.Fatalf("Could not unmarshal route info: %v", err) 106 } 107 108 if info.ID != rc2ID { 109 t.Fatalf("Expected info.ID to be %q, got %q", rc2ID, info.ID) 110 } 111 if info.IP == "" { 112 t.Fatalf("Expected a IP for the implicit route") 113 } 114 if info.IP != hp2 { 115 t.Fatalf("Expected IP Host of %s, got %s\n", hp2, info.IP) 116 } 117 118 route2Expect(infoRe) 119 routeSend2("PING\r\n") 120 route2Expect(pongRe) 121 122 // Now let's do a third. 123 rc3 := createRouteConn(t, opts.Cluster.Host, opts.Cluster.Port) 124 defer rc3.Close() 125 126 rc3ID := "2226" 127 rc3Port := 26 128 rc3Host := "127.0.0.1" 129 130 routeSend3, _ := setupRouteEx(t, rc3, opts, rc3ID) 131 132 // register ourselves via INFO 133 r3Info := server.Info{ID: rc3ID, Host: rc3Host, Port: rc3Port} 134 b, _ = json.Marshal(r3Info) 135 infoJSON = fmt.Sprintf(server.InfoProto, b) 136 routeSend3(infoJSON) 137 138 // Now read back out the info from the seed route 139 buf = route1Expect(infoRe) 140 141 info = server.Info{} 142 if err := json.Unmarshal(buf[4:], &info); err != nil { 143 t.Fatalf("Could not unmarshal route info: %v", err) 144 } 145 146 if info.ID != rc3ID { 147 t.Fatalf("Expected info.ID to be %q, got %q", rc3ID, info.ID) 148 } 149 150 // Now read back out the info from the seed route 151 buf = route2Expect(infoRe) 152 153 info = server.Info{} 154 if err := json.Unmarshal(buf[4:], &info); err != nil { 155 t.Fatalf("Could not unmarshal route info: %v", err) 156 } 157 158 if info.ID != rc3ID { 159 t.Fatalf("Expected info.ID to be %q, got %q", rc3ID, info.ID) 160 } 161 } 162 163 func TestSeedSolicitWorks(t *testing.T) { 164 s1, opts := runSeedServer(t) 165 defer s1.Shutdown() 166 167 // Create the routes string for others to connect to the seed. 168 routesStr := fmt.Sprintf("nats-route://%s:%d/", opts.Cluster.Host, opts.Cluster.Port) 169 170 // Run Server #2 171 s2Opts := nextServerOpts(opts) 172 s2Opts.Routes = server.RoutesFromStr(routesStr) 173 174 s2 := RunServer(s2Opts) 175 defer s2.Shutdown() 176 177 // Run Server #3 178 s3Opts := nextServerOpts(s2Opts) 179 180 s3 := RunServer(s3Opts) 181 defer s3.Shutdown() 182 183 // Wait for a bit for graph to connect 184 time.Sleep(500 * time.Millisecond) 185 186 // Grab Routez from monitor ports, make sure we are fully connected. 187 url := fmt.Sprintf("http://%s:%d/", opts.Host, opts.HTTPPort) 188 rz := readHTTPRoutez(t, url) 189 for _, route := range rz.Routes { 190 if route.LastActivity.IsZero() { 191 t.Error("Expected LastActivity to be valid\n") 192 } 193 } 194 ris := expectRids(t, rz, []string{s2.ID(), s3.ID()}) 195 if ris[s2.ID()].IsConfigured { 196 t.Fatalf("Expected server not to be configured\n") 197 } 198 if ris[s3.ID()].IsConfigured { 199 t.Fatalf("Expected server not to be configured\n") 200 } 201 202 // Server 2 did solicit routes to Server 1. 203 url = fmt.Sprintf("http://%s:%d/", s2Opts.Host, s2Opts.HTTPPort) 204 rz = readHTTPRoutez(t, url) 205 for _, route := range rz.Routes { 206 if route.LastActivity.IsZero() { 207 t.Error("Expected LastActivity to be valid") 208 } 209 } 210 ris = expectRids(t, rz, []string{s1.ID(), s3.ID()}) 211 if !ris[s1.ID()].IsConfigured { 212 t.Fatalf("Expected seed server to be configured\n") 213 } 214 if ris[s3.ID()].IsConfigured { 215 t.Fatalf("Expected server not to be configured\n") 216 } 217 218 url = fmt.Sprintf("http://%s:%d/", s3Opts.Host, s3Opts.HTTPPort) 219 rz = readHTTPRoutez(t, url) 220 for _, route := range rz.Routes { 221 if route.LastActivity.IsZero() { 222 t.Error("Expected LastActivity to be valid") 223 } 224 } 225 ris = expectRids(t, rz, []string{s1.ID(), s2.ID()}) 226 if !ris[s1.ID()].IsConfigured { 227 t.Fatalf("Expected seed server to be configured\n") 228 } 229 if ris[s2.ID()].IsConfigured { 230 t.Fatalf("Expected server not to be configured\n") 231 } 232 } 233 234 type serverInfo struct { 235 server *server.Server 236 opts *server.Options 237 } 238 239 func checkConnected(t *testing.T, servers []serverInfo, current int, oneSeed bool) error { 240 s := servers[current] 241 242 // Grab Routez from monitor ports, make sure we are fully connected 243 url := fmt.Sprintf("http://%s:%d/", s.opts.Host, s.opts.HTTPPort) 244 rz := readHTTPRoutez(t, url) 245 total := len(servers) 246 var ids []string 247 for i := 0; i < total; i++ { 248 if i == current { 249 continue 250 } 251 ids = append(ids, servers[i].server.ID()) 252 } 253 ris, err := expectRidsNoFatal(t, true, rz, ids) 254 if err != nil { 255 return err 256 } 257 for i := 0; i < total; i++ { 258 if i == current { 259 continue 260 } 261 s := servers[i] 262 if current == 0 || ((oneSeed && i > 0) || (!oneSeed && (i != current-1))) { 263 if ris[s.server.ID()].IsConfigured { 264 return fmt.Errorf("Expected server %s:%d not to be configured", s.opts.Host, s.opts.Port) 265 } 266 } else if oneSeed || (i == current-1) { 267 if !ris[s.server.ID()].IsConfigured { 268 return fmt.Errorf("Expected server %s:%d to be configured", s.opts.Host, s.opts.Port) 269 } 270 } 271 } 272 return nil 273 } 274 275 func TestStressSeedSolicitWorks(t *testing.T) { 276 s1, opts := runSeedServer(t) 277 defer s1.Shutdown() 278 279 // Create the routes string for others to connect to the seed. 280 routesStr := fmt.Sprintf("nats-route://%s:%d/", opts.Cluster.Host, opts.Cluster.Port) 281 282 s2Opts := nextServerOpts(opts) 283 s2Opts.Routes = server.RoutesFromStr(routesStr) 284 285 s3Opts := nextServerOpts(s2Opts) 286 s4Opts := nextServerOpts(s3Opts) 287 288 for i := 0; i < 10; i++ { 289 func() { 290 // Run these servers manually, because we want them to start and 291 // connect to s1 as fast as possible. 292 293 s2 := server.New(s2Opts) 294 if s2 == nil { 295 panic("No NATS Server object returned.") 296 } 297 defer s2.Shutdown() 298 go s2.Start() 299 300 s3 := server.New(s3Opts) 301 if s3 == nil { 302 panic("No NATS Server object returned.") 303 } 304 defer s3.Shutdown() 305 go s3.Start() 306 307 s4 := server.New(s4Opts) 308 if s4 == nil { 309 panic("No NATS Server object returned.") 310 } 311 defer s4.Shutdown() 312 go s4.Start() 313 314 serversInfo := []serverInfo{{s1, opts}, {s2, s2Opts}, {s3, s3Opts}, {s4, s4Opts}} 315 316 checkFor(t, 5*time.Second, 100*time.Millisecond, func() error { 317 for j := 0; j < len(serversInfo); j++ { 318 if err := checkConnected(t, serversInfo, j, true); err != nil { 319 return err 320 } 321 } 322 return nil 323 }) 324 }() 325 checkNumRoutes(t, s1, 0) 326 } 327 } 328 329 func TestChainedSolicitWorks(t *testing.T) { 330 s1, opts := runSeedServer(t) 331 defer s1.Shutdown() 332 333 // Create the routes string for others to connect to the seed. 334 routesStr := fmt.Sprintf("nats-route://%s:%d/", opts.Cluster.Host, opts.Cluster.Port) 335 336 // Run Server #2 337 s2Opts := nextServerOpts(opts) 338 s2Opts.Routes = server.RoutesFromStr(routesStr) 339 340 s2 := RunServer(s2Opts) 341 defer s2.Shutdown() 342 343 // Run Server #3 344 s3Opts := nextServerOpts(s2Opts) 345 // We will have s3 connect to s2, not the seed. 346 routesStr = fmt.Sprintf("nats-route://%s:%d/", s2Opts.Cluster.Host, s2Opts.Cluster.Port) 347 s3Opts.Routes = server.RoutesFromStr(routesStr) 348 349 s3 := RunServer(s3Opts) 350 defer s3.Shutdown() 351 352 // Wait for a bit for graph to connect 353 time.Sleep(500 * time.Millisecond) 354 355 // Grab Routez from monitor ports, make sure we are fully connected 356 url := fmt.Sprintf("http://%s:%d/", opts.Host, opts.HTTPPort) 357 rz := readHTTPRoutez(t, url) 358 ris := expectRids(t, rz, []string{s2.ID(), s3.ID()}) 359 if ris[s2.ID()].IsConfigured { 360 t.Fatalf("Expected server not to be configured\n") 361 } 362 if ris[s3.ID()].IsConfigured { 363 t.Fatalf("Expected server not to be configured\n") 364 } 365 366 url = fmt.Sprintf("http://%s:%d/", s2Opts.Host, s2Opts.HTTPPort) 367 rz = readHTTPRoutez(t, url) 368 ris = expectRids(t, rz, []string{s1.ID(), s3.ID()}) 369 if !ris[s1.ID()].IsConfigured { 370 t.Fatalf("Expected seed server to be configured\n") 371 } 372 if ris[s3.ID()].IsConfigured { 373 t.Fatalf("Expected server not to be configured\n") 374 } 375 376 url = fmt.Sprintf("http://%s:%d/", s3Opts.Host, s3Opts.HTTPPort) 377 rz = readHTTPRoutez(t, url) 378 ris = expectRids(t, rz, []string{s1.ID(), s2.ID()}) 379 if !ris[s2.ID()].IsConfigured { 380 t.Fatalf("Expected s2 server to be configured\n") 381 } 382 if ris[s1.ID()].IsConfigured { 383 t.Fatalf("Expected seed server not to be configured\n") 384 } 385 } 386 387 func TestStressChainedSolicitWorks(t *testing.T) { 388 s1, opts := runSeedServer(t) 389 defer s1.Shutdown() 390 391 // Create the routes string for s2 to connect to the seed 392 routesStr := fmt.Sprintf("nats-route://%s:%d/", opts.Cluster.Host, opts.Cluster.Port) 393 s2Opts := nextServerOpts(opts) 394 s2Opts.Routes = server.RoutesFromStr(routesStr) 395 396 s3Opts := nextServerOpts(s2Opts) 397 // Create the routes string for s3 to connect to s2 398 routesStr = fmt.Sprintf("nats-route://%s:%d/", s2Opts.Cluster.Host, s2Opts.Cluster.Port) 399 s3Opts.Routes = server.RoutesFromStr(routesStr) 400 401 s4Opts := nextServerOpts(s3Opts) 402 // Create the routes string for s4 to connect to s3 403 routesStr = fmt.Sprintf("nats-route://%s:%d/", s3Opts.Cluster.Host, s3Opts.Cluster.Port) 404 s4Opts.Routes = server.RoutesFromStr(routesStr) 405 406 for i := 0; i < 10; i++ { 407 func() { 408 // Run these servers manually, because we want them to start and 409 // connect to s1 as fast as possible. 410 411 s2 := server.New(s2Opts) 412 if s2 == nil { 413 panic("No NATS Server object returned.") 414 } 415 defer s2.Shutdown() 416 go s2.Start() 417 418 s3 := server.New(s3Opts) 419 if s3 == nil { 420 panic("No NATS Server object returned.") 421 } 422 defer s3.Shutdown() 423 go s3.Start() 424 425 s4 := server.New(s4Opts) 426 if s4 == nil { 427 panic("No NATS Server object returned.") 428 } 429 defer s4.Shutdown() 430 go s4.Start() 431 432 serversInfo := []serverInfo{{s1, opts}, {s2, s2Opts}, {s3, s3Opts}, {s4, s4Opts}} 433 434 checkFor(t, 5*time.Second, 100*time.Millisecond, func() error { 435 for j := 0; j < len(serversInfo); j++ { 436 if err := checkConnected(t, serversInfo, j, false); err != nil { 437 return err 438 } 439 } 440 return nil 441 }) 442 }() 443 checkNumRoutes(t, s1, 0) 444 } 445 } 446 447 func TestAuthSeedSolicitWorks(t *testing.T) { 448 s1, opts := runAuthSeedServer(t) 449 defer s1.Shutdown() 450 451 // Create the routes string for others to connect to the seed. 452 routesStr := fmt.Sprintf("nats-route://%s:%s@%s:%d/", opts.Cluster.Username, opts.Cluster.Password, opts.Cluster.Host, opts.Cluster.Port) 453 454 // Run Server #2 455 s2Opts := nextServerOpts(opts) 456 s2Opts.Routes = server.RoutesFromStr(routesStr) 457 458 s2 := RunServer(s2Opts) 459 defer s2.Shutdown() 460 461 // Run Server #3 462 s3Opts := nextServerOpts(s2Opts) 463 464 s3 := RunServer(s3Opts) 465 defer s3.Shutdown() 466 467 // Wait for a bit for graph to connect 468 time.Sleep(500 * time.Millisecond) 469 470 // Grab Routez from monitor ports, make sure we are fully connected 471 url := fmt.Sprintf("http://%s:%d/", opts.Host, opts.HTTPPort) 472 rz := readHTTPRoutez(t, url) 473 ris := expectRids(t, rz, []string{s2.ID(), s3.ID()}) 474 if ris[s2.ID()].IsConfigured { 475 t.Fatalf("Expected server not to be configured\n") 476 } 477 if ris[s3.ID()].IsConfigured { 478 t.Fatalf("Expected server not to be configured\n") 479 } 480 481 url = fmt.Sprintf("http://%s:%d/", s2Opts.Host, s2Opts.HTTPPort) 482 rz = readHTTPRoutez(t, url) 483 ris = expectRids(t, rz, []string{s1.ID(), s3.ID()}) 484 if !ris[s1.ID()].IsConfigured { 485 t.Fatalf("Expected seed server to be configured\n") 486 } 487 if ris[s3.ID()].IsConfigured { 488 t.Fatalf("Expected server not to be configured\n") 489 } 490 491 url = fmt.Sprintf("http://%s:%d/", s3Opts.Host, s3Opts.HTTPPort) 492 rz = readHTTPRoutez(t, url) 493 ris = expectRids(t, rz, []string{s1.ID(), s2.ID()}) 494 if !ris[s1.ID()].IsConfigured { 495 t.Fatalf("Expected seed server to be configured\n") 496 } 497 if ris[s2.ID()].IsConfigured { 498 t.Fatalf("Expected server not to be configured\n") 499 } 500 } 501 502 // Helper to check for correct route memberships 503 func expectRids(t *testing.T, rz *server.Routez, rids []string) map[string]*server.RouteInfo { 504 ri, err := expectRidsNoFatal(t, false, rz, rids) 505 if err != nil { 506 t.Fatalf("%v", err) 507 } 508 return ri 509 } 510 511 func expectRidsNoFatal(t *testing.T, direct bool, rz *server.Routez, rids []string) (map[string]*server.RouteInfo, error) { 512 caller := 1 513 if !direct { 514 caller++ 515 } 516 if len(rids) != rz.NumRoutes { 517 _, fn, line, _ := runtime.Caller(caller) 518 return nil, fmt.Errorf("[%s:%d] Expecting %d routes, got %d\n", fn, line, len(rids), rz.NumRoutes) 519 } 520 set := make(map[string]bool) 521 for _, v := range rids { 522 set[v] = true 523 } 524 // Make result map for additional checking 525 ri := make(map[string]*server.RouteInfo) 526 for _, r := range rz.Routes { 527 if !set[r.RemoteID] { 528 _, fn, line, _ := runtime.Caller(caller) 529 return nil, fmt.Errorf("[%s:%d] Route with rid %s unexpected, expected %+v\n", fn, line, r.RemoteID, rids) 530 } 531 ri[r.RemoteID] = r 532 } 533 return ri, nil 534 } 535 536 // Helper to easily grab routez info. 537 func readHTTPRoutez(t *testing.T, url string) *server.Routez { 538 resetPreviousHTTPConnections() 539 resp, err := http.Get(url + "routez") 540 if err != nil { 541 stackFatalf(t, "Expected no error: Got %v\n", err) 542 } 543 defer resp.Body.Close() 544 if resp.StatusCode != 200 { 545 stackFatalf(t, "Expected a 200 response, got %d\n", resp.StatusCode) 546 } 547 body, err := io.ReadAll(resp.Body) 548 if err != nil { 549 stackFatalf(t, "Got an error reading the body: %v\n", err) 550 } 551 r := server.Routez{} 552 if err := json.Unmarshal(body, &r); err != nil { 553 stackFatalf(t, "Got an error unmarshalling the body: %v\n", err) 554 } 555 return &r 556 } 557 558 func TestSeedReturnIPInInfo(t *testing.T) { 559 s, opts := runSeedServer(t) 560 defer s.Shutdown() 561 562 rc1 := createRouteConn(t, opts.Cluster.Host, opts.Cluster.Port) 563 defer rc1.Close() 564 565 rc1ID := "2222" 566 rc1Port := 22 567 rc1Host := "127.0.0.1" 568 569 routeSend1, route1Expect := setupRouteEx(t, rc1, opts, rc1ID) 570 route1Expect(infoRe) 571 572 // register ourselves via INFO 573 r1Info := server.Info{ID: rc1ID, Host: rc1Host, Port: rc1Port} 574 b, _ := json.Marshal(r1Info) 575 infoJSON := fmt.Sprintf(server.InfoProto, b) 576 routeSend1(infoJSON) 577 routeSend1("PING\r\n") 578 route1Expect(pongRe) 579 580 rc2 := createRouteConn(t, opts.Cluster.Host, opts.Cluster.Port) 581 defer rc2.Close() 582 583 rc2ID := "2224" 584 rc2Port := 24 585 rc2Host := "127.0.0.1" 586 587 routeSend2, _ := setupRouteEx(t, rc2, opts, rc2ID) 588 589 // register ourselves via INFO 590 r2Info := server.Info{ID: rc2ID, Host: rc2Host, Port: rc2Port} 591 b, _ = json.Marshal(r2Info) 592 infoJSON = fmt.Sprintf(server.InfoProto, b) 593 routeSend2(infoJSON) 594 595 // Now read info that route1 should have received from the seed 596 buf := route1Expect(infoRe) 597 598 info := server.Info{} 599 if err := json.Unmarshal(buf[4:], &info); err != nil { 600 t.Fatalf("Could not unmarshal route info: %v", err) 601 } 602 603 if info.IP == "" { 604 t.Fatal("Expected to have IP in INFO") 605 } 606 rip, _, err := net.SplitHostPort(strings.TrimPrefix(info.IP, "nats-route://")) 607 if err != nil { 608 t.Fatalf("Error parsing url: %v", err) 609 } 610 addr, ok := rc1.RemoteAddr().(*net.TCPAddr) 611 if !ok { 612 t.Fatal("Unable to get IP address from route") 613 } 614 s1 := strings.ToLower(addr.IP.String()) 615 s2 := strings.ToLower(rip) 616 if s1 != s2 { 617 t.Fatalf("Expected IP %s, got %s", s1, s2) 618 } 619 } 620 621 func TestImplicitRouteRetry(t *testing.T) { 622 srvSeed, optsSeed := runSeedServer(t) 623 defer srvSeed.Shutdown() 624 625 optsA := nextServerOpts(optsSeed) 626 optsA.Routes = server.RoutesFromStr(fmt.Sprintf("nats://%s:%d", optsSeed.Cluster.Host, optsSeed.Cluster.Port)) 627 optsA.Cluster.ConnectRetries = 5 628 srvA := RunServer(optsA) 629 defer srvA.Shutdown() 630 631 optsB := nextServerOpts(optsA) 632 rcb := createRouteConn(t, optsSeed.Cluster.Host, optsSeed.Cluster.Port) 633 defer rcb.Close() 634 rcbID := "ServerB" 635 routeBSend, routeBExpect := setupRouteEx(t, rcb, optsB, rcbID) 636 routeBExpect(infoRe) 637 // register ourselves via INFO 638 rbInfo := server.Info{ID: rcbID, Host: optsB.Cluster.Host, Port: optsB.Cluster.Port} 639 b, _ := json.Marshal(rbInfo) 640 infoJSON := fmt.Sprintf(server.InfoProto, b) 641 routeBSend(infoJSON) 642 routeBSend("PING\r\n") 643 routeBExpect(pongRe) 644 645 // srvA should try to connect. Wait to make sure that it fails. 646 time.Sleep(1200 * time.Millisecond) 647 648 // Setup a fake route listen for routeB 649 rbListen, err := net.Listen("tcp", fmt.Sprintf("%s:%d", optsB.Cluster.Host, optsB.Cluster.Port)) 650 if err != nil { 651 t.Fatalf("Error during listen: %v", err) 652 } 653 defer rbListen.Close() 654 c, err := rbListen.Accept() 655 if err != nil { 656 t.Fatalf("Error during accept: %v", err) 657 } 658 defer c.Close() 659 660 br := bufio.NewReaderSize(c, 32768) 661 // Consume CONNECT and INFO 662 for i := 0; i < 2; i++ { 663 c.SetReadDeadline(time.Now().Add(2 * time.Second)) 664 buf, _, err := br.ReadLine() 665 c.SetReadDeadline(time.Time{}) 666 if err != nil { 667 t.Fatalf("Error reading: %v", err) 668 } 669 if i == 0 { 670 continue 671 } 672 buf = buf[len("INFO "):] 673 info := &server.Info{} 674 if err := json.Unmarshal(buf, info); err != nil { 675 t.Fatalf("Error during unmarshal: %v", err) 676 } 677 // Check INFO is from server A. 678 if info.ID != srvA.ID() { 679 t.Fatalf("Expected CONNECT from %v, got CONNECT from %v", srvA.ID(), info.ID) 680 } 681 } 682 }