mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
Merge pull request #16472 from ahrtr/expr_expect_20230825
test: support regular expression matching on the response
This commit is contained in:
commit
b6935cf2e9
@ -23,6 +23,7 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
@ -37,6 +38,11 @@ var (
|
||||
ErrProcessRunning = fmt.Errorf("process is still running")
|
||||
)
|
||||
|
||||
type ExpectedResponse struct {
|
||||
Value string
|
||||
IsRegularExpr bool
|
||||
}
|
||||
|
||||
type ExpectProcess struct {
|
||||
cfg expectConfig
|
||||
|
||||
@ -223,14 +229,29 @@ func (ep *ExpectProcess) ExpectFunc(ctx context.Context, f func(string) bool) (s
|
||||
}
|
||||
|
||||
// ExpectWithContext returns the first line containing the given string.
|
||||
func (ep *ExpectProcess) ExpectWithContext(ctx context.Context, s string) (string, error) {
|
||||
return ep.ExpectFunc(ctx, func(txt string) bool { return strings.Contains(txt, s) })
|
||||
func (ep *ExpectProcess) ExpectWithContext(ctx context.Context, s ExpectedResponse) (string, error) {
|
||||
var (
|
||||
expr *regexp.Regexp
|
||||
err error
|
||||
)
|
||||
if s.IsRegularExpr {
|
||||
expr, err = regexp.Compile(s.Value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
return ep.ExpectFunc(ctx, func(txt string) bool {
|
||||
if expr != nil {
|
||||
return expr.MatchString(txt)
|
||||
}
|
||||
return strings.Contains(txt, s.Value)
|
||||
})
|
||||
}
|
||||
|
||||
// Expect returns the first line containing the given string.
|
||||
// Deprecated: please use ExpectWithContext instead.
|
||||
func (ep *ExpectProcess) Expect(s string) (string, error) {
|
||||
return ep.ExpectWithContext(context.Background(), s)
|
||||
return ep.ExpectWithContext(context.Background(), ExpectedResponse{Value: s})
|
||||
}
|
||||
|
||||
// LineCount returns the number of recorded lines since
|
||||
|
@ -127,7 +127,7 @@ func TestEcho(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ctx := context.Background()
|
||||
l, eerr := ep.ExpectWithContext(ctx, "world")
|
||||
l, eerr := ep.ExpectWithContext(ctx, ExpectedResponse{Value: "world"})
|
||||
if eerr != nil {
|
||||
t.Fatal(eerr)
|
||||
}
|
||||
@ -138,7 +138,7 @@ func TestEcho(t *testing.T) {
|
||||
if cerr := ep.Close(); cerr != nil {
|
||||
t.Fatal(cerr)
|
||||
}
|
||||
if _, eerr = ep.ExpectWithContext(ctx, "..."); eerr == nil {
|
||||
if _, eerr = ep.ExpectWithContext(ctx, ExpectedResponse{Value: "..."}); eerr == nil {
|
||||
t.Fatalf("expected error on closed expect process")
|
||||
}
|
||||
}
|
||||
@ -149,7 +149,7 @@ func TestLineCount(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
wstr := "3"
|
||||
l, eerr := ep.ExpectWithContext(context.Background(), wstr)
|
||||
l, eerr := ep.ExpectWithContext(context.Background(), ExpectedResponse{Value: wstr})
|
||||
if eerr != nil {
|
||||
t.Fatal(eerr)
|
||||
}
|
||||
@ -172,7 +172,7 @@ func TestSend(t *testing.T) {
|
||||
if err := ep.Send("a\r"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := ep.ExpectWithContext(context.Background(), "b"); err != nil {
|
||||
if _, err := ep.ExpectWithContext(context.Background(), ExpectedResponse{Value: "b"}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := ep.Stop(); err != nil {
|
||||
@ -218,3 +218,59 @@ func TestExpectForFailFastCommand(t *testing.T) {
|
||||
_, err = ep.Expect("failed setting cipher list")
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestResponseMatchRegularExpr(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
mockOutput string
|
||||
expectedResp ExpectedResponse
|
||||
expectMatch bool
|
||||
}{
|
||||
{
|
||||
name: "exact match",
|
||||
mockOutput: "hello world",
|
||||
expectedResp: ExpectedResponse{Value: "hello world"},
|
||||
expectMatch: true,
|
||||
},
|
||||
{
|
||||
name: "not exact match",
|
||||
mockOutput: "hello world",
|
||||
expectedResp: ExpectedResponse{Value: "hello wld"},
|
||||
expectMatch: false,
|
||||
},
|
||||
{
|
||||
name: "match regular expression",
|
||||
mockOutput: "hello world",
|
||||
expectedResp: ExpectedResponse{Value: `.*llo\sworld`, IsRegularExpr: true},
|
||||
expectMatch: true,
|
||||
},
|
||||
{
|
||||
name: "not match regular expression",
|
||||
mockOutput: "hello world",
|
||||
expectedResp: ExpectedResponse{Value: `.*llo wrld`, IsRegularExpr: true},
|
||||
expectMatch: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
|
||||
ep, err := NewExpect("echo", "-n", tc.mockOutput)
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
l, err := ep.ExpectWithContext(ctx, tc.expectedResp)
|
||||
|
||||
if tc.expectMatch {
|
||||
require.Equal(t, tc.mockOutput, l)
|
||||
} else {
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
cerr := ep.Close()
|
||||
require.NoError(t, cerr)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ import (
|
||||
|
||||
"go.etcd.io/etcd/api/v3/etcdserverpb"
|
||||
clientv3 "go.etcd.io/etcd/client/v3"
|
||||
"go.etcd.io/etcd/pkg/v3/expect"
|
||||
"go.etcd.io/etcd/server/v3/storage/datadir"
|
||||
"go.etcd.io/etcd/server/v3/storage/mvcc/testutil"
|
||||
"go.etcd.io/etcd/tests/v3/framework/config"
|
||||
@ -334,11 +335,11 @@ func TestCompactHashCheckDetectCorruptionInterrupt(t *testing.T) {
|
||||
err = epc.Procs[slowCompactionNodeIndex].Restart(ctx)
|
||||
|
||||
// Wait until the node finished compaction and the leader finished compaction hash check
|
||||
_, err = epc.Procs[slowCompactionNodeIndex].Logs().ExpectWithContext(ctx, "finished scheduled compaction")
|
||||
_, err = epc.Procs[slowCompactionNodeIndex].Logs().ExpectWithContext(ctx, expect.ExpectedResponse{Value: "finished scheduled compaction"})
|
||||
require.NoError(t, err, "can't get log indicating finished scheduled compaction")
|
||||
|
||||
leaderIndex := epc.WaitLeader(t)
|
||||
_, err = epc.Procs[leaderIndex].Logs().ExpectWithContext(ctx, "finished compaction hash check")
|
||||
_, err = epc.Procs[leaderIndex].Logs().ExpectWithContext(ctx, expect.ExpectedResponse{Value: "finished compaction hash check"})
|
||||
require.NoError(t, err, "can't get log indicating finished compaction hash check")
|
||||
|
||||
alarmResponse, err := cc.AlarmList(ctx)
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"go.etcd.io/etcd/pkg/v3/expect"
|
||||
"go.etcd.io/etcd/tests/v3/framework/e2e"
|
||||
)
|
||||
|
||||
@ -58,25 +59,25 @@ func authEnable(cx ctlCtx) error {
|
||||
|
||||
func ctlV3AuthEnable(cx ctlCtx) error {
|
||||
cmdArgs := append(cx.PrefixArgs(), "auth", "enable")
|
||||
return e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, "Authentication Enabled")
|
||||
return e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, expect.ExpectedResponse{Value: "Authentication Enabled"})
|
||||
}
|
||||
|
||||
func ctlV3PutFailPerm(cx ctlCtx, key, val string) error {
|
||||
return e2e.SpawnWithExpectWithEnv(append(cx.PrefixArgs(), "put", key, val), cx.envMap, "permission denied")
|
||||
return e2e.SpawnWithExpectWithEnv(append(cx.PrefixArgs(), "put", key, val), cx.envMap, expect.ExpectedResponse{Value: "permission denied"})
|
||||
}
|
||||
|
||||
func authSetupTestUser(cx ctlCtx) {
|
||||
if err := ctlV3User(cx, []string{"add", "test-user", "--interactive=false"}, "User test-user created", []string{"pass"}); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
if err := e2e.SpawnWithExpectWithEnv(append(cx.PrefixArgs(), "role", "add", "test-role"), cx.envMap, "Role test-role created"); err != nil {
|
||||
if err := e2e.SpawnWithExpectWithEnv(append(cx.PrefixArgs(), "role", "add", "test-role"), cx.envMap, expect.ExpectedResponse{Value: "Role test-role created"}); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
if err := ctlV3User(cx, []string{"grant-role", "test-user", "test-role"}, "Role test-role is granted to user test-user", nil); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
cmd := append(cx.PrefixArgs(), "role", "grant-permission", "test-role", "readwrite", "foo")
|
||||
if err := e2e.SpawnWithExpectWithEnv(cmd, cx.envMap, "Role test-role updated"); err != nil {
|
||||
if err := e2e.SpawnWithExpectWithEnv(cmd, cx.envMap, expect.ExpectedResponse{Value: "Role test-role updated"}); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@ -118,7 +119,7 @@ func authTestCertCN(cx ctlCtx) {
|
||||
if err := ctlV3User(cx, []string{"add", "example.com", "--interactive=false"}, "User example.com created", []string{""}); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
if err := e2e.SpawnWithExpectWithEnv(append(cx.PrefixArgs(), "role", "add", "test-role"), cx.envMap, "Role test-role created"); err != nil {
|
||||
if err := e2e.SpawnWithExpectWithEnv(append(cx.PrefixArgs(), "role", "add", "test-role"), cx.envMap, expect.ExpectedResponse{Value: "Role test-role created"}); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
if err := ctlV3User(cx, []string{"grant-role", "example.com", "test-role"}, "Role test-role is granted to user example.com", nil); err != nil {
|
||||
@ -379,7 +380,7 @@ func certCNAndUsername(cx ctlCtx, noPassword bool) {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
}
|
||||
if err := e2e.SpawnWithExpectWithEnv(append(cx.PrefixArgs(), "role", "add", "test-role-cn"), cx.envMap, "Role test-role-cn created"); err != nil {
|
||||
if err := e2e.SpawnWithExpectWithEnv(append(cx.PrefixArgs(), "role", "add", "test-role-cn"), cx.envMap, expect.ExpectedResponse{Value: "Role test-role-cn created"}); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
if err := ctlV3User(cx, []string{"grant-role", "example.com", "test-role-cn"}, "Role test-role-cn is granted to user example.com", nil); err != nil {
|
||||
@ -428,9 +429,9 @@ func authTestCertCNAndUsernameNoPassword(cx ctlCtx) {
|
||||
|
||||
func ctlV3EndpointHealth(cx ctlCtx) error {
|
||||
cmdArgs := append(cx.PrefixArgs(), "endpoint", "health")
|
||||
lines := make([]string, cx.epc.Cfg.ClusterSize)
|
||||
lines := make([]expect.ExpectedResponse, cx.epc.Cfg.ClusterSize)
|
||||
for i := range lines {
|
||||
lines[i] = "is healthy"
|
||||
lines[i] = expect.ExpectedResponse{Value: "is healthy"}
|
||||
}
|
||||
return e2e.SpawnWithExpects(cmdArgs, cx.envMap, lines...)
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ package e2e
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"go.etcd.io/etcd/pkg/v3/expect"
|
||||
"go.etcd.io/etcd/tests/v3/framework/e2e"
|
||||
)
|
||||
|
||||
@ -35,16 +36,16 @@ func maintenanceInitKeys(cx ctlCtx) {
|
||||
|
||||
func ctlV3OnlineDefrag(cx ctlCtx) error {
|
||||
cmdArgs := append(cx.PrefixArgs(), "defrag")
|
||||
lines := make([]string, cx.epc.Cfg.ClusterSize)
|
||||
lines := make([]expect.ExpectedResponse, cx.epc.Cfg.ClusterSize)
|
||||
for i := range lines {
|
||||
lines[i] = "Finished defragmenting etcd member"
|
||||
lines[i] = expect.ExpectedResponse{Value: "Finished defragmenting etcd member"}
|
||||
}
|
||||
return e2e.SpawnWithExpects(cmdArgs, cx.envMap, lines...)
|
||||
}
|
||||
|
||||
func ctlV3OfflineDefrag(cx ctlCtx) error {
|
||||
cmdArgs := append(cx.PrefixArgsUtl(), "defrag", "--data-dir", cx.dataDir)
|
||||
lines := []string{"finished defragmenting directory"}
|
||||
lines := []expect.ExpectedResponse{{Value: "finished defragmenting directory"}}
|
||||
return e2e.SpawnWithExpects(cmdArgs, cx.envMap, lines...)
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"go.etcd.io/etcd/pkg/v3/expect"
|
||||
"go.etcd.io/etcd/tests/v3/framework/config"
|
||||
"go.etcd.io/etcd/tests/v3/framework/e2e"
|
||||
"go.etcd.io/etcd/tests/v3/framework/testutils"
|
||||
@ -160,7 +161,7 @@ func templateEndpoints(t *testing.T, pattern string, clus *e2e.EtcdProcessCluste
|
||||
|
||||
func assertAuthority(t *testing.T, expectAuthorityPattern string, clus *e2e.EtcdProcessCluster) {
|
||||
for i := range clus.Procs {
|
||||
line, _ := clus.Procs[i].Logs().ExpectWithContext(context.TODO(), `http2: decoded hpack field header field ":authority"`)
|
||||
line, _ := clus.Procs[i].Logs().ExpectWithContext(context.TODO(), expect.ExpectedResponse{Value: `http2: decoded hpack field header field ":authority"`})
|
||||
line = strings.TrimSuffix(line, "\n")
|
||||
line = strings.TrimSuffix(line, "\r")
|
||||
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"go.etcd.io/etcd/pkg/v3/expect"
|
||||
"go.etcd.io/etcd/tests/v3/framework/e2e"
|
||||
)
|
||||
|
||||
@ -178,7 +179,7 @@ func getFormatTest(cx ctlCtx) {
|
||||
cmdArgs = append(cmdArgs, "--print-value-only")
|
||||
}
|
||||
cmdArgs = append(cmdArgs, "abc")
|
||||
if err := e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, tt.wstr); err != nil {
|
||||
if err := e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, expect.ExpectedResponse{Value: tt.wstr}); err != nil {
|
||||
cx.t.Errorf("#%d: error (%v), wanted %v", i, err, tt.wstr)
|
||||
}
|
||||
}
|
||||
@ -216,28 +217,28 @@ func getKeysOnlyTest(cx ctlCtx) {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
cmdArgs := append(cx.PrefixArgs(), []string{"get", "--keys-only", "key"}...)
|
||||
if err := e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, "key"); err != nil {
|
||||
if err := e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, expect.ExpectedResponse{Value: "key"}); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
lines, err := e2e.SpawnWithExpectLines(ctx, cmdArgs, cx.envMap, "key")
|
||||
lines, err := e2e.SpawnWithExpectLines(ctx, cmdArgs, cx.envMap, expect.ExpectedResponse{Value: "key"})
|
||||
require.NoError(cx.t, err)
|
||||
require.NotContains(cx.t, lines, "val", "got value but passed --keys-only")
|
||||
}
|
||||
|
||||
func getCountOnlyTest(cx ctlCtx) {
|
||||
cmdArgs := append(cx.PrefixArgs(), []string{"get", "--count-only", "key", "--prefix", "--write-out=fields"}...)
|
||||
if err := e2e.SpawnWithExpects(cmdArgs, cx.envMap, "\"Count\" : 0"); err != nil {
|
||||
if err := e2e.SpawnWithExpects(cmdArgs, cx.envMap, expect.ExpectedResponse{Value: "\"Count\" : 0"}); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
if err := ctlV3Put(cx, "key", "val", ""); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
cmdArgs = append(cx.PrefixArgs(), []string{"get", "--count-only", "key", "--prefix", "--write-out=fields"}...)
|
||||
if err := e2e.SpawnWithExpects(cmdArgs, cx.envMap, "\"Count\" : 1"); err != nil {
|
||||
if err := e2e.SpawnWithExpects(cmdArgs, cx.envMap, expect.ExpectedResponse{Value: "\"Count\" : 1"}); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
if err := ctlV3Put(cx, "key1", "val", ""); err != nil {
|
||||
@ -247,14 +248,14 @@ func getCountOnlyTest(cx ctlCtx) {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
cmdArgs = append(cx.PrefixArgs(), []string{"get", "--count-only", "key", "--prefix", "--write-out=fields"}...)
|
||||
if err := e2e.SpawnWithExpects(cmdArgs, cx.envMap, "\"Count\" : 2"); err != nil {
|
||||
if err := e2e.SpawnWithExpects(cmdArgs, cx.envMap, expect.ExpectedResponse{Value: "\"Count\" : 2"}); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
if err := ctlV3Put(cx, "key2", "val", ""); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
cmdArgs = append(cx.PrefixArgs(), []string{"get", "--count-only", "key", "--prefix", "--write-out=fields"}...)
|
||||
if err := e2e.SpawnWithExpects(cmdArgs, cx.envMap, "\"Count\" : 3"); err != nil {
|
||||
if err := e2e.SpawnWithExpects(cmdArgs, cx.envMap, expect.ExpectedResponse{Value: "\"Count\" : 3"}); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
|
||||
@ -262,7 +263,7 @@ func getCountOnlyTest(cx ctlCtx) {
|
||||
defer cancel()
|
||||
|
||||
cmdArgs = append(cx.PrefixArgs(), []string{"get", "--count-only", "key3", "--prefix", "--write-out=fields"}...)
|
||||
lines, err := e2e.SpawnWithExpectLines(ctx, cmdArgs, cx.envMap, "\"Count\"")
|
||||
lines, err := e2e.SpawnWithExpectLines(ctx, cmdArgs, cx.envMap, expect.ExpectedResponse{Value: "\"Count\""})
|
||||
require.NoError(cx.t, err)
|
||||
require.NotContains(cx.t, lines, "\"Count\" : 3")
|
||||
}
|
||||
@ -341,7 +342,7 @@ func ctlV3Put(cx ctlCtx, key, value, leaseID string, flags ...string) error {
|
||||
if len(flags) != 0 {
|
||||
cmdArgs = append(cmdArgs, flags...)
|
||||
}
|
||||
return e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, "OK")
|
||||
return e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, expect.ExpectedResponse{Value: "OK"})
|
||||
}
|
||||
|
||||
type kv struct {
|
||||
@ -354,25 +355,15 @@ func ctlV3Get(cx ctlCtx, args []string, kvs ...kv) error {
|
||||
if !cx.quorum {
|
||||
cmdArgs = append(cmdArgs, "--consistency", "s")
|
||||
}
|
||||
var lines []string
|
||||
var lines []expect.ExpectedResponse
|
||||
for _, elem := range kvs {
|
||||
lines = append(lines, elem.key, elem.val)
|
||||
lines = append(lines, expect.ExpectedResponse{Value: elem.key}, expect.ExpectedResponse{Value: elem.val})
|
||||
}
|
||||
return e2e.SpawnWithExpects(cmdArgs, cx.envMap, lines...)
|
||||
}
|
||||
|
||||
// ctlV3GetWithErr runs "get" command expecting no output but error
|
||||
func ctlV3GetWithErr(cx ctlCtx, args []string, errs []string) error {
|
||||
cmdArgs := append(cx.PrefixArgs(), "get")
|
||||
cmdArgs = append(cmdArgs, args...)
|
||||
if !cx.quorum {
|
||||
cmdArgs = append(cmdArgs, "--consistency", "s")
|
||||
}
|
||||
return e2e.SpawnWithExpects(cmdArgs, cx.envMap, errs...)
|
||||
}
|
||||
|
||||
func ctlV3Del(cx ctlCtx, args []string, num int) error {
|
||||
cmdArgs := append(cx.PrefixArgs(), "del")
|
||||
cmdArgs = append(cmdArgs, args...)
|
||||
return e2e.SpawnWithExpects(cmdArgs, cx.envMap, fmt.Sprintf("%d", num))
|
||||
return e2e.SpawnWithExpects(cmdArgs, cx.envMap, expect.ExpectedResponse{Value: fmt.Sprintf("%d", num)})
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"go.etcd.io/etcd/pkg/v3/expect"
|
||||
"go.etcd.io/etcd/tests/v3/framework/e2e"
|
||||
)
|
||||
|
||||
@ -93,7 +94,7 @@ func ctlV3LeaseKeepAlive(cx ctlCtx, leaseID string) error {
|
||||
|
||||
func ctlV3LeaseRevoke(cx ctlCtx, leaseID string) error {
|
||||
cmdArgs := append(cx.PrefixArgs(), "lease", "revoke", leaseID)
|
||||
return e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, fmt.Sprintf("lease %s revoked", leaseID))
|
||||
return e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, expect.ExpectedResponse{Value: fmt.Sprintf("lease %s revoked", leaseID)})
|
||||
}
|
||||
|
||||
func ctlV3LeaseTimeToLive(cx ctlCtx, leaseID string, withKeys bool) error {
|
||||
@ -101,5 +102,5 @@ func ctlV3LeaseTimeToLive(cx ctlCtx, leaseID string, withKeys bool) error {
|
||||
if withKeys {
|
||||
cmdArgs = append(cmdArgs, "--keys")
|
||||
}
|
||||
return e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, fmt.Sprintf("lease %s granted with", leaseID))
|
||||
return e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, expect.ExpectedResponse{Value: fmt.Sprintf("lease %s granted with", leaseID)})
|
||||
}
|
||||
|
@ -114,16 +114,16 @@ func testLock(cx ctlCtx) {
|
||||
func testLockWithCmd(cx ctlCtx) {
|
||||
// exec command with zero exit code
|
||||
echoCmd := []string{"echo"}
|
||||
if err := ctlV3LockWithCmd(cx, echoCmd, ""); err != nil {
|
||||
if err := ctlV3LockWithCmd(cx, echoCmd, expect.ExpectedResponse{Value: ""}); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
|
||||
// exec command with non-zero exit code
|
||||
code := 3
|
||||
awkCmd := []string{"awk", fmt.Sprintf("BEGIN{exit %d}", code)}
|
||||
expect := fmt.Sprintf("Error: exit status %d", code)
|
||||
expect := expect.ExpectedResponse{Value: fmt.Sprintf("Error: exit status %d", code)}
|
||||
err := ctlV3LockWithCmd(cx, awkCmd, expect)
|
||||
require.ErrorContains(cx.t, err, expect)
|
||||
require.ErrorContains(cx.t, err, expect.Value)
|
||||
}
|
||||
|
||||
// ctlV3Lock creates a lock process with a channel listening for when it acquires the lock.
|
||||
@ -149,7 +149,7 @@ func ctlV3Lock(cx ctlCtx, name string) (*expect.ExpectProcess, <-chan string, er
|
||||
}
|
||||
|
||||
// ctlV3LockWithCmd creates a lock process to exec command.
|
||||
func ctlV3LockWithCmd(cx ctlCtx, execCmd []string, as ...string) error {
|
||||
func ctlV3LockWithCmd(cx ctlCtx, execCmd []string, as ...expect.ExpectedResponse) error {
|
||||
// use command as lock name
|
||||
cmdArgs := append(cx.PrefixArgs(), "lock", execCmd[0])
|
||||
cmdArgs = append(cmdArgs, execCmd...)
|
||||
|
@ -25,6 +25,7 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"go.etcd.io/etcd/api/v3/etcdserverpb"
|
||||
"go.etcd.io/etcd/pkg/v3/expect"
|
||||
"go.etcd.io/etcd/tests/v3/framework/e2e"
|
||||
)
|
||||
|
||||
@ -75,9 +76,9 @@ func memberListSerializableTest(cx ctlCtx) {
|
||||
|
||||
func ctlV3MemberList(cx ctlCtx) error {
|
||||
cmdArgs := append(cx.PrefixArgs(), "member", "list")
|
||||
lines := make([]string, cx.cfg.ClusterSize)
|
||||
lines := make([]expect.ExpectedResponse, cx.cfg.ClusterSize)
|
||||
for i := range lines {
|
||||
lines[i] = "started"
|
||||
lines[i] = expect.ExpectedResponse{Value: "started"}
|
||||
}
|
||||
return e2e.SpawnWithExpects(cmdArgs, cx.envMap, lines...)
|
||||
}
|
||||
@ -162,7 +163,7 @@ func memberListWithHexTest(cx ctlCtx) {
|
||||
|
||||
func ctlV3MemberRemove(cx ctlCtx, ep, memberID, clusterID string) error {
|
||||
cmdArgs := append(cx.prefixArgs([]string{ep}), "member", "remove", memberID)
|
||||
return e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, fmt.Sprintf("%s removed from cluster %s", memberID, clusterID))
|
||||
return e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, expect.ExpectedResponse{Value: fmt.Sprintf("%s removed from cluster %s", memberID, clusterID)})
|
||||
}
|
||||
|
||||
func memberAddTest(cx ctlCtx) {
|
||||
@ -186,7 +187,7 @@ func ctlV3MemberAdd(cx ctlCtx, peerURL string, isLearner bool) error {
|
||||
cmdArgs = append(cmdArgs, "--learner")
|
||||
asLearner = " as learner "
|
||||
}
|
||||
return e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, fmt.Sprintf(" added%sto cluster ", asLearner))
|
||||
return e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, expect.ExpectedResponse{Value: fmt.Sprintf(" added%sto cluster ", asLearner)})
|
||||
}
|
||||
|
||||
func memberUpdateTest(cx ctlCtx) {
|
||||
@ -204,5 +205,5 @@ func memberUpdateTest(cx ctlCtx) {
|
||||
|
||||
func ctlV3MemberUpdate(cx ctlCtx, memberID, peerURL string) error {
|
||||
cmdArgs := append(cx.PrefixArgs(), "member", "update", memberID, fmt.Sprintf("--peer-urls=%s", peerURL))
|
||||
return e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, " updated in cluster ")
|
||||
return e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, expect.ExpectedResponse{Value: " updated in cluster "})
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import (
|
||||
"go.etcd.io/etcd/client/pkg/v3/transport"
|
||||
"go.etcd.io/etcd/client/pkg/v3/types"
|
||||
clientv3 "go.etcd.io/etcd/client/v3"
|
||||
"go.etcd.io/etcd/pkg/v3/expect"
|
||||
"go.etcd.io/etcd/tests/v3/framework/e2e"
|
||||
)
|
||||
|
||||
@ -135,7 +136,7 @@ func testCtlV3MoveLeader(t *testing.T, cfg e2e.EtcdProcessClusterConfig, envVars
|
||||
for i, tc := range tests {
|
||||
prefix := cx.prefixArgs(tc.eps)
|
||||
cmdArgs := append(prefix, "move-leader", types.ID(transferee).String())
|
||||
err := e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, tc.expect)
|
||||
err := e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, expect.ExpectedResponse{Value: tc.expect})
|
||||
if tc.expectErr {
|
||||
require.ErrorContains(t, err, tc.expect)
|
||||
} else {
|
||||
|
@ -18,6 +18,7 @@ import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"go.etcd.io/etcd/pkg/v3/expect"
|
||||
"go.etcd.io/etcd/tests/v3/framework/e2e"
|
||||
)
|
||||
|
||||
@ -55,7 +56,7 @@ func ctlV3Role(cx ctlCtx, args []string, expStr string) error {
|
||||
cmdArgs := append(cx.PrefixArgs(), "role")
|
||||
cmdArgs = append(cmdArgs, args...)
|
||||
|
||||
return e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, expStr)
|
||||
return e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, expect.ExpectedResponse{Value: expStr})
|
||||
}
|
||||
|
||||
func ctlV3RoleGrantPermission(cx ctlCtx, rolename string, perm grantingPerm) error {
|
||||
|
@ -94,7 +94,7 @@ func snapshotCorruptTest(cx ctlCtx) {
|
||||
"--data-dir", datadir,
|
||||
fpath),
|
||||
cx.envMap,
|
||||
"expected sha256")
|
||||
expect.ExpectedResponse{Value: "expected sha256"})
|
||||
require.ErrorContains(cx.t, serr, "Error: expected sha256")
|
||||
}
|
||||
|
||||
@ -125,7 +125,7 @@ func snapshotStatusBeforeRestoreTest(cx ctlCtx) {
|
||||
"--data-dir", dataDir,
|
||||
fpath),
|
||||
cx.envMap,
|
||||
"added member")
|
||||
expect.ExpectedResponse{Value: "added member"})
|
||||
if serr != nil {
|
||||
cx.t.Fatal(serr)
|
||||
}
|
||||
@ -133,7 +133,7 @@ func snapshotStatusBeforeRestoreTest(cx ctlCtx) {
|
||||
|
||||
func ctlV3SnapshotSave(cx ctlCtx, fpath string) error {
|
||||
cmdArgs := append(cx.PrefixArgs(), "snapshot", "save", fpath)
|
||||
return e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, fmt.Sprintf("Snapshot saved at %s", fpath))
|
||||
return e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, expect.ExpectedResponse{Value: fmt.Sprintf("Snapshot saved at %s", fpath)})
|
||||
}
|
||||
|
||||
func getSnapshotStatus(cx ctlCtx, fpath string) (snapshot.Status, error) {
|
||||
@ -194,7 +194,7 @@ func testIssue6361(t *testing.T) {
|
||||
t.Log("Writing some keys...")
|
||||
kvs := []kv{{"foo1", "val1"}, {"foo2", "val2"}, {"foo3", "val3"}}
|
||||
for i := range kvs {
|
||||
if err = e2e.SpawnWithExpect(append(prefixArgs, "put", kvs[i].key, kvs[i].val), "OK"); err != nil {
|
||||
if err = e2e.SpawnWithExpect(append(prefixArgs, "put", kvs[i].key, kvs[i].val), expect.ExpectedResponse{Value: "OK"}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@ -204,7 +204,7 @@ func testIssue6361(t *testing.T) {
|
||||
t.Log("etcdctl saving snapshot...")
|
||||
if err = e2e.SpawnWithExpects(append(prefixArgs, "snapshot", "save", fpath),
|
||||
nil,
|
||||
fmt.Sprintf("Snapshot saved at %s", fpath),
|
||||
expect.ExpectedResponse{Value: fmt.Sprintf("Snapshot saved at %s", fpath)},
|
||||
); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -216,7 +216,14 @@ func testIssue6361(t *testing.T) {
|
||||
|
||||
newDataDir := filepath.Join(t.TempDir(), "test.data")
|
||||
t.Log("etcdctl restoring the snapshot...")
|
||||
err = e2e.SpawnWithExpect([]string{e2e.BinPath.Etcdutl, "snapshot", "restore", fpath, "--name", epc.Procs[0].Config().Name, "--initial-cluster", epc.Procs[0].Config().InitialCluster, "--initial-cluster-token", epc.Procs[0].Config().InitialToken, "--initial-advertise-peer-urls", epc.Procs[0].Config().PeerURL.String(), "--data-dir", newDataDir}, "added member")
|
||||
err = e2e.SpawnWithExpect([]string{
|
||||
e2e.BinPath.Etcdutl, "snapshot", "restore", fpath,
|
||||
"--name", epc.Procs[0].Config().Name,
|
||||
"--initial-cluster", epc.Procs[0].Config().InitialCluster,
|
||||
"--initial-cluster-token", epc.Procs[0].Config().InitialToken,
|
||||
"--initial-advertise-peer-urls", epc.Procs[0].Config().PeerURL.String(),
|
||||
"--data-dir", newDataDir},
|
||||
expect.ExpectedResponse{Value: "added member"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -234,7 +241,7 @@ func testIssue6361(t *testing.T) {
|
||||
|
||||
t.Log("Ensuring the restored member has the correct data...")
|
||||
for i := range kvs {
|
||||
if err = e2e.SpawnWithExpect(append(prefixArgs, "get", kvs[i].key), kvs[i].val); err != nil {
|
||||
if err = e2e.SpawnWithExpect(append(prefixArgs, "get", kvs[i].key), expect.ExpectedResponse{Value: kvs[i].val}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@ -242,7 +249,7 @@ func testIssue6361(t *testing.T) {
|
||||
t.Log("Adding new member into the cluster")
|
||||
clientURL := fmt.Sprintf("http://localhost:%d", e2e.EtcdProcessBasePort+30)
|
||||
peerURL := fmt.Sprintf("http://localhost:%d", e2e.EtcdProcessBasePort+31)
|
||||
err = e2e.SpawnWithExpect(append(prefixArgs, "member", "add", "newmember", fmt.Sprintf("--peer-urls=%s", peerURL)), " added to cluster ")
|
||||
err = e2e.SpawnWithExpect(append(prefixArgs, "member", "add", "newmember", fmt.Sprintf("--peer-urls=%s", peerURL)), expect.ExpectedResponse{Value: " added to cluster "})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -271,7 +278,7 @@ func testIssue6361(t *testing.T) {
|
||||
|
||||
t.Log("Ensuring added member has data from incoming snapshot...")
|
||||
for i := range kvs {
|
||||
if err = e2e.SpawnWithExpect(append(prefixArgs, "get", kvs[i].key), kvs[i].val); err != nil {
|
||||
if err = e2e.SpawnWithExpect(append(prefixArgs, "get", kvs[i].key), expect.ExpectedResponse{Value: kvs[i].val}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@ -350,7 +357,7 @@ func TestRestoreCompactionRevBump(t *testing.T) {
|
||||
|
||||
t.Log("etcdctl saving snapshot...")
|
||||
cmdPrefix := []string{e2e.BinPath.Etcdctl, "--endpoints", strings.Join(epc.EndpointsGRPC(), ",")}
|
||||
require.NoError(t, e2e.SpawnWithExpects(append(cmdPrefix, "snapshot", "save", fpath), nil, fmt.Sprintf("Snapshot saved at %s", fpath)))
|
||||
require.NoError(t, e2e.SpawnWithExpects(append(cmdPrefix, "snapshot", "save", fpath), nil, expect.ExpectedResponse{Value: fmt.Sprintf("Snapshot saved at %s", fpath)}))
|
||||
|
||||
// add some more kvs that are not in the snapshot that will be lost after restore
|
||||
unsnappedKVs := []testutils.KV{{Key: "unsnapped1", Val: "one"}, {Key: "unsnapped2", Val: "two"}, {Key: "unsnapped3", Val: "three"}}
|
||||
@ -378,7 +385,7 @@ func TestRestoreCompactionRevBump(t *testing.T) {
|
||||
"--bump-revision", fmt.Sprintf("%d", bumpAmount),
|
||||
"--mark-compacted",
|
||||
"--data-dir", newDataDir,
|
||||
}, "added member")
|
||||
}, expect.ExpectedResponse{Value: "added member"})
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Log("(Re)starting the etcd member using the restored snapshot...")
|
||||
|
@ -26,6 +26,7 @@ import (
|
||||
|
||||
"go.etcd.io/etcd/api/v3/version"
|
||||
"go.etcd.io/etcd/client/pkg/v3/testutil"
|
||||
"go.etcd.io/etcd/pkg/v3/expect"
|
||||
"go.etcd.io/etcd/pkg/v3/flags"
|
||||
"go.etcd.io/etcd/tests/v3/framework/e2e"
|
||||
)
|
||||
@ -88,7 +89,7 @@ func versionTest(cx ctlCtx) {
|
||||
func clusterVersionTest(cx ctlCtx, expected string) {
|
||||
var err error
|
||||
for i := 0; i < 35; i++ {
|
||||
if err = e2e.CURLGet(cx.epc, e2e.CURLReq{Endpoint: "/version", Expected: expected}); err != nil {
|
||||
if err = e2e.CURLGet(cx.epc, e2e.CURLReq{Endpoint: "/version", Expected: expect.ExpectedResponse{Value: expected}}); err != nil {
|
||||
cx.t.Logf("#%d: v3 is not ready yet (%v)", i, err)
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
continue
|
||||
@ -102,7 +103,7 @@ func clusterVersionTest(cx ctlCtx, expected string) {
|
||||
|
||||
func ctlV3Version(cx ctlCtx) error {
|
||||
cmdArgs := append(cx.PrefixArgs(), "version")
|
||||
return e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, version.Version)
|
||||
return e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, expect.ExpectedResponse{Value: version.Version})
|
||||
}
|
||||
|
||||
// TestCtlV3DialWithHTTPScheme ensures that client handles Endpoints with HTTPS scheme.
|
||||
@ -112,7 +113,7 @@ func TestCtlV3DialWithHTTPScheme(t *testing.T) {
|
||||
|
||||
func dialWithSchemeTest(cx ctlCtx) {
|
||||
cmdArgs := append(cx.prefixArgs(cx.epc.EndpointsGRPC()), "put", "foo", "bar")
|
||||
if err := e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, "OK"); err != nil {
|
||||
if err := e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, expect.ExpectedResponse{Value: "OK"}); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import (
|
||||
"go.etcd.io/etcd/client/pkg/v3/testutil"
|
||||
"go.etcd.io/etcd/client/pkg/v3/transport"
|
||||
"go.etcd.io/etcd/client/v2"
|
||||
"go.etcd.io/etcd/pkg/v3/expect"
|
||||
"go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp"
|
||||
"go.etcd.io/etcd/tests/v3/framework/e2e"
|
||||
"go.etcd.io/etcd/tests/v3/framework/integration"
|
||||
@ -73,10 +74,10 @@ func testClusterUsingDiscovery(t *testing.T, size int, peerTLS bool) {
|
||||
defer c.Close()
|
||||
|
||||
kubectl := []string{e2e.BinPath.Etcdctl, "--endpoints", strings.Join(c.EndpointsGRPC(), ",")}
|
||||
if err := e2e.SpawnWithExpect(append(kubectl, "put", "key", "value"), "OK"); err != nil {
|
||||
if err := e2e.SpawnWithExpect(append(kubectl, "put", "key", "value"), expect.ExpectedResponse{Value: "OK"}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := e2e.SpawnWithExpect(append(kubectl, "get", "key"), "value"); err != nil {
|
||||
if err := e2e.SpawnWithExpect(append(kubectl, "get", "key"), expect.ExpectedResponse{Value: "value"}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"go.etcd.io/etcd/pkg/v3/expect"
|
||||
"go.etcd.io/etcd/tests/v3/framework/e2e"
|
||||
)
|
||||
|
||||
@ -76,10 +77,10 @@ func testClusterUsingV3Discovery(t *testing.T, discoveryClusterSize, targetClust
|
||||
|
||||
// step 4: sanity test on the etcd cluster
|
||||
etcdctl := []string{e2e.BinPath.Etcdctl, "--endpoints", strings.Join(epc.EndpointsGRPC(), ",")}
|
||||
if err := e2e.SpawnWithExpect(append(etcdctl, "put", "key", "value"), "OK"); err != nil {
|
||||
if err := e2e.SpawnWithExpect(append(etcdctl, "put", "key", "value"), expect.ExpectedResponse{Value: "OK"}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := e2e.SpawnWithExpect(append(etcdctl, "get", "key"), "value"); err != nil {
|
||||
if err := e2e.SpawnWithExpect(append(etcdctl, "get", "key"), expect.ExpectedResponse{Value: "value"}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
@ -296,7 +296,7 @@ func TestGrpcproxyAndCommonName(t *testing.T) {
|
||||
"--cacert", e2e.CaPath,
|
||||
}
|
||||
|
||||
err := e2e.SpawnWithExpect(argsWithNonEmptyCN, "cert has non empty Common Name")
|
||||
err := e2e.SpawnWithExpect(argsWithNonEmptyCN, expect.ExpectedResponse{Value: "cert has non empty Common Name"})
|
||||
require.ErrorContains(t, err, "cert has non empty Common Name")
|
||||
|
||||
p, err := e2e.SpawnCmd(argsWithEmptyCN, nil)
|
||||
|
@ -23,6 +23,7 @@ import (
|
||||
|
||||
"go.etcd.io/etcd/api/v3/version"
|
||||
"go.etcd.io/etcd/client/pkg/v3/fileutil"
|
||||
"go.etcd.io/etcd/pkg/v3/expect"
|
||||
"go.etcd.io/etcd/tests/v3/framework/e2e"
|
||||
)
|
||||
|
||||
@ -97,7 +98,7 @@ func TestReleaseUpgrade(t *testing.T) {
|
||||
// new cluster version needs more time to upgrade
|
||||
ver := version.Cluster(version.Version)
|
||||
for i := 0; i < 7; i++ {
|
||||
if err = e2e.CURLGet(epc, e2e.CURLReq{Endpoint: "/version", Expected: `"etcdcluster":"` + ver}); err != nil {
|
||||
if err = e2e.CURLGet(epc, e2e.CURLReq{Endpoint: "/version", Expected: expect.ExpectedResponse{Value: `"etcdcluster":"` + ver}}); err != nil {
|
||||
t.Logf("#%d: %v is not ready yet (%v)", i, ver, err)
|
||||
time.Sleep(time.Second)
|
||||
continue
|
||||
|
@ -42,7 +42,7 @@ func TestGateway(t *testing.T) {
|
||||
p.Close()
|
||||
}()
|
||||
|
||||
err = e2e.SpawnWithExpect([]string{e2e.BinPath.Etcdctl, "--endpoints=" + defaultGatewayEndpoint, "put", "foo", "bar"}, "OK\r\n")
|
||||
err = e2e.SpawnWithExpect([]string{e2e.BinPath.Etcdctl, "--endpoints=" + defaultGatewayEndpoint, "put", "foo", "bar"}, expect.ExpectedResponse{Value: "OK\r\n"})
|
||||
if err != nil {
|
||||
t.Errorf("failed to finish put request through gateway: %v", err)
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"go.etcd.io/etcd/api/v3/version"
|
||||
"go.etcd.io/etcd/pkg/v3/expect"
|
||||
"go.etcd.io/etcd/tests/v3/framework/e2e"
|
||||
)
|
||||
|
||||
@ -63,7 +64,7 @@ func metricsTest(cx ctlCtx) {
|
||||
if err := ctlV3Watch(cx, []string{"k", "--rev", "1"}, []kvExec{{key: "k", val: "v"}}...); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
if err := e2e.CURLGet(cx.epc, e2e.CURLReq{Endpoint: test.endpoint, Expected: test.expected}); err != nil {
|
||||
if err := e2e.CURLGet(cx.epc, e2e.CURLReq{Endpoint: test.endpoint, Expected: expect.ExpectedResponse{Value: test.expected}}); err != nil {
|
||||
cx.t.Fatalf("failed get with curl (%v)", err)
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ import (
|
||||
|
||||
"go.etcd.io/etcd/api/v3/version"
|
||||
"go.etcd.io/etcd/client/pkg/v3/fileutil"
|
||||
"go.etcd.io/etcd/pkg/v3/expect"
|
||||
"go.etcd.io/etcd/server/v3/storage/backend"
|
||||
"go.etcd.io/etcd/server/v3/storage/schema"
|
||||
"go.etcd.io/etcd/tests/v3/framework/e2e"
|
||||
@ -139,7 +140,7 @@ func TestEtctlutlMigrate(t *testing.T) {
|
||||
|
||||
t.Log("Write keys to ensure wal snapshot is created and all v3.5 fields are set...")
|
||||
for i := 0; i < 10; i++ {
|
||||
if err = e2e.SpawnWithExpect(append(prefixArgs, "put", fmt.Sprintf("%d", i), "value"), "OK"); err != nil {
|
||||
if err = e2e.SpawnWithExpect(append(prefixArgs, "put", fmt.Sprintf("%d", i), "value"), expect.ExpectedResponse{Value: "OK"}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@ -155,7 +156,7 @@ func TestEtctlutlMigrate(t *testing.T) {
|
||||
if tc.force {
|
||||
args = append(args, "--force")
|
||||
}
|
||||
err = e2e.SpawnWithExpect(args, tc.expectLogsSubString)
|
||||
err = e2e.SpawnWithExpect(args, expect.ExpectedResponse{Value: tc.expectLogsSubString})
|
||||
if err != nil {
|
||||
if tc.expectLogsSubString != "" {
|
||||
require.ErrorContains(t, err, tc.expectLogsSubString)
|
||||
|
@ -29,6 +29,7 @@ import (
|
||||
"go.uber.org/zap/zaptest"
|
||||
|
||||
"go.etcd.io/etcd/client/pkg/v3/fileutil"
|
||||
"go.etcd.io/etcd/pkg/v3/expect"
|
||||
"go.etcd.io/etcd/server/v3/etcdserver"
|
||||
"go.etcd.io/etcd/server/v3/etcdserver/api/membership"
|
||||
"go.etcd.io/etcd/server/v3/etcdserver/api/snap"
|
||||
@ -58,7 +59,7 @@ func createV2store(t testing.TB, dataDirPath string) string {
|
||||
for i := 0; i < 10; i++ {
|
||||
if err := e2e.CURLPut(epc, e2e.CURLReq{
|
||||
Endpoint: "/v2/keys/foo", Value: "bar" + fmt.Sprint(i),
|
||||
Expected: `{"action":"set","node":{"key":"/foo","value":"bar` + fmt.Sprint(i)}); err != nil {
|
||||
Expected: expect.ExpectedResponse{Value: `{"action":"set","node":{"key":"/foo","value":"bar` + fmt.Sprint(i)}}); err != nil {
|
||||
t.Fatalf("failed put with curl (%v)", err)
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"go.etcd.io/etcd/api/v3/version"
|
||||
"go.etcd.io/etcd/pkg/v3/expect"
|
||||
"go.etcd.io/etcd/tests/v3/framework/e2e"
|
||||
)
|
||||
|
||||
@ -49,7 +50,7 @@ func testV3CurlCipherSuites(t *testing.T, valid bool) {
|
||||
func cipherSuiteTestValid(cx ctlCtx) {
|
||||
if err := e2e.CURLGet(cx.epc, e2e.CURLReq{
|
||||
Endpoint: "/metrics",
|
||||
Expected: fmt.Sprintf(`etcd_server_version{server_version="%s"} 1`, version.Version),
|
||||
Expected: expect.ExpectedResponse{Value: fmt.Sprintf(`etcd_server_version{server_version="%s"} 1`, version.Version)},
|
||||
Ciphers: "ECDHE-RSA-AES128-GCM-SHA256", // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
|
||||
}); err != nil {
|
||||
require.ErrorContains(cx.t, err, fmt.Sprintf(`etcd_server_version{server_version="%s"} 1`, version.Version))
|
||||
@ -59,7 +60,7 @@ func cipherSuiteTestValid(cx ctlCtx) {
|
||||
func cipherSuiteTestMismatch(cx ctlCtx) {
|
||||
err := e2e.CURLGet(cx.epc, e2e.CURLReq{
|
||||
Endpoint: "/metrics",
|
||||
Expected: "failed setting cipher list",
|
||||
Expected: expect.ExpectedResponse{Value: "failed setting cipher list"},
|
||||
Ciphers: "ECDHE-RSA-DES-CBC3-SHA", // TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
|
||||
})
|
||||
require.ErrorContains(cx.t, err, "curl: (59) failed setting cipher list")
|
||||
|
@ -29,6 +29,7 @@ import (
|
||||
|
||||
pb "go.etcd.io/etcd/api/v3/etcdserverpb"
|
||||
"go.etcd.io/etcd/client/pkg/v3/testutil"
|
||||
"go.etcd.io/etcd/pkg/v3/expect"
|
||||
"go.etcd.io/etcd/tests/v3/framework/e2e"
|
||||
"go.etcd.io/etcd/tests/v3/framework/testutils"
|
||||
)
|
||||
@ -166,7 +167,7 @@ func submitConcurrentWatch(cx ctlCtx, number int, wgDone *sync.WaitGroup, closeC
|
||||
|
||||
// make sure that watch request has been created
|
||||
expectedLine := `"created":true}}`
|
||||
_, lerr := proc.ExpectWithContext(context.TODO(), expectedLine)
|
||||
_, lerr := proc.ExpectWithContext(context.TODO(), expect.ExpectedResponse{Value: expectedLine})
|
||||
if lerr != nil {
|
||||
return fmt.Errorf("%v %v (expected %q). Try EXPECT_DEBUG=TRUE", args, lerr, expectedLine)
|
||||
}
|
||||
@ -213,7 +214,7 @@ func submitRangeAfterConcurrentWatch(cx ctlCtx, expectedValue string) {
|
||||
}
|
||||
|
||||
cx.t.Log("Submitting range request...")
|
||||
if err := e2e.CURLPost(cx.epc, e2e.CURLReq{Endpoint: "/v3/kv/range", Value: string(rangeData), Expected: expectedValue, Timeout: 5}); err != nil {
|
||||
if err := e2e.CURLPost(cx.epc, e2e.CURLReq{Endpoint: "/v3/kv/range", Value: string(rangeData), Expected: expect.ExpectedResponse{Value: expectedValue}, Timeout: 5}); err != nil {
|
||||
require.ErrorContains(cx.t, err, expectedValue)
|
||||
}
|
||||
cx.t.Log("range request done")
|
||||
|
@ -30,6 +30,7 @@ import (
|
||||
pb "go.etcd.io/etcd/api/v3/etcdserverpb"
|
||||
"go.etcd.io/etcd/api/v3/v3rpc/rpctypes"
|
||||
"go.etcd.io/etcd/client/pkg/v3/testutil"
|
||||
"go.etcd.io/etcd/pkg/v3/expect"
|
||||
epb "go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb"
|
||||
"go.etcd.io/etcd/tests/v3/framework/e2e"
|
||||
|
||||
@ -108,14 +109,14 @@ func testV3CurlPutGet(cx ctlCtx) {
|
||||
|
||||
p := cx.apiPrefix
|
||||
|
||||
if err := e2e.CURLPost(cx.epc, e2e.CURLReq{Endpoint: path.Join(p, "/kv/put"), Value: string(putData), Expected: expectPut}); err != nil {
|
||||
if err := e2e.CURLPost(cx.epc, e2e.CURLReq{Endpoint: path.Join(p, "/kv/put"), Value: string(putData), Expected: expect.ExpectedResponse{Value: expectPut}}); err != nil {
|
||||
cx.t.Fatalf("failed testV3CurlPutGet put with curl using prefix (%s) (%v)", p, err)
|
||||
}
|
||||
if err := e2e.CURLPost(cx.epc, e2e.CURLReq{Endpoint: path.Join(p, "/kv/range"), Value: string(rangeData), Expected: expectGet}); err != nil {
|
||||
if err := e2e.CURLPost(cx.epc, e2e.CURLReq{Endpoint: path.Join(p, "/kv/range"), Value: string(rangeData), Expected: expect.ExpectedResponse{Value: expectGet}}); err != nil {
|
||||
cx.t.Fatalf("failed testV3CurlPutGet get with curl using prefix (%s) (%v)", p, err)
|
||||
}
|
||||
if cx.cfg.Client.ConnectionType == e2e.ClientTLSAndNonTLS {
|
||||
if err := e2e.CURLPost(cx.epc, e2e.CURLReq{Endpoint: path.Join(p, "/kv/range"), Value: string(rangeData), Expected: expectGet, IsTLS: true}); err != nil {
|
||||
if err := e2e.CURLPost(cx.epc, e2e.CURLReq{Endpoint: path.Join(p, "/kv/range"), Value: string(rangeData), Expected: expect.ExpectedResponse{Value: expectGet}, IsTLS: true}); err != nil {
|
||||
cx.t.Fatalf("failed testV3CurlPutGet get with curl using prefix (%s) (%v)", p, err)
|
||||
}
|
||||
}
|
||||
@ -139,11 +140,11 @@ func testV3CurlWatch(cx ctlCtx) {
|
||||
wstr := `{"create_request" : ` + string(wreq) + "}"
|
||||
p := cx.apiPrefix
|
||||
|
||||
if err = e2e.CURLPost(cx.epc, e2e.CURLReq{Endpoint: path.Join(p, "/kv/put"), Value: string(putreq), Expected: "revision"}); err != nil {
|
||||
if err = e2e.CURLPost(cx.epc, e2e.CURLReq{Endpoint: path.Join(p, "/kv/put"), Value: string(putreq), Expected: expect.ExpectedResponse{Value: "revision"}}); err != nil {
|
||||
cx.t.Fatalf("failed testV3CurlWatch put with curl using prefix (%s) (%v)", p, err)
|
||||
}
|
||||
// expects "bar", timeout after 2 seconds since stream waits forever
|
||||
err = e2e.CURLPost(cx.epc, e2e.CURLReq{Endpoint: path.Join(p, "/watch"), Value: wstr, Expected: `"YmFy"`, Timeout: 2})
|
||||
err = e2e.CURLPost(cx.epc, e2e.CURLReq{Endpoint: path.Join(p, "/watch"), Value: wstr, Expected: expect.ExpectedResponse{Value: `"YmFy"`}, Timeout: 2})
|
||||
require.ErrorContains(cx.t, err, "unexpected exit code")
|
||||
}
|
||||
|
||||
@ -175,13 +176,13 @@ func testV3CurlTxn(cx ctlCtx) {
|
||||
}
|
||||
expected := `"succeeded":true,"responses":[{"response_put":{"header":{"revision":"2"}}}]`
|
||||
p := cx.apiPrefix
|
||||
if err := e2e.CURLPost(cx.epc, e2e.CURLReq{Endpoint: path.Join(p, "/kv/txn"), Value: string(jsonDat), Expected: expected}); err != nil {
|
||||
if err := e2e.CURLPost(cx.epc, e2e.CURLReq{Endpoint: path.Join(p, "/kv/txn"), Value: string(jsonDat), Expected: expect.ExpectedResponse{Value: expected}}); err != nil {
|
||||
cx.t.Fatalf("failed testV3CurlTxn txn with curl using prefix (%s) (%v)", p, err)
|
||||
}
|
||||
|
||||
// was crashing etcd server
|
||||
malformed := `{"compare":[{"result":0,"target":1,"key":"Zm9v","TargetUnion":null}],"success":[{"Request":{"RequestPut":{"key":"Zm9v","value":"YmFy"}}}]}`
|
||||
if err := e2e.CURLPost(cx.epc, e2e.CURLReq{Endpoint: path.Join(p, "/kv/txn"), Value: malformed, Expected: "error"}); err != nil {
|
||||
if err := e2e.CURLPost(cx.epc, e2e.CURLReq{Endpoint: path.Join(p, "/kv/txn"), Value: malformed, Expected: expect.ExpectedResponse{Value: "error"}}); err != nil {
|
||||
cx.t.Fatalf("failed testV3CurlTxn put with curl using prefix (%s) (%v)", p, err)
|
||||
}
|
||||
|
||||
@ -198,7 +199,7 @@ func testV3CurlAuth(cx ctlCtx) {
|
||||
user, err := json.Marshal(&pb.AuthUserAddRequest{Name: usernames[i], Password: pwds[i], Options: options[i]})
|
||||
testutil.AssertNil(cx.t, err)
|
||||
|
||||
if err = e2e.CURLPost(cx.epc, e2e.CURLReq{Endpoint: path.Join(p, "/auth/user/add"), Value: string(user), Expected: "revision"}); err != nil {
|
||||
if err = e2e.CURLPost(cx.epc, e2e.CURLReq{Endpoint: path.Join(p, "/auth/user/add"), Value: string(user), Expected: expect.ExpectedResponse{Value: "revision"}}); err != nil {
|
||||
cx.t.Fatalf("failed testV3CurlAuth add user %v with curl (%v)", usernames[i], err)
|
||||
}
|
||||
}
|
||||
@ -207,7 +208,7 @@ func testV3CurlAuth(cx ctlCtx) {
|
||||
rolereq, err := json.Marshal(&pb.AuthRoleAddRequest{Name: "root"})
|
||||
testutil.AssertNil(cx.t, err)
|
||||
|
||||
if err = e2e.CURLPost(cx.epc, e2e.CURLReq{Endpoint: path.Join(p, "/auth/role/add"), Value: string(rolereq), Expected: "revision"}); err != nil {
|
||||
if err = e2e.CURLPost(cx.epc, e2e.CURLReq{Endpoint: path.Join(p, "/auth/role/add"), Value: string(rolereq), Expected: expect.ExpectedResponse{Value: "revision"}}); err != nil {
|
||||
cx.t.Fatalf("failed testV3CurlAuth create role with curl using prefix (%s) (%v)", p, err)
|
||||
}
|
||||
|
||||
@ -216,13 +217,13 @@ func testV3CurlAuth(cx ctlCtx) {
|
||||
grantroleroot, err := json.Marshal(&pb.AuthUserGrantRoleRequest{User: usernames[i], Role: "root"})
|
||||
testutil.AssertNil(cx.t, err)
|
||||
|
||||
if err = e2e.CURLPost(cx.epc, e2e.CURLReq{Endpoint: path.Join(p, "/auth/user/grant"), Value: string(grantroleroot), Expected: "revision"}); err != nil {
|
||||
if err = e2e.CURLPost(cx.epc, e2e.CURLReq{Endpoint: path.Join(p, "/auth/user/grant"), Value: string(grantroleroot), Expected: expect.ExpectedResponse{Value: "revision"}}); err != nil {
|
||||
cx.t.Fatalf("failed testV3CurlAuth grant role with curl using prefix (%s) (%v)", p, err)
|
||||
}
|
||||
}
|
||||
|
||||
// enable auth
|
||||
if err = e2e.CURLPost(cx.epc, e2e.CURLReq{Endpoint: path.Join(p, "/auth/enable"), Value: "{}", Expected: "revision"}); err != nil {
|
||||
if err = e2e.CURLPost(cx.epc, e2e.CURLReq{Endpoint: path.Join(p, "/auth/enable"), Value: "{}", Expected: expect.ExpectedResponse{Value: "revision"}}); err != nil {
|
||||
cx.t.Fatalf("failed testV3CurlAuth enable auth with curl using prefix (%s) (%v)", p, err)
|
||||
}
|
||||
|
||||
@ -232,7 +233,7 @@ func testV3CurlAuth(cx ctlCtx) {
|
||||
testutil.AssertNil(cx.t, err)
|
||||
|
||||
// fail put no auth
|
||||
if err = e2e.CURLPost(cx.epc, e2e.CURLReq{Endpoint: path.Join(p, "/kv/put"), Value: string(putreq), Expected: "error"}); err != nil {
|
||||
if err = e2e.CURLPost(cx.epc, e2e.CURLReq{Endpoint: path.Join(p, "/kv/put"), Value: string(putreq), Expected: expect.ExpectedResponse{Value: "error"}}); err != nil {
|
||||
cx.t.Fatalf("failed testV3CurlAuth no auth put with curl using prefix (%s) (%v)", p, err)
|
||||
}
|
||||
|
||||
@ -265,7 +266,7 @@ func testV3CurlAuth(cx ctlCtx) {
|
||||
authHeader = "Authorization: " + token
|
||||
|
||||
// put with auth
|
||||
if err = e2e.CURLPost(cx.epc, e2e.CURLReq{Endpoint: path.Join(p, "/kv/put"), Value: string(putreq), Header: authHeader, Expected: "revision"}); err != nil {
|
||||
if err = e2e.CURLPost(cx.epc, e2e.CURLReq{Endpoint: path.Join(p, "/kv/put"), Value: string(putreq), Header: authHeader, Expected: expect.ExpectedResponse{Value: "revision"}}); err != nil {
|
||||
cx.t.Fatalf("failed testV3CurlAuth auth put with curl using prefix (%s) and user (%v) (%v)", p, usernames[i], err)
|
||||
}
|
||||
}
|
||||
@ -289,7 +290,7 @@ func testV3CurlCampaign(cx ctlCtx) {
|
||||
Endpoint: path.Join(cx.apiPrefix, "/election/campaign"),
|
||||
Value: string(cdata),
|
||||
})
|
||||
lines, err := e2e.SpawnWithExpectLines(context.TODO(), cargs, cx.envMap, `"leader":{"name":"`)
|
||||
lines, err := e2e.SpawnWithExpectLines(context.TODO(), cargs, cx.envMap, expect.ExpectedResponse{Value: `"leader":{"name":"`})
|
||||
if err != nil {
|
||||
cx.t.Fatalf("failed post campaign request (%s) (%v)", cx.apiPrefix, err)
|
||||
}
|
||||
@ -327,7 +328,7 @@ func testV3CurlCampaign(cx ctlCtx) {
|
||||
if err = e2e.CURLPost(cx.epc, e2e.CURLReq{
|
||||
Endpoint: path.Join(cx.apiPrefix, "/election/proclaim"),
|
||||
Value: string(pdata),
|
||||
Expected: `"revision":`,
|
||||
Expected: expect.ExpectedResponse{Value: `"revision":`},
|
||||
}); err != nil {
|
||||
cx.t.Fatalf("failed post proclaim request (%s) (%v)", cx.apiPrefix, err)
|
||||
}
|
||||
@ -347,7 +348,7 @@ func testV3CurlProclaimMissiongLeaderKey(cx ctlCtx) {
|
||||
if err = e2e.CURLPost(cx.epc, e2e.CURLReq{
|
||||
Endpoint: path.Join(cx.apiPrefix, "/election/proclaim"),
|
||||
Value: string(pdata),
|
||||
Expected: `{"error":"\"leader\" field must be provided","code":2,"message":"\"leader\" field must be provided"}`,
|
||||
Expected: expect.ExpectedResponse{Value: `{"error":"\"leader\" field must be provided","code":2,"message":"\"leader\" field must be provided"}`},
|
||||
}); err != nil {
|
||||
cx.t.Fatalf("failed post proclaim request (%s) (%v)", cx.apiPrefix, err)
|
||||
}
|
||||
@ -363,7 +364,7 @@ func testV3CurlResignMissiongLeaderKey(cx ctlCtx) {
|
||||
if err := e2e.CURLPost(cx.epc, e2e.CURLReq{
|
||||
Endpoint: path.Join(cx.apiPrefix, "/election/resign"),
|
||||
Value: `{}`,
|
||||
Expected: `{"error":"\"leader\" field must be provided","code":2,"message":"\"leader\" field must be provided"}`,
|
||||
Expected: expect.ExpectedResponse{Value: `{"error":"\"leader\" field must be provided","code":2,"message":"\"leader\" field must be provided"}`},
|
||||
}); err != nil {
|
||||
cx.t.Fatalf("failed post resign request (%s) (%v)", cx.apiPrefix, err)
|
||||
}
|
||||
@ -399,7 +400,7 @@ func CURLWithExpected(cx ctlCtx, tests []v3cURLTest) error {
|
||||
p := cx.apiPrefix
|
||||
for _, t := range tests {
|
||||
value := fmt.Sprintf("%v", t.value)
|
||||
if err := e2e.CURLPost(cx.epc, e2e.CURLReq{Endpoint: path.Join(p, t.endpoint), Value: value, Expected: t.expected}); err != nil {
|
||||
if err := e2e.CURLPost(cx.epc, e2e.CURLReq{Endpoint: path.Join(p, t.endpoint), Value: value, Expected: expect.ExpectedResponse{Value: t.expected}}); err != nil {
|
||||
return fmt.Errorf("prefix (%s) endpoint (%s): error (%v), wanted %v", p, t.endpoint, err, t.expected)
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,8 @@ import (
|
||||
"math/rand"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"go.etcd.io/etcd/pkg/v3/expect"
|
||||
)
|
||||
|
||||
type CURLReq struct {
|
||||
@ -32,7 +34,7 @@ type CURLReq struct {
|
||||
Endpoint string
|
||||
|
||||
Value string
|
||||
Expected string
|
||||
Expected expect.ExpectedResponse
|
||||
Header string
|
||||
|
||||
Ciphers string
|
||||
|
@ -62,7 +62,7 @@ type EtcdProcess interface {
|
||||
}
|
||||
|
||||
type LogsExpect interface {
|
||||
ExpectWithContext(context.Context, string) (string, error)
|
||||
ExpectWithContext(context.Context, expect.ExpectedResponse) (string, error)
|
||||
Lines() []string
|
||||
LineCount() int
|
||||
}
|
||||
@ -313,7 +313,7 @@ func AssertProcessLogs(t *testing.T, ep EtcdProcess, expectLog string) {
|
||||
var err error
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
_, err = ep.Logs().ExpectWithContext(ctx, expectLog)
|
||||
_, err = ep.Logs().ExpectWithContext(ctx, expect.ExpectedResponse{Value: expectLog})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ import (
|
||||
"go.etcd.io/etcd/api/v3/authpb"
|
||||
"go.etcd.io/etcd/api/v3/etcdserverpb"
|
||||
clientv3 "go.etcd.io/etcd/client/v3"
|
||||
"go.etcd.io/etcd/pkg/v3/expect"
|
||||
"go.etcd.io/etcd/tests/v3/framework/config"
|
||||
)
|
||||
|
||||
@ -80,7 +81,7 @@ func WithEndpoints(endpoints []string) config.ClientOption {
|
||||
}
|
||||
|
||||
func (ctl *EtcdctlV3) DowngradeEnable(ctx context.Context, version string) error {
|
||||
_, err := SpawnWithExpectLines(ctx, ctl.cmdArgs("downgrade", "enable", version), nil, "Downgrade enable success")
|
||||
_, err := SpawnWithExpectLines(ctx, ctl.cmdArgs("downgrade", "enable", version), nil, expect.ExpectedResponse{Value: "Downgrade enable success"})
|
||||
return err
|
||||
}
|
||||
|
||||
@ -144,7 +145,7 @@ func (ctl *EtcdctlV3) Get(ctx context.Context, key string, o config.GetOptions)
|
||||
return nil, err
|
||||
}
|
||||
defer cmd.Close()
|
||||
_, err = cmd.ExpectWithContext(ctx, "Count")
|
||||
_, err = cmd.ExpectWithContext(ctx, expect.ExpectedResponse{Value: "Count"})
|
||||
return &resp, err
|
||||
}
|
||||
err := ctl.spawnJsonCmd(ctx, &resp, args...)
|
||||
@ -157,7 +158,7 @@ func (ctl *EtcdctlV3) Put(ctx context.Context, key, value string, opts config.Pu
|
||||
if opts.LeaseID != 0 {
|
||||
args = append(args, "--lease", strconv.FormatInt(int64(opts.LeaseID), 16))
|
||||
}
|
||||
_, err := SpawnWithExpectLines(ctx, args, nil, "OK")
|
||||
_, err := SpawnWithExpectLines(ctx, args, nil, expect.ExpectedResponse{Value: "OK"})
|
||||
return err
|
||||
}
|
||||
|
||||
@ -189,7 +190,7 @@ func (ctl *EtcdctlV3) Txn(ctx context.Context, compares, ifSucess, ifFail []stri
|
||||
return nil, err
|
||||
}
|
||||
defer cmd.Close()
|
||||
_, err = cmd.ExpectWithContext(ctx, "compares:")
|
||||
_, err = cmd.ExpectWithContext(ctx, expect.ExpectedResponse{Value: "compares:"})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -201,7 +202,7 @@ func (ctl *EtcdctlV3) Txn(ctx context.Context, compares, ifSucess, ifFail []stri
|
||||
if err := cmd.Send("\r"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = cmd.ExpectWithContext(ctx, "success requests (get, put, del):")
|
||||
_, err = cmd.ExpectWithContext(ctx, expect.ExpectedResponse{Value: "success requests (get, put, del):"})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -214,7 +215,7 @@ func (ctl *EtcdctlV3) Txn(ctx context.Context, compares, ifSucess, ifFail []stri
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = cmd.ExpectWithContext(ctx, "failure requests (get, put, del):")
|
||||
_, err = cmd.ExpectWithContext(ctx, expect.ExpectedResponse{Value: "failure requests (get, put, del):"})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -227,7 +228,7 @@ func (ctl *EtcdctlV3) Txn(ctx context.Context, compares, ifSucess, ifFail []stri
|
||||
return nil, err
|
||||
}
|
||||
var line string
|
||||
line, err = cmd.ExpectWithContext(ctx, "header")
|
||||
line, err = cmd.ExpectWithContext(ctx, expect.ExpectedResponse{Value: "header"})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -348,7 +349,7 @@ func (ctl *EtcdctlV3) Compact(ctx context.Context, rev int64, o config.CompactOp
|
||||
args = append(args, "--physical")
|
||||
}
|
||||
|
||||
_, err := SpawnWithExpectLines(ctx, args, nil, fmt.Sprintf("compacted revision %v", rev))
|
||||
_, err := SpawnWithExpectLines(ctx, args, nil, expect.ExpectedResponse{Value: fmt.Sprintf("compacted revision %v", rev)})
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -387,9 +388,9 @@ func (ctl *EtcdctlV3) HashKV(ctx context.Context, rev int64) ([]*clientv3.HashKV
|
||||
func (ctl *EtcdctlV3) Health(ctx context.Context) error {
|
||||
args := ctl.cmdArgs()
|
||||
args = append(args, "endpoint", "health")
|
||||
lines := make([]string, len(ctl.endpoints))
|
||||
lines := make([]expect.ExpectedResponse, len(ctl.endpoints))
|
||||
for i := range lines {
|
||||
lines[i] = "is healthy"
|
||||
lines[i] = expect.ExpectedResponse{Value: "is healthy"}
|
||||
}
|
||||
_, err := SpawnWithExpectLines(ctx, args, nil, lines...)
|
||||
return err
|
||||
@ -404,7 +405,7 @@ func (ctl *EtcdctlV3) Grant(ctx context.Context, ttl int64) (*clientv3.LeaseGran
|
||||
}
|
||||
defer cmd.Close()
|
||||
var resp clientv3.LeaseGrantResponse
|
||||
line, err := cmd.ExpectWithContext(ctx, "ID")
|
||||
line, err := cmd.ExpectWithContext(ctx, expect.ExpectedResponse{Value: "ID"})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -424,7 +425,7 @@ func (ctl *EtcdctlV3) TimeToLive(ctx context.Context, id clientv3.LeaseID, o con
|
||||
}
|
||||
defer cmd.Close()
|
||||
var resp clientv3.LeaseTimeToLiveResponse
|
||||
line, err := cmd.ExpectWithContext(ctx, "id")
|
||||
line, err := cmd.ExpectWithContext(ctx, expect.ExpectedResponse{Value: "id"})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -437,9 +438,9 @@ func (ctl *EtcdctlV3) Defragment(ctx context.Context, o config.DefragOption) err
|
||||
if o.Timeout != 0 {
|
||||
args = append(args, fmt.Sprintf("--command-timeout=%s", o.Timeout))
|
||||
}
|
||||
lines := make([]string, len(ctl.endpoints))
|
||||
lines := make([]expect.ExpectedResponse, len(ctl.endpoints))
|
||||
for i := range lines {
|
||||
lines[i] = "Finished defragmenting etcd member"
|
||||
lines[i] = expect.ExpectedResponse{Value: "Finished defragmenting etcd member"}
|
||||
}
|
||||
_, err := SpawnWithExpectLines(ctx, args, map[string]string{}, lines...)
|
||||
return err
|
||||
@ -453,7 +454,7 @@ func (ctl *EtcdctlV3) Leases(ctx context.Context) (*clientv3.LeaseLeasesResponse
|
||||
}
|
||||
defer cmd.Close()
|
||||
var resp clientv3.LeaseLeasesResponse
|
||||
line, err := cmd.ExpectWithContext(ctx, "id")
|
||||
line, err := cmd.ExpectWithContext(ctx, expect.ExpectedResponse{Value: "id"})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -469,7 +470,7 @@ func (ctl *EtcdctlV3) KeepAliveOnce(ctx context.Context, id clientv3.LeaseID) (*
|
||||
}
|
||||
defer cmd.Close()
|
||||
var resp clientv3.LeaseKeepAliveResponse
|
||||
line, err := cmd.ExpectWithContext(ctx, "ID")
|
||||
line, err := cmd.ExpectWithContext(ctx, expect.ExpectedResponse{Value: "ID"})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -498,7 +499,7 @@ func (ctl *EtcdctlV3) AlarmDisarm(ctx context.Context, _ *clientv3.AlarmMember)
|
||||
}
|
||||
defer ep.Close()
|
||||
var resp clientv3.AlarmResponse
|
||||
line, err := ep.ExpectWithContext(ctx, "alarm")
|
||||
line, err := ep.ExpectWithContext(ctx, expect.ExpectedResponse{Value: "alarm"})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -514,7 +515,7 @@ func (ctl *EtcdctlV3) AuthEnable(ctx context.Context) error {
|
||||
}
|
||||
defer cmd.Close()
|
||||
|
||||
_, err = cmd.ExpectWithContext(ctx, "Authentication Enabled")
|
||||
_, err = cmd.ExpectWithContext(ctx, expect.ExpectedResponse{Value: "Authentication Enabled"})
|
||||
return err
|
||||
}
|
||||
|
||||
@ -526,7 +527,7 @@ func (ctl *EtcdctlV3) AuthDisable(ctx context.Context) error {
|
||||
}
|
||||
defer cmd.Close()
|
||||
|
||||
_, err = cmd.ExpectWithContext(ctx, "Authentication Disabled")
|
||||
_, err = cmd.ExpectWithContext(ctx, expect.ExpectedResponse{Value: "Authentication Disabled"})
|
||||
return err
|
||||
}
|
||||
|
||||
@ -567,7 +568,7 @@ func (ctl *EtcdctlV3) UserAdd(ctx context.Context, name, password string, opts c
|
||||
}
|
||||
|
||||
var resp clientv3.AuthUserAddResponse
|
||||
line, err := cmd.ExpectWithContext(ctx, "header")
|
||||
line, err := cmd.ExpectWithContext(ctx, expect.ExpectedResponse{Value: "header"})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -606,7 +607,7 @@ func (ctl *EtcdctlV3) UserChangePass(ctx context.Context, user, newPass string)
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = cmd.ExpectWithContext(ctx, "Password updated")
|
||||
_, err = cmd.ExpectWithContext(ctx, expect.ExpectedResponse{Value: "Password updated"})
|
||||
return err
|
||||
}
|
||||
|
||||
@ -666,7 +667,7 @@ func (ctl *EtcdctlV3) spawnJsonCmd(ctx context.Context, output interface{}, args
|
||||
return err
|
||||
}
|
||||
defer cmd.Close()
|
||||
line, err := cmd.ExpectWithContext(ctx, "header")
|
||||
line, err := cmd.ExpectWithContext(ctx, expect.ExpectedResponse{Value: "header"})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ func (fs *LazyFS) Start(ctx context.Context) (err error) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = fs.ep.ExpectWithContext(ctx, "waiting for fault commands")
|
||||
_, err = fs.ep.ExpectWithContext(ctx, expect.ExpectedResponse{Value: "waiting for fault commands"})
|
||||
return err
|
||||
}
|
||||
|
||||
@ -109,6 +109,6 @@ func (fs *LazyFS) ClearCache(ctx context.Context) error {
|
||||
}
|
||||
// TODO: Wait for response on socket instead of reading logs to get command completion.
|
||||
// Set `fifo_path_completed` config for LazyFS to create separate socket to write when it has completed command.
|
||||
_, err = fs.ep.ExpectWithContext(ctx, "cache is cleared")
|
||||
_, err = fs.ep.ExpectWithContext(ctx, expect.ExpectedResponse{Value: "cache is cleared"})
|
||||
return err
|
||||
}
|
||||
|
@ -41,24 +41,24 @@ func WaitReadyExpectProc(ctx context.Context, exproc *expect.ExpectProcess, read
|
||||
return err
|
||||
}
|
||||
|
||||
func SpawnWithExpect(args []string, expected string) error {
|
||||
return SpawnWithExpects(args, nil, []string{expected}...)
|
||||
func SpawnWithExpect(args []string, expected expect.ExpectedResponse) error {
|
||||
return SpawnWithExpects(args, nil, []expect.ExpectedResponse{expected}...)
|
||||
}
|
||||
|
||||
func SpawnWithExpectWithEnv(args []string, envVars map[string]string, expected string) error {
|
||||
return SpawnWithExpects(args, envVars, []string{expected}...)
|
||||
func SpawnWithExpectWithEnv(args []string, envVars map[string]string, expected expect.ExpectedResponse) error {
|
||||
return SpawnWithExpects(args, envVars, []expect.ExpectedResponse{expected}...)
|
||||
}
|
||||
|
||||
func SpawnWithExpects(args []string, envVars map[string]string, xs ...string) error {
|
||||
func SpawnWithExpects(args []string, envVars map[string]string, xs ...expect.ExpectedResponse) error {
|
||||
return SpawnWithExpectsContext(context.TODO(), args, envVars, xs...)
|
||||
}
|
||||
|
||||
func SpawnWithExpectsContext(ctx context.Context, args []string, envVars map[string]string, xs ...string) error {
|
||||
func SpawnWithExpectsContext(ctx context.Context, args []string, envVars map[string]string, xs ...expect.ExpectedResponse) error {
|
||||
_, err := SpawnWithExpectLines(ctx, args, envVars, xs...)
|
||||
return err
|
||||
}
|
||||
|
||||
func SpawnWithExpectLines(ctx context.Context, args []string, envVars map[string]string, xs ...string) ([]string, error) {
|
||||
func SpawnWithExpectLines(ctx context.Context, args []string, envVars map[string]string, xs ...expect.ExpectedResponse) ([]string, error) {
|
||||
proc, err := SpawnCmd(args, envVars)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -73,7 +73,7 @@ func SpawnWithExpectLines(ctx context.Context, args []string, envVars map[string
|
||||
l, lerr := proc.ExpectWithContext(ctx, txt)
|
||||
if lerr != nil {
|
||||
proc.Close()
|
||||
return nil, fmt.Errorf("%v %v (expected %q, got %q). Try EXPECT_DEBUG=TRUE", args, lerr, txt, lines)
|
||||
return nil, fmt.Errorf("%v %v (expected %q, got %q). Try EXPECT_DEBUG=TRUE", args, lerr, txt.Value, lines)
|
||||
}
|
||||
lines = append(lines, l)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user