e2e: etcdctlv3 version, txn basic tests

This commit is contained in:
Gyu-Ho Lee 2016-04-03 09:28:29 -07:00
parent 19136afc2b
commit c280871714

View File

@ -23,6 +23,7 @@ import (
"time"
"github.com/coreos/etcd/pkg/testutil"
"github.com/coreos/etcd/version"
)
func TestCtlV3Put(t *testing.T) { testCtl(t, putTest) }
@ -59,6 +60,27 @@ func TestCtlV3WatchInteractivePeerTLS(t *testing.T) {
testCtl(t, watchTest, withInteractive(), withCfg(configPeerTLS))
}
// TODO: watch by prefix
func TestCtlV3TxnInteractiveSuccess(t *testing.T) {
testCtl(t, txnTestSuccess, withInteractive())
}
func TestCtlV3TxnInteractiveSuccessNoTLS(t *testing.T) {
testCtl(t, txnTestSuccess, withInteractive(), withCfg(configNoTLS))
}
func TestCtlV3TxnInteractiveSuccessClientTLS(t *testing.T) {
testCtl(t, txnTestSuccess, withInteractive(), withCfg(configClientTLS))
}
func TestCtlV3TxnInteractiveSuccessPeerTLS(t *testing.T) {
testCtl(t, txnTestSuccess, withInteractive(), withCfg(configPeerTLS))
}
func TestCtlV3TxnInteractiveFail(t *testing.T) {
testCtl(t, txnTestFail, withInteractive())
}
func TestCtlV3Version(t *testing.T) { testCtl(t, versionTest) }
type ctlCtx struct {
t *testing.T
cfg etcdProcessClusterConfig
@ -199,6 +221,14 @@ func watchTest(cx ctlCtx) {
}
}
func versionTest(cx ctlCtx) {
defer close(cx.errc)
if err := ctlV3Version(cx); err != nil {
cx.t.Fatalf("versionTest error (%v)", err)
}
}
func getTest(cx ctlCtx) {
defer close(cx.errc)
@ -230,6 +260,42 @@ func getTest(cx ctlCtx) {
}
}
}
func txnTestSuccess(cx ctlCtx) {
defer close(cx.errc)
if err := ctlV3Put(cx, "key1", "value1"); err != nil {
cx.t.Fatalf("txnTestSuccess error (%v)", err)
}
if err := ctlV3Put(cx, "key2", "value2"); err != nil {
cx.t.Fatalf("txnTestSuccess error (%v)", err)
}
rqs := txnRequests{
compare: []string{`version("key1") = "1"`, `version("key2") = "1"`},
ifSucess: []string{"get key1", "get key2"},
ifFail: []string{`put key1 "fail"`, `put key2 "fail"`},
results: []string{"SUCCESS", "key1", "value1", "key2", "value2"},
}
if err := ctlV3Txn(cx, rqs); err != nil {
cx.t.Fatal(err)
}
}
func txnTestFail(cx ctlCtx) {
defer close(cx.errc)
rqs := txnRequests{
compare: []string{`version("key") < "0"`},
ifSucess: []string{`put key "success"`},
ifFail: []string{`put key "fail"`},
results: []string{"FAILURE", "OK"},
}
if err := ctlV3Txn(cx, rqs); err != nil {
cx.t.Fatal(err)
}
}
func ctlV3PrefixArgs(clus *etcdProcessCluster, dialTimeout time.Duration) []string {
if len(clus.proxies()) > 0 { // TODO: add proxy check as in v2
panic("v3 proxy not implemented")
@ -297,7 +363,7 @@ func ctlV3Watch(cx ctlCtx, key, value string) error {
if cx.watchRevision > 0 {
watchLine = fmt.Sprintf("watch %s --rev %d", key, cx.watchRevision)
}
if err = proc.SendLine(watchLine); err != nil {
if err = proc.Send(watchLine + "\r"); err != nil {
return err
}
_, err = proc.Expect(key)
@ -311,6 +377,76 @@ func ctlV3Watch(cx ctlCtx, key, value string) error {
return proc.Close()
}
type txnRequests struct {
compare []string
ifSucess []string
ifFail []string
results []string
}
func ctlV3Txn(cx ctlCtx, rqs txnRequests) error {
// TODO: support non-interactive mode
cmdArgs := append(ctlV3PrefixArgs(cx.epc, cx.dialTimeout), "txn")
if cx.interactive {
cmdArgs = append(cmdArgs, "--interactive")
}
proc, err := spawnCmd(cmdArgs)
if err != nil {
return err
}
_, err = proc.Expect("compares:")
if err != nil {
return err
}
for _, req := range rqs.compare {
if err = proc.Send(req + "\r"); err != nil {
return err
}
}
if err = proc.Send("\r"); err != nil {
return err
}
_, err = proc.Expect("success requests (get, put, delete):")
if err != nil {
return err
}
for _, req := range rqs.ifSucess {
if err = proc.Send(req + "\r"); err != nil {
return err
}
}
if err = proc.Send("\r"); err != nil {
return err
}
_, err = proc.Expect("failure requests (get, put, delete):")
if err != nil {
return err
}
for _, req := range rqs.ifFail {
if err = proc.Send(req + "\r"); err != nil {
return err
}
}
if err = proc.Send("\r"); err != nil {
return err
}
for _, line := range rqs.results {
_, err = proc.Expect(line)
if err != nil {
return err
}
}
return proc.Close()
}
func ctlV3Version(cx ctlCtx) error {
cmdArgs := append(ctlV3PrefixArgs(cx.epc, cx.dialTimeout), "version")
return spawnWithExpect(cmdArgs, version.Version)
}
func isGRPCTimedout(err error) bool {
return strings.Contains(err.Error(), "grpc: timed out trying to connect")
}