mirror of
https://github.com/gogrlx/nats-server.git
synced 2026-04-12 17:31:22 -07:00
356 lines
9.9 KiB
Go
356 lines
9.9 KiB
Go
// Copyright 2015 Apcera Inc. All rights reserved.
|
|
|
|
package test
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"net"
|
|
"net/http"
|
|
"runtime"
|
|
"strconv"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/nats-io/gnatsd/server"
|
|
)
|
|
|
|
func runSeedServer(t *testing.T) (*server.Server, *server.Options) {
|
|
return RunServerWithConfig("./configs/seed.conf")
|
|
}
|
|
|
|
func runAuthSeedServer(t *testing.T) (*server.Server, *server.Options) {
|
|
return RunServerWithConfig("./configs/auth_seed.conf")
|
|
}
|
|
|
|
func TestSeedFirstRouteInfo(t *testing.T) {
|
|
s, opts := runSeedServer(t)
|
|
defer s.Shutdown()
|
|
|
|
rc := createRouteConn(t, opts.ClusterHost, opts.ClusterPort)
|
|
defer rc.Close()
|
|
|
|
_, routeExpect := setupRoute(t, rc, opts)
|
|
buf := routeExpect(infoRe)
|
|
|
|
info := server.Info{}
|
|
if err := json.Unmarshal(buf[4:], &info); err != nil {
|
|
t.Fatalf("Could not unmarshal route info: %v", err)
|
|
}
|
|
|
|
if len(info.Routes) != 0 {
|
|
t.Fatalf("Expected len of []Routes to be zero vs %d\n", len(info.Routes))
|
|
}
|
|
}
|
|
|
|
func TestSeedMultipleRouteInfo(t *testing.T) {
|
|
s, opts := runSeedServer(t)
|
|
defer s.Shutdown()
|
|
|
|
rc1 := createRouteConn(t, opts.ClusterHost, opts.ClusterPort)
|
|
defer rc1.Close()
|
|
|
|
routeSend1, route1Expect := setupRoute(t, rc1, opts)
|
|
route1Expect(infoRe)
|
|
|
|
rc1ID := "2222"
|
|
rc1Port := 22
|
|
rc1Host := "127.0.0.1"
|
|
|
|
hp1 := fmt.Sprintf("nats-route://%s/", net.JoinHostPort(rc1Host, strconv.Itoa(rc1Port)))
|
|
|
|
// register ourselves via INFO
|
|
r1Info := server.Info{ID: rc1ID, Host: rc1Host, Port: rc1Port}
|
|
b, _ := json.Marshal(r1Info)
|
|
infoJSON := fmt.Sprintf(server.InfoProto, b)
|
|
routeSend1(infoJSON)
|
|
routeSend1("PING\r\n")
|
|
route1Expect(pongRe)
|
|
|
|
rc2 := createRouteConn(t, opts.ClusterHost, opts.ClusterPort)
|
|
defer rc2.Close()
|
|
|
|
routeSend2, route2Expect := setupRoute(t, rc2, opts)
|
|
|
|
rc2ID := "2224"
|
|
rc2Port := 24
|
|
rc2Host := "127.0.0.1"
|
|
|
|
// hp2 := net.JoinHostPort(rc2Host, strconv.Itoa(rc2Port))
|
|
|
|
// register ourselves via INFO
|
|
r2Info := server.Info{ID: rc2ID, Host: rc2Host, Port: rc2Port}
|
|
b, _ = json.Marshal(r2Info)
|
|
infoJSON = fmt.Sprintf(server.InfoProto, b)
|
|
routeSend2(infoJSON)
|
|
|
|
// Now read back out the info from the seed route
|
|
buf := route2Expect(infoRe)
|
|
|
|
info := server.Info{}
|
|
if err := json.Unmarshal(buf[4:], &info); err != nil {
|
|
t.Fatalf("Could not unmarshal route info: %v", err)
|
|
}
|
|
|
|
if len(info.Routes) != 1 {
|
|
t.Fatalf("Expected len of []Routes to be 1 vs %d\n", len(info.Routes))
|
|
}
|
|
|
|
route := info.Routes[0]
|
|
if route.RemoteID != rc1ID {
|
|
t.Fatalf("Expected RemoteID of \"22\", got %q\n", route.RemoteID)
|
|
}
|
|
if route.URL == "" {
|
|
t.Fatalf("Expected a URL for the implicit route")
|
|
}
|
|
if route.URL != hp1 {
|
|
t.Fatalf("Expected URL Host of %s, got %s\n", hp1, route.URL)
|
|
}
|
|
|
|
routeSend2("PING\r\n")
|
|
route2Expect(pongRe)
|
|
|
|
// Now let's do a third.
|
|
rc3 := createRouteConn(t, opts.ClusterHost, opts.ClusterPort)
|
|
defer rc3.Close()
|
|
|
|
routeSend3, route3Expect := setupRoute(t, rc3, opts)
|
|
|
|
rc3ID := "2226"
|
|
rc3Port := 26
|
|
rc3Host := "127.0.0.1"
|
|
|
|
// register ourselves via INFO
|
|
r3Info := server.Info{ID: rc3ID, Host: rc3Host, Port: rc3Port}
|
|
b, _ = json.Marshal(r3Info)
|
|
infoJSON = fmt.Sprintf(server.InfoProto, b)
|
|
routeSend3(infoJSON)
|
|
|
|
// Now read back out the info from the seed route
|
|
buf = route3Expect(infoRe)
|
|
|
|
info = server.Info{}
|
|
if err := json.Unmarshal(buf[4:], &info); err != nil {
|
|
t.Fatalf("Could not unmarshal route info: %v", err)
|
|
}
|
|
if len(info.Routes) != 2 {
|
|
t.Fatalf("Expected len of []Routes to be 2 vs %d\n", len(info.Routes))
|
|
}
|
|
}
|
|
|
|
func TestSeedSolicitWorks(t *testing.T) {
|
|
s1, opts := runSeedServer(t)
|
|
defer s1.Shutdown()
|
|
|
|
// Create the routes string for others to connect to the seed.
|
|
routesStr := fmt.Sprintf("nats-route://%s:%d/", opts.ClusterHost, opts.ClusterPort)
|
|
|
|
// Run Server #2
|
|
s2Opts := nextServerOpts(opts)
|
|
s2Opts.Routes = server.RoutesFromStr(routesStr)
|
|
|
|
s2 := RunServer(s2Opts)
|
|
defer s2.Shutdown()
|
|
|
|
// Run Server #3
|
|
s3Opts := nextServerOpts(s2Opts)
|
|
|
|
s3 := RunServer(s3Opts)
|
|
defer s3.Shutdown()
|
|
|
|
// Wait for a bit for graph to connect
|
|
time.Sleep(500 * time.Millisecond)
|
|
|
|
// Grab Routez from monitor ports, make sure we are fully connected
|
|
url := fmt.Sprintf("http://%s:%d/", opts.Host, opts.HTTPPort)
|
|
rz := readHttpRoutez(t, url)
|
|
ris := expectRids(t, rz, []string{s2.Id(), s3.Id()})
|
|
if ris[s2.Id()].IsConfigured == true {
|
|
t.Fatalf("Expected server not to be configured\n")
|
|
}
|
|
if ris[s3.Id()].IsConfigured == true {
|
|
t.Fatalf("Expected server not to be configured\n")
|
|
}
|
|
|
|
url = fmt.Sprintf("http://%s:%d/", s2Opts.Host, s2Opts.HTTPPort)
|
|
rz = readHttpRoutez(t, url)
|
|
ris = expectRids(t, rz, []string{s1.Id(), s3.Id()})
|
|
if ris[s1.Id()].IsConfigured != true {
|
|
t.Fatalf("Expected seed server to be configured\n")
|
|
}
|
|
if ris[s3.Id()].IsConfigured == true {
|
|
t.Fatalf("Expected server not to be configured\n")
|
|
}
|
|
|
|
url = fmt.Sprintf("http://%s:%d/", s3Opts.Host, s3Opts.HTTPPort)
|
|
rz = readHttpRoutez(t, url)
|
|
ris = expectRids(t, rz, []string{s1.Id(), s2.Id()})
|
|
if ris[s1.Id()].IsConfigured != true {
|
|
t.Fatalf("Expected seed server to be configured\n")
|
|
}
|
|
if ris[s2.Id()].IsConfigured == true {
|
|
t.Fatalf("Expected server not to be configured\n")
|
|
}
|
|
}
|
|
|
|
func TestChainedSolicitWorks(t *testing.T) {
|
|
s1, opts := runSeedServer(t)
|
|
defer s1.Shutdown()
|
|
|
|
// Create the routes string for others to connect to the seed.
|
|
routesStr := fmt.Sprintf("nats-route://%s:%d/", opts.ClusterHost, opts.ClusterPort)
|
|
|
|
// Run Server #2
|
|
s2Opts := nextServerOpts(opts)
|
|
s2Opts.Routes = server.RoutesFromStr(routesStr)
|
|
|
|
s2 := RunServer(s2Opts)
|
|
defer s2.Shutdown()
|
|
|
|
// Run Server #3
|
|
s3Opts := nextServerOpts(s2Opts)
|
|
// We will have s3 connect to s2, not the seed.
|
|
routesStr = fmt.Sprintf("nats-route://%s:%d/", s2Opts.ClusterHost, s2Opts.ClusterPort)
|
|
s3Opts.Routes = server.RoutesFromStr(routesStr)
|
|
|
|
s3 := RunServer(s3Opts)
|
|
defer s3.Shutdown()
|
|
|
|
// Wait for a bit for graph to connect
|
|
time.Sleep(500 * time.Millisecond)
|
|
|
|
// Grab Routez from monitor ports, make sure we are fully connected
|
|
url := fmt.Sprintf("http://%s:%d/", opts.Host, opts.HTTPPort)
|
|
rz := readHttpRoutez(t, url)
|
|
ris := expectRids(t, rz, []string{s2.Id(), s3.Id()})
|
|
if ris[s2.Id()].IsConfigured == true {
|
|
t.Fatalf("Expected server not to be configured\n")
|
|
}
|
|
if ris[s3.Id()].IsConfigured == true {
|
|
t.Fatalf("Expected server not to be configured\n")
|
|
}
|
|
|
|
url = fmt.Sprintf("http://%s:%d/", s2Opts.Host, s2Opts.HTTPPort)
|
|
rz = readHttpRoutez(t, url)
|
|
ris = expectRids(t, rz, []string{s1.Id(), s3.Id()})
|
|
if ris[s1.Id()].IsConfigured != true {
|
|
t.Fatalf("Expected seed server to be configured\n")
|
|
}
|
|
if ris[s3.Id()].IsConfigured == true {
|
|
t.Fatalf("Expected server not to be configured\n")
|
|
}
|
|
|
|
url = fmt.Sprintf("http://%s:%d/", s3Opts.Host, s3Opts.HTTPPort)
|
|
rz = readHttpRoutez(t, url)
|
|
ris = expectRids(t, rz, []string{s1.Id(), s2.Id()})
|
|
if ris[s2.Id()].IsConfigured != true {
|
|
t.Fatalf("Expected s2 server to be configured\n")
|
|
}
|
|
if ris[s1.Id()].IsConfigured == true {
|
|
t.Fatalf("Expected seed server not to be configured\n")
|
|
}
|
|
}
|
|
|
|
func TestAuthSeedSolicitWorks(t *testing.T) {
|
|
s1, opts := runAuthSeedServer(t)
|
|
defer s1.Shutdown()
|
|
|
|
// Create the routes string for others to connect to the seed.
|
|
routesStr := fmt.Sprintf("nats-route://%s:%s@%s:%d/", opts.ClusterUsername, opts.ClusterPassword, opts.ClusterHost, opts.ClusterPort)
|
|
|
|
// Run Server #2
|
|
s2Opts := nextServerOpts(opts)
|
|
s2Opts.Routes = server.RoutesFromStr(routesStr)
|
|
|
|
s2 := RunServer(s2Opts)
|
|
defer s2.Shutdown()
|
|
|
|
// Run Server #3
|
|
s3Opts := nextServerOpts(s2Opts)
|
|
|
|
s3 := RunServer(s3Opts)
|
|
defer s3.Shutdown()
|
|
|
|
// Wait for a bit for graph to connect
|
|
time.Sleep(500 * time.Millisecond)
|
|
|
|
// Grab Routez from monitor ports, make sure we are fully connected
|
|
url := fmt.Sprintf("http://%s:%d/", opts.Host, opts.HTTPPort)
|
|
rz := readHttpRoutez(t, url)
|
|
ris := expectRids(t, rz, []string{s2.Id(), s3.Id()})
|
|
if ris[s2.Id()].IsConfigured == true {
|
|
t.Fatalf("Expected server not to be configured\n")
|
|
}
|
|
if ris[s3.Id()].IsConfigured == true {
|
|
t.Fatalf("Expected server not to be configured\n")
|
|
}
|
|
|
|
url = fmt.Sprintf("http://%s:%d/", s2Opts.Host, s2Opts.HTTPPort)
|
|
rz = readHttpRoutez(t, url)
|
|
ris = expectRids(t, rz, []string{s1.Id(), s3.Id()})
|
|
if ris[s1.Id()].IsConfigured != true {
|
|
t.Fatalf("Expected seed server to be configured\n")
|
|
}
|
|
if ris[s3.Id()].IsConfigured == true {
|
|
t.Fatalf("Expected server not to be configured\n")
|
|
}
|
|
|
|
url = fmt.Sprintf("http://%s:%d/", s3Opts.Host, s3Opts.HTTPPort)
|
|
rz = readHttpRoutez(t, url)
|
|
ris = expectRids(t, rz, []string{s1.Id(), s2.Id()})
|
|
if ris[s1.Id()].IsConfigured != true {
|
|
t.Fatalf("Expected seed server to be configured\n")
|
|
}
|
|
if ris[s2.Id()].IsConfigured == true {
|
|
t.Fatalf("Expected server not to be configured\n")
|
|
}
|
|
}
|
|
|
|
// Helper to check for correct route memberships
|
|
func expectRids(t *testing.T, rz *server.Routez, rids []string) map[string]*server.RouteInfo {
|
|
if len(rids) != rz.NumRoutes {
|
|
_, fn, line, _ := runtime.Caller(1)
|
|
t.Fatalf("[%s:%d] Expecting %d routes, got %d\n", fn, line, len(rids), rz.NumRoutes)
|
|
}
|
|
set := make(map[string]bool)
|
|
for _, v := range rids {
|
|
set[v] = true
|
|
}
|
|
// Make result map for additional checking
|
|
ri := make(map[string]*server.RouteInfo)
|
|
for _, r := range rz.Routes {
|
|
if set[r.RemoteId] != true {
|
|
_, fn, line, _ := runtime.Caller(1)
|
|
t.Fatalf("[%s:%d] Route with rid %s unexpected, expected %+v\n", fn, line, r.RemoteId, rids)
|
|
}
|
|
ri[r.RemoteId] = r
|
|
}
|
|
return ri
|
|
}
|
|
|
|
// Helper to easily grab routez info.
|
|
func readHttpRoutez(t *testing.T, url string) *server.Routez {
|
|
resp, err := http.Get(url + "routez")
|
|
if err != nil {
|
|
t.Fatalf("Expected no error: Got %v\n", err)
|
|
}
|
|
if resp.StatusCode != 200 {
|
|
// Do one retry - FIXME(dlc) - Why does this fail when running the solicit tests b2b?
|
|
resp, _ = http.Get(url + "routez")
|
|
if resp.StatusCode != 200 {
|
|
t.Fatalf("Expected a 200 response, got %d\n", resp.StatusCode)
|
|
}
|
|
}
|
|
defer resp.Body.Close()
|
|
body, err := ioutil.ReadAll(resp.Body)
|
|
if err != nil {
|
|
t.Fatalf("Got an error reading the body: %v\n", err)
|
|
}
|
|
r := server.Routez{}
|
|
if err := json.Unmarshal(body, &r); err != nil {
|
|
t.Fatalf("Got an error unmarshalling the body: %v\n", err)
|
|
}
|
|
return &r
|
|
}
|