Split intengration/clientv3 tests into multiple packages
They used to take >10min with coverage, so were causing interrupted Travis runs. Know thay fit in 100-150s (together), thanks also to parallel execution.
This commit is contained in:
parent
88ee005a0f
commit
351bdb33c5
10
codecov.yml
10
codecov.yml
@ -6,13 +6,13 @@ fixes:
|
|||||||
- "go.etcd.io/etcd/api/v3/::api/"
|
- "go.etcd.io/etcd/api/v3/::api/"
|
||||||
- "go.etcd.io/etcd/client/v3/::client/v3/"
|
- "go.etcd.io/etcd/client/v3/::client/v3/"
|
||||||
- "go.etcd.io/etcd/client/v2/::client/v2/"
|
- "go.etcd.io/etcd/client/v2/::client/v2/"
|
||||||
- "go.etcd.io/etcd/etcdctl/v3::etcdctl/"
|
- "go.etcd.io/etcd/etcdctl/v3/::etcdctl/"
|
||||||
- "go.etcd.io/etcd/pkg/v3::pkg/"
|
- "go.etcd.io/etcd/pkg/v3/::pkg/"
|
||||||
- "go.etcd.io/etcd/raft/v3::raft/"
|
- "go.etcd.io/etcd/raft/v3/::raft/"
|
||||||
- "go.etcd.io/etcd/server/v3::server/"
|
- "go.etcd.io/etcd/server/v3/::server/"
|
||||||
|
|
||||||
ignore:
|
ignore:
|
||||||
- "**/*.pb.go"
|
- "**/*.pb.go"
|
||||||
- "**/*.pb.gw.go"
|
- "**/*.pb.gw.go"
|
||||||
- "tests/**/*"
|
- "tests/**/*"
|
||||||
- "go.etcd.io/etcd/tests/**/*"
|
- "go.etcd.io/etcd/tests/**/*"
|
||||||
|
@ -17,6 +17,7 @@ package testutil
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@ -91,3 +92,14 @@ func SkipTestIfShortMode(t testing.TB, reason string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExitInShortMode closes the current process (with 0) if the short test mode detected.
|
||||||
|
//
|
||||||
|
// To be used in Test-main, where test context (testing.TB) is not available.
|
||||||
|
//
|
||||||
|
// Requires custom env-variable (GOLANG_TEST_SHORT) apart of `go test --short flag`.
|
||||||
|
func ExitInShortMode(reason string) {
|
||||||
|
if os.Getenv("GOLANG_TEST_SHORT") == "true" {
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
6
test.sh
6
test.sh
@ -91,7 +91,7 @@ function run_unit_tests {
|
|||||||
local pkgs="${1:-./...}"
|
local pkgs="${1:-./...}"
|
||||||
shift 1
|
shift 1
|
||||||
# shellcheck disable=SC2086
|
# shellcheck disable=SC2086
|
||||||
go_test "${pkgs}" "parallel" : -short -timeout="${TIMEOUT:-3m}" "${COMMON_TEST_FLAGS[@]}" "${RUN_ARG[@]}" "$@"
|
GOLANG_TEST_SHORT=true go_test "${pkgs}" "parallel" : -short -timeout="${TIMEOUT:-3m}" "${COMMON_TEST_FLAGS[@]}" "${RUN_ARG[@]}" "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
function unit_pass {
|
function unit_pass {
|
||||||
@ -109,7 +109,7 @@ function integration_extra {
|
|||||||
|
|
||||||
function integration_pass {
|
function integration_pass {
|
||||||
local pkgs=${USERPKG:-"./integration/..."}
|
local pkgs=${USERPKG:-"./integration/..."}
|
||||||
run_for_module "tests" go_test "${pkgs}" "keep_going" : -timeout="${TIMEOUT:-30m}" "${COMMON_TEST_FLAGS[@]}" "${RUN_ARG[@]}" "$@" || return $?
|
run_for_module "tests" go_test "${pkgs}" "parallel" : -timeout="${TIMEOUT:-30m}" "${COMMON_TEST_FLAGS[@]}" "${RUN_ARG[@]}" "$@" || return $?
|
||||||
integration_extra "$@"
|
integration_extra "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,7 +307,7 @@ function cov_pass {
|
|||||||
|
|
||||||
log_callout "[$(date)] Collecting coverage from unit tests ..."
|
log_callout "[$(date)] Collecting coverage from unit tests ..."
|
||||||
for m in $(module_dirs); do
|
for m in $(module_dirs); do
|
||||||
run_for_module "${m}" go_test "./..." "parallel" "pkg_to_coverprofileflag unit_${m}" -short -timeout=30m \
|
GOLANG_TEST_SHORT=true run_for_module "${m}" go_test "./..." "parallel" "pkg_to_coverprofileflag unit_${m}" -short -timeout=30m \
|
||||||
"${gocov_build_flags[@]}" "$@" || failed="$failed unit"
|
"${gocov_build_flags[@]}" "$@" || failed="$failed unit"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ func (clus *Cluster) Run() {
|
|||||||
clus.rd = round
|
clus.rd = round
|
||||||
|
|
||||||
if err := clus.doRound(); err != nil {
|
if err := clus.doRound(); err != nil {
|
||||||
clus.lg.Warn(
|
clus.lg.Error(
|
||||||
"round FAIL",
|
"round FAIL",
|
||||||
zap.Int("round", clus.rd),
|
zap.Int("round", clus.rd),
|
||||||
zap.Int("case", clus.cs),
|
zap.Int("case", clus.cs),
|
||||||
@ -316,7 +316,7 @@ func (clus *Cluster) compact(rev int64, timeout time.Duration) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (clus *Cluster) failed() {
|
func (clus *Cluster) failed() {
|
||||||
clus.lg.Info(
|
clus.lg.Error(
|
||||||
"functional-tester FAIL",
|
"functional-tester FAIL",
|
||||||
zap.Int("round", clus.rd),
|
zap.Int("round", clus.rd),
|
||||||
zap.Int("case", clus.cs),
|
zap.Int("case", clus.cs),
|
||||||
|
@ -33,6 +33,8 @@ func forUnitTestsRunInMockedContext(mocking func(), example func()) {
|
|||||||
|
|
||||||
// TestMain sets up an etcd cluster if running the examples.
|
// TestMain sets up an etcd cluster if running the examples.
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
|
testutil.ExitInShortMode("Skipping: the tests require real cluster")
|
||||||
|
|
||||||
v := m.Run()
|
v := m.Run()
|
||||||
lazyCluster.Terminate()
|
lazyCluster.Terminate()
|
||||||
if v == 0 {
|
if v == 0 {
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
// +build !cluster_proxy
|
// +build !cluster_proxy
|
||||||
|
|
||||||
package clientv3test
|
package connectivity_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -25,6 +25,7 @@ import (
|
|||||||
"go.etcd.io/etcd/client/v3"
|
"go.etcd.io/etcd/client/v3"
|
||||||
"go.etcd.io/etcd/pkg/v3/testutil"
|
"go.etcd.io/etcd/pkg/v3/testutil"
|
||||||
"go.etcd.io/etcd/tests/v3/integration"
|
"go.etcd.io/etcd/tests/v3/integration"
|
||||||
|
"go.etcd.io/etcd/tests/v3/integration/clientv3"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -111,7 +112,7 @@ func TestBalancerUnderBlackholeKeepAliveWatch(t *testing.T) {
|
|||||||
func TestBalancerUnderBlackholeNoKeepAlivePut(t *testing.T) {
|
func TestBalancerUnderBlackholeNoKeepAlivePut(t *testing.T) {
|
||||||
testBalancerUnderBlackholeNoKeepAlive(t, func(cli *clientv3.Client, ctx context.Context) error {
|
testBalancerUnderBlackholeNoKeepAlive(t, func(cli *clientv3.Client, ctx context.Context) error {
|
||||||
_, err := cli.Put(ctx, "foo", "bar")
|
_, err := cli.Put(ctx, "foo", "bar")
|
||||||
if isClientTimeout(err) || isServerCtxTimeout(err) || err == rpctypes.ErrTimeout {
|
if clientv3test.IsClientTimeout(err) || clientv3test.IsServerCtxTimeout(err) || err == rpctypes.ErrTimeout {
|
||||||
return errExpected
|
return errExpected
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
@ -121,7 +122,7 @@ func TestBalancerUnderBlackholeNoKeepAlivePut(t *testing.T) {
|
|||||||
func TestBalancerUnderBlackholeNoKeepAliveDelete(t *testing.T) {
|
func TestBalancerUnderBlackholeNoKeepAliveDelete(t *testing.T) {
|
||||||
testBalancerUnderBlackholeNoKeepAlive(t, func(cli *clientv3.Client, ctx context.Context) error {
|
testBalancerUnderBlackholeNoKeepAlive(t, func(cli *clientv3.Client, ctx context.Context) error {
|
||||||
_, err := cli.Delete(ctx, "foo")
|
_, err := cli.Delete(ctx, "foo")
|
||||||
if isClientTimeout(err) || isServerCtxTimeout(err) || err == rpctypes.ErrTimeout {
|
if clientv3test.IsClientTimeout(err) || clientv3test.IsServerCtxTimeout(err) || err == rpctypes.ErrTimeout {
|
||||||
return errExpected
|
return errExpected
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
@ -134,7 +135,7 @@ func TestBalancerUnderBlackholeNoKeepAliveTxn(t *testing.T) {
|
|||||||
If(clientv3.Compare(clientv3.Version("foo"), "=", 0)).
|
If(clientv3.Compare(clientv3.Version("foo"), "=", 0)).
|
||||||
Then(clientv3.OpPut("foo", "bar")).
|
Then(clientv3.OpPut("foo", "bar")).
|
||||||
Else(clientv3.OpPut("foo", "baz")).Commit()
|
Else(clientv3.OpPut("foo", "baz")).Commit()
|
||||||
if isClientTimeout(err) || isServerCtxTimeout(err) || err == rpctypes.ErrTimeout {
|
if clientv3test.IsClientTimeout(err) || clientv3test.IsServerCtxTimeout(err) || err == rpctypes.ErrTimeout {
|
||||||
return errExpected
|
return errExpected
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
@ -144,7 +145,7 @@ func TestBalancerUnderBlackholeNoKeepAliveTxn(t *testing.T) {
|
|||||||
func TestBalancerUnderBlackholeNoKeepAliveLinearizableGet(t *testing.T) {
|
func TestBalancerUnderBlackholeNoKeepAliveLinearizableGet(t *testing.T) {
|
||||||
testBalancerUnderBlackholeNoKeepAlive(t, func(cli *clientv3.Client, ctx context.Context) error {
|
testBalancerUnderBlackholeNoKeepAlive(t, func(cli *clientv3.Client, ctx context.Context) error {
|
||||||
_, err := cli.Get(ctx, "a")
|
_, err := cli.Get(ctx, "a")
|
||||||
if isClientTimeout(err) || isServerCtxTimeout(err) || err == rpctypes.ErrTimeout {
|
if clientv3test.IsClientTimeout(err) || clientv3test.IsServerCtxTimeout(err) || err == rpctypes.ErrTimeout {
|
||||||
return errExpected
|
return errExpected
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
@ -154,7 +155,7 @@ func TestBalancerUnderBlackholeNoKeepAliveLinearizableGet(t *testing.T) {
|
|||||||
func TestBalancerUnderBlackholeNoKeepAliveSerializableGet(t *testing.T) {
|
func TestBalancerUnderBlackholeNoKeepAliveSerializableGet(t *testing.T) {
|
||||||
testBalancerUnderBlackholeNoKeepAlive(t, func(cli *clientv3.Client, ctx context.Context) error {
|
testBalancerUnderBlackholeNoKeepAlive(t, func(cli *clientv3.Client, ctx context.Context) error {
|
||||||
_, err := cli.Get(ctx, "a", clientv3.WithSerializable())
|
_, err := cli.Get(ctx, "a", clientv3.WithSerializable())
|
||||||
if isClientTimeout(err) || isServerCtxTimeout(err) {
|
if clientv3test.IsClientTimeout(err) || clientv3test.IsServerCtxTimeout(err) {
|
||||||
return errExpected
|
return errExpected
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
@ -186,7 +187,7 @@ func testBalancerUnderBlackholeNoKeepAlive(t *testing.T, op func(*clientv3.Clien
|
|||||||
defer cli.Close()
|
defer cli.Close()
|
||||||
|
|
||||||
// wait for eps[0] to be pinned
|
// wait for eps[0] to be pinned
|
||||||
mustWaitPinReady(t, cli)
|
clientv3test.MustWaitPinReady(t, cli)
|
||||||
|
|
||||||
// add all eps to list, so that when the original pined one fails
|
// add all eps to list, so that when the original pined one fails
|
||||||
// the client can switch to other available eps
|
// the client can switch to other available eps
|
@ -12,7 +12,7 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package clientv3test
|
package connectivity_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -26,21 +26,22 @@ import (
|
|||||||
"go.etcd.io/etcd/pkg/v3/testutil"
|
"go.etcd.io/etcd/pkg/v3/testutil"
|
||||||
"go.etcd.io/etcd/pkg/v3/transport"
|
"go.etcd.io/etcd/pkg/v3/transport"
|
||||||
"go.etcd.io/etcd/tests/v3/integration"
|
"go.etcd.io/etcd/tests/v3/integration"
|
||||||
|
clientv3test "go.etcd.io/etcd/tests/v3/integration/clientv3"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
testTLSInfo = transport.TLSInfo{
|
testTLSInfo = transport.TLSInfo{
|
||||||
KeyFile: "../../fixtures/server.key.insecure",
|
KeyFile: "../../../fixtures/server.key.insecure",
|
||||||
CertFile: "../../fixtures/server.crt",
|
CertFile: "../../../fixtures/server.crt",
|
||||||
TrustedCAFile: "../../fixtures/ca.crt",
|
TrustedCAFile: "../../../fixtures/ca.crt",
|
||||||
ClientCertAuth: true,
|
ClientCertAuth: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
testTLSInfoExpired = transport.TLSInfo{
|
testTLSInfoExpired = transport.TLSInfo{
|
||||||
KeyFile: "../fixtures-expired/server.key.insecure",
|
KeyFile: "../../fixtures-expired/server.key.insecure",
|
||||||
CertFile: "../fixtures-expired/server.crt",
|
CertFile: "../../fixtures-expired/server.crt",
|
||||||
TrustedCAFile: "../fixtures-expired/ca.crt",
|
TrustedCAFile: "../../fixtures-expired/ca.crt",
|
||||||
ClientCertAuth: true,
|
ClientCertAuth: true,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -62,7 +63,7 @@ func TestDialTLSExpired(t *testing.T) {
|
|||||||
DialOptions: []grpc.DialOption{grpc.WithBlock()},
|
DialOptions: []grpc.DialOption{grpc.WithBlock()},
|
||||||
TLS: tls,
|
TLS: tls,
|
||||||
})
|
})
|
||||||
if !isClientTimeout(err) {
|
if !clientv3test.IsClientTimeout(err) {
|
||||||
t.Fatalf("expected dial timeout error, got %v", err)
|
t.Fatalf("expected dial timeout error, got %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,7 +85,7 @@ func TestDialTLSNoConfig(t *testing.T) {
|
|||||||
c.Close()
|
c.Close()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
if !isClientTimeout(err) {
|
if !clientv3test.IsClientTimeout(err) {
|
||||||
t.Fatalf("expected dial timeout error, got %v", err)
|
t.Fatalf("expected dial timeout error, got %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
15
tests/integration/clientv3/connectivity/doc.go
Normal file
15
tests/integration/clientv3/connectivity/doc.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// Copyright 2021 The etcd Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package connectivity
|
15
tests/integration/clientv3/connectivity/main_test.go
Normal file
15
tests/integration/clientv3/connectivity/main_test.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// Copyright 2013 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package connectivity
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"go.etcd.io/etcd/pkg/v3/testutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
testutil.MustTestMainWithLeakDetection(m)
|
||||||
|
}
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
// +build !cluster_proxy
|
// +build !cluster_proxy
|
||||||
|
|
||||||
package clientv3test
|
package connectivity_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -27,6 +27,7 @@ import (
|
|||||||
"go.etcd.io/etcd/client/v3"
|
"go.etcd.io/etcd/client/v3"
|
||||||
"go.etcd.io/etcd/pkg/v3/testutil"
|
"go.etcd.io/etcd/pkg/v3/testutil"
|
||||||
"go.etcd.io/etcd/tests/v3/integration"
|
"go.etcd.io/etcd/tests/v3/integration"
|
||||||
|
"go.etcd.io/etcd/tests/v3/integration/clientv3"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -38,7 +39,7 @@ var errExpected = errors.New("expected error")
|
|||||||
func TestBalancerUnderNetworkPartitionPut(t *testing.T) {
|
func TestBalancerUnderNetworkPartitionPut(t *testing.T) {
|
||||||
testBalancerUnderNetworkPartition(t, func(cli *clientv3.Client, ctx context.Context) error {
|
testBalancerUnderNetworkPartition(t, func(cli *clientv3.Client, ctx context.Context) error {
|
||||||
_, err := cli.Put(ctx, "a", "b")
|
_, err := cli.Put(ctx, "a", "b")
|
||||||
if isClientTimeout(err) || isServerCtxTimeout(err) || err == rpctypes.ErrTimeout {
|
if clientv3test.IsClientTimeout(err) || clientv3test.IsServerCtxTimeout(err) || err == rpctypes.ErrTimeout {
|
||||||
return errExpected
|
return errExpected
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
@ -48,7 +49,7 @@ func TestBalancerUnderNetworkPartitionPut(t *testing.T) {
|
|||||||
func TestBalancerUnderNetworkPartitionDelete(t *testing.T) {
|
func TestBalancerUnderNetworkPartitionDelete(t *testing.T) {
|
||||||
testBalancerUnderNetworkPartition(t, func(cli *clientv3.Client, ctx context.Context) error {
|
testBalancerUnderNetworkPartition(t, func(cli *clientv3.Client, ctx context.Context) error {
|
||||||
_, err := cli.Delete(ctx, "a")
|
_, err := cli.Delete(ctx, "a")
|
||||||
if isClientTimeout(err) || isServerCtxTimeout(err) || err == rpctypes.ErrTimeout {
|
if clientv3test.IsClientTimeout(err) || clientv3test.IsServerCtxTimeout(err) || err == rpctypes.ErrTimeout {
|
||||||
return errExpected
|
return errExpected
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
@ -61,7 +62,7 @@ func TestBalancerUnderNetworkPartitionTxn(t *testing.T) {
|
|||||||
If(clientv3.Compare(clientv3.Version("foo"), "=", 0)).
|
If(clientv3.Compare(clientv3.Version("foo"), "=", 0)).
|
||||||
Then(clientv3.OpPut("foo", "bar")).
|
Then(clientv3.OpPut("foo", "bar")).
|
||||||
Else(clientv3.OpPut("foo", "baz")).Commit()
|
Else(clientv3.OpPut("foo", "baz")).Commit()
|
||||||
if isClientTimeout(err) || isServerCtxTimeout(err) || err == rpctypes.ErrTimeout {
|
if clientv3test.IsClientTimeout(err) || clientv3test.IsServerCtxTimeout(err) || err == rpctypes.ErrTimeout {
|
||||||
return errExpected
|
return errExpected
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
@ -74,7 +75,7 @@ func TestBalancerUnderNetworkPartitionTxn(t *testing.T) {
|
|||||||
func TestBalancerUnderNetworkPartitionLinearizableGetWithLongTimeout(t *testing.T) {
|
func TestBalancerUnderNetworkPartitionLinearizableGetWithLongTimeout(t *testing.T) {
|
||||||
testBalancerUnderNetworkPartition(t, func(cli *clientv3.Client, ctx context.Context) error {
|
testBalancerUnderNetworkPartition(t, func(cli *clientv3.Client, ctx context.Context) error {
|
||||||
_, err := cli.Get(ctx, "a")
|
_, err := cli.Get(ctx, "a")
|
||||||
if isClientTimeout(err) || isServerCtxTimeout(err) || err == rpctypes.ErrTimeout {
|
if clientv3test.IsClientTimeout(err) || clientv3test.IsServerCtxTimeout(err) || err == rpctypes.ErrTimeout {
|
||||||
return errExpected
|
return errExpected
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
@ -87,7 +88,7 @@ func TestBalancerUnderNetworkPartitionLinearizableGetWithLongTimeout(t *testing.
|
|||||||
func TestBalancerUnderNetworkPartitionLinearizableGetWithShortTimeout(t *testing.T) {
|
func TestBalancerUnderNetworkPartitionLinearizableGetWithShortTimeout(t *testing.T) {
|
||||||
testBalancerUnderNetworkPartition(t, func(cli *clientv3.Client, ctx context.Context) error {
|
testBalancerUnderNetworkPartition(t, func(cli *clientv3.Client, ctx context.Context) error {
|
||||||
_, err := cli.Get(ctx, "a")
|
_, err := cli.Get(ctx, "a")
|
||||||
if isClientTimeout(err) || isServerCtxTimeout(err) {
|
if clientv3test.IsClientTimeout(err) || clientv3test.IsServerCtxTimeout(err) {
|
||||||
return errExpected
|
return errExpected
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
@ -125,7 +126,7 @@ func testBalancerUnderNetworkPartition(t *testing.T, op func(*clientv3.Client, c
|
|||||||
defer cli.Close()
|
defer cli.Close()
|
||||||
|
|
||||||
// wait for eps[0] to be pinned
|
// wait for eps[0] to be pinned
|
||||||
mustWaitPinReady(t, cli)
|
clientv3test.MustWaitPinReady(t, cli)
|
||||||
|
|
||||||
// add other endpoints for later endpoint switch
|
// add other endpoints for later endpoint switch
|
||||||
cli.SetEndpoints(eps...)
|
cli.SetEndpoints(eps...)
|
||||||
@ -235,7 +236,7 @@ func testBalancerUnderNetworkPartitionWatch(t *testing.T, isolateLeader bool) {
|
|||||||
defer watchCli.Close()
|
defer watchCli.Close()
|
||||||
|
|
||||||
// wait for eps[target] to be pinned
|
// wait for eps[target] to be pinned
|
||||||
mustWaitPinReady(t, watchCli)
|
clientv3test.MustWaitPinReady(t, watchCli)
|
||||||
|
|
||||||
// add all eps to list, so that when the original pined one fails
|
// add all eps to list, so that when the original pined one fails
|
||||||
// the client can switch to other available eps
|
// the client can switch to other available eps
|
||||||
@ -290,7 +291,7 @@ func TestDropReadUnderNetworkPartition(t *testing.T) {
|
|||||||
defer cli.Close()
|
defer cli.Close()
|
||||||
|
|
||||||
// wait for eps[0] to be pinned
|
// wait for eps[0] to be pinned
|
||||||
mustWaitPinReady(t, cli)
|
clientv3test.MustWaitPinReady(t, cli)
|
||||||
|
|
||||||
// add other endpoints for later endpoint switch
|
// add other endpoints for later endpoint switch
|
||||||
cli.SetEndpoints(eps...)
|
cli.SetEndpoints(eps...)
|
@ -12,12 +12,11 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package clientv3test
|
package connectivity_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -25,9 +24,7 @@ import (
|
|||||||
"go.etcd.io/etcd/client/v3"
|
"go.etcd.io/etcd/client/v3"
|
||||||
"go.etcd.io/etcd/pkg/v3/testutil"
|
"go.etcd.io/etcd/pkg/v3/testutil"
|
||||||
"go.etcd.io/etcd/tests/v3/integration"
|
"go.etcd.io/etcd/tests/v3/integration"
|
||||||
|
"go.etcd.io/etcd/tests/v3/integration/clientv3"
|
||||||
"google.golang.org/grpc/codes"
|
|
||||||
"google.golang.org/grpc/status"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestBalancerUnderServerShutdownWatch expects that watch client
|
// TestBalancerUnderServerShutdownWatch expects that watch client
|
||||||
@ -53,7 +50,7 @@ func TestBalancerUnderServerShutdownWatch(t *testing.T) {
|
|||||||
defer watchCli.Close()
|
defer watchCli.Close()
|
||||||
|
|
||||||
// wait for eps[lead] to be pinned
|
// wait for eps[lead] to be pinned
|
||||||
mustWaitPinReady(t, watchCli)
|
clientv3test.MustWaitPinReady(t, watchCli)
|
||||||
|
|
||||||
// add all eps to list, so that when the original pined one fails
|
// add all eps to list, so that when the original pined one fails
|
||||||
// the client can switch to other available eps
|
// the client can switch to other available eps
|
||||||
@ -104,7 +101,7 @@ func TestBalancerUnderServerShutdownWatch(t *testing.T) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if isClientTimeout(err) || isServerCtxTimeout(err) || err == rpctypes.ErrTimeout || err == rpctypes.ErrTimeoutDueToLeaderFail {
|
if clientv3test.IsClientTimeout(err) || clientv3test.IsServerCtxTimeout(err) || err == rpctypes.ErrTimeout || err == rpctypes.ErrTimeoutDueToLeaderFail {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -163,7 +160,7 @@ func testBalancerUnderServerShutdownMutable(t *testing.T, op func(*clientv3.Clie
|
|||||||
defer cli.Close()
|
defer cli.Close()
|
||||||
|
|
||||||
// wait for eps[0] to be pinned
|
// wait for eps[0] to be pinned
|
||||||
mustWaitPinReady(t, cli)
|
clientv3test.MustWaitPinReady(t, cli)
|
||||||
|
|
||||||
// add all eps to list, so that when the original pined one fails
|
// add all eps to list, so that when the original pined one fails
|
||||||
// the client can switch to other available eps
|
// the client can switch to other available eps
|
||||||
@ -221,7 +218,7 @@ func testBalancerUnderServerShutdownImmutable(t *testing.T, op func(*clientv3.Cl
|
|||||||
defer cli.Close()
|
defer cli.Close()
|
||||||
|
|
||||||
// wait for eps[0] to be pinned
|
// wait for eps[0] to be pinned
|
||||||
mustWaitPinReady(t, cli)
|
clientv3test.MustWaitPinReady(t, cli)
|
||||||
|
|
||||||
// add all eps to list, so that when the original pined one fails
|
// add all eps to list, so that when the original pined one fails
|
||||||
// the client can switch to other available eps
|
// the client can switch to other available eps
|
||||||
@ -304,7 +301,7 @@ func testBalancerUnderServerStopInflightRangeOnRestart(t *testing.T, linearizabl
|
|||||||
defer cli.Close()
|
defer cli.Close()
|
||||||
|
|
||||||
// wait for eps[target] to be pinned
|
// wait for eps[target] to be pinned
|
||||||
mustWaitPinReady(t, cli)
|
clientv3test.MustWaitPinReady(t, cli)
|
||||||
|
|
||||||
// add all eps to list, so that when the original pined one fails
|
// add all eps to list, so that when the original pined one fails
|
||||||
// the client can switch to other available eps
|
// the client can switch to other available eps
|
||||||
@ -363,65 +360,3 @@ func testBalancerUnderServerStopInflightRangeOnRestart(t *testing.T, linearizabl
|
|||||||
case <-donec:
|
case <-donec:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// e.g. due to clock drifts in server-side,
|
|
||||||
// client context times out first in server-side
|
|
||||||
// while original client-side context is not timed out yet
|
|
||||||
func isServerCtxTimeout(err error) bool {
|
|
||||||
if err == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
ev, ok := status.FromError(err)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
code := ev.Code()
|
|
||||||
return code == codes.DeadlineExceeded && strings.Contains(err.Error(), "context deadline exceeded")
|
|
||||||
}
|
|
||||||
|
|
||||||
// In grpc v1.11.3+ dial timeouts can error out with transport.ErrConnClosing. Previously dial timeouts
|
|
||||||
// would always error out with context.DeadlineExceeded.
|
|
||||||
func isClientTimeout(err error) bool {
|
|
||||||
if err == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if err == context.DeadlineExceeded {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
ev, ok := status.FromError(err)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
code := ev.Code()
|
|
||||||
return code == codes.DeadlineExceeded
|
|
||||||
}
|
|
||||||
|
|
||||||
func isCanceled(err error) bool {
|
|
||||||
if err == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if err == context.Canceled {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
ev, ok := status.FromError(err)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
code := ev.Code()
|
|
||||||
return code == codes.Canceled
|
|
||||||
}
|
|
||||||
|
|
||||||
func isUnavailable(err error) bool {
|
|
||||||
if err == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if err == context.Canceled {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
ev, ok := status.FromError(err)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
code := ev.Code()
|
|
||||||
return code == codes.Unavailable
|
|
||||||
}
|
|
@ -42,6 +42,7 @@ func forUnitTestsRunInMockedContext(mocking func(), example func()) {
|
|||||||
|
|
||||||
// TestMain sets up an etcd cluster if running the examples.
|
// TestMain sets up an etcd cluster if running the examples.
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
|
testutil.ExitInShortMode("Skipping: the tests require real cluster")
|
||||||
v := m.Run()
|
v := m.Run()
|
||||||
lazyCluster.Terminate()
|
lazyCluster.Terminate()
|
||||||
|
|
||||||
|
@ -31,7 +31,6 @@ import (
|
|||||||
"go.etcd.io/etcd/client/v3"
|
"go.etcd.io/etcd/client/v3"
|
||||||
"go.etcd.io/etcd/pkg/v3/testutil"
|
"go.etcd.io/etcd/pkg/v3/testutil"
|
||||||
"go.etcd.io/etcd/tests/v3/integration"
|
"go.etcd.io/etcd/tests/v3/integration"
|
||||||
|
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
)
|
)
|
||||||
@ -838,7 +837,7 @@ func TestKVGetStoppedServerAndClose(t *testing.T) {
|
|||||||
// this Get fails and triggers an asynchronous connection retry
|
// this Get fails and triggers an asynchronous connection retry
|
||||||
_, err := cli.Get(ctx, "abc")
|
_, err := cli.Get(ctx, "abc")
|
||||||
cancel()
|
cancel()
|
||||||
if err != nil && !(isCanceled(err) || isClientTimeout(err)) {
|
if err != nil && !(IsCanceled(err) || IsClientTimeout(err)) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -860,7 +859,7 @@ func TestKVPutStoppedServerAndClose(t *testing.T) {
|
|||||||
// grpc finds out the original connection is down due to the member shutdown.
|
// grpc finds out the original connection is down due to the member shutdown.
|
||||||
_, err := cli.Get(ctx, "abc")
|
_, err := cli.Get(ctx, "abc")
|
||||||
cancel()
|
cancel()
|
||||||
if err != nil && !(isCanceled(err) || isClientTimeout(err)) {
|
if err != nil && !(IsCanceled(err) || IsClientTimeout(err)) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -868,7 +867,7 @@ func TestKVPutStoppedServerAndClose(t *testing.T) {
|
|||||||
// this Put fails and triggers an asynchronous connection retry
|
// this Put fails and triggers an asynchronous connection retry
|
||||||
_, err = cli.Put(ctx, "abc", "123")
|
_, err = cli.Put(ctx, "abc", "123")
|
||||||
cancel()
|
cancel()
|
||||||
if err != nil && !(isCanceled(err) || isClientTimeout(err) || isUnavailable(err)) {
|
if err != nil && !(IsCanceled(err) || IsClientTimeout(err) || IsUnavailable(err)) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
15
tests/integration/clientv3/lease/doc.go
Normal file
15
tests/integration/clientv3/lease/doc.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// Copyright 2021 The etcd Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package lease
|
@ -12,7 +12,7 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package clientv3test
|
package lease_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
@ -12,7 +12,7 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package clientv3test
|
package lease_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
15
tests/integration/clientv3/lease/main_test.go
Normal file
15
tests/integration/clientv3/lease/main_test.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// Copyright 2013 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package lease_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"go.etcd.io/etcd/pkg/v3/testutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
testutil.MustTestMainWithLeakDetection(m)
|
||||||
|
}
|
@ -133,7 +133,7 @@ func TestMaintenanceSnapshotError(t *testing.T) {
|
|||||||
time.Sleep(2 * time.Second)
|
time.Sleep(2 * time.Second)
|
||||||
|
|
||||||
_, err = io.Copy(ioutil.Discard, rc2)
|
_, err = io.Copy(ioutil.Discard, rc2)
|
||||||
if err != nil && !isClientTimeout(err) {
|
if err != nil && !IsClientTimeout(err) {
|
||||||
t.Errorf("expected client timeout, got %v", err)
|
t.Errorf("expected client timeout, got %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -192,7 +192,7 @@ func TestMaintenanceSnapshotErrorInflight(t *testing.T) {
|
|||||||
// 300ms left and expect timeout while snapshot reading is in progress
|
// 300ms left and expect timeout while snapshot reading is in progress
|
||||||
time.Sleep(700 * time.Millisecond)
|
time.Sleep(700 * time.Millisecond)
|
||||||
_, err = io.Copy(ioutil.Discard, rc2)
|
_, err = io.Copy(ioutil.Discard, rc2)
|
||||||
if err != nil && !isClientTimeout(err) {
|
if err != nil && !IsClientTimeout(err) {
|
||||||
t.Errorf("expected client timeout, got %v", err)
|
t.Errorf("expected client timeout, got %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,15 +16,18 @@ package clientv3test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go.etcd.io/etcd/client/v3"
|
"go.etcd.io/etcd/client/v3"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
// mustWaitPinReady waits up to 3-second until connection is up (pin endpoint).
|
// MustWaitPinReady waits up to 3-second until connection is up (pin endpoint).
|
||||||
// Fatal on time-out.
|
// Fatal on time-out.
|
||||||
func mustWaitPinReady(t *testing.T, cli *clientv3.Client) {
|
func MustWaitPinReady(t *testing.T, cli *clientv3.Client) {
|
||||||
// TODO: decrease timeout after balancer rewrite!!!
|
// TODO: decrease timeout after balancer rewrite!!!
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
_, err := cli.Get(ctx, "foo")
|
_, err := cli.Get(ctx, "foo")
|
||||||
@ -33,3 +36,67 @@ func mustWaitPinReady(t *testing.T, cli *clientv3.Client) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsServerCtxTimeout checks reason of the error.
|
||||||
|
// e.g. due to clock drifts in server-side,
|
||||||
|
// client context times out first in server-side
|
||||||
|
// while original client-side context is not timed out yet
|
||||||
|
func IsServerCtxTimeout(err error) bool {
|
||||||
|
if err == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
ev, ok := status.FromError(err)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
code := ev.Code()
|
||||||
|
return code == codes.DeadlineExceeded && strings.Contains(err.Error(), "context deadline exceeded")
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsClientTimeout checks reason of the error.
|
||||||
|
// In grpc v1.11.3+ dial timeouts can error out with transport.ErrConnClosing. Previously dial timeouts
|
||||||
|
// would always error out with context.DeadlineExceeded.
|
||||||
|
func IsClientTimeout(err error) bool {
|
||||||
|
if err == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if err == context.DeadlineExceeded {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
ev, ok := status.FromError(err)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
code := ev.Code()
|
||||||
|
return code == codes.DeadlineExceeded
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsCanceled(err error) bool {
|
||||||
|
if err == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if err == context.Canceled {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
ev, ok := status.FromError(err)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
code := ev.Code()
|
||||||
|
return code == codes.Canceled
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsUnavailable(err error) bool {
|
||||||
|
if err == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if err == context.Canceled {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
ev, ok := status.FromError(err)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
code := ev.Code()
|
||||||
|
return code == codes.Unavailable
|
||||||
|
}
|
||||||
|
@ -31,7 +31,6 @@ import (
|
|||||||
"go.etcd.io/etcd/pkg/v3/testutil"
|
"go.etcd.io/etcd/pkg/v3/testutil"
|
||||||
"go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc"
|
"go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc"
|
||||||
"go.etcd.io/etcd/tests/v3/integration"
|
"go.etcd.io/etcd/tests/v3/integration"
|
||||||
|
|
||||||
"google.golang.org/grpc/metadata"
|
"google.golang.org/grpc/metadata"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -768,7 +767,7 @@ func TestWatchErrConnClosed(t *testing.T) {
|
|||||||
defer close(donec)
|
defer close(donec)
|
||||||
ch := cli.Watch(context.TODO(), "foo")
|
ch := cli.Watch(context.TODO(), "foo")
|
||||||
|
|
||||||
if wr := <-ch; !isCanceled(wr.Err()) {
|
if wr := <-ch; !IsCanceled(wr.Err()) {
|
||||||
t.Errorf("expected context canceled, got %v", wr.Err())
|
t.Errorf("expected context canceled, got %v", wr.Err())
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
Loading…
Reference in New Issue
Block a user