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 }