github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/server/config_test.go (about)

     1  // Copyright 2015 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package server
    12  
    13  import (
    14  	"context"
    15  	"net"
    16  	"os"
    17  	"reflect"
    18  	"testing"
    19  	"time"
    20  
    21  	"github.com/cockroachdb/cockroach/pkg/base"
    22  	"github.com/cockroachdb/cockroach/pkg/gossip/resolver"
    23  	"github.com/cockroachdb/cockroach/pkg/settings/cluster"
    24  	"github.com/cockroachdb/cockroach/pkg/util"
    25  	"github.com/cockroachdb/cockroach/pkg/util/envutil"
    26  	"github.com/cockroachdb/cockroach/pkg/util/leaktest"
    27  	"github.com/cockroachdb/cockroach/pkg/util/netutil"
    28  	"github.com/kr/pretty"
    29  	"github.com/stretchr/testify/require"
    30  )
    31  
    32  func TestParseInitNodeAttributes(t *testing.T) {
    33  	defer leaktest.AfterTest(t)()
    34  	cfg := MakeConfig(context.Background(), cluster.MakeTestingClusterSettings())
    35  	cfg.Attrs = "attr1=val1::attr2=val2"
    36  	cfg.Stores = base.StoreSpecList{Specs: []base.StoreSpec{{InMemory: true, Size: base.SizeSpec{InBytes: base.MinimumStoreSize * 100}}}}
    37  	engines, err := cfg.CreateEngines(context.Background())
    38  	if err != nil {
    39  		t.Fatalf("Failed to initialize stores: %s", err)
    40  	}
    41  	defer engines.Close()
    42  	if err := cfg.InitNode(context.Background()); err != nil {
    43  		t.Fatalf("Failed to initialize node: %s", err)
    44  	}
    45  
    46  	if a, e := cfg.NodeAttributes.Attrs, []string{"attr1=val1", "attr2=val2"}; !reflect.DeepEqual(a, e) {
    47  		t.Fatalf("expected attributes: %v, found: %v", e, a)
    48  	}
    49  }
    50  
    51  // TestParseJoinUsingAddrs verifies that JoinList is parsed
    52  // correctly.
    53  func TestParseJoinUsingAddrs(t *testing.T) {
    54  	defer leaktest.AfterTest(t)()
    55  	cfg := MakeConfig(context.Background(), cluster.MakeTestingClusterSettings())
    56  	cfg.JoinList = []string{"localhost:12345", "localhost:23456", "localhost:34567", "localhost"}
    57  	cfg.Stores = base.StoreSpecList{Specs: []base.StoreSpec{{InMemory: true, Size: base.SizeSpec{InBytes: base.MinimumStoreSize * 100}}}}
    58  	engines, err := cfg.CreateEngines(context.Background())
    59  	if err != nil {
    60  		t.Fatalf("Failed to initialize stores: %s", err)
    61  	}
    62  	defer engines.Close()
    63  	if err := cfg.InitNode(context.Background()); err != nil {
    64  		t.Fatalf("Failed to initialize node: %s", err)
    65  	}
    66  	r1, err := resolver.NewResolver("localhost:12345")
    67  	if err != nil {
    68  		t.Fatal(err)
    69  	}
    70  	r2, err := resolver.NewResolver("localhost:23456")
    71  	if err != nil {
    72  		t.Fatal(err)
    73  	}
    74  	r3, err := resolver.NewResolver("localhost:34567")
    75  	if err != nil {
    76  		t.Fatal(err)
    77  	}
    78  	r4, err := resolver.NewResolver("localhost:26257")
    79  	if err != nil {
    80  		t.Fatal(err)
    81  	}
    82  	expected := []resolver.Resolver{r1, r2, r3, r4}
    83  	if !reflect.DeepEqual(cfg.GossipBootstrapResolvers, expected) {
    84  		t.Fatalf("Unexpected bootstrap addresses: %v, expected: %v", cfg.GossipBootstrapResolvers, expected)
    85  	}
    86  }
    87  
    88  // TestReadEnvironmentVariables verifies that all environment variables are
    89  // correctly parsed.
    90  func TestReadEnvironmentVariables(t *testing.T) {
    91  	defer leaktest.AfterTest(t)()
    92  
    93  	resetEnvVar := func() {
    94  		// Reset all environment variables in case any were already set.
    95  		if err := os.Unsetenv("COCKROACH_EXPERIMENTAL_LINEARIZABLE"); err != nil {
    96  			t.Fatal(err)
    97  		}
    98  		if err := os.Unsetenv("COCKROACH_SCAN_INTERVAL"); err != nil {
    99  			t.Fatal(err)
   100  		}
   101  		if err := os.Unsetenv("COCKROACH_SCAN_MIN_IDLE_TIME"); err != nil {
   102  			t.Fatal(err)
   103  		}
   104  		if err := os.Unsetenv("COCKROACH_SCAN_MAX_IDLE_TIME"); err != nil {
   105  			t.Fatal(err)
   106  		}
   107  		if err := os.Unsetenv("COCKROACH_CONSISTENCY_CHECK_INTERVAL"); err != nil {
   108  			t.Fatal(err)
   109  		}
   110  		envutil.ClearEnvCache()
   111  	}
   112  	defer resetEnvVar()
   113  
   114  	st := cluster.MakeTestingClusterSettings()
   115  	// Makes sure no values are set when no environment variables are set.
   116  	cfg := MakeConfig(context.Background(), st)
   117  	cfgExpected := MakeConfig(context.Background(), st)
   118  
   119  	resetEnvVar()
   120  	cfg.readEnvironmentVariables()
   121  	require.Equal(t, cfgExpected, cfg)
   122  
   123  	// Set all the environment variables to valid values and ensure they are set
   124  	// correctly.
   125  	if err := os.Setenv("COCKROACH_EXPERIMENTAL_LINEARIZABLE", "true"); err != nil {
   126  		t.Fatal(err)
   127  	}
   128  	cfgExpected.Linearizable = true
   129  	if err := os.Setenv("COCKROACH_SCAN_INTERVAL", "48h"); err != nil {
   130  		t.Fatal(err)
   131  	}
   132  	cfgExpected.ScanInterval = time.Hour * 48
   133  	if err := os.Setenv("COCKROACH_SCAN_MIN_IDLE_TIME", "1h"); err != nil {
   134  		t.Fatal(err)
   135  	}
   136  	cfgExpected.ScanMinIdleTime = time.Hour
   137  	if err := os.Setenv("COCKROACH_SCAN_MAX_IDLE_TIME", "100ns"); err != nil {
   138  		t.Fatal(err)
   139  	}
   140  	cfgExpected.ScanMaxIdleTime = time.Nanosecond * 100
   141  
   142  	envutil.ClearEnvCache()
   143  	cfg.readEnvironmentVariables()
   144  	if !reflect.DeepEqual(cfg, cfgExpected) {
   145  		t.Fatalf("actual context does not match expected: diff(actual,expected) = %s", pretty.Diff(cfgExpected, cfg))
   146  	}
   147  
   148  	for _, envVar := range []string{
   149  		"COCKROACH_EXPERIMENTAL_LINEARIZABLE",
   150  		"COCKROACH_SCAN_INTERVAL",
   151  		"COCKROACH_SCAN_MIN_IDLE_TIME",
   152  		"COCKROACH_SCAN_MAX_IDLE_TIME",
   153  	} {
   154  		t.Run("invalid", func(t *testing.T) {
   155  			if err := os.Setenv(envVar, "abcd"); err != nil {
   156  				t.Fatal(err)
   157  			}
   158  			envutil.ClearEnvCache()
   159  
   160  			defer func() {
   161  				if recover() == nil {
   162  					t.Fatal("expected panic")
   163  				}
   164  			}()
   165  
   166  			cfg.readEnvironmentVariables()
   167  		})
   168  	}
   169  }
   170  
   171  func TestFilterGossipBootstrapResolvers(t *testing.T) {
   172  	defer leaktest.AfterTest(t)()
   173  
   174  	resolverSpecs := []string{
   175  		"127.0.0.1:9000",
   176  		"127.0.0.1:9001",
   177  		"localhost:9004",
   178  	}
   179  
   180  	resolvers := []resolver.Resolver{}
   181  	for _, rs := range resolverSpecs {
   182  		resolver, err := resolver.NewResolver(rs)
   183  		if err == nil {
   184  			resolvers = append(resolvers, resolver)
   185  		}
   186  	}
   187  	cfg := MakeConfig(context.Background(), cluster.MakeTestingClusterSettings())
   188  	cfg.GossipBootstrapResolvers = resolvers
   189  
   190  	listenAddr := util.MakeUnresolvedAddr("tcp", resolverSpecs[0])
   191  	advertAddr := util.MakeUnresolvedAddr("tcp", resolverSpecs[2])
   192  	filtered := cfg.FilterGossipBootstrapResolvers(context.Background(), &listenAddr, &advertAddr)
   193  	if len(filtered) != 1 {
   194  		t.Fatalf("expected one resolver; got %+v", filtered)
   195  	} else if filtered[0].Addr() != resolverSpecs[1] {
   196  		t.Fatalf("expected resolver to be %q; got %q", resolverSpecs[1], filtered[0].Addr())
   197  	}
   198  }
   199  
   200  func TestParseBootstrapResolvers(t *testing.T) {
   201  	defer leaktest.AfterTest(t)()
   202  
   203  	cfg := MakeConfig(context.Background(), cluster.MakeTestingClusterSettings())
   204  	const expectedName = "hello"
   205  
   206  	t.Run("nosrv", func(t *testing.T) {
   207  		// Ensure that a name in the join list becomes a resolver for that name,
   208  		// when SRV lookups are disabled.
   209  		cfg.JoinPreferSRVRecords = false
   210  		cfg.JoinList = append(base.JoinListType(nil), expectedName)
   211  
   212  		resolvers, err := cfg.parseGossipBootstrapResolvers(context.Background())
   213  		if err != nil {
   214  			t.Fatal(err)
   215  		}
   216  		if len(resolvers) != 1 {
   217  			t.Fatalf("expected 1 resolver, got %# v", pretty.Formatter(resolvers))
   218  		}
   219  		host, port, err := netutil.SplitHostPort(resolvers[0].Addr(), "UNKNOWN")
   220  		if err != nil {
   221  			t.Fatal(err)
   222  		}
   223  		if port == "UNKNOWN" {
   224  			t.Fatalf("expected port defined in resover: %# v", pretty.Formatter(resolvers))
   225  		}
   226  		if host != expectedName {
   227  			t.Errorf("expected name %q, got %q", expectedName, host)
   228  		}
   229  	})
   230  
   231  	t.Run("srv", func(t *testing.T) {
   232  		cfg.JoinPreferSRVRecords = true
   233  		cfg.JoinList = append(base.JoinListType(nil), "othername")
   234  
   235  		defer resolver.TestingOverrideSRVLookupFn(func(service, proto, name string) (string, []*net.SRV, error) {
   236  			return "cluster", []*net.SRV{{Target: expectedName, Port: 111}}, nil
   237  		})()
   238  
   239  		resolvers, err := cfg.parseGossipBootstrapResolvers(context.Background())
   240  		if err != nil {
   241  			t.Fatal(err)
   242  		}
   243  		if len(resolvers) != 1 {
   244  			t.Fatalf("expected 1 resolver, got %# v", pretty.Formatter(resolvers))
   245  		}
   246  		host, port, err := netutil.SplitHostPort(resolvers[0].Addr(), "UNKNOWN")
   247  		if err != nil {
   248  			t.Fatal(err)
   249  		}
   250  		if port == "UNKNOWN" {
   251  			t.Fatalf("expected port defined in resover: %# v", pretty.Formatter(resolvers))
   252  		}
   253  		if port != "111" {
   254  			t.Fatalf("expected port 111 from SRV, got %q", port)
   255  		}
   256  		if host != expectedName {
   257  			t.Errorf("expected name %q, got %q", expectedName, host)
   258  		}
   259  	})
   260  }