github.com/nats-io/nats-server/v2@v2.11.0-preview.2/server/monitor_test.go (about)

     1  // Copyright 2013-2023 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 server
    15  
    16  import (
    17  	"bytes"
    18  	"crypto/tls"
    19  	"encoding/json"
    20  	"errors"
    21  	"fmt"
    22  	"io"
    23  	"math/rand"
    24  	"net"
    25  	"net/http"
    26  	"net/url"
    27  	"os"
    28  	"reflect"
    29  	"runtime"
    30  	"sort"
    31  	"strings"
    32  	"sync"
    33  	"testing"
    34  	"time"
    35  	"unicode"
    36  
    37  	"github.com/nats-io/jwt/v2"
    38  	"github.com/nats-io/nats.go"
    39  	"github.com/nats-io/nkeys"
    40  )
    41  
    42  const CLIENT_PORT = -1
    43  const MONITOR_PORT = -1
    44  const CLUSTER_PORT = -1
    45  
    46  func DefaultMonitorOptions() *Options {
    47  	return &Options{
    48  		Host:         "127.0.0.1",
    49  		Port:         CLIENT_PORT,
    50  		HTTPHost:     "127.0.0.1",
    51  		HTTPPort:     MONITOR_PORT,
    52  		HTTPBasePath: "/",
    53  		ServerName:   "monitor_server",
    54  		NoLog:        true,
    55  		NoSigs:       true,
    56  		Tags:         []string{"tag"},
    57  	}
    58  }
    59  
    60  func runMonitorServer() *Server {
    61  	resetPreviousHTTPConnections()
    62  	opts := DefaultMonitorOptions()
    63  	opts.NoSystemAccount = true
    64  	return RunServer(opts)
    65  }
    66  
    67  func runMonitorServerWithAccounts() *Server {
    68  	resetPreviousHTTPConnections()
    69  	opts := DefaultMonitorOptions()
    70  	opts.NoSystemAccount = true
    71  	aA := NewAccount("A")
    72  	aB := NewAccount("B")
    73  	opts.Accounts = append(opts.Accounts, aA, aB)
    74  	opts.Users = append(opts.Users,
    75  		&User{Username: "a", Password: "a", Account: aA},
    76  		&User{Username: "b", Password: "b", Account: aB})
    77  	return RunServer(opts)
    78  }
    79  
    80  func runMonitorServerNoHTTPPort() *Server {
    81  	resetPreviousHTTPConnections()
    82  	opts := DefaultMonitorOptions()
    83  	opts.NoSystemAccount = true
    84  	opts.HTTPPort = 0
    85  	return RunServer(opts)
    86  }
    87  
    88  func resetPreviousHTTPConnections() {
    89  	http.DefaultTransport.(*http.Transport).CloseIdleConnections()
    90  }
    91  
    92  func TestMyUptime(t *testing.T) {
    93  	// Make sure we print this stuff right.
    94  	var d time.Duration
    95  	var s string
    96  
    97  	d = 22 * time.Second
    98  	s = myUptime(d)
    99  	if s != "22s" {
   100  		t.Fatalf("Expected `22s`, go ``%s`", s)
   101  	}
   102  	d = 4*time.Minute + d
   103  	s = myUptime(d)
   104  	if s != "4m22s" {
   105  		t.Fatalf("Expected `4m22s`, go ``%s`", s)
   106  	}
   107  	d = 4*time.Hour + d
   108  	s = myUptime(d)
   109  	if s != "4h4m22s" {
   110  		t.Fatalf("Expected `4h4m22s`, go ``%s`", s)
   111  	}
   112  	d = 32*24*time.Hour + d
   113  	s = myUptime(d)
   114  	if s != "32d4h4m22s" {
   115  		t.Fatalf("Expected `32d4h4m22s`, go ``%s`", s)
   116  	}
   117  	d = 22*365*24*time.Hour + d
   118  	s = myUptime(d)
   119  	if s != "22y32d4h4m22s" {
   120  		t.Fatalf("Expected `22y32d4h4m22s`, go ``%s`", s)
   121  	}
   122  }
   123  
   124  // Make sure that we do not run the http server for monitoring unless asked.
   125  func TestNoMonitorPort(t *testing.T) {
   126  	s := runMonitorServerNoHTTPPort()
   127  	defer s.Shutdown()
   128  
   129  	// this test might be meaningless now that we're testing with random ports?
   130  	url := fmt.Sprintf("http://127.0.0.1:%d/", 11245)
   131  	if resp, err := http.Get(url + "varz"); err == nil {
   132  		t.Fatalf("Expected error: Got %+v\n", resp)
   133  	}
   134  	if resp, err := http.Get(url + "healthz"); err == nil {
   135  		t.Fatalf("Expected error: Got %+v\n", resp)
   136  	}
   137  	if resp, err := http.Get(url + "connz"); err == nil {
   138  		t.Fatalf("Expected error: Got %+v\n", resp)
   139  	}
   140  }
   141  
   142  var (
   143  	appJSONContent = "application/json"
   144  	appJSContent   = "application/javascript"
   145  	textPlain      = "text/plain; charset=utf-8"
   146  	textHTML       = "text/html; charset=utf-8"
   147  )
   148  
   149  func readBodyEx(t *testing.T, url string, status int, content string) []byte {
   150  	t.Helper()
   151  	resp, err := http.Get(url)
   152  	if err != nil {
   153  		t.Fatalf("Expected no error: Got %v\n", err)
   154  	}
   155  	defer resp.Body.Close()
   156  	if resp.StatusCode != status {
   157  		t.Fatalf("Expected a %d response, got %d\n", status, resp.StatusCode)
   158  	}
   159  	ct := resp.Header.Get("Content-Type")
   160  	if ct != content {
   161  		t.Fatalf("Expected %q content-type, got %q\n", content, ct)
   162  	}
   163  	// Check the CORS header for "application/json" requests only.
   164  	if ct == appJSONContent {
   165  		acao := resp.Header.Get("Access-Control-Allow-Origin")
   166  		if acao != "*" {
   167  			t.Fatalf("Expected with %q Content-Type an Access-Control-Allow-Origin header with value %q, got %q\n", appJSONContent, "*", acao)
   168  		}
   169  	}
   170  	body, err := io.ReadAll(resp.Body)
   171  	if err != nil {
   172  		t.Fatalf("Got an error reading the body: %v\n", err)
   173  	}
   174  	return body
   175  }
   176  
   177  func TestHTTPBasePath(t *testing.T) {
   178  	resetPreviousHTTPConnections()
   179  	opts := DefaultMonitorOptions()
   180  	opts.NoSystemAccount = true
   181  	opts.HTTPBasePath = "/nats"
   182  
   183  	s := RunServer(opts)
   184  	defer s.Shutdown()
   185  
   186  	url := fmt.Sprintf("http://127.0.0.1:%d/nats", s.MonitorAddr().Port)
   187  	readBodyEx(t, url, http.StatusOK, textHTML)
   188  }
   189  
   190  func readBody(t *testing.T, url string) []byte {
   191  	return readBodyEx(t, url, http.StatusOK, appJSONContent)
   192  }
   193  
   194  func pollVarz(t *testing.T, s *Server, mode int, url string, opts *VarzOptions) *Varz {
   195  	t.Helper()
   196  	if mode == 0 {
   197  		v := &Varz{}
   198  		body := readBody(t, url)
   199  		if err := json.Unmarshal(body, v); err != nil {
   200  			t.Fatalf("Got an error unmarshalling the body: %v\n", err)
   201  		}
   202  		return v
   203  	}
   204  	v, err := s.Varz(opts)
   205  	if err != nil {
   206  		t.Fatalf("Error on Varz: %v", err)
   207  	}
   208  	return v
   209  }
   210  
   211  // https://github.com/nats-io/nats-server/issues/2170
   212  // Just the ever increasing subs part.
   213  func TestVarzSubscriptionsResetProperly(t *testing.T) {
   214  	// Run with JS to create a bunch of subs to start.
   215  	resetPreviousHTTPConnections()
   216  	opts := DefaultMonitorOptions()
   217  	opts.JetStream = true
   218  	s := RunServer(opts)
   219  	defer s.Shutdown()
   220  
   221  	// This bug seems to only happen via the http endpoint, not direct calls.
   222  	// Every time you call it doubles.
   223  	url := fmt.Sprintf("http://127.0.0.1:%d/varz", s.MonitorAddr().Port)
   224  	osubs := pollVarz(t, s, 0, url, nil).Subscriptions
   225  	// Make sure we get same number back.
   226  	if v := pollVarz(t, s, 0, url, nil); v.Subscriptions != osubs {
   227  		t.Fatalf("Expected subs to stay the same, %d vs %d", osubs, v.Subscriptions)
   228  	}
   229  }
   230  
   231  func TestHandleVarz(t *testing.T) {
   232  	s := runMonitorServer()
   233  	defer s.Shutdown()
   234  
   235  	url := fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
   236  
   237  	for mode := 0; mode < 2; mode++ {
   238  		v := pollVarz(t, s, mode, url+"varz", nil)
   239  
   240  		// Do some sanity checks on values
   241  		if time.Since(v.Start) > 10*time.Second {
   242  			t.Fatal("Expected start time to be within 10 seconds.")
   243  		}
   244  	}
   245  
   246  	time.Sleep(100 * time.Millisecond)
   247  
   248  	nc := createClientConnSubscribeAndPublish(t, s)
   249  	defer nc.Close()
   250  
   251  	for mode := 0; mode < 2; mode++ {
   252  		v := pollVarz(t, s, mode, url+"varz", nil)
   253  
   254  		if v.Connections != 1 {
   255  			t.Fatalf("Expected Connections of 1, got %v\n", v.Connections)
   256  		}
   257  		if v.TotalConnections < 1 {
   258  			t.Fatalf("Expected Total Connections of at least 1, got %v\n", v.TotalConnections)
   259  		}
   260  		if v.InMsgs != 1 {
   261  			t.Fatalf("Expected InMsgs of 1, got %v\n", v.InMsgs)
   262  		}
   263  		if v.OutMsgs != 1 {
   264  			t.Fatalf("Expected OutMsgs of 1, got %v\n", v.OutMsgs)
   265  		}
   266  		if v.InBytes != 5 {
   267  			t.Fatalf("Expected InBytes of 5, got %v\n", v.InBytes)
   268  		}
   269  		if v.OutBytes != 5 {
   270  			t.Fatalf("Expected OutBytes of 5, got %v\n", v.OutBytes)
   271  		}
   272  		if v.Subscriptions != 0 {
   273  			t.Fatalf("Expected Subscriptions of 0, got %v\n", v.Subscriptions)
   274  		}
   275  		if v.Name != "monitor_server" {
   276  			t.Fatal("Expected ServerName to be 'monitor_server'")
   277  		}
   278  		if !v.Tags.Contains("tag") {
   279  			t.Fatal("Expected tags to be 'tag'")
   280  		}
   281  	}
   282  
   283  	// Test JSONP
   284  	readBodyEx(t, url+"varz?callback=callback", http.StatusOK, appJSContent)
   285  }
   286  
   287  func pollConz(t *testing.T, s *Server, mode int, url string, opts *ConnzOptions) *Connz {
   288  	t.Helper()
   289  	if mode == 0 {
   290  		body := readBody(t, url)
   291  		c := &Connz{}
   292  		if err := json.Unmarshal(body, &c); err != nil {
   293  			t.Fatalf("Got an error unmarshalling the body: %v\n", err)
   294  		}
   295  		return c
   296  	}
   297  	c, err := s.Connz(opts)
   298  	if err != nil {
   299  		t.Fatalf("Error on Connz(): %v", err)
   300  	}
   301  	return c
   302  }
   303  
   304  func TestConnz(t *testing.T) {
   305  	s := runMonitorServer()
   306  	defer s.Shutdown()
   307  
   308  	url := fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
   309  
   310  	testConnz := func(mode int) {
   311  		c := pollConz(t, s, mode, url+"connz", nil)
   312  
   313  		// Test contents..
   314  		if c.NumConns != 0 {
   315  			t.Fatalf("Expected 0 connections, got %d\n", c.NumConns)
   316  		}
   317  		if c.Total != 0 {
   318  			t.Fatalf("Expected 0 live connections, got %d\n", c.Total)
   319  		}
   320  		if c.Conns == nil || len(c.Conns) != 0 {
   321  			t.Fatalf("Expected 0 connections in array, got %p\n", c.Conns)
   322  		}
   323  
   324  		// Test with connections.
   325  		nc := createClientConnSubscribeAndPublish(t, s)
   326  		defer nc.Close()
   327  
   328  		time.Sleep(50 * time.Millisecond)
   329  
   330  		c = pollConz(t, s, mode, url+"connz", nil)
   331  
   332  		if c.NumConns != 1 {
   333  			t.Fatalf("Expected 1 connection, got %d\n", c.NumConns)
   334  		}
   335  		if c.Total != 1 {
   336  			t.Fatalf("Expected 1 live connection, got %d\n", c.Total)
   337  		}
   338  		if c.Conns == nil || len(c.Conns) != 1 {
   339  			t.Fatalf("Expected 1 connection in array, got %d\n", len(c.Conns))
   340  		}
   341  
   342  		if c.Limit != DefaultConnListSize {
   343  			t.Fatalf("Expected limit of %d, got %v\n", DefaultConnListSize, c.Limit)
   344  		}
   345  
   346  		if c.Offset != 0 {
   347  			t.Fatalf("Expected offset of 0, got %v\n", c.Offset)
   348  		}
   349  
   350  		// Test inside details of each connection
   351  		ci := c.Conns[0]
   352  
   353  		if ci.Cid == 0 {
   354  			t.Fatalf("Expected non-zero cid, got %v\n", ci.Cid)
   355  		}
   356  		if ci.IP != "127.0.0.1" {
   357  			t.Fatalf("Expected \"127.0.0.1\" for IP, got %v\n", ci.IP)
   358  		}
   359  		if ci.Port == 0 {
   360  			t.Fatalf("Expected non-zero port, got %v\n", ci.Port)
   361  		}
   362  		if ci.NumSubs != 0 {
   363  			t.Fatalf("Expected num_subs of 0, got %v\n", ci.NumSubs)
   364  		}
   365  		if len(ci.Subs) != 0 {
   366  			t.Fatalf("Expected subs of 0, got %v\n", ci.Subs)
   367  		}
   368  		if len(ci.SubsDetail) != 0 {
   369  			t.Fatalf("Expected subsdetail of 0, got %v\n", ci.SubsDetail)
   370  		}
   371  		if ci.InMsgs != 1 {
   372  			t.Fatalf("Expected InMsgs of 1, got %v\n", ci.InMsgs)
   373  		}
   374  		if ci.OutMsgs != 1 {
   375  			t.Fatalf("Expected OutMsgs of 1, got %v\n", ci.OutMsgs)
   376  		}
   377  		if ci.InBytes != 5 {
   378  			t.Fatalf("Expected InBytes of 1, got %v\n", ci.InBytes)
   379  		}
   380  		if ci.OutBytes != 5 {
   381  			t.Fatalf("Expected OutBytes of 1, got %v\n", ci.OutBytes)
   382  		}
   383  		if ci.Start.IsZero() {
   384  			t.Fatal("Expected Start to be valid\n")
   385  		}
   386  		if ci.Uptime == "" {
   387  			t.Fatal("Expected Uptime to be valid\n")
   388  		}
   389  		if ci.LastActivity.IsZero() {
   390  			t.Fatal("Expected LastActivity to be valid\n")
   391  		}
   392  		if ci.LastActivity.UnixNano() < ci.Start.UnixNano() {
   393  			t.Fatalf("Expected LastActivity [%v] to be > Start [%v]\n", ci.LastActivity, ci.Start)
   394  		}
   395  		if ci.Idle == "" {
   396  			t.Fatal("Expected Idle to be valid\n")
   397  		}
   398  		// This is a change, we now expect them to be set for connections when the
   399  		// client sends a connect.
   400  		if ci.RTT == "" {
   401  			t.Fatal("Expected RTT to be set for new connection\n")
   402  		}
   403  	}
   404  
   405  	for mode := 0; mode < 2; mode++ {
   406  		testConnz(mode)
   407  		checkClientsCount(t, s, 0)
   408  	}
   409  
   410  	// Test JSONP
   411  	readBodyEx(t, url+"connz?callback=callback", http.StatusOK, appJSContent)
   412  }
   413  
   414  func TestConnzBadParams(t *testing.T) {
   415  	s := runMonitorServer()
   416  	defer s.Shutdown()
   417  
   418  	url := fmt.Sprintf("http://127.0.0.1:%d/connz?", s.MonitorAddr().Port)
   419  	readBodyEx(t, url+"auth=xxx", http.StatusBadRequest, textPlain)
   420  	readBodyEx(t, url+"subs=xxx", http.StatusBadRequest, textPlain)
   421  	readBodyEx(t, url+"offset=xxx", http.StatusBadRequest, textPlain)
   422  	readBodyEx(t, url+"limit=xxx", http.StatusBadRequest, textPlain)
   423  	readBodyEx(t, url+"state=xxx", http.StatusBadRequest, textPlain)
   424  }
   425  
   426  func TestConnzWithSubs(t *testing.T) {
   427  	s := runMonitorServer()
   428  	defer s.Shutdown()
   429  
   430  	nc := createClientConnSubscribeAndPublish(t, s)
   431  	defer nc.Close()
   432  
   433  	nc.Subscribe("hello.foo", func(m *nats.Msg) {})
   434  	ensureServerActivityRecorded(t, nc)
   435  
   436  	url := fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
   437  	for mode := 0; mode < 2; mode++ {
   438  		c := pollConz(t, s, mode, url+"connz?subs=1", &ConnzOptions{Subscriptions: true})
   439  		// Test inside details of each connection
   440  		ci := c.Conns[0]
   441  		if len(ci.Subs) != 1 || ci.Subs[0] != "hello.foo" {
   442  			t.Fatalf("Expected subs of 1, got %v\n", ci.Subs)
   443  		}
   444  	}
   445  }
   446  
   447  func TestConnzWithSubsDetail(t *testing.T) {
   448  	s := runMonitorServer()
   449  	defer s.Shutdown()
   450  
   451  	nc := createClientConnSubscribeAndPublish(t, s)
   452  	defer nc.Close()
   453  
   454  	nc.Subscribe("hello.foo", func(m *nats.Msg) {})
   455  	ensureServerActivityRecorded(t, nc)
   456  
   457  	url := fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
   458  	for mode := 0; mode < 2; mode++ {
   459  		c := pollConz(t, s, mode, url+"connz?subs=detail", &ConnzOptions{SubscriptionsDetail: true})
   460  		// Test inside details of each connection
   461  		ci := c.Conns[0]
   462  		if len(ci.SubsDetail) != 1 || ci.SubsDetail[0].Subject != "hello.foo" {
   463  			t.Fatalf("Expected subsdetail of 1, got %v\n", ci.Subs)
   464  		}
   465  	}
   466  }
   467  
   468  func TestClosedConnzWithSubsDetail(t *testing.T) {
   469  	s := runMonitorServer()
   470  	defer s.Shutdown()
   471  
   472  	nc := createClientConnSubscribeAndPublish(t, s)
   473  
   474  	nc.Subscribe("hello.foo", func(m *nats.Msg) {})
   475  	ensureServerActivityRecorded(t, nc)
   476  	nc.Close()
   477  
   478  	s.mu.Lock()
   479  	for len(s.clients) != 0 {
   480  		s.mu.Unlock()
   481  		<-time.After(100 * time.Millisecond)
   482  		s.mu.Lock()
   483  	}
   484  	s.mu.Unlock()
   485  
   486  	url := fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
   487  	for mode := 0; mode < 2; mode++ {
   488  		c := pollConz(t, s, mode, url+"connz?state=closed&subs=detail", &ConnzOptions{State: ConnClosed,
   489  			SubscriptionsDetail: true})
   490  		// Test inside details of each connection
   491  		ci := c.Conns[0]
   492  		if len(ci.SubsDetail) != 1 || ci.SubsDetail[0].Subject != "hello.foo" {
   493  			t.Fatalf("Expected subsdetail of 1, got %v\n", ci.Subs)
   494  		}
   495  	}
   496  }
   497  
   498  func TestConnzWithCID(t *testing.T) {
   499  	s := runMonitorServer()
   500  	defer s.Shutdown()
   501  
   502  	// The one we will request
   503  	cid := 5
   504  	total := 10
   505  
   506  	// Create 10
   507  	for i := 1; i <= total; i++ {
   508  		nc := createClientConnSubscribeAndPublish(t, s)
   509  		defer nc.Close()
   510  		if i == cid {
   511  			nc.Subscribe("hello.foo", func(m *nats.Msg) {})
   512  			nc.Subscribe("hello.bar", func(m *nats.Msg) {})
   513  			ensureServerActivityRecorded(t, nc)
   514  		}
   515  	}
   516  
   517  	url := fmt.Sprintf("http://127.0.0.1:%d/connz?cid=%d", s.MonitorAddr().Port, cid)
   518  	for mode := 0; mode < 2; mode++ {
   519  		c := pollConz(t, s, mode, url, &ConnzOptions{CID: uint64(cid)})
   520  		// Test inside details of each connection
   521  		if len(c.Conns) != 1 {
   522  			t.Fatalf("Expected only one connection, but got %d\n", len(c.Conns))
   523  		}
   524  		if c.NumConns != 1 {
   525  			t.Fatalf("Expected NumConns to be 1, but got %d\n", c.NumConns)
   526  		}
   527  		ci := c.Conns[0]
   528  		if ci.Cid != uint64(cid) {
   529  			t.Fatalf("Expected to receive connection %v, but received %v\n", cid, ci.Cid)
   530  		}
   531  		if ci.NumSubs != 2 {
   532  			t.Fatalf("Expected to receive connection with %d subs, but received %d\n", 2, ci.NumSubs)
   533  		}
   534  		// Now test a miss
   535  		badUrl := fmt.Sprintf("http://127.0.0.1:%d/connz?cid=%d", s.MonitorAddr().Port, 100)
   536  		c = pollConz(t, s, mode, badUrl, &ConnzOptions{CID: uint64(100)})
   537  		if len(c.Conns) != 0 {
   538  			t.Fatalf("Expected no connections, got %d\n", len(c.Conns))
   539  		}
   540  		if c.NumConns != 0 {
   541  			t.Fatalf("Expected NumConns of 0, got %d\n", c.NumConns)
   542  		}
   543  	}
   544  }
   545  
   546  // Helper to map to connection name
   547  func createConnMap(cz *Connz) map[string]*ConnInfo {
   548  	cm := make(map[string]*ConnInfo)
   549  	for _, c := range cz.Conns {
   550  		cm[c.Name] = c
   551  	}
   552  	return cm
   553  }
   554  
   555  func getFooAndBar(cm map[string]*ConnInfo) (*ConnInfo, *ConnInfo) {
   556  	return cm["foo"], cm["bar"]
   557  }
   558  
   559  func ensureServerActivityRecorded(t *testing.T, nc *nats.Conn) {
   560  	nc.Flush()
   561  	err := nc.Flush()
   562  	if err != nil {
   563  		t.Fatalf("Error flushing: %v\n", err)
   564  	}
   565  }
   566  
   567  func TestConnzRTT(t *testing.T) {
   568  	s := runMonitorServer()
   569  	defer s.Shutdown()
   570  
   571  	url := fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
   572  
   573  	testRTT := func(mode int) {
   574  		// Test with connections.
   575  		nc := createClientConnSubscribeAndPublish(t, s)
   576  		defer nc.Close()
   577  
   578  		c := pollConz(t, s, mode, url+"connz", nil)
   579  
   580  		if c.NumConns != 1 {
   581  			t.Fatalf("Expected 1 connection, got %d\n", c.NumConns)
   582  		}
   583  
   584  		// Send a server side PING to record RTT
   585  		s.mu.Lock()
   586  		ci := c.Conns[0]
   587  		sc := s.clients[ci.Cid]
   588  		if sc == nil {
   589  			t.Fatalf("Error looking up client %v\n", ci.Cid)
   590  		}
   591  		s.mu.Unlock()
   592  		sc.mu.Lock()
   593  		sc.sendPing()
   594  		sc.mu.Unlock()
   595  
   596  		// Wait for client to respond with PONG
   597  		time.Sleep(20 * time.Millisecond)
   598  
   599  		// Repoll for updated information.
   600  		c = pollConz(t, s, mode, url+"connz", nil)
   601  		ci = c.Conns[0]
   602  
   603  		rtt, err := time.ParseDuration(ci.RTT)
   604  		if err != nil {
   605  			t.Fatalf("Could not parse RTT properly, %v (ci.RTT=%v)", err, ci.RTT)
   606  		}
   607  		if rtt <= 0 {
   608  			t.Fatal("Expected RTT to be valid and non-zero\n")
   609  		}
   610  		if (runtime.GOOS == "windows" && rtt > 20*time.Millisecond) ||
   611  			rtt > 20*time.Millisecond || rtt < 100*time.Nanosecond {
   612  			t.Fatalf("Invalid RTT of %s\n", ci.RTT)
   613  		}
   614  	}
   615  
   616  	for mode := 0; mode < 2; mode++ {
   617  		testRTT(mode)
   618  		checkClientsCount(t, s, 0)
   619  	}
   620  }
   621  
   622  func TestConnzLastActivity(t *testing.T) {
   623  	s := runMonitorServer()
   624  	defer s.Shutdown()
   625  
   626  	url := fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
   627  	url += "connz?subs=1"
   628  	opts := &ConnzOptions{Subscriptions: true}
   629  
   630  	var sleepTime time.Duration
   631  	if runtime.GOOS == "windows" {
   632  		sleepTime = 10 * time.Millisecond
   633  	}
   634  
   635  	testActivity := func(mode int) {
   636  		ncFoo := createClientConnWithName(t, "foo", s)
   637  		defer ncFoo.Close()
   638  
   639  		ncBar := createClientConnWithName(t, "bar", s)
   640  		defer ncBar.Close()
   641  
   642  		// Test inside details of each connection
   643  		ciFoo, ciBar := getFooAndBar(createConnMap(pollConz(t, s, mode, url, opts)))
   644  
   645  		// Test that LastActivity is non-zero
   646  		if ciFoo.LastActivity.IsZero() {
   647  			t.Fatalf("Expected LastActivity for connection '%s'to be valid\n", ciFoo.Name)
   648  		}
   649  		if ciBar.LastActivity.IsZero() {
   650  			t.Fatalf("Expected LastActivity for connection '%s'to be valid\n", ciBar.Name)
   651  		}
   652  		// Foo should be older than Bar
   653  		if ciFoo.LastActivity.After(ciBar.LastActivity) {
   654  			t.Fatal("Expected connection 'foo' to be older than 'bar'\n")
   655  		}
   656  
   657  		fooLA := ciFoo.LastActivity
   658  		barLA := ciBar.LastActivity
   659  
   660  		ensureServerActivityRecorded(t, ncFoo)
   661  		ensureServerActivityRecorded(t, ncBar)
   662  
   663  		time.Sleep(sleepTime)
   664  
   665  		// Sub should trigger update.
   666  		sub, _ := ncFoo.Subscribe("hello.world", func(m *nats.Msg) {})
   667  		ensureServerActivityRecorded(t, ncFoo)
   668  
   669  		ciFoo, _ = getFooAndBar(createConnMap(pollConz(t, s, mode, url, opts)))
   670  		nextLA := ciFoo.LastActivity
   671  		if fooLA.Equal(nextLA) {
   672  			t.Fatalf("Subscribe should have triggered update to LastActivity %+v\n", ciFoo)
   673  		}
   674  		fooLA = nextLA
   675  
   676  		time.Sleep(sleepTime)
   677  
   678  		// Publish and Message Delivery should trigger as well. So both connections
   679  		// should have updates.
   680  		ncBar.Publish("hello.world", []byte("Hello"))
   681  
   682  		ensureServerActivityRecorded(t, ncFoo)
   683  		ensureServerActivityRecorded(t, ncBar)
   684  
   685  		ciFoo, ciBar = getFooAndBar(createConnMap(pollConz(t, s, mode, url, opts)))
   686  		nextLA = ciBar.LastActivity
   687  		if barLA.Equal(nextLA) {
   688  			t.Fatalf("Publish should have triggered update to LastActivity\n")
   689  		}
   690  
   691  		// Message delivery on ncFoo should have triggered as well.
   692  		nextLA = ciFoo.LastActivity
   693  		if fooLA.Equal(nextLA) {
   694  			t.Fatalf("Message delivery should have triggered update to LastActivity\n")
   695  		}
   696  		fooLA = nextLA
   697  
   698  		time.Sleep(sleepTime)
   699  
   700  		// Unsub should trigger as well
   701  		sub.Unsubscribe()
   702  		ensureServerActivityRecorded(t, ncFoo)
   703  
   704  		ciFoo, _ = getFooAndBar(createConnMap(pollConz(t, s, mode, url, opts)))
   705  		nextLA = ciFoo.LastActivity
   706  		if fooLA.Equal(nextLA) {
   707  			t.Fatalf("Message delivery should have triggered update to LastActivity\n")
   708  		}
   709  	}
   710  
   711  	for mode := 0; mode < 2; mode++ {
   712  		testActivity(mode)
   713  	}
   714  }
   715  
   716  func TestConnzWithOffsetAndLimit(t *testing.T) {
   717  	s := runMonitorServer()
   718  	defer s.Shutdown()
   719  
   720  	url := fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
   721  
   722  	for mode := 0; mode < 2; mode++ {
   723  		c := pollConz(t, s, mode, url+"connz?offset=1&limit=1", &ConnzOptions{Offset: 1, Limit: 1})
   724  		if c.Conns == nil || len(c.Conns) != 0 {
   725  			t.Fatalf("Expected 0 connections in array, got %p\n", c.Conns)
   726  		}
   727  
   728  		// Test that when given negative values, 0 or default is used
   729  		c = pollConz(t, s, mode, url+"connz?offset=-1&limit=-1", &ConnzOptions{Offset: -11, Limit: -11})
   730  		if c.Conns == nil || len(c.Conns) != 0 {
   731  			t.Fatalf("Expected 0 connections in array, got %p\n", c.Conns)
   732  		}
   733  		if c.Offset != 0 {
   734  			t.Fatalf("Expected offset to be 0, and limit to be %v, got %v and %v",
   735  				DefaultConnListSize, c.Offset, c.Limit)
   736  		}
   737  	}
   738  
   739  	cl1 := createClientConnSubscribeAndPublish(t, s)
   740  	defer cl1.Close()
   741  
   742  	cl2 := createClientConnSubscribeAndPublish(t, s)
   743  	defer cl2.Close()
   744  
   745  	for mode := 0; mode < 2; mode++ {
   746  		c := pollConz(t, s, mode, url+"connz?offset=1&limit=1", &ConnzOptions{Offset: 1, Limit: 1})
   747  		if c.Limit != 1 {
   748  			t.Fatalf("Expected limit of 1, got %v\n", c.Limit)
   749  		}
   750  
   751  		if c.Offset != 1 {
   752  			t.Fatalf("Expected offset of 1, got %v\n", c.Offset)
   753  		}
   754  
   755  		if len(c.Conns) != 1 {
   756  			t.Fatalf("Expected conns of 1, got %v\n", len(c.Conns))
   757  		}
   758  
   759  		if c.NumConns != 1 {
   760  			t.Fatalf("Expected NumConns to be 1, got %v\n", c.NumConns)
   761  		}
   762  
   763  		if c.Total != 2 {
   764  			t.Fatalf("Expected Total to be at least 2, got %v", c.Total)
   765  		}
   766  
   767  		c = pollConz(t, s, mode, url+"connz?offset=2&limit=1", &ConnzOptions{Offset: 2, Limit: 1})
   768  		if c.Limit != 1 {
   769  			t.Fatalf("Expected limit of 1, got %v\n", c.Limit)
   770  		}
   771  
   772  		if c.Offset != 2 {
   773  			t.Fatalf("Expected offset of 2, got %v\n", c.Offset)
   774  		}
   775  
   776  		if len(c.Conns) != 0 {
   777  			t.Fatalf("Expected conns of 0, got %v\n", len(c.Conns))
   778  		}
   779  
   780  		if c.NumConns != 0 {
   781  			t.Fatalf("Expected NumConns to be 0, got %v\n", c.NumConns)
   782  		}
   783  
   784  		if c.Total != 2 {
   785  			t.Fatalf("Expected Total to be 2, got %v", c.Total)
   786  		}
   787  	}
   788  }
   789  
   790  func TestConnzDefaultSorted(t *testing.T) {
   791  	s := runMonitorServer()
   792  	defer s.Shutdown()
   793  
   794  	clients := make([]*nats.Conn, 4)
   795  	for i := range clients {
   796  		clients[i] = createClientConnSubscribeAndPublish(t, s)
   797  		defer clients[i].Close()
   798  	}
   799  
   800  	url := fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
   801  	for mode := 0; mode < 2; mode++ {
   802  		c := pollConz(t, s, mode, url+"connz", nil)
   803  		if c.Conns[0].Cid > c.Conns[1].Cid ||
   804  			c.Conns[1].Cid > c.Conns[2].Cid ||
   805  			c.Conns[2].Cid > c.Conns[3].Cid {
   806  			t.Fatalf("Expected conns sorted in ascending order by cid, got %v < %v\n", c.Conns[0].Cid, c.Conns[3].Cid)
   807  		}
   808  	}
   809  }
   810  
   811  func TestConnzSortedByCid(t *testing.T) {
   812  	s := runMonitorServer()
   813  	defer s.Shutdown()
   814  
   815  	clients := make([]*nats.Conn, 4)
   816  	for i := range clients {
   817  		clients[i] = createClientConnSubscribeAndPublish(t, s)
   818  		defer clients[i].Close()
   819  	}
   820  
   821  	url := fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
   822  	for mode := 0; mode < 2; mode++ {
   823  		c := pollConz(t, s, mode, url+"connz?sort=cid", &ConnzOptions{Sort: ByCid})
   824  		if c.Conns[0].Cid > c.Conns[1].Cid ||
   825  			c.Conns[1].Cid > c.Conns[2].Cid ||
   826  			c.Conns[2].Cid > c.Conns[3].Cid {
   827  			t.Fatalf("Expected conns sorted in ascending order by cid, got [%v, %v, %v, %v]\n",
   828  				c.Conns[0].Cid, c.Conns[1].Cid, c.Conns[2].Cid, c.Conns[3].Cid)
   829  		}
   830  	}
   831  }
   832  
   833  func TestConnzSortedByStart(t *testing.T) {
   834  	s := runMonitorServer()
   835  	defer s.Shutdown()
   836  
   837  	clients := make([]*nats.Conn, 4)
   838  	for i := range clients {
   839  		clients[i] = createClientConnSubscribeAndPublish(t, s)
   840  		defer clients[i].Close()
   841  	}
   842  
   843  	url := fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
   844  	for mode := 0; mode < 2; mode++ {
   845  		c := pollConz(t, s, mode, url+"connz?sort=start", &ConnzOptions{Sort: ByStart})
   846  		if c.Conns[0].Start.After(c.Conns[1].Start) ||
   847  			c.Conns[1].Start.After(c.Conns[2].Start) ||
   848  			c.Conns[2].Start.After(c.Conns[3].Start) {
   849  			t.Fatalf("Expected conns sorted in ascending order by startime, got [%v, %v, %v, %v]\n",
   850  				c.Conns[0].Start, c.Conns[1].Start, c.Conns[2].Start, c.Conns[3].Start)
   851  		}
   852  	}
   853  }
   854  
   855  func TestConnzSortedByBytesAndMsgs(t *testing.T) {
   856  	s := runMonitorServer()
   857  	defer s.Shutdown()
   858  
   859  	// Create a connection and make it send more messages than others
   860  	firstClient := createClientConnSubscribeAndPublish(t, s)
   861  	for i := 0; i < 100; i++ {
   862  		firstClient.Publish("foo", []byte("Hello World"))
   863  	}
   864  	defer firstClient.Close()
   865  	firstClient.Flush()
   866  
   867  	clients := make([]*nats.Conn, 3)
   868  	for i := range clients {
   869  		clients[i] = createClientConnSubscribeAndPublish(t, s)
   870  		defer clients[i].Close()
   871  	}
   872  
   873  	url := fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
   874  	for mode := 0; mode < 2; mode++ {
   875  		c := pollConz(t, s, mode, url+"connz?sort=bytes_to", &ConnzOptions{Sort: ByOutBytes})
   876  		if c.Conns[0].OutBytes < c.Conns[1].OutBytes ||
   877  			c.Conns[0].OutBytes < c.Conns[2].OutBytes ||
   878  			c.Conns[0].OutBytes < c.Conns[3].OutBytes {
   879  			t.Fatalf("Expected conns sorted in descending order by bytes to, got %v < one of [%v, %v, %v]\n",
   880  				c.Conns[0].OutBytes, c.Conns[1].OutBytes, c.Conns[2].OutBytes, c.Conns[3].OutBytes)
   881  		}
   882  
   883  		c = pollConz(t, s, mode, url+"connz?sort=msgs_to", &ConnzOptions{Sort: ByOutMsgs})
   884  		if c.Conns[0].OutMsgs < c.Conns[1].OutMsgs ||
   885  			c.Conns[0].OutMsgs < c.Conns[2].OutMsgs ||
   886  			c.Conns[0].OutMsgs < c.Conns[3].OutMsgs {
   887  			t.Fatalf("Expected conns sorted in descending order by msgs from, got %v < one of [%v, %v, %v]\n",
   888  				c.Conns[0].OutMsgs, c.Conns[1].OutMsgs, c.Conns[2].OutMsgs, c.Conns[3].OutMsgs)
   889  		}
   890  
   891  		c = pollConz(t, s, mode, url+"connz?sort=bytes_from", &ConnzOptions{Sort: ByInBytes})
   892  		if c.Conns[0].InBytes < c.Conns[1].InBytes ||
   893  			c.Conns[0].InBytes < c.Conns[2].InBytes ||
   894  			c.Conns[0].InBytes < c.Conns[3].InBytes {
   895  			t.Fatalf("Expected conns sorted in descending order by bytes from, got %v < one of [%v, %v, %v]\n",
   896  				c.Conns[0].InBytes, c.Conns[1].InBytes, c.Conns[2].InBytes, c.Conns[3].InBytes)
   897  		}
   898  
   899  		c = pollConz(t, s, mode, url+"connz?sort=msgs_from", &ConnzOptions{Sort: ByInMsgs})
   900  		if c.Conns[0].InMsgs < c.Conns[1].InMsgs ||
   901  			c.Conns[0].InMsgs < c.Conns[2].InMsgs ||
   902  			c.Conns[0].InMsgs < c.Conns[3].InMsgs {
   903  			t.Fatalf("Expected conns sorted in descending order by msgs from, got %v < one of [%v, %v, %v]\n",
   904  				c.Conns[0].InMsgs, c.Conns[1].InMsgs, c.Conns[2].InMsgs, c.Conns[3].InMsgs)
   905  		}
   906  	}
   907  }
   908  
   909  func TestConnzSortedByPending(t *testing.T) {
   910  	s := runMonitorServer()
   911  	defer s.Shutdown()
   912  
   913  	firstClient := createClientConnSubscribeAndPublish(t, s)
   914  	firstClient.Subscribe("hello.world", func(m *nats.Msg) {})
   915  	clients := make([]*nats.Conn, 3)
   916  	for i := range clients {
   917  		clients[i] = createClientConnSubscribeAndPublish(t, s)
   918  		defer clients[i].Close()
   919  	}
   920  	defer firstClient.Close()
   921  
   922  	url := fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
   923  	for mode := 0; mode < 2; mode++ {
   924  		c := pollConz(t, s, mode, url+"connz?sort=pending", &ConnzOptions{Sort: ByPending})
   925  		if c.Conns[0].Pending < c.Conns[1].Pending ||
   926  			c.Conns[0].Pending < c.Conns[2].Pending ||
   927  			c.Conns[0].Pending < c.Conns[3].Pending {
   928  			t.Fatalf("Expected conns sorted in descending order by number of pending, got %v < one of [%v, %v, %v]\n",
   929  				c.Conns[0].Pending, c.Conns[1].Pending, c.Conns[2].Pending, c.Conns[3].Pending)
   930  		}
   931  	}
   932  }
   933  
   934  func TestConnzSortedBySubs(t *testing.T) {
   935  	s := runMonitorServer()
   936  	defer s.Shutdown()
   937  
   938  	firstClient := createClientConnSubscribeAndPublish(t, s)
   939  	firstClient.Subscribe("hello.world", func(m *nats.Msg) {})
   940  	defer firstClient.Close()
   941  
   942  	clients := make([]*nats.Conn, 3)
   943  	for i := range clients {
   944  		clients[i] = createClientConnSubscribeAndPublish(t, s)
   945  		defer clients[i].Close()
   946  	}
   947  
   948  	url := fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
   949  	for mode := 0; mode < 2; mode++ {
   950  		c := pollConz(t, s, mode, url+"connz?sort=subs", &ConnzOptions{Sort: BySubs})
   951  		if c.Conns[0].NumSubs < c.Conns[1].NumSubs ||
   952  			c.Conns[0].NumSubs < c.Conns[2].NumSubs ||
   953  			c.Conns[0].NumSubs < c.Conns[3].NumSubs {
   954  			t.Fatalf("Expected conns sorted in descending order by number of subs, got %v < one of [%v, %v, %v]\n",
   955  				c.Conns[0].NumSubs, c.Conns[1].NumSubs, c.Conns[2].NumSubs, c.Conns[3].NumSubs)
   956  		}
   957  	}
   958  }
   959  
   960  func TestConnzSortedByLast(t *testing.T) {
   961  	resetPreviousHTTPConnections()
   962  	opts := DefaultMonitorOptions()
   963  	opts.NoSystemAccount = true
   964  	s := RunServer(opts)
   965  	defer s.Shutdown()
   966  
   967  	firstClient := createClientConnSubscribeAndPublish(t, s)
   968  	defer firstClient.Close()
   969  	firstClient.Subscribe("hello.world", func(m *nats.Msg) {})
   970  	firstClient.Flush()
   971  
   972  	clients := make([]*nats.Conn, 3)
   973  	for i := range clients {
   974  		clients[i] = createClientConnSubscribeAndPublish(t, s)
   975  		defer clients[i].Close()
   976  		clients[i].Flush()
   977  	}
   978  
   979  	url := fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
   980  	for mode := 0; mode < 2; mode++ {
   981  		c := pollConz(t, s, mode, url+"connz?sort=last", &ConnzOptions{Sort: ByLast})
   982  		if c.Conns[0].LastActivity.UnixNano() < c.Conns[1].LastActivity.UnixNano() ||
   983  			c.Conns[1].LastActivity.UnixNano() < c.Conns[2].LastActivity.UnixNano() ||
   984  			c.Conns[2].LastActivity.UnixNano() < c.Conns[3].LastActivity.UnixNano() {
   985  			t.Fatalf("Expected conns sorted in descending order by lastActivity, got %v < one of [%v, %v, %v]\n",
   986  				c.Conns[0].LastActivity, c.Conns[1].LastActivity, c.Conns[2].LastActivity, c.Conns[3].LastActivity)
   987  		}
   988  	}
   989  }
   990  
   991  func TestConnzSortedByUptime(t *testing.T) {
   992  	s := runMonitorServer()
   993  	defer s.Shutdown()
   994  
   995  	for i := 0; i < 4; i++ {
   996  		client := createClientConnSubscribeAndPublish(t, s)
   997  		defer client.Close()
   998  		// Since we check times (now-start) does not have to be big.
   999  		time.Sleep(50 * time.Millisecond)
  1000  	}
  1001  
  1002  	url := fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
  1003  	for mode := 0; mode < 2; mode++ {
  1004  		c := pollConz(t, s, mode, url+"connz?sort=uptime", &ConnzOptions{Sort: ByUptime})
  1005  		now := time.Now()
  1006  		ups := make([]int, 4)
  1007  		for i := 0; i < 4; i++ {
  1008  			ups[i] = int(now.Sub(c.Conns[i].Start))
  1009  		}
  1010  		if !sort.IntsAreSorted(ups) {
  1011  			d := make([]time.Duration, 4)
  1012  			for i := 0; i < 4; i++ {
  1013  				d[i] = time.Duration(ups[i])
  1014  			}
  1015  			t.Fatalf("Expected conns sorted in ascending order by uptime (now-Start), got %+v\n", d)
  1016  		}
  1017  	}
  1018  }
  1019  
  1020  func TestConnzSortedByUptimeClosedConn(t *testing.T) {
  1021  	s := runMonitorServer()
  1022  	defer s.Shutdown()
  1023  
  1024  	for i := time.Duration(1); i <= 4; i++ {
  1025  		c := createClientConnSubscribeAndPublish(t, s)
  1026  
  1027  		// Grab client and asjust start time such that
  1028  		client := s.getClient(uint64(i))
  1029  		if client == nil {
  1030  			t.Fatalf("Could nopt retrieve client for %d\n", i)
  1031  		}
  1032  		client.mu.Lock()
  1033  		client.start = client.start.Add(-10 * (4 - i) * time.Second)
  1034  		client.mu.Unlock()
  1035  
  1036  		c.Close()
  1037  	}
  1038  
  1039  	checkClosedConns(t, s, 4, time.Second)
  1040  
  1041  	url := fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
  1042  	for mode := 0; mode < 2; mode++ {
  1043  		c := pollConz(t, s, mode, url+"connz?state=closed&sort=uptime", &ConnzOptions{State: ConnClosed, Sort: ByUptime})
  1044  		ups := make([]int, 4)
  1045  		for i := 0; i < 4; i++ {
  1046  			ups[i] = int(c.Conns[i].Stop.Sub(c.Conns[i].Start))
  1047  		}
  1048  		if !sort.IntsAreSorted(ups) {
  1049  			d := make([]time.Duration, 4)
  1050  			for i := 0; i < 4; i++ {
  1051  				d[i] = time.Duration(ups[i])
  1052  			}
  1053  			t.Fatalf("Expected conns sorted in ascending order by uptime, got %+v\n", d)
  1054  		}
  1055  	}
  1056  }
  1057  
  1058  func TestConnzSortedByStopOnOpen(t *testing.T) {
  1059  	s := runMonitorServer()
  1060  	defer s.Shutdown()
  1061  
  1062  	opts := s.getOpts()
  1063  	url := fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port)
  1064  
  1065  	// 4 clients
  1066  	for i := 0; i < 4; i++ {
  1067  		c, err := nats.Connect(url)
  1068  		if err != nil {
  1069  			t.Fatalf("Could not create client: %v\n", err)
  1070  		}
  1071  		defer c.Close()
  1072  	}
  1073  
  1074  	c, err := s.Connz(&ConnzOptions{Sort: ByStop})
  1075  	if err == nil {
  1076  		t.Fatalf("Expected err to be non-nil, got %+v\n", c)
  1077  	}
  1078  }
  1079  
  1080  func TestConnzSortedByStopTimeClosedConn(t *testing.T) {
  1081  	s := runMonitorServer()
  1082  	defer s.Shutdown()
  1083  
  1084  	opts := s.getOpts()
  1085  	url := fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port)
  1086  
  1087  	// 4 clients
  1088  	for i := 0; i < 4; i++ {
  1089  		c, err := nats.Connect(url)
  1090  		if err != nil {
  1091  			t.Fatalf("Could not create client: %v\n", err)
  1092  		}
  1093  		c.Close()
  1094  	}
  1095  	checkClosedConns(t, s, 4, time.Second)
  1096  
  1097  	// Now adjust the Stop times for these with some random values.
  1098  	s.mu.Lock()
  1099  	now := time.Now().UTC()
  1100  	ccs := s.closed.closedClients()
  1101  	for _, cc := range ccs {
  1102  		newStop := now.Add(time.Duration(rand.Int()%120) * -time.Minute)
  1103  		cc.Stop = &newStop
  1104  	}
  1105  	s.mu.Unlock()
  1106  
  1107  	url = fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
  1108  	for mode := 0; mode < 2; mode++ {
  1109  		c := pollConz(t, s, mode, url+"connz?state=closed&sort=stop", &ConnzOptions{State: ConnClosed, Sort: ByStop})
  1110  		ups := make([]int, 4)
  1111  		nowU := time.Now().UnixNano()
  1112  		for i := 0; i < 4; i++ {
  1113  			ups[i] = int(nowU - c.Conns[i].Stop.UnixNano())
  1114  		}
  1115  		if !sort.IntsAreSorted(ups) {
  1116  			d := make([]time.Duration, 4)
  1117  			for i := 0; i < 4; i++ {
  1118  				d[i] = time.Duration(ups[i])
  1119  			}
  1120  			t.Fatalf("Expected conns sorted in ascending order by stop time, got %+v\n", d)
  1121  		}
  1122  	}
  1123  }
  1124  
  1125  func TestConnzSortedByReason(t *testing.T) {
  1126  	s := runMonitorServer()
  1127  	defer s.Shutdown()
  1128  
  1129  	opts := s.getOpts()
  1130  	url := fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port)
  1131  
  1132  	// 20 clients
  1133  	for i := 0; i < 20; i++ {
  1134  		c, err := nats.Connect(url)
  1135  		if err != nil {
  1136  			t.Fatalf("Could not create client: %v\n", err)
  1137  		}
  1138  		c.Close()
  1139  	}
  1140  	checkClosedConns(t, s, 20, time.Second)
  1141  
  1142  	// Now adjust the Reasons for these with some random values.
  1143  	s.mu.Lock()
  1144  	ccs := s.closed.closedClients()
  1145  	max := int(ServerShutdown)
  1146  	for _, cc := range ccs {
  1147  		cc.Reason = ClosedState(rand.Int() % max).String()
  1148  	}
  1149  	s.mu.Unlock()
  1150  
  1151  	url = fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
  1152  	for mode := 0; mode < 2; mode++ {
  1153  		c := pollConz(t, s, mode, url+"connz?state=closed&sort=reason", &ConnzOptions{State: ConnClosed, Sort: ByReason})
  1154  		rs := make([]string, 20)
  1155  		for i := 0; i < 20; i++ {
  1156  			rs[i] = c.Conns[i].Reason
  1157  		}
  1158  		if !sort.StringsAreSorted(rs) {
  1159  			t.Fatalf("Expected conns sorted in order by stop reason, got %#v\n", rs)
  1160  		}
  1161  	}
  1162  }
  1163  
  1164  func TestConnzSortedByReasonOnOpen(t *testing.T) {
  1165  	s := runMonitorServer()
  1166  	defer s.Shutdown()
  1167  
  1168  	opts := s.getOpts()
  1169  	url := fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port)
  1170  
  1171  	// 4 clients
  1172  	for i := 0; i < 4; i++ {
  1173  		c, err := nats.Connect(url)
  1174  		if err != nil {
  1175  			t.Fatalf("Could not create client: %v\n", err)
  1176  		}
  1177  		defer c.Close()
  1178  	}
  1179  
  1180  	c, err := s.Connz(&ConnzOptions{Sort: ByReason})
  1181  	if err == nil {
  1182  		t.Fatalf("Expected err to be non-nil, got %+v\n", c)
  1183  	}
  1184  }
  1185  
  1186  func TestConnzSortedByIdle(t *testing.T) {
  1187  	s := runMonitorServer()
  1188  	defer s.Shutdown()
  1189  
  1190  	url := fmt.Sprintf("http://%s/connz?sort=idle", s.MonitorAddr())
  1191  	now := time.Now()
  1192  
  1193  	clients := []struct {
  1194  		start time.Time // Client start time.
  1195  		last  time.Time // Client last activity time.
  1196  	}{
  1197  		{start: now.Add(-10 * time.Second), last: now.Add(-5 * time.Second)},
  1198  		{start: now.Add(-20 * time.Second), last: now.Add(-10 * time.Second)},
  1199  		{start: now.Add(-3 * time.Second), last: now.Add(-2 * time.Second)},
  1200  		{start: now.Add(-30 * time.Second), last: now.Add(-20 * time.Second)},
  1201  	}
  1202  
  1203  	testIdle := func(mode int) {
  1204  		// Connect the specified number of clients.
  1205  		for _, c := range clients {
  1206  			clientConn := createClientConnSubscribeAndPublish(t, s)
  1207  			defer clientConn.Close()
  1208  
  1209  			cid, err := clientConn.GetClientID()
  1210  			if err != nil {
  1211  				t.Fatalf("error getting the client CID: %v", err)
  1212  			}
  1213  
  1214  			client := s.getClient(cid)
  1215  			if client == nil {
  1216  				t.Fatalf("error looking up client %d", cid)
  1217  			}
  1218  
  1219  			// Change the client's start and last activity times.
  1220  			client.mu.Lock()
  1221  			client.start = c.start
  1222  			client.last = c.last
  1223  			client.mu.Unlock()
  1224  		}
  1225  
  1226  		connz := pollConz(t, s, mode, url, &ConnzOptions{Sort: ByIdle})
  1227  
  1228  		wantConns := len(clients)
  1229  		gotConns := len(connz.Conns)
  1230  
  1231  		if gotConns != wantConns {
  1232  			t.Fatalf("want %d connections, got %d", wantConns, gotConns)
  1233  		}
  1234  
  1235  		idleDurations := getConnsIdleDurations(t, connz.Conns)
  1236  
  1237  		if !sortedDurationsDesc(idleDurations) {
  1238  			t.Errorf("want durations sorted in descending order, got %v", idleDurations)
  1239  		}
  1240  	}
  1241  
  1242  	for mode := 0; mode < 2; mode++ {
  1243  		testIdle(mode)
  1244  	}
  1245  }
  1246  
  1247  // getConnsIdleDurations returns a slice of parsed idle durations from a connection info slice.
  1248  func getConnsIdleDurations(t *testing.T, conns []*ConnInfo) []time.Duration {
  1249  	t.Helper()
  1250  
  1251  	durations := make([]time.Duration, 0, len(conns))
  1252  
  1253  	for _, conn := range conns {
  1254  		idle, err := time.ParseDuration(conn.Idle)
  1255  		if err != nil {
  1256  			t.Fatalf("error parsing duration %q: %v", conn.Idle, err)
  1257  		}
  1258  		durations = append(durations, idle)
  1259  	}
  1260  
  1261  	return durations
  1262  }
  1263  
  1264  // sortedDurationsDesc checks if a time.Duration slice is sorted in descending order.
  1265  func sortedDurationsDesc(durations []time.Duration) bool {
  1266  	return sort.SliceIsSorted(durations, func(i, j int) bool {
  1267  		// Must be longer than the next duration.
  1268  		return durations[i] > durations[j]
  1269  	})
  1270  }
  1271  
  1272  func TestConnzSortByIdleTime(t *testing.T) {
  1273  	now := time.Now().UTC()
  1274  
  1275  	cases := map[string]ConnInfos{
  1276  		"zero values": {{}, {}, {}, {}},
  1277  		"equal last activity times": {
  1278  			{Start: now.Add(-50 * time.Minute), LastActivity: now.Add(-time.Minute)},
  1279  			{Start: now.Add(-30 * time.Minute), LastActivity: now.Add(-time.Minute)},
  1280  			{Start: now.Add(-10 * time.Second), LastActivity: now.Add(-time.Minute)},
  1281  			{Start: now.Add(-2 * time.Hour), LastActivity: now.Add(-time.Minute)},
  1282  		},
  1283  		"last activity in the future": {
  1284  			{Start: now.Add(-50 * time.Minute), LastActivity: now.Add(10 * time.Minute)}, // +10m
  1285  			{Start: now.Add(-30 * time.Minute), LastActivity: now.Add(5 * time.Minute)},  // +5m
  1286  			{Start: now.Add(-24 * time.Hour), LastActivity: now.Add(2 * time.Second)},    // +2s
  1287  			{Start: now.Add(-10 * time.Second), LastActivity: now.Add(15 * time.Minute)}, // +15m
  1288  			{Start: now.Add(-2 * time.Hour), LastActivity: now.Add(time.Minute)},         // +1m
  1289  		},
  1290  		"unsorted": {
  1291  			{Start: now.Add(-50 * time.Minute), LastActivity: now.Add(-10 * time.Minute)}, // 10m ago
  1292  			{Start: now.Add(-30 * time.Minute), LastActivity: now.Add(-5 * time.Minute)},  // 5m ago
  1293  			{Start: now.Add(-24 * time.Hour), LastActivity: now.Add(-2 * time.Second)},    // 2s ago
  1294  			{Start: now.Add(-10 * time.Second), LastActivity: now.Add(-15 * time.Minute)}, // 15m ago
  1295  			{Start: now.Add(-2 * time.Hour), LastActivity: now.Add(-time.Minute)},         // 1m ago
  1296  		},
  1297  		"unsorted with zero value start time": {
  1298  			{LastActivity: now.Add(-10 * time.Minute)}, // 10m ago
  1299  			{LastActivity: now.Add(-5 * time.Minute)},  // 5m ago
  1300  			{LastActivity: now.Add(-2 * time.Second)},  // 2s ago
  1301  			{LastActivity: now.Add(-15 * time.Minute)}, // 15m ago
  1302  			{LastActivity: now.Add(-time.Minute)},      // 1m ago
  1303  		},
  1304  		"sorted": {
  1305  			{Start: now.Add(-24 * time.Hour), LastActivity: now.Add(-2 * time.Second)},    // 2s ago
  1306  			{Start: now.Add(-2 * time.Hour), LastActivity: now.Add(-time.Minute)},         // 1m ago
  1307  			{Start: now.Add(-30 * time.Minute), LastActivity: now.Add(-5 * time.Minute)},  // 5m ago
  1308  			{Start: now.Add(-50 * time.Minute), LastActivity: now.Add(-10 * time.Minute)}, // 10m ago
  1309  			{Start: now.Add(-10 * time.Second), LastActivity: now.Add(-15 * time.Minute)}, // 15m ago
  1310  		},
  1311  		"sorted with zero value start time": {
  1312  			{LastActivity: now.Add(-2 * time.Second)},  // 2s ago
  1313  			{LastActivity: now.Add(-time.Minute)},      // 1m ago
  1314  			{LastActivity: now.Add(-5 * time.Minute)},  // 5m ago
  1315  			{LastActivity: now.Add(-10 * time.Minute)}, // 10m ago
  1316  			{LastActivity: now.Add(-15 * time.Minute)}, // 15m ago
  1317  		},
  1318  	}
  1319  
  1320  	for name, conns := range cases {
  1321  		t.Run(name, func(t *testing.T) {
  1322  			sort.Sort(byIdle{conns, now})
  1323  
  1324  			idleDurations := getIdleDurations(conns, now)
  1325  
  1326  			if !sortedDurationsAsc(idleDurations) {
  1327  				t.Errorf("want durations sorted in ascending order, got %v", idleDurations)
  1328  			}
  1329  		})
  1330  	}
  1331  }
  1332  
  1333  // getIdleDurations returns a slice of idle durations from a connection info list up until now time.
  1334  func getIdleDurations(conns ConnInfos, now time.Time) []time.Duration {
  1335  	durations := make([]time.Duration, 0, len(conns))
  1336  
  1337  	for _, conn := range conns {
  1338  		durations = append(durations, now.Sub(conn.LastActivity))
  1339  	}
  1340  
  1341  	return durations
  1342  }
  1343  
  1344  // sortedDurationsAsc checks if a time.Duration slice is sorted in ascending order.
  1345  func sortedDurationsAsc(durations []time.Duration) bool {
  1346  	return sort.SliceIsSorted(durations, func(i, j int) bool {
  1347  		return durations[i] < durations[j]
  1348  	})
  1349  }
  1350  
  1351  func TestConnzSortBadRequest(t *testing.T) {
  1352  	s := runMonitorServer()
  1353  	defer s.Shutdown()
  1354  
  1355  	firstClient := createClientConnSubscribeAndPublish(t, s)
  1356  	firstClient.Subscribe("hello.world", func(m *nats.Msg) {})
  1357  	clients := make([]*nats.Conn, 3)
  1358  	for i := range clients {
  1359  		clients[i] = createClientConnSubscribeAndPublish(t, s)
  1360  		defer clients[i].Close()
  1361  	}
  1362  	defer firstClient.Close()
  1363  
  1364  	url := fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
  1365  	readBodyEx(t, url+"connz?sort=foo", http.StatusBadRequest, textPlain)
  1366  
  1367  	if _, err := s.Connz(&ConnzOptions{Sort: "foo"}); err == nil {
  1368  		t.Fatal("Expected error, got none")
  1369  	}
  1370  }
  1371  
  1372  func pollRoutez(t *testing.T, s *Server, mode int, url string, opts *RoutezOptions) *Routez {
  1373  	t.Helper()
  1374  	if mode == 0 {
  1375  		rz := &Routez{}
  1376  		body := readBody(t, url)
  1377  		if err := json.Unmarshal(body, rz); err != nil {
  1378  			t.Fatalf("Got an error unmarshalling the body: %v\n", err)
  1379  		}
  1380  		return rz
  1381  	}
  1382  	rz, err := s.Routez(opts)
  1383  	if err != nil {
  1384  		t.Fatalf("Error on Routez: %v", err)
  1385  	}
  1386  	return rz
  1387  }
  1388  
  1389  func TestConnzWithRoutes(t *testing.T) {
  1390  	resetPreviousHTTPConnections()
  1391  	opts := DefaultMonitorOptions()
  1392  	opts.NoSystemAccount = true
  1393  	opts.Cluster.Name = "A"
  1394  	opts.Cluster.Host = "127.0.0.1"
  1395  	opts.Cluster.Port = CLUSTER_PORT
  1396  
  1397  	s := RunServer(opts)
  1398  	defer s.Shutdown()
  1399  
  1400  	opts = &Options{
  1401  		Host: "127.0.0.1",
  1402  		Port: -1,
  1403  		Cluster: ClusterOpts{
  1404  			Name: "A",
  1405  			Host: "127.0.0.1",
  1406  			Port: -1,
  1407  		},
  1408  		NoLog:           true,
  1409  		NoSigs:          true,
  1410  		NoSystemAccount: true,
  1411  	}
  1412  	routeURL, _ := url.Parse(fmt.Sprintf("nats-route://127.0.0.1:%d", s.ClusterAddr().Port))
  1413  	opts.Routes = []*url.URL{routeURL}
  1414  
  1415  	start := time.Now()
  1416  	sc := RunServer(opts)
  1417  	defer sc.Shutdown()
  1418  
  1419  	checkClusterFormed(t, s, sc)
  1420  
  1421  	url := fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
  1422  	for mode := 0; mode < 2; mode++ {
  1423  		c := pollConz(t, s, mode, url+"connz", nil)
  1424  		// Test contents..
  1425  		// Make sure routes don't show up under connz, but do under routez
  1426  		if c.NumConns != 0 {
  1427  			t.Fatalf("Expected 0 connections, got %d", c.NumConns)
  1428  		}
  1429  		if c.Conns == nil || len(c.Conns) != 0 {
  1430  			t.Fatalf("Expected 0 connections in array, got %p", c.Conns)
  1431  		}
  1432  	}
  1433  
  1434  	nc := createClientConnSubscribeAndPublish(t, sc)
  1435  	defer nc.Close()
  1436  
  1437  	nc.Subscribe("hello.bar", func(m *nats.Msg) {})
  1438  	nc.Flush()
  1439  	checkExpectedSubs(t, 1, s, sc)
  1440  
  1441  	// Now check routez
  1442  	urls := []string{"routez", "routez?subs=1", "routez?subs=detail"}
  1443  	for subs, urlSuffix := range urls {
  1444  		for mode := 0; mode < 2; mode++ {
  1445  			rz := pollRoutez(t, s, mode, url+urlSuffix, &RoutezOptions{Subscriptions: subs == 1, SubscriptionsDetail: subs == 2})
  1446  
  1447  			if rz.NumRoutes != DEFAULT_ROUTE_POOL_SIZE {
  1448  				t.Fatalf("Expected %d route, got %d", DEFAULT_ROUTE_POOL_SIZE, rz.NumRoutes)
  1449  			}
  1450  
  1451  			if len(rz.Routes) != DEFAULT_ROUTE_POOL_SIZE {
  1452  				t.Fatalf("Expected route array of %d, got %v", DEFAULT_ROUTE_POOL_SIZE, len(rz.Routes))
  1453  			}
  1454  
  1455  			route := rz.Routes[0]
  1456  
  1457  			if route.DidSolicit {
  1458  				t.Fatalf("Expected unsolicited route, got %v", route.DidSolicit)
  1459  			}
  1460  
  1461  			if route.Start.IsZero() {
  1462  				t.Fatalf("Expected Start to be set, got %+v", route)
  1463  			} else if route.Start.Before(start) {
  1464  				t.Fatalf("Unexpected start time: route was started around %v, got %v", start, route.Start)
  1465  			}
  1466  			if route.LastActivity.IsZero() {
  1467  				t.Fatalf("Expected LastActivity to be set, got %+v", route)
  1468  			}
  1469  			if route.Uptime == _EMPTY_ {
  1470  				t.Fatalf("Expected Uptime to be set, it was not")
  1471  			}
  1472  			if route.Idle == _EMPTY_ {
  1473  				t.Fatalf("Expected Idle to be set, it was not")
  1474  			}
  1475  
  1476  			// Don't ask for subs, so there should not be any
  1477  			if subs == 0 {
  1478  				if len(route.Subs) != 0 {
  1479  					t.Fatalf("There should not be subs, got %v", len(route.Subs))
  1480  				}
  1481  			} else if subs == 1 {
  1482  				if len(route.Subs) != 1 && len(route.SubsDetail) != 0 {
  1483  					t.Fatalf("There should be 1 sub, got %v", len(route.Subs))
  1484  				}
  1485  			} else if subs == 2 {
  1486  				if len(route.SubsDetail) != 1 && len(route.Subs) != 0 {
  1487  					t.Fatalf("There should be 1 sub, got %v", len(route.SubsDetail))
  1488  				}
  1489  			}
  1490  		}
  1491  	}
  1492  
  1493  	// Test JSONP
  1494  	readBodyEx(t, url+"routez?callback=callback", http.StatusOK, appJSContent)
  1495  }
  1496  
  1497  func TestRoutezWithBadParams(t *testing.T) {
  1498  	s := runMonitorServer()
  1499  	defer s.Shutdown()
  1500  
  1501  	url := fmt.Sprintf("http://127.0.0.1:%d/routez?", s.MonitorAddr().Port)
  1502  	readBodyEx(t, url+"subs=xxx", http.StatusBadRequest, textPlain)
  1503  }
  1504  
  1505  func pollSubsz(t *testing.T, s *Server, mode int, url string, opts *SubszOptions) *Subsz {
  1506  	t.Helper()
  1507  	if mode == 0 {
  1508  		body := readBody(t, url)
  1509  		sz := &Subsz{}
  1510  		if err := json.Unmarshal(body, sz); err != nil {
  1511  			t.Fatalf("Got an error unmarshalling the body: %v\n", err)
  1512  		}
  1513  		return sz
  1514  	}
  1515  	sz, err := s.Subsz(opts)
  1516  	if err != nil {
  1517  		t.Fatalf("Error on Subsz: %v", err)
  1518  	}
  1519  	return sz
  1520  }
  1521  
  1522  func TestSubsz(t *testing.T) {
  1523  	s := runMonitorServer()
  1524  	defer s.Shutdown()
  1525  
  1526  	nc := createClientConnSubscribeAndPublish(t, s)
  1527  	defer nc.Close()
  1528  
  1529  	url := fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
  1530  
  1531  	for mode := 0; mode < 2; mode++ {
  1532  		sl := pollSubsz(t, s, mode, url+"subsz", nil)
  1533  		if sl.NumSubs != 0 {
  1534  			t.Fatalf("Expected NumSubs of 0, got %d\n", sl.NumSubs)
  1535  		}
  1536  		if sl.NumInserts != 1 {
  1537  			t.Fatalf("Expected NumInserts of 1, got %d\n", sl.NumInserts)
  1538  		}
  1539  		if sl.NumMatches != 1 {
  1540  			t.Fatalf("Expected NumMatches of 1, got %d\n", sl.NumMatches)
  1541  		}
  1542  	}
  1543  
  1544  	// Test JSONP
  1545  	readBodyEx(t, url+"subsz?callback=callback", http.StatusOK, appJSContent)
  1546  }
  1547  
  1548  func TestSubszDetails(t *testing.T) {
  1549  	s := runMonitorServer()
  1550  	defer s.Shutdown()
  1551  
  1552  	nc := createClientConnSubscribeAndPublish(t, s)
  1553  	defer nc.Close()
  1554  
  1555  	nc.Subscribe("foo.*", func(m *nats.Msg) {})
  1556  	nc.Subscribe("foo.bar", func(m *nats.Msg) {})
  1557  	nc.Subscribe("foo.foo", func(m *nats.Msg) {})
  1558  
  1559  	nc.Publish("foo.bar", []byte("Hello"))
  1560  	nc.Publish("foo.baz", []byte("Hello"))
  1561  	nc.Publish("foo.foo", []byte("Hello"))
  1562  
  1563  	nc.Flush()
  1564  
  1565  	url := fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
  1566  
  1567  	for mode := 0; mode < 2; mode++ {
  1568  		sl := pollSubsz(t, s, mode, url+"subsz?subs=1", &SubszOptions{Subscriptions: true})
  1569  		if sl.NumSubs != 3 {
  1570  			t.Fatalf("Expected NumSubs of 3, got %d\n", sl.NumSubs)
  1571  		}
  1572  		if sl.Total != 3 {
  1573  			t.Fatalf("Expected Total of 3, got %d\n", sl.Total)
  1574  		}
  1575  		if len(sl.Subs) != 3 {
  1576  			t.Fatalf("Expected subscription details for 3 subs, got %d\n", len(sl.Subs))
  1577  		}
  1578  	}
  1579  }
  1580  
  1581  func TestSubszWithOffsetAndLimit(t *testing.T) {
  1582  	s := runMonitorServer()
  1583  	defer s.Shutdown()
  1584  
  1585  	nc := createClientConnSubscribeAndPublish(t, s)
  1586  	defer nc.Close()
  1587  
  1588  	for i := 0; i < 200; i++ {
  1589  		nc.Subscribe(fmt.Sprintf("foo.%d", i), func(m *nats.Msg) {})
  1590  	}
  1591  	nc.Flush()
  1592  
  1593  	url := fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
  1594  	for mode := 0; mode < 2; mode++ {
  1595  		sl := pollSubsz(t, s, mode, url+"subsz?subs=1&offset=10&limit=100", &SubszOptions{Subscriptions: true, Offset: 10, Limit: 100})
  1596  		if sl.NumSubs != 200 {
  1597  			t.Fatalf("Expected NumSubs of 200, got %d\n", sl.NumSubs)
  1598  		}
  1599  		if sl.Total != 100 {
  1600  			t.Fatalf("Expected Total of 100, got %d\n", sl.Total)
  1601  		}
  1602  		if sl.Offset != 10 {
  1603  			t.Fatalf("Expected Offset of 10, got %d\n", sl.Offset)
  1604  		}
  1605  		if sl.Limit != 100 {
  1606  			t.Fatalf("Expected Total of 100, got %d\n", sl.Limit)
  1607  		}
  1608  		if len(sl.Subs) != 100 {
  1609  			t.Fatalf("Expected subscription details for 100 subs, got %d\n", len(sl.Subs))
  1610  		}
  1611  	}
  1612  }
  1613  
  1614  func TestSubszTestPubSubject(t *testing.T) {
  1615  	s := runMonitorServer()
  1616  	defer s.Shutdown()
  1617  
  1618  	nc := createClientConnSubscribeAndPublish(t, s)
  1619  	defer nc.Close()
  1620  
  1621  	nc.Subscribe("foo.*", func(m *nats.Msg) {})
  1622  	nc.Subscribe("foo.bar", func(m *nats.Msg) {})
  1623  	nc.Subscribe("foo.foo", func(m *nats.Msg) {})
  1624  	nc.Flush()
  1625  
  1626  	url := fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
  1627  	for mode := 0; mode < 2; mode++ {
  1628  		sl := pollSubsz(t, s, mode, url+"subsz?subs=1&test=foo.foo", &SubszOptions{Subscriptions: true, Test: "foo.foo"})
  1629  		if sl.Total != 2 {
  1630  			t.Fatalf("Expected Total of 2 match, got %d\n", sl.Total)
  1631  		}
  1632  		if len(sl.Subs) != 2 {
  1633  			t.Fatalf("Expected subscription details for 2 matching subs, got %d\n", len(sl.Subs))
  1634  		}
  1635  		sl = pollSubsz(t, s, mode, url+"subsz?subs=1&test=foo", &SubszOptions{Subscriptions: true, Test: "foo"})
  1636  		if len(sl.Subs) != 0 {
  1637  			t.Fatalf("Expected no matching subs, got %d\n", len(sl.Subs))
  1638  		}
  1639  	}
  1640  	// Make sure we get an error with invalid test subject.
  1641  	testUrl := url + "subsz?subs=1&"
  1642  	readBodyEx(t, testUrl+"test=*", http.StatusBadRequest, textPlain)
  1643  	readBodyEx(t, testUrl+"test=foo.*", http.StatusBadRequest, textPlain)
  1644  	readBodyEx(t, testUrl+"test=foo.>", http.StatusBadRequest, textPlain)
  1645  	readBodyEx(t, testUrl+"test=foo..bar", http.StatusBadRequest, textPlain)
  1646  }
  1647  
  1648  func TestSubszMultiAccount(t *testing.T) {
  1649  	s := runMonitorServerWithAccounts()
  1650  	defer s.Shutdown()
  1651  
  1652  	ncA := createClientConnWithUserSubscribeAndPublish(t, s, "a", "a")
  1653  	defer ncA.Close()
  1654  
  1655  	ncA.Subscribe("foo.*", func(m *nats.Msg) {})
  1656  	ncA.Subscribe("foo.bar", func(m *nats.Msg) {})
  1657  	ncA.Subscribe("foo.foo", func(m *nats.Msg) {})
  1658  
  1659  	ncA.Publish("foo.bar", []byte("Hello"))
  1660  	ncA.Publish("foo.baz", []byte("Hello"))
  1661  	ncA.Publish("foo.foo", []byte("Hello"))
  1662  
  1663  	ncA.Flush()
  1664  
  1665  	ncB := createClientConnWithUserSubscribeAndPublish(t, s, "b", "b")
  1666  	defer ncB.Close()
  1667  
  1668  	ncB.Subscribe("foo.*", func(m *nats.Msg) {})
  1669  	ncB.Subscribe("foo.bar", func(m *nats.Msg) {})
  1670  	ncB.Subscribe("foo.foo", func(m *nats.Msg) {})
  1671  
  1672  	ncB.Publish("foo.bar", []byte("Hello"))
  1673  	ncB.Publish("foo.baz", []byte("Hello"))
  1674  	ncB.Publish("foo.foo", []byte("Hello"))
  1675  
  1676  	ncB.Flush()
  1677  
  1678  	url := fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
  1679  
  1680  	for mode := 0; mode < 2; mode++ {
  1681  		sl := pollSubsz(t, s, mode, url+"subsz?subs=1", &SubszOptions{Subscriptions: true})
  1682  		if sl.NumSubs != 6 {
  1683  			t.Fatalf("Expected NumSubs of 6, got %d\n", sl.NumSubs)
  1684  		}
  1685  		if sl.Total != 6 {
  1686  			t.Fatalf("Expected Total of 6, got %d\n", sl.Total)
  1687  		}
  1688  		if len(sl.Subs) != 6 {
  1689  			t.Fatalf("Expected subscription details for 6 subs, got %d\n", len(sl.Subs))
  1690  		}
  1691  		for _, sd := range sl.Subs {
  1692  			if sd.Account != "A" && sd.Account != "B" {
  1693  				t.Fatalf("Expected account information to be present and be 'A' or 'B', got %q", sd.Account)
  1694  			}
  1695  		}
  1696  
  1697  		// Now make sure we can filter on account.
  1698  		sl = pollSubsz(t, s, mode, url+"subsz?subs=1&acc=A", &SubszOptions{Account: "A", Subscriptions: true})
  1699  		if sl.NumSubs != 3 {
  1700  			t.Fatalf("Expected NumSubs of 3, got %d\n", sl.NumSubs)
  1701  		}
  1702  		if sl.Total != 3 {
  1703  			t.Fatalf("Expected Total of 6, got %d\n", sl.Total)
  1704  		}
  1705  		if len(sl.Subs) != 3 {
  1706  			t.Fatalf("Expected subscription details for 6 subs, got %d\n", len(sl.Subs))
  1707  		}
  1708  		for _, sd := range sl.Subs {
  1709  			if sd.Account != "A" {
  1710  				t.Fatalf("Expected account information to be present and be 'A', got %q", sd.Account)
  1711  			}
  1712  		}
  1713  	}
  1714  }
  1715  
  1716  func TestSubszMultiAccountWithOffsetAndLimit(t *testing.T) {
  1717  	s := runMonitorServer()
  1718  	defer s.Shutdown()
  1719  
  1720  	ncA := createClientConnWithUserSubscribeAndPublish(t, s, "a", "a")
  1721  	defer ncA.Close()
  1722  
  1723  	for i := 0; i < 200; i++ {
  1724  		ncA.Subscribe(fmt.Sprintf("foo.%d", i), func(m *nats.Msg) {})
  1725  	}
  1726  	ncA.Flush()
  1727  
  1728  	ncB := createClientConnWithUserSubscribeAndPublish(t, s, "b", "b")
  1729  	defer ncB.Close()
  1730  
  1731  	for i := 0; i < 200; i++ {
  1732  		ncB.Subscribe(fmt.Sprintf("foo.%d", i), func(m *nats.Msg) {})
  1733  	}
  1734  	ncB.Flush()
  1735  
  1736  	url := fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
  1737  	for mode := 0; mode < 2; mode++ {
  1738  		sl := pollSubsz(t, s, mode, url+"subsz?subs=1&offset=10&limit=100", &SubszOptions{Subscriptions: true, Offset: 10, Limit: 100})
  1739  		if sl.NumSubs != 400 {
  1740  			t.Fatalf("Expected NumSubs of 200, got %d\n", sl.NumSubs)
  1741  		}
  1742  		if sl.Total != 100 {
  1743  			t.Fatalf("Expected Total of 100, got %d\n", sl.Total)
  1744  		}
  1745  		if sl.Offset != 10 {
  1746  			t.Fatalf("Expected Offset of 10, got %d\n", sl.Offset)
  1747  		}
  1748  		if sl.Limit != 100 {
  1749  			t.Fatalf("Expected Total of 100, got %d\n", sl.Limit)
  1750  		}
  1751  		if len(sl.Subs) != 100 {
  1752  			t.Fatalf("Expected subscription details for 100 subs, got %d\n", len(sl.Subs))
  1753  		}
  1754  	}
  1755  }
  1756  
  1757  // Tests handle root
  1758  func TestHandleRoot(t *testing.T) {
  1759  	s := runMonitorServer()
  1760  	defer s.Shutdown()
  1761  
  1762  	nc := createClientConnSubscribeAndPublish(t, s)
  1763  	defer nc.Close()
  1764  
  1765  	resp, err := http.Get(fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port))
  1766  	if err != nil {
  1767  		t.Fatalf("Expected no error: Got %v\n", err)
  1768  	}
  1769  	defer resp.Body.Close()
  1770  	if resp.StatusCode != http.StatusOK {
  1771  		t.Fatalf("Expected a %d response, got %d\n", http.StatusOK, resp.StatusCode)
  1772  	}
  1773  
  1774  	body, err := io.ReadAll(resp.Body)
  1775  	if err != nil {
  1776  		t.Fatalf("Expected no error reading body: Got %v\n", err)
  1777  	}
  1778  	for _, b := range body {
  1779  		if b > unicode.MaxASCII {
  1780  			t.Fatalf("Expected body to contain only ASCII characters, but got %v\n", b)
  1781  		}
  1782  	}
  1783  
  1784  	ct := resp.Header.Get("Content-Type")
  1785  	if !strings.Contains(ct, "text/html") {
  1786  		t.Fatalf("Expected text/html response, got %s\n", ct)
  1787  	}
  1788  }
  1789  
  1790  func TestConnzWithNamedClient(t *testing.T) {
  1791  	s := runMonitorServer()
  1792  	defer s.Shutdown()
  1793  
  1794  	clientName := "test-client"
  1795  	nc := createClientConnWithName(t, clientName, s)
  1796  	defer nc.Close()
  1797  
  1798  	url := fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
  1799  	for mode := 0; mode < 2; mode++ {
  1800  		// Confirm server is exposing client name in monitoring endpoint.
  1801  		c := pollConz(t, s, mode, url+"connz", nil)
  1802  		got := len(c.Conns)
  1803  		expected := 1
  1804  		if got != expected {
  1805  			t.Fatalf("Expected %d connection in array, got %d\n", expected, got)
  1806  		}
  1807  
  1808  		conn := c.Conns[0]
  1809  		if conn.Name != clientName {
  1810  			t.Fatalf("Expected client to have name %q. got %q", clientName, conn.Name)
  1811  		}
  1812  	}
  1813  }
  1814  
  1815  func TestConnzWithStateForClosedConns(t *testing.T) {
  1816  	s := runMonitorServer()
  1817  	defer s.Shutdown()
  1818  
  1819  	numEach := 10
  1820  	// Create 10 closed, and 10 to leave open.
  1821  	for i := 0; i < numEach; i++ {
  1822  		nc := createClientConnSubscribeAndPublish(t, s)
  1823  		nc.Subscribe("hello.closed.conns", func(m *nats.Msg) {})
  1824  		nc.Close()
  1825  		nc = createClientConnSubscribeAndPublish(t, s)
  1826  		nc.Subscribe("hello.open.conns", func(m *nats.Msg) {})
  1827  		defer nc.Close()
  1828  	}
  1829  
  1830  	url := fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
  1831  
  1832  	for mode := 0; mode < 2; mode++ {
  1833  		checkFor(t, 2*time.Second, 10*time.Millisecond, func() error {
  1834  			// Look at all open
  1835  			c := pollConz(t, s, mode, url+"connz?state=open", &ConnzOptions{State: ConnOpen})
  1836  			if lc := len(c.Conns); lc != numEach {
  1837  				return fmt.Errorf("Expected %d connections in array, got %d", numEach, lc)
  1838  			}
  1839  			// Look at all closed
  1840  			c = pollConz(t, s, mode, url+"connz?state=closed", &ConnzOptions{State: ConnClosed})
  1841  			if lc := len(c.Conns); lc != numEach {
  1842  				return fmt.Errorf("Expected %d connections in array, got %d", numEach, lc)
  1843  			}
  1844  			// Look at all
  1845  			c = pollConz(t, s, mode, url+"connz?state=ALL", &ConnzOptions{State: ConnAll})
  1846  			if lc := len(c.Conns); lc != numEach*2 {
  1847  				return fmt.Errorf("Expected %d connections in array, got %d", 2*numEach, lc)
  1848  			}
  1849  			// Look at CID #1, which is in closed.
  1850  			c = pollConz(t, s, mode, url+"connz?cid=1&state=open", &ConnzOptions{CID: 1, State: ConnOpen})
  1851  			if lc := len(c.Conns); lc != 0 {
  1852  				return fmt.Errorf("Expected no connections in open array, got %d", lc)
  1853  			}
  1854  			c = pollConz(t, s, mode, url+"connz?cid=1&state=closed", &ConnzOptions{CID: 1, State: ConnClosed})
  1855  			if lc := len(c.Conns); lc != 1 {
  1856  				return fmt.Errorf("Expected a connection in closed array, got %d", lc)
  1857  			}
  1858  			c = pollConz(t, s, mode, url+"connz?cid=1&state=ALL", &ConnzOptions{CID: 1, State: ConnAll})
  1859  			if lc := len(c.Conns); lc != 1 {
  1860  				return fmt.Errorf("Expected a connection in closed array, got %d", lc)
  1861  			}
  1862  			c = pollConz(t, s, mode, url+"connz?cid=1&state=closed&subs=true",
  1863  				&ConnzOptions{CID: 1, State: ConnClosed, Subscriptions: true})
  1864  			if lc := len(c.Conns); lc != 1 {
  1865  				return fmt.Errorf("Expected a connection in closed array, got %d", lc)
  1866  			}
  1867  			ci := c.Conns[0]
  1868  			if ci.NumSubs != 1 {
  1869  				return fmt.Errorf("Expected NumSubs to be 1, got %d", ci.NumSubs)
  1870  			}
  1871  			if len(ci.Subs) != 1 {
  1872  				return fmt.Errorf("Expected len(ci.Subs) to be 1 also, got %d", len(ci.Subs))
  1873  			}
  1874  			// Now ask for same thing without subs and make sure they are not returned.
  1875  			c = pollConz(t, s, mode, url+"connz?cid=1&state=closed&subs=false",
  1876  				&ConnzOptions{CID: 1, State: ConnClosed, Subscriptions: false})
  1877  			if lc := len(c.Conns); lc != 1 {
  1878  				return fmt.Errorf("Expected a connection in closed array, got %d", lc)
  1879  			}
  1880  			ci = c.Conns[0]
  1881  			if ci.NumSubs != 1 {
  1882  				return fmt.Errorf("Expected NumSubs to be 1, got %d", ci.NumSubs)
  1883  			}
  1884  			if len(ci.Subs) != 0 {
  1885  				return fmt.Errorf("Expected len(ci.Subs) to be 0 since subs=false, got %d", len(ci.Subs))
  1886  			}
  1887  
  1888  			// CID #2 is in open
  1889  			c = pollConz(t, s, mode, url+"connz?cid=2&state=open", &ConnzOptions{CID: 2, State: ConnOpen})
  1890  			if lc := len(c.Conns); lc != 1 {
  1891  				return fmt.Errorf("Expected a connection in open array, got %d", lc)
  1892  			}
  1893  			c = pollConz(t, s, mode, url+"connz?cid=2&state=closed", &ConnzOptions{CID: 2, State: ConnClosed})
  1894  			if lc := len(c.Conns); lc != 0 {
  1895  				return fmt.Errorf("Expected no connections in closed array, got %d", lc)
  1896  			}
  1897  			return nil
  1898  		})
  1899  	}
  1900  }
  1901  
  1902  // Make sure options for ConnInfo like subs=1, authuser, etc do not cause a race.
  1903  func TestConnzClosedConnsRace(t *testing.T) {
  1904  	s := runMonitorServer()
  1905  	defer s.Shutdown()
  1906  
  1907  	// Create 100 closed connections.
  1908  	for i := 0; i < 100; i++ {
  1909  		nc := createClientConnSubscribeAndPublish(t, s)
  1910  		nc.Close()
  1911  	}
  1912  
  1913  	urlWithoutSubs := fmt.Sprintf("http://127.0.0.1:%d/connz?state=closed", s.MonitorAddr().Port)
  1914  	urlWithSubs := urlWithoutSubs + "&subs=true"
  1915  
  1916  	checkClosedConns(t, s, 100, 2*time.Second)
  1917  
  1918  	wg := &sync.WaitGroup{}
  1919  
  1920  	fn := func(url string) {
  1921  		deadline := time.Now().Add(1 * time.Second)
  1922  		for time.Now().Before(deadline) {
  1923  			c := pollConz(t, s, 0, url, nil)
  1924  			if len(c.Conns) != 100 {
  1925  				t.Errorf("Incorrect Results: %+v\n", c)
  1926  			}
  1927  		}
  1928  		wg.Done()
  1929  	}
  1930  
  1931  	wg.Add(2)
  1932  	go fn(urlWithSubs)
  1933  	go fn(urlWithoutSubs)
  1934  	wg.Wait()
  1935  }
  1936  
  1937  // Make sure a bad client that is disconnected right away has proper values.
  1938  func TestConnzClosedConnsBadClient(t *testing.T) {
  1939  	s := runMonitorServer()
  1940  	defer s.Shutdown()
  1941  
  1942  	opts := s.getOpts()
  1943  
  1944  	rc, err := net.Dial("tcp", fmt.Sprintf("%s:%d", opts.Host, opts.Port))
  1945  	if err != nil {
  1946  		t.Fatalf("Error on dial: %v", err)
  1947  	}
  1948  	rc.Close()
  1949  
  1950  	checkClosedConns(t, s, 1, 2*time.Second)
  1951  
  1952  	c := pollConz(t, s, 1, "", &ConnzOptions{State: ConnClosed})
  1953  	if len(c.Conns) != 1 {
  1954  		t.Errorf("Incorrect Results: %+v\n", c)
  1955  	}
  1956  	ci := c.Conns[0]
  1957  
  1958  	uptime := ci.Stop.Sub(ci.Start)
  1959  	idle, err := time.ParseDuration(ci.Idle)
  1960  	if err != nil {
  1961  		t.Fatalf("Could not parse Idle: %v\n", err)
  1962  	}
  1963  	if idle > uptime {
  1964  		t.Fatalf("Idle can't be larger then uptime, %v vs %v\n", idle, uptime)
  1965  	}
  1966  	if ci.LastActivity.IsZero() {
  1967  		t.Fatalf("LastActivity should not be Zero\n")
  1968  	}
  1969  }
  1970  
  1971  // Make sure a bad client that tries to connect plain to TLS has proper values.
  1972  func TestConnzClosedConnsBadTLSClient(t *testing.T) {
  1973  	resetPreviousHTTPConnections()
  1974  
  1975  	tc := &TLSConfigOpts{}
  1976  	tc.CertFile = "configs/certs/server.pem"
  1977  	tc.KeyFile = "configs/certs/key.pem"
  1978  
  1979  	var err error
  1980  	opts := DefaultMonitorOptions()
  1981  	opts.NoSystemAccount = true
  1982  	opts.TLSTimeout = 1.5 // 1.5 seconds
  1983  	opts.TLSConfig, err = GenTLSConfig(tc)
  1984  	if err != nil {
  1985  		t.Fatalf("Error creating TSL config: %v", err)
  1986  	}
  1987  
  1988  	s := RunServer(opts)
  1989  	defer s.Shutdown()
  1990  
  1991  	opts = s.getOpts()
  1992  
  1993  	rc, err := net.Dial("tcp", fmt.Sprintf("%s:%d", opts.Host, opts.Port))
  1994  	if err != nil {
  1995  		t.Fatalf("Error on dial: %v", err)
  1996  	}
  1997  	rc.Write([]byte("CONNECT {}\r\n"))
  1998  	rc.Close()
  1999  
  2000  	checkClosedConns(t, s, 1, 2*time.Second)
  2001  
  2002  	c := pollConz(t, s, 1, "", &ConnzOptions{State: ConnClosed})
  2003  	if len(c.Conns) != 1 {
  2004  		t.Errorf("Incorrect Results: %+v\n", c)
  2005  	}
  2006  	ci := c.Conns[0]
  2007  
  2008  	uptime := ci.Stop.Sub(ci.Start)
  2009  	idle, err := time.ParseDuration(ci.Idle)
  2010  	if err != nil {
  2011  		t.Fatalf("Could not parse Idle: %v\n", err)
  2012  	}
  2013  	if idle > uptime {
  2014  		t.Fatalf("Idle can't be larger then uptime, %v vs %v\n", idle, uptime)
  2015  	}
  2016  	if ci.LastActivity.IsZero() {
  2017  		t.Fatalf("LastActivity should not be Zero\n")
  2018  	}
  2019  }
  2020  
  2021  // Create a connection to test ConnInfo
  2022  func createClientConnWithUserSubscribeAndPublish(t *testing.T, s *Server, user, pwd string) *nats.Conn {
  2023  	natsURL := ""
  2024  	if user == "" {
  2025  		natsURL = fmt.Sprintf("nats://127.0.0.1:%d", s.Addr().(*net.TCPAddr).Port)
  2026  	} else {
  2027  		natsURL = fmt.Sprintf("nats://%s:%s@127.0.0.1:%d", user, pwd, s.Addr().(*net.TCPAddr).Port)
  2028  	}
  2029  	client := nats.DefaultOptions
  2030  	client.Servers = []string{natsURL}
  2031  	nc, err := client.Connect()
  2032  	if err != nil {
  2033  		t.Fatalf("Error creating client: %v to: %s\n", err, natsURL)
  2034  	}
  2035  
  2036  	ch := make(chan bool)
  2037  	inbox := nats.NewInbox()
  2038  	sub, err := nc.Subscribe(inbox, func(m *nats.Msg) { ch <- true })
  2039  	if err != nil {
  2040  		t.Fatalf("Error subscribing to `%s`: %v\n", inbox, err)
  2041  	}
  2042  	nc.Publish(inbox, []byte("Hello"))
  2043  	// Wait for message
  2044  	<-ch
  2045  	sub.Unsubscribe()
  2046  	close(ch)
  2047  	nc.Flush()
  2048  	return nc
  2049  }
  2050  
  2051  func createClientConnSubscribeAndPublish(t *testing.T, s *Server) *nats.Conn {
  2052  	return createClientConnWithUserSubscribeAndPublish(t, s, "", "")
  2053  }
  2054  
  2055  func createClientConnWithName(t *testing.T, name string, s *Server) *nats.Conn {
  2056  	natsURI := fmt.Sprintf("nats://127.0.0.1:%d", s.Addr().(*net.TCPAddr).Port)
  2057  
  2058  	client := nats.DefaultOptions
  2059  	client.Servers = []string{natsURI}
  2060  	client.Name = name
  2061  	nc, err := client.Connect()
  2062  	if err != nil {
  2063  		t.Fatalf("Error creating client: %v\n", err)
  2064  	}
  2065  	return nc
  2066  }
  2067  
  2068  func TestStacksz(t *testing.T) {
  2069  	s := runMonitorServer()
  2070  	defer s.Shutdown()
  2071  
  2072  	url := fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
  2073  	body := readBody(t, url+"stacksz")
  2074  	// Check content
  2075  	str := string(body)
  2076  	if !strings.Contains(str, "HandleStacksz") {
  2077  		t.Fatalf("Result does not seem to contain server's stacks:\n%v", str)
  2078  	}
  2079  }
  2080  
  2081  func TestConcurrentMonitoring(t *testing.T) {
  2082  	s := runMonitorServer()
  2083  	defer s.Shutdown()
  2084  
  2085  	url := fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
  2086  	// Get some endpoints. Make sure we have at least varz,
  2087  	// and the more the merrier.
  2088  	endpoints := []string{"varz", "varz", "varz", "connz", "connz", "subsz", "subsz", "routez", "routez"}
  2089  	wg := &sync.WaitGroup{}
  2090  	wg.Add(len(endpoints))
  2091  	ech := make(chan string, len(endpoints))
  2092  
  2093  	for _, e := range endpoints {
  2094  		go func(endpoint string) {
  2095  			defer wg.Done()
  2096  			for i := 0; i < 50; i++ {
  2097  				resp, err := http.Get(url + endpoint)
  2098  				if err != nil {
  2099  					ech <- fmt.Sprintf("Expected no error: Got %v\n", err)
  2100  					return
  2101  				}
  2102  				defer resp.Body.Close()
  2103  				if resp.StatusCode != http.StatusOK {
  2104  					ech <- fmt.Sprintf("Expected a %v response, got %d\n", http.StatusOK, resp.StatusCode)
  2105  					return
  2106  				}
  2107  				ct := resp.Header.Get("Content-Type")
  2108  				if ct != "application/json" {
  2109  					ech <- fmt.Sprintf("Expected application/json content-type, got %s\n", ct)
  2110  					return
  2111  				}
  2112  				if _, err := io.ReadAll(resp.Body); err != nil {
  2113  					ech <- fmt.Sprintf("Got an error reading the body: %v\n", err)
  2114  					return
  2115  				}
  2116  				resp.Body.Close()
  2117  			}
  2118  		}(e)
  2119  	}
  2120  	wg.Wait()
  2121  	// Check for any errors
  2122  	select {
  2123  	case err := <-ech:
  2124  		t.Fatal(err)
  2125  	default:
  2126  	}
  2127  }
  2128  
  2129  func TestMonitorHandler(t *testing.T) {
  2130  	s := runMonitorServer()
  2131  	defer s.Shutdown()
  2132  	handler := s.HTTPHandler()
  2133  	if handler == nil {
  2134  		t.Fatal("HTTP Handler should be set")
  2135  	}
  2136  	s.Shutdown()
  2137  	handler = s.HTTPHandler()
  2138  	if handler != nil {
  2139  		t.Fatal("HTTP Handler should be nil")
  2140  	}
  2141  }
  2142  
  2143  func TestMonitorRoutezRace(t *testing.T) {
  2144  	resetPreviousHTTPConnections()
  2145  	srvAOpts := DefaultMonitorOptions()
  2146  	srvAOpts.NoSystemAccount = true
  2147  	srvAOpts.Cluster.Name = "B"
  2148  	srvAOpts.Cluster.Port = -1
  2149  	srvA := RunServer(srvAOpts)
  2150  	defer srvA.Shutdown()
  2151  
  2152  	srvBOpts := nextServerOpts(srvAOpts)
  2153  	srvBOpts.Routes = RoutesFromStr(fmt.Sprintf("nats://127.0.0.1:%d", srvA.ClusterAddr().Port))
  2154  
  2155  	doneCh := make(chan struct{})
  2156  	go func() {
  2157  		defer func() {
  2158  			doneCh <- struct{}{}
  2159  		}()
  2160  		for i := 0; i < 10; i++ {
  2161  			time.Sleep(10 * time.Millisecond)
  2162  			// Reset ports
  2163  			srvBOpts.Port = -1
  2164  			srvBOpts.Cluster.Port = -1
  2165  			srvB := RunServer(srvBOpts)
  2166  			time.Sleep(20 * time.Millisecond)
  2167  			srvB.Shutdown()
  2168  		}
  2169  	}()
  2170  	done := false
  2171  	for !done {
  2172  		if _, err := srvA.Routez(nil); err != nil {
  2173  			time.Sleep(10 * time.Millisecond)
  2174  		}
  2175  		select {
  2176  		case <-doneCh:
  2177  			done = true
  2178  		default:
  2179  		}
  2180  	}
  2181  }
  2182  
  2183  func TestConnzTLSInHandshake(t *testing.T) {
  2184  	resetPreviousHTTPConnections()
  2185  
  2186  	tc := &TLSConfigOpts{}
  2187  	tc.CertFile = "configs/certs/server.pem"
  2188  	tc.KeyFile = "configs/certs/key.pem"
  2189  
  2190  	var err error
  2191  	opts := DefaultMonitorOptions()
  2192  	opts.NoSystemAccount = true
  2193  	opts.TLSTimeout = 1.5 // 1.5 seconds
  2194  	opts.TLSConfig, err = GenTLSConfig(tc)
  2195  	if err != nil {
  2196  		t.Fatalf("Error creating TSL config: %v", err)
  2197  	}
  2198  
  2199  	s := RunServer(opts)
  2200  	defer s.Shutdown()
  2201  
  2202  	// Create bare TCP connection to delay client TLS handshake
  2203  	c, err := net.Dial("tcp", fmt.Sprintf("%s:%d", opts.Host, opts.Port))
  2204  	if err != nil {
  2205  		t.Fatalf("Error on dial: %v", err)
  2206  	}
  2207  	defer c.Close()
  2208  
  2209  	// Wait for the connection to be registered
  2210  	checkClientsCount(t, s, 1)
  2211  
  2212  	start := time.Now()
  2213  	endpoint := fmt.Sprintf("http://%s:%d/connz", opts.HTTPHost, s.MonitorAddr().Port)
  2214  	for mode := 0; mode < 2; mode++ {
  2215  		connz := pollConz(t, s, mode, endpoint, nil)
  2216  		duration := time.Since(start)
  2217  		if duration >= 1500*time.Millisecond {
  2218  			t.Fatalf("Looks like connz blocked on handshake, took %v", duration)
  2219  		}
  2220  		if len(connz.Conns) != 1 {
  2221  			t.Fatalf("Expected 1 conn, got %v", len(connz.Conns))
  2222  		}
  2223  		conn := connz.Conns[0]
  2224  		// TLS fields should be not set
  2225  		if conn.TLSVersion != "" || conn.TLSCipher != "" {
  2226  			t.Fatalf("Expected TLS fields to not be set, got version:%v cipher:%v", conn.TLSVersion, conn.TLSCipher)
  2227  		}
  2228  	}
  2229  }
  2230  
  2231  func TestConnzTLSCfg(t *testing.T) {
  2232  	resetPreviousHTTPConnections()
  2233  
  2234  	tc := &TLSConfigOpts{}
  2235  	tc.CertFile = "configs/certs/server.pem"
  2236  	tc.KeyFile = "configs/certs/key.pem"
  2237  
  2238  	var err error
  2239  	opts := DefaultMonitorOptions()
  2240  	opts.NoSystemAccount = true
  2241  	opts.TLSTimeout = 1.5 // 1.5 seconds
  2242  	opts.TLSConfig, err = GenTLSConfig(tc)
  2243  	require_NoError(t, err)
  2244  	opts.TLSConfig.ClientAuth = tls.RequireAndVerifyClientCert
  2245  	opts.Gateway.TLSConfig, err = GenTLSConfig(tc)
  2246  	require_NoError(t, err)
  2247  	opts.Gateway.TLSTimeout = 1.5
  2248  	opts.LeafNode.TLSConfig, err = GenTLSConfig(tc)
  2249  	require_NoError(t, err)
  2250  	opts.LeafNode.TLSConfig.ClientAuth = tls.RequireAndVerifyClientCert
  2251  	opts.LeafNode.TLSTimeout = 1.5
  2252  	opts.Cluster.TLSConfig, err = GenTLSConfig(tc)
  2253  	require_NoError(t, err)
  2254  	opts.Cluster.TLSTimeout = 1.5
  2255  
  2256  	s := RunServer(opts)
  2257  	defer s.Shutdown()
  2258  
  2259  	check := func(verify, required bool, timeout float64) {
  2260  		t.Helper()
  2261  		if !verify {
  2262  			t.Fatalf("Expected tls_verify to be true")
  2263  		}
  2264  		if !required {
  2265  			t.Fatalf("Expected tls_required to be true")
  2266  		}
  2267  		if timeout != 1.5 {
  2268  			t.Fatalf("Expected tls_timeout to be 1.5")
  2269  		}
  2270  	}
  2271  
  2272  	start := time.Now()
  2273  	endpoint := fmt.Sprintf("http://%s:%d/varz", opts.HTTPHost, s.MonitorAddr().Port)
  2274  	for mode := 0; mode < 2; mode++ {
  2275  		varz := pollVarz(t, s, mode, endpoint, nil)
  2276  		duration := time.Since(start)
  2277  		if duration >= 1500*time.Millisecond {
  2278  			t.Fatalf("Looks like varz blocked on handshake, took %v", duration)
  2279  		}
  2280  		check(varz.TLSVerify, varz.TLSRequired, varz.TLSTimeout)
  2281  		check(varz.Cluster.TLSVerify, varz.Cluster.TLSRequired, varz.Cluster.TLSTimeout)
  2282  		check(varz.Gateway.TLSVerify, varz.Gateway.TLSRequired, varz.Gateway.TLSTimeout)
  2283  		check(varz.LeafNode.TLSVerify, varz.LeafNode.TLSRequired, varz.LeafNode.TLSTimeout)
  2284  	}
  2285  }
  2286  
  2287  func TestConnzTLSPeerCerts(t *testing.T) {
  2288  	resetPreviousHTTPConnections()
  2289  
  2290  	tc := &TLSConfigOpts{}
  2291  	tc.CertFile = "../test/configs/certs/server-cert.pem"
  2292  	tc.KeyFile = "../test/configs/certs/server-key.pem"
  2293  	tc.CaFile = "../test/configs/certs/ca.pem"
  2294  	tc.Verify = true
  2295  	tc.Timeout = 2.0
  2296  
  2297  	var err error
  2298  	opts := DefaultMonitorOptions()
  2299  	opts.TLSConfig, err = GenTLSConfig(tc)
  2300  	require_NoError(t, err)
  2301  
  2302  	s := RunServer(opts)
  2303  	defer s.Shutdown()
  2304  
  2305  	nc := natsConnect(t, s.ClientURL(),
  2306  		nats.ClientCert("../test/configs/certs/client-cert.pem", "../test/configs/certs/client-key.pem"),
  2307  		nats.RootCAs("../test/configs/certs/ca.pem"))
  2308  	defer nc.Close()
  2309  
  2310  	endpoint := fmt.Sprintf("http://%s:%d/connz", opts.HTTPHost, s.MonitorAddr().Port)
  2311  	for mode := 0; mode < 2; mode++ {
  2312  		// Without "auth" option, we should not get the details
  2313  		connz := pollConz(t, s, mode, endpoint, nil)
  2314  		require_True(t, len(connz.Conns) == 1)
  2315  		c := connz.Conns[0]
  2316  		if c.TLSPeerCerts != nil {
  2317  			t.Fatalf("Did not expect TLSPeerCerts when auth is not specified: %+v", c.TLSPeerCerts)
  2318  		}
  2319  		// Now specify "auth" option
  2320  		connz = pollConz(t, s, mode, endpoint+"?auth=1", &ConnzOptions{Username: true})
  2321  		require_True(t, len(connz.Conns) == 1)
  2322  		c = connz.Conns[0]
  2323  		if c.TLSPeerCerts == nil {
  2324  			t.Fatal("Expected TLSPeerCerts to be set, was not")
  2325  		} else if len(c.TLSPeerCerts) != 1 {
  2326  			t.Fatalf("Unexpected peer certificates: %+v", c.TLSPeerCerts)
  2327  		} else {
  2328  			for _, d := range c.TLSPeerCerts {
  2329  				if d.Subject != "CN=localhost,OU=nats.io,O=Synadia,ST=California,C=US" {
  2330  					t.Fatalf("Unexpected subject: %s", d.Subject)
  2331  				}
  2332  				if len(d.SubjectPKISha256) != 64 {
  2333  					t.Fatalf("Unexpected spki_sha256: %s", d.SubjectPKISha256)
  2334  				}
  2335  				if len(d.CertSha256) != 64 {
  2336  					t.Fatalf("Unexpected cert_sha256: %s", d.CertSha256)
  2337  				}
  2338  			}
  2339  		}
  2340  	}
  2341  }
  2342  
  2343  func TestServerIDs(t *testing.T) {
  2344  	s := runMonitorServer()
  2345  	defer s.Shutdown()
  2346  
  2347  	murl := fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
  2348  
  2349  	for mode := 0; mode < 2; mode++ {
  2350  		v := pollVarz(t, s, mode, murl+"varz", nil)
  2351  		if v.ID == _EMPTY_ {
  2352  			t.Fatal("Varz ID is empty")
  2353  		}
  2354  		c := pollConz(t, s, mode, murl+"connz", nil)
  2355  		if c.ID == _EMPTY_ {
  2356  			t.Fatal("Connz ID is empty")
  2357  		}
  2358  		r := pollRoutez(t, s, mode, murl+"routez", nil)
  2359  		if r.ID == _EMPTY_ {
  2360  			t.Fatal("Routez ID is empty")
  2361  		}
  2362  		if v.ID != c.ID || v.ID != r.ID {
  2363  			t.Fatalf("Varz ID [%s] is not equal to Connz ID [%s] or Routez ID [%s]", v.ID, c.ID, r.ID)
  2364  		}
  2365  	}
  2366  }
  2367  
  2368  func TestHttpStatsNoUpdatedWhenUsingServerFuncs(t *testing.T) {
  2369  	s := runMonitorServer()
  2370  	defer s.Shutdown()
  2371  
  2372  	for i := 0; i < 10; i++ {
  2373  		s.Varz(nil)
  2374  		s.Connz(nil)
  2375  		s.Routez(nil)
  2376  		s.Subsz(nil)
  2377  	}
  2378  
  2379  	v, _ := s.Varz(nil)
  2380  	endpoints := []string{VarzPath, ConnzPath, RoutezPath, SubszPath}
  2381  	for _, e := range endpoints {
  2382  		stats := v.HTTPReqStats[e]
  2383  		if stats != 0 {
  2384  			t.Fatalf("Expected HTTPReqStats for %q to be 0, got %v", e, stats)
  2385  		}
  2386  	}
  2387  }
  2388  
  2389  func TestClusterEmptyWhenNotDefined(t *testing.T) {
  2390  	s := runMonitorServer()
  2391  	defer s.Shutdown()
  2392  
  2393  	body := readBody(t, fmt.Sprintf("http://127.0.0.1:%d/varz", s.MonitorAddr().Port))
  2394  	var v map[string]any
  2395  	if err := json.Unmarshal(body, &v); err != nil {
  2396  		t.Fatalf("Got an error unmarshalling the body: %v\n", err)
  2397  	}
  2398  	// Cluster can empty, or be defined but that needs to be empty.
  2399  	c, ok := v["cluster"]
  2400  	if !ok {
  2401  		return
  2402  	}
  2403  	if len(c.(map[string]any)) != 0 {
  2404  		t.Fatalf("Expected an empty cluster definition, instead got %+v\n", c)
  2405  	}
  2406  }
  2407  
  2408  func TestRoutezPermissions(t *testing.T) {
  2409  	resetPreviousHTTPConnections()
  2410  	opts := DefaultMonitorOptions()
  2411  	opts.NoSystemAccount = true
  2412  	opts.Cluster.Name = "A"
  2413  	opts.Cluster.Host = "127.0.0.1"
  2414  	opts.Cluster.Port = -1
  2415  	opts.Cluster.Permissions = &RoutePermissions{
  2416  		Import: &SubjectPermission{
  2417  			Allow: []string{"foo"},
  2418  		},
  2419  		Export: &SubjectPermission{
  2420  			Allow: []string{"*"},
  2421  			Deny:  []string{"foo", "nats"},
  2422  		},
  2423  	}
  2424  
  2425  	s1 := RunServer(opts)
  2426  	defer s1.Shutdown()
  2427  
  2428  	opts = DefaultMonitorOptions()
  2429  	opts.NoSystemAccount = true
  2430  	opts.ServerName = "monitor_server_2"
  2431  	opts.Cluster.Host = "127.0.0.1"
  2432  	opts.Cluster.Name = "A"
  2433  	opts.Cluster.Port = -1
  2434  	routeURL, _ := url.Parse(fmt.Sprintf("nats-route://127.0.0.1:%d", s1.ClusterAddr().Port))
  2435  	opts.Routes = []*url.URL{routeURL}
  2436  	opts.HTTPPort = -1
  2437  
  2438  	s2 := RunServer(opts)
  2439  	defer s2.Shutdown()
  2440  
  2441  	checkClusterFormed(t, s1, s2)
  2442  
  2443  	urls := []string{
  2444  		fmt.Sprintf("http://127.0.0.1:%d/routez", s1.MonitorAddr().Port),
  2445  		fmt.Sprintf("http://127.0.0.1:%d/routez", s2.MonitorAddr().Port),
  2446  	}
  2447  	servers := []*Server{s1, s2}
  2448  
  2449  	for i, url := range urls {
  2450  		for mode := 0; mode < 2; mode++ {
  2451  			rz := pollRoutez(t, servers[i], mode, url, nil)
  2452  			// For server 1, we expect to see imports and exports
  2453  			if i == 0 {
  2454  				if rz.Import == nil || rz.Import.Allow == nil ||
  2455  					len(rz.Import.Allow) != 1 || rz.Import.Allow[0] != "foo" ||
  2456  					rz.Import.Deny != nil {
  2457  					t.Fatalf("Unexpected Import %v", rz.Import)
  2458  				}
  2459  				if rz.Export == nil || rz.Export.Allow == nil || rz.Export.Deny == nil ||
  2460  					len(rz.Export.Allow) != 1 || rz.Export.Allow[0] != "*" ||
  2461  					len(rz.Export.Deny) != 2 || rz.Export.Deny[0] != "foo" || rz.Export.Deny[1] != "nats" {
  2462  					t.Fatalf("Unexpected Export %v", rz.Export)
  2463  				}
  2464  			} else {
  2465  				// We expect to see NO imports and exports for server B by default.
  2466  				if rz.Import != nil {
  2467  					t.Fatal("Routez body should NOT contain \"import\" information.")
  2468  				}
  2469  				if rz.Export != nil {
  2470  					t.Fatal("Routez body should NOT contain \"export\" information.")
  2471  				}
  2472  				// We do expect to see them show up for the information we have on Server A though.
  2473  				if len(rz.Routes) != DEFAULT_ROUTE_POOL_SIZE {
  2474  					t.Fatalf("Expected route array of %d, got %v\n", DEFAULT_ROUTE_POOL_SIZE, len(rz.Routes))
  2475  				}
  2476  				route := rz.Routes[0]
  2477  				if route.Import == nil || route.Import.Allow == nil ||
  2478  					len(route.Import.Allow) != 1 || route.Import.Allow[0] != "foo" ||
  2479  					route.Import.Deny != nil {
  2480  					t.Fatalf("Unexpected Import %v", route.Import)
  2481  				}
  2482  				if route.Export == nil || route.Export.Allow == nil || route.Export.Deny == nil ||
  2483  					len(route.Export.Allow) != 1 || route.Export.Allow[0] != "*" ||
  2484  					len(route.Export.Deny) != 2 || route.Export.Deny[0] != "foo" || route.Export.Deny[1] != "nats" {
  2485  					t.Fatalf("Unexpected Export %v", route.Export)
  2486  				}
  2487  			}
  2488  		}
  2489  	}
  2490  }
  2491  
  2492  // Benchmark our Connz generation. Don't use HTTP here, just measure server endpoint.
  2493  func Benchmark_Connz(b *testing.B) {
  2494  	runtime.MemProfileRate = 0
  2495  
  2496  	s := runMonitorServerNoHTTPPort()
  2497  	defer s.Shutdown()
  2498  
  2499  	opts := s.getOpts()
  2500  	url := fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port)
  2501  
  2502  	// Create 250 connections with 100 subs each.
  2503  	for i := 0; i < 250; i++ {
  2504  		nc, err := nats.Connect(url)
  2505  		if err != nil {
  2506  			b.Fatalf("Error on connection[%d] to %s: %v", i, url, err)
  2507  		}
  2508  		for x := 0; x < 100; x++ {
  2509  			subj := fmt.Sprintf("foo.%d", x)
  2510  			nc.Subscribe(subj, func(m *nats.Msg) {})
  2511  		}
  2512  		nc.Flush()
  2513  		defer nc.Close()
  2514  	}
  2515  
  2516  	b.ResetTimer()
  2517  	runtime.MemProfileRate = 1
  2518  
  2519  	copts := &ConnzOptions{Subscriptions: false}
  2520  	for i := 0; i < b.N; i++ {
  2521  		_, err := s.Connz(copts)
  2522  		if err != nil {
  2523  			b.Fatalf("Error on Connz(): %v", err)
  2524  		}
  2525  	}
  2526  }
  2527  
  2528  func Benchmark_Varz(b *testing.B) {
  2529  	runtime.MemProfileRate = 0
  2530  
  2531  	s := runMonitorServerNoHTTPPort()
  2532  	defer s.Shutdown()
  2533  
  2534  	b.ResetTimer()
  2535  	runtime.MemProfileRate = 1
  2536  
  2537  	for i := 0; i < b.N; i++ {
  2538  		_, err := s.Varz(nil)
  2539  		if err != nil {
  2540  			b.Fatalf("Error on Connz(): %v", err)
  2541  		}
  2542  	}
  2543  }
  2544  
  2545  func Benchmark_VarzHttp(b *testing.B) {
  2546  	runtime.MemProfileRate = 0
  2547  
  2548  	s := runMonitorServer()
  2549  	defer s.Shutdown()
  2550  
  2551  	murl := fmt.Sprintf("http://127.0.0.1:%d/varz", s.MonitorAddr().Port)
  2552  
  2553  	b.ResetTimer()
  2554  	runtime.MemProfileRate = 1
  2555  
  2556  	for i := 0; i < b.N; i++ {
  2557  		v := &Varz{}
  2558  		resp, err := http.Get(murl)
  2559  		if err != nil {
  2560  			b.Fatalf("Expected no error: Got %v\n", err)
  2561  		}
  2562  		defer resp.Body.Close()
  2563  		body, err := io.ReadAll(resp.Body)
  2564  		if err != nil {
  2565  			b.Fatalf("Got an error reading the body: %v\n", err)
  2566  		}
  2567  		if err := json.Unmarshal(body, v); err != nil {
  2568  			b.Fatalf("Got an error unmarshalling the body: %v\n", err)
  2569  		}
  2570  		resp.Body.Close()
  2571  	}
  2572  }
  2573  
  2574  func TestVarzRaces(t *testing.T) {
  2575  	s := runMonitorServer()
  2576  	defer s.Shutdown()
  2577  
  2578  	murl := fmt.Sprintf("http://127.0.0.1:%d/varz", s.MonitorAddr().Port)
  2579  	done := make(chan struct{})
  2580  	wg := sync.WaitGroup{}
  2581  	wg.Add(1)
  2582  	go func() {
  2583  		defer wg.Done()
  2584  		for {
  2585  			for i := 0; i < 2; i++ {
  2586  				v := pollVarz(t, s, i, murl, nil)
  2587  				// Check the field that we are setting in main thread
  2588  				// to ensure that we have a copy and there is no
  2589  				// race with fields set in s.info and s.opts
  2590  				if v.ID == "abc" || v.MaxConn == -1 {
  2591  					// We will not get there. Need to have something
  2592  					// otherwise staticcheck will report empty branch
  2593  					return
  2594  				}
  2595  
  2596  				select {
  2597  				case <-done:
  2598  					return
  2599  				default:
  2600  				}
  2601  			}
  2602  		}
  2603  	}()
  2604  
  2605  	for i := 0; i < 1000; i++ {
  2606  		// Simulate a change in server's info and options
  2607  		// by changing something.
  2608  		s.mu.Lock()
  2609  		s.info.ID = fmt.Sprintf("serverid_%d", i)
  2610  		s.opts.MaxConn = 100 + i
  2611  		s.mu.Unlock()
  2612  		time.Sleep(time.Nanosecond)
  2613  	}
  2614  	close(done)
  2615  	wg.Wait()
  2616  
  2617  	// Now check that there is no race doing parallel polling
  2618  	wg.Add(3)
  2619  	done = make(chan struct{})
  2620  	poll := func() {
  2621  		defer wg.Done()
  2622  		for {
  2623  			for mode := 0; mode < 2; mode++ {
  2624  				pollVarz(t, s, mode, murl, nil)
  2625  			}
  2626  			select {
  2627  			case <-done:
  2628  				return
  2629  			default:
  2630  			}
  2631  		}
  2632  	}
  2633  	for i := 0; i < 3; i++ {
  2634  		go poll()
  2635  	}
  2636  	time.Sleep(500 * time.Millisecond)
  2637  	close(done)
  2638  	wg.Wait()
  2639  }
  2640  
  2641  func testMonitorStructPresent(t *testing.T, tag string) {
  2642  	t.Helper()
  2643  
  2644  	resetPreviousHTTPConnections()
  2645  	opts := DefaultMonitorOptions()
  2646  	opts.NoSystemAccount = true
  2647  	s := RunServer(opts)
  2648  	defer s.Shutdown()
  2649  
  2650  	varzURL := fmt.Sprintf("http://127.0.0.1:%d/varz", s.MonitorAddr().Port)
  2651  	body := readBody(t, varzURL)
  2652  	if !bytes.Contains(body, []byte(`"`+tag+`": {}`)) {
  2653  		t.Fatalf("%s should be present and empty, got %s", tag, body)
  2654  	}
  2655  }
  2656  
  2657  func TestMonitorCluster(t *testing.T) {
  2658  	testMonitorStructPresent(t, "cluster")
  2659  
  2660  	resetPreviousHTTPConnections()
  2661  	opts := DefaultMonitorOptions()
  2662  	opts.NoSystemAccount = true
  2663  	opts.Cluster.Name = "A"
  2664  	opts.Cluster.Port = -1
  2665  	opts.Cluster.AuthTimeout = 1
  2666  	opts.Routes = RoutesFromStr("nats://127.0.0.1:1234")
  2667  	s := RunServer(opts)
  2668  	defer s.Shutdown()
  2669  
  2670  	expected := ClusterOptsVarz{
  2671  		"A",
  2672  		opts.Cluster.Host,
  2673  		opts.Cluster.Port,
  2674  		opts.Cluster.AuthTimeout,
  2675  		[]string{"127.0.0.1:1234"},
  2676  		opts.Cluster.TLSTimeout,
  2677  		opts.Cluster.TLSConfig != nil,
  2678  		opts.Cluster.TLSConfig != nil,
  2679  		DEFAULT_ROUTE_POOL_SIZE,
  2680  	}
  2681  
  2682  	varzURL := fmt.Sprintf("http://127.0.0.1:%d/varz", s.MonitorAddr().Port)
  2683  	for mode := 0; mode < 2; mode++ {
  2684  		check := func(t *testing.T, v *Varz) {
  2685  			t.Helper()
  2686  			if !reflect.DeepEqual(v.Cluster, expected) {
  2687  				t.Fatalf("mode=%v - expected %+v, got %+v", mode, expected, v.Cluster)
  2688  			}
  2689  		}
  2690  		v := pollVarz(t, s, mode, varzURL, nil)
  2691  		check(t, v)
  2692  
  2693  		// Having this here to make sure that if fields are added in ClusterOptsVarz,
  2694  		// we make sure to update this test (compiler will report an error if we don't)
  2695  		_ = ClusterOptsVarz{"", "", 0, 0, nil, 2, false, false, 0}
  2696  
  2697  		// Alter the fields to make sure that we have a proper deep copy
  2698  		// of what may be stored in the server. Anything we change here
  2699  		// should not affect the next returned value.
  2700  		v.Cluster.Name = "wrong"
  2701  		v.Cluster.Host = "wrong"
  2702  		v.Cluster.Port = 0
  2703  		v.Cluster.AuthTimeout = 0
  2704  		v.Cluster.URLs = []string{"wrong"}
  2705  		v = pollVarz(t, s, mode, varzURL, nil)
  2706  		check(t, v)
  2707  	}
  2708  }
  2709  
  2710  func TestMonitorClusterURLs(t *testing.T) {
  2711  	resetPreviousHTTPConnections()
  2712  
  2713  	o2 := DefaultOptions()
  2714  	o2.Cluster.Host = "127.0.0.1"
  2715  	o2.Cluster.Name = "A"
  2716  
  2717  	s2 := RunServer(o2)
  2718  	defer s2.Shutdown()
  2719  
  2720  	s2ClusterHostPort := fmt.Sprintf("127.0.0.1:%d", s2.ClusterAddr().Port)
  2721  
  2722  	template := `
  2723  		port: -1
  2724  		http: -1
  2725  		cluster: {
  2726  			name: "A"
  2727  			port: -1
  2728  			routes [
  2729  				%s
  2730  				%s
  2731  			]
  2732  		}
  2733  	`
  2734  	conf := createConfFile(t, []byte(fmt.Sprintf(template, "nats://"+s2ClusterHostPort, "")))
  2735  	s1, _ := RunServerWithConfig(conf)
  2736  	defer s1.Shutdown()
  2737  
  2738  	checkClusterFormed(t, s1, s2)
  2739  
  2740  	// Check /varz cluster{} to see the URLs from s1 to s2
  2741  	varzURL := fmt.Sprintf("http://127.0.0.1:%d/varz", s1.MonitorAddr().Port)
  2742  	for mode := 0; mode < 2; mode++ {
  2743  		v := pollVarz(t, s1, mode, varzURL, nil)
  2744  		if n := len(v.Cluster.URLs); n != 1 {
  2745  			t.Fatalf("mode=%v - Expected 1 URL, got %v", mode, n)
  2746  		}
  2747  		if v.Cluster.URLs[0] != s2ClusterHostPort {
  2748  			t.Fatalf("mode=%v - Expected url %q, got %q", mode, s2ClusterHostPort, v.Cluster.URLs[0])
  2749  		}
  2750  	}
  2751  
  2752  	otherClusterHostPort := "127.0.0.1:1234"
  2753  	// Now update the config and add a route
  2754  	changeCurrentConfigContentWithNewContent(t, conf, []byte(fmt.Sprintf(template, "nats://"+s2ClusterHostPort, "nats://"+otherClusterHostPort)))
  2755  
  2756  	if err := s1.Reload(); err != nil {
  2757  		t.Fatalf("Error on reload: %v", err)
  2758  	}
  2759  
  2760  	// Verify cluster still ok
  2761  	checkClusterFormed(t, s1, s2)
  2762  
  2763  	// Now verify that s1 reports in /varz the new URL
  2764  	checkFor(t, 2*time.Second, 15*time.Millisecond, func() error {
  2765  		for mode := 0; mode < 2; mode++ {
  2766  			v := pollVarz(t, s1, mode, varzURL, nil)
  2767  			if n := len(v.Cluster.URLs); n != 2 {
  2768  				t.Fatalf("mode=%v - Expected 2 URL, got %v", mode, n)
  2769  			}
  2770  			gotS2 := false
  2771  			gotOther := false
  2772  			for _, u := range v.Cluster.URLs {
  2773  				if u == s2ClusterHostPort {
  2774  					gotS2 = true
  2775  				} else if u == otherClusterHostPort {
  2776  					gotOther = true
  2777  				} else {
  2778  					t.Fatalf("mode=%v - Incorrect url: %q", mode, u)
  2779  				}
  2780  			}
  2781  			if !gotS2 {
  2782  				t.Fatalf("mode=%v - Did not get cluster URL for s2", mode)
  2783  			}
  2784  			if !gotOther {
  2785  				t.Fatalf("mode=%v - Did not get the new cluster URL", mode)
  2786  			}
  2787  		}
  2788  		return nil
  2789  	})
  2790  
  2791  	// Remove all routes from config
  2792  	changeCurrentConfigContentWithNewContent(t, conf, []byte(fmt.Sprintf(template, "", "")))
  2793  
  2794  	if err := s1.Reload(); err != nil {
  2795  		t.Fatalf("Error on reload: %v", err)
  2796  	}
  2797  
  2798  	// Now verify that s1 reports no ULRs in /varz
  2799  	checkFor(t, 2*time.Second, 15*time.Millisecond, func() error {
  2800  		for mode := 0; mode < 2; mode++ {
  2801  			v := pollVarz(t, s1, mode, varzURL, nil)
  2802  			if n := len(v.Cluster.URLs); n != 0 {
  2803  				t.Fatalf("mode=%v - Expected 0 URL, got %v", mode, n)
  2804  			}
  2805  		}
  2806  		return nil
  2807  	})
  2808  }
  2809  
  2810  func TestMonitorGateway(t *testing.T) {
  2811  	testMonitorStructPresent(t, "gateway")
  2812  
  2813  	resetPreviousHTTPConnections()
  2814  	opts := DefaultMonitorOptions()
  2815  	opts.NoSystemAccount = true
  2816  	opts.Gateway.Name = "A"
  2817  	opts.Gateway.Port = -1
  2818  	opts.Gateway.AuthTimeout = 1
  2819  	opts.Gateway.TLSTimeout = 1
  2820  	opts.Gateway.Advertise = "127.0.0.1"
  2821  	opts.Gateway.ConnectRetries = 1
  2822  	opts.Gateway.RejectUnknown = false
  2823  	u1, _ := url.Parse("nats://ivan:pwd@localhost:1234")
  2824  	u2, _ := url.Parse("nats://localhost:1235")
  2825  	opts.Gateway.Gateways = []*RemoteGatewayOpts{
  2826  		{
  2827  			Name:       "B",
  2828  			TLSTimeout: 1,
  2829  			URLs: []*url.URL{
  2830  				u1,
  2831  				u2,
  2832  			},
  2833  		},
  2834  	}
  2835  	s := RunServer(opts)
  2836  	defer s.Shutdown()
  2837  
  2838  	expected := GatewayOptsVarz{
  2839  		"A",
  2840  		opts.Gateway.Host,
  2841  		opts.Gateway.Port,
  2842  		opts.Gateway.AuthTimeout,
  2843  		opts.Gateway.TLSTimeout,
  2844  		opts.Gateway.TLSConfig != nil,
  2845  		opts.Gateway.TLSConfig != nil,
  2846  		opts.Gateway.Advertise,
  2847  		opts.Gateway.ConnectRetries,
  2848  		[]RemoteGatewayOptsVarz{{"B", 1, nil}},
  2849  		opts.Gateway.RejectUnknown,
  2850  	}
  2851  	// Since URLs array is not guaranteed to be always the same order,
  2852  	// we don't add it in the expected GatewayOptsVarz, instead we
  2853  	// maintain here.
  2854  	expectedURLs := []string{"localhost:1234", "localhost:1235"}
  2855  
  2856  	varzURL := fmt.Sprintf("http://127.0.0.1:%d/varz", s.MonitorAddr().Port)
  2857  	for mode := 0; mode < 2; mode++ {
  2858  		check := func(t *testing.T, v *Varz) {
  2859  			t.Helper()
  2860  			var urls []string
  2861  			if len(v.Gateway.Gateways) == 1 {
  2862  				urls = v.Gateway.Gateways[0].URLs
  2863  				v.Gateway.Gateways[0].URLs = nil
  2864  			}
  2865  			if !reflect.DeepEqual(v.Gateway, expected) {
  2866  				t.Fatalf("mode=%v - expected %+v, got %+v", mode, expected, v.Gateway)
  2867  			}
  2868  			// Now compare urls
  2869  			for _, u := range expectedURLs {
  2870  				ok := false
  2871  				for _, u2 := range urls {
  2872  					if u == u2 {
  2873  						ok = true
  2874  						break
  2875  					}
  2876  				}
  2877  				if !ok {
  2878  					t.Fatalf("mode=%v - expected urls to be %v, got %v", mode, expected.Gateways[0].URLs, urls)
  2879  				}
  2880  			}
  2881  		}
  2882  		v := pollVarz(t, s, mode, varzURL, nil)
  2883  		check(t, v)
  2884  
  2885  		// Having this here to make sure that if fields are added in GatewayOptsVarz,
  2886  		// we make sure to update this test (compiler will report an error if we don't)
  2887  		_ = GatewayOptsVarz{"", "", 0, 0, 0, false, false, "", 0, []RemoteGatewayOptsVarz{{"", 0, nil}}, false}
  2888  
  2889  		// Alter the fields to make sure that we have a proper deep copy
  2890  		// of what may be stored in the server. Anything we change here
  2891  		// should not affect the next returned value.
  2892  		v.Gateway.Name = "wrong"
  2893  		v.Gateway.Host = "wrong"
  2894  		v.Gateway.Port = 0
  2895  		v.Gateway.AuthTimeout = 1234.5
  2896  		v.Gateway.TLSTimeout = 1234.5
  2897  		v.Gateway.Advertise = "wrong"
  2898  		v.Gateway.ConnectRetries = 1234
  2899  		v.Gateway.Gateways[0].Name = "wrong"
  2900  		v.Gateway.Gateways[0].TLSTimeout = 1234.5
  2901  		v.Gateway.Gateways[0].URLs = []string{"wrong"}
  2902  		v.Gateway.RejectUnknown = true
  2903  		v = pollVarz(t, s, mode, varzURL, nil)
  2904  		check(t, v)
  2905  	}
  2906  }
  2907  
  2908  func TestMonitorGatewayURLsUpdated(t *testing.T) {
  2909  	resetPreviousHTTPConnections()
  2910  
  2911  	ob1 := testDefaultOptionsForGateway("B")
  2912  	sb1 := runGatewayServer(ob1)
  2913  	defer sb1.Shutdown()
  2914  
  2915  	// Start a1 that has a single URL to sb1.
  2916  	oa := testGatewayOptionsFromToWithServers(t, "A", "B", sb1)
  2917  	oa.HTTPHost = "127.0.0.1"
  2918  	oa.HTTPPort = MONITOR_PORT
  2919  	sa := runGatewayServer(oa)
  2920  	defer sa.Shutdown()
  2921  
  2922  	waitForOutboundGateways(t, sa, 1, 2*time.Second)
  2923  
  2924  	varzURL := fmt.Sprintf("http://127.0.0.1:%d/varz", sa.MonitorAddr().Port)
  2925  	// Check the /varz gateway's URLs
  2926  	for mode := 0; mode < 2; mode++ {
  2927  		v := pollVarz(t, sa, mode, varzURL, nil)
  2928  		if n := len(v.Gateway.Gateways); n != 1 {
  2929  			t.Fatalf("mode=%v - Expected 1 remote gateway, got %v", mode, n)
  2930  		}
  2931  		gw := v.Gateway.Gateways[0]
  2932  		if n := len(gw.URLs); n != 1 {
  2933  			t.Fatalf("mode=%v - Expected 1 url, got %v", mode, n)
  2934  		}
  2935  		expected := oa.Gateway.Gateways[0].URLs[0].Host
  2936  		if u := gw.URLs[0]; u != expected {
  2937  			t.Fatalf("mode=%v - Expected URL %q, got %q", mode, expected, u)
  2938  		}
  2939  	}
  2940  
  2941  	// Now start sb2 that clusters with sb1. sa should add to its list of URLs
  2942  	// sb2 gateway's connect URL.
  2943  	ob2 := testDefaultOptionsForGateway("B")
  2944  	ob2.Routes = RoutesFromStr(fmt.Sprintf("nats://127.0.0.1:%d", sb1.ClusterAddr().Port))
  2945  	sb2 := runGatewayServer(ob2)
  2946  	defer sb2.Shutdown()
  2947  
  2948  	// Wait for sb1 and sb2 to connect
  2949  	checkClusterFormed(t, sb1, sb2)
  2950  	// sb2 should be made aware of gateway A and connect to sa
  2951  	waitForInboundGateways(t, sa, 2, 2*time.Second)
  2952  	// Now check that URLs in /varz get updated
  2953  	checkFor(t, 2*time.Second, 15*time.Millisecond, func() error {
  2954  		for mode := 0; mode < 2; mode++ {
  2955  			v := pollVarz(t, sa, mode, varzURL, nil)
  2956  			if n := len(v.Gateway.Gateways); n != 1 {
  2957  				return fmt.Errorf("mode=%v - Expected 1 remote gateway, got %v", mode, n)
  2958  			}
  2959  			gw := v.Gateway.Gateways[0]
  2960  			if n := len(gw.URLs); n != 2 {
  2961  				return fmt.Errorf("mode=%v - Expected 2 urls, got %v", mode, n)
  2962  			}
  2963  
  2964  			gotSB1 := false
  2965  			gotSB2 := false
  2966  			for _, u := range gw.URLs {
  2967  				if u == fmt.Sprintf("127.0.0.1:%d", sb1.GatewayAddr().Port) {
  2968  					gotSB1 = true
  2969  				} else if u == fmt.Sprintf("127.0.0.1:%d", sb2.GatewayAddr().Port) {
  2970  					gotSB2 = true
  2971  				} else {
  2972  					return fmt.Errorf("mode=%v - Incorrect URL to gateway B: %v", mode, u)
  2973  				}
  2974  			}
  2975  			if !gotSB1 {
  2976  				return fmt.Errorf("mode=%v - Did not get URL to sb1", mode)
  2977  			}
  2978  			if !gotSB2 {
  2979  				return fmt.Errorf("mode=%v - Did not get URL to sb2", mode)
  2980  			}
  2981  		}
  2982  		return nil
  2983  	})
  2984  
  2985  	// Now stop sb2 and make sure that its removal is reflected in varz.
  2986  	sb2.Shutdown()
  2987  	// Wait for it to disappear from sa.
  2988  	waitForInboundGateways(t, sa, 1, 2*time.Second)
  2989  	// Now check that URLs in /varz get updated.
  2990  	checkFor(t, 2*time.Second, 15*time.Millisecond, func() error {
  2991  		for mode := 0; mode < 2; mode++ {
  2992  			v := pollVarz(t, sa, mode, varzURL, nil)
  2993  			if n := len(v.Gateway.Gateways); n != 1 {
  2994  				return fmt.Errorf("mode=%v - Expected 1 remote gateway, got %v", mode, n)
  2995  			}
  2996  			gw := v.Gateway.Gateways[0]
  2997  			if n := len(gw.URLs); n != 1 {
  2998  				return fmt.Errorf("mode=%v - Expected 1 url, got %v", mode, n)
  2999  			}
  3000  			u := gw.URLs[0]
  3001  			if u != fmt.Sprintf("127.0.0.1:%d", sb1.GatewayAddr().Port) {
  3002  				return fmt.Errorf("mode=%v - Did not get URL to sb1", mode)
  3003  			}
  3004  		}
  3005  		return nil
  3006  	})
  3007  }
  3008  
  3009  func TestMonitorGatewayReportItsOwnURLs(t *testing.T) {
  3010  	resetPreviousHTTPConnections()
  3011  
  3012  	// In this test, we show that if a server has its own gateway information
  3013  	// as a remote (which is the case when remote gateway definitions is copied
  3014  	// on all clusters), we display the defined URLs.
  3015  	oa := testGatewayOptionsFromToWithURLs(t, "A", "A", []string{"nats://127.0.0.1:1234", "nats://127.0.0.1:1235"})
  3016  	oa.HTTPHost = "127.0.0.1"
  3017  	oa.HTTPPort = MONITOR_PORT
  3018  	sa := runGatewayServer(oa)
  3019  	defer sa.Shutdown()
  3020  
  3021  	varzURL := fmt.Sprintf("http://127.0.0.1:%d/varz", sa.MonitorAddr().Port)
  3022  	// Check the /varz gateway's URLs
  3023  	for mode := 0; mode < 2; mode++ {
  3024  		v := pollVarz(t, sa, mode, varzURL, nil)
  3025  		if n := len(v.Gateway.Gateways); n != 1 {
  3026  			t.Fatalf("mode=%v - Expected 1 remote gateway, got %v", mode, n)
  3027  		}
  3028  		gw := v.Gateway.Gateways[0]
  3029  		if n := len(gw.URLs); n != 2 {
  3030  			t.Fatalf("mode=%v - Expected 2 urls, got %v", mode, gw.URLs)
  3031  		}
  3032  		expected := []string{"127.0.0.1:1234", "127.0.0.1:1235"}
  3033  		if !reflect.DeepEqual(gw.URLs, expected) {
  3034  			t.Fatalf("mode=%v - Expected URLs %q, got %q", mode, expected, gw.URLs)
  3035  		}
  3036  	}
  3037  }
  3038  
  3039  func TestMonitorLeafNode(t *testing.T) {
  3040  	testMonitorStructPresent(t, "leaf")
  3041  
  3042  	resetPreviousHTTPConnections()
  3043  	opts := DefaultMonitorOptions()
  3044  	opts.NoSystemAccount = true
  3045  	opts.LeafNode.Port = -1
  3046  	opts.LeafNode.AuthTimeout = 1
  3047  	opts.LeafNode.TLSTimeout = 1
  3048  	opts.Accounts = []*Account{NewAccount("acc")}
  3049  	u, _ := url.Parse("nats://ivan:pwd@localhost:1234")
  3050  	opts.LeafNode.Remotes = []*RemoteLeafOpts{
  3051  		{
  3052  			LocalAccount: "acc",
  3053  			URLs:         []*url.URL{u},
  3054  			TLSTimeout:   1,
  3055  		},
  3056  	}
  3057  	s := RunServer(opts)
  3058  	defer s.Shutdown()
  3059  
  3060  	expected := LeafNodeOptsVarz{
  3061  		opts.LeafNode.Host,
  3062  		opts.LeafNode.Port,
  3063  		opts.LeafNode.AuthTimeout,
  3064  		opts.LeafNode.TLSTimeout,
  3065  		opts.LeafNode.TLSConfig != nil,
  3066  		opts.LeafNode.TLSConfig != nil,
  3067  		[]RemoteLeafOptsVarz{
  3068  			{
  3069  				"acc", 1, []string{"localhost:1234"}, nil, false,
  3070  			},
  3071  		},
  3072  		false,
  3073  	}
  3074  
  3075  	varzURL := fmt.Sprintf("http://127.0.0.1:%d/varz", s.MonitorAddr().Port)
  3076  
  3077  	for mode := 0; mode < 2; mode++ {
  3078  		check := func(t *testing.T, v *Varz) {
  3079  			t.Helper()
  3080  			if !reflect.DeepEqual(v.LeafNode, expected) {
  3081  				t.Fatalf("mode=%v - expected %+v, got %+v", mode, expected, v.LeafNode)
  3082  			}
  3083  		}
  3084  		v := pollVarz(t, s, mode, varzURL, nil)
  3085  		check(t, v)
  3086  
  3087  		// Having this here to make sure that if fields are added in ClusterOptsVarz,
  3088  		// we make sure to update this test (compiler will report an error if we don't)
  3089  		_ = LeafNodeOptsVarz{"", 0, 0, 0, false, false, []RemoteLeafOptsVarz{{"", 0, nil, nil, false}}, false}
  3090  
  3091  		// Alter the fields to make sure that we have a proper deep copy
  3092  		// of what may be stored in the server. Anything we change here
  3093  		// should not affect the next returned value.
  3094  		v.LeafNode.Host = "wrong"
  3095  		v.LeafNode.Port = 0
  3096  		v.LeafNode.AuthTimeout = 1234.5
  3097  		v.LeafNode.TLSTimeout = 1234.5
  3098  		v.LeafNode.Remotes[0].LocalAccount = "wrong"
  3099  		v.LeafNode.Remotes[0].URLs = append(v.LeafNode.Remotes[0].URLs, "wrong")
  3100  		v.LeafNode.Remotes[0].TLSTimeout = 1234.5
  3101  		v = pollVarz(t, s, mode, varzURL, nil)
  3102  		check(t, v)
  3103  	}
  3104  }
  3105  
  3106  func pollGatewayz(t *testing.T, s *Server, mode int, url string, opts *GatewayzOptions) *Gatewayz {
  3107  	t.Helper()
  3108  	if mode == 0 {
  3109  		g := &Gatewayz{}
  3110  		body := readBody(t, url)
  3111  		if err := json.Unmarshal(body, g); err != nil {
  3112  			t.Fatalf("Got an error unmarshalling the body: %v\n", err)
  3113  		}
  3114  		return g
  3115  	}
  3116  	g, err := s.Gatewayz(opts)
  3117  	if err != nil {
  3118  		t.Fatalf("Error on Gatewayz: %v", err)
  3119  	}
  3120  	return g
  3121  }
  3122  
  3123  func TestMonitorGatewayz(t *testing.T) {
  3124  	resetPreviousHTTPConnections()
  3125  
  3126  	// First check that without gateway configured
  3127  	s := runMonitorServer()
  3128  	defer s.Shutdown()
  3129  	url := fmt.Sprintf("http://127.0.0.1:%d/gatewayz", s.MonitorAddr().Port)
  3130  	for pollMode := 0; pollMode < 2; pollMode++ {
  3131  		g := pollGatewayz(t, s, pollMode, url, nil)
  3132  		// Expect Name and port to be empty
  3133  		if g.Name != _EMPTY_ || g.Port != 0 {
  3134  			t.Fatalf("Expected no gateway, got %+v", g)
  3135  		}
  3136  	}
  3137  	s.Shutdown()
  3138  
  3139  	ob1 := testDefaultOptionsForGateway("B")
  3140  	sb1 := runGatewayServer(ob1)
  3141  	defer sb1.Shutdown()
  3142  
  3143  	// Start a1 that has a single URL to sb1.
  3144  	oa := testGatewayOptionsFromToWithServers(t, "A", "B", sb1)
  3145  	oa.HTTPHost = "127.0.0.1"
  3146  	oa.HTTPPort = MONITOR_PORT
  3147  	sa := runGatewayServer(oa)
  3148  	defer sa.Shutdown()
  3149  
  3150  	waitForOutboundGateways(t, sa, 1, 2*time.Second)
  3151  	waitForInboundGateways(t, sa, 1, 2*time.Second)
  3152  
  3153  	waitForOutboundGateways(t, sb1, 1, 2*time.Second)
  3154  	waitForInboundGateways(t, sb1, 1, 2*time.Second)
  3155  
  3156  	gatewayzURL := fmt.Sprintf("http://127.0.0.1:%d/gatewayz", sa.MonitorAddr().Port)
  3157  	for pollMode := 0; pollMode < 2; pollMode++ {
  3158  		g := pollGatewayz(t, sa, pollMode, gatewayzURL, nil)
  3159  		if g.Host != oa.Gateway.Host {
  3160  			t.Fatalf("mode=%v - Expected host to be %q, got %q", pollMode, oa.Gateway.Host, g.Host)
  3161  		}
  3162  		if g.Port != oa.Gateway.Port {
  3163  			t.Fatalf("mode=%v - Expected port to be %v, got %v", pollMode, oa.Gateway.Port, g.Port)
  3164  		}
  3165  		if n := len(g.OutboundGateways); n != 1 {
  3166  			t.Fatalf("mode=%v - Expected outbound to 1 gateway, got %v", pollMode, n)
  3167  		}
  3168  		if n := len(g.InboundGateways); n != 1 {
  3169  			t.Fatalf("mode=%v - Expected inbound from 1 gateway, got %v", pollMode, n)
  3170  		}
  3171  		og := g.OutboundGateways["B"]
  3172  		if og == nil {
  3173  			t.Fatalf("mode=%v - Expected to find outbound connection to B, got none", pollMode)
  3174  		}
  3175  		if !og.IsConfigured {
  3176  			t.Fatalf("mode=%v - Expected gw connection to be configured, was not", pollMode)
  3177  		}
  3178  		if og.Connection == nil {
  3179  			t.Fatalf("mode=%v - Expected outbound connection to B to be set, wat not", pollMode)
  3180  		}
  3181  		if og.Connection.Name != sb1.ID() {
  3182  			t.Fatalf("mode=%v - Expected outbound connection to B to have name %q, got %q", pollMode, sb1.ID(), og.Connection.Name)
  3183  		}
  3184  		if n := len(og.Accounts); n != 0 {
  3185  			t.Fatalf("mode=%v - Expected no account, got %v", pollMode, n)
  3186  		}
  3187  		ig := g.InboundGateways["B"]
  3188  		if ig == nil {
  3189  			t.Fatalf("mode=%v - Expected to find inbound connection from B, got none", pollMode)
  3190  		}
  3191  		if n := len(ig); n != 1 {
  3192  			t.Fatalf("mode=%v - Expected 1 inbound connection, got %v", pollMode, n)
  3193  		}
  3194  		igc := ig[0]
  3195  		if igc.Connection == nil {
  3196  			t.Fatalf("mode=%v - Expected inbound connection to B to be set, wat not", pollMode)
  3197  		}
  3198  		if igc.Connection.Name != sb1.ID() {
  3199  			t.Fatalf("mode=%v - Expected inbound connection to B to have name %q, got %q", pollMode, sb1.ID(), igc.Connection.Name)
  3200  		}
  3201  	}
  3202  
  3203  	// Now start sb2 that clusters with sb1. sa should add to its list of URLs
  3204  	// sb2 gateway's connect URL.
  3205  	ob2 := testDefaultOptionsForGateway("B")
  3206  	ob2.Routes = RoutesFromStr(fmt.Sprintf("nats://127.0.0.1:%d", sb1.ClusterAddr().Port))
  3207  	sb2 := runGatewayServer(ob2)
  3208  	defer sb2.Shutdown()
  3209  
  3210  	// Wait for sb1 and sb2 to connect
  3211  	checkClusterFormed(t, sb1, sb2)
  3212  	// sb2 should be made aware of gateway A and connect to sa
  3213  	waitForInboundGateways(t, sa, 2, 2*time.Second)
  3214  	// Now check that URLs in /varz get updated
  3215  	checkGatewayB := func(t *testing.T, url string, opts *GatewayzOptions) {
  3216  		t.Helper()
  3217  		checkFor(t, 2*time.Second, 15*time.Millisecond, func() error {
  3218  			for pollMode := 0; pollMode < 2; pollMode++ {
  3219  				g := pollGatewayz(t, sa, pollMode, url, opts)
  3220  				if n := len(g.OutboundGateways); n != 1 {
  3221  					t.Fatalf("mode=%v - Expected outbound to 1 gateway, got %v", pollMode, n)
  3222  				}
  3223  				// The InboundGateways is a map with key the gateway names,
  3224  				// then value is array of connections. So should be 1 here.
  3225  				if n := len(g.InboundGateways); n != 1 {
  3226  					t.Fatalf("mode=%v - Expected inbound from 1 gateway, got %v", pollMode, n)
  3227  				}
  3228  				ig := g.InboundGateways["B"]
  3229  				if ig == nil {
  3230  					t.Fatalf("mode=%v - Expected to find inbound connection from B, got none", pollMode)
  3231  				}
  3232  				if n := len(ig); n != 2 {
  3233  					t.Fatalf("mode=%v - Expected 2 inbound connections from gateway B, got %v", pollMode, n)
  3234  				}
  3235  				gotSB1 := false
  3236  				gotSB2 := false
  3237  				for _, rg := range ig {
  3238  					if rg.Connection != nil {
  3239  						if rg.Connection.Name == sb1.ID() {
  3240  							gotSB1 = true
  3241  						} else if rg.Connection.Name == sb2.ID() {
  3242  							gotSB2 = true
  3243  						}
  3244  					}
  3245  				}
  3246  				if !gotSB1 {
  3247  					t.Fatalf("mode=%v - Missing inbound connection from sb1", pollMode)
  3248  				}
  3249  				if !gotSB2 {
  3250  					t.Fatalf("mode=%v - Missing inbound connection from sb2", pollMode)
  3251  				}
  3252  			}
  3253  			return nil
  3254  		})
  3255  	}
  3256  	checkGatewayB(t, gatewayzURL, nil)
  3257  
  3258  	// Start a new cluser C that connects to B. A should see it as
  3259  	// a non-configured gateway.
  3260  	oc := testGatewayOptionsFromToWithServers(t, "C", "B", sb1)
  3261  	sc := runGatewayServer(oc)
  3262  	defer sc.Shutdown()
  3263  
  3264  	// All servers should have 2 outbound connections (one for each other cluster)
  3265  	waitForOutboundGateways(t, sa, 2, 2*time.Second)
  3266  	waitForOutboundGateways(t, sb1, 2, 2*time.Second)
  3267  	waitForOutboundGateways(t, sb2, 2, 2*time.Second)
  3268  	waitForOutboundGateways(t, sc, 2, 2*time.Second)
  3269  
  3270  	// Server sa should have 3 inbounds now
  3271  	waitForInboundGateways(t, sa, 3, 2*time.Second)
  3272  
  3273  	// Check gatewayz again to see that we have C now.
  3274  	checkFor(t, 2*time.Second, 15*time.Millisecond, func() error {
  3275  		for pollMode := 0; pollMode < 2; pollMode++ {
  3276  			g := pollGatewayz(t, sa, pollMode, gatewayzURL, nil)
  3277  			if n := len(g.OutboundGateways); n != 2 {
  3278  				t.Fatalf("mode=%v - Expected outbound to 2 gateways, got %v", pollMode, n)
  3279  			}
  3280  			// The InboundGateways is a map with key the gateway names,
  3281  			// then value is array of connections. So should be 2 here.
  3282  			if n := len(g.InboundGateways); n != 2 {
  3283  				t.Fatalf("mode=%v - Expected inbound from 2 gateways, got %v", pollMode, n)
  3284  			}
  3285  			og := g.OutboundGateways["C"]
  3286  			if og == nil {
  3287  				t.Fatalf("mode=%v - Expected to find outbound connection to C, got none", pollMode)
  3288  			}
  3289  			if og.IsConfigured {
  3290  				t.Fatalf("mode=%v - Expected IsConfigured for gateway C to be false, was true", pollMode)
  3291  			}
  3292  			if og.Connection == nil {
  3293  				t.Fatalf("mode=%v - Expected connection to C, got none", pollMode)
  3294  			}
  3295  			if og.Connection.Name != sc.ID() {
  3296  				t.Fatalf("mode=%v - Expected outbound connection to C to have name %q, got %q", pollMode, sc.ID(), og.Connection.Name)
  3297  			}
  3298  			ig := g.InboundGateways["C"]
  3299  			if ig == nil {
  3300  				t.Fatalf("mode=%v - Expected to find inbound connection from C, got none", pollMode)
  3301  			}
  3302  			if n := len(ig); n != 1 {
  3303  				t.Fatalf("mode=%v - Expected 1 inbound connections from gateway C, got %v", pollMode, n)
  3304  			}
  3305  			igc := ig[0]
  3306  			if igc.Connection == nil {
  3307  				t.Fatalf("mode=%v - Expected connection to C, got none", pollMode)
  3308  			}
  3309  			if igc.Connection.Name != sc.ID() {
  3310  				t.Fatalf("mode=%v - Expected outbound connection to C to have name %q, got %q", pollMode, sc.ID(), og.Connection.Name)
  3311  			}
  3312  		}
  3313  		return nil
  3314  	})
  3315  
  3316  	// Select only 1 gateway by passing the name to option/url
  3317  	opts := &GatewayzOptions{Name: "B"}
  3318  	checkGatewayB(t, gatewayzURL+"?gw_name=B", opts)
  3319  
  3320  	// Stop gateway C and check that we have only B, with and without filter.
  3321  	sc.Shutdown()
  3322  	checkGatewayB(t, gatewayzURL+"?gw_name=B", opts)
  3323  	checkGatewayB(t, gatewayzURL, nil)
  3324  }
  3325  
  3326  func TestMonitorGatewayzAccounts(t *testing.T) {
  3327  	GatewayDoNotForceInterestOnlyMode(true)
  3328  	defer GatewayDoNotForceInterestOnlyMode(false)
  3329  
  3330  	resetPreviousHTTPConnections()
  3331  
  3332  	// Create bunch of Accounts
  3333  	totalAccounts := 15
  3334  	accounts := ""
  3335  	for i := 0; i < totalAccounts; i++ {
  3336  		acc := fmt.Sprintf("	acc_%d: { users=[{user:user_%d, password: pwd}] }\n", i, i)
  3337  		accounts += acc
  3338  	}
  3339  
  3340  	bConf := createConfFile(t, []byte(fmt.Sprintf(`
  3341  		accounts {
  3342  			%s
  3343  		}
  3344  		port: -1
  3345  		http: -1
  3346  		gateway: {
  3347  			name: "B"
  3348  			port: -1
  3349  		}
  3350  		no_sys_acc = true
  3351  	`, accounts)))
  3352  
  3353  	sb, ob := RunServerWithConfig(bConf)
  3354  	defer sb.Shutdown()
  3355  	sb.SetLogger(&DummyLogger{}, true, true)
  3356  
  3357  	// Start a1 that has a single URL to sb1.
  3358  	aConf := createConfFile(t, []byte(fmt.Sprintf(`
  3359  		accounts {
  3360  			%s
  3361  		}
  3362  		port: -1
  3363  		http: -1
  3364  		gateway: {
  3365  			name: "A"
  3366  			port: -1
  3367  			gateways [
  3368  				{
  3369  					name: "B"
  3370  					url: "nats://127.0.0.1:%d"
  3371  				}
  3372  			]
  3373  		}
  3374  		no_sys_acc = true
  3375  	`, accounts, sb.GatewayAddr().Port)))
  3376  
  3377  	sa, oa := RunServerWithConfig(aConf)
  3378  	defer sa.Shutdown()
  3379  	sa.SetLogger(&DummyLogger{}, true, true)
  3380  
  3381  	waitForOutboundGateways(t, sa, 1, 2*time.Second)
  3382  	waitForInboundGateways(t, sa, 1, 2*time.Second)
  3383  	waitForOutboundGateways(t, sb, 1, 2*time.Second)
  3384  	waitForInboundGateways(t, sb, 1, 2*time.Second)
  3385  
  3386  	// Create clients for each account on A and publish a message
  3387  	// so that list of accounts appear in gatewayz
  3388  	produceMsgsFromA := func(t *testing.T) {
  3389  		t.Helper()
  3390  		for i := 0; i < totalAccounts; i++ {
  3391  			nc, err := nats.Connect(fmt.Sprintf("nats://user_%d:pwd@%s:%d", i, oa.Host, oa.Port))
  3392  			if err != nil {
  3393  				t.Fatalf("Error on connect: %v", err)
  3394  			}
  3395  			nc.Publish("foo", []byte("hello"))
  3396  			nc.Flush()
  3397  			nc.Close()
  3398  		}
  3399  	}
  3400  	produceMsgsFromA(t)
  3401  
  3402  	// Wait for A- for all accounts
  3403  	gwc := sa.getOutboundGatewayConnection("B")
  3404  	for i := 0; i < totalAccounts; i++ {
  3405  		checkForAccountNoInterest(t, gwc, fmt.Sprintf("acc_%d", i), true, 2*time.Second)
  3406  	}
  3407  
  3408  	// Check accounts...
  3409  	gatewayzURL := fmt.Sprintf("http://127.0.0.1:%d/gatewayz", sa.MonitorAddr().Port)
  3410  	for pollMode := 0; pollMode < 2; pollMode++ {
  3411  		// First, without asking for it, they should not be present.
  3412  		g := pollGatewayz(t, sa, pollMode, gatewayzURL, nil)
  3413  		og := g.OutboundGateways["B"]
  3414  		if og == nil {
  3415  			t.Fatalf("mode=%v - Expected outbound gateway to B, got none", pollMode)
  3416  		}
  3417  		if n := len(og.Accounts); n != 0 {
  3418  			t.Fatalf("mode=%v - Expected accounts list to not be present by default, got %v", pollMode, n)
  3419  		}
  3420  		// Now ask for the accounts
  3421  		g = pollGatewayz(t, sa, pollMode, gatewayzURL+"?accs=1", &GatewayzOptions{Accounts: true})
  3422  		og = g.OutboundGateways["B"]
  3423  		if og == nil {
  3424  			t.Fatalf("mode=%v - Expected outbound gateway to B, got none", pollMode)
  3425  		}
  3426  		if n := len(og.Accounts); n != totalAccounts {
  3427  			t.Fatalf("mode=%v - Expected to get all %d accounts, got %v", pollMode, totalAccounts, n)
  3428  		}
  3429  		// Now account details
  3430  		for _, acc := range og.Accounts {
  3431  			if acc.InterestMode != Optimistic.String() {
  3432  				t.Fatalf("mode=%v - Expected optimistic mode, got %q", pollMode, acc.InterestMode)
  3433  			}
  3434  			// Since there is no interest at all on B, the publish
  3435  			// will have resulted in total account no interest, so
  3436  			// the number of no interest (subject wise) should be 0
  3437  			if acc.NoInterestCount != 0 {
  3438  				t.Fatalf("mode=%v - Expected 0 no-interest, got %v", pollMode, acc.NoInterestCount)
  3439  			}
  3440  			if acc.NumQueueSubscriptions != 0 || acc.TotalSubscriptions != 0 {
  3441  				t.Fatalf("mode=%v - Expected total subs to be 0, got %v - and num queue subs to be 0, got %v",
  3442  					pollMode, acc.TotalSubscriptions, acc.NumQueueSubscriptions)
  3443  			}
  3444  		}
  3445  	}
  3446  
  3447  	// Check inbound on B
  3448  	gwURLServerB := fmt.Sprintf("http://127.0.0.1:%d/gatewayz", sb.MonitorAddr().Port)
  3449  	checkFor(t, 2*time.Second, 15*time.Millisecond, func() error {
  3450  		for pollMode := 0; pollMode < 2; pollMode++ {
  3451  			// First, without asking for it, they should not be present.
  3452  			g := pollGatewayz(t, sb, pollMode, gwURLServerB, nil)
  3453  			igs := g.InboundGateways["A"]
  3454  			if igs == nil {
  3455  				return fmt.Errorf("mode=%v - Expected inbound gateway to A, got none", pollMode)
  3456  			}
  3457  			if len(igs) != 1 {
  3458  				return fmt.Errorf("mode=%v - Expected single inbound, got %v", pollMode, len(igs))
  3459  			}
  3460  			ig := igs[0]
  3461  			if n := len(ig.Accounts); n != 0 {
  3462  				return fmt.Errorf("mode=%v - Expected no account, got %v", pollMode, n)
  3463  			}
  3464  			// Check that list of accounts
  3465  			g = pollGatewayz(t, sb, pollMode, gwURLServerB+"?accs=1", &GatewayzOptions{Accounts: true})
  3466  			igs = g.InboundGateways["A"]
  3467  			if igs == nil {
  3468  				return fmt.Errorf("mode=%v - Expected inbound gateway to A, got none", pollMode)
  3469  			}
  3470  			if len(igs) != 1 {
  3471  				return fmt.Errorf("mode=%v - Expected single inbound, got %v", pollMode, len(igs))
  3472  			}
  3473  			ig = igs[0]
  3474  			if ig.Connection == nil {
  3475  				return fmt.Errorf("mode=%v - Expected inbound connection from A to be set, wat not", pollMode)
  3476  			}
  3477  			if ig.Connection.Name != sa.ID() {
  3478  				t.Fatalf("mode=%v - Expected inbound connection from A to have name %q, got %q", pollMode, sa.ID(), ig.Connection.Name)
  3479  			}
  3480  			if n := len(ig.Accounts); n != totalAccounts {
  3481  				return fmt.Errorf("mode=%v - Expected to get all %d accounts, got %v", pollMode, totalAccounts, n)
  3482  			}
  3483  			// Now account details
  3484  			for _, acc := range ig.Accounts {
  3485  				if acc.InterestMode != Optimistic.String() {
  3486  					return fmt.Errorf("mode=%v - Expected optimistic mode, got %q", pollMode, acc.InterestMode)
  3487  				}
  3488  				// Since there is no interest at all on B, the publish
  3489  				// will have resulted in total account no interest, so
  3490  				// the number of no interest (subject wise) should be 0
  3491  				if acc.NoInterestCount != 0 {
  3492  					t.Fatalf("mode=%v - Expected 0 no-interest, got %v", pollMode, acc.NoInterestCount)
  3493  				}
  3494  				// For inbound gateway, NumQueueSubscriptions and TotalSubscriptions
  3495  				// are not relevant.
  3496  				if acc.NumQueueSubscriptions != 0 || acc.TotalSubscriptions != 0 {
  3497  					return fmt.Errorf("mode=%v - For inbound connection, expected num queue subs and total subs to be 0, got %v and %v",
  3498  						pollMode, acc.TotalSubscriptions, acc.NumQueueSubscriptions)
  3499  				}
  3500  			}
  3501  		}
  3502  		return nil
  3503  	})
  3504  
  3505  	// Now create subscriptions on B to prevent A- and check on subject no interest
  3506  	for i := 0; i < totalAccounts; i++ {
  3507  		nc, err := nats.Connect(fmt.Sprintf("nats://user_%d:pwd@%s:%d", i, ob.Host, ob.Port))
  3508  		if err != nil {
  3509  			t.Fatalf("Error on connect: %v", err)
  3510  		}
  3511  		defer nc.Close()
  3512  		// Create a queue sub so it shows up in gatewayz
  3513  		nc.QueueSubscribeSync("bar", "queue")
  3514  		// Create plain subscriptions on baz.0, baz.1 and baz.2.
  3515  		// Create to for each subject. Since gateways will send
  3516  		// only once per subject, the number of subs should be 3, not 6.
  3517  		for j := 0; j < 3; j++ {
  3518  			subj := fmt.Sprintf("baz.%d", j)
  3519  			nc.SubscribeSync(subj)
  3520  			nc.SubscribeSync(subj)
  3521  		}
  3522  		nc.Flush()
  3523  	}
  3524  
  3525  	for i := 0; i < totalAccounts; i++ {
  3526  		accName := fmt.Sprintf("acc_%d", i)
  3527  		checkForRegisteredQSubInterest(t, sa, "B", accName, "bar", 1, 2*time.Second)
  3528  	}
  3529  
  3530  	// Resend msgs from A on foo, on all accounts. There will be no interest on this subject.
  3531  	produceMsgsFromA(t)
  3532  
  3533  	for i := 0; i < totalAccounts; i++ {
  3534  		accName := fmt.Sprintf("acc_%d", i)
  3535  		checkForSubjectNoInterest(t, gwc, accName, "foo", true, 2*time.Second)
  3536  		// Verify that we still have the queue interest registered
  3537  		checkForRegisteredQSubInterest(t, sa, "B", accName, "bar", 1, 2*time.Second)
  3538  	}
  3539  
  3540  	// Check accounts...
  3541  	checkFor(t, 2*time.Second, 15*time.Millisecond, func() error {
  3542  		for pollMode := 0; pollMode < 2; pollMode++ {
  3543  			g := pollGatewayz(t, sa, pollMode, gatewayzURL+"?accs=1", &GatewayzOptions{Accounts: true})
  3544  			og := g.OutboundGateways["B"]
  3545  			if og == nil {
  3546  				return fmt.Errorf("mode=%v - Expected outbound gateway to B, got none", pollMode)
  3547  			}
  3548  			if n := len(og.Accounts); n != totalAccounts {
  3549  				return fmt.Errorf("mode=%v - Expected to get all %d accounts, got %v", pollMode, totalAccounts, n)
  3550  			}
  3551  			// Now account details
  3552  			for _, acc := range og.Accounts {
  3553  				if acc.InterestMode != Optimistic.String() {
  3554  					return fmt.Errorf("mode=%v - Expected optimistic mode, got %q", pollMode, acc.InterestMode)
  3555  				}
  3556  				if acc.NoInterestCount != 1 {
  3557  					return fmt.Errorf("mode=%v - Expected 1 no-interest, got %v", pollMode, acc.NoInterestCount)
  3558  				}
  3559  				if acc.NumQueueSubscriptions != 1 || acc.TotalSubscriptions != 1 {
  3560  					return fmt.Errorf("mode=%v - Expected total subs to be 1, got %v - and num queue subs to be 1, got %v",
  3561  						pollMode, acc.TotalSubscriptions, acc.NumQueueSubscriptions)
  3562  				}
  3563  			}
  3564  		}
  3565  		return nil
  3566  	})
  3567  
  3568  	// Check inbound on server B
  3569  	checkFor(t, 2*time.Second, 15*time.Millisecond, func() error {
  3570  		for pollMode := 0; pollMode < 2; pollMode++ {
  3571  			// Ask for accounts list
  3572  			g := pollGatewayz(t, sb, pollMode, gwURLServerB+"?accs=1", &GatewayzOptions{Accounts: true})
  3573  			igs := g.InboundGateways["A"]
  3574  			if igs == nil {
  3575  				return fmt.Errorf("mode=%v - Expected inbound gateway to A, got none", pollMode)
  3576  			}
  3577  			if len(igs) != 1 {
  3578  				return fmt.Errorf("mode=%v - Expected single inbound, got %v", pollMode, len(igs))
  3579  			}
  3580  			ig := igs[0]
  3581  			if ig.Connection == nil {
  3582  				return fmt.Errorf("mode=%v - Expected inbound connection from A to be set, wat not", pollMode)
  3583  			}
  3584  			if ig.Connection.Name != sa.ID() {
  3585  				t.Fatalf("mode=%v - Expected inbound connection from A to have name %q, got %q", pollMode, sa.ID(), ig.Connection.Name)
  3586  			}
  3587  			if n := len(ig.Accounts); n != totalAccounts {
  3588  				return fmt.Errorf("mode=%v - Expected to get all %d accounts, got %v", pollMode, totalAccounts, n)
  3589  			}
  3590  			// Now account details
  3591  			for _, acc := range ig.Accounts {
  3592  				if acc.InterestMode != Optimistic.String() {
  3593  					return fmt.Errorf("mode=%v - Expected optimistic mode, got %q", pollMode, acc.InterestMode)
  3594  				}
  3595  				if acc.NoInterestCount != 1 {
  3596  					return fmt.Errorf("mode=%v - Expected 1 no-interest, got %v", pollMode, acc.NoInterestCount)
  3597  				}
  3598  				// For inbound gateway, NumQueueSubscriptions and TotalSubscriptions
  3599  				// are not relevant.
  3600  				if acc.NumQueueSubscriptions != 0 || acc.TotalSubscriptions != 0 {
  3601  					return fmt.Errorf("mode=%v - For inbound connection, expected num queue subs and total subs to be 0, got %v and %v",
  3602  						pollMode, acc.TotalSubscriptions, acc.NumQueueSubscriptions)
  3603  				}
  3604  			}
  3605  		}
  3606  		return nil
  3607  	})
  3608  
  3609  	// Make one of the account to switch to interest only
  3610  	nc, err := nats.Connect(fmt.Sprintf("nats://user_1:pwd@%s:%d", oa.Host, oa.Port))
  3611  	if err != nil {
  3612  		t.Fatalf("Error on connect: %v", err)
  3613  	}
  3614  	defer nc.Close()
  3615  	for i := 0; i < 1100; i++ {
  3616  		nc.Publish(fmt.Sprintf("foo.%d", i), []byte("hello"))
  3617  	}
  3618  	nc.Flush()
  3619  	nc.Close()
  3620  
  3621  	// Check that we can select single account
  3622  	checkFor(t, 2*time.Second, 15*time.Millisecond, func() error {
  3623  		for pollMode := 0; pollMode < 2; pollMode++ {
  3624  			g := pollGatewayz(t, sa, pollMode, gatewayzURL+"?gw_name=B&acc_name=acc_1", &GatewayzOptions{Name: "B", AccountName: "acc_1"})
  3625  			og := g.OutboundGateways["B"]
  3626  			if og == nil {
  3627  				return fmt.Errorf("mode=%v - Expected outbound gateway to B, got none", pollMode)
  3628  			}
  3629  			if n := len(og.Accounts); n != 1 {
  3630  				return fmt.Errorf("mode=%v - Expected to get 1 account, got %v", pollMode, n)
  3631  			}
  3632  			// Now account details
  3633  			acc := og.Accounts[0]
  3634  			if acc.InterestMode != InterestOnly.String() {
  3635  				return fmt.Errorf("mode=%v - Expected interest-only mode, got %q", pollMode, acc.InterestMode)
  3636  			}
  3637  			// Since we switched, this should be set to 0
  3638  			if acc.NoInterestCount != 0 {
  3639  				return fmt.Errorf("mode=%v - Expected 0 no-interest, got %v", pollMode, acc.NoInterestCount)
  3640  			}
  3641  			// We have created 3 subs on that account on B, and 1 queue sub.
  3642  			// So total should be 4 and 1 for queue sub.
  3643  			if acc.NumQueueSubscriptions != 1 {
  3644  				return fmt.Errorf("mode=%v - Expected num queue subs to be 1, got %v",
  3645  					pollMode, acc.NumQueueSubscriptions)
  3646  			}
  3647  			if acc.TotalSubscriptions != 4 {
  3648  				return fmt.Errorf("mode=%v - Expected total subs to be 4, got %v",
  3649  					pollMode, acc.TotalSubscriptions)
  3650  			}
  3651  		}
  3652  		return nil
  3653  	})
  3654  
  3655  	// Check inbound on B now...
  3656  	checkFor(t, 2*time.Second, 15*time.Millisecond, func() error {
  3657  		for pollMode := 0; pollMode < 2; pollMode++ {
  3658  			g := pollGatewayz(t, sb, pollMode, gwURLServerB+"?gw_name=A&acc_name=acc_1", &GatewayzOptions{Name: "A", AccountName: "acc_1"})
  3659  			igs := g.InboundGateways["A"]
  3660  			if igs == nil {
  3661  				return fmt.Errorf("mode=%v - Expected inbound gateway from A, got none", pollMode)
  3662  			}
  3663  			if len(igs) != 1 {
  3664  				return fmt.Errorf("mode=%v - Expected single inbound, got %v", pollMode, len(igs))
  3665  			}
  3666  			ig := igs[0]
  3667  			if n := len(ig.Accounts); n != 1 {
  3668  				return fmt.Errorf("mode=%v - Expected to get 1 account, got %v", pollMode, n)
  3669  			}
  3670  			// Now account details
  3671  			acc := ig.Accounts[0]
  3672  			if acc.InterestMode != InterestOnly.String() {
  3673  				return fmt.Errorf("mode=%v - Expected interest-only mode, got %q", pollMode, acc.InterestMode)
  3674  			}
  3675  			if acc.InterestMode != InterestOnly.String() {
  3676  				return fmt.Errorf("Should be in %q mode, got %q", InterestOnly.String(), acc.InterestMode)
  3677  			}
  3678  			// Since we switched, this should be set to 0
  3679  			if acc.NoInterestCount != 0 {
  3680  				return fmt.Errorf("mode=%v - Expected 0 no-interest, got %v", pollMode, acc.NoInterestCount)
  3681  			}
  3682  			// Again, for inbound, these should be always 0.
  3683  			if acc.NumQueueSubscriptions != 0 || acc.TotalSubscriptions != 0 {
  3684  				return fmt.Errorf("mode=%v - For inbound connection, expected num queue subs and total subs to be 0, got %v and %v",
  3685  					pollMode, acc.TotalSubscriptions, acc.NumQueueSubscriptions)
  3686  			}
  3687  		}
  3688  		return nil
  3689  	})
  3690  }
  3691  
  3692  func TestMonitorRouteRTT(t *testing.T) {
  3693  	// Do not change default PingInterval and expect RTT to still be reported
  3694  
  3695  	ob := DefaultOptions()
  3696  	sb := RunServer(ob)
  3697  	defer sb.Shutdown()
  3698  
  3699  	oa := DefaultOptions()
  3700  	oa.Routes = RoutesFromStr(fmt.Sprintf("nats://%s:%d", ob.Cluster.Host, ob.Cluster.Port))
  3701  	sa := RunServer(oa)
  3702  	defer sa.Shutdown()
  3703  
  3704  	checkClusterFormed(t, sa, sb)
  3705  
  3706  	checkRouteInfo := func(t *testing.T, s *Server) {
  3707  		t.Helper()
  3708  		routezURL := fmt.Sprintf("http://127.0.0.1:%d/routez", s.MonitorAddr().Port)
  3709  		for pollMode := 0; pollMode < 2; pollMode++ {
  3710  			checkFor(t, 2*firstPingInterval, 15*time.Millisecond, func() error {
  3711  				rz := pollRoutez(t, s, pollMode, routezURL, nil)
  3712  				// Pool size + 1 for system account
  3713  				if len(rz.Routes) != DEFAULT_ROUTE_POOL_SIZE+1 {
  3714  					return fmt.Errorf("Expected %d route, got %v", DEFAULT_ROUTE_POOL_SIZE+1, len(rz.Routes))
  3715  				}
  3716  				for _, ri := range rz.Routes {
  3717  					if ri.RTT == _EMPTY_ {
  3718  						return fmt.Errorf("Route's RTT not reported")
  3719  					}
  3720  				}
  3721  				return nil
  3722  			})
  3723  		}
  3724  	}
  3725  	checkRouteInfo(t, sa)
  3726  	checkRouteInfo(t, sb)
  3727  }
  3728  
  3729  func pollLeafz(t *testing.T, s *Server, mode int, url string, opts *LeafzOptions) *Leafz {
  3730  	t.Helper()
  3731  	if mode == 0 {
  3732  		l := &Leafz{}
  3733  		body := readBody(t, url)
  3734  		if err := json.Unmarshal(body, l); err != nil {
  3735  			t.Fatalf("Got an error unmarshalling the body: %v\n", err)
  3736  		}
  3737  		return l
  3738  	}
  3739  	l, err := s.Leafz(opts)
  3740  	if err != nil {
  3741  		t.Fatalf("Error on Leafz: %v", err)
  3742  	}
  3743  	return l
  3744  }
  3745  
  3746  func TestMonitorOpJWT(t *testing.T) {
  3747  	content := `
  3748  	listen: "127.0.0.1:-1"
  3749  	http: "127.0.0.1:-1"
  3750  	operator = "../test/configs/nkeys/op.jwt"
  3751  	resolver = MEMORY
  3752  	`
  3753  	conf := createConfFile(t, []byte(content))
  3754  	sa, _ := RunServerWithConfig(conf)
  3755  	defer sa.Shutdown()
  3756  
  3757  	theJWT, err := os.ReadFile("../test/configs/nkeys/op.jwt")
  3758  	require_NoError(t, err)
  3759  	theJWT = []byte(strings.Split(string(theJWT), "\n")[1])
  3760  	claim, err := jwt.DecodeOperatorClaims(string(theJWT))
  3761  	require_NoError(t, err)
  3762  
  3763  	pollURL := fmt.Sprintf("http://127.0.0.1:%d/varz", sa.MonitorAddr().Port)
  3764  	for pollMode := 1; pollMode < 2; pollMode++ {
  3765  		l := pollVarz(t, sa, pollMode, pollURL, nil)
  3766  
  3767  		if len(l.TrustedOperatorsJwt) != 1 {
  3768  			t.Fatalf("Expected one operator jwt")
  3769  		}
  3770  		if len(l.TrustedOperatorsClaim) != 1 {
  3771  			t.Fatalf("Expected one operator claim")
  3772  		}
  3773  		if l.TrustedOperatorsJwt[0] != string(theJWT) {
  3774  			t.Fatalf("Expected operator to be identical to configuration")
  3775  		}
  3776  		if !reflect.DeepEqual(l.TrustedOperatorsClaim[0], claim) {
  3777  			t.Fatal("claims need to be equal")
  3778  		}
  3779  	}
  3780  }
  3781  
  3782  func TestMonitorLeafz(t *testing.T) {
  3783  	content := `
  3784  	server_name: "hub"
  3785  	listen: "127.0.0.1:-1"
  3786  	http: "127.0.0.1:-1"
  3787  	operator = "../test/configs/nkeys/op.jwt"
  3788  	resolver = MEMORY
  3789  	ping_interval = 1
  3790  	leafnodes {
  3791  		listen: "127.0.0.1:-1"
  3792  	}
  3793  	`
  3794  	conf := createConfFile(t, []byte(content))
  3795  	sb, ob := RunServerWithConfig(conf)
  3796  	defer sb.Shutdown()
  3797  
  3798  	createAcc := func(t *testing.T) (*Account, string) {
  3799  		t.Helper()
  3800  		acc, akp := createAccount(sb)
  3801  		kp, _ := nkeys.CreateUser()
  3802  		pub, _ := kp.PublicKey()
  3803  		nuc := jwt.NewUserClaims(pub)
  3804  		ujwt, err := nuc.Encode(akp)
  3805  		if err != nil {
  3806  			t.Fatalf("Error generating user JWT: %v", err)
  3807  		}
  3808  		seed, _ := kp.Seed()
  3809  		creds := genCredsFile(t, ujwt, seed)
  3810  		return acc, creds
  3811  	}
  3812  	acc1, mycreds1 := createAcc(t)
  3813  	acc2, mycreds2 := createAcc(t)
  3814  	leafName := "my-leaf-node"
  3815  
  3816  	content = `
  3817  		port: -1
  3818  		http: "127.0.0.1:-1"
  3819  		ping_interval = 1
  3820  		server_name: %s
  3821  		accounts {
  3822  			%s {
  3823  				users [
  3824  					{user: user1, password: pwd}
  3825  				]
  3826  			}
  3827  			%s {
  3828  				users [
  3829  					{user: user2, password: pwd}
  3830  				]
  3831  			}
  3832  		}
  3833  		leafnodes {
  3834  			remotes = [
  3835  				{
  3836  					account: "%s"
  3837  					url: nats-leaf://127.0.0.1:%d
  3838  					credentials: '%s'
  3839  				}
  3840  				{
  3841  					account: "%s"
  3842  					url: nats-leaf://127.0.0.1:%d
  3843  					credentials: '%s'
  3844  				}
  3845  			]
  3846  		}
  3847  		`
  3848  	config := fmt.Sprintf(content,
  3849  		leafName,
  3850  		acc1.Name, acc2.Name,
  3851  		acc1.Name, ob.LeafNode.Port, mycreds1,
  3852  		acc2.Name, ob.LeafNode.Port, mycreds2)
  3853  	conf = createConfFile(t, []byte(config))
  3854  	sa, oa := RunServerWithConfig(conf)
  3855  	defer sa.Shutdown()
  3856  
  3857  	checkFor(t, time.Second, 15*time.Millisecond, func() error {
  3858  		if n := sa.NumLeafNodes(); n != 2 {
  3859  			return fmt.Errorf("Expected 2 leaf connections, got %v", n)
  3860  		}
  3861  		return nil
  3862  	})
  3863  
  3864  	// Wait for initial RTT to be computed
  3865  	time.Sleep(firstPingInterval + 500*time.Millisecond)
  3866  
  3867  	ch := make(chan bool, 1)
  3868  	nc1B := natsConnect(t, fmt.Sprintf("nats://127.0.0.1:%d", ob.Port), nats.UserCredentials(mycreds1))
  3869  	defer nc1B.Close()
  3870  	natsSub(t, nc1B, "foo", func(_ *nats.Msg) { ch <- true })
  3871  	natsSub(t, nc1B, "bar", func(_ *nats.Msg) {})
  3872  	natsFlush(t, nc1B)
  3873  
  3874  	nc2B := natsConnect(t, fmt.Sprintf("nats://127.0.0.1:%d", ob.Port), nats.UserCredentials(mycreds2))
  3875  	defer nc2B.Close()
  3876  	natsSub(t, nc2B, "bar", func(_ *nats.Msg) { ch <- true })
  3877  	natsSub(t, nc2B, "foo", func(_ *nats.Msg) {})
  3878  	natsFlush(t, nc2B)
  3879  
  3880  	nc1A := natsConnect(t, fmt.Sprintf("nats://user1:pwd@127.0.0.1:%d", oa.Port))
  3881  	defer nc1A.Close()
  3882  	natsPub(t, nc1A, "foo", []byte("hello"))
  3883  	natsFlush(t, nc1A)
  3884  
  3885  	waitCh(t, ch, "Did not get the message")
  3886  
  3887  	nc2A := natsConnect(t, fmt.Sprintf("nats://user2:pwd@127.0.0.1:%d", oa.Port))
  3888  	defer nc2A.Close()
  3889  	natsPub(t, nc2A, "bar", []byte("hello"))
  3890  	natsPub(t, nc2A, "bar", []byte("hello"))
  3891  	natsFlush(t, nc2A)
  3892  
  3893  	waitCh(t, ch, "Did not get the message")
  3894  	waitCh(t, ch, "Did not get the message")
  3895  
  3896  	// Let's poll server A
  3897  	pollURL := fmt.Sprintf("http://127.0.0.1:%d/leafz?subs=1", sa.MonitorAddr().Port)
  3898  	for pollMode := 1; pollMode < 2; pollMode++ {
  3899  		l := pollLeafz(t, sa, pollMode, pollURL, &LeafzOptions{Subscriptions: true})
  3900  		if l.ID != sa.ID() {
  3901  			t.Fatalf("Expected ID to be %q, got %q", sa.ID(), l.ID)
  3902  		}
  3903  		if l.Now.IsZero() {
  3904  			t.Fatalf("Expected Now to be set, was not")
  3905  		}
  3906  		if l.NumLeafs != 2 {
  3907  			t.Fatalf("Expected NumLeafs to be 2, got %v", l.NumLeafs)
  3908  		}
  3909  		if len(l.Leafs) != 2 {
  3910  			t.Fatalf("Expected array to be len 2, got %v", len(l.Leafs))
  3911  		}
  3912  		for _, ln := range l.Leafs {
  3913  			if ln.Account == acc1.Name {
  3914  				if ln.OutMsgs != 1 || ln.OutBytes == 0 || ln.InMsgs != 0 || ln.InBytes != 0 {
  3915  					t.Fatalf("Expected 1 OutMsgs/Bytes and 0 InMsgs/Bytes, got %+v", ln)
  3916  				}
  3917  			} else if ln.Account == acc2.Name {
  3918  				if ln.OutMsgs != 2 || ln.OutBytes == 0 || ln.InMsgs != 0 || ln.InBytes != 0 {
  3919  					t.Fatalf("Expected 2 OutMsgs/Bytes and 0 InMsgs/Bytes, got %+v", ln)
  3920  				}
  3921  			} else {
  3922  				t.Fatalf("Expected account to be %q or %q, got %q", acc1.Name, acc2.Name, ln.Account)
  3923  			}
  3924  			if ln.Name != "hub" {
  3925  				t.Fatalf("Expected name to be %q, got %q", "hub", ln.Name)
  3926  			}
  3927  			if !ln.IsSpoke {
  3928  				t.Fatal("Expected leafnode connection to be spoke")
  3929  			}
  3930  			if ln.RTT == "" {
  3931  				t.Fatalf("RTT not tracked?")
  3932  			}
  3933  			if ln.NumSubs != 3 {
  3934  				t.Fatalf("Expected 3 subs, got %v", ln.NumSubs)
  3935  			}
  3936  			if len(ln.Subs) != 3 {
  3937  				t.Fatalf("Expected subs to be returned, got %v", len(ln.Subs))
  3938  			}
  3939  			var foundFoo bool
  3940  			var foundBar bool
  3941  			for _, sub := range ln.Subs {
  3942  				if sub == "foo" {
  3943  					foundFoo = true
  3944  				} else if sub == "bar" {
  3945  					foundBar = true
  3946  				}
  3947  			}
  3948  			if !foundFoo {
  3949  				t.Fatal("Did not find subject foo")
  3950  			}
  3951  			if !foundBar {
  3952  				t.Fatal("Did not find subject bar")
  3953  			}
  3954  		}
  3955  	}
  3956  	// Make sure that if we don't ask for subs, we don't get them
  3957  	pollURL = fmt.Sprintf("http://127.0.0.1:%d/leafz", sa.MonitorAddr().Port)
  3958  	for pollMode := 1; pollMode < 2; pollMode++ {
  3959  		l := pollLeafz(t, sa, pollMode, pollURL, nil)
  3960  		for _, ln := range l.Leafs {
  3961  			if ln.NumSubs != 3 {
  3962  				t.Fatalf("Number of subs should be 3, got %v", ln.NumSubs)
  3963  			}
  3964  			if len(ln.Subs) != 0 {
  3965  				t.Fatalf("Subs should not have been returned, got %v", ln.Subs)
  3966  			}
  3967  		}
  3968  	}
  3969  	// Make sure that we can request per account - existing account
  3970  	pollURL = fmt.Sprintf("http://127.0.0.1:%d/leafz?acc=%s", sa.MonitorAddr().Port, acc1.Name)
  3971  	for pollMode := 1; pollMode < 2; pollMode++ {
  3972  		l := pollLeafz(t, sa, pollMode, pollURL, &LeafzOptions{Account: acc1.Name})
  3973  		for _, ln := range l.Leafs {
  3974  			if ln.Account != acc1.Name {
  3975  				t.Fatalf("Expected leaf node to be from account %s, got: %v", acc1.Name, ln)
  3976  			}
  3977  		}
  3978  		if len(l.Leafs) != 1 {
  3979  			t.Fatalf("Expected only two leaf node for this account, got: %v", len(l.Leafs))
  3980  		}
  3981  	}
  3982  	// Make sure that we can request per account - non existing account
  3983  	pollURL = fmt.Sprintf("http://127.0.0.1:%d/leafz?acc=%s", sa.MonitorAddr().Port, "DOESNOTEXIST")
  3984  	for pollMode := 1; pollMode < 2; pollMode++ {
  3985  		l := pollLeafz(t, sa, pollMode, pollURL, &LeafzOptions{Account: "DOESNOTEXIST"})
  3986  		if len(l.Leafs) != 0 {
  3987  			t.Fatalf("Expected no leaf node for this account, got: %v", len(l.Leafs))
  3988  		}
  3989  	}
  3990  	// Now polling server B.
  3991  	pollURL = fmt.Sprintf("http://127.0.0.1:%d/leafz?subs=1", sb.MonitorAddr().Port)
  3992  	for pollMode := 1; pollMode < 2; pollMode++ {
  3993  		l := pollLeafz(t, sb, pollMode, pollURL, &LeafzOptions{Subscriptions: true})
  3994  		if l.ID != sb.ID() {
  3995  			t.Fatalf("Expected ID to be %q, got %q", sb.ID(), l.ID)
  3996  		}
  3997  		if l.Now.IsZero() {
  3998  			t.Fatalf("Expected Now to be set, was not")
  3999  		}
  4000  		if l.NumLeafs != 2 {
  4001  			t.Fatalf("Expected NumLeafs to be 1, got %v", l.NumLeafs)
  4002  		}
  4003  		if len(l.Leafs) != 2 {
  4004  			t.Fatalf("Expected array to be len 2, got %v", len(l.Leafs))
  4005  		}
  4006  		for _, ln := range l.Leafs {
  4007  			if ln.Account == acc1.Name {
  4008  				if ln.OutMsgs != 0 || ln.OutBytes != 0 || ln.InMsgs != 1 || ln.InBytes == 0 {
  4009  					t.Fatalf("Expected 1 InMsgs/Bytes and 0 OutMsgs/Bytes, got %+v", ln)
  4010  				}
  4011  			} else if ln.Account == acc2.Name {
  4012  				if ln.OutMsgs != 0 || ln.OutBytes != 0 || ln.InMsgs != 2 || ln.InBytes == 0 {
  4013  					t.Fatalf("Expected 2 InMsgs/Bytes and 0 OutMsgs/Bytes, got %+v", ln)
  4014  				}
  4015  			} else {
  4016  				t.Fatalf("Expected account to be %q or %q, got %q", acc1.Name, acc2.Name, ln.Account)
  4017  			}
  4018  			if ln.Name != leafName {
  4019  				t.Fatalf("Expected name to be %q, got %q", leafName, ln.Name)
  4020  			}
  4021  			if ln.IsSpoke {
  4022  				t.Fatal("Expected leafnode connection to be hub")
  4023  			}
  4024  			if ln.RTT == "" {
  4025  				t.Fatalf("RTT not tracked?")
  4026  			}
  4027  			// LDS should be only one.
  4028  			if ln.NumSubs != 5 || len(ln.Subs) != 5 {
  4029  				t.Fatalf("Expected 5 subs, got %v (%v)", ln.NumSubs, ln.Subs)
  4030  			}
  4031  		}
  4032  	}
  4033  }
  4034  
  4035  func TestMonitorAccountz(t *testing.T) {
  4036  	s := RunServer(DefaultMonitorOptions())
  4037  	defer s.Shutdown()
  4038  	body := string(readBody(t, fmt.Sprintf("http://127.0.0.1:%d%s", s.MonitorAddr().Port, AccountzPath)))
  4039  	require_Contains(t, body, `$G`)
  4040  	require_Contains(t, body, `$SYS`)
  4041  	require_Contains(t, body, `"accounts": [`)
  4042  	require_Contains(t, body, `"system_account": "$SYS"`)
  4043  
  4044  	body = string(readBody(t, fmt.Sprintf("http://127.0.0.1:%d%s?acc=$SYS", s.MonitorAddr().Port, AccountzPath)))
  4045  	require_Contains(t, body, `"account_detail": {`)
  4046  	require_Contains(t, body, `"account_name": "$SYS",`)
  4047  	require_Contains(t, body, `"subscriptions": 50,`)
  4048  	require_Contains(t, body, `"is_system": true,`)
  4049  	require_Contains(t, body, `"system_account": "$SYS"`)
  4050  
  4051  	body = string(readBody(t, fmt.Sprintf("http://127.0.0.1:%d%s?unused=1", s.MonitorAddr().Port, AccountStatzPath)))
  4052  	require_Contains(t, body, `"acc": "$G"`)
  4053  	require_Contains(t, body, `"name": "$G"`)
  4054  	require_Contains(t, body, `"acc": "$SYS"`)
  4055  	require_Contains(t, body, `"name": "$SYS"`)
  4056  	require_Contains(t, body, `"sent": {`)
  4057  	require_Contains(t, body, `"received": {`)
  4058  	require_Contains(t, body, `"total_conns": 0,`)
  4059  	require_Contains(t, body, `"leafnodes": 0,`)
  4060  }
  4061  
  4062  func TestMonitorAccountzOperatorMode(t *testing.T) {
  4063  	_, sysPub := createKey(t)
  4064  	sysClaim := jwt.NewAccountClaims(sysPub)
  4065  	sysClaim.Name = "SYS"
  4066  	sysJwt := encodeClaim(t, sysClaim, sysPub)
  4067  
  4068  	accKp, accPub := createKey(t)
  4069  	accClaim := jwt.NewAccountClaims(accPub)
  4070  	accClaim.Name = "APP"
  4071  	accJwt := encodeClaim(t, accClaim, accPub)
  4072  
  4073  	conf := createConfFile(t, []byte(fmt.Sprintf(`
  4074  		listen: 127.0.0.1:-1
  4075  		http: 127.0.0.1:-1
  4076  		operator = %s
  4077  		resolver = MEMORY
  4078  		system_account: %s
  4079  		resolver_preload = {
  4080  			%s : %s
  4081  			%s : %s
  4082  		}
  4083  	`, ojwt, sysPub, accPub, accJwt, sysPub, sysJwt)))
  4084  
  4085  	s, _ := RunServerWithConfig(conf)
  4086  	defer s.Shutdown()
  4087  
  4088  	createUser := func() (string, string) {
  4089  		ukp, _ := nkeys.CreateUser()
  4090  		seed, _ := ukp.Seed()
  4091  		upub, _ := ukp.PublicKey()
  4092  		uclaim := newJWTTestUserClaims()
  4093  		uclaim.Subject = upub
  4094  		ujwt, err := uclaim.Encode(accKp)
  4095  		require_NoError(t, err)
  4096  		return upub, genCredsFile(t, ujwt, seed)
  4097  	}
  4098  
  4099  	_, aCreds := createUser()
  4100  
  4101  	nc, err := nats.Connect(s.ClientURL(), nats.UserCredentials(aCreds))
  4102  	require_NoError(t, err)
  4103  	defer nc.Close()
  4104  
  4105  	body := string(readBody(t, fmt.Sprintf("http://127.0.0.1:%d%s", s.MonitorAddr().Port, AccountzPath)))
  4106  	require_Contains(t, body, accPub)
  4107  	require_Contains(t, body, sysPub)
  4108  	require_Contains(t, body, `"accounts": [`)
  4109  	require_Contains(t, body, fmt.Sprintf(`"system_account": "%s"`, sysPub))
  4110  
  4111  	body = string(readBody(t, fmt.Sprintf("http://127.0.0.1:%d%s?acc=%s", s.MonitorAddr().Port, AccountzPath, sysPub)))
  4112  	require_Contains(t, body, `"account_detail": {`)
  4113  	require_Contains(t, body, fmt.Sprintf(`"account_name": "%s",`, sysPub))
  4114  	require_Contains(t, body, `"subscriptions": 50,`)
  4115  	require_Contains(t, body, `"is_system": true,`)
  4116  	require_Contains(t, body, fmt.Sprintf(`"system_account": "%s"`, sysPub))
  4117  
  4118  	// TODO: understand why the APP account did not show up in the accountz detail
  4119  	// even though unused is set. It required a connection to be made to show up.
  4120  	body = string(readBody(t, fmt.Sprintf("http://127.0.0.1:%d%s?unused=1", s.MonitorAddr().Port, AccountStatzPath)))
  4121  	require_Contains(t, body, fmt.Sprintf(`"acc": "%s"`, accPub))
  4122  	require_Contains(t, body, fmt.Sprintf(`"name": "%s"`, accClaim.Name))
  4123  	require_Contains(t, body, fmt.Sprintf(`"acc": "%s"`, sysPub))
  4124  	require_Contains(t, body, fmt.Sprintf(`"name": "%s"`, sysClaim.Name))
  4125  	require_Contains(t, body, `"sent": {`)
  4126  	require_Contains(t, body, `"received": {`)
  4127  	require_Contains(t, body, `"total_conns": 0,`)
  4128  	require_Contains(t, body, `"leafnodes": 0,`)
  4129  }
  4130  
  4131  func TestMonitorAuthorizedUsers(t *testing.T) {
  4132  	kp, _ := nkeys.FromSeed(seed)
  4133  	usrNKey, _ := kp.PublicKey()
  4134  	opts := DefaultMonitorOptions()
  4135  	opts.Nkeys = []*NkeyUser{{Nkey: string(usrNKey)}}
  4136  	opts.Users = []*User{{Username: "user", Password: "pwd"}}
  4137  	s := RunServer(opts)
  4138  	defer s.Shutdown()
  4139  
  4140  	checkAuthUser := func(expected string) {
  4141  		t.Helper()
  4142  		resetPreviousHTTPConnections()
  4143  		url := fmt.Sprintf("http://127.0.0.1:%d/connz?auth=true", s.MonitorAddr().Port)
  4144  		for mode := 0; mode < 2; mode++ {
  4145  			connz := pollConz(t, s, mode, url, &ConnzOptions{Username: true})
  4146  			if l := len(connz.Conns); l != 1 {
  4147  				t.Fatalf("Expected 1, got %v", l)
  4148  			}
  4149  			conn := connz.Conns[0]
  4150  			au := conn.AuthorizedUser
  4151  			if au == _EMPTY_ {
  4152  				t.Fatal("AuthorizedUser is empty!")
  4153  			}
  4154  			if au != expected {
  4155  				t.Fatalf("Expected %q, got %q", expected, au)
  4156  			}
  4157  		}
  4158  	}
  4159  
  4160  	c := natsConnect(t, fmt.Sprintf("nats://user:pwd@127.0.0.1:%d", opts.Port))
  4161  	defer c.Close()
  4162  	checkAuthUser("user")
  4163  	c.Close()
  4164  
  4165  	c = natsConnect(t, fmt.Sprintf("nats://127.0.0.1:%d", opts.Port),
  4166  		nats.Nkey(usrNKey, func(nonce []byte) ([]byte, error) {
  4167  			return kp.Sign(nonce)
  4168  		}))
  4169  	defer c.Close()
  4170  	// we should get the user's NKey
  4171  	checkAuthUser(usrNKey)
  4172  	c.Close()
  4173  
  4174  	s.Shutdown()
  4175  	opts = DefaultMonitorOptions()
  4176  	opts.Authorization = "sometoken"
  4177  	s = RunServer(opts)
  4178  	defer s.Shutdown()
  4179  
  4180  	c = natsConnect(t, fmt.Sprintf("nats://127.0.0.1:%d", opts.Port),
  4181  		nats.Token("sometoken"))
  4182  	defer c.Close()
  4183  	// We should get the token specified by the user
  4184  	checkAuthUser("sometoken")
  4185  	c.Close()
  4186  	s.Shutdown()
  4187  
  4188  	opts = DefaultMonitorOptions()
  4189  	// User an operator seed
  4190  	kp, _ = nkeys.FromSeed(oSeed)
  4191  	pub, _ := kp.PublicKey()
  4192  	opts.TrustedKeys = []string{pub}
  4193  	s = RunServer(opts)
  4194  	defer s.Shutdown()
  4195  
  4196  	akp, _ := nkeys.CreateAccount()
  4197  	apub, _ := akp.PublicKey()
  4198  	nac := jwt.NewAccountClaims(apub)
  4199  	ajwt, err := nac.Encode(oKp)
  4200  	if err != nil {
  4201  		t.Fatalf("Error generating account JWT: %v", err)
  4202  	}
  4203  
  4204  	nkp, _ := nkeys.CreateUser()
  4205  	upub, _ := nkp.PublicKey()
  4206  	nuc := jwt.NewUserClaims(upub)
  4207  	jwt, err := nuc.Encode(akp)
  4208  	if err != nil {
  4209  		t.Fatalf("Error generating user JWT: %v", err)
  4210  	}
  4211  
  4212  	buildMemAccResolver(s)
  4213  	addAccountToMemResolver(s, apub, ajwt)
  4214  
  4215  	c = natsConnect(t, fmt.Sprintf("nats://127.0.0.1:%d", opts.Port),
  4216  		nats.UserJWT(
  4217  			func() (string, error) { return jwt, nil },
  4218  			func(nonce []byte) ([]byte, error) { return nkp.Sign(nonce) }))
  4219  	defer c.Close()
  4220  	// we should get the user's pubkey
  4221  	checkAuthUser(upub)
  4222  }
  4223  
  4224  // Helper function to check that a JS cluster is formed
  4225  func checkForJSClusterUp(t *testing.T, servers ...*Server) {
  4226  	t.Helper()
  4227  	// We will use the other JetStream helpers here.
  4228  	c := &cluster{t: t, servers: servers}
  4229  	c.checkClusterFormed()
  4230  	c.waitOnClusterReady()
  4231  }
  4232  
  4233  func TestMonitorJszNonJszServer(t *testing.T) {
  4234  	srv := RunServer(DefaultOptions())
  4235  	defer srv.Shutdown()
  4236  
  4237  	if !srv.ReadyForConnections(5 * time.Second) {
  4238  		t.Fatalf("server did not become ready")
  4239  	}
  4240  
  4241  	jsi, err := srv.Jsz(&JSzOptions{})
  4242  	if err != nil {
  4243  		t.Fatalf("jsi failed: %v", err)
  4244  	}
  4245  	if jsi.ID != srv.ID() {
  4246  		t.Fatalf("did not receive valid info")
  4247  	}
  4248  
  4249  	jsi, err = srv.Jsz(&JSzOptions{LeaderOnly: true})
  4250  	if !errors.Is(err, errSkipZreq) {
  4251  		t.Fatalf("expected a skip z req error: %v", err)
  4252  	}
  4253  	if jsi != nil {
  4254  		t.Fatalf("expected no jsi: %v", jsi)
  4255  	}
  4256  }
  4257  
  4258  func TestMonitorJsz(t *testing.T) {
  4259  	readJsInfo := func(url string) *JSInfo {
  4260  		t.Helper()
  4261  		body := readBody(t, url)
  4262  		info := &JSInfo{}
  4263  		err := json.Unmarshal(body, info)
  4264  		require_NoError(t, err)
  4265  		return info
  4266  	}
  4267  	srvs := []*Server{}
  4268  	for _, test := range []struct {
  4269  		port   int
  4270  		mport  int
  4271  		cport  int
  4272  		routed int
  4273  	}{
  4274  		{7500, 7501, 7502, 5502},
  4275  		{5500, 5501, 5502, 7502},
  4276  	} {
  4277  		tmpDir := t.TempDir()
  4278  		cf := createConfFile(t, []byte(fmt.Sprintf(`
  4279  		listen: 127.0.0.1:%d
  4280  		http: 127.0.0.1:%d
  4281  		system_account: SYS
  4282  		accounts {
  4283  			SYS {
  4284  				users [{user: sys, password: pwd}]
  4285  			}
  4286  			ACC {
  4287  				users [{user: usr, password: pwd}]
  4288  				// In clustered mode, these reservations will not impact any one server.
  4289  				jetstream: {max_store: 4Mb, max_memory: 5Mb}
  4290  			}
  4291  			BCC_TO_HAVE_ONE_EXTRA {
  4292  				users [{user: usr2, password: pwd}]
  4293  				jetstream: enabled
  4294  			}
  4295  		}
  4296  		jetstream: {
  4297  			max_mem_store: 10Mb
  4298  			max_file_store: 10Mb
  4299  			store_dir: '%s'
  4300  			unique_tag: az
  4301  		}
  4302  		cluster {
  4303  			name: cluster_name
  4304  			listen: 127.0.0.1:%d
  4305  			routes: [nats-route://127.0.0.1:%d]
  4306  		}
  4307  		server_name: server_%d
  4308  		server_tags: [ "az:%d" ] `, test.port, test.mport, tmpDir, test.cport, test.routed, test.port, test.port)))
  4309  
  4310  		s, _ := RunServerWithConfig(cf)
  4311  		defer s.Shutdown()
  4312  		srvs = append(srvs, s)
  4313  	}
  4314  	checkClusterFormed(t, srvs...)
  4315  	checkForJSClusterUp(t, srvs...)
  4316  
  4317  	nc := natsConnect(t, "nats://usr:pwd@127.0.0.1:7500")
  4318  	defer nc.Close()
  4319  	js, err := nc.JetStream(nats.MaxWait(5 * time.Second))
  4320  	require_NoError(t, err)
  4321  	_, err = js.AddStream(&nats.StreamConfig{
  4322  		Name:     "my-stream-replicated",
  4323  		Subjects: []string{"foo", "bar"},
  4324  		Replicas: 2,
  4325  	})
  4326  	require_NoError(t, err)
  4327  	_, err = js.AddStream(&nats.StreamConfig{
  4328  		Name:     "my-stream-non-replicated",
  4329  		Subjects: []string{"baz"},
  4330  		Replicas: 1,
  4331  	})
  4332  	require_NoError(t, err)
  4333  	_, err = js.AddStream(&nats.StreamConfig{
  4334  		Name:     "my-stream-mirror",
  4335  		Replicas: 2,
  4336  		Mirror: &nats.StreamSource{
  4337  			Name: "my-stream-replicated",
  4338  		},
  4339  	})
  4340  	require_NoError(t, err)
  4341  	_, err = js.AddConsumer("my-stream-replicated", &nats.ConsumerConfig{
  4342  		Durable:   "my-consumer-replicated",
  4343  		AckPolicy: nats.AckExplicitPolicy,
  4344  	})
  4345  	require_NoError(t, err)
  4346  	_, err = js.AddConsumer("my-stream-non-replicated", &nats.ConsumerConfig{
  4347  		Durable:   "my-consumer-non-replicated",
  4348  		AckPolicy: nats.AckExplicitPolicy,
  4349  	})
  4350  	require_NoError(t, err)
  4351  	_, err = js.AddConsumer("my-stream-mirror", &nats.ConsumerConfig{
  4352  		Durable:   "my-consumer-mirror",
  4353  		AckPolicy: nats.AckExplicitPolicy,
  4354  	})
  4355  	require_NoError(t, err)
  4356  	nc.Flush()
  4357  	_, err = js.Publish("foo", nil)
  4358  	require_NoError(t, err)
  4359  	// Wait for mirror replication
  4360  	time.Sleep(200 * time.Millisecond)
  4361  
  4362  	monUrl1 := fmt.Sprintf("http://127.0.0.1:%d/jsz", 7501)
  4363  	monUrl2 := fmt.Sprintf("http://127.0.0.1:%d/jsz", 5501)
  4364  
  4365  	t.Run("default", func(t *testing.T) {
  4366  		for _, url := range []string{monUrl1, monUrl2} {
  4367  			info := readJsInfo(url)
  4368  			if len(info.AccountDetails) != 0 {
  4369  				t.Fatalf("expected no account to be returned by %s but got %v", url, info)
  4370  			}
  4371  			if info.Streams == 0 {
  4372  				t.Fatalf("expected stream count to be 3 but got %d", info.Streams)
  4373  			}
  4374  			if info.Consumers == 0 {
  4375  				t.Fatalf("expected consumer count to be 3 but got %d", info.Consumers)
  4376  			}
  4377  			if info.Messages != 2 {
  4378  				t.Fatalf("expected two message but got %d", info.Messages)
  4379  			}
  4380  		}
  4381  	})
  4382  	t.Run("accounts", func(t *testing.T) {
  4383  		for _, url := range []string{monUrl1, monUrl2} {
  4384  			info := readJsInfo(url + "?accounts=true")
  4385  			if len(info.AccountDetails) != 2 {
  4386  				t.Fatalf("expected both accounts to be returned by %s but got %v", url, info)
  4387  			}
  4388  		}
  4389  	})
  4390  	t.Run("accounts reserved metrics", func(t *testing.T) {
  4391  		for _, url := range []string{monUrl1, monUrl2} {
  4392  			info := readJsInfo(url + "?accounts=true&acc=ACC")
  4393  			if len(info.AccountDetails) != 1 {
  4394  				t.Fatalf("expected single account")
  4395  			}
  4396  			acc := info.AccountDetails[0]
  4397  			got := int(acc.ReservedMemory)
  4398  			expected := 5242880
  4399  			if got != expected {
  4400  				t.Errorf("Expected: %v, got: %v", expected, got)
  4401  			}
  4402  			got = int(acc.ReservedStore)
  4403  			expected = 4194304
  4404  			if got != expected {
  4405  				t.Errorf("Expected: %v, got: %v", expected, got)
  4406  			}
  4407  
  4408  			info = readJsInfo(url + "?accounts=true&acc=BCC_TO_HAVE_ONE_EXTRA")
  4409  			if len(info.AccountDetails) != 1 {
  4410  				t.Fatalf("expected single account")
  4411  			}
  4412  			acc = info.AccountDetails[0]
  4413  			got = int(acc.ReservedMemory)
  4414  			expected = -1
  4415  			if got != expected {
  4416  				t.Errorf("Expected: %v, got: %v", expected, got)
  4417  			}
  4418  			got = int(acc.ReservedStore)
  4419  			expected = -1
  4420  			if got != expected {
  4421  				t.Errorf("Expected: %v, got: %v", expected, got)
  4422  			}
  4423  		}
  4424  	})
  4425  	t.Run("offset-too-big", func(t *testing.T) {
  4426  		for _, url := range []string{monUrl1, monUrl2} {
  4427  			info := readJsInfo(url + "?accounts=true&offset=10")
  4428  			if len(info.AccountDetails) != 0 {
  4429  				t.Fatalf("expected no accounts to be returned by %s but got %v", url, info)
  4430  			}
  4431  		}
  4432  	})
  4433  	t.Run("limit", func(t *testing.T) {
  4434  		for _, url := range []string{monUrl1, monUrl2} {
  4435  			info := readJsInfo(url + "?accounts=true&limit=1")
  4436  			if len(info.AccountDetails) != 1 {
  4437  				t.Fatalf("expected one account to be returned by %s but got %v", url, info)
  4438  			}
  4439  			if info := readJsInfo(url + "?accounts=true&offset=1&limit=1"); len(info.AccountDetails) != 1 {
  4440  				t.Fatalf("expected one account to be returned by %s but got %v", url, info)
  4441  			}
  4442  		}
  4443  	})
  4444  	t.Run("offset-stable", func(t *testing.T) {
  4445  		for _, url := range []string{monUrl1, monUrl2} {
  4446  			info1 := readJsInfo(url + "?accounts=true&offset=1&limit=1")
  4447  			if len(info1.AccountDetails) != 1 {
  4448  				t.Fatalf("expected one account to be returned by %s but got %v", url, info1)
  4449  			}
  4450  			info2 := readJsInfo(url + "?accounts=true&offset=1&limit=1")
  4451  			if len(info2.AccountDetails) != 1 {
  4452  				t.Fatalf("expected one account to be returned by %s but got %v", url, info2)
  4453  			}
  4454  			if info1.AccountDetails[0].Name != info2.AccountDetails[0].Name {
  4455  				t.Fatalf("absent changes, same offset should result in same account but gut: %v %v",
  4456  					info1.AccountDetails[0].Name, info2.AccountDetails[0].Name)
  4457  			}
  4458  		}
  4459  	})
  4460  	t.Run("filter-account", func(t *testing.T) {
  4461  		for _, url := range []string{monUrl1, monUrl2} {
  4462  			info := readJsInfo(url + "?acc=ACC")
  4463  			if len(info.AccountDetails) != 1 {
  4464  				t.Fatalf("expected account ACC to be returned by %s but got %v", url, info)
  4465  			}
  4466  			if info.AccountDetails[0].Name != "ACC" {
  4467  				t.Fatalf("expected account ACC to be returned by %s but got %v", url, info)
  4468  			}
  4469  			if len(info.AccountDetails[0].Streams) != 0 {
  4470  				t.Fatalf("expected account ACC to be returned by %s but got %v", url, info)
  4471  			}
  4472  		}
  4473  	})
  4474  	t.Run("streams", func(t *testing.T) {
  4475  		for _, url := range []string{monUrl1, monUrl2} {
  4476  			info := readJsInfo(url + "?acc=ACC&streams=true")
  4477  			if len(info.AccountDetails) != 1 {
  4478  				t.Fatalf("expected account ACC to be returned by %s but got %v", url, info)
  4479  			}
  4480  			if len(info.AccountDetails[0].Streams) == 0 {
  4481  				t.Fatalf("expected streams to be returned by %s but got %v", url, info)
  4482  			}
  4483  			if len(info.AccountDetails[0].Streams[0].Consumer) != 0 {
  4484  				t.Fatalf("expected no consumers to be returned by %s but got %v", url, info)
  4485  			}
  4486  		}
  4487  	})
  4488  	t.Run("consumers", func(t *testing.T) {
  4489  		for _, url := range []string{monUrl1, monUrl2} {
  4490  			info := readJsInfo(url + "?acc=ACC&consumers=true")
  4491  			if len(info.AccountDetails) != 1 {
  4492  				t.Fatalf("expected account ACC to be returned by %s but got %v", url, info)
  4493  			}
  4494  			if len(info.AccountDetails[0].Streams[0].Consumer) == 0 {
  4495  				t.Fatalf("expected consumers to be returned by %s but got %v", url, info)
  4496  			}
  4497  			if info.AccountDetails[0].Streams[0].Config != nil {
  4498  				t.Fatal("Config expected to not be present")
  4499  			}
  4500  			if info.AccountDetails[0].Streams[0].Consumer[0].Config != nil {
  4501  				t.Fatal("Config expected to not be present")
  4502  			}
  4503  			if len(info.AccountDetails[0].Streams[0].ConsumerRaftGroups) != 0 {
  4504  				t.Fatalf("expected consumer raft groups to not be returned by %s but got %v", url, info)
  4505  			}
  4506  		}
  4507  	})
  4508  	t.Run("config", func(t *testing.T) {
  4509  		for _, url := range []string{monUrl1, monUrl2} {
  4510  			info := readJsInfo(url + "?acc=ACC&consumers=true&config=true")
  4511  			if len(info.AccountDetails) != 1 {
  4512  				t.Fatalf("expected account ACC to be returned by %s but got %v", url, info)
  4513  			}
  4514  			if info.AccountDetails[0].Streams[0].Config == nil {
  4515  				t.Fatal("Config expected to be present")
  4516  			}
  4517  			if info.AccountDetails[0].Streams[0].Consumer[0].Config == nil {
  4518  				t.Fatal("Config expected to be present")
  4519  			}
  4520  		}
  4521  	})
  4522  	t.Run("replication", func(t *testing.T) {
  4523  		// The replication lag may only be present on the leader
  4524  		replicationFound := false
  4525  		for _, url := range []string{monUrl1, monUrl2} {
  4526  			info := readJsInfo(url + "?acc=ACC&streams=true")
  4527  			if len(info.AccountDetails) != 1 {
  4528  				t.Fatalf("expected account ACC to be returned by %s but got %v", url, info)
  4529  			}
  4530  			streamFound := false
  4531  			for _, stream := range info.AccountDetails[0].Streams {
  4532  				if stream.Name == "my-stream-mirror" {
  4533  					streamFound = true
  4534  					if stream.Mirror != nil {
  4535  						replicationFound = true
  4536  					}
  4537  				}
  4538  			}
  4539  			if !streamFound {
  4540  				t.Fatalf("Did not locate my-stream-mirror stream in results")
  4541  			}
  4542  		}
  4543  		if !replicationFound {
  4544  			t.Fatal("ReplicationLag expected to be present for my-stream-mirror stream")
  4545  		}
  4546  	})
  4547  	t.Run("cluster-info", func(t *testing.T) {
  4548  		found := 0
  4549  		for i, url := range []string{monUrl1, monUrl2} {
  4550  			info := readJsInfo(url + "")
  4551  			if info.Meta.Peer != getHash(info.Meta.Leader) {
  4552  				t.Fatalf("Invalid Peer: %+v", info.Meta)
  4553  			}
  4554  			if info.Meta.Replicas != nil {
  4555  				found++
  4556  				for _, r := range info.Meta.Replicas {
  4557  					if r.Peer == _EMPTY_ {
  4558  						t.Fatalf("Replicas' Peer is empty: %+v", r)
  4559  					}
  4560  				}
  4561  				if info.Meta.Leader != srvs[i].Name() {
  4562  					t.Fatalf("received cluster info from non leader: leader %s, server: %s", info.Meta.Leader, srvs[i].Name())
  4563  				}
  4564  			}
  4565  		}
  4566  		if found == 0 {
  4567  			t.Fatalf("did not receive cluster info from any node")
  4568  		}
  4569  		if found > 1 {
  4570  			t.Fatalf("received cluster info from multiple nodes")
  4571  		}
  4572  	})
  4573  	t.Run("account-non-existing", func(t *testing.T) {
  4574  		for _, url := range []string{monUrl1, monUrl2} {
  4575  			info := readJsInfo(url + "?acc=DOES_NOT_EXIST")
  4576  			if len(info.AccountDetails) != 0 {
  4577  				t.Fatalf("expected no account to be returned by %s but got %v", url, info)
  4578  			}
  4579  		}
  4580  	})
  4581  	t.Run("account-non-existing-with-stream-details", func(t *testing.T) {
  4582  		for _, url := range []string{monUrl1, monUrl2} {
  4583  			info := readJsInfo(url + "?acc=DOES_NOT_EXIST&streams=true")
  4584  			if len(info.AccountDetails) != 0 {
  4585  				t.Fatalf("expected no account to be returned by %s but got %v", url, info)
  4586  			}
  4587  		}
  4588  	})
  4589  	t.Run("unique-tag-exists", func(t *testing.T) {
  4590  		for _, url := range []string{monUrl1, monUrl2} {
  4591  			info := readJsInfo(url)
  4592  			if len(info.Config.UniqueTag) == 0 {
  4593  				t.Fatalf("expected unique_tag to be returned by %s but got %v", url, info)
  4594  			}
  4595  		}
  4596  	})
  4597  	t.Run("raftgroups", func(t *testing.T) {
  4598  		for _, url := range []string{monUrl1, monUrl2} {
  4599  			info := readJsInfo(url + "?acc=ACC&consumers=true&raft=true")
  4600  			if len(info.AccountDetails) != 1 {
  4601  				t.Fatalf("expected account ACC to be returned by %s but got %v", url, info)
  4602  			}
  4603  
  4604  			// We will have two streams and order is not guaranteed. So grab the one we want.
  4605  			var si StreamDetail
  4606  			if info.AccountDetails[0].Streams[0].Name == "my-stream-replicated" {
  4607  				si = info.AccountDetails[0].Streams[0]
  4608  			} else {
  4609  				si = info.AccountDetails[0].Streams[1]
  4610  			}
  4611  
  4612  			if len(si.Consumer) == 0 {
  4613  				t.Fatalf("expected consumers to be returned by %s but got %v", url, info)
  4614  			}
  4615  			if len(si.ConsumerRaftGroups) == 0 {
  4616  				t.Fatalf("expected consumer raft groups to be returned by %s but got %v", url, info)
  4617  			}
  4618  			if len(si.RaftGroup) == 0 {
  4619  				t.Fatal("expected stream raft group info to be included")
  4620  			}
  4621  			crgroup := si.ConsumerRaftGroups[0]
  4622  			if crgroup.Name != "my-consumer-replicated" && crgroup.Name != "my-consumer-mirror" {
  4623  				t.Fatalf("expected consumer name to be included in raft group info, got: %v", crgroup.Name)
  4624  			}
  4625  			if len(crgroup.RaftGroup) == 0 {
  4626  				t.Fatal("expected consumer raft group info to be included")
  4627  			}
  4628  		}
  4629  	})
  4630  }
  4631  
  4632  func TestMonitorReloadTLSConfig(t *testing.T) {
  4633  	template := `
  4634  		listen: "127.0.0.1:-1"
  4635  		https: "127.0.0.1:-1"
  4636  		tls {
  4637  			cert_file: '%s'
  4638  			key_file: '%s'
  4639  			ca_file: '../test/configs/certs/ca.pem'
  4640  
  4641  			# Set this to make sure that it does not impact secure monitoring
  4642  			# (which it did, see issue: https://github.com/nats-io/nats-server/issues/2980)
  4643  			verify_and_map: true
  4644  		}
  4645  	`
  4646  	conf := createConfFile(t, []byte(fmt.Sprintf(template,
  4647  		"../test/configs/certs/server-noip.pem",
  4648  		"../test/configs/certs/server-key-noip.pem")))
  4649  
  4650  	s, _ := RunServerWithConfig(conf)
  4651  	defer s.Shutdown()
  4652  
  4653  	addr := fmt.Sprintf("127.0.0.1:%d", s.MonitorAddr().Port)
  4654  	c, err := net.Dial("tcp", addr)
  4655  	if err != nil {
  4656  		t.Fatalf("Error creating ws connection: %v", err)
  4657  	}
  4658  	defer c.Close()
  4659  
  4660  	tc := &TLSConfigOpts{CaFile: "../test/configs/certs/ca.pem"}
  4661  	tlsConfig, err := GenTLSConfig(tc)
  4662  	if err != nil {
  4663  		t.Fatalf("Error generating TLS config: %v", err)
  4664  	}
  4665  	tlsConfig.ServerName = "127.0.0.1"
  4666  	tlsConfig.RootCAs = tlsConfig.ClientCAs
  4667  	tlsConfig.ClientCAs = nil
  4668  	c = tls.Client(c, tlsConfig.Clone())
  4669  	if err := c.(*tls.Conn).Handshake(); err == nil || !strings.Contains(err.Error(), "SAN") {
  4670  		t.Fatalf("Unexpected error: %v", err)
  4671  	}
  4672  	c.Close()
  4673  
  4674  	reloadUpdateConfig(t, s, conf, fmt.Sprintf(template,
  4675  		"../test/configs/certs/server-cert.pem",
  4676  		"../test/configs/certs/server-key.pem"))
  4677  
  4678  	c, err = net.Dial("tcp", addr)
  4679  	if err != nil {
  4680  		t.Fatalf("Error creating ws connection: %v", err)
  4681  	}
  4682  	defer c.Close()
  4683  
  4684  	c = tls.Client(c, tlsConfig.Clone())
  4685  	if err := c.(*tls.Conn).Handshake(); err != nil {
  4686  		t.Fatalf("Error on TLS handshake: %v", err)
  4687  	}
  4688  
  4689  	// Need to read something to see if there is a problem with the certificate or not.
  4690  	var buf [64]byte
  4691  	c.SetReadDeadline(time.Now().Add(250 * time.Millisecond))
  4692  	_, err = c.Read(buf[:])
  4693  	if ne, ok := err.(net.Error); !ok || !ne.Timeout() {
  4694  		t.Fatalf("Error: %v", err)
  4695  	}
  4696  }
  4697  
  4698  func TestMonitorMQTT(t *testing.T) {
  4699  	o := DefaultOptions()
  4700  	o.HTTPHost = "127.0.0.1"
  4701  	o.HTTPPort = -1
  4702  	o.ServerName = "mqtt_server"
  4703  	o.Users = []*User{{Username: "someuser"}}
  4704  	pinnedCerts := make(PinnedCertSet)
  4705  	pinnedCerts["7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069"] = struct{}{}
  4706  	o.MQTT = MQTTOpts{
  4707  		Host:           "127.0.0.1",
  4708  		Port:           -1,
  4709  		NoAuthUser:     "someuser",
  4710  		JsDomain:       "js",
  4711  		AuthTimeout:    2.0,
  4712  		TLSMap:         true,
  4713  		TLSTimeout:     3.0,
  4714  		TLSPinnedCerts: pinnedCerts,
  4715  		AckWait:        4 * time.Second,
  4716  		MaxAckPending:  256,
  4717  	}
  4718  	s := RunServer(o)
  4719  	defer s.Shutdown()
  4720  
  4721  	expected := &MQTTOptsVarz{
  4722  		Host:           "127.0.0.1",
  4723  		Port:           o.MQTT.Port,
  4724  		NoAuthUser:     "someuser",
  4725  		JsDomain:       "js",
  4726  		AuthTimeout:    2.0,
  4727  		TLSMap:         true,
  4728  		TLSTimeout:     3.0,
  4729  		TLSPinnedCerts: []string{"7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069"},
  4730  		AckWait:        4 * time.Second,
  4731  		MaxAckPending:  256,
  4732  	}
  4733  	url := fmt.Sprintf("http://127.0.0.1:%d/varz", s.MonitorAddr().Port)
  4734  	for mode := 0; mode < 2; mode++ {
  4735  		v := pollVarz(t, s, mode, url, nil)
  4736  		vm := &v.MQTT
  4737  		if !reflect.DeepEqual(vm, expected) {
  4738  			t.Fatalf("Expected\n%+v\nGot:\n%+v", expected, vm)
  4739  		}
  4740  	}
  4741  }
  4742  
  4743  func TestMonitorWebsocket(t *testing.T) {
  4744  	o := DefaultOptions()
  4745  	o.HTTPHost = "127.0.0.1"
  4746  	o.HTTPPort = -1
  4747  	kp, _ := nkeys.FromSeed(oSeed)
  4748  	pub, _ := kp.PublicKey()
  4749  	o.TrustedKeys = []string{pub}
  4750  	o.Users = []*User{{Username: "someuser"}}
  4751  	pinnedCerts := make(PinnedCertSet)
  4752  	pinnedCerts["7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069"] = struct{}{}
  4753  	o.Websocket = WebsocketOpts{
  4754  		Host:             "127.0.0.1",
  4755  		Port:             -1,
  4756  		Advertise:        "somehost:8080",
  4757  		NoAuthUser:       "someuser",
  4758  		JWTCookie:        "somecookiename",
  4759  		AuthTimeout:      2.0,
  4760  		NoTLS:            true,
  4761  		TLSMap:           true,
  4762  		TLSPinnedCerts:   pinnedCerts,
  4763  		SameOrigin:       true,
  4764  		AllowedOrigins:   []string{"origin1", "origin2"},
  4765  		Compression:      true,
  4766  		HandshakeTimeout: 4 * time.Second,
  4767  	}
  4768  	s := RunServer(o)
  4769  	defer s.Shutdown()
  4770  
  4771  	expected := &WebsocketOptsVarz{
  4772  		Host:             "127.0.0.1",
  4773  		Port:             o.Websocket.Port,
  4774  		Advertise:        "somehost:8080",
  4775  		NoAuthUser:       "someuser",
  4776  		JWTCookie:        "somecookiename",
  4777  		AuthTimeout:      2.0,
  4778  		NoTLS:            true,
  4779  		TLSMap:           true,
  4780  		TLSPinnedCerts:   []string{"7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069"},
  4781  		SameOrigin:       true,
  4782  		AllowedOrigins:   []string{"origin1", "origin2"},
  4783  		Compression:      true,
  4784  		HandshakeTimeout: 4 * time.Second,
  4785  	}
  4786  	url := fmt.Sprintf("http://127.0.0.1:%d/varz", s.MonitorAddr().Port)
  4787  	for mode := 0; mode < 2; mode++ {
  4788  		v := pollVarz(t, s, mode, url, nil)
  4789  		vw := &v.Websocket
  4790  		if !reflect.DeepEqual(vw, expected) {
  4791  			t.Fatalf("Expected\n%+v\nGot:\n%+v", expected, vw)
  4792  		}
  4793  	}
  4794  }
  4795  
  4796  func TestServerIDZRequest(t *testing.T) {
  4797  	conf := createConfFile(t, []byte(`
  4798  		listen: 127.0.0.1:-1
  4799  		server_name: TEST22
  4800  		# For access to system account.
  4801  		accounts { $SYS { users = [ { user: "admin", pass: "s3cr3t!" } ] } }
  4802  	`))
  4803  	defer removeFile(t, conf)
  4804  
  4805  	s, _ := RunServerWithConfig(conf)
  4806  	defer s.Shutdown()
  4807  
  4808  	nc, err := nats.Connect(s.ClientURL(), nats.UserInfo("admin", "s3cr3t!"))
  4809  	require_NoError(t, err)
  4810  
  4811  	subject := fmt.Sprintf(serverPingReqSubj, "IDZ")
  4812  	resp, err := nc.Request(subject, nil, time.Second)
  4813  	require_NoError(t, err)
  4814  
  4815  	var sid ServerID
  4816  	err = json.Unmarshal(resp.Data, &sid)
  4817  	require_NoError(t, err)
  4818  
  4819  	require_True(t, sid.Name == "TEST22")
  4820  	require_True(t, strings.HasPrefix(sid.ID, "N"))
  4821  }
  4822  
  4823  func TestMonitorProfilez(t *testing.T) {
  4824  	s := RunServer(DefaultOptions())
  4825  	defer s.Shutdown()
  4826  
  4827  	// Then start profiling.
  4828  	s.StartProfiler()
  4829  
  4830  	// Now check that all of the profiles that we expect are
  4831  	// returning instead of erroring.
  4832  	for _, try := range []*ProfilezOptions{
  4833  		{Name: "allocs", Debug: 0},
  4834  		{Name: "allocs", Debug: 1},
  4835  		{Name: "block", Debug: 0},
  4836  		{Name: "goroutine", Debug: 0},
  4837  		{Name: "goroutine", Debug: 1},
  4838  		{Name: "goroutine", Debug: 2},
  4839  		{Name: "heap", Debug: 0},
  4840  		{Name: "heap", Debug: 1},
  4841  		{Name: "mutex", Debug: 0},
  4842  		{Name: "threadcreate", Debug: 0},
  4843  	} {
  4844  		if ps := s.profilez(try); ps.Error != _EMPTY_ {
  4845  			t.Fatalf("Unexpected error on %v: %s", try, ps.Error)
  4846  		}
  4847  	}
  4848  }
  4849  
  4850  func TestMonitorRoutePoolSize(t *testing.T) {
  4851  	conf1 := createConfFile(t, []byte(`
  4852  		port: -1
  4853  		http: -1
  4854  		cluster {
  4855  			port: -1
  4856  			name: "local"
  4857  			pool_size: 5
  4858  		}
  4859  		no_sys_acc: true
  4860  	`))
  4861  	defer removeFile(t, conf1)
  4862  	s1, o1 := RunServerWithConfig(conf1)
  4863  	defer s1.Shutdown()
  4864  
  4865  	conf23 := createConfFile(t, []byte(fmt.Sprintf(`
  4866  		port: -1
  4867  		http: -1
  4868  		cluster {
  4869  			port: -1
  4870  			name: "local"
  4871  			routes: ["nats://127.0.0.1:%d"]
  4872  			pool_size: 5
  4873  		}
  4874  		no_sys_acc: true
  4875  	`, o1.Cluster.Port)))
  4876  	defer removeFile(t, conf23)
  4877  
  4878  	s2, _ := RunServerWithConfig(conf23)
  4879  	defer s2.Shutdown()
  4880  	s3, _ := RunServerWithConfig(conf23)
  4881  	defer s3.Shutdown()
  4882  
  4883  	checkClusterFormed(t, s1, s2, s3)
  4884  
  4885  	for i, s := range []*Server{s1, s2, s3} {
  4886  		url := fmt.Sprintf("http://127.0.0.1:%d/varz", s.MonitorAddr().Port)
  4887  		for mode := 0; mode < 2; mode++ {
  4888  			v := pollVarz(t, s, mode, url, nil)
  4889  			if v.Cluster.PoolSize != 5 {
  4890  				t.Fatalf("Expected Cluster.PoolSize==5, got %v", v.Cluster.PoolSize)
  4891  			}
  4892  			if v.Remotes != 2 {
  4893  				t.Fatalf("Expected Remotes==2, got %v", v.Remotes)
  4894  			}
  4895  			if v.Routes != 10 {
  4896  				t.Fatalf("Expected NumRoutes==10, got %v", v.Routes)
  4897  			}
  4898  		}
  4899  
  4900  		url = fmt.Sprintf("http://127.0.0.1:%d/routez", s.MonitorAddr().Port)
  4901  		for mode := 0; mode < 2; mode++ {
  4902  			v := pollRoutez(t, s, mode, url, nil)
  4903  			if v.NumRoutes != 10 {
  4904  				t.Fatalf("Expected NumRoutes==10, got %v", v.NumRoutes)
  4905  			}
  4906  			if n := len(v.Routes); n != 10 {
  4907  				t.Fatalf("Expected len(Routes)==10, got %v", n)
  4908  			}
  4909  			remotes := make(map[string]int)
  4910  			for _, r := range v.Routes {
  4911  				remotes[r.RemoteID]++
  4912  			}
  4913  			if n := len(remotes); n != 2 {
  4914  				t.Fatalf("Expected routes for 2 different servers, got %v", n)
  4915  			}
  4916  			switch i {
  4917  			case 0:
  4918  				if n := remotes[s2.ID()]; n != 5 {
  4919  					t.Fatalf("Expected 5 routes from S1 to S2, got %v", n)
  4920  				}
  4921  				if n := remotes[s3.ID()]; n != 5 {
  4922  					t.Fatalf("Expected 5 routes from S1 to S3, got %v", n)
  4923  				}
  4924  			case 1:
  4925  				if n := remotes[s1.ID()]; n != 5 {
  4926  					t.Fatalf("Expected 5 routes from S2 to S1, got %v", n)
  4927  				}
  4928  				if n := remotes[s3.ID()]; n != 5 {
  4929  					t.Fatalf("Expected 5 routes from S2 to S3, got %v", n)
  4930  				}
  4931  			case 2:
  4932  				if n := remotes[s1.ID()]; n != 5 {
  4933  					t.Fatalf("Expected 5 routes from S3 to S1, got %v", n)
  4934  				}
  4935  				if n := remotes[s2.ID()]; n != 5 {
  4936  					t.Fatalf("Expected 5 routes from S3 to S2, got %v", n)
  4937  				}
  4938  			}
  4939  		}
  4940  	}
  4941  }
  4942  
  4943  func TestMonitorRoutePerAccount(t *testing.T) {
  4944  	conf1 := createConfFile(t, []byte(`
  4945  		port: -1
  4946  		http: -1
  4947  		accounts {
  4948  			A { users: [{user: "a", password: "pwd"}] }
  4949  		}
  4950  		cluster {
  4951  			port: -1
  4952  			name: "local"
  4953  			accounts: ["A"]
  4954  		}
  4955  	`))
  4956  	defer removeFile(t, conf1)
  4957  	s1, o1 := RunServerWithConfig(conf1)
  4958  	defer s1.Shutdown()
  4959  
  4960  	conf23 := createConfFile(t, []byte(fmt.Sprintf(`
  4961  		port: -1
  4962  		http: -1
  4963  		accounts {
  4964  			A { users: [{user: "a", password: "pwd"}] }
  4965  		}
  4966  		cluster {
  4967  			port: -1
  4968  			name: "local"
  4969  			routes: ["nats://127.0.0.1:%d"]
  4970  			accounts: ["A"]
  4971  		}
  4972  	`, o1.Cluster.Port)))
  4973  	defer removeFile(t, conf23)
  4974  
  4975  	s2, _ := RunServerWithConfig(conf23)
  4976  	defer s2.Shutdown()
  4977  	s3, _ := RunServerWithConfig(conf23)
  4978  	defer s3.Shutdown()
  4979  
  4980  	checkClusterFormed(t, s1, s2, s3)
  4981  
  4982  	for _, s := range []*Server{s1, s2, s3} {
  4983  		// Default pool size + account "A" + system account (added by default)
  4984  		enr := 2 * (DEFAULT_ROUTE_POOL_SIZE + 1 + 1)
  4985  		url := fmt.Sprintf("http://127.0.0.1:%d/varz", s.MonitorAddr().Port)
  4986  		for mode := 0; mode < 2; mode++ {
  4987  			v := pollVarz(t, s, mode, url, nil)
  4988  			if v.Remotes != 2 {
  4989  				t.Fatalf("Expected Remotes==2, got %v", v.Remotes)
  4990  			}
  4991  			if v.Routes != enr {
  4992  				t.Fatalf("Expected NumRoutes==%d, got %v", enr, v.Routes)
  4993  			}
  4994  		}
  4995  
  4996  		url = fmt.Sprintf("http://127.0.0.1:%d/routez", s.MonitorAddr().Port)
  4997  		for mode := 0; mode < 2; mode++ {
  4998  			v := pollRoutez(t, s, mode, url, nil)
  4999  			if v.NumRoutes != enr {
  5000  				t.Fatalf("Expected NumRoutes==%d, got %v", enr, v.NumRoutes)
  5001  			}
  5002  			if n := len(v.Routes); n != enr {
  5003  				t.Fatalf("Expected len(Routes)==%d, got %v", enr, n)
  5004  			}
  5005  			remotes := make(map[string]int)
  5006  			for _, r := range v.Routes {
  5007  				var acc int
  5008  				if r.Account == "A" {
  5009  					acc = 1
  5010  				}
  5011  				remotes[r.RemoteID] += acc
  5012  			}
  5013  			if n := len(remotes); n != 2 {
  5014  				t.Fatalf("Expected routes for 2 different servers, got %v", n)
  5015  			}
  5016  			for remoteID, v := range remotes {
  5017  				if v != 1 {
  5018  					t.Fatalf("Expected one and only one connection for account A for remote %q, got %v", remoteID, v)
  5019  				}
  5020  			}
  5021  		}
  5022  	}
  5023  }
  5024  
  5025  func TestMonitorConnzOperatorModeFilterByUser(t *testing.T) {
  5026  	accKp, accPub := createKey(t)
  5027  	accClaim := jwt.NewAccountClaims(accPub)
  5028  	accJwt := encodeClaim(t, accClaim, accPub)
  5029  
  5030  	conf := createConfFile(t, []byte(fmt.Sprintf(`
  5031  		listen: 127.0.0.1:-1
  5032  		http: 127.0.0.1:-1
  5033  		operator = %s
  5034  		resolver = MEMORY
  5035  		resolver_preload = {
  5036  			%s : %s
  5037  		}
  5038  	`, ojwt, accPub, accJwt)))
  5039  
  5040  	s, _ := RunServerWithConfig(conf)
  5041  	defer s.Shutdown()
  5042  
  5043  	createUser := func() (string, string) {
  5044  		ukp, _ := nkeys.CreateUser()
  5045  		seed, _ := ukp.Seed()
  5046  		upub, _ := ukp.PublicKey()
  5047  		uclaim := newJWTTestUserClaims()
  5048  		uclaim.Subject = upub
  5049  		ujwt, err := uclaim.Encode(accKp)
  5050  		require_NoError(t, err)
  5051  		return upub, genCredsFile(t, ujwt, seed)
  5052  	}
  5053  
  5054  	// Now create 2 users.
  5055  	aUser, aCreds := createUser()
  5056  	bUser, bCreds := createUser()
  5057  
  5058  	var users []*nats.Conn
  5059  
  5060  	// Create 2 for A
  5061  	for i := 0; i < 2; i++ {
  5062  		nc, err := nats.Connect(s.ClientURL(), nats.UserCredentials(aCreds))
  5063  		require_NoError(t, err)
  5064  		defer nc.Close()
  5065  		users = append(users, nc)
  5066  	}
  5067  	// Create 5 for B
  5068  	for i := 0; i < 5; i++ {
  5069  		nc, err := nats.Connect(s.ClientURL(), nats.UserCredentials(bCreds))
  5070  		require_NoError(t, err)
  5071  		defer nc.Close()
  5072  		users = append(users, nc)
  5073  	}
  5074  
  5075  	// Test A
  5076  	connz := pollConz(t, s, 1, _EMPTY_, &ConnzOptions{User: aUser, Username: true})
  5077  	require_True(t, connz.NumConns == 2)
  5078  	for _, ci := range connz.Conns {
  5079  		require_True(t, ci.AuthorizedUser == aUser)
  5080  	}
  5081  	// Test B
  5082  	connz = pollConz(t, s, 1, _EMPTY_, &ConnzOptions{User: bUser, Username: true})
  5083  	require_True(t, connz.NumConns == 5)
  5084  	for _, ci := range connz.Conns {
  5085  		require_True(t, ci.AuthorizedUser == bUser)
  5086  	}
  5087  
  5088  	// Make sure URL access is the same.
  5089  	url := fmt.Sprintf("http://127.0.0.1:%d/", s.MonitorAddr().Port)
  5090  	urlFull := url + fmt.Sprintf("connz?auth=true&user=%s", aUser)
  5091  	connz = pollConz(t, s, 0, urlFull, nil)
  5092  	require_True(t, connz.NumConns == 2)
  5093  	for _, ci := range connz.Conns {
  5094  		require_True(t, ci.AuthorizedUser == aUser)
  5095  	}
  5096  
  5097  	// Now test closed filtering as well.
  5098  	for _, nc := range users {
  5099  		nc.Close()
  5100  	}
  5101  	// Let them process and be moved to closed ring buffer in server.
  5102  	time.Sleep(100 * time.Millisecond)
  5103  
  5104  	connz = pollConz(t, s, 1, _EMPTY_, &ConnzOptions{User: aUser, Username: true, State: ConnClosed})
  5105  	require_True(t, connz.NumConns == 2)
  5106  	for _, ci := range connz.Conns {
  5107  		require_True(t, ci.AuthorizedUser == aUser)
  5108  	}
  5109  }
  5110  
  5111  func TestMonitorConnzSortByRTT(t *testing.T) {
  5112  	s := runMonitorServer()
  5113  	defer s.Shutdown()
  5114  
  5115  	for i := 0; i < 10; i++ {
  5116  		nc, err := nats.Connect(s.ClientURL())
  5117  		require_NoError(t, err)
  5118  		defer nc.Close()
  5119  	}
  5120  
  5121  	connz := pollConz(t, s, 1, _EMPTY_, &ConnzOptions{Sort: ByRTT})
  5122  	require_True(t, connz.NumConns == 10)
  5123  
  5124  	var rtt int64
  5125  	for _, ci := range connz.Conns {
  5126  		if rtt == 0 {
  5127  			rtt = ci.rtt
  5128  		} else {
  5129  			if ci.rtt > rtt {
  5130  				t.Fatalf("RTT not in descending order: %v vs %v",
  5131  					time.Duration(rtt), time.Duration(ci.rtt))
  5132  			}
  5133  			rtt = ci.rtt
  5134  		}
  5135  	}
  5136  
  5137  	// Make sure url works as well.
  5138  	url := fmt.Sprintf("http://127.0.0.1:%d/connz?sort=rtt", s.MonitorAddr().Port)
  5139  	connz = pollConz(t, s, 0, url, nil)
  5140  	require_True(t, connz.NumConns == 10)
  5141  
  5142  	rtt = 0
  5143  	for _, ci := range connz.Conns {
  5144  		crttd, err := time.ParseDuration(ci.RTT)
  5145  		require_NoError(t, err)
  5146  		crtt := int64(crttd)
  5147  		if rtt == 0 {
  5148  			rtt = crtt
  5149  		} else {
  5150  			if crtt > rtt {
  5151  				t.Fatalf("RTT not in descending order: %v vs %v",
  5152  					time.Duration(rtt), time.Duration(crtt))
  5153  			}
  5154  			rtt = ci.rtt
  5155  		}
  5156  	}
  5157  }
  5158  
  5159  // https://github.com/nats-io/nats-server/issues/4144
  5160  func TestMonitorAccountszMappingOrderReporting(t *testing.T) {
  5161  	conf := createConfFile(t, []byte(`
  5162  	listen: 127.0.0.1:-1
  5163  	server_name: SR22
  5164  	accounts {
  5165  		CLOUD {
  5166  			exports [ { service: "downlink.>" } ]
  5167  		}
  5168  		APP {
  5169  			imports [ { service: { account: CLOUD, subject: "downlink.>"}, to: "event.>"} ]
  5170  		}
  5171  	}`))
  5172  
  5173  	s, _ := RunServerWithConfig(conf)
  5174  	defer s.Shutdown()
  5175  
  5176  	az, err := s.Accountz(&AccountzOptions{"APP"})
  5177  	require_NoError(t, err)
  5178  	require_NotNil(t, az.Account)
  5179  	require_True(t, len(az.Account.Imports) > 0)
  5180  
  5181  	var found bool
  5182  	for _, si := range az.Account.Imports {
  5183  		if si.Import.Subject == "downlink.>" {
  5184  			found = true
  5185  			require_True(t, si.Import.LocalSubject == "event.>")
  5186  			break
  5187  		}
  5188  	}
  5189  	require_True(t, found)
  5190  }
  5191  
  5192  // createCallbackURL adds a callback query parameter for JSONP requests.
  5193  func createCallbackURL(t *testing.T, endpoint string) string {
  5194  	t.Helper()
  5195  
  5196  	u, err := url.Parse(endpoint)
  5197  	if err != nil {
  5198  		t.Fatal(err)
  5199  	}
  5200  
  5201  	params := u.Query()
  5202  	params.Set("callback", "callback")
  5203  
  5204  	u.RawQuery = params.Encode()
  5205  
  5206  	return u.String()
  5207  }
  5208  
  5209  // stripCallback removes the JSONP callback function from the response.
  5210  // Returns the JSON body without the wrapping callback function.
  5211  // If there's no callback function, the data is returned as is.
  5212  func stripCallback(data []byte) []byte {
  5213  	// Cut the JSONP callback function with the opening parentheses.
  5214  	_, after, found := bytes.Cut(data, []byte("("))
  5215  
  5216  	if found {
  5217  		return bytes.TrimSuffix(after, []byte(")"))
  5218  	}
  5219  
  5220  	return data
  5221  }
  5222  
  5223  // expectHealthStatus makes 1 regular and 1 JSONP request to the URL and checks the
  5224  // HTTP status code, Content-Type header and health status string.
  5225  func expectHealthStatus(t *testing.T, url string, statusCode int, wantStatus string) {
  5226  	t.Helper()
  5227  
  5228  	// First check for regular requests.
  5229  	body := readBodyEx(t, url, statusCode, appJSONContent)
  5230  	checkHealthStatus(t, body, wantStatus)
  5231  
  5232  	// Another check for JSONP requests.
  5233  	jsonpURL := createCallbackURL(t, url) // Adds a callback query param.
  5234  	jsonpBody := readBodyEx(t, jsonpURL, statusCode, appJSContent)
  5235  	checkHealthStatus(t, stripCallback(jsonpBody), wantStatus)
  5236  }
  5237  
  5238  // checkHealthStatus checks the health status from a JSON response.
  5239  func checkHealthStatus(t *testing.T, body []byte, wantStatus string) {
  5240  	t.Helper()
  5241  
  5242  	h := &HealthStatus{}
  5243  
  5244  	if err := json.Unmarshal(body, h); err != nil {
  5245  		t.Fatalf("error unmarshalling the body: %v", err)
  5246  	}
  5247  
  5248  	if h.Status != wantStatus {
  5249  		t.Errorf("want health status %q, got %q", wantStatus, h.Status)
  5250  	}
  5251  }
  5252  
  5253  // checkHealthzEndpoint makes requests to the /healthz endpoint and checks the health status.
  5254  func checkHealthzEndpoint(t *testing.T, address string, statusCode int, wantStatus string) {
  5255  	t.Helper()
  5256  
  5257  	cases := map[string]string{
  5258  		"healthz":         fmt.Sprintf("http://%s/healthz", address),
  5259  		"js-enabled-only": fmt.Sprintf("http://%s/healthz?js-enabled-only=true", address),
  5260  		"js-server-only":  fmt.Sprintf("http://%s/healthz?js-server-only=true", address),
  5261  	}
  5262  
  5263  	for name, url := range cases {
  5264  		t.Run(name, func(t *testing.T) {
  5265  			expectHealthStatus(t, url, statusCode, wantStatus)
  5266  		})
  5267  	}
  5268  }
  5269  
  5270  func TestHealthzStatusOK(t *testing.T) {
  5271  	s := runMonitorServer()
  5272  	defer s.Shutdown()
  5273  
  5274  	checkHealthzEndpoint(t, s.MonitorAddr().String(), http.StatusOK, "ok")
  5275  }
  5276  
  5277  func TestHealthzStatusError(t *testing.T) {
  5278  	s := runMonitorServer()
  5279  	defer s.Shutdown()
  5280  
  5281  	// Intentionally causing an error in readyForConnections().
  5282  	// Note: Private field access, taking advantage of having the tests in the same package.
  5283  	s.listener = nil
  5284  
  5285  	checkHealthzEndpoint(t, s.MonitorAddr().String(), http.StatusInternalServerError, "error")
  5286  }
  5287  
  5288  func TestHealthzStatusUnavailable(t *testing.T) {
  5289  	opts := DefaultMonitorOptions()
  5290  	opts.JetStream = true
  5291  
  5292  	s := RunServer(opts)
  5293  	defer s.Shutdown()
  5294  
  5295  	if !s.JetStreamEnabled() {
  5296  		t.Fatalf("want JetStream to be enabled first")
  5297  	}
  5298  
  5299  	err := s.DisableJetStream()
  5300  
  5301  	if err != nil {
  5302  		t.Fatalf("got an error disabling JetStream: %v", err)
  5303  	}
  5304  
  5305  	for _, test := range []struct {
  5306  		name       string
  5307  		url        string
  5308  		statusCode int
  5309  		wantStatus string
  5310  	}{
  5311  		{
  5312  			"healthz",
  5313  			fmt.Sprintf("http://%s/healthz", s.MonitorAddr().String()),
  5314  			http.StatusServiceUnavailable,
  5315  			"unavailable",
  5316  		},
  5317  		{
  5318  			"js-enabled-only",
  5319  			fmt.Sprintf("http://%s/healthz?js-enabled-only=true", s.MonitorAddr().String()),
  5320  			http.StatusServiceUnavailable,
  5321  			"unavailable",
  5322  		},
  5323  		{
  5324  			"js-server-only",
  5325  			fmt.Sprintf("http://%s/healthz?js-server-only=true", s.MonitorAddr().String()),
  5326  			http.StatusOK,
  5327  			"ok",
  5328  		},
  5329  	} {
  5330  		t.Run(test.name, func(t *testing.T) {
  5331  			expectHealthStatus(t, test.url, test.statusCode, test.wantStatus)
  5332  		})
  5333  	}
  5334  }
  5335  
  5336  // When we converted ipq to use generics we still were using sync.Map. Currently you can not convert
  5337  // any or any to a generic parameterized type. So this stopped working and panics.
  5338  func TestIpqzWithGenerics(t *testing.T) {
  5339  	opts := DefaultMonitorOptions()
  5340  	opts.JetStream = true
  5341  
  5342  	s := RunServer(opts)
  5343  	defer s.Shutdown()
  5344  
  5345  	url := fmt.Sprintf("http://%s/ipqueuesz?all=1", s.MonitorAddr().String())
  5346  	body := readBody(t, url)
  5347  	require_True(t, len(body) > 0)
  5348  
  5349  	queues := map[string]*monitorIPQueue{}
  5350  	require_NoError(t, json.Unmarshal(body, &queues))
  5351  	require_True(t, len(queues) >= 4)
  5352  	require_True(t, queues["SendQ"] != nil)
  5353  }
  5354  
  5355  func TestVarzSyncInterval(t *testing.T) {
  5356  	resetPreviousHTTPConnections()
  5357  	opts := DefaultMonitorOptions()
  5358  	opts.JetStream = true
  5359  	opts.SyncInterval = 22 * time.Second
  5360  	opts.SyncAlways = true
  5361  
  5362  	s := RunServer(opts)
  5363  	defer s.Shutdown()
  5364  
  5365  	url := fmt.Sprintf("http://127.0.0.1:%d/varz", s.MonitorAddr().Port)
  5366  
  5367  	jscfg := pollVarz(t, s, 0, url, nil).JetStream.Config
  5368  	require_True(t, jscfg.SyncInterval == opts.SyncInterval)
  5369  	require_True(t, jscfg.SyncAlways)
  5370  }