mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
Merge pull request #14281 from clarkfw/migrate-member-add-tests
tests: Migrate member add tests to common framework
This commit is contained in:
commit
f0c95cadea
@ -19,6 +19,9 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
clientv3 "go.etcd.io/etcd/client/v3"
|
||||
"go.etcd.io/etcd/server/v3/etcdserver"
|
||||
"go.etcd.io/etcd/tests/v3/framework/testutils"
|
||||
)
|
||||
|
||||
@ -52,3 +55,100 @@ func TestMemberList(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMemberAdd(t *testing.T) {
|
||||
testRunner.BeforeTest(t)
|
||||
|
||||
learnerTcs := []struct {
|
||||
name string
|
||||
learner bool
|
||||
}{
|
||||
{
|
||||
name: "NotLearner",
|
||||
learner: false,
|
||||
},
|
||||
{
|
||||
name: "Learner",
|
||||
learner: true,
|
||||
},
|
||||
}
|
||||
|
||||
quorumTcs := []struct {
|
||||
name string
|
||||
strictReconfigCheck bool
|
||||
waitForQuorum bool
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
name: "StrictReconfigCheck/WaitForQuorum",
|
||||
strictReconfigCheck: true,
|
||||
waitForQuorum: true,
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "StrictReconfigCheck/NoWaitForQuorum",
|
||||
strictReconfigCheck: true,
|
||||
waitForQuorum: false,
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "DisableStrictReconfigCheck/WaitForQuorum",
|
||||
strictReconfigCheck: false,
|
||||
waitForQuorum: true,
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "DisableStrictReconfigCheck/NoWaitForQuorum",
|
||||
strictReconfigCheck: false,
|
||||
waitForQuorum: false,
|
||||
expectError: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, learnerTc := range learnerTcs {
|
||||
for _, quorumTc := range quorumTcs {
|
||||
for _, clusterTc := range clusterTestCases {
|
||||
t.Run(learnerTc.name+"/"+quorumTc.name+"/"+clusterTc.name, func(t *testing.T) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
c := clusterTc.config
|
||||
if !quorumTc.strictReconfigCheck {
|
||||
c.DisableStrictReconfigCheck = true
|
||||
}
|
||||
clus := testRunner.NewCluster(ctx, t, c)
|
||||
defer clus.Close()
|
||||
cc := clus.Client()
|
||||
|
||||
testutils.ExecuteUntil(ctx, t, func() {
|
||||
var addResp *clientv3.MemberAddResponse
|
||||
var err error
|
||||
if quorumTc.waitForQuorum {
|
||||
time.Sleep(etcdserver.HealthInterval)
|
||||
}
|
||||
if learnerTc.learner {
|
||||
addResp, err = cc.MemberAddAsLearner(ctx, "newmember", []string{"http://localhost:123"})
|
||||
} else {
|
||||
addResp, err = cc.MemberAdd(ctx, "newmember", []string{"http://localhost:123"})
|
||||
}
|
||||
if quorumTc.expectError && c.ClusterSize > 1 {
|
||||
// calling MemberAdd/MemberAddAsLearner on a single node will not fail,
|
||||
// whether strictReconfigCheck or whether waitForQuorum
|
||||
require.ErrorContains(t, err, "etcdserver: unhealthy cluster")
|
||||
} else {
|
||||
require.NoError(t, err, "MemberAdd failed")
|
||||
if addResp.Member == nil {
|
||||
t.Fatalf("MemberAdd failed, expected: member != nil, got: member == nil")
|
||||
}
|
||||
if addResp.Member.ID == 0 {
|
||||
t.Fatalf("MemberAdd failed, expected: ID != 0, got: ID == 0")
|
||||
}
|
||||
if len(addResp.Member.PeerURLs) == 0 {
|
||||
t.Fatalf("MemberAdd failed, expected: non-empty PeerURLs, got: empty PeerURLs")
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -50,19 +50,7 @@ func TestCtlV3MemberRemoveClientAutoTLS(t *testing.T) {
|
||||
func TestCtlV3MemberRemovePeerTLS(t *testing.T) {
|
||||
testCtl(t, memberRemoveTest, withQuorum(), withDisableStrictReconfig(), withCfg(*e2e.NewConfigPeerTLS()))
|
||||
}
|
||||
func TestCtlV3MemberAdd(t *testing.T) { testCtl(t, memberAddTest) }
|
||||
func TestCtlV3MemberAddNoTLS(t *testing.T) { testCtl(t, memberAddTest, withCfg(*e2e.NewConfigNoTLS())) }
|
||||
func TestCtlV3MemberAddClientTLS(t *testing.T) {
|
||||
testCtl(t, memberAddTest, withCfg(*e2e.NewConfigClientTLS()))
|
||||
}
|
||||
func TestCtlV3MemberAddClientAutoTLS(t *testing.T) {
|
||||
testCtl(t, memberAddTest, withCfg(*e2e.NewConfigClientAutoTLS()))
|
||||
}
|
||||
func TestCtlV3MemberAddPeerTLS(t *testing.T) {
|
||||
testCtl(t, memberAddTest, withCfg(*e2e.NewConfigPeerTLS()))
|
||||
}
|
||||
func TestCtlV3MemberAddForLearner(t *testing.T) { testCtl(t, memberAddForLearnerTest) }
|
||||
func TestCtlV3MemberUpdate(t *testing.T) { testCtl(t, memberUpdateTest) }
|
||||
func TestCtlV3MemberUpdate(t *testing.T) { testCtl(t, memberUpdateTest) }
|
||||
func TestCtlV3MemberUpdateNoTLS(t *testing.T) {
|
||||
testCtl(t, memberUpdateTest, withCfg(*e2e.NewConfigNoTLS()))
|
||||
}
|
||||
@ -178,18 +166,6 @@ func ctlV3MemberRemove(cx ctlCtx, ep, memberID, clusterID string) error {
|
||||
return e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, fmt.Sprintf("%s removed from cluster %s", memberID, clusterID))
|
||||
}
|
||||
|
||||
func memberAddTest(cx ctlCtx) {
|
||||
if err := ctlV3MemberAdd(cx, fmt.Sprintf("http://localhost:%d", e2e.EtcdProcessBasePort+11), false); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func memberAddForLearnerTest(cx ctlCtx) {
|
||||
if err := ctlV3MemberAdd(cx, fmt.Sprintf("http://localhost:%d", e2e.EtcdProcessBasePort+11), true); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func ctlV3MemberAdd(cx ctlCtx, peerURL string, isLearner bool) error {
|
||||
cmdArgs := append(cx.PrefixArgs(), "member", "add", "newmember", fmt.Sprintf("--peer-urls=%s", peerURL))
|
||||
if isLearner {
|
||||
|
@ -76,14 +76,6 @@ func NewConfigClientTLS() *EtcdProcessClusterConfig {
|
||||
}
|
||||
}
|
||||
|
||||
func NewConfigClientBoth() *EtcdProcessClusterConfig {
|
||||
return &EtcdProcessClusterConfig{
|
||||
ClusterSize: 1,
|
||||
ClientTLS: ClientTLSAndNonTLS,
|
||||
InitialToken: "new",
|
||||
}
|
||||
}
|
||||
|
||||
func NewConfigClientAutoTLS() *EtcdProcessClusterConfig {
|
||||
return &EtcdProcessClusterConfig{
|
||||
ClusterSize: 1,
|
||||
|
@ -329,3 +329,11 @@ func (c integrationClient) Watch(ctx context.Context, key string, opts config.Wa
|
||||
|
||||
return c.Client.Watch(ctx, key, opOpts...)
|
||||
}
|
||||
|
||||
func (c integrationClient) MemberAdd(ctx context.Context, _ string, peerAddrs []string) (*clientv3.MemberAddResponse, error) {
|
||||
return c.Client.MemberAdd(ctx, peerAddrs)
|
||||
}
|
||||
|
||||
func (c integrationClient) MemberAddAsLearner(ctx context.Context, _ string, peerAddrs []string) (*clientv3.MemberAddResponse, error) {
|
||||
return c.Client.MemberAddAsLearner(ctx, peerAddrs)
|
||||
}
|
||||
|
@ -72,6 +72,8 @@ type Client interface {
|
||||
Txn(context context.Context, compares, ifSucess, ifFail []string, o config.TxnOptions) (*clientv3.TxnResponse, error)
|
||||
|
||||
MemberList(context context.Context) (*clientv3.MemberListResponse, error)
|
||||
MemberAdd(context context.Context, name string, peerAddrs []string) (*clientv3.MemberAddResponse, error)
|
||||
MemberAddAsLearner(context context.Context, name string, peerAddrs []string) (*clientv3.MemberAddResponse, error)
|
||||
|
||||
Watch(ctx context.Context, key string, opts config.WatchOptions) clientv3.WatchChan
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user