get.pme.sh/pnats@v0.0.0-20240304004023-26bb5a137ed0/test/monitor_test.go (about) 1 // Copyright 2012-2020 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 "crypto/tls" 18 "crypto/x509" 19 "encoding/json" 20 "fmt" 21 "io" 22 "net" 23 "net/http" 24 "os" 25 "strings" 26 "sync" 27 "sync/atomic" 28 "testing" 29 "time" 30 31 "get.pme.sh/pnats/server" 32 "github.com/nats-io/nats.go" 33 ) 34 35 const CLIENT_PORT = 11422 36 const MONITOR_PORT = 11522 37 38 func runMonitorServer() *server.Server { 39 resetPreviousHTTPConnections() 40 opts := DefaultTestOptions 41 opts.Port = CLIENT_PORT 42 opts.HTTPPort = MONITOR_PORT 43 opts.HTTPHost = "127.0.0.1" 44 opts.NoSystemAccount = true 45 return RunServer(&opts) 46 } 47 48 // Runs a clustered pair of monitor servers for testing the /routez endpoint 49 func runMonitorServerClusteredPair(t *testing.T) (*server.Server, *server.Server) { 50 resetPreviousHTTPConnections() 51 opts := DefaultTestOptions 52 opts.Port = CLIENT_PORT 53 opts.HTTPPort = MONITOR_PORT 54 opts.HTTPHost = "127.0.0.1" 55 opts.Cluster = server.ClusterOpts{Name: "M", Host: "127.0.0.1", Port: 10223} 56 opts.Routes = server.RoutesFromStr("nats-route://127.0.0.1:10222") 57 opts.NoSystemAccount = true 58 59 s1 := RunServer(&opts) 60 61 opts2 := DefaultTestOptions 62 opts2.Port = CLIENT_PORT + 1 63 opts2.HTTPPort = MONITOR_PORT + 1 64 opts2.HTTPHost = "127.0.0.1" 65 opts2.Cluster = server.ClusterOpts{Name: "M", Host: "127.0.0.1", Port: 10222} 66 opts2.Routes = server.RoutesFromStr("nats-route://127.0.0.1:10223") 67 opts2.NoSystemAccount = true 68 69 s2 := RunServer(&opts2) 70 71 checkClusterFormed(t, s1, s2) 72 73 return s1, s2 74 } 75 76 func runMonitorServerNoHTTPPort() *server.Server { 77 resetPreviousHTTPConnections() 78 opts := DefaultTestOptions 79 opts.Port = CLIENT_PORT 80 opts.HTTPPort = 0 81 opts.NoSystemAccount = true 82 83 return RunServer(&opts) 84 } 85 86 func resetPreviousHTTPConnections() { 87 http.DefaultTransport.(*http.Transport).CloseIdleConnections() 88 } 89 90 // Make sure that we do not run the http server for monitoring unless asked. 91 func TestNoMonitorPort(t *testing.T) { 92 s := runMonitorServerNoHTTPPort() 93 defer s.Shutdown() 94 95 url := fmt.Sprintf("http://127.0.0.1:%d/", MONITOR_PORT) 96 if resp, err := http.Get(url + "varz"); err == nil { 97 t.Fatalf("Expected error: Got %+v\n", resp) 98 } 99 if resp, err := http.Get(url + "healthz"); err == nil { 100 t.Fatalf("Expected error: Got %+v\n", resp) 101 } 102 if resp, err := http.Get(url + "connz"); err == nil { 103 t.Fatalf("Expected error: Got %+v\n", resp) 104 } 105 } 106 107 // testEndpointDataRace tests a monitoring endpoint for data races by polling 108 // while client code acts to ensure statistics are updated. It is designed to 109 // run under the -race flag to catch violations. The caller must start the 110 // NATS server. 111 func testEndpointDataRace(endpoint string, t *testing.T) { 112 var doneWg sync.WaitGroup 113 114 url := fmt.Sprintf("http://127.0.0.1:%d/", MONITOR_PORT) 115 116 // Poll as fast as we can, while creating connections, publishing, 117 // and subscribing. 118 clientDone := int64(0) 119 doneWg.Add(1) 120 go func() { 121 for atomic.LoadInt64(&clientDone) == 0 { 122 resp, err := http.Get(url + endpoint) 123 if err != nil { 124 t.Errorf("Expected no error: Got %v\n", err) 125 } else { 126 resp.Body.Close() 127 } 128 } 129 doneWg.Done() 130 }() 131 132 // create connections, subscriptions, and publish messages to 133 // update the monitor variables. 134 var conns []net.Conn 135 for i := 0; i < 50; i++ { 136 cl := createClientConnSubscribeAndPublish(t) 137 // keep a few connections around to test monitor variables. 138 if i%10 == 0 { 139 conns = append(conns, cl) 140 } else { 141 cl.Close() 142 } 143 } 144 atomic.AddInt64(&clientDone, 1) 145 146 // wait for the endpoint polling goroutine to exit 147 doneWg.Wait() 148 149 // cleanup the conns 150 for _, cl := range conns { 151 cl.Close() 152 } 153 } 154 155 func TestEndpointDataRaces(t *testing.T) { 156 // setup a small cluster to test /routez 157 s1, s2 := runMonitorServerClusteredPair(t) 158 defer s1.Shutdown() 159 defer s2.Shutdown() 160 161 // test all of our endpoints 162 testEndpointDataRace("varz", t) 163 testEndpointDataRace("connz", t) 164 testEndpointDataRace("routez", t) 165 testEndpointDataRace("subsz", t) 166 testEndpointDataRace("stacksz", t) 167 } 168 169 func TestVarz(t *testing.T) { 170 s := runMonitorServer() 171 defer s.Shutdown() 172 173 url := fmt.Sprintf("http://127.0.0.1:%d/", MONITOR_PORT) 174 resp, err := http.Get(url + "varz") 175 if err != nil { 176 t.Fatalf("Expected no error: Got %v\n", err) 177 } 178 if resp.StatusCode != 200 { 179 t.Fatalf("Expected a 200 response, got %d\n", resp.StatusCode) 180 } 181 defer resp.Body.Close() 182 body, err := io.ReadAll(resp.Body) 183 if err != nil { 184 t.Fatalf("Got an error reading the body: %v\n", err) 185 } 186 187 v := server.Varz{} 188 if err := json.Unmarshal(body, &v); err != nil { 189 t.Fatalf("Got an error unmarshalling the body: %v\n", err) 190 } 191 192 // Do some sanity checks on values 193 if time.Since(v.Start) > 10*time.Second { 194 t.Fatal("Expected start time to be within 10 seconds.") 195 } 196 197 cl := createClientConnSubscribeAndPublish(t) 198 defer cl.Close() 199 200 resp, err = http.Get(url + "varz") 201 if err != nil { 202 t.Fatalf("Expected no error: Got %v\n", err) 203 } 204 if resp.StatusCode != 200 { 205 t.Fatalf("Expected a 200 response, got %d\n", resp.StatusCode) 206 } 207 defer resp.Body.Close() 208 body, err = io.ReadAll(resp.Body) 209 if err != nil { 210 t.Fatalf("Got an error reading the body: %v\n", err) 211 } 212 213 if strings.Contains(string(body), "cluster_port") { 214 t.Fatal("Varz body contains cluster information when no cluster is defined.") 215 } 216 217 v = server.Varz{} 218 if err := json.Unmarshal(body, &v); err != nil { 219 t.Fatalf("Got an error unmarshalling the body: %v\n", err) 220 } 221 222 if v.Connections != 1 { 223 t.Fatalf("Expected Connections of 1, got %v\n", v.Connections) 224 } 225 if v.InMsgs != 1 { 226 t.Fatalf("Expected InMsgs of 1, got %v\n", v.InMsgs) 227 } 228 if v.OutMsgs != 1 { 229 t.Fatalf("Expected OutMsgs of 1, got %v\n", v.OutMsgs) 230 } 231 if v.InBytes != 5 { 232 t.Fatalf("Expected InBytes of 5, got %v\n", v.InBytes) 233 } 234 if v.OutBytes != 5 { 235 t.Fatalf("Expected OutBytes of 5, got %v\n", v.OutBytes) 236 } 237 if v.MaxPending != server.MAX_PENDING_SIZE { 238 t.Fatalf("Expected MaxPending of %d, got %v\n", 239 server.MAX_PENDING_SIZE, v.MaxPending) 240 } 241 if v.WriteDeadline != server.DEFAULT_FLUSH_DEADLINE { 242 t.Fatalf("Expected WriteDeadline of %d, got %v\n", 243 server.DEFAULT_FLUSH_DEADLINE, v.WriteDeadline) 244 } 245 } 246 247 func TestConnz(t *testing.T) { 248 s := runMonitorServer() 249 defer s.Shutdown() 250 251 url := fmt.Sprintf("http://127.0.0.1:%d/", MONITOR_PORT) 252 resp, err := http.Get(url + "connz") 253 if err != nil { 254 t.Fatalf("Expected no error: Got %v\n", err) 255 } 256 if resp.StatusCode != 200 { 257 t.Fatalf("Expected a 200 response, got %d\n", resp.StatusCode) 258 } 259 defer resp.Body.Close() 260 body, err := io.ReadAll(resp.Body) 261 if err != nil { 262 t.Fatalf("Got an error reading the body: %v\n", err) 263 } 264 265 c := server.Connz{} 266 if err := json.Unmarshal(body, &c); err != nil { 267 t.Fatalf("Got an error unmarshalling the body: %v\n", err) 268 } 269 270 // Test contents.. 271 if c.NumConns != 0 { 272 t.Fatalf("Expected 0 connections, got %d\n", c.NumConns) 273 } 274 if c.Total != 0 { 275 t.Fatalf("Expected 0 live connections, got %d\n", c.Total) 276 } 277 if c.Conns == nil || len(c.Conns) != 0 { 278 t.Fatalf("Expected 0 connections in array, got %p\n", c.Conns) 279 } 280 281 cl := createClientConnSubscribeAndPublish(t) 282 defer cl.Close() 283 284 resp, err = http.Get(url + "connz") 285 if err != nil { 286 t.Fatalf("Expected no error: Got %v\n", err) 287 } 288 if resp.StatusCode != 200 { 289 t.Fatalf("Expected a 200 response, got %d\n", resp.StatusCode) 290 } 291 defer resp.Body.Close() 292 body, err = io.ReadAll(resp.Body) 293 if err != nil { 294 t.Fatalf("Got an error reading the body: %v\n", err) 295 } 296 if err := json.Unmarshal(body, &c); err != nil { 297 t.Fatalf("Got an error unmarshalling the body: %v\n", err) 298 } 299 300 if c.NumConns != 1 { 301 t.Fatalf("Expected 1 connection, got %d\n", c.NumConns) 302 } 303 if c.Total != 1 { 304 t.Fatalf("Expected 1 live connection, got %d\n", c.Total) 305 } 306 if c.Conns == nil || len(c.Conns) != 1 { 307 t.Fatalf("Expected 1 connection in array, got %p\n", c.Conns) 308 } 309 310 if c.Limit != server.DefaultConnListSize { 311 t.Fatalf("Expected limit of %d, got %v\n", server.DefaultConnListSize, c.Limit) 312 } 313 314 if c.Offset != 0 { 315 t.Fatalf("Expected offset of 0, got %v\n", c.Offset) 316 } 317 318 // Test inside details of each connection 319 ci := c.Conns[0] 320 321 if ci.Cid == 0 { 322 t.Fatalf("Expected non-zero cid, got %v\n", ci.Cid) 323 } 324 if ci.IP != "127.0.0.1" { 325 t.Fatalf("Expected \"127.0.0.1\" for IP, got %v\n", ci.IP) 326 } 327 if ci.Port == 0 { 328 t.Fatalf("Expected non-zero port, got %v\n", ci.Port) 329 } 330 if ci.NumSubs != 1 { 331 t.Fatalf("Expected num_subs of 1, got %v\n", ci.NumSubs) 332 } 333 if len(ci.Subs) != 0 { 334 t.Fatalf("Expected subs of 0, got %v\n", ci.Subs) 335 } 336 if ci.InMsgs != 1 { 337 t.Fatalf("Expected InMsgs of 1, got %v\n", ci.InMsgs) 338 } 339 if ci.OutMsgs != 1 { 340 t.Fatalf("Expected OutMsgs of 1, got %v\n", ci.OutMsgs) 341 } 342 if ci.InBytes != 5 { 343 t.Fatalf("Expected InBytes of 1, got %v\n", ci.InBytes) 344 } 345 if ci.OutBytes != 5 { 346 t.Fatalf("Expected OutBytes of 1, got %v\n", ci.OutBytes) 347 } 348 } 349 350 func TestTLSConnz(t *testing.T) { 351 srv, opts := RunServerWithConfig("./configs/tls.conf") 352 defer srv.Shutdown() 353 rootCAFile := "./configs/certs/ca.pem" 354 clientCertFile := "./configs/certs/client-cert.pem" 355 clientKeyFile := "./configs/certs/client-key.pem" 356 357 // Test with secure connection 358 endpoint := fmt.Sprintf("%s:%d", opts.Host, opts.Port) 359 nurl := fmt.Sprintf("tls://%s:%s@%s/", opts.Username, opts.Password, endpoint) 360 nc, err := nats.Connect(nurl, nats.RootCAs(rootCAFile)) 361 if err != nil { 362 t.Fatalf("Got an error on Connect with Secure Options: %+v\n", err) 363 } 364 defer nc.Close() 365 ch := make(chan struct{}) 366 nc.Subscribe("foo", func(m *nats.Msg) { ch <- struct{}{} }) 367 nc.Publish("foo", []byte("Hello")) 368 369 // Wait for message 370 <-ch 371 372 url := fmt.Sprintf("https://127.0.0.1:%d/", opts.HTTPSPort) 373 tlsConfig := &tls.Config{} 374 caCert, err := os.ReadFile(rootCAFile) 375 if err != nil { 376 t.Fatalf("Got error reading RootCA file: %s", err) 377 } 378 caCertPool := x509.NewCertPool() 379 caCertPool.AppendCertsFromPEM(caCert) 380 tlsConfig.RootCAs = caCertPool 381 382 cert, err := tls.LoadX509KeyPair(clientCertFile, clientKeyFile) 383 if err != nil { 384 t.Fatalf("Got error reading client certificates: %s", err) 385 } 386 tlsConfig.Certificates = []tls.Certificate{cert} 387 transport := &http.Transport{TLSClientConfig: tlsConfig} 388 httpClient := &http.Client{Transport: transport} 389 390 resp, err := httpClient.Get(url + "connz") 391 if err != nil { 392 t.Fatalf("Expected no error: Got %v\n", err) 393 } 394 if resp.StatusCode != 200 { 395 t.Fatalf("Expected a 200 response, got %d\n", resp.StatusCode) 396 } 397 defer resp.Body.Close() 398 body, err := io.ReadAll(resp.Body) 399 400 if err != nil { 401 t.Fatalf("Got an error reading the body: %v\n", err) 402 } 403 c := server.Connz{} 404 if err := json.Unmarshal(body, &c); err != nil { 405 t.Fatalf("Got an error unmarshalling the body: %v\n", err) 406 } 407 408 if c.NumConns != 1 { 409 t.Fatalf("Expected 1 connection, got %d\n", c.NumConns) 410 } 411 if c.Total != 1 { 412 t.Fatalf("Expected 1 live connection, got %d\n", c.Total) 413 } 414 if c.Conns == nil || len(c.Conns) != 1 { 415 t.Fatalf("Expected 1 connection in array, got %d\n", len(c.Conns)) 416 } 417 418 // Test inside details of each connection 419 ci := c.Conns[0] 420 421 if ci.Cid == 0 { 422 t.Fatalf("Expected non-zero cid, got %v\n", ci.Cid) 423 } 424 if ci.IP != "127.0.0.1" { 425 t.Fatalf("Expected \"127.0.0.1\" for IP, got %v\n", ci.IP) 426 } 427 if ci.Port == 0 { 428 t.Fatalf("Expected non-zero port, got %v\n", ci.Port) 429 } 430 if ci.NumSubs != 1 { 431 t.Fatalf("Expected num_subs of 1, got %v\n", ci.NumSubs) 432 } 433 if len(ci.Subs) != 0 { 434 t.Fatalf("Expected subs of 0, got %v\n", ci.Subs) 435 } 436 if ci.InMsgs != 1 { 437 t.Fatalf("Expected InMsgs of 1, got %v\n", ci.InMsgs) 438 } 439 if ci.OutMsgs != 1 { 440 t.Fatalf("Expected OutMsgs of 1, got %v\n", ci.OutMsgs) 441 } 442 if ci.InBytes != 5 { 443 t.Fatalf("Expected InBytes of 1, got %v\n", ci.InBytes) 444 } 445 if ci.OutBytes != 5 { 446 t.Fatalf("Expected OutBytes of 1, got %v\n", ci.OutBytes) 447 } 448 if ci.Start.IsZero() { 449 t.Fatalf("Expected Start to be valid\n") 450 } 451 if ci.Uptime == "" { 452 t.Fatalf("Expected Uptime to be valid\n") 453 } 454 if ci.LastActivity.IsZero() { 455 t.Fatalf("Expected LastActivity to be valid\n") 456 } 457 if ci.LastActivity.UnixNano() < ci.Start.UnixNano() { 458 t.Fatalf("Expected LastActivity [%v] to be > Start [%v]\n", ci.LastActivity, ci.Start) 459 } 460 if ci.Idle == "" { 461 t.Fatalf("Expected Idle to be valid\n") 462 } 463 } 464 465 func TestConnzWithSubs(t *testing.T) { 466 s := runMonitorServer() 467 defer s.Shutdown() 468 469 cl := createClientConnSubscribeAndPublish(t) 470 defer cl.Close() 471 472 url := fmt.Sprintf("http://127.0.0.1:%d/", MONITOR_PORT) 473 resp, err := http.Get(url + "connz?subs=1") 474 if err != nil { 475 t.Fatalf("Expected no error: Got %v\n", err) 476 } 477 if resp.StatusCode != 200 { 478 t.Fatalf("Expected a 200 response, got %d\n", resp.StatusCode) 479 } 480 defer resp.Body.Close() 481 body, err := io.ReadAll(resp.Body) 482 if err != nil { 483 t.Fatalf("Got an error reading the body: %v\n", err) 484 } 485 486 c := server.Connz{} 487 if err := json.Unmarshal(body, &c); err != nil { 488 t.Fatalf("Got an error unmarshalling the body: %v\n", err) 489 } 490 491 // Test inside details of each connection 492 ci := c.Conns[0] 493 if len(ci.Subs) != 1 || ci.Subs[0] != "foo" { 494 t.Fatalf("Expected subs of 1, got %v\n", ci.Subs) 495 } 496 } 497 498 func TestConnzWithAuth(t *testing.T) { 499 srv, opts := RunServerWithConfig("./configs/multi_user.conf") 500 defer srv.Shutdown() 501 502 endpoint := fmt.Sprintf("%s:%d", opts.Host, opts.Port) 503 curl := fmt.Sprintf("nats://%s:%s@%s/", opts.Users[0].Username, opts.Users[0].Password, endpoint) 504 nc, err := nats.Connect(curl) 505 if err != nil { 506 t.Fatalf("Got an error on Connect: %+v\n", err) 507 } 508 defer nc.Close() 509 510 ch := make(chan struct{}) 511 nc.Subscribe("foo", func(m *nats.Msg) { ch <- struct{}{} }) 512 nc.Publish("foo", []byte("Hello")) 513 514 // Wait for message 515 <-ch 516 517 url := fmt.Sprintf("http://127.0.0.1:%d/", opts.HTTPPort) 518 519 resp, err := http.Get(url + "connz?auth=1") 520 if err != nil { 521 t.Fatalf("Expected no error: Got %v\n", err) 522 } 523 if resp.StatusCode != 200 { 524 t.Fatalf("Expected a 200 response, got %d\n", resp.StatusCode) 525 } 526 defer resp.Body.Close() 527 body, err := io.ReadAll(resp.Body) 528 if err != nil { 529 t.Fatalf("Got an error reading the body: %v\n", err) 530 } 531 532 c := server.Connz{} 533 if err := json.Unmarshal(body, &c); err != nil { 534 t.Fatalf("Got an error unmarshalling the body: %v\n", err) 535 } 536 537 // Test that we have authorized_user and its Alice. 538 ci := c.Conns[0] 539 if ci.AuthorizedUser != opts.Users[0].Username { 540 t.Fatalf("Expected authorized_user to be %q, got %q\n", 541 opts.Users[0].Username, ci.AuthorizedUser) 542 } 543 } 544 545 func TestConnzWithAccounts(t *testing.T) { 546 resetPreviousHTTPConnections() 547 s, opts := RunServerWithConfig("./configs/multi_accounts.conf") 548 defer s.Shutdown() 549 550 endpoint := fmt.Sprintf("%s:%d", opts.Host, opts.Port) 551 552 // Connect all the users. Tests depend on knowing users, accounts. 553 if len(opts.Users) != 6 { 554 t.Fatalf("Expected 6 total users, got %d", len(opts.Users)) 555 } 556 if len(opts.Accounts) != 3 { 557 t.Fatalf("Expected 3 total accounts, got %d", len(opts.Accounts)) 558 } 559 560 // Map from user to account name. 561 utoa := make(map[string]string) 562 conns := make([]*nats.Conn, len(opts.Users)) 563 for _, u := range opts.Users { 564 nc, err := nats.Connect(fmt.Sprintf("nats://%s:%s@%s/", u.Username, u.Password, endpoint)) 565 if err != nil { 566 t.Fatalf("Got an error on Connect: %+v\n", err) 567 } 568 defer nc.Close() 569 utoa[u.Username] = u.Account.Name 570 conns = append(conns, nc) 571 } 572 573 url := fmt.Sprintf("http://127.0.0.1:%d/", opts.HTTPPort) 574 575 grabConnz := func(args string) *server.Connz { 576 t.Helper() 577 if args != "" { 578 args = "&" + args 579 } 580 resp, err := http.Get(url + "connz?auth=1" + args) 581 if err != nil { 582 t.Fatalf("Expected no error: Got %v\n", err) 583 } 584 if resp.StatusCode != 200 { 585 t.Fatalf("Expected a 200 response, got %d\n", resp.StatusCode) 586 } 587 defer resp.Body.Close() 588 body, err := io.ReadAll(resp.Body) 589 if err != nil { 590 t.Fatalf("Got an error reading the body: %v\n", err) 591 } 592 c := server.Connz{} 593 if err := json.Unmarshal(body, &c); err != nil { 594 t.Fatalf("Got an error unmarshalling the body: %v\n", err) 595 } 596 return &c 597 } 598 599 c := grabConnz("") 600 if c.NumConns != 6 { 601 t.Fatalf("Expected 6 connection entries, got %d", c.NumConns) 602 } 603 604 checkConn := func(ci *server.ConnInfo) { 605 t.Helper() 606 user := ci.AuthorizedUser 607 account := utoa[user] 608 if user == "" || account == "" { 609 t.Fatalf("Empty user or account: %q - %q", user, account) 610 } 611 if ci.Account != account { 612 t.Fatalf("Expected account of %q, got %q", account, ci.Account) 613 } 614 } 615 616 for i, ci := range c.Conns { 617 if ci.Cid != uint64(i+1) { 618 t.Fatalf("Expected CID of %d, got %d", i+1, ci.Cid) 619 } 620 checkConn(ci) 621 } 622 623 // Now make sure we can pull connections by account and user 624 pullByAccount := func(accName, state string) { 625 t.Helper() 626 c = grabConnz("acc=" + accName + "&state=" + state) 627 if c.NumConns != 2 { 628 t.Fatalf("Expected 2 connection entries, got %d", c.NumConns) 629 } 630 for _, ci := range c.Conns { 631 if ci.Account != accName { 632 t.Fatalf("Expected %q account, go %q", accName, ci.Account) 633 } 634 } 635 } 636 637 pullByUser := func(user, state string) { 638 t.Helper() 639 c = grabConnz("user=" + user + "&state=" + state) 640 if c.NumConns != 1 { 641 t.Fatalf("Expected 1 connection, got %d", c.NumConns) 642 } 643 if c.Conns[0].AuthorizedUser != user { 644 t.Fatalf("Expected user %q, got %q", user, c.Conns[0].AuthorizedUser) 645 } 646 } 647 648 pullByAccount("engineering", "open") 649 pullByAccount("finance", "open") 650 pullByAccount("legal", "open") 651 652 pullByUser("alice", "open") 653 pullByUser("bob", "open") 654 655 pullByUser("john", "open") 656 pullByUser("mary", "open") 657 658 pullByUser("peter", "open") 659 pullByUser("paul", "open") 660 661 // Now closed and make sure these work on closed as well. 662 for _, nc := range conns { 663 nc.Close() 664 } 665 666 checkFor(t, time.Second, 10*time.Millisecond, func() error { 667 if numClients := s.NumClients(); numClients != 0 { 668 return fmt.Errorf("Number of client is %d", numClients) 669 } 670 return nil 671 }) 672 673 pullByAccount("engineering", "closed") 674 pullByAccount("finance", "closed") 675 pullByAccount("legal", "closed") 676 677 pullByUser("alice", "closed") 678 pullByUser("bob", "closed") 679 680 pullByUser("john", "closed") 681 pullByUser("mary", "closed") 682 683 pullByUser("peter", "closed") 684 pullByUser("paul", "closed") 685 } 686 687 func TestConnzWithOffsetAndLimit(t *testing.T) { 688 s := runMonitorServer() 689 defer s.Shutdown() 690 691 cl1 := createClientConnSubscribeAndPublish(t) 692 defer cl1.Close() 693 694 cl2 := createClientConnSubscribeAndPublish(t) 695 defer cl2.Close() 696 697 url := fmt.Sprintf("http://127.0.0.1:%d/", MONITOR_PORT) 698 resp, err := http.Get(url + "connz?offset=1&limit=1") 699 if err != nil { 700 t.Fatalf("Expected no error: Got %v\n", err) 701 } 702 if resp.StatusCode != 200 { 703 t.Fatalf("Expected a 200 response, got %d\n", resp.StatusCode) 704 } 705 defer resp.Body.Close() 706 body, err := io.ReadAll(resp.Body) 707 if err != nil { 708 t.Fatalf("Got an error reading the body: %v\n", err) 709 } 710 711 c := server.Connz{} 712 if err := json.Unmarshal(body, &c); err != nil { 713 t.Fatalf("Got an error unmarshalling the body: %v\n", err) 714 } 715 716 if c.Limit != 1 { 717 t.Fatalf("Expected limit of 1, got %v\n", c.Limit) 718 } 719 720 if c.Offset != 1 { 721 t.Fatalf("Expected offset of 1, got %v\n", c.Offset) 722 } 723 724 if len(c.Conns) != 1 { 725 t.Fatalf("Expected conns of 1, got %v\n", len(c.Conns)) 726 } 727 } 728 729 func TestSubsz(t *testing.T) { 730 s := runMonitorServer() 731 defer s.Shutdown() 732 733 cl := createClientConnSubscribeAndPublish(t) 734 defer cl.Close() 735 736 url := fmt.Sprintf("http://127.0.0.1:%d/", MONITOR_PORT) 737 resp, err := http.Get(url + "subscriptionsz") 738 if err != nil { 739 t.Fatalf("Expected no error: Got %v\n", err) 740 } 741 if resp.StatusCode != 200 { 742 t.Fatalf("Expected a 200 response, got %d\n", resp.StatusCode) 743 } 744 defer resp.Body.Close() 745 body, err := io.ReadAll(resp.Body) 746 if err != nil { 747 t.Fatalf("Got an error reading the body: %v\n", err) 748 } 749 750 su := server.Subsz{} 751 if err := json.Unmarshal(body, &su); err != nil { 752 t.Fatalf("Got an error unmarshalling the body: %v\n", err) 753 } 754 755 // Do some sanity checks on values 756 if su.NumSubs != 1 { 757 t.Fatalf("Expected num_subs of 1, got %v\n", su.NumSubs) 758 } 759 } 760 761 func TestHTTPHost(t *testing.T) { 762 s := runMonitorServer() 763 defer s.Shutdown() 764 765 // Grab non-127.0.0.1 address and try to use that to connect. 766 // Should fail. 767 var ip net.IP 768 ifaces, _ := net.Interfaces() 769 for _, i := range ifaces { 770 addrs, _ := i.Addrs() 771 for _, addr := range addrs { 772 switch v := addr.(type) { 773 case *net.IPNet: 774 ip = v.IP 775 case *net.IPAddr: 776 ip = v.IP 777 } 778 // Skip loopback/127.0.0.1 or any ipv6 for now. 779 if ip.IsLoopback() || ip.To4() == nil { 780 ip = nil 781 continue 782 } 783 break 784 } 785 if ip != nil { 786 break 787 } 788 } 789 if ip == nil { 790 t.Fatalf("Could not find non-loopback IPV4 address") 791 } 792 url := fmt.Sprintf("http://%v:%d/", ip, MONITOR_PORT) 793 if resp, err := http.Get(url + "varz"); err == nil { 794 t.Fatalf("Expected error: Got %+v\n", resp) 795 } 796 } 797 798 // Create a connection to test ConnInfo 799 func createClientConnSubscribeAndPublish(t *testing.T) net.Conn { 800 cl := createClientConn(t, "127.0.0.1", CLIENT_PORT) 801 send, expect := setupConn(t, cl) 802 expectMsgs := expectMsgsCommand(t, expect) 803 804 send("SUB foo 1\r\nPUB foo 5\r\nhello\r\n") 805 expectMsgs(1) 806 807 return cl 808 } 809 810 func TestMonitorNoTLSConfig(t *testing.T) { 811 opts := DefaultTestOptions 812 opts.Port = CLIENT_PORT 813 opts.HTTPHost = "127.0.0.1" 814 opts.HTTPSPort = MONITOR_PORT 815 s := server.New(&opts) 816 defer s.Shutdown() 817 // Check with manually starting the monitoring, which should return an error 818 if err := s.StartMonitoring(); err == nil || !strings.Contains(err.Error(), "TLS") { 819 t.Fatalf("Expected error about missing TLS config, got %v", err) 820 } 821 // Also check by calling Start(), which should produce a fatal error 822 dl := &dummyLogger{} 823 s.SetLogger(dl, false, false) 824 defer s.SetLogger(nil, false, false) 825 s.Start() 826 if !strings.Contains(dl.msg, "TLS") { 827 t.Fatalf("Expected error about missing TLS config, got %v", dl.msg) 828 } 829 } 830 831 func TestMonitorErrorOnListen(t *testing.T) { 832 s := runMonitorServer() 833 defer s.Shutdown() 834 835 opts := DefaultTestOptions 836 opts.Port = CLIENT_PORT + 1 837 opts.HTTPHost = "127.0.0.1" 838 opts.HTTPPort = MONITOR_PORT 839 s2 := server.New(&opts) 840 defer s2.Shutdown() 841 if err := s2.StartMonitoring(); err == nil || !strings.Contains(err.Error(), "listen") { 842 t.Fatalf("Expected error about not able to start listener, got %v", err) 843 } 844 } 845 846 func TestMonitorBothPortsConfigured(t *testing.T) { 847 opts := DefaultTestOptions 848 opts.Port = CLIENT_PORT 849 opts.HTTPHost = "127.0.0.1" 850 opts.HTTPPort = MONITOR_PORT 851 opts.HTTPSPort = MONITOR_PORT + 1 852 s := server.New(&opts) 853 defer s.Shutdown() 854 if err := s.StartMonitoring(); err == nil || !strings.Contains(err.Error(), "specify both") { 855 t.Fatalf("Expected error about ports configured, got %v", err) 856 } 857 } 858 859 func TestMonitorStop(t *testing.T) { 860 resetPreviousHTTPConnections() 861 opts := DefaultTestOptions 862 opts.Port = CLIENT_PORT 863 opts.HTTPHost = "127.0.0.1" 864 opts.HTTPPort = MONITOR_PORT 865 url := fmt.Sprintf("http://%v:%d/", opts.HTTPHost, MONITOR_PORT) 866 // Create a server instance and start only the monitoring http server. 867 s := server.New(&opts) 868 if err := s.StartMonitoring(); err != nil { 869 t.Fatalf("Error starting monitoring: %v", err) 870 } 871 // Make sure http server is started 872 resp, err := http.Get(url + "varz") 873 if err != nil { 874 t.Fatalf("Error on http request: %v", err) 875 } 876 resp.Body.Close() 877 // Although the server itself was not started (we did not call s.Start()), 878 // Shutdown() should stop the http server. 879 s.Shutdown() 880 // HTTP request should now fail 881 if resp, err := http.Get(url + "varz"); err == nil { 882 t.Fatalf("Expected error: Got %+v\n", resp) 883 } 884 }