diff --git a/client/pkg/testutil/assert.go b/client/pkg/testutil/assert.go index e8e042021..7222a1700 100644 --- a/client/pkg/testutil/assert.go +++ b/client/pkg/testutil/assert.go @@ -29,10 +29,11 @@ func AssertEqual(t *testing.T, e, a interface{}, msg ...string) { return } s := "" - if len(msg) > 1 { + if len(msg) > 0 { s = msg[0] + ": " } - s = fmt.Sprintf("%sexpected %+v, got %+v", s, e, a) + + s = fmt.Sprintf("%s:expected %+v, got %+v", s, e, a) FatalStack(t, s) } diff --git a/client/pkg/transport/sockopt.go b/client/pkg/transport/sockopt.go index 38548ddd7..fe028c613 100644 --- a/client/pkg/transport/sockopt.go +++ b/client/pkg/transport/sockopt.go @@ -21,12 +21,12 @@ type SocketOpts struct { // in which case lock on data file could result in unexpected // condition. User should take caution to protect against lock race. // [1] https://man7.org/linux/man-pages/man7/socket.7.html - ReusePort bool + ReusePort bool `json:"reuse-port"` // ReuseAddress enables a socket option SO_REUSEADDR which allows // binding to an address in `TIME_WAIT` state. Useful to improve MTTR // in cases where etcd slow to restart due to excessive `TIME_WAIT`. // [1] https://man7.org/linux/man-pages/man7/socket.7.html - ReuseAddress bool + ReuseAddress bool `json:"reuse-address"` } func getControls(sopts *SocketOpts) Controls { diff --git a/server/embed/config.go b/server/embed/config.go index 380c0c3aa..eec169a85 100644 --- a/server/embed/config.go +++ b/server/embed/config.go @@ -252,7 +252,7 @@ type Config struct { GRPCKeepAliveTimeout time.Duration `json:"grpc-keepalive-timeout"` // SocketOpts are socket options passed to listener config. - SocketOpts transport.SocketOpts + SocketOpts transport.SocketOpts `json:"socket-options"` // PreVote is true to enable Raft Pre-Vote. // If enabled, Raft runs an additional election phase @@ -449,7 +449,10 @@ func NewConfig() *Config { GRPCKeepAliveInterval: DefaultGRPCKeepAliveInterval, GRPCKeepAliveTimeout: DefaultGRPCKeepAliveTimeout, - SocketOpts: transport.SocketOpts{}, + SocketOpts: transport.SocketOpts{ + ReusePort: false, + ReuseAddress: false, + }, TickMs: 100, ElectionMs: 1000, diff --git a/server/embed/config_test.go b/server/embed/config_test.go index b86d0d6c2..8fa52e38d 100644 --- a/server/embed/config_test.go +++ b/server/embed/config_test.go @@ -25,6 +25,7 @@ import ( "time" "go.etcd.io/etcd/client/pkg/v3/srv" + "go.etcd.io/etcd/client/pkg/v3/testutil" "go.etcd.io/etcd/client/pkg/v3/transport" "go.etcd.io/etcd/client/pkg/v3/types" @@ -40,12 +41,13 @@ func TestConfigFileOtherFields(t *testing.T) { ctls := securityConfig{TrustedCAFile: "cca", CertFile: "ccert", KeyFile: "ckey"} ptls := securityConfig{TrustedCAFile: "pca", CertFile: "pcert", KeyFile: "pkey"} yc := struct { - ClientSecurityCfgFile securityConfig `json:"client-transport-security"` - PeerSecurityCfgFile securityConfig `json:"peer-transport-security"` - ForceNewCluster bool `json:"force-new-cluster"` - Logger string `json:"logger"` - LogOutputs []string `json:"log-outputs"` - Debug bool `json:"debug"` + ClientSecurityCfgFile securityConfig `json:"client-transport-security"` + PeerSecurityCfgFile securityConfig `json:"peer-transport-security"` + ForceNewCluster bool `json:"force-new-cluster"` + Logger string `json:"logger"` + LogOutputs []string `json:"log-outputs"` + Debug bool `json:"debug"` + SocketOpts transport.SocketOpts `json:"socket-options"` }{ ctls, ptls, @@ -53,6 +55,9 @@ func TestConfigFileOtherFields(t *testing.T) { "zap", []string{"/dev/null"}, false, + transport.SocketOpts{ + ReusePort: true, + }, } b, err := yaml.Marshal(&yc) @@ -68,16 +73,18 @@ func TestConfigFileOtherFields(t *testing.T) { t.Fatal(err) } - if !cfg.ForceNewCluster { - t.Errorf("ForceNewCluster = %v, want %v", cfg.ForceNewCluster, true) - } - if !ctls.equals(&cfg.ClientTLSInfo) { t.Errorf("ClientTLS = %v, want %v", cfg.ClientTLSInfo, ctls) } if !ptls.equals(&cfg.PeerTLSInfo) { t.Errorf("PeerTLS = %v, want %v", cfg.PeerTLSInfo, ptls) } + + testutil.AssertEqual(t, true, cfg.ForceNewCluster, "ForceNewCluster does not match") + + testutil.AssertEqual(t, true, cfg.SocketOpts.ReusePort, "ReusePort does not match") + + testutil.AssertEqual(t, false, cfg.SocketOpts.ReuseAddress, "ReuseAddress does not match") } // TestUpdateDefaultClusterFromName ensures that etcd can start with 'etcd --name=abc'. diff --git a/test.sh b/test.sh index 308cde402..018340d55 100755 --- a/test.sh +++ b/test.sh @@ -1,35 +1,35 @@ #!/usr/bin/env bash # # Run all etcd tests -# ./test -# ./test -v +# ./test.sh +# ./test.sh -v # # # Run specified test pass # -# $ PASSES=unit ./test -# $ PASSES=integration ./test +# $ PASSES=unit ./test.sh +# $ PASSES=integration ./test.sh # # # Run tests for one package # Each pass has different default timeout, if you just run tests in one package or 1 test case then you can set TIMEOUT # flag for different expectation # -# $ PASSES=unit PKG=./wal TIMEOUT=1m ./test -# $ PASSES=integration PKG=./clientv3 TIMEOUT=1m ./test +# $ PASSES=unit PKG=./wal TIMEOUT=1m ./test.sh +# $ PASSES=integration PKG=./clientv3 TIMEOUT=1m ./test.sh # # Run specified unit tests in one package # To run all the tests with prefix of "TestNew", set "TESTCASE=TestNew "; # to run only "TestNew", set "TESTCASE="\bTestNew\b"" # -# $ PASSES=unit PKG=./wal TESTCASE=TestNew TIMEOUT=1m ./test -# $ PASSES=unit PKG=./wal TESTCASE="\bTestNew\b" TIMEOUT=1m ./test -# $ PASSES=integration PKG=./client/integration TESTCASE="\bTestV2NoRetryEOF\b" TIMEOUT=1m ./test +# $ PASSES=unit PKG=./wal TESTCASE=TestNew TIMEOUT=1m ./test.sh +# $ PASSES=unit PKG=./wal TESTCASE="\bTestNew\b" TIMEOUT=1m ./test.sh +# $ PASSES=integration PKG=./client/integration TESTCASE="\bTestV2NoRetryEOF\b" TIMEOUT=1m ./test.sh # # # Run code coverage # COVERDIR must either be a absolute path or a relative path to the etcd root -# $ COVERDIR=coverage PASSES="build build_cov cov" ./test +# $ COVERDIR=coverage PASSES="build build_cov cov" ./test.sh # $ go tool cover -html ./coverage/cover.out set -e set -o pipefail @@ -290,7 +290,7 @@ function cov_pass { fi if [ ! -f "bin/etcd_test" ]; then - log_error "etcd_test binary not found. Call: PASSES='build_cov' ./test" + log_error "etcd_test binary not found. Call: PASSES='build_cov' ./test.sh" return 255 fi