Browse Source

e2e: move

Signed-off-by: Gyuho Lee <leegyuho@amazon.com>
Gyuho Lee 6 years ago
parent
commit
082c5e0705

+ 0 - 21
e2e/cluster_direct_test.go

@@ -1,21 +0,0 @@
-// Copyright 2017 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.
-
-// +build !cluster_proxy
-
-package e2e
-
-func newEtcdProcess(cfg *etcdServerProcessConfig) (etcdProcess, error) {
-	return newEtcdServerProcess(cfg)
-}

+ 0 - 288
e2e/cluster_proxy_test.go

@@ -1,288 +0,0 @@
-// Copyright 2017 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.
-
-// +build cluster_proxy
-
-package e2e
-
-import (
-	"fmt"
-	"net"
-	"net/url"
-	"os"
-	"strconv"
-	"strings"
-
-	"github.com/coreos/etcd/pkg/expect"
-)
-
-type proxyEtcdProcess struct {
-	etcdProc etcdProcess
-	proxyV2  *proxyV2Proc
-	proxyV3  *proxyV3Proc
-}
-
-func newEtcdProcess(cfg *etcdServerProcessConfig) (etcdProcess, error) {
-	return newProxyEtcdProcess(cfg)
-}
-
-func newProxyEtcdProcess(cfg *etcdServerProcessConfig) (*proxyEtcdProcess, error) {
-	ep, err := newEtcdServerProcess(cfg)
-	if err != nil {
-		return nil, err
-	}
-	pep := &proxyEtcdProcess{
-		etcdProc: ep,
-		proxyV2:  newProxyV2Proc(cfg),
-		proxyV3:  newProxyV3Proc(cfg),
-	}
-	return pep, nil
-}
-
-func (p *proxyEtcdProcess) Config() *etcdServerProcessConfig { return p.etcdProc.Config() }
-
-func (p *proxyEtcdProcess) EndpointsV2() []string { return p.proxyV2.endpoints() }
-func (p *proxyEtcdProcess) EndpointsV3() []string { return p.proxyV3.endpoints() }
-func (p *proxyEtcdProcess) EndpointsMetrics() []string {
-	panic("not implemented; proxy doesn't provide health information")
-}
-
-func (p *proxyEtcdProcess) Start() error {
-	if err := p.etcdProc.Start(); err != nil {
-		return err
-	}
-	if err := p.proxyV2.Start(); err != nil {
-		return err
-	}
-	return p.proxyV3.Start()
-}
-
-func (p *proxyEtcdProcess) Restart() error {
-	if err := p.etcdProc.Restart(); err != nil {
-		return err
-	}
-	if err := p.proxyV2.Restart(); err != nil {
-		return err
-	}
-	return p.proxyV3.Restart()
-}
-
-func (p *proxyEtcdProcess) Stop() error {
-	err := p.proxyV2.Stop()
-	if v3err := p.proxyV3.Stop(); err == nil {
-		err = v3err
-	}
-	if eerr := p.etcdProc.Stop(); eerr != nil && err == nil {
-		// fails on go-grpc issue #1384
-		if !strings.Contains(eerr.Error(), "exit status 2") {
-			err = eerr
-		}
-	}
-	return err
-}
-
-func (p *proxyEtcdProcess) Close() error {
-	err := p.proxyV2.Close()
-	if v3err := p.proxyV3.Close(); err == nil {
-		err = v3err
-	}
-	if eerr := p.etcdProc.Close(); eerr != nil && err == nil {
-		// fails on go-grpc issue #1384
-		if !strings.Contains(eerr.Error(), "exit status 2") {
-			err = eerr
-		}
-	}
-	return err
-}
-
-func (p *proxyEtcdProcess) WithStopSignal(sig os.Signal) os.Signal {
-	p.proxyV3.WithStopSignal(sig)
-	p.proxyV3.WithStopSignal(sig)
-	return p.etcdProc.WithStopSignal(sig)
-}
-
-type proxyProc struct {
-	execPath string
-	args     []string
-	ep       string
-	murl     string
-	donec    chan struct{}
-
-	proc *expect.ExpectProcess
-}
-
-func (pp *proxyProc) endpoints() []string { return []string{pp.ep} }
-
-func (pp *proxyProc) start() error {
-	if pp.proc != nil {
-		panic("already started")
-	}
-	proc, err := spawnCmd(append([]string{pp.execPath}, pp.args...))
-	if err != nil {
-		return err
-	}
-	pp.proc = proc
-	return nil
-}
-
-func (pp *proxyProc) waitReady(readyStr string) error {
-	defer close(pp.donec)
-	return waitReadyExpectProc(pp.proc, []string{readyStr})
-}
-
-func (pp *proxyProc) Stop() error {
-	if pp.proc == nil {
-		return nil
-	}
-	if err := pp.proc.Stop(); err != nil && !strings.Contains(err.Error(), "exit status 1") {
-		// v2proxy exits with status 1 on auto tls; not sure why
-		return err
-	}
-	pp.proc = nil
-	<-pp.donec
-	pp.donec = make(chan struct{})
-	return nil
-}
-
-func (pp *proxyProc) WithStopSignal(sig os.Signal) os.Signal {
-	ret := pp.proc.StopSignal
-	pp.proc.StopSignal = sig
-	return ret
-}
-
-func (pp *proxyProc) Close() error { return pp.Stop() }
-
-type proxyV2Proc struct {
-	proxyProc
-	dataDir string
-}
-
-func proxyListenURL(cfg *etcdServerProcessConfig, portOffset int) string {
-	u, err := url.Parse(cfg.acurl)
-	if err != nil {
-		panic(err)
-	}
-	host, port, _ := net.SplitHostPort(u.Host)
-	p, _ := strconv.ParseInt(port, 10, 16)
-	u.Host = fmt.Sprintf("%s:%d", host, int(p)+portOffset)
-	return u.String()
-}
-
-func newProxyV2Proc(cfg *etcdServerProcessConfig) *proxyV2Proc {
-	listenAddr := proxyListenURL(cfg, 2)
-	name := fmt.Sprintf("testname-proxy-%p", cfg)
-	args := []string{
-		"--name", name,
-		"--proxy", "on",
-		"--listen-client-urls", listenAddr,
-		"--initial-cluster", cfg.name + "=" + cfg.purl.String(),
-	}
-	return &proxyV2Proc{
-		proxyProc{
-			execPath: cfg.execPath,
-			args:     append(args, cfg.tlsArgs...),
-			ep:       listenAddr,
-			donec:    make(chan struct{}),
-		},
-		name + ".etcd",
-	}
-}
-
-func (v2p *proxyV2Proc) Start() error {
-	os.RemoveAll(v2p.dataDir)
-	if err := v2p.start(); err != nil {
-		return err
-	}
-	return v2p.waitReady("httpproxy: endpoints found")
-}
-
-func (v2p *proxyV2Proc) Restart() error {
-	if err := v2p.Stop(); err != nil {
-		return err
-	}
-	return v2p.Start()
-}
-
-func (v2p *proxyV2Proc) Stop() error {
-	if err := v2p.proxyProc.Stop(); err != nil {
-		return err
-	}
-	// v2 proxy caches members; avoid reuse of directory
-	return os.RemoveAll(v2p.dataDir)
-}
-
-type proxyV3Proc struct {
-	proxyProc
-}
-
-func newProxyV3Proc(cfg *etcdServerProcessConfig) *proxyV3Proc {
-	listenAddr := proxyListenURL(cfg, 3)
-	args := []string{
-		"grpc-proxy",
-		"start",
-		"--listen-addr", strings.Split(listenAddr, "/")[2],
-		"--endpoints", cfg.acurl,
-		// pass-through member RPCs
-		"--advertise-client-url", "",
-	}
-	murl := ""
-	if cfg.murl != "" {
-		murl = proxyListenURL(cfg, 4)
-		args = append(args, "--metrics-addr", murl)
-	}
-	tlsArgs := []string{}
-	for i := 0; i < len(cfg.tlsArgs); i++ {
-		switch cfg.tlsArgs[i] {
-		case "--cert-file":
-			tlsArgs = append(tlsArgs, "--cert", cfg.tlsArgs[i+1], "--cert-file", cfg.tlsArgs[i+1])
-			i++
-		case "--key-file":
-			tlsArgs = append(tlsArgs, "--key", cfg.tlsArgs[i+1], "--key-file", cfg.tlsArgs[i+1])
-			i++
-		case "--ca-file":
-			tlsArgs = append(tlsArgs, "--cacert", cfg.tlsArgs[i+1], "--trusted-ca-file", cfg.tlsArgs[i+1])
-			i++
-		case "--auto-tls":
-			tlsArgs = append(tlsArgs, "--auto-tls", "--insecure-skip-tls-verify")
-		case "--peer-ca-file", "--peer-cert-file", "--peer-key-file":
-			i++ // skip arg
-		case "--client-cert-auth", "--peer-auto-tls":
-		default:
-			tlsArgs = append(tlsArgs, cfg.tlsArgs[i])
-		}
-	}
-	return &proxyV3Proc{
-		proxyProc{
-			execPath: cfg.execPath,
-			args:     append(args, tlsArgs...),
-			ep:       listenAddr,
-			murl:     murl,
-			donec:    make(chan struct{}),
-		},
-	}
-}
-
-func (v3p *proxyV3Proc) Restart() error {
-	if err := v3p.Stop(); err != nil {
-		return err
-	}
-	return v3p.Start()
-}
-
-func (v3p *proxyV3Proc) Start() error {
-	if err := v3p.start(); err != nil {
-		return err
-	}
-	return v3p.waitReady("listening for grpc-proxy client requests")
-}

+ 0 - 381
e2e/cluster_test.go

@@ -1,381 +0,0 @@
-// Copyright 2016 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 e2e
-
-import (
-	"fmt"
-	"io/ioutil"
-	"net/url"
-	"os"
-	"strings"
-
-	"github.com/coreos/etcd/etcdserver"
-)
-
-const etcdProcessBasePort = 20000
-
-type clientConnType int
-
-const (
-	clientNonTLS clientConnType = iota
-	clientTLS
-	clientTLSAndNonTLS
-)
-
-var (
-	configNoTLS = etcdProcessClusterConfig{
-		clusterSize:  3,
-		initialToken: "new",
-	}
-	configAutoTLS = etcdProcessClusterConfig{
-		clusterSize:   3,
-		isPeerTLS:     true,
-		isPeerAutoTLS: true,
-		initialToken:  "new",
-	}
-	configTLS = etcdProcessClusterConfig{
-		clusterSize:  3,
-		clientTLS:    clientTLS,
-		isPeerTLS:    true,
-		initialToken: "new",
-	}
-	configClientTLS = etcdProcessClusterConfig{
-		clusterSize:  3,
-		clientTLS:    clientTLS,
-		initialToken: "new",
-	}
-	configClientBoth = etcdProcessClusterConfig{
-		clusterSize:  1,
-		clientTLS:    clientTLSAndNonTLS,
-		initialToken: "new",
-	}
-	configClientAutoTLS = etcdProcessClusterConfig{
-		clusterSize:     1,
-		isClientAutoTLS: true,
-		clientTLS:       clientTLS,
-		initialToken:    "new",
-	}
-	configPeerTLS = etcdProcessClusterConfig{
-		clusterSize:  3,
-		isPeerTLS:    true,
-		initialToken: "new",
-	}
-	configClientTLSCertAuth = etcdProcessClusterConfig{
-		clusterSize:           1,
-		clientTLS:             clientTLS,
-		initialToken:          "new",
-		clientCertAuthEnabled: true,
-	}
-)
-
-func configStandalone(cfg etcdProcessClusterConfig) *etcdProcessClusterConfig {
-	ret := cfg
-	ret.clusterSize = 1
-	return &ret
-}
-
-type etcdProcessCluster struct {
-	cfg   *etcdProcessClusterConfig
-	procs []etcdProcess
-}
-
-type etcdProcessClusterConfig struct {
-	execPath    string
-	dataDirPath string
-	keepDataDir bool
-
-	clusterSize int
-
-	baseScheme string
-	basePort   int
-
-	metricsURLScheme string
-
-	snapCount int // default is 10000
-
-	clientTLS             clientConnType
-	clientCertAuthEnabled bool
-	isPeerTLS             bool
-	isPeerAutoTLS         bool
-	isClientAutoTLS       bool
-	isClientCRL           bool
-
-	cipherSuites []string
-
-	forceNewCluster     bool
-	initialToken        string
-	quotaBackendBytes   int64
-	noStrictReconfig    bool
-	initialCorruptCheck bool
-}
-
-// newEtcdProcessCluster launches a new cluster from etcd processes, returning
-// a new etcdProcessCluster once all nodes are ready to accept client requests.
-func newEtcdProcessCluster(cfg *etcdProcessClusterConfig) (*etcdProcessCluster, error) {
-	etcdCfgs := cfg.etcdServerProcessConfigs()
-	epc := &etcdProcessCluster{
-		cfg:   cfg,
-		procs: make([]etcdProcess, cfg.clusterSize),
-	}
-
-	// launch etcd processes
-	for i := range etcdCfgs {
-		proc, err := newEtcdProcess(etcdCfgs[i])
-		if err != nil {
-			epc.Close()
-			return nil, err
-		}
-		epc.procs[i] = proc
-	}
-
-	if err := epc.Start(); err != nil {
-		return nil, err
-	}
-	return epc, nil
-}
-
-func (cfg *etcdProcessClusterConfig) clientScheme() string {
-	if cfg.clientTLS == clientTLS {
-		return "https"
-	}
-	return "http"
-}
-
-func (cfg *etcdProcessClusterConfig) peerScheme() string {
-	peerScheme := cfg.baseScheme
-	if peerScheme == "" {
-		peerScheme = "http"
-	}
-	if cfg.isPeerTLS {
-		peerScheme += "s"
-	}
-	return peerScheme
-}
-
-func (cfg *etcdProcessClusterConfig) etcdServerProcessConfigs() []*etcdServerProcessConfig {
-	if cfg.basePort == 0 {
-		cfg.basePort = etcdProcessBasePort
-	}
-	if cfg.execPath == "" {
-		cfg.execPath = binPath
-	}
-	if cfg.snapCount == 0 {
-		cfg.snapCount = etcdserver.DefaultSnapCount
-	}
-
-	etcdCfgs := make([]*etcdServerProcessConfig, cfg.clusterSize)
-	initialCluster := make([]string, cfg.clusterSize)
-	for i := 0; i < cfg.clusterSize; i++ {
-		var curls []string
-		var curl, curltls string
-		port := cfg.basePort + 5*i
-		curlHost := fmt.Sprintf("localhost:%d", port)
-
-		switch cfg.clientTLS {
-		case clientNonTLS, clientTLS:
-			curl = (&url.URL{Scheme: cfg.clientScheme(), Host: curlHost}).String()
-			curls = []string{curl}
-		case clientTLSAndNonTLS:
-			curl = (&url.URL{Scheme: "http", Host: curlHost}).String()
-			curltls = (&url.URL{Scheme: "https", Host: curlHost}).String()
-			curls = []string{curl, curltls}
-		}
-
-		purl := url.URL{Scheme: cfg.peerScheme(), Host: fmt.Sprintf("localhost:%d", port+1)}
-		name := fmt.Sprintf("testname%d", i)
-		dataDirPath := cfg.dataDirPath
-		if cfg.dataDirPath == "" {
-			var derr error
-			dataDirPath, derr = ioutil.TempDir("", name+".etcd")
-			if derr != nil {
-				panic(fmt.Sprintf("could not get tempdir for datadir: %s", derr))
-			}
-		}
-		initialCluster[i] = fmt.Sprintf("%s=%s", name, purl.String())
-
-		args := []string{
-			"--name", name,
-			"--listen-client-urls", strings.Join(curls, ","),
-			"--advertise-client-urls", strings.Join(curls, ","),
-			"--listen-peer-urls", purl.String(),
-			"--initial-advertise-peer-urls", purl.String(),
-			"--initial-cluster-token", cfg.initialToken,
-			"--data-dir", dataDirPath,
-			"--snapshot-count", fmt.Sprintf("%d", cfg.snapCount),
-		}
-		args = addV2Args(args)
-		if cfg.forceNewCluster {
-			args = append(args, "--force-new-cluster")
-		}
-		if cfg.quotaBackendBytes > 0 {
-			args = append(args,
-				"--quota-backend-bytes", fmt.Sprintf("%d", cfg.quotaBackendBytes),
-			)
-		}
-		if cfg.noStrictReconfig {
-			args = append(args, "--strict-reconfig-check=false")
-		}
-		if cfg.initialCorruptCheck {
-			args = append(args, "--experimental-initial-corrupt-check")
-		}
-		var murl string
-		if cfg.metricsURLScheme != "" {
-			murl = (&url.URL{
-				Scheme: cfg.metricsURLScheme,
-				Host:   fmt.Sprintf("localhost:%d", port+2),
-			}).String()
-			args = append(args, "--listen-metrics-urls", murl)
-		}
-
-		args = append(args, cfg.tlsArgs()...)
-		etcdCfgs[i] = &etcdServerProcessConfig{
-			execPath:     cfg.execPath,
-			args:         args,
-			tlsArgs:      cfg.tlsArgs(),
-			dataDirPath:  dataDirPath,
-			keepDataDir:  cfg.keepDataDir,
-			name:         name,
-			purl:         purl,
-			acurl:        curl,
-			murl:         murl,
-			initialToken: cfg.initialToken,
-		}
-	}
-
-	initialClusterArgs := []string{"--initial-cluster", strings.Join(initialCluster, ",")}
-	for i := range etcdCfgs {
-		etcdCfgs[i].initialCluster = strings.Join(initialCluster, ",")
-		etcdCfgs[i].args = append(etcdCfgs[i].args, initialClusterArgs...)
-	}
-
-	return etcdCfgs
-}
-
-func (cfg *etcdProcessClusterConfig) tlsArgs() (args []string) {
-	if cfg.clientTLS != clientNonTLS {
-		if cfg.isClientAutoTLS {
-			args = append(args, "--auto-tls")
-		} else {
-			tlsClientArgs := []string{
-				"--cert-file", certPath,
-				"--key-file", privateKeyPath,
-				"--ca-file", caPath,
-			}
-			args = append(args, tlsClientArgs...)
-
-			if cfg.clientCertAuthEnabled {
-				args = append(args, "--client-cert-auth")
-			}
-		}
-	}
-
-	if cfg.isPeerTLS {
-		if cfg.isPeerAutoTLS {
-			args = append(args, "--peer-auto-tls")
-		} else {
-			tlsPeerArgs := []string{
-				"--peer-cert-file", certPath,
-				"--peer-key-file", privateKeyPath,
-				"--peer-ca-file", caPath,
-			}
-			args = append(args, tlsPeerArgs...)
-		}
-	}
-
-	if cfg.isClientCRL {
-		args = append(args, "--client-crl-file", crlPath, "--client-cert-auth")
-	}
-
-	if len(cfg.cipherSuites) > 0 {
-		args = append(args, "--cipher-suites", strings.Join(cfg.cipherSuites, ","))
-	}
-
-	return args
-}
-
-func (epc *etcdProcessCluster) EndpointsV2() []string {
-	return epc.endpoints(func(ep etcdProcess) []string { return ep.EndpointsV2() })
-}
-
-func (epc *etcdProcessCluster) EndpointsV3() []string {
-	return epc.endpoints(func(ep etcdProcess) []string { return ep.EndpointsV3() })
-}
-
-func (epc *etcdProcessCluster) endpoints(f func(ep etcdProcess) []string) (ret []string) {
-	for _, p := range epc.procs {
-		ret = append(ret, f(p)...)
-	}
-	return ret
-}
-
-func (epc *etcdProcessCluster) Start() error {
-	return epc.start(func(ep etcdProcess) error { return ep.Start() })
-}
-
-func (epc *etcdProcessCluster) Restart() error {
-	return epc.start(func(ep etcdProcess) error { return ep.Restart() })
-}
-
-func (epc *etcdProcessCluster) start(f func(ep etcdProcess) error) error {
-	readyC := make(chan error, len(epc.procs))
-	for i := range epc.procs {
-		go func(n int) { readyC <- f(epc.procs[n]) }(i)
-	}
-	for range epc.procs {
-		if err := <-readyC; err != nil {
-			epc.Close()
-			return err
-		}
-	}
-	return nil
-}
-
-func (epc *etcdProcessCluster) Stop() (err error) {
-	for _, p := range epc.procs {
-		if p == nil {
-			continue
-		}
-		if curErr := p.Stop(); curErr != nil {
-			if err != nil {
-				err = fmt.Errorf("%v; %v", err, curErr)
-			} else {
-				err = curErr
-			}
-		}
-	}
-	return err
-}
-
-func (epc *etcdProcessCluster) Close() error {
-	err := epc.Stop()
-	for _, p := range epc.procs {
-		// p is nil when newEtcdProcess fails in the middle
-		// Close still gets called to clean up test data
-		if p == nil {
-			continue
-		}
-		if cerr := p.Close(); cerr != nil {
-			err = cerr
-		}
-	}
-	return err
-}
-
-func (epc *etcdProcessCluster) WithStopSignal(sig os.Signal) (ret os.Signal) {
-	for _, p := range epc.procs {
-		ret = p.WithStopSignal(sig)
-	}
-	return ret
-}

+ 0 - 513
e2e/ctl_v2_test.go

@@ -1,513 +0,0 @@
-// Copyright 2016 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 e2e
-
-import (
-	"io/ioutil"
-	"os"
-	"strings"
-	"testing"
-	"time"
-
-	"github.com/coreos/etcd/pkg/fileutil"
-	"github.com/coreos/etcd/pkg/testutil"
-)
-
-func TestCtlV2Set(t *testing.T)          { testCtlV2Set(t, &configNoTLS, false) }
-func TestCtlV2SetQuorum(t *testing.T)    { testCtlV2Set(t, &configNoTLS, true) }
-func TestCtlV2SetClientTLS(t *testing.T) { testCtlV2Set(t, &configClientTLS, false) }
-func TestCtlV2SetPeerTLS(t *testing.T)   { testCtlV2Set(t, &configPeerTLS, false) }
-func TestCtlV2SetTLS(t *testing.T)       { testCtlV2Set(t, &configTLS, false) }
-func testCtlV2Set(t *testing.T, cfg *etcdProcessClusterConfig, quorum bool) {
-	defer testutil.AfterTest(t)
-
-	epc := setupEtcdctlTest(t, cfg, quorum)
-	defer func() {
-		if errC := epc.Close(); errC != nil {
-			t.Fatalf("error closing etcd processes (%v)", errC)
-		}
-	}()
-
-	key, value := "foo", "bar"
-
-	if err := etcdctlSet(epc, key, value); err != nil {
-		t.Fatalf("failed set (%v)", err)
-	}
-
-	if err := etcdctlGet(epc, key, value, quorum); err != nil {
-		t.Fatalf("failed get (%v)", err)
-	}
-}
-
-func TestCtlV2Mk(t *testing.T)       { testCtlV2Mk(t, &configNoTLS, false) }
-func TestCtlV2MkQuorum(t *testing.T) { testCtlV2Mk(t, &configNoTLS, true) }
-func TestCtlV2MkTLS(t *testing.T)    { testCtlV2Mk(t, &configTLS, false) }
-func testCtlV2Mk(t *testing.T, cfg *etcdProcessClusterConfig, quorum bool) {
-	defer testutil.AfterTest(t)
-
-	epc := setupEtcdctlTest(t, cfg, quorum)
-	defer func() {
-		if errC := epc.Close(); errC != nil {
-			t.Fatalf("error closing etcd processes (%v)", errC)
-		}
-	}()
-
-	key, value := "foo", "bar"
-
-	if err := etcdctlMk(epc, key, value, true); err != nil {
-		t.Fatalf("failed mk (%v)", err)
-	}
-	if err := etcdctlMk(epc, key, value, false); err != nil {
-		t.Fatalf("failed mk (%v)", err)
-	}
-
-	if err := etcdctlGet(epc, key, value, quorum); err != nil {
-		t.Fatalf("failed get (%v)", err)
-	}
-}
-
-func TestCtlV2Rm(t *testing.T)    { testCtlV2Rm(t, &configNoTLS) }
-func TestCtlV2RmTLS(t *testing.T) { testCtlV2Rm(t, &configTLS) }
-func testCtlV2Rm(t *testing.T, cfg *etcdProcessClusterConfig) {
-	defer testutil.AfterTest(t)
-
-	epc := setupEtcdctlTest(t, cfg, true)
-	defer func() {
-		if errC := epc.Close(); errC != nil {
-			t.Fatalf("error closing etcd processes (%v)", errC)
-		}
-	}()
-
-	key, value := "foo", "bar"
-
-	if err := etcdctlSet(epc, key, value); err != nil {
-		t.Fatalf("failed set (%v)", err)
-	}
-
-	if err := etcdctlRm(epc, key, value, true); err != nil {
-		t.Fatalf("failed rm (%v)", err)
-	}
-	if err := etcdctlRm(epc, key, value, false); err != nil {
-		t.Fatalf("failed rm (%v)", err)
-	}
-}
-
-func TestCtlV2Ls(t *testing.T)       { testCtlV2Ls(t, &configNoTLS, false) }
-func TestCtlV2LsQuorum(t *testing.T) { testCtlV2Ls(t, &configNoTLS, true) }
-func TestCtlV2LsTLS(t *testing.T)    { testCtlV2Ls(t, &configTLS, false) }
-func testCtlV2Ls(t *testing.T, cfg *etcdProcessClusterConfig, quorum bool) {
-	defer testutil.AfterTest(t)
-
-	epc := setupEtcdctlTest(t, cfg, quorum)
-	defer func() {
-		if errC := epc.Close(); errC != nil {
-			t.Fatalf("error closing etcd processes (%v)", errC)
-		}
-	}()
-
-	key, value := "foo", "bar"
-
-	if err := etcdctlSet(epc, key, value); err != nil {
-		t.Fatalf("failed set (%v)", err)
-	}
-
-	if err := etcdctlLs(epc, key, quorum); err != nil {
-		t.Fatalf("failed ls (%v)", err)
-	}
-}
-
-func TestCtlV2Watch(t *testing.T)    { testCtlV2Watch(t, &configNoTLS, false) }
-func TestCtlV2WatchTLS(t *testing.T) { testCtlV2Watch(t, &configTLS, false) }
-
-func testCtlV2Watch(t *testing.T, cfg *etcdProcessClusterConfig, noSync bool) {
-	defer testutil.AfterTest(t)
-
-	epc := setupEtcdctlTest(t, cfg, true)
-	defer func() {
-		if errC := epc.Close(); errC != nil {
-			t.Fatalf("error closing etcd processes (%v)", errC)
-		}
-	}()
-
-	key, value := "foo", "bar"
-	errc := etcdctlWatch(epc, key, value, noSync)
-	if err := etcdctlSet(epc, key, value); err != nil {
-		t.Fatalf("failed set (%v)", err)
-	}
-
-	select {
-	case err := <-errc:
-		if err != nil {
-			t.Fatalf("failed watch (%v)", err)
-		}
-	case <-time.After(5 * time.Second):
-		t.Fatalf("watch timed out")
-	}
-}
-
-func TestCtlV2GetRoleUser(t *testing.T) {
-	defer testutil.AfterTest(t)
-
-	epc := setupEtcdctlTest(t, &configNoTLS, false)
-	defer func() {
-		if err := epc.Close(); err != nil {
-			t.Fatalf("error closing etcd processes (%v)", err)
-		}
-	}()
-
-	if err := etcdctlRoleAdd(epc, "foo"); err != nil {
-		t.Fatalf("failed to add role (%v)", err)
-	}
-	if err := etcdctlUserAdd(epc, "username", "password"); err != nil {
-		t.Fatalf("failed to add user (%v)", err)
-	}
-	if err := etcdctlUserGrant(epc, "username", "foo"); err != nil {
-		t.Fatalf("failed to grant role (%v)", err)
-	}
-	if err := etcdctlUserGet(epc, "username"); err != nil {
-		t.Fatalf("failed to get user (%v)", err)
-	}
-
-	// ensure double grant gives an error; was crashing in 2.3.1
-	regrantArgs := etcdctlPrefixArgs(epc)
-	regrantArgs = append(regrantArgs, "user", "grant", "--roles", "foo", "username")
-	if err := spawnWithExpect(regrantArgs, "duplicate"); err != nil {
-		t.Fatalf("missing duplicate error on double grant role (%v)", err)
-	}
-}
-
-func TestCtlV2UserListUsername(t *testing.T) { testCtlV2UserList(t, "username") }
-func TestCtlV2UserListRoot(t *testing.T)     { testCtlV2UserList(t, "root") }
-func testCtlV2UserList(t *testing.T, username string) {
-	defer testutil.AfterTest(t)
-
-	epc := setupEtcdctlTest(t, &configNoTLS, false)
-	defer func() {
-		if err := epc.Close(); err != nil {
-			t.Fatalf("error closing etcd processes (%v)", err)
-		}
-	}()
-
-	if err := etcdctlUserAdd(epc, username, "password"); err != nil {
-		t.Fatalf("failed to add user (%v)", err)
-	}
-	if err := etcdctlUserList(epc, username); err != nil {
-		t.Fatalf("failed to list users (%v)", err)
-	}
-}
-
-func TestCtlV2RoleList(t *testing.T) {
-	defer testutil.AfterTest(t)
-
-	epc := setupEtcdctlTest(t, &configNoTLS, false)
-	defer func() {
-		if err := epc.Close(); err != nil {
-			t.Fatalf("error closing etcd processes (%v)", err)
-		}
-	}()
-
-	if err := etcdctlRoleAdd(epc, "foo"); err != nil {
-		t.Fatalf("failed to add role (%v)", err)
-	}
-	if err := etcdctlRoleList(epc, "foo"); err != nil {
-		t.Fatalf("failed to list roles (%v)", err)
-	}
-}
-
-func TestCtlV2Backup(t *testing.T)         { testCtlV2Backup(t, 0, false) }
-func TestCtlV2BackupSnapshot(t *testing.T) { testCtlV2Backup(t, 1, false) }
-
-func TestCtlV2BackupV3(t *testing.T)         { testCtlV2Backup(t, 0, true) }
-func TestCtlV2BackupV3Snapshot(t *testing.T) { testCtlV2Backup(t, 1, true) }
-
-func testCtlV2Backup(t *testing.T, snapCount int, v3 bool) {
-	defer testutil.AfterTest(t)
-
-	backupDir, err := ioutil.TempDir("", "testbackup0.etcd")
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer os.RemoveAll(backupDir)
-
-	etcdCfg := configNoTLS
-	etcdCfg.snapCount = snapCount
-	epc1 := setupEtcdctlTest(t, &etcdCfg, false)
-
-	// v3 put before v2 set so snapshot happens after v3 operations to confirm
-	// v3 data is preserved after snapshot.
-	if err := ctlV3Put(ctlCtx{t: t, epc: epc1}, "v3key", "123", ""); err != nil {
-		t.Fatal(err)
-	}
-
-	if err := etcdctlSet(epc1, "foo1", "bar"); err != nil {
-		t.Fatal(err)
-	}
-
-	if v3 {
-		// v3 must lock the db to backup, so stop process
-		if err := epc1.Stop(); err != nil {
-			t.Fatal(err)
-		}
-	}
-	if err := etcdctlBackup(epc1, epc1.procs[0].Config().dataDirPath, backupDir, v3); err != nil {
-		t.Fatal(err)
-	}
-	if err := epc1.Close(); err != nil {
-		t.Fatalf("error closing etcd processes (%v)", err)
-	}
-
-	// restart from the backup directory
-	cfg2 := configNoTLS
-	cfg2.dataDirPath = backupDir
-	cfg2.keepDataDir = true
-	cfg2.forceNewCluster = true
-	epc2 := setupEtcdctlTest(t, &cfg2, false)
-
-	// check if backup went through correctly
-	if err := etcdctlGet(epc2, "foo1", "bar", false); err != nil {
-		t.Fatal(err)
-	}
-
-	ctx2 := ctlCtx{t: t, epc: epc2}
-	if v3 {
-		if err := ctlV3Get(ctx2, []string{"v3key"}, kv{"v3key", "123"}); err != nil {
-			t.Fatal(err)
-		}
-	} else {
-		if err := ctlV3Get(ctx2, []string{"v3key"}); err != nil {
-			t.Fatal(err)
-		}
-	}
-
-	// check if it can serve client requests
-	if err := etcdctlSet(epc2, "foo2", "bar"); err != nil {
-		t.Fatal(err)
-	}
-	if err := etcdctlGet(epc2, "foo2", "bar", false); err != nil {
-		t.Fatal(err)
-	}
-
-	if err := epc2.Close(); err != nil {
-		t.Fatalf("error closing etcd processes (%v)", err)
-	}
-}
-
-func TestCtlV2AuthWithCommonName(t *testing.T) {
-	defer testutil.AfterTest(t)
-
-	copiedCfg := configClientTLS
-	copiedCfg.clientCertAuthEnabled = true
-
-	epc := setupEtcdctlTest(t, &copiedCfg, false)
-	defer func() {
-		if err := epc.Close(); err != nil {
-			t.Fatalf("error closing etcd processes (%v)", err)
-		}
-	}()
-
-	if err := etcdctlRoleAdd(epc, "testrole"); err != nil {
-		t.Fatalf("failed to add role (%v)", err)
-	}
-	if err := etcdctlRoleGrant(epc, "testrole", "--rw", "--path=/foo"); err != nil {
-		t.Fatalf("failed to grant role (%v)", err)
-	}
-	if err := etcdctlUserAdd(epc, "root", "123"); err != nil {
-		t.Fatalf("failed to add user (%v)", err)
-	}
-	if err := etcdctlUserAdd(epc, "Autogenerated CA", "123"); err != nil {
-		t.Fatalf("failed to add user (%v)", err)
-	}
-	if err := etcdctlUserGrant(epc, "Autogenerated CA", "testrole"); err != nil {
-		t.Fatalf("failed to grant role (%v)", err)
-	}
-	if err := etcdctlAuthEnable(epc); err != nil {
-		t.Fatalf("failed to enable auth (%v)", err)
-	}
-	if err := etcdctlSet(epc, "foo", "bar"); err != nil {
-		t.Fatalf("failed to write (%v)", err)
-	}
-}
-
-func TestCtlV2ClusterHealth(t *testing.T) {
-	defer testutil.AfterTest(t)
-	epc := setupEtcdctlTest(t, &configNoTLS, true)
-	defer func() {
-		if err := epc.Close(); err != nil {
-			t.Fatalf("error closing etcd processes (%v)", err)
-		}
-	}()
-
-	// all members available
-	if err := etcdctlClusterHealth(epc, "cluster is healthy"); err != nil {
-		t.Fatalf("cluster-health expected to be healthy (%v)", err)
-	}
-
-	// missing members, has quorum
-	epc.procs[0].Stop()
-
-	for i := 0; i < 3; i++ {
-		err := etcdctlClusterHealth(epc, "cluster is degraded")
-		if err == nil {
-			break
-		} else if i == 2 {
-			t.Fatalf("cluster-health expected to be degraded (%v)", err)
-		}
-		// possibly no leader yet; retry
-		time.Sleep(time.Second)
-	}
-
-	// no quorum
-	epc.procs[1].Stop()
-	if err := etcdctlClusterHealth(epc, "cluster is unavailable"); err != nil {
-		t.Fatalf("cluster-health expected to be unavailable (%v)", err)
-	}
-
-	epc.procs[0], epc.procs[1] = nil, nil
-}
-
-func etcdctlPrefixArgs(clus *etcdProcessCluster) []string {
-	endpoints := strings.Join(clus.EndpointsV2(), ",")
-	cmdArgs := []string{ctlBinPath, "--endpoints", endpoints}
-	if clus.cfg.clientTLS == clientTLS {
-		cmdArgs = append(cmdArgs, "--ca-file", caPath, "--cert-file", certPath, "--key-file", privateKeyPath)
-	}
-	return cmdArgs
-}
-
-func etcdctlClusterHealth(clus *etcdProcessCluster, val string) error {
-	cmdArgs := append(etcdctlPrefixArgs(clus), "cluster-health")
-	return spawnWithExpect(cmdArgs, val)
-}
-
-func etcdctlSet(clus *etcdProcessCluster, key, value string) error {
-	cmdArgs := append(etcdctlPrefixArgs(clus), "set", key, value)
-	return spawnWithExpect(cmdArgs, value)
-}
-
-func etcdctlMk(clus *etcdProcessCluster, key, value string, first bool) error {
-	cmdArgs := append(etcdctlPrefixArgs(clus), "mk", key, value)
-	if first {
-		return spawnWithExpect(cmdArgs, value)
-	}
-	return spawnWithExpect(cmdArgs, "Error:  105: Key already exists")
-}
-
-func etcdctlGet(clus *etcdProcessCluster, key, value string, quorum bool) error {
-	cmdArgs := append(etcdctlPrefixArgs(clus), "get", key)
-	if quorum {
-		cmdArgs = append(cmdArgs, "--quorum")
-	}
-	return spawnWithExpect(cmdArgs, value)
-}
-
-func etcdctlRm(clus *etcdProcessCluster, key, value string, first bool) error {
-	cmdArgs := append(etcdctlPrefixArgs(clus), "rm", key)
-	if first {
-		return spawnWithExpect(cmdArgs, "PrevNode.Value: "+value)
-	}
-	return spawnWithExpect(cmdArgs, "Error:  100: Key not found")
-}
-
-func etcdctlLs(clus *etcdProcessCluster, key string, quorum bool) error {
-	cmdArgs := append(etcdctlPrefixArgs(clus), "ls")
-	if quorum {
-		cmdArgs = append(cmdArgs, "--quorum")
-	}
-	return spawnWithExpect(cmdArgs, key)
-}
-
-func etcdctlWatch(clus *etcdProcessCluster, key, value string, noSync bool) <-chan error {
-	cmdArgs := append(etcdctlPrefixArgs(clus), "watch", "--after-index=1", key)
-	if noSync {
-		cmdArgs = append(cmdArgs, "--no-sync")
-	}
-	errc := make(chan error, 1)
-	go func() {
-		errc <- spawnWithExpect(cmdArgs, value)
-	}()
-	return errc
-}
-
-func etcdctlRoleAdd(clus *etcdProcessCluster, role string) error {
-	cmdArgs := append(etcdctlPrefixArgs(clus), "role", "add", role)
-	return spawnWithExpect(cmdArgs, role)
-}
-
-func etcdctlRoleGrant(clus *etcdProcessCluster, role string, perms ...string) error {
-	cmdArgs := append(etcdctlPrefixArgs(clus), "role", "grant")
-	cmdArgs = append(cmdArgs, perms...)
-	cmdArgs = append(cmdArgs, role)
-	return spawnWithExpect(cmdArgs, role)
-}
-
-func etcdctlRoleList(clus *etcdProcessCluster, expectedRole string) error {
-	cmdArgs := append(etcdctlPrefixArgs(clus), "role", "list")
-	return spawnWithExpect(cmdArgs, expectedRole)
-}
-
-func etcdctlUserAdd(clus *etcdProcessCluster, user, pass string) error {
-	cmdArgs := append(etcdctlPrefixArgs(clus), "user", "add", user+":"+pass)
-	return spawnWithExpect(cmdArgs, "User "+user+" created")
-}
-
-func etcdctlUserGrant(clus *etcdProcessCluster, user, role string) error {
-	cmdArgs := append(etcdctlPrefixArgs(clus), "user", "grant", "--roles", role, user)
-	return spawnWithExpect(cmdArgs, "User "+user+" updated")
-}
-
-func etcdctlUserGet(clus *etcdProcessCluster, user string) error {
-	cmdArgs := append(etcdctlPrefixArgs(clus), "user", "get", user)
-	return spawnWithExpect(cmdArgs, "User: "+user)
-}
-
-func etcdctlUserList(clus *etcdProcessCluster, expectedUser string) error {
-	cmdArgs := append(etcdctlPrefixArgs(clus), "user", "list")
-	return spawnWithExpect(cmdArgs, expectedUser)
-}
-
-func etcdctlAuthEnable(clus *etcdProcessCluster) error {
-	cmdArgs := append(etcdctlPrefixArgs(clus), "auth", "enable")
-	return spawnWithExpect(cmdArgs, "Authentication Enabled")
-}
-
-func etcdctlBackup(clus *etcdProcessCluster, dataDir, backupDir string, v3 bool) error {
-	cmdArgs := append(etcdctlPrefixArgs(clus), "backup", "--data-dir", dataDir, "--backup-dir", backupDir)
-	if v3 {
-		cmdArgs = append(cmdArgs, "--with-v3")
-	}
-	proc, err := spawnCmd(cmdArgs)
-	if err != nil {
-		return err
-	}
-	return proc.Close()
-}
-
-func mustEtcdctl(t *testing.T) {
-	if !fileutil.Exist(binDir + "/etcdctl") {
-		t.Fatalf("could not find etcdctl binary")
-	}
-}
-
-func setupEtcdctlTest(t *testing.T, cfg *etcdProcessClusterConfig, quorum bool) *etcdProcessCluster {
-	mustEtcdctl(t)
-	if !quorum {
-		cfg = configStandalone(*cfg)
-	}
-	epc, err := newEtcdProcessCluster(cfg)
-	if err != nil {
-		t.Fatalf("could not start etcd process cluster (%v)", err)
-	}
-	return epc
-}

+ 0 - 105
e2e/ctl_v3_alarm_test.go

@@ -1,105 +0,0 @@
-// Copyright 2016 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 e2e
-
-import (
-	"context"
-	"os"
-	"strings"
-	"testing"
-	"time"
-
-	"github.com/coreos/etcd/clientv3"
-)
-
-func TestCtlV3Alarm(t *testing.T) {
-	// The boltdb minimum working set is six pages.
-	testCtl(t, alarmTest, withQuota(int64(13*os.Getpagesize())))
-}
-
-func alarmTest(cx ctlCtx) {
-	// test small put still works
-	smallbuf := strings.Repeat("a", 64)
-	if err := ctlV3Put(cx, "1st_test", smallbuf, ""); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// write some chunks to fill up the database
-	buf := strings.Repeat("b", int(os.Getpagesize()))
-	for {
-		if err := ctlV3Put(cx, "2nd_test", buf, ""); err != nil {
-			if !strings.Contains(err.Error(), "etcdserver: mvcc: database space exceeded") {
-				cx.t.Fatal(err)
-			}
-			break
-		}
-	}
-
-	// quota alarm should now be on
-	if err := ctlV3Alarm(cx, "list", "alarm:NOSPACE"); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// '/health' handler should return 'false'
-	if err := cURLGet(cx.epc, cURLReq{endpoint: "/health", expected: `{"health":"false"}`}); err != nil {
-		cx.t.Fatalf("failed get with curl (%v)", err)
-	}
-
-	// check that Put is rejected when alarm is on
-	if err := ctlV3Put(cx, "3rd_test", smallbuf, ""); err != nil {
-		if !strings.Contains(err.Error(), "etcdserver: mvcc: database space exceeded") {
-			cx.t.Fatal(err)
-		}
-	}
-
-	eps := cx.epc.EndpointsV3()
-
-	// get latest revision to compact
-	cli, err := clientv3.New(clientv3.Config{
-		Endpoints:   eps,
-		DialTimeout: 3 * time.Second,
-	})
-	if err != nil {
-		cx.t.Fatal(err)
-	}
-	defer cli.Close()
-	sresp, err := cli.Status(context.TODO(), eps[0])
-	if err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// make some space
-	if err := ctlV3Compact(cx, sresp.Header.Revision, true); err != nil {
-		cx.t.Fatal(err)
-	}
-	if err := ctlV3Defrag(cx); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// turn off alarm
-	if err := ctlV3Alarm(cx, "disarm", "alarm:NOSPACE"); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// put one more key below quota
-	if err := ctlV3Put(cx, "4th_test", smallbuf, ""); err != nil {
-		cx.t.Fatal(err)
-	}
-}
-
-func ctlV3Alarm(cx ctlCtx, cmd string, as ...string) error {
-	cmdArgs := append(cx.PrefixArgs(), "alarm", cmd)
-	return spawnWithExpects(cmdArgs, as...)
-}

+ 0 - 1055
e2e/ctl_v3_auth_test.go

@@ -1,1055 +0,0 @@
-// Copyright 2016 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 e2e
-
-import (
-	"fmt"
-	"os"
-	"testing"
-
-	"github.com/coreos/etcd/clientv3"
-)
-
-func TestCtlV3AuthEnable(t *testing.T)              { testCtl(t, authEnableTest) }
-func TestCtlV3AuthDisable(t *testing.T)             { testCtl(t, authDisableTest) }
-func TestCtlV3AuthWriteKey(t *testing.T)            { testCtl(t, authCredWriteKeyTest) }
-func TestCtlV3AuthRoleUpdate(t *testing.T)          { testCtl(t, authRoleUpdateTest) }
-func TestCtlV3AuthUserDeleteDuringOps(t *testing.T) { testCtl(t, authUserDeleteDuringOpsTest) }
-func TestCtlV3AuthRoleRevokeDuringOps(t *testing.T) { testCtl(t, authRoleRevokeDuringOpsTest) }
-func TestCtlV3AuthTxn(t *testing.T)                 { testCtl(t, authTestTxn) }
-func TestCtlV3AuthPrefixPerm(t *testing.T)          { testCtl(t, authTestPrefixPerm) }
-func TestCtlV3AuthMemberAdd(t *testing.T)           { testCtl(t, authTestMemberAdd) }
-func TestCtlV3AuthMemberRemove(t *testing.T) {
-	testCtl(t, authTestMemberRemove, withQuorum(), withNoStrictReconfig())
-}
-func TestCtlV3AuthMemberUpdate(t *testing.T)     { testCtl(t, authTestMemberUpdate) }
-func TestCtlV3AuthCertCN(t *testing.T)           { testCtl(t, authTestCertCN, withCfg(configClientTLSCertAuth)) }
-func TestCtlV3AuthRevokeWithDelete(t *testing.T) { testCtl(t, authTestRevokeWithDelete) }
-func TestCtlV3AuthInvalidMgmt(t *testing.T)      { testCtl(t, authTestInvalidMgmt) }
-func TestCtlV3AuthFromKeyPerm(t *testing.T)      { testCtl(t, authTestFromKeyPerm) }
-func TestCtlV3AuthAndWatch(t *testing.T)         { testCtl(t, authTestWatch) }
-
-func TestCtlV3AuthLeaseTestKeepAlive(t *testing.T)         { testCtl(t, authLeaseTestKeepAlive) }
-func TestCtlV3AuthLeaseTestTimeToLiveExpired(t *testing.T) { testCtl(t, authLeaseTestTimeToLiveExpired) }
-
-func TestCtlV3AuthRoleGet(t *testing.T)  { testCtl(t, authTestRoleGet) }
-func TestCtlV3AuthUserGet(t *testing.T)  { testCtl(t, authTestUserGet) }
-func TestCtlV3AuthRoleList(t *testing.T) { testCtl(t, authTestRoleList) }
-
-func TestCtlV3AuthDefrag(t *testing.T) { testCtl(t, authTestDefrag) }
-func TestCtlV3AuthEndpointHealth(t *testing.T) {
-	testCtl(t, authTestEndpointHealth, withQuorum())
-}
-func TestCtlV3AuthSnapshot(t *testing.T) { testCtl(t, authTestSnapshot) }
-func TestCtlV3AuthCertCNAndUsername(t *testing.T) {
-	testCtl(t, authTestCertCNAndUsername, withCfg(configClientTLSCertAuth))
-}
-
-func authEnableTest(cx ctlCtx) {
-	if err := authEnable(cx); err != nil {
-		cx.t.Fatal(err)
-	}
-}
-
-func authEnable(cx ctlCtx) error {
-	// create root user with root role
-	if err := ctlV3User(cx, []string{"add", "root", "--interactive=false"}, "User root created", []string{"root"}); err != nil {
-		return fmt.Errorf("failed to create root user %v", err)
-	}
-	if err := ctlV3User(cx, []string{"grant-role", "root", "root"}, "Role root is granted to user root", nil); err != nil {
-		return fmt.Errorf("failed to grant root user root role %v", err)
-	}
-	if err := ctlV3AuthEnable(cx); err != nil {
-		return fmt.Errorf("authEnableTest ctlV3AuthEnable error (%v)", err)
-	}
-	return nil
-}
-
-func ctlV3AuthEnable(cx ctlCtx) error {
-	cmdArgs := append(cx.PrefixArgs(), "auth", "enable")
-	return spawnWithExpect(cmdArgs, "Authentication Enabled")
-}
-
-func authDisableTest(cx ctlCtx) {
-	// a key that isn't granted to test-user
-	if err := ctlV3Put(cx, "hoo", "a", ""); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	if err := authEnable(cx); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	cx.user, cx.pass = "root", "root"
-	authSetupTestUser(cx)
-
-	// test-user doesn't have the permission, it must fail
-	cx.user, cx.pass = "test-user", "pass"
-	if err := ctlV3PutFailPerm(cx, "hoo", "bar"); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	cx.user, cx.pass = "root", "root"
-	if err := ctlV3AuthDisable(cx); err != nil {
-		cx.t.Fatalf("authDisableTest ctlV3AuthDisable error (%v)", err)
-	}
-
-	// now ErrAuthNotEnabled of Authenticate() is simply ignored
-	cx.user, cx.pass = "test-user", "pass"
-	if err := ctlV3Put(cx, "hoo", "bar", ""); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// now the key can be accessed
-	cx.user, cx.pass = "", ""
-	if err := ctlV3Put(cx, "hoo", "bar", ""); err != nil {
-		cx.t.Fatal(err)
-	}
-	// confirm put succeeded
-	if err := ctlV3Get(cx, []string{"hoo"}, []kv{{"hoo", "bar"}}...); err != nil {
-		cx.t.Fatal(err)
-	}
-}
-
-func ctlV3AuthDisable(cx ctlCtx) error {
-	cmdArgs := append(cx.PrefixArgs(), "auth", "disable")
-	return spawnWithExpect(cmdArgs, "Authentication Disabled")
-}
-
-func authCredWriteKeyTest(cx ctlCtx) {
-	// baseline key to check for failed puts
-	if err := ctlV3Put(cx, "foo", "a", ""); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	if err := authEnable(cx); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	cx.user, cx.pass = "root", "root"
-	authSetupTestUser(cx)
-
-	// confirm root role can access to all keys
-	if err := ctlV3Put(cx, "foo", "bar", ""); err != nil {
-		cx.t.Fatal(err)
-	}
-	if err := ctlV3Get(cx, []string{"foo"}, []kv{{"foo", "bar"}}...); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// try invalid user
-	cx.user, cx.pass = "a", "b"
-	if err := ctlV3PutFailAuth(cx, "foo", "bar"); err != nil {
-		cx.t.Fatal(err)
-	}
-	// confirm put failed
-	cx.user, cx.pass = "test-user", "pass"
-	if err := ctlV3Get(cx, []string{"foo"}, []kv{{"foo", "bar"}}...); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// try good user
-	cx.user, cx.pass = "test-user", "pass"
-	if err := ctlV3Put(cx, "foo", "bar2", ""); err != nil {
-		cx.t.Fatal(err)
-	}
-	// confirm put succeeded
-	if err := ctlV3Get(cx, []string{"foo"}, []kv{{"foo", "bar2"}}...); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// try bad password
-	cx.user, cx.pass = "test-user", "badpass"
-	if err := ctlV3PutFailAuth(cx, "foo", "baz"); err != nil {
-		cx.t.Fatal(err)
-	}
-	// confirm put failed
-	cx.user, cx.pass = "test-user", "pass"
-	if err := ctlV3Get(cx, []string{"foo"}, []kv{{"foo", "bar2"}}...); err != nil {
-		cx.t.Fatal(err)
-	}
-}
-
-func authRoleUpdateTest(cx ctlCtx) {
-	if err := ctlV3Put(cx, "foo", "bar", ""); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	if err := authEnable(cx); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	cx.user, cx.pass = "root", "root"
-	authSetupTestUser(cx)
-
-	// try put to not granted key
-	cx.user, cx.pass = "test-user", "pass"
-	if err := ctlV3PutFailPerm(cx, "hoo", "bar"); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// grant a new key
-	cx.user, cx.pass = "root", "root"
-	if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, "hoo", "", false}); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// try a newly granted key
-	cx.user, cx.pass = "test-user", "pass"
-	if err := ctlV3Put(cx, "hoo", "bar", ""); err != nil {
-		cx.t.Fatal(err)
-	}
-	// confirm put succeeded
-	if err := ctlV3Get(cx, []string{"hoo"}, []kv{{"hoo", "bar"}}...); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// revoke the newly granted key
-	cx.user, cx.pass = "root", "root"
-	if err := ctlV3RoleRevokePermission(cx, "test-role", "hoo", "", false); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// try put to the revoked key
-	cx.user, cx.pass = "test-user", "pass"
-	if err := ctlV3PutFailPerm(cx, "hoo", "bar"); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// confirm a key still granted can be accessed
-	if err := ctlV3Get(cx, []string{"foo"}, []kv{{"foo", "bar"}}...); err != nil {
-		cx.t.Fatal(err)
-	}
-}
-
-func authUserDeleteDuringOpsTest(cx ctlCtx) {
-	if err := ctlV3Put(cx, "foo", "bar", ""); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	if err := authEnable(cx); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	cx.user, cx.pass = "root", "root"
-	authSetupTestUser(cx)
-
-	// create a key
-	cx.user, cx.pass = "test-user", "pass"
-	if err := ctlV3Put(cx, "foo", "bar", ""); err != nil {
-		cx.t.Fatal(err)
-	}
-	// confirm put succeeded
-	if err := ctlV3Get(cx, []string{"foo"}, []kv{{"foo", "bar"}}...); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// delete the user
-	cx.user, cx.pass = "root", "root"
-	err := ctlV3User(cx, []string{"delete", "test-user"}, "User test-user deleted", []string{})
-	if err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// check the user is deleted
-	cx.user, cx.pass = "test-user", "pass"
-	if err := ctlV3PutFailAuth(cx, "foo", "baz"); err != nil {
-		cx.t.Fatal(err)
-	}
-}
-
-func authRoleRevokeDuringOpsTest(cx ctlCtx) {
-	if err := ctlV3Put(cx, "foo", "bar", ""); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	if err := authEnable(cx); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	cx.user, cx.pass = "root", "root"
-	authSetupTestUser(cx)
-
-	// create a key
-	cx.user, cx.pass = "test-user", "pass"
-	if err := ctlV3Put(cx, "foo", "bar", ""); err != nil {
-		cx.t.Fatal(err)
-	}
-	// confirm put succeeded
-	if err := ctlV3Get(cx, []string{"foo"}, []kv{{"foo", "bar"}}...); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// create a new role
-	cx.user, cx.pass = "root", "root"
-	if err := ctlV3Role(cx, []string{"add", "test-role2"}, "Role test-role2 created"); err != nil {
-		cx.t.Fatal(err)
-	}
-	// grant a new key to the new role
-	if err := ctlV3RoleGrantPermission(cx, "test-role2", grantingPerm{true, true, "hoo", "", false}); err != nil {
-		cx.t.Fatal(err)
-	}
-	// grant the new role to the user
-	if err := ctlV3User(cx, []string{"grant-role", "test-user", "test-role2"}, "Role test-role2 is granted to user test-user", nil); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// try a newly granted key
-	cx.user, cx.pass = "test-user", "pass"
-	if err := ctlV3Put(cx, "hoo", "bar", ""); err != nil {
-		cx.t.Fatal(err)
-	}
-	// confirm put succeeded
-	if err := ctlV3Get(cx, []string{"hoo"}, []kv{{"hoo", "bar"}}...); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// revoke a role from the user
-	cx.user, cx.pass = "root", "root"
-	err := ctlV3User(cx, []string{"revoke-role", "test-user", "test-role"}, "Role test-role is revoked from user test-user", []string{})
-	if err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// check the role is revoked and permission is lost from the user
-	cx.user, cx.pass = "test-user", "pass"
-	if err := ctlV3PutFailPerm(cx, "foo", "baz"); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// try a key that can be accessed from the remaining role
-	cx.user, cx.pass = "test-user", "pass"
-	if err := ctlV3Put(cx, "hoo", "bar2", ""); err != nil {
-		cx.t.Fatal(err)
-	}
-	// confirm put succeeded
-	if err := ctlV3Get(cx, []string{"hoo"}, []kv{{"hoo", "bar2"}}...); err != nil {
-		cx.t.Fatal(err)
-	}
-}
-
-func ctlV3PutFailAuth(cx ctlCtx, key, val string) error {
-	return spawnWithExpect(append(cx.PrefixArgs(), "put", key, val), "authentication failed")
-}
-
-func ctlV3PutFailPerm(cx ctlCtx, key, val string) error {
-	return spawnWithExpect(append(cx.PrefixArgs(), "put", key, val), "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 := spawnWithExpect(append(cx.PrefixArgs(), "role", "add", "test-role"), "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 := spawnWithExpect(cmd, "Role test-role updated"); err != nil {
-		cx.t.Fatal(err)
-	}
-}
-
-func authTestTxn(cx ctlCtx) {
-	// keys with 1 suffix aren't granted to test-user
-	// keys with 2 suffix are granted to test-user
-
-	keys := []string{"c1", "s1", "f1"}
-	grantedKeys := []string{"c2", "s2", "f2"}
-	for _, key := range keys {
-		if err := ctlV3Put(cx, key, "v", ""); err != nil {
-			cx.t.Fatal(err)
-		}
-	}
-
-	for _, key := range grantedKeys {
-		if err := ctlV3Put(cx, key, "v", ""); err != nil {
-			cx.t.Fatal(err)
-		}
-	}
-
-	if err := authEnable(cx); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	cx.user, cx.pass = "root", "root"
-	authSetupTestUser(cx)
-
-	// grant keys to test-user
-	cx.user, cx.pass = "root", "root"
-	for _, key := range grantedKeys {
-		if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, key, "", false}); err != nil {
-			cx.t.Fatal(err)
-		}
-	}
-
-	// now test txn
-	cx.interactive = true
-	cx.user, cx.pass = "test-user", "pass"
-
-	rqs := txnRequests{
-		compare:  []string{`version("c2") = "1"`},
-		ifSucess: []string{"get s2"},
-		ifFail:   []string{"get f2"},
-		results:  []string{"SUCCESS", "s2", "v"},
-	}
-	if err := ctlV3Txn(cx, rqs); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// a key of compare case isn't granted
-	rqs = txnRequests{
-		compare:  []string{`version("c1") = "1"`},
-		ifSucess: []string{"get s2"},
-		ifFail:   []string{"get f2"},
-		results:  []string{"Error: etcdserver: permission denied"},
-	}
-	if err := ctlV3Txn(cx, rqs); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// a key of success case isn't granted
-	rqs = txnRequests{
-		compare:  []string{`version("c2") = "1"`},
-		ifSucess: []string{"get s1"},
-		ifFail:   []string{"get f2"},
-		results:  []string{"Error: etcdserver: permission denied"},
-	}
-	if err := ctlV3Txn(cx, rqs); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// a key of failure case isn't granted
-	rqs = txnRequests{
-		compare:  []string{`version("c2") = "1"`},
-		ifSucess: []string{"get s2"},
-		ifFail:   []string{"get f1"},
-		results:  []string{"Error: etcdserver: permission denied"},
-	}
-	if err := ctlV3Txn(cx, rqs); err != nil {
-		cx.t.Fatal(err)
-	}
-}
-
-func authTestPrefixPerm(cx ctlCtx) {
-	if err := authEnable(cx); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	cx.user, cx.pass = "root", "root"
-	authSetupTestUser(cx)
-
-	prefix := "/prefix/" // directory like prefix
-	// grant keys to test-user
-	cx.user, cx.pass = "root", "root"
-	if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, prefix, "", true}); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// try a prefix granted permission
-	cx.user, cx.pass = "test-user", "pass"
-	for i := 0; i < 10; i++ {
-		key := fmt.Sprintf("%s%d", prefix, i)
-		if err := ctlV3Put(cx, key, "val", ""); err != nil {
-			cx.t.Fatal(err)
-		}
-	}
-
-	if err := ctlV3PutFailPerm(cx, clientv3.GetPrefixRangeEnd(prefix), "baz"); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// grant the entire keys to test-user
-	cx.user, cx.pass = "root", "root"
-	if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, "", "", true}); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	prefix2 := "/prefix2/"
-	cx.user, cx.pass = "test-user", "pass"
-	for i := 0; i < 10; i++ {
-		key := fmt.Sprintf("%s%d", prefix2, i)
-		if err := ctlV3Put(cx, key, "val", ""); err != nil {
-			cx.t.Fatal(err)
-		}
-	}
-}
-
-func authTestMemberAdd(cx ctlCtx) {
-	if err := authEnable(cx); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	cx.user, cx.pass = "root", "root"
-	authSetupTestUser(cx)
-
-	peerURL := fmt.Sprintf("http://localhost:%d", etcdProcessBasePort+11)
-	// ordinary user cannot add a new member
-	cx.user, cx.pass = "test-user", "pass"
-	if err := ctlV3MemberAdd(cx, peerURL); err == nil {
-		cx.t.Fatalf("ordinary user must not be allowed to add a member")
-	}
-
-	// root can add a new member
-	cx.user, cx.pass = "root", "root"
-	if err := ctlV3MemberAdd(cx, peerURL); err != nil {
-		cx.t.Fatal(err)
-	}
-}
-
-func authTestMemberRemove(cx ctlCtx) {
-	if err := authEnable(cx); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	cx.user, cx.pass = "root", "root"
-	authSetupTestUser(cx)
-
-	ep, memIDToRemove, clusterID := cx.memberToRemove()
-
-	// ordinary user cannot remove a member
-	cx.user, cx.pass = "test-user", "pass"
-	if err := ctlV3MemberRemove(cx, ep, memIDToRemove, clusterID); err == nil {
-		cx.t.Fatalf("ordinary user must not be allowed to remove a member")
-	}
-
-	// root can remove a member
-	cx.user, cx.pass = "root", "root"
-	if err := ctlV3MemberRemove(cx, ep, memIDToRemove, clusterID); err != nil {
-		cx.t.Fatal(err)
-	}
-}
-
-func authTestMemberUpdate(cx ctlCtx) {
-	if err := authEnable(cx); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	cx.user, cx.pass = "root", "root"
-	authSetupTestUser(cx)
-
-	mr, err := getMemberList(cx)
-	if err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// ordinary user cannot update a member
-	cx.user, cx.pass = "test-user", "pass"
-	peerURL := fmt.Sprintf("http://localhost:%d", etcdProcessBasePort+11)
-	memberID := fmt.Sprintf("%x", mr.Members[0].ID)
-	if err = ctlV3MemberUpdate(cx, memberID, peerURL); err == nil {
-		cx.t.Fatalf("ordinary user must not be allowed to update a member")
-	}
-
-	// root can update a member
-	cx.user, cx.pass = "root", "root"
-	if err = ctlV3MemberUpdate(cx, memberID, peerURL); err != nil {
-		cx.t.Fatal(err)
-	}
-}
-
-func authTestCertCN(cx ctlCtx) {
-	if err := authEnable(cx); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	cx.user, cx.pass = "root", "root"
-	if err := ctlV3User(cx, []string{"add", "example.com", "--interactive=false"}, "User example.com created", []string{""}); err != nil {
-		cx.t.Fatal(err)
-	}
-	if err := spawnWithExpect(append(cx.PrefixArgs(), "role", "add", "test-role"), "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 {
-		cx.t.Fatal(err)
-	}
-
-	// grant a new key
-	if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, "hoo", "", false}); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// try a granted key
-	cx.user, cx.pass = "", ""
-	if err := ctlV3Put(cx, "hoo", "bar", ""); err != nil {
-		cx.t.Error(err)
-	}
-
-	// try a non granted key
-	cx.user, cx.pass = "", ""
-	if err := ctlV3PutFailPerm(cx, "baz", "bar"); err != nil {
-		cx.t.Error(err)
-	}
-}
-
-func authTestRevokeWithDelete(cx ctlCtx) {
-	if err := authEnable(cx); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	cx.user, cx.pass = "root", "root"
-	authSetupTestUser(cx)
-
-	// create a new role
-	cx.user, cx.pass = "root", "root"
-	if err := ctlV3Role(cx, []string{"add", "test-role2"}, "Role test-role2 created"); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// grant the new role to the user
-	if err := ctlV3User(cx, []string{"grant-role", "test-user", "test-role2"}, "Role test-role2 is granted to user test-user", nil); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// check the result
-	if err := ctlV3User(cx, []string{"get", "test-user"}, "Roles: test-role test-role2", nil); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// delete the role, test-role2 must be revoked from test-user
-	if err := ctlV3Role(cx, []string{"delete", "test-role2"}, "Role test-role2 deleted"); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// check the result
-	if err := ctlV3User(cx, []string{"get", "test-user"}, "Roles: test-role", nil); err != nil {
-		cx.t.Fatal(err)
-	}
-}
-
-func authTestInvalidMgmt(cx ctlCtx) {
-	if err := authEnable(cx); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	if err := ctlV3Role(cx, []string{"delete", "root"}, "Error: etcdserver: invalid auth management"); err == nil {
-		cx.t.Fatal("deleting the role root must not be allowed")
-	}
-
-	if err := ctlV3User(cx, []string{"revoke-role", "root", "root"}, "Error: etcdserver: invalid auth management", []string{}); err == nil {
-		cx.t.Fatal("revoking the role root from the user root must not be allowed")
-	}
-}
-
-func authTestFromKeyPerm(cx ctlCtx) {
-	if err := authEnable(cx); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	cx.user, cx.pass = "root", "root"
-	authSetupTestUser(cx)
-
-	// grant keys after z to test-user
-	cx.user, cx.pass = "root", "root"
-	if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, "z", "\x00", false}); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// try the granted open ended permission
-	cx.user, cx.pass = "test-user", "pass"
-	for i := 0; i < 10; i++ {
-		key := fmt.Sprintf("z%d", i)
-		if err := ctlV3Put(cx, key, "val", ""); err != nil {
-			cx.t.Fatal(err)
-		}
-	}
-	largeKey := ""
-	for i := 0; i < 10; i++ {
-		largeKey += "\xff"
-		if err := ctlV3Put(cx, largeKey, "val", ""); err != nil {
-			cx.t.Fatal(err)
-		}
-	}
-
-	// try a non granted key
-	if err := ctlV3PutFailPerm(cx, "x", "baz"); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// revoke the open ended permission
-	cx.user, cx.pass = "root", "root"
-	if err := ctlV3RoleRevokePermission(cx, "test-role", "z", "", true); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// try the revoked open ended permission
-	cx.user, cx.pass = "test-user", "pass"
-	for i := 0; i < 10; i++ {
-		key := fmt.Sprintf("z%d", i)
-		if err := ctlV3PutFailPerm(cx, key, "val"); err != nil {
-			cx.t.Fatal(err)
-		}
-	}
-
-	// grant the entire keys
-	cx.user, cx.pass = "root", "root"
-	if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, "", "\x00", false}); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// try keys, of course it must be allowed because test-role has a permission of the entire keys
-	cx.user, cx.pass = "test-user", "pass"
-	for i := 0; i < 10; i++ {
-		key := fmt.Sprintf("z%d", i)
-		if err := ctlV3Put(cx, key, "val", ""); err != nil {
-			cx.t.Fatal(err)
-		}
-	}
-
-	// revoke the entire keys
-	cx.user, cx.pass = "root", "root"
-	if err := ctlV3RoleRevokePermission(cx, "test-role", "", "", true); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// try the revoked entire key permission
-	cx.user, cx.pass = "test-user", "pass"
-	for i := 0; i < 10; i++ {
-		key := fmt.Sprintf("z%d", i)
-		if err := ctlV3PutFailPerm(cx, key, "val"); err != nil {
-			cx.t.Fatal(err)
-		}
-	}
-}
-
-func authLeaseTestKeepAlive(cx ctlCtx) {
-	if err := authEnable(cx); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	cx.user, cx.pass = "root", "root"
-	authSetupTestUser(cx)
-	// put with TTL 10 seconds and keep-alive
-	leaseID, err := ctlV3LeaseGrant(cx, 10)
-	if err != nil {
-		cx.t.Fatalf("leaseTestKeepAlive: ctlV3LeaseGrant error (%v)", err)
-	}
-	if err := ctlV3Put(cx, "key", "val", leaseID); err != nil {
-		cx.t.Fatalf("leaseTestKeepAlive: ctlV3Put error (%v)", err)
-	}
-	if err := ctlV3LeaseKeepAlive(cx, leaseID); err != nil {
-		cx.t.Fatalf("leaseTestKeepAlive: ctlV3LeaseKeepAlive error (%v)", err)
-	}
-	if err := ctlV3Get(cx, []string{"key"}, kv{"key", "val"}); err != nil {
-		cx.t.Fatalf("leaseTestKeepAlive: ctlV3Get error (%v)", err)
-	}
-}
-
-func authLeaseTestTimeToLiveExpired(cx ctlCtx) {
-	if err := authEnable(cx); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	cx.user, cx.pass = "root", "root"
-	authSetupTestUser(cx)
-
-	ttl := 3
-	if err := leaseTestTimeToLiveExpire(cx, ttl); err != nil {
-		cx.t.Fatal(err)
-	}
-}
-
-func authTestWatch(cx ctlCtx) {
-	if err := authEnable(cx); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	cx.user, cx.pass = "root", "root"
-	authSetupTestUser(cx)
-
-	// grant a key range
-	if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, "key", "key4", false}); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	tests := []struct {
-		puts []kv
-		args []string
-
-		wkv  []kvExec
-		want bool
-	}{
-		{ // watch 1 key, should be successful
-			[]kv{{"key", "value"}},
-			[]string{"key", "--rev", "1"},
-			[]kvExec{{key: "key", val: "value"}},
-			true,
-		},
-		{ // watch 3 keys by range, should be successful
-			[]kv{{"key1", "val1"}, {"key3", "val3"}, {"key2", "val2"}},
-			[]string{"key", "key3", "--rev", "1"},
-			[]kvExec{{key: "key1", val: "val1"}, {key: "key2", val: "val2"}},
-			true,
-		},
-
-		{ // watch 1 key, should not be successful
-			[]kv{},
-			[]string{"key5", "--rev", "1"},
-			[]kvExec{},
-			false,
-		},
-		{ // watch 3 keys by range, should not be successful
-			[]kv{},
-			[]string{"key", "key6", "--rev", "1"},
-			[]kvExec{},
-			false,
-		},
-	}
-
-	cx.user, cx.pass = "test-user", "pass"
-	for i, tt := range tests {
-		donec := make(chan struct{})
-		go func(i int, puts []kv) {
-			defer close(donec)
-			for j := range puts {
-				if err := ctlV3Put(cx, puts[j].key, puts[j].val, ""); err != nil {
-					cx.t.Fatalf("watchTest #%d-%d: ctlV3Put error (%v)", i, j, err)
-				}
-			}
-		}(i, tt.puts)
-
-		var err error
-		if tt.want {
-			err = ctlV3Watch(cx, tt.args, tt.wkv...)
-		} else {
-			err = ctlV3WatchFailPerm(cx, tt.args)
-		}
-
-		if err != nil {
-			if cx.dialTimeout > 0 && !isGRPCTimedout(err) {
-				cx.t.Errorf("watchTest #%d: ctlV3Watch error (%v)", i, err)
-			}
-		}
-
-		<-donec
-	}
-
-}
-
-func authTestRoleGet(cx ctlCtx) {
-	if err := authEnable(cx); err != nil {
-		cx.t.Fatal(err)
-	}
-	cx.user, cx.pass = "root", "root"
-	authSetupTestUser(cx)
-
-	expected := []string{
-		"Role test-role",
-		"KV Read:", "foo",
-		"KV Write:", "foo",
-	}
-	if err := spawnWithExpects(append(cx.PrefixArgs(), "role", "get", "test-role"), expected...); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// test-user can get the information of test-role because it belongs to the role
-	cx.user, cx.pass = "test-user", "pass"
-	if err := spawnWithExpects(append(cx.PrefixArgs(), "role", "get", "test-role"), expected...); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// test-user cannot get the information of root because it doesn't belong to the role
-	expected = []string{
-		"Error: etcdserver: permission denied",
-	}
-	if err := spawnWithExpects(append(cx.PrefixArgs(), "role", "get", "root"), expected...); err != nil {
-		cx.t.Fatal(err)
-	}
-}
-
-func authTestUserGet(cx ctlCtx) {
-	if err := authEnable(cx); err != nil {
-		cx.t.Fatal(err)
-	}
-	cx.user, cx.pass = "root", "root"
-	authSetupTestUser(cx)
-
-	expected := []string{
-		"User: test-user",
-		"Roles: test-role",
-	}
-
-	if err := spawnWithExpects(append(cx.PrefixArgs(), "user", "get", "test-user"), expected...); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// test-user can get the information of test-user itself
-	cx.user, cx.pass = "test-user", "pass"
-	if err := spawnWithExpects(append(cx.PrefixArgs(), "user", "get", "test-user"), expected...); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// test-user cannot get the information of root
-	expected = []string{
-		"Error: etcdserver: permission denied",
-	}
-	if err := spawnWithExpects(append(cx.PrefixArgs(), "user", "get", "root"), expected...); err != nil {
-		cx.t.Fatal(err)
-	}
-}
-
-func authTestRoleList(cx ctlCtx) {
-	if err := authEnable(cx); err != nil {
-		cx.t.Fatal(err)
-	}
-	cx.user, cx.pass = "root", "root"
-	authSetupTestUser(cx)
-	if err := spawnWithExpect(append(cx.PrefixArgs(), "role", "list"), "test-role"); err != nil {
-		cx.t.Fatal(err)
-	}
-}
-
-func authTestDefrag(cx ctlCtx) {
-	maintenanceInitKeys(cx)
-
-	if err := authEnable(cx); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	cx.user, cx.pass = "root", "root"
-	authSetupTestUser(cx)
-
-	// ordinary user cannot defrag
-	cx.user, cx.pass = "test-user", "pass"
-	if err := ctlV3Defrag(cx); err == nil {
-		cx.t.Fatal("ordinary user should not be able to issue a defrag request")
-	}
-
-	// root can defrag
-	cx.user, cx.pass = "root", "root"
-	if err := ctlV3Defrag(cx); err != nil {
-		cx.t.Fatal(err)
-	}
-}
-
-func authTestSnapshot(cx ctlCtx) {
-	maintenanceInitKeys(cx)
-
-	if err := authEnable(cx); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	cx.user, cx.pass = "root", "root"
-	authSetupTestUser(cx)
-
-	fpath := "test.snapshot"
-	defer os.RemoveAll(fpath)
-
-	// ordinary user cannot save a snapshot
-	cx.user, cx.pass = "test-user", "pass"
-	if err := ctlV3SnapshotSave(cx, fpath); err == nil {
-		cx.t.Fatal("ordinary user should not be able to save a snapshot")
-	}
-
-	// root can save a snapshot
-	cx.user, cx.pass = "root", "root"
-	if err := ctlV3SnapshotSave(cx, fpath); err != nil {
-		cx.t.Fatalf("snapshotTest ctlV3SnapshotSave error (%v)", err)
-	}
-
-	st, err := getSnapshotStatus(cx, fpath)
-	if err != nil {
-		cx.t.Fatalf("snapshotTest getSnapshotStatus error (%v)", err)
-	}
-	if st.Revision != 4 {
-		cx.t.Fatalf("expected 4, got %d", st.Revision)
-	}
-	if st.TotalKey < 3 {
-		cx.t.Fatalf("expected at least 3, got %d", st.TotalKey)
-	}
-}
-
-func authTestEndpointHealth(cx ctlCtx) {
-	if err := authEnable(cx); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	cx.user, cx.pass = "root", "root"
-	authSetupTestUser(cx)
-
-	if err := ctlV3EndpointHealth(cx); err != nil {
-		cx.t.Fatalf("endpointStatusTest ctlV3EndpointHealth error (%v)", err)
-	}
-
-	// health checking with an ordinary user "succeeds" since permission denial goes through consensus
-	cx.user, cx.pass = "test-user", "pass"
-	if err := ctlV3EndpointHealth(cx); err != nil {
-		cx.t.Fatalf("endpointStatusTest ctlV3EndpointHealth error (%v)", err)
-	}
-
-	// succeed if permissions granted for ordinary user
-	cx.user, cx.pass = "root", "root"
-	if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, "health", "", false}); err != nil {
-		cx.t.Fatal(err)
-	}
-	cx.user, cx.pass = "test-user", "pass"
-	if err := ctlV3EndpointHealth(cx); err != nil {
-		cx.t.Fatalf("endpointStatusTest ctlV3EndpointHealth error (%v)", err)
-	}
-}
-
-func authTestCertCNAndUsername(cx ctlCtx) {
-	if err := authEnable(cx); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	cx.user, cx.pass = "root", "root"
-	authSetupTestUser(cx)
-
-	if err := ctlV3User(cx, []string{"add", "example.com", "--interactive=false"}, "User example.com created", []string{""}); err != nil {
-		cx.t.Fatal(err)
-	}
-	if err := spawnWithExpect(append(cx.PrefixArgs(), "role", "add", "test-role-cn"), "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 {
-		cx.t.Fatal(err)
-	}
-
-	// grant a new key for CN based user
-	if err := ctlV3RoleGrantPermission(cx, "test-role-cn", grantingPerm{true, true, "hoo", "", false}); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// grant a new key for username based user
-	if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, "bar", "", false}); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// try a granted key for CN based user
-	cx.user, cx.pass = "", ""
-	if err := ctlV3Put(cx, "hoo", "bar", ""); err != nil {
-		cx.t.Error(err)
-	}
-
-	// try a granted key for username based user
-	cx.user, cx.pass = "test-user", "pass"
-	if err := ctlV3Put(cx, "bar", "bar", ""); err != nil {
-		cx.t.Error(err)
-	}
-
-	// try a non granted key for both of them
-	cx.user, cx.pass = "", ""
-	if err := ctlV3PutFailPerm(cx, "baz", "bar"); err != nil {
-		cx.t.Error(err)
-	}
-
-	cx.user, cx.pass = "test-user", "pass"
-	if err := ctlV3PutFailPerm(cx, "baz", "bar"); err != nil {
-		cx.t.Error(err)
-	}
-}

+ 0 - 75
e2e/ctl_v3_compact_test.go

@@ -1,75 +0,0 @@
-// Copyright 2016 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 e2e
-
-import (
-	"strconv"
-	"strings"
-	"testing"
-)
-
-func TestCtlV3Compact(t *testing.T)         { testCtl(t, compactTest) }
-func TestCtlV3CompactPhysical(t *testing.T) { testCtl(t, compactTest, withCompactPhysical()) }
-
-func compactTest(cx ctlCtx) {
-	compactPhysical := cx.compactPhysical
-	if err := ctlV3Compact(cx, 2, compactPhysical); err != nil {
-		if !strings.Contains(err.Error(), "required revision is a future revision") {
-			cx.t.Fatal(err)
-		}
-	} else {
-		cx.t.Fatalf("expected '...future revision' error, got <nil>")
-	}
-
-	var kvs = []kv{{"key", "val1"}, {"key", "val2"}, {"key", "val3"}}
-	for i := range kvs {
-		if err := ctlV3Put(cx, kvs[i].key, kvs[i].val, ""); err != nil {
-			cx.t.Fatalf("compactTest #%d: ctlV3Put error (%v)", i, err)
-		}
-	}
-
-	if err := ctlV3Get(cx, []string{"key", "--rev", "3"}, kvs[1:2]...); err != nil {
-		cx.t.Errorf("compactTest: ctlV3Get error (%v)", err)
-	}
-
-	if err := ctlV3Compact(cx, 4, compactPhysical); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	if err := ctlV3Get(cx, []string{"key", "--rev", "3"}, kvs[1:2]...); err != nil {
-		if !strings.Contains(err.Error(), "required revision has been compacted") {
-			cx.t.Errorf("compactTest: ctlV3Get error (%v)", err)
-		}
-	} else {
-		cx.t.Fatalf("expected '...has been compacted' error, got <nil>")
-	}
-
-	if err := ctlV3Compact(cx, 2, compactPhysical); err != nil {
-		if !strings.Contains(err.Error(), "required revision has been compacted") {
-			cx.t.Fatal(err)
-		}
-	} else {
-		cx.t.Fatalf("expected '...has been compacted' error, got <nil>")
-	}
-}
-
-func ctlV3Compact(cx ctlCtx, rev int64, physical bool) error {
-	rs := strconv.FormatInt(rev, 10)
-	cmdArgs := append(cx.PrefixArgs(), "compact", rs)
-	if physical {
-		cmdArgs = append(cmdArgs, "--physical")
-	}
-	return spawnWithExpect(cmdArgs, "compacted revision "+rs)
-}

+ 0 - 49
e2e/ctl_v3_defrag_test.go

@@ -1,49 +0,0 @@
-// Copyright 2016 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 e2e
-
-import "testing"
-
-func TestCtlV3Defrag(t *testing.T) { testCtl(t, defragTest) }
-
-func maintenanceInitKeys(cx ctlCtx) {
-	var kvs = []kv{{"key", "val1"}, {"key", "val2"}, {"key", "val3"}}
-	for i := range kvs {
-		if err := ctlV3Put(cx, kvs[i].key, kvs[i].val, ""); err != nil {
-			cx.t.Fatal(err)
-		}
-	}
-}
-
-func defragTest(cx ctlCtx) {
-	maintenanceInitKeys(cx)
-
-	if err := ctlV3Compact(cx, 4, cx.compactPhysical); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	if err := ctlV3Defrag(cx); err != nil {
-		cx.t.Fatalf("defragTest ctlV3Defrag error (%v)", err)
-	}
-}
-
-func ctlV3Defrag(cx ctlCtx) error {
-	cmdArgs := append(cx.PrefixArgs(), "defrag")
-	lines := make([]string, cx.epc.cfg.clusterSize)
-	for i := range lines {
-		lines[i] = "Finished defragmenting etcd member"
-	}
-	return spawnWithExpects(cmdArgs, lines...)
-}

+ 0 - 119
e2e/ctl_v3_elect_test.go

@@ -1,119 +0,0 @@
-// Copyright 2016 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 e2e
-
-import (
-	"os"
-	"strings"
-	"testing"
-	"time"
-
-	"github.com/coreos/etcd/pkg/expect"
-)
-
-func TestCtlV3Elect(t *testing.T) {
-	oldenv := os.Getenv("EXPECT_DEBUG")
-	defer os.Setenv("EXPECT_DEBUG", oldenv)
-	os.Setenv("EXPECT_DEBUG", "1")
-
-	testCtl(t, testElect)
-}
-
-func testElect(cx ctlCtx) {
-	name := "a"
-
-	holder, ch, err := ctlV3Elect(cx, name, "p1")
-	if err != nil {
-		cx.t.Fatal(err)
-	}
-
-	l1 := ""
-	select {
-	case <-time.After(2 * time.Second):
-		cx.t.Fatalf("timed out electing")
-	case l1 = <-ch:
-		if !strings.HasPrefix(l1, name) {
-			cx.t.Errorf("got %q, expected %q prefix", l1, name)
-		}
-	}
-
-	// blocked process that won't win the election
-	blocked, ch, err := ctlV3Elect(cx, name, "p2")
-	if err != nil {
-		cx.t.Fatal(err)
-	}
-	select {
-	case <-time.After(100 * time.Millisecond):
-	case <-ch:
-		cx.t.Fatalf("should block")
-	}
-
-	// overlap with a blocker that will win the election
-	blockAcquire, ch, err := ctlV3Elect(cx, name, "p2")
-	if err != nil {
-		cx.t.Fatal(err)
-	}
-	defer blockAcquire.Stop()
-	select {
-	case <-time.After(100 * time.Millisecond):
-	case <-ch:
-		cx.t.Fatalf("should block")
-	}
-
-	// kill blocked process with clean shutdown
-	if err = blocked.Signal(os.Interrupt); err != nil {
-		cx.t.Fatal(err)
-	}
-	if err = closeWithTimeout(blocked, time.Second); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// kill the holder with clean shutdown
-	if err = holder.Signal(os.Interrupt); err != nil {
-		cx.t.Fatal(err)
-	}
-	if err = closeWithTimeout(holder, time.Second); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// blockAcquire should win the election
-	select {
-	case <-time.After(time.Second):
-		cx.t.Fatalf("timed out from waiting to holding")
-	case l2 := <-ch:
-		if l1 == l2 || !strings.HasPrefix(l2, name) {
-			cx.t.Fatalf("expected different elect name, got l1=%q, l2=%q", l1, l2)
-		}
-	}
-}
-
-// ctlV3Elect creates a elect process with a channel listening for when it wins the election.
-func ctlV3Elect(cx ctlCtx, name, proposal string) (*expect.ExpectProcess, <-chan string, error) {
-	cmdArgs := append(cx.PrefixArgs(), "elect", name, proposal)
-	proc, err := spawnCmd(cmdArgs)
-	outc := make(chan string, 1)
-	if err != nil {
-		close(outc)
-		return proc, outc, err
-	}
-	go func() {
-		s, xerr := proc.ExpectFunc(func(string) bool { return true })
-		if xerr != nil {
-			cx.t.Errorf("expect failed (%v)", xerr)
-		}
-		outc <- s
-	}()
-	return proc, outc, err
-}

+ 0 - 92
e2e/ctl_v3_endpoint_test.go

@@ -1,92 +0,0 @@
-// Copyright 2016 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 e2e
-
-import (
-	"context"
-	"fmt"
-	"net/url"
-	"testing"
-	"time"
-
-	"github.com/coreos/etcd/clientv3"
-)
-
-func TestCtlV3EndpointHealth(t *testing.T) { testCtl(t, endpointHealthTest, withQuorum()) }
-func TestCtlV3EndpointStatus(t *testing.T) { testCtl(t, endpointStatusTest, withQuorum()) }
-func TestCtlV3EndpointHashKV(t *testing.T) { testCtl(t, endpointHashKVTest, withQuorum()) }
-
-func endpointHealthTest(cx ctlCtx) {
-	if err := ctlV3EndpointHealth(cx); err != nil {
-		cx.t.Fatalf("endpointStatusTest ctlV3EndpointHealth error (%v)", err)
-	}
-}
-
-func ctlV3EndpointHealth(cx ctlCtx) error {
-	cmdArgs := append(cx.PrefixArgs(), "endpoint", "health")
-	lines := make([]string, cx.epc.cfg.clusterSize)
-	for i := range lines {
-		lines[i] = "is healthy"
-	}
-	return spawnWithExpects(cmdArgs, lines...)
-}
-
-func endpointStatusTest(cx ctlCtx) {
-	if err := ctlV3EndpointStatus(cx); err != nil {
-		cx.t.Fatalf("endpointStatusTest ctlV3EndpointStatus error (%v)", err)
-	}
-}
-
-func ctlV3EndpointStatus(cx ctlCtx) error {
-	cmdArgs := append(cx.PrefixArgs(), "endpoint", "status")
-	var eps []string
-	for _, ep := range cx.epc.EndpointsV3() {
-		u, _ := url.Parse(ep)
-		eps = append(eps, u.Host)
-	}
-	return spawnWithExpects(cmdArgs, eps...)
-}
-
-func endpointHashKVTest(cx ctlCtx) {
-	if err := ctlV3EndpointHashKV(cx); err != nil {
-		cx.t.Fatalf("endpointHashKVTest ctlV3EndpointHashKV error (%v)", err)
-	}
-}
-
-func ctlV3EndpointHashKV(cx ctlCtx) error {
-	eps := cx.epc.EndpointsV3()
-
-	// get latest hash to compare
-	cli, err := clientv3.New(clientv3.Config{
-		Endpoints:   eps,
-		DialTimeout: 3 * time.Second,
-	})
-	if err != nil {
-		cx.t.Fatal(err)
-	}
-	defer cli.Close()
-	hresp, err := cli.HashKV(context.TODO(), eps[0], 0)
-	if err != nil {
-		cx.t.Fatal(err)
-	}
-
-	cmdArgs := append(cx.PrefixArgs(), "endpoint", "hashkv")
-	var ss []string
-	for _, ep := range cx.epc.EndpointsV3() {
-		u, _ := url.Parse(ep)
-		ss = append(ss, fmt.Sprintf("%s, %d", u.Host, hresp.Hash))
-	}
-	return spawnWithExpects(cmdArgs, ss...)
-}

+ 0 - 335
e2e/ctl_v3_kv_test.go

@@ -1,335 +0,0 @@
-// Copyright 2016 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 e2e
-
-import (
-	"fmt"
-	"strings"
-	"testing"
-)
-
-func TestCtlV3Put(t *testing.T)              { testCtl(t, putTest) }
-func TestCtlV3PutNoTLS(t *testing.T)         { testCtl(t, putTest, withCfg(configNoTLS)) }
-func TestCtlV3PutClientTLS(t *testing.T)     { testCtl(t, putTest, withCfg(configClientTLS)) }
-func TestCtlV3PutClientAutoTLS(t *testing.T) { testCtl(t, putTest, withCfg(configClientAutoTLS)) }
-func TestCtlV3PutPeerTLS(t *testing.T)       { testCtl(t, putTest, withCfg(configPeerTLS)) }
-func TestCtlV3PutTimeout(t *testing.T)       { testCtl(t, putTest, withDialTimeout(0)) }
-func TestCtlV3PutClientTLSFlagByEnv(t *testing.T) {
-	testCtl(t, putTest, withCfg(configClientTLS), withFlagByEnv())
-}
-func TestCtlV3PutIgnoreValue(t *testing.T) { testCtl(t, putTestIgnoreValue) }
-func TestCtlV3PutIgnoreLease(t *testing.T) { testCtl(t, putTestIgnoreLease) }
-
-func TestCtlV3Get(t *testing.T)              { testCtl(t, getTest) }
-func TestCtlV3GetNoTLS(t *testing.T)         { testCtl(t, getTest, withCfg(configNoTLS)) }
-func TestCtlV3GetClientTLS(t *testing.T)     { testCtl(t, getTest, withCfg(configClientTLS)) }
-func TestCtlV3GetClientAutoTLS(t *testing.T) { testCtl(t, getTest, withCfg(configClientAutoTLS)) }
-func TestCtlV3GetPeerTLS(t *testing.T)       { testCtl(t, getTest, withCfg(configPeerTLS)) }
-func TestCtlV3GetTimeout(t *testing.T)       { testCtl(t, getTest, withDialTimeout(0)) }
-func TestCtlV3GetQuorum(t *testing.T)        { testCtl(t, getTest, withQuorum()) }
-
-func TestCtlV3GetFormat(t *testing.T)   { testCtl(t, getFormatTest) }
-func TestCtlV3GetRev(t *testing.T)      { testCtl(t, getRevTest) }
-func TestCtlV3GetKeysOnly(t *testing.T) { testCtl(t, getKeysOnlyTest) }
-
-func TestCtlV3Del(t *testing.T)          { testCtl(t, delTest) }
-func TestCtlV3DelNoTLS(t *testing.T)     { testCtl(t, delTest, withCfg(configNoTLS)) }
-func TestCtlV3DelClientTLS(t *testing.T) { testCtl(t, delTest, withCfg(configClientTLS)) }
-func TestCtlV3DelPeerTLS(t *testing.T)   { testCtl(t, delTest, withCfg(configPeerTLS)) }
-func TestCtlV3DelTimeout(t *testing.T)   { testCtl(t, delTest, withDialTimeout(0)) }
-
-func TestCtlV3GetRevokedCRL(t *testing.T) {
-	cfg := etcdProcessClusterConfig{
-		clusterSize:           1,
-		initialToken:          "new",
-		clientTLS:             clientTLS,
-		isClientCRL:           true,
-		clientCertAuthEnabled: true,
-	}
-	testCtl(t, testGetRevokedCRL, withCfg(cfg))
-}
-
-func testGetRevokedCRL(cx ctlCtx) {
-	// test reject
-	if err := ctlV3Put(cx, "k", "v", ""); err == nil || !strings.Contains(err.Error(), "Error:") {
-		cx.t.Fatalf("expected reset connection on put, got %v", err)
-	}
-	// test accept
-	cx.epc.cfg.isClientCRL = false
-	if err := ctlV3Put(cx, "k", "v", ""); err != nil {
-		cx.t.Fatal(err)
-	}
-}
-
-func putTest(cx ctlCtx) {
-	key, value := "foo", "bar"
-
-	if err := ctlV3Put(cx, key, value, ""); err != nil {
-		if cx.dialTimeout > 0 && !isGRPCTimedout(err) {
-			cx.t.Fatalf("putTest ctlV3Put error (%v)", err)
-		}
-	}
-	if err := ctlV3Get(cx, []string{key}, kv{key, value}); err != nil {
-		if cx.dialTimeout > 0 && !isGRPCTimedout(err) {
-			cx.t.Fatalf("putTest ctlV3Get error (%v)", err)
-		}
-	}
-}
-
-func putTestIgnoreValue(cx ctlCtx) {
-	if err := ctlV3Put(cx, "foo", "bar", ""); err != nil {
-		cx.t.Fatal(err)
-	}
-	if err := ctlV3Get(cx, []string{"foo"}, kv{"foo", "bar"}); err != nil {
-		cx.t.Fatal(err)
-	}
-	if err := ctlV3Put(cx, "foo", "", "", "--ignore-value"); err != nil {
-		cx.t.Fatal(err)
-	}
-	if err := ctlV3Get(cx, []string{"foo"}, kv{"foo", "bar"}); err != nil {
-		cx.t.Fatal(err)
-	}
-}
-
-func putTestIgnoreLease(cx ctlCtx) {
-	leaseID, err := ctlV3LeaseGrant(cx, 10)
-	if err != nil {
-		cx.t.Fatalf("putTestIgnoreLease: ctlV3LeaseGrant error (%v)", err)
-	}
-	if err := ctlV3Put(cx, "foo", "bar", leaseID); err != nil {
-		cx.t.Fatalf("putTestIgnoreLease: ctlV3Put error (%v)", err)
-	}
-	if err := ctlV3Get(cx, []string{"foo"}, kv{"foo", "bar"}); err != nil {
-		cx.t.Fatalf("putTestIgnoreLease: ctlV3Get error (%v)", err)
-	}
-	if err := ctlV3Put(cx, "foo", "bar1", "", "--ignore-lease"); err != nil {
-		cx.t.Fatalf("putTestIgnoreLease: ctlV3Put error (%v)", err)
-	}
-	if err := ctlV3Get(cx, []string{"foo"}, kv{"foo", "bar1"}); err != nil {
-		cx.t.Fatalf("putTestIgnoreLease: ctlV3Get error (%v)", err)
-	}
-	if err := ctlV3LeaseRevoke(cx, leaseID); err != nil {
-		cx.t.Fatalf("putTestIgnoreLease: ctlV3LeaseRevok error (%v)", err)
-	}
-	if err := ctlV3Get(cx, []string{"key"}); err != nil { // expect no output
-		cx.t.Fatalf("putTestIgnoreLease: ctlV3Get error (%v)", err)
-	}
-}
-
-func getTest(cx ctlCtx) {
-	var (
-		kvs    = []kv{{"key1", "val1"}, {"key2", "val2"}, {"key3", "val3"}}
-		revkvs = []kv{{"key3", "val3"}, {"key2", "val2"}, {"key1", "val1"}}
-	)
-	for i := range kvs {
-		if err := ctlV3Put(cx, kvs[i].key, kvs[i].val, ""); err != nil {
-			cx.t.Fatalf("getTest #%d: ctlV3Put error (%v)", i, err)
-		}
-	}
-
-	tests := []struct {
-		args []string
-
-		wkv []kv
-	}{
-		{[]string{"key1"}, []kv{{"key1", "val1"}}},
-		{[]string{"", "--prefix"}, kvs},
-		{[]string{"", "--from-key"}, kvs},
-		{[]string{"key", "--prefix"}, kvs},
-		{[]string{"key", "--prefix", "--limit=2"}, kvs[:2]},
-		{[]string{"key", "--prefix", "--order=ASCEND", "--sort-by=MODIFY"}, kvs},
-		{[]string{"key", "--prefix", "--order=ASCEND", "--sort-by=VERSION"}, kvs},
-		{[]string{"key", "--prefix", "--sort-by=CREATE"}, kvs}, // ASCEND by default
-		{[]string{"key", "--prefix", "--order=DESCEND", "--sort-by=CREATE"}, revkvs},
-		{[]string{"key", "--prefix", "--order=DESCEND", "--sort-by=KEY"}, revkvs},
-	}
-	for i, tt := range tests {
-		if err := ctlV3Get(cx, tt.args, tt.wkv...); err != nil {
-			if cx.dialTimeout > 0 && !isGRPCTimedout(err) {
-				cx.t.Errorf("getTest #%d: ctlV3Get error (%v)", i, err)
-			}
-		}
-	}
-}
-
-func getFormatTest(cx ctlCtx) {
-	if err := ctlV3Put(cx, "abc", "123", ""); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	tests := []struct {
-		format    string
-		valueOnly bool
-
-		wstr string
-	}{
-		{"simple", false, "abc"},
-		{"simple", true, "123"},
-		{"json", false, `"kvs":[{"key":"YWJj"`},
-		{"protobuf", false, "\x17\b\x93\xe7\xf6\x93\xd4ņ\xe14\x10\xed"},
-	}
-
-	for i, tt := range tests {
-		cmdArgs := append(cx.PrefixArgs(), "get")
-		cmdArgs = append(cmdArgs, "--write-out="+tt.format)
-		if tt.valueOnly {
-			cmdArgs = append(cmdArgs, "--print-value-only")
-		}
-		cmdArgs = append(cmdArgs, "abc")
-		if err := spawnWithExpect(cmdArgs, tt.wstr); err != nil {
-			cx.t.Errorf("#%d: error (%v), wanted %v", i, err, tt.wstr)
-		}
-	}
-}
-
-func getRevTest(cx ctlCtx) {
-	var (
-		kvs = []kv{{"key", "val1"}, {"key", "val2"}, {"key", "val3"}}
-	)
-	for i := range kvs {
-		if err := ctlV3Put(cx, kvs[i].key, kvs[i].val, ""); err != nil {
-			cx.t.Fatalf("getRevTest #%d: ctlV3Put error (%v)", i, err)
-		}
-	}
-
-	tests := []struct {
-		args []string
-
-		wkv []kv
-	}{
-		{[]string{"key", "--rev", "2"}, kvs[:1]},
-		{[]string{"key", "--rev", "3"}, kvs[1:2]},
-		{[]string{"key", "--rev", "4"}, kvs[2:]},
-	}
-
-	for i, tt := range tests {
-		if err := ctlV3Get(cx, tt.args, tt.wkv...); err != nil {
-			cx.t.Errorf("getTest #%d: ctlV3Get error (%v)", i, err)
-		}
-	}
-}
-
-func getKeysOnlyTest(cx ctlCtx) {
-	if err := ctlV3Put(cx, "key", "val", ""); err != nil {
-		cx.t.Fatal(err)
-	}
-	cmdArgs := append(cx.PrefixArgs(), []string{"get", "--keys-only", "key"}...)
-	if err := spawnWithExpect(cmdArgs, "key"); err != nil {
-		cx.t.Fatal(err)
-	}
-	if err := spawnWithExpects(cmdArgs, "val"); err == nil {
-		cx.t.Fatalf("got value but passed --keys-only")
-	}
-}
-
-func delTest(cx ctlCtx) {
-	tests := []struct {
-		puts []kv
-		args []string
-
-		deletedNum int
-	}{
-		{ // delete all keys
-			[]kv{{"foo1", "bar"}, {"foo2", "bar"}, {"foo3", "bar"}},
-			[]string{"", "--prefix"},
-			3,
-		},
-		{ // delete all keys
-			[]kv{{"foo1", "bar"}, {"foo2", "bar"}, {"foo3", "bar"}},
-			[]string{"", "--from-key"},
-			3,
-		},
-		{
-			[]kv{{"this", "value"}},
-			[]string{"that"},
-			0,
-		},
-		{
-			[]kv{{"sample", "value"}},
-			[]string{"sample"},
-			1,
-		},
-		{
-			[]kv{{"key1", "val1"}, {"key2", "val2"}, {"key3", "val3"}},
-			[]string{"key", "--prefix"},
-			3,
-		},
-		{
-			[]kv{{"zoo1", "bar"}, {"zoo2", "bar2"}, {"zoo3", "bar3"}},
-			[]string{"zoo1", "--from-key"},
-			3,
-		},
-	}
-
-	for i, tt := range tests {
-		for j := range tt.puts {
-			if err := ctlV3Put(cx, tt.puts[j].key, tt.puts[j].val, ""); err != nil {
-				cx.t.Fatalf("delTest #%d-%d: ctlV3Put error (%v)", i, j, err)
-			}
-		}
-		if err := ctlV3Del(cx, tt.args, tt.deletedNum); err != nil {
-			if cx.dialTimeout > 0 && !isGRPCTimedout(err) {
-				cx.t.Fatalf("delTest #%d: ctlV3Del error (%v)", i, err)
-			}
-		}
-	}
-}
-
-func ctlV3Put(cx ctlCtx, key, value, leaseID string, flags ...string) error {
-	skipValue := false
-	skipLease := false
-	for _, f := range flags {
-		if f == "--ignore-value" {
-			skipValue = true
-		}
-		if f == "--ignore-lease" {
-			skipLease = true
-		}
-	}
-	cmdArgs := append(cx.PrefixArgs(), "put", key)
-	if !skipValue {
-		cmdArgs = append(cmdArgs, value)
-	}
-	if leaseID != "" && !skipLease {
-		cmdArgs = append(cmdArgs, "--lease", leaseID)
-	}
-	if len(flags) != 0 {
-		cmdArgs = append(cmdArgs, flags...)
-	}
-	return spawnWithExpect(cmdArgs, "OK")
-}
-
-type kv struct {
-	key, val string
-}
-
-func ctlV3Get(cx ctlCtx, args []string, kvs ...kv) error {
-	cmdArgs := append(cx.PrefixArgs(), "get")
-	cmdArgs = append(cmdArgs, args...)
-	if !cx.quorum {
-		cmdArgs = append(cmdArgs, "--consistency", "s")
-	}
-	var lines []string
-	for _, elem := range kvs {
-		lines = append(lines, elem.key, elem.val)
-	}
-	return spawnWithExpects(cmdArgs, lines...)
-}
-
-func ctlV3Del(cx ctlCtx, args []string, num int) error {
-	cmdArgs := append(cx.PrefixArgs(), "del")
-	cmdArgs = append(cmdArgs, args...)
-	return spawnWithExpects(cmdArgs, fmt.Sprintf("%d", num))
-}

+ 0 - 212
e2e/ctl_v3_lease_test.go

@@ -1,212 +0,0 @@
-// Copyright 2016 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 e2e
-
-import (
-	"fmt"
-	"strconv"
-	"strings"
-	"testing"
-	"time"
-)
-
-func TestCtlV3LeaseGrantTimeToLive(t *testing.T)       { testCtl(t, leaseTestGrantTimeToLive) }
-func TestCtlV3LeaseGrantLeases(t *testing.T)           { testCtl(t, leaseTestGrantLeasesList) }
-func TestCtlV3LeaseTestTimeToLiveExpired(t *testing.T) { testCtl(t, leaseTestTimeToLiveExpired) }
-func TestCtlV3LeaseKeepAlive(t *testing.T)             { testCtl(t, leaseTestKeepAlive) }
-func TestCtlV3LeaseKeepAliveOnce(t *testing.T)         { testCtl(t, leaseTestKeepAliveOnce) }
-func TestCtlV3LeaseRevoke(t *testing.T)                { testCtl(t, leaseTestRevoke) }
-
-func leaseTestGrantTimeToLive(cx ctlCtx) {
-	id, err := ctlV3LeaseGrant(cx, 10)
-	if err != nil {
-		cx.t.Fatal(err)
-	}
-
-	cmdArgs := append(cx.PrefixArgs(), "lease", "timetolive", id, "--keys")
-	proc, err := spawnCmd(cmdArgs)
-	if err != nil {
-		cx.t.Fatal(err)
-	}
-	line, err := proc.Expect(" granted with TTL(")
-	if err != nil {
-		cx.t.Fatal(err)
-	}
-	if err = proc.Close(); err != nil {
-		cx.t.Fatal(err)
-	}
-	if !strings.Contains(line, ", attached keys") {
-		cx.t.Fatalf("expected 'attached keys', got %q", line)
-	}
-	if !strings.Contains(line, id) {
-		cx.t.Fatalf("expected leaseID %q, got %q", id, line)
-	}
-}
-
-func leaseTestGrantLeasesList(cx ctlCtx) {
-	id, err := ctlV3LeaseGrant(cx, 10)
-	if err != nil {
-		cx.t.Fatal(err)
-	}
-
-	cmdArgs := append(cx.PrefixArgs(), "lease", "list")
-	proc, err := spawnCmd(cmdArgs)
-	if err != nil {
-		cx.t.Fatal(err)
-	}
-	_, err = proc.Expect(id)
-	if err != nil {
-		cx.t.Fatal(err)
-	}
-	if err = proc.Close(); err != nil {
-		cx.t.Fatal(err)
-	}
-}
-
-func leaseTestTimeToLiveExpired(cx ctlCtx) {
-	err := leaseTestTimeToLiveExpire(cx, 3)
-	if err != nil {
-		cx.t.Fatal(err)
-	}
-}
-
-func leaseTestTimeToLiveExpire(cx ctlCtx, ttl int) error {
-	leaseID, err := ctlV3LeaseGrant(cx, ttl)
-	if err != nil {
-		return err
-	}
-
-	if err = ctlV3Put(cx, "key", "val", leaseID); err != nil {
-		return fmt.Errorf("leaseTestTimeToLiveExpire: ctlV3Put error (%v)", err)
-	}
-	// eliminate false positive
-	time.Sleep(time.Duration(ttl+1) * time.Second)
-	cmdArgs := append(cx.PrefixArgs(), "lease", "timetolive", leaseID)
-	exp := fmt.Sprintf("lease %s already expired", leaseID)
-	if err = spawnWithExpect(cmdArgs, exp); err != nil {
-		return err
-	}
-	if err := ctlV3Get(cx, []string{"key"}); err != nil {
-		return fmt.Errorf("leaseTestTimeToLiveExpire: ctlV3Get error (%v)", err)
-	}
-	return nil
-}
-
-func leaseTestKeepAlive(cx ctlCtx) {
-	// put with TTL 10 seconds and keep-alive
-	leaseID, err := ctlV3LeaseGrant(cx, 10)
-	if err != nil {
-		cx.t.Fatalf("leaseTestKeepAlive: ctlV3LeaseGrant error (%v)", err)
-	}
-	if err := ctlV3Put(cx, "key", "val", leaseID); err != nil {
-		cx.t.Fatalf("leaseTestKeepAlive: ctlV3Put error (%v)", err)
-	}
-	if err := ctlV3LeaseKeepAlive(cx, leaseID); err != nil {
-		cx.t.Fatalf("leaseTestKeepAlive: ctlV3LeaseKeepAlive error (%v)", err)
-	}
-	if err := ctlV3Get(cx, []string{"key"}, kv{"key", "val"}); err != nil {
-		cx.t.Fatalf("leaseTestKeepAlive: ctlV3Get error (%v)", err)
-	}
-}
-
-func leaseTestKeepAliveOnce(cx ctlCtx) {
-	// put with TTL 10 seconds and keep-alive once
-	leaseID, err := ctlV3LeaseGrant(cx, 10)
-	if err != nil {
-		cx.t.Fatalf("leaseTestKeepAlive: ctlV3LeaseGrant error (%v)", err)
-	}
-	if err := ctlV3Put(cx, "key", "val", leaseID); err != nil {
-		cx.t.Fatalf("leaseTestKeepAlive: ctlV3Put error (%v)", err)
-	}
-	if err := ctlV3LeaseKeepAliveOnce(cx, leaseID); err != nil {
-		cx.t.Fatalf("leaseTestKeepAlive: ctlV3LeaseKeepAliveOnce error (%v)", err)
-	}
-	if err := ctlV3Get(cx, []string{"key"}, kv{"key", "val"}); err != nil {
-		cx.t.Fatalf("leaseTestKeepAlive: ctlV3Get error (%v)", err)
-	}
-}
-
-func leaseTestRevoke(cx ctlCtx) {
-	// put with TTL 10 seconds and revoke
-	leaseID, err := ctlV3LeaseGrant(cx, 10)
-	if err != nil {
-		cx.t.Fatalf("leaseTestRevoke: ctlV3LeaseGrant error (%v)", err)
-	}
-	if err := ctlV3Put(cx, "key", "val", leaseID); err != nil {
-		cx.t.Fatalf("leaseTestRevoke: ctlV3Put error (%v)", err)
-	}
-	if err := ctlV3LeaseRevoke(cx, leaseID); err != nil {
-		cx.t.Fatalf("leaseTestRevoke: ctlV3LeaseRevok error (%v)", err)
-	}
-	if err := ctlV3Get(cx, []string{"key"}); err != nil { // expect no output
-		cx.t.Fatalf("leaseTestRevoke: ctlV3Get error (%v)", err)
-	}
-}
-
-func ctlV3LeaseGrant(cx ctlCtx, ttl int) (string, error) {
-	cmdArgs := append(cx.PrefixArgs(), "lease", "grant", strconv.Itoa(ttl))
-	proc, err := spawnCmd(cmdArgs)
-	if err != nil {
-		return "", err
-	}
-
-	line, err := proc.Expect(" granted with TTL(")
-	if err != nil {
-		return "", err
-	}
-	if err = proc.Close(); err != nil {
-		return "", err
-	}
-
-	// parse 'line LEASE_ID granted with TTL(5s)' to get lease ID
-	hs := strings.Split(line, " ")
-	if len(hs) < 2 {
-		return "", fmt.Errorf("lease grant failed with %q", line)
-	}
-	return hs[1], nil
-}
-
-func ctlV3LeaseKeepAlive(cx ctlCtx, leaseID string) error {
-	cmdArgs := append(cx.PrefixArgs(), "lease", "keep-alive", leaseID)
-
-	proc, err := spawnCmd(cmdArgs)
-	if err != nil {
-		return err
-	}
-
-	if _, err = proc.Expect(fmt.Sprintf("lease %s keepalived with TTL(", leaseID)); err != nil {
-		return err
-	}
-	return proc.Stop()
-}
-
-func ctlV3LeaseKeepAliveOnce(cx ctlCtx, leaseID string) error {
-	cmdArgs := append(cx.PrefixArgs(), "lease", "keep-alive", "--once", leaseID)
-
-	proc, err := spawnCmd(cmdArgs)
-	if err != nil {
-		return err
-	}
-
-	if _, err = proc.Expect(fmt.Sprintf("lease %s keepalived with TTL(", leaseID)); err != nil {
-		return err
-	}
-	return proc.Stop()
-}
-
-func ctlV3LeaseRevoke(cx ctlCtx, leaseID string) error {
-	cmdArgs := append(cx.PrefixArgs(), "lease", "revoke", leaseID)
-	return spawnWithExpect(cmdArgs, fmt.Sprintf("lease %s revoked", leaseID))
-}

+ 0 - 119
e2e/ctl_v3_lock_test.go

@@ -1,119 +0,0 @@
-// Copyright 2016 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 e2e
-
-import (
-	"os"
-	"strings"
-	"testing"
-	"time"
-
-	"github.com/coreos/etcd/pkg/expect"
-)
-
-func TestCtlV3Lock(t *testing.T) {
-	oldenv := os.Getenv("EXPECT_DEBUG")
-	defer os.Setenv("EXPECT_DEBUG", oldenv)
-	os.Setenv("EXPECT_DEBUG", "1")
-
-	testCtl(t, testLock)
-}
-
-func testLock(cx ctlCtx) {
-	name := "a"
-
-	holder, ch, err := ctlV3Lock(cx, name)
-	if err != nil {
-		cx.t.Fatal(err)
-	}
-
-	l1 := ""
-	select {
-	case <-time.After(2 * time.Second):
-		cx.t.Fatalf("timed out locking")
-	case l1 = <-ch:
-		if !strings.HasPrefix(l1, name) {
-			cx.t.Errorf("got %q, expected %q prefix", l1, name)
-		}
-	}
-
-	// blocked process that won't acquire the lock
-	blocked, ch, err := ctlV3Lock(cx, name)
-	if err != nil {
-		cx.t.Fatal(err)
-	}
-	select {
-	case <-time.After(100 * time.Millisecond):
-	case <-ch:
-		cx.t.Fatalf("should block")
-	}
-
-	// overlap with a blocker that will acquire the lock
-	blockAcquire, ch, err := ctlV3Lock(cx, name)
-	if err != nil {
-		cx.t.Fatal(err)
-	}
-	defer blockAcquire.Stop()
-	select {
-	case <-time.After(100 * time.Millisecond):
-	case <-ch:
-		cx.t.Fatalf("should block")
-	}
-
-	// kill blocked process with clean shutdown
-	if err = blocked.Signal(os.Interrupt); err != nil {
-		cx.t.Fatal(err)
-	}
-	if err = closeWithTimeout(blocked, time.Second); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// kill the holder with clean shutdown
-	if err = holder.Signal(os.Interrupt); err != nil {
-		cx.t.Fatal(err)
-	}
-	if err = closeWithTimeout(holder, time.Second); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	// blockAcquire should acquire the lock
-	select {
-	case <-time.After(time.Second):
-		cx.t.Fatalf("timed out from waiting to holding")
-	case l2 := <-ch:
-		if l1 == l2 || !strings.HasPrefix(l2, name) {
-			cx.t.Fatalf("expected different lock name, got l1=%q, l2=%q", l1, l2)
-		}
-	}
-}
-
-// ctlV3Lock creates a lock process with a channel listening for when it acquires the lock.
-func ctlV3Lock(cx ctlCtx, name string) (*expect.ExpectProcess, <-chan string, error) {
-	cmdArgs := append(cx.PrefixArgs(), "lock", name)
-	proc, err := spawnCmd(cmdArgs)
-	outc := make(chan string, 1)
-	if err != nil {
-		close(outc)
-		return proc, outc, err
-	}
-	go func() {
-		s, xerr := proc.ExpectFunc(func(string) bool { return true })
-		if xerr != nil {
-			cx.t.Errorf("expect failed (%v)", xerr)
-		}
-		outc <- s
-	}()
-	return proc, outc, err
-}

+ 0 - 109
e2e/ctl_v3_make_mirror_test.go

@@ -1,109 +0,0 @@
-// Copyright 2016 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 e2e
-
-import (
-	"fmt"
-	"testing"
-	"time"
-)
-
-func TestCtlV3MakeMirror(t *testing.T)                 { testCtl(t, makeMirrorTest) }
-func TestCtlV3MakeMirrorModifyDestPrefix(t *testing.T) { testCtl(t, makeMirrorModifyDestPrefixTest) }
-func TestCtlV3MakeMirrorNoDestPrefix(t *testing.T)     { testCtl(t, makeMirrorNoDestPrefixTest) }
-
-func makeMirrorTest(cx ctlCtx) {
-	var (
-		flags  = []string{}
-		kvs    = []kv{{"key1", "val1"}, {"key2", "val2"}, {"key3", "val3"}}
-		kvs2   = []kvExec{{key: "key1", val: "val1"}, {key: "key2", val: "val2"}, {key: "key3", val: "val3"}}
-		prefix = "key"
-	)
-	testMirrorCommand(cx, flags, kvs, kvs2, prefix, prefix)
-}
-
-func makeMirrorModifyDestPrefixTest(cx ctlCtx) {
-	var (
-		flags      = []string{"--prefix", "o_", "--dest-prefix", "d_"}
-		kvs        = []kv{{"o_key1", "val1"}, {"o_key2", "val2"}, {"o_key3", "val3"}}
-		kvs2       = []kvExec{{key: "d_key1", val: "val1"}, {key: "d_key2", val: "val2"}, {key: "d_key3", val: "val3"}}
-		srcprefix  = "o_"
-		destprefix = "d_"
-	)
-	testMirrorCommand(cx, flags, kvs, kvs2, srcprefix, destprefix)
-}
-
-func makeMirrorNoDestPrefixTest(cx ctlCtx) {
-	var (
-		flags      = []string{"--prefix", "o_", "--no-dest-prefix"}
-		kvs        = []kv{{"o_key1", "val1"}, {"o_key2", "val2"}, {"o_key3", "val3"}}
-		kvs2       = []kvExec{{key: "key1", val: "val1"}, {key: "key2", val: "val2"}, {key: "key3", val: "val3"}}
-		srcprefix  = "o_"
-		destprefix = "key"
-	)
-
-	testMirrorCommand(cx, flags, kvs, kvs2, srcprefix, destprefix)
-}
-
-func testMirrorCommand(cx ctlCtx, flags []string, sourcekvs []kv, destkvs []kvExec, srcprefix, destprefix string) {
-	// set up another cluster to mirror with
-	mirrorcfg := configAutoTLS
-	mirrorcfg.clusterSize = 1
-	mirrorcfg.basePort = 10000
-	mirrorctx := ctlCtx{
-		t:           cx.t,
-		cfg:         mirrorcfg,
-		dialTimeout: 7 * time.Second,
-	}
-
-	mirrorepc, err := newEtcdProcessCluster(&mirrorctx.cfg)
-	if err != nil {
-		cx.t.Fatalf("could not start etcd process cluster (%v)", err)
-	}
-	mirrorctx.epc = mirrorepc
-
-	defer func() {
-		if err = mirrorctx.epc.Close(); err != nil {
-			cx.t.Fatalf("error closing etcd processes (%v)", err)
-		}
-	}()
-
-	cmdArgs := append(cx.PrefixArgs(), "make-mirror")
-	cmdArgs = append(cmdArgs, flags...)
-	cmdArgs = append(cmdArgs, fmt.Sprintf("localhost:%d", mirrorcfg.basePort))
-	proc, err := spawnCmd(cmdArgs)
-	if err != nil {
-		cx.t.Fatal(err)
-	}
-	defer func() {
-		err = proc.Stop()
-		if err != nil {
-			cx.t.Fatal(err)
-		}
-	}()
-
-	for i := range sourcekvs {
-		if err = ctlV3Put(cx, sourcekvs[i].key, sourcekvs[i].val, ""); err != nil {
-			cx.t.Fatal(err)
-		}
-	}
-	if err = ctlV3Get(cx, []string{srcprefix, "--prefix"}, sourcekvs...); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	if err = ctlV3Watch(mirrorctx, []string{destprefix, "--rev", "1", "--prefix"}, destkvs...); err != nil {
-		cx.t.Fatal(err)
-	}
-}

+ 0 - 112
e2e/ctl_v3_member_test.go

@@ -1,112 +0,0 @@
-// Copyright 2016 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 e2e
-
-import (
-	"encoding/json"
-	"fmt"
-	"io"
-	"strings"
-	"testing"
-
-	"github.com/coreos/etcd/etcdserver/etcdserverpb"
-)
-
-func TestCtlV3MemberList(t *testing.T) { testCtl(t, memberListTest) }
-func TestCtlV3MemberRemove(t *testing.T) {
-	testCtl(t, memberRemoveTest, withQuorum(), withNoStrictReconfig())
-}
-func TestCtlV3MemberAdd(t *testing.T)    { testCtl(t, memberAddTest) }
-func TestCtlV3MemberUpdate(t *testing.T) { testCtl(t, memberUpdateTest) }
-
-func memberListTest(cx ctlCtx) {
-	if err := ctlV3MemberList(cx); err != nil {
-		cx.t.Fatalf("memberListTest ctlV3MemberList error (%v)", err)
-	}
-}
-
-func ctlV3MemberList(cx ctlCtx) error {
-	cmdArgs := append(cx.PrefixArgs(), "member", "list")
-	lines := make([]string, cx.cfg.clusterSize)
-	for i := range lines {
-		lines[i] = "started"
-	}
-	return spawnWithExpects(cmdArgs, lines...)
-}
-
-func getMemberList(cx ctlCtx) (etcdserverpb.MemberListResponse, error) {
-	cmdArgs := append(cx.PrefixArgs(), "--write-out", "json", "member", "list")
-
-	proc, err := spawnCmd(cmdArgs)
-	if err != nil {
-		return etcdserverpb.MemberListResponse{}, err
-	}
-	var txt string
-	txt, err = proc.Expect("members")
-	if err != nil {
-		return etcdserverpb.MemberListResponse{}, err
-	}
-	if err = proc.Close(); err != nil {
-		return etcdserverpb.MemberListResponse{}, err
-	}
-
-	resp := etcdserverpb.MemberListResponse{}
-	dec := json.NewDecoder(strings.NewReader(txt))
-	if err := dec.Decode(&resp); err == io.EOF {
-		return etcdserverpb.MemberListResponse{}, err
-	}
-	return resp, nil
-}
-
-func memberRemoveTest(cx ctlCtx) {
-	ep, memIDToRemove, clusterID := cx.memberToRemove()
-	if err := ctlV3MemberRemove(cx, ep, memIDToRemove, clusterID); err != nil {
-		cx.t.Fatal(err)
-	}
-}
-
-func ctlV3MemberRemove(cx ctlCtx, ep, memberID, clusterID string) error {
-	cmdArgs := append(cx.prefixArgs([]string{ep}), "member", "remove", memberID)
-	return spawnWithExpect(cmdArgs, fmt.Sprintf("%s removed from cluster %s", memberID, clusterID))
-}
-
-func memberAddTest(cx ctlCtx) {
-	if err := ctlV3MemberAdd(cx, fmt.Sprintf("http://localhost:%d", etcdProcessBasePort+11)); err != nil {
-		cx.t.Fatal(err)
-	}
-}
-
-func ctlV3MemberAdd(cx ctlCtx, peerURL string) error {
-	cmdArgs := append(cx.PrefixArgs(), "member", "add", "newmember", fmt.Sprintf("--peer-urls=%s", peerURL))
-	return spawnWithExpect(cmdArgs, " added to cluster ")
-}
-
-func memberUpdateTest(cx ctlCtx) {
-	mr, err := getMemberList(cx)
-	if err != nil {
-		cx.t.Fatal(err)
-	}
-
-	peerURL := fmt.Sprintf("http://localhost:%d", etcdProcessBasePort+11)
-	memberID := fmt.Sprintf("%x", mr.Members[0].ID)
-	if err = ctlV3MemberUpdate(cx, memberID, peerURL); err != nil {
-		cx.t.Fatal(err)
-	}
-}
-
-func ctlV3MemberUpdate(cx ctlCtx, memberID, peerURL string) error {
-	cmdArgs := append(cx.PrefixArgs(), "member", "update", memberID, fmt.Sprintf("--peer-urls=%s", peerURL))
-	return spawnWithExpect(cmdArgs, " updated in cluster ")
-}

+ 0 - 99
e2e/ctl_v3_migrate_test.go

@@ -1,99 +0,0 @@
-// Copyright 2016 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 e2e
-
-import (
-	"context"
-	"fmt"
-	"os"
-	"testing"
-	"time"
-
-	"github.com/coreos/etcd/clientv3"
-	"github.com/coreos/etcd/pkg/testutil"
-)
-
-func TestCtlV3Migrate(t *testing.T) {
-	defer testutil.AfterTest(t)
-
-	epc := setupEtcdctlTest(t, &configNoTLS, false)
-	defer func() {
-		if errC := epc.Close(); errC != nil {
-			t.Fatalf("error closing etcd processes (%v)", errC)
-		}
-	}()
-
-	keys := make([]string, 3)
-	vals := make([]string, 3)
-	for i := range keys {
-		keys[i] = fmt.Sprintf("foo_%d", i)
-		vals[i] = fmt.Sprintf("bar_%d", i)
-	}
-	for i := range keys {
-		if err := etcdctlSet(epc, keys[i], vals[i]); err != nil {
-			t.Fatal(err)
-		}
-	}
-
-	dataDir := epc.procs[0].Config().dataDirPath
-	if err := epc.Stop(); err != nil {
-		t.Fatalf("error closing etcd processes (%v)", err)
-	}
-
-	os.Setenv("ETCDCTL_API", "3")
-	defer os.Unsetenv("ETCDCTL_API")
-	cx := ctlCtx{
-		t:           t,
-		cfg:         configNoTLS,
-		dialTimeout: 7 * time.Second,
-		epc:         epc,
-	}
-	if err := ctlV3Migrate(cx, dataDir, ""); err != nil {
-		t.Fatal(err)
-	}
-
-	epc.procs[0].Config().keepDataDir = true
-	if err := epc.Restart(); err != nil {
-		t.Fatal(err)
-	}
-
-	// to ensure revision increment is continuous from migrated v2 data
-	if err := ctlV3Put(cx, "test", "value", ""); err != nil {
-		t.Fatal(err)
-	}
-	cli, err := clientv3.New(clientv3.Config{
-		Endpoints:   epc.EndpointsV3(),
-		DialTimeout: 3 * time.Second,
-	})
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer cli.Close()
-	resp, err := cli.Get(context.TODO(), "test")
-	if err != nil {
-		t.Fatal(err)
-	}
-	if len(resp.Kvs) != 1 {
-		t.Fatalf("len(resp.Kvs) expected 1, got %+v", resp.Kvs)
-	}
-	if resp.Kvs[0].CreateRevision != 7 {
-		t.Fatalf("resp.Kvs[0].CreateRevision expected 7, got %d", resp.Kvs[0].CreateRevision)
-	}
-}
-
-func ctlV3Migrate(cx ctlCtx, dataDir, walDir string) error {
-	cmdArgs := append(cx.PrefixArgs(), "migrate", "--data-dir", dataDir, "--wal-dir", walDir)
-	return spawnWithExpects(cmdArgs, "finished transforming keys")
-}

+ 0 - 117
e2e/ctl_v3_move_leader_test.go

@@ -1,117 +0,0 @@
-// Copyright 2017 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 e2e
-
-import (
-	"context"
-	"crypto/tls"
-	"fmt"
-	"os"
-	"testing"
-	"time"
-
-	"github.com/coreos/etcd/clientv3"
-	"github.com/coreos/etcd/pkg/testutil"
-	"github.com/coreos/etcd/pkg/transport"
-	"github.com/coreos/etcd/pkg/types"
-)
-
-func TestCtlV3MoveLeaderSecure(t *testing.T) {
-	testCtlV3MoveLeader(t, configTLS)
-}
-
-func TestCtlV3MoveLeaderInsecure(t *testing.T) {
-	testCtlV3MoveLeader(t, configNoTLS)
-}
-
-func testCtlV3MoveLeader(t *testing.T, cfg etcdProcessClusterConfig) {
-	defer testutil.AfterTest(t)
-
-	epc := setupEtcdctlTest(t, &cfg, true)
-	defer func() {
-		if errC := epc.Close(); errC != nil {
-			t.Fatalf("error closing etcd processes (%v)", errC)
-		}
-	}()
-
-	var tcfg *tls.Config
-	if cfg.clientTLS == clientTLS {
-		tinfo := transport.TLSInfo{
-			CertFile:      certPath,
-			KeyFile:       privateKeyPath,
-			TrustedCAFile: caPath,
-		}
-		var err error
-		tcfg, err = tinfo.ClientConfig()
-		if err != nil {
-			t.Fatal(err)
-		}
-	}
-
-	var leadIdx int
-	var leaderID uint64
-	var transferee uint64
-	for i, ep := range epc.EndpointsV3() {
-		cli, err := clientv3.New(clientv3.Config{
-			Endpoints:   []string{ep},
-			DialTimeout: 3 * time.Second,
-			TLS:         tcfg,
-		})
-		if err != nil {
-			t.Fatal(err)
-		}
-		resp, err := cli.Status(context.Background(), ep)
-		if err != nil {
-			t.Fatal(err)
-		}
-		cli.Close()
-
-		if resp.Header.GetMemberId() == resp.Leader {
-			leadIdx = i
-			leaderID = resp.Leader
-		} else {
-			transferee = resp.Header.GetMemberId()
-		}
-	}
-
-	os.Setenv("ETCDCTL_API", "3")
-	defer os.Unsetenv("ETCDCTL_API")
-	cx := ctlCtx{
-		t:           t,
-		cfg:         configNoTLS,
-		dialTimeout: 7 * time.Second,
-		epc:         epc,
-	}
-
-	tests := []struct {
-		prefixes []string
-		expect   string
-	}{
-		{ // request to non-leader
-			cx.prefixArgs([]string{cx.epc.EndpointsV3()[(leadIdx+1)%3]}),
-			"no leader endpoint given at ",
-		},
-		{ // request to leader
-			cx.prefixArgs([]string{cx.epc.EndpointsV3()[leadIdx]}),
-			fmt.Sprintf("Leadership transferred from %s to %s", types.ID(leaderID), types.ID(transferee)),
-		},
-	}
-	for i, tc := range tests {
-		cmdArgs := append(tc.prefixes, "move-leader", types.ID(transferee).String())
-		if err := spawnWithExpect(cmdArgs, tc.expect); err != nil {
-			t.Fatalf("#%d: %v", i, err)
-		}
-	}
-}

+ 0 - 179
e2e/ctl_v3_role_test.go

@@ -1,179 +0,0 @@
-// Copyright 2016 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 e2e
-
-import (
-	"fmt"
-	"testing"
-)
-
-func TestCtlV3RoleAdd(t *testing.T)          { testCtl(t, roleAddTest) }
-func TestCtlV3RoleAddNoTLS(t *testing.T)     { testCtl(t, roleAddTest, withCfg(configNoTLS)) }
-func TestCtlV3RoleAddClientTLS(t *testing.T) { testCtl(t, roleAddTest, withCfg(configClientTLS)) }
-func TestCtlV3RoleAddPeerTLS(t *testing.T)   { testCtl(t, roleAddTest, withCfg(configPeerTLS)) }
-func TestCtlV3RoleAddTimeout(t *testing.T)   { testCtl(t, roleAddTest, withDialTimeout(0)) }
-
-func TestCtlV3RoleGrant(t *testing.T) { testCtl(t, roleGrantTest) }
-
-func roleAddTest(cx ctlCtx) {
-	cmdSet := []struct {
-		args        []string
-		expectedStr string
-	}{
-		// Add a role.
-		{
-			args:        []string{"add", "root"},
-			expectedStr: "Role root created",
-		},
-		// Try adding the same role.
-		{
-			args:        []string{"add", "root"},
-			expectedStr: "role name already exists",
-		},
-	}
-
-	for i, cmd := range cmdSet {
-		if err := ctlV3Role(cx, cmd.args, cmd.expectedStr); err != nil {
-			if cx.dialTimeout > 0 && !isGRPCTimedout(err) {
-				cx.t.Fatalf("roleAddTest #%d: ctlV3Role error (%v)", i, err)
-			}
-		}
-	}
-}
-
-func roleGrantTest(cx ctlCtx) {
-	cmdSet := []struct {
-		args        []string
-		expectedStr string
-	}{
-		// Add a role.
-		{
-			args:        []string{"add", "root"},
-			expectedStr: "Role root created",
-		},
-		// Grant read permission to the role.
-		{
-			args:        []string{"grant", "root", "read", "foo"},
-			expectedStr: "Role root updated",
-		},
-		// Grant write permission to the role.
-		{
-			args:        []string{"grant", "root", "write", "foo"},
-			expectedStr: "Role root updated",
-		},
-		// Grant rw permission to the role.
-		{
-			args:        []string{"grant", "root", "readwrite", "foo"},
-			expectedStr: "Role root updated",
-		},
-		// Try granting invalid permission to the role.
-		{
-			args:        []string{"grant", "root", "123", "foo"},
-			expectedStr: "invalid permission type",
-		},
-	}
-
-	for i, cmd := range cmdSet {
-		if err := ctlV3Role(cx, cmd.args, cmd.expectedStr); err != nil {
-			cx.t.Fatalf("roleGrantTest #%d: ctlV3Role error (%v)", i, err)
-		}
-	}
-}
-
-func ctlV3Role(cx ctlCtx, args []string, expStr string) error {
-	cmdArgs := append(cx.PrefixArgs(), "role")
-	cmdArgs = append(cmdArgs, args...)
-
-	return spawnWithExpect(cmdArgs, expStr)
-}
-
-func ctlV3RoleGrantPermission(cx ctlCtx, rolename string, perm grantingPerm) error {
-	cmdArgs := append(cx.PrefixArgs(), "role", "grant-permission")
-	if perm.prefix {
-		cmdArgs = append(cmdArgs, "--prefix")
-	} else if len(perm.rangeEnd) == 1 && perm.rangeEnd[0] == '\x00' {
-		cmdArgs = append(cmdArgs, "--from-key")
-	}
-
-	cmdArgs = append(cmdArgs, rolename)
-	cmdArgs = append(cmdArgs, grantingPermToArgs(perm)...)
-
-	proc, err := spawnCmd(cmdArgs)
-	if err != nil {
-		return err
-	}
-
-	expStr := fmt.Sprintf("Role %s updated", rolename)
-	_, err = proc.Expect(expStr)
-	return err
-}
-
-func ctlV3RoleRevokePermission(cx ctlCtx, rolename string, key, rangeEnd string, fromKey bool) error {
-	cmdArgs := append(cx.PrefixArgs(), "role", "revoke-permission")
-	cmdArgs = append(cmdArgs, rolename)
-	cmdArgs = append(cmdArgs, key)
-	var expStr string
-	if len(rangeEnd) != 0 {
-		cmdArgs = append(cmdArgs, rangeEnd)
-		expStr = fmt.Sprintf("Permission of range [%s, %s) is revoked from role %s", key, rangeEnd, rolename)
-	} else if fromKey {
-		cmdArgs = append(cmdArgs, "--from-key")
-		expStr = fmt.Sprintf("Permission of range [%s, <open ended> is revoked from role %s", key, rolename)
-	} else {
-		expStr = fmt.Sprintf("Permission of key %s is revoked from role %s", key, rolename)
-	}
-
-	proc, err := spawnCmd(cmdArgs)
-	if err != nil {
-		return err
-	}
-
-	_, err = proc.Expect(expStr)
-	return err
-}
-
-type grantingPerm struct {
-	read     bool
-	write    bool
-	key      string
-	rangeEnd string
-	prefix   bool
-}
-
-func grantingPermToArgs(perm grantingPerm) []string {
-	permstr := ""
-
-	if perm.read {
-		permstr += "read"
-	}
-
-	if perm.write {
-		permstr += "write"
-	}
-
-	if len(permstr) == 0 {
-		panic("invalid granting permission")
-	}
-
-	if len(perm.rangeEnd) == 0 {
-		return []string{permstr, perm.key}
-	}
-
-	if len(perm.rangeEnd) == 1 && perm.rangeEnd[0] == '\x00' {
-		return []string{permstr, perm.key}
-	}
-
-	return []string{permstr, perm.key, perm.rangeEnd}
-}

+ 0 - 276
e2e/ctl_v3_snapshot_test.go

@@ -1,276 +0,0 @@
-// Copyright 2016 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 e2e
-
-import (
-	"encoding/json"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"os"
-	"path/filepath"
-	"strings"
-	"testing"
-	"time"
-
-	"github.com/coreos/etcd/pkg/expect"
-	"github.com/coreos/etcd/pkg/testutil"
-)
-
-func TestCtlV3Snapshot(t *testing.T) { testCtl(t, snapshotTest) }
-
-func snapshotTest(cx ctlCtx) {
-	maintenanceInitKeys(cx)
-
-	leaseID, err := ctlV3LeaseGrant(cx, 100)
-	if err != nil {
-		cx.t.Fatalf("snapshot: ctlV3LeaseGrant error (%v)", err)
-	}
-	if err = ctlV3Put(cx, "withlease", "withlease", leaseID); err != nil {
-		cx.t.Fatalf("snapshot: ctlV3Put error (%v)", err)
-	}
-
-	fpath := "test.snapshot"
-	defer os.RemoveAll(fpath)
-
-	if err = ctlV3SnapshotSave(cx, fpath); err != nil {
-		cx.t.Fatalf("snapshotTest ctlV3SnapshotSave error (%v)", err)
-	}
-
-	st, err := getSnapshotStatus(cx, fpath)
-	if err != nil {
-		cx.t.Fatalf("snapshotTest getSnapshotStatus error (%v)", err)
-	}
-	if st.Revision != 5 {
-		cx.t.Fatalf("expected 4, got %d", st.Revision)
-	}
-	if st.TotalKey < 4 {
-		cx.t.Fatalf("expected at least 4, got %d", st.TotalKey)
-	}
-}
-
-func TestCtlV3SnapshotCorrupt(t *testing.T) { testCtl(t, snapshotCorruptTest) }
-
-func snapshotCorruptTest(cx ctlCtx) {
-	fpath := "test.snapshot"
-	defer os.RemoveAll(fpath)
-
-	if err := ctlV3SnapshotSave(cx, fpath); err != nil {
-		cx.t.Fatalf("snapshotTest ctlV3SnapshotSave error (%v)", err)
-	}
-
-	// corrupt file
-	f, oerr := os.OpenFile(fpath, os.O_WRONLY, 0)
-	if oerr != nil {
-		cx.t.Fatal(oerr)
-	}
-	if _, err := f.Write(make([]byte, 512)); err != nil {
-		cx.t.Fatal(err)
-	}
-	f.Close()
-
-	defer os.RemoveAll("snap.etcd")
-	serr := spawnWithExpect(
-		append(cx.PrefixArgs(), "snapshot", "restore",
-			"--data-dir", "snap.etcd",
-			fpath),
-		"expected sha256")
-
-	if serr != nil {
-		cx.t.Fatal(serr)
-	}
-}
-
-// This test ensures that the snapshot status does not modify the snapshot file
-func TestCtlV3SnapshotStatusBeforeRestore(t *testing.T) { testCtl(t, snapshotStatusBeforeRestoreTest) }
-
-func snapshotStatusBeforeRestoreTest(cx ctlCtx) {
-	fpath := "test.snapshot"
-	defer os.RemoveAll(fpath)
-
-	if err := ctlV3SnapshotSave(cx, fpath); err != nil {
-		cx.t.Fatalf("snapshotTest ctlV3SnapshotSave error (%v)", err)
-	}
-
-	// snapshot status on the fresh snapshot file
-	_, err := getSnapshotStatus(cx, fpath)
-	if err != nil {
-		cx.t.Fatalf("snapshotTest getSnapshotStatus error (%v)", err)
-	}
-
-	defer os.RemoveAll("snap.etcd")
-	serr := spawnWithExpect(
-		append(cx.PrefixArgs(), "snapshot", "restore",
-			"--data-dir", "snap.etcd",
-			fpath),
-		"added member")
-
-	if serr != nil {
-		cx.t.Fatal(serr)
-	}
-}
-
-func ctlV3SnapshotSave(cx ctlCtx, fpath string) error {
-	cmdArgs := append(cx.PrefixArgs(), "snapshot", "save", fpath)
-	return spawnWithExpect(cmdArgs, fmt.Sprintf("Snapshot saved at %s", fpath))
-}
-
-type snapshotStatus struct {
-	Hash      uint32 `json:"hash"`
-	Revision  int64  `json:"revision"`
-	TotalKey  int    `json:"totalKey"`
-	TotalSize int64  `json:"totalSize"`
-}
-
-func getSnapshotStatus(cx ctlCtx, fpath string) (snapshotStatus, error) {
-	cmdArgs := append(cx.PrefixArgs(), "--write-out", "json", "snapshot", "status", fpath)
-
-	proc, err := spawnCmd(cmdArgs)
-	if err != nil {
-		return snapshotStatus{}, err
-	}
-	var txt string
-	txt, err = proc.Expect("totalKey")
-	if err != nil {
-		return snapshotStatus{}, err
-	}
-	if err = proc.Close(); err != nil {
-		return snapshotStatus{}, err
-	}
-
-	resp := snapshotStatus{}
-	dec := json.NewDecoder(strings.NewReader(txt))
-	if err := dec.Decode(&resp); err == io.EOF {
-		return snapshotStatus{}, err
-	}
-	return resp, nil
-}
-
-// TestIssue6361 ensures new member that starts with snapshot correctly
-// syncs up with other members and serve correct data.
-func TestIssue6361(t *testing.T) {
-	defer testutil.AfterTest(t)
-	mustEtcdctl(t)
-	os.Setenv("ETCDCTL_API", "3")
-	defer os.Unsetenv("ETCDCTL_API")
-
-	epc, err := newEtcdProcessCluster(&etcdProcessClusterConfig{
-		clusterSize:  1,
-		initialToken: "new",
-		keepDataDir:  true,
-	})
-	if err != nil {
-		t.Fatalf("could not start etcd process cluster (%v)", err)
-	}
-	defer func() {
-		if errC := epc.Close(); errC != nil {
-			t.Fatalf("error closing etcd processes (%v)", errC)
-		}
-	}()
-
-	dialTimeout := 7 * time.Second
-	prefixArgs := []string{ctlBinPath, "--endpoints", strings.Join(epc.EndpointsV3(), ","), "--dial-timeout", dialTimeout.String()}
-
-	// write some keys
-	kvs := []kv{{"foo1", "val1"}, {"foo2", "val2"}, {"foo3", "val3"}}
-	for i := range kvs {
-		if err = spawnWithExpect(append(prefixArgs, "put", kvs[i].key, kvs[i].val), "OK"); err != nil {
-			t.Fatal(err)
-		}
-	}
-
-	fpath := filepath.Join(os.TempDir(), "test.snapshot")
-	defer os.RemoveAll(fpath)
-
-	// etcdctl save snapshot
-	if err = spawnWithExpect(append(prefixArgs, "snapshot", "save", fpath), fmt.Sprintf("Snapshot saved at %s", fpath)); err != nil {
-		t.Fatal(err)
-	}
-
-	if err = epc.procs[0].Stop(); err != nil {
-		t.Fatal(err)
-	}
-
-	newDataDir := filepath.Join(os.TempDir(), "test.data")
-	defer os.RemoveAll(newDataDir)
-
-	// etcdctl restore the snapshot
-	err = spawnWithExpect([]string{ctlBinPath, "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().purl.String(), "--data-dir", newDataDir}, "membership: added member")
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	// start the etcd member using the restored snapshot
-	epc.procs[0].Config().dataDirPath = newDataDir
-	for i := range epc.procs[0].Config().args {
-		if epc.procs[0].Config().args[i] == "--data-dir" {
-			epc.procs[0].Config().args[i+1] = newDataDir
-		}
-	}
-	if err = epc.procs[0].Restart(); err != nil {
-		t.Fatal(err)
-	}
-
-	// ensure the restored member has the correct data
-	for i := range kvs {
-		if err = spawnWithExpect(append(prefixArgs, "get", kvs[i].key), kvs[i].val); err != nil {
-			t.Fatal(err)
-		}
-	}
-
-	// add a new member into the cluster
-	clientURL := fmt.Sprintf("http://localhost:%d", etcdProcessBasePort+30)
-	peerURL := fmt.Sprintf("http://localhost:%d", etcdProcessBasePort+31)
-	err = spawnWithExpect(append(prefixArgs, "member", "add", "newmember", fmt.Sprintf("--peer-urls=%s", peerURL)), " added to cluster ")
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	var newDataDir2 string
-	newDataDir2, err = ioutil.TempDir("", "newdata2")
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer os.RemoveAll(newDataDir2)
-
-	name2 := "infra2"
-	initialCluster2 := epc.procs[0].Config().initialCluster + fmt.Sprintf(",%s=%s", name2, peerURL)
-
-	// start the new member
-	var nepc *expect.ExpectProcess
-	nepc, err = spawnCmd([]string{epc.procs[0].Config().execPath, "--name", name2,
-		"--listen-client-urls", clientURL, "--advertise-client-urls", clientURL,
-		"--listen-peer-urls", peerURL, "--initial-advertise-peer-urls", peerURL,
-		"--initial-cluster", initialCluster2, "--initial-cluster-state", "existing", "--data-dir", newDataDir2})
-	if err != nil {
-		t.Fatal(err)
-	}
-	if _, err = nepc.Expect("enabled capabilities for version"); err != nil {
-		t.Fatal(err)
-	}
-
-	prefixArgs = []string{ctlBinPath, "--endpoints", clientURL, "--dial-timeout", dialTimeout.String()}
-
-	// ensure added member has data from incoming snapshot
-	for i := range kvs {
-		if err = spawnWithExpect(append(prefixArgs, "get", kvs[i].key), kvs[i].val); err != nil {
-			t.Fatal(err)
-		}
-	}
-
-	if err = nepc.Stop(); err != nil {
-		t.Fatal(err)
-	}
-}

+ 0 - 250
e2e/ctl_v3_test.go

@@ -1,250 +0,0 @@
-// Copyright 2016 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 e2e
-
-import (
-	"fmt"
-	"os"
-	"strings"
-	"testing"
-	"time"
-
-	"github.com/coreos/etcd/pkg/flags"
-	"github.com/coreos/etcd/pkg/testutil"
-	"github.com/coreos/etcd/version"
-)
-
-func TestCtlV3Version(t *testing.T) { testCtl(t, versionTest) }
-
-func versionTest(cx ctlCtx) {
-	if err := ctlV3Version(cx); err != nil {
-		cx.t.Fatalf("versionTest ctlV3Version error (%v)", err)
-	}
-}
-
-func ctlV3Version(cx ctlCtx) error {
-	cmdArgs := append(cx.PrefixArgs(), "version")
-	return spawnWithExpect(cmdArgs, version.Version)
-}
-
-// TestCtlV3DialWithHTTPScheme ensures that client handles endpoints with HTTPS scheme.
-func TestCtlV3DialWithHTTPScheme(t *testing.T) {
-	testCtl(t, dialWithSchemeTest, withCfg(configClientTLS))
-}
-
-func dialWithSchemeTest(cx ctlCtx) {
-	cmdArgs := append(cx.prefixArgs(cx.epc.EndpointsV3()), "put", "foo", "bar")
-	if err := spawnWithExpect(cmdArgs, "OK"); err != nil {
-		cx.t.Fatal(err)
-	}
-}
-
-type ctlCtx struct {
-	t                 *testing.T
-	cfg               etcdProcessClusterConfig
-	quotaBackendBytes int64
-	corruptFunc       func(string) error
-	noStrictReconfig  bool
-
-	epc *etcdProcessCluster
-
-	envMap map[string]struct{}
-
-	dialTimeout time.Duration
-
-	quorum      bool // if true, set up 3-node cluster and linearizable read
-	interactive bool
-
-	user string
-	pass string
-
-	initialCorruptCheck bool
-
-	// for compaction
-	compactPhysical bool
-}
-
-type ctlOption func(*ctlCtx)
-
-func (cx *ctlCtx) applyOpts(opts []ctlOption) {
-	for _, opt := range opts {
-		opt(cx)
-	}
-	cx.initialCorruptCheck = true
-}
-
-func withCfg(cfg etcdProcessClusterConfig) ctlOption {
-	return func(cx *ctlCtx) { cx.cfg = cfg }
-}
-
-func withDialTimeout(timeout time.Duration) ctlOption {
-	return func(cx *ctlCtx) { cx.dialTimeout = timeout }
-}
-
-func withQuorum() ctlOption {
-	return func(cx *ctlCtx) { cx.quorum = true }
-}
-
-func withInteractive() ctlOption {
-	return func(cx *ctlCtx) { cx.interactive = true }
-}
-
-func withQuota(b int64) ctlOption {
-	return func(cx *ctlCtx) { cx.quotaBackendBytes = b }
-}
-
-func withCompactPhysical() ctlOption {
-	return func(cx *ctlCtx) { cx.compactPhysical = true }
-}
-
-func withInitialCorruptCheck() ctlOption {
-	return func(cx *ctlCtx) { cx.initialCorruptCheck = true }
-}
-
-func withCorruptFunc(f func(string) error) ctlOption {
-	return func(cx *ctlCtx) { cx.corruptFunc = f }
-}
-
-func withNoStrictReconfig() ctlOption {
-	return func(cx *ctlCtx) { cx.noStrictReconfig = true }
-}
-
-func withFlagByEnv() ctlOption {
-	return func(cx *ctlCtx) { cx.envMap = make(map[string]struct{}) }
-}
-
-func testCtl(t *testing.T, testFunc func(ctlCtx), opts ...ctlOption) {
-	defer testutil.AfterTest(t)
-
-	ret := ctlCtx{
-		t:           t,
-		cfg:         configAutoTLS,
-		dialTimeout: 7 * time.Second,
-	}
-	ret.applyOpts(opts)
-
-	mustEtcdctl(t)
-	if !ret.quorum {
-		ret.cfg = *configStandalone(ret.cfg)
-	}
-	if ret.quotaBackendBytes > 0 {
-		ret.cfg.quotaBackendBytes = ret.quotaBackendBytes
-	}
-	ret.cfg.noStrictReconfig = ret.noStrictReconfig
-	if ret.initialCorruptCheck {
-		ret.cfg.initialCorruptCheck = ret.initialCorruptCheck
-	}
-
-	epc, err := newEtcdProcessCluster(&ret.cfg)
-	if err != nil {
-		t.Fatalf("could not start etcd process cluster (%v)", err)
-	}
-	ret.epc = epc
-
-	defer func() {
-		if ret.envMap != nil {
-			for k := range ret.envMap {
-				os.Unsetenv(k)
-			}
-		}
-		if errC := ret.epc.Close(); errC != nil {
-			t.Fatalf("error closing etcd processes (%v)", errC)
-		}
-	}()
-
-	donec := make(chan struct{})
-	go func() {
-		defer close(donec)
-		testFunc(ret)
-	}()
-
-	timeout := 2*ret.dialTimeout + time.Second
-	if ret.dialTimeout == 0 {
-		timeout = 30 * time.Second
-	}
-	select {
-	case <-time.After(timeout):
-		testutil.FatalStack(t, fmt.Sprintf("test timed out after %v", timeout))
-	case <-donec:
-	}
-}
-
-func (cx *ctlCtx) prefixArgs(eps []string) []string {
-	fmap := make(map[string]string)
-	fmap["endpoints"] = strings.Join(eps, ",")
-	fmap["dial-timeout"] = cx.dialTimeout.String()
-	if cx.epc.cfg.clientTLS == clientTLS {
-		if cx.epc.cfg.isClientAutoTLS {
-			fmap["insecure-transport"] = "false"
-			fmap["insecure-skip-tls-verify"] = "true"
-		} else if cx.epc.cfg.isClientCRL {
-			fmap["cacert"] = caPath
-			fmap["cert"] = revokedCertPath
-			fmap["key"] = revokedPrivateKeyPath
-		} else {
-			fmap["cacert"] = caPath
-			fmap["cert"] = certPath
-			fmap["key"] = privateKeyPath
-		}
-	}
-	if cx.user != "" {
-		fmap["user"] = cx.user + ":" + cx.pass
-	}
-
-	useEnv := cx.envMap != nil
-
-	cmdArgs := []string{ctlBinPath + "3"}
-	for k, v := range fmap {
-		if useEnv {
-			ek := flags.FlagToEnv("ETCDCTL", k)
-			os.Setenv(ek, v)
-			cx.envMap[ek] = struct{}{}
-		} else {
-			cmdArgs = append(cmdArgs, fmt.Sprintf("--%s=%s", k, v))
-		}
-	}
-	return cmdArgs
-}
-
-// PrefixArgs prefixes etcdctl command.
-// Make sure to unset environment variables after tests.
-func (cx *ctlCtx) PrefixArgs() []string {
-	return cx.prefixArgs(cx.epc.EndpointsV3())
-}
-
-func isGRPCTimedout(err error) bool {
-	return strings.Contains(err.Error(), "grpc: timed out trying to connect")
-}
-
-func (cx *ctlCtx) memberToRemove() (ep string, memberID string, clusterID string) {
-	n1 := cx.cfg.clusterSize
-	if n1 < 2 {
-		cx.t.Fatalf("%d-node is too small to test 'member remove'", n1)
-	}
-
-	resp, err := getMemberList(*cx)
-	if err != nil {
-		cx.t.Fatal(err)
-	}
-	if n1 != len(resp.Members) {
-		cx.t.Fatalf("expected %d, got %d", n1, len(resp.Members))
-	}
-
-	ep = resp.Members[0].ClientURLs[0]
-	clusterID = fmt.Sprintf("%x", resp.Header.ClusterId)
-	memberID = fmt.Sprintf("%x", resp.Members[1].ID)
-
-	return ep, memberID, clusterID
-}

+ 0 - 155
e2e/ctl_v3_txn_test.go

@@ -1,155 +0,0 @@
-// Copyright 2016 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 e2e
-
-import "testing"
-
-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 txnTestSuccess(cx ctlCtx) {
-	if err := ctlV3Put(cx, "key1", "value1", ""); err != nil {
-		cx.t.Fatalf("txnTestSuccess ctlV3Put error (%v)", err)
-	}
-	if err := ctlV3Put(cx, "key2", "value2", ""); err != nil {
-		cx.t.Fatalf("txnTestSuccess ctlV3Put error (%v)", err)
-	}
-	rqs := []txnRequests{
-		{
-			compare:  []string{`value("key1") != "value2"`, `value("key2") != "value1"`},
-			ifSucess: []string{"get key1", "get key2"},
-			results:  []string{"SUCCESS", "key1", "value1", "key2", "value2"},
-		},
-		{
-			compare:  []string{`version("key1") = "1"`, `version("key2") = "1"`},
-			ifSucess: []string{"get key1", "get key2", `put "key \"with\" space" "value \x23"`},
-			ifFail:   []string{`put key1 "fail"`, `put key2 "fail"`},
-			results:  []string{"SUCCESS", "key1", "value1", "key2", "value2"},
-		},
-		{
-			compare:  []string{`version("key \"with\" space") = "1"`},
-			ifSucess: []string{`get "key \"with\" space"`},
-			results:  []string{"SUCCESS", `key "with" space`, "value \x23"},
-		},
-	}
-	for _, rq := range rqs {
-		if err := ctlV3Txn(cx, rq); err != nil {
-			cx.t.Fatal(err)
-		}
-	}
-}
-
-func txnTestFail(cx ctlCtx) {
-	if err := ctlV3Put(cx, "key1", "value1", ""); err != nil {
-		cx.t.Fatalf("txnTestSuccess ctlV3Put error (%v)", err)
-	}
-	rqs := []txnRequests{
-		{
-			compare:  []string{`version("key") < "0"`},
-			ifSucess: []string{`put key "success"`},
-			ifFail:   []string{`put key "fail"`},
-			results:  []string{"FAILURE", "OK"},
-		},
-		{
-			compare:  []string{`value("key1") != "value1"`},
-			ifSucess: []string{`put key1 "success"`},
-			ifFail:   []string{`put key1 "fail"`},
-			results:  []string{"FAILURE", "OK"},
-		},
-	}
-	for _, rq := range rqs {
-		if err := ctlV3Txn(cx, rq); err != nil {
-			cx.t.Fatal(err)
-		}
-	}
-}
-
-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(cx.PrefixArgs(), "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, del):")
-	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, del):")
-	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()
-}

+ 0 - 139
e2e/ctl_v3_user_test.go

@@ -1,139 +0,0 @@
-// Copyright 2016 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 e2e
-
-import "testing"
-
-func TestCtlV3UserAdd(t *testing.T)          { testCtl(t, userAddTest) }
-func TestCtlV3UserAddNoTLS(t *testing.T)     { testCtl(t, userAddTest, withCfg(configNoTLS)) }
-func TestCtlV3UserAddClientTLS(t *testing.T) { testCtl(t, userAddTest, withCfg(configClientTLS)) }
-func TestCtlV3UserAddPeerTLS(t *testing.T)   { testCtl(t, userAddTest, withCfg(configPeerTLS)) }
-func TestCtlV3UserAddTimeout(t *testing.T)   { testCtl(t, userAddTest, withDialTimeout(0)) }
-
-func TestCtlV3UserDelete(t *testing.T) { testCtl(t, userDelTest) }
-func TestCtlV3UserPasswd(t *testing.T) { testCtl(t, userPasswdTest) }
-
-type userCmdDesc struct {
-	args        []string
-	expectedStr string
-	stdIn       []string
-}
-
-func userAddTest(cx ctlCtx) {
-	cmdSet := []userCmdDesc{
-		// Adds a user name.
-		{
-			args:        []string{"add", "username", "--interactive=false"},
-			expectedStr: "User username created",
-			stdIn:       []string{"password"},
-		},
-		// Adds a user name using the usertest:password syntax.
-		{
-			args:        []string{"add", "usertest:password"},
-			expectedStr: "User usertest created",
-			stdIn:       []string{},
-		},
-		// Tries to add a user with empty username.
-		{
-			args:        []string{"add", ":password"},
-			expectedStr: "empty user name is not allowed.",
-			stdIn:       []string{},
-		},
-		// Tries to add a user name that already exists.
-		{
-			args:        []string{"add", "username", "--interactive=false"},
-			expectedStr: "user name already exists",
-			stdIn:       []string{"password"},
-		},
-	}
-
-	for i, cmd := range cmdSet {
-		if err := ctlV3User(cx, cmd.args, cmd.expectedStr, cmd.stdIn); err != nil {
-			if cx.dialTimeout > 0 && !isGRPCTimedout(err) {
-				cx.t.Fatalf("userAddTest #%d: ctlV3User error (%v)", i, err)
-			}
-		}
-	}
-}
-
-func userDelTest(cx ctlCtx) {
-	cmdSet := []userCmdDesc{
-		// Adds a user name.
-		{
-			args:        []string{"add", "username", "--interactive=false"},
-			expectedStr: "User username created",
-			stdIn:       []string{"password"},
-		},
-		// Deletes the user name just added.
-		{
-			args:        []string{"delete", "username"},
-			expectedStr: "User username deleted",
-		},
-		// Deletes a user name that is not present.
-		{
-			args:        []string{"delete", "username"},
-			expectedStr: "user name not found",
-		},
-	}
-
-	for i, cmd := range cmdSet {
-		if err := ctlV3User(cx, cmd.args, cmd.expectedStr, cmd.stdIn); err != nil {
-			cx.t.Fatalf("userDelTest #%d: ctlV3User error (%v)", i, err)
-		}
-	}
-}
-
-func userPasswdTest(cx ctlCtx) {
-	cmdSet := []userCmdDesc{
-		// Adds a user name.
-		{
-			args:        []string{"add", "username", "--interactive=false"},
-			expectedStr: "User username created",
-			stdIn:       []string{"password"},
-		},
-		// Changes the password.
-		{
-			args:        []string{"passwd", "username", "--interactive=false"},
-			expectedStr: "Password updated",
-			stdIn:       []string{"password1"},
-		},
-	}
-
-	for i, cmd := range cmdSet {
-		if err := ctlV3User(cx, cmd.args, cmd.expectedStr, cmd.stdIn); err != nil {
-			cx.t.Fatalf("userPasswdTest #%d: ctlV3User error (%v)", i, err)
-		}
-	}
-}
-
-func ctlV3User(cx ctlCtx, args []string, expStr string, stdIn []string) error {
-	cmdArgs := append(cx.PrefixArgs(), "user")
-	cmdArgs = append(cmdArgs, args...)
-
-	proc, err := spawnCmd(cmdArgs)
-	if err != nil {
-		return err
-	}
-
-	// Send 'stdIn' strings as input.
-	for _, s := range stdIn {
-		if err = proc.Send(s + "\r"); err != nil {
-			return err
-		}
-	}
-
-	_, err = proc.Expect(expStr)
-	return err
-}

+ 0 - 89
e2e/ctl_v3_watch_test.go

@@ -1,89 +0,0 @@
-// Copyright 2018 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 e2e
-
-import "strings"
-
-type kvExec struct {
-	key, val   string
-	execOutput string
-}
-
-func setupWatchArgs(cx ctlCtx, args []string) []string {
-	cmdArgs := append(cx.PrefixArgs(), "watch")
-	if cx.interactive {
-		cmdArgs = append(cmdArgs, "--interactive")
-	} else {
-		cmdArgs = append(cmdArgs, args...)
-	}
-
-	return cmdArgs
-}
-
-func ctlV3Watch(cx ctlCtx, args []string, kvs ...kvExec) error {
-	cmdArgs := setupWatchArgs(cx, args)
-
-	proc, err := spawnCmd(cmdArgs)
-	if err != nil {
-		return err
-	}
-
-	if cx.interactive {
-		wl := strings.Join(append([]string{"watch"}, args...), " ") + "\r"
-		if err = proc.Send(wl); err != nil {
-			return err
-		}
-	}
-
-	for _, elem := range kvs {
-		if _, err = proc.Expect(elem.key); err != nil {
-			return err
-		}
-		if _, err = proc.Expect(elem.val); err != nil {
-			return err
-		}
-		if elem.execOutput != "" {
-			if _, err = proc.Expect(elem.execOutput); err != nil {
-				return err
-			}
-		}
-	}
-	return proc.Stop()
-}
-
-func ctlV3WatchFailPerm(cx ctlCtx, args []string) error {
-	cmdArgs := setupWatchArgs(cx, args)
-
-	proc, err := spawnCmd(cmdArgs)
-	if err != nil {
-		return err
-	}
-
-	if cx.interactive {
-		wl := strings.Join(append([]string{"watch"}, args...), " ") + "\r"
-		if err = proc.Send(wl); err != nil {
-			return err
-		}
-	}
-
-	// TODO(mitake): after printing accurate error message that includes
-	// "permission denied", the above string argument of proc.Expect()
-	// should be updated.
-	_, err = proc.Expect("watch is canceled by the server")
-	if err != nil {
-		return err
-	}
-	return proc.Close()
-}

+ 0 - 24
e2e/doc.go

@@ -1,24 +0,0 @@
-// Copyright 2016 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 e2e implements tests built upon etcd binaries, and focus on
-end-to-end testing.
-
-Features/goals of the end-to-end tests:
-1. test command-line parsing and arguments.
-2. test user-facing command-line API.
-3. launch full processes and check for expected outputs.
-*/
-package e2e

+ 0 - 192
e2e/etcd_config_test.go

@@ -1,192 +0,0 @@
-// Copyright 2016 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 e2e
-
-import (
-	"fmt"
-	"io/ioutil"
-	"os"
-	"strings"
-	"testing"
-
-	"github.com/coreos/etcd/pkg/expect"
-)
-
-const exampleConfigFile = "../etcd.conf.yml.sample"
-
-func TestEtcdExampleConfig(t *testing.T) {
-	proc, err := spawnCmd([]string{binDir + "/etcd", "--config-file", exampleConfigFile})
-	if err != nil {
-		t.Fatal(err)
-	}
-	if err = waitReadyExpectProc(proc, etcdServerReadyLines); err != nil {
-		t.Fatal(err)
-	}
-	if err = proc.Stop(); err != nil {
-		t.Fatal(err)
-	}
-}
-
-func TestEtcdMultiPeer(t *testing.T) {
-	peers, tmpdirs := make([]string, 3), make([]string, 3)
-	for i := range peers {
-		peers[i] = fmt.Sprintf("e%d=http://127.0.0.1:%d", i, etcdProcessBasePort+i)
-		d, err := ioutil.TempDir("", fmt.Sprintf("e%d.etcd", i))
-		if err != nil {
-			t.Fatal(err)
-		}
-		tmpdirs[i] = d
-	}
-	ic := strings.Join(peers, ",")
-
-	procs := make([]*expect.ExpectProcess, len(peers))
-	defer func() {
-		for i := range procs {
-			if procs[i] != nil {
-				procs[i].Stop()
-			}
-			os.RemoveAll(tmpdirs[i])
-		}
-	}()
-	for i := range procs {
-		args := []string{
-			binDir + "/etcd",
-			"--name", fmt.Sprintf("e%d", i),
-			"--listen-client-urls", "http://0.0.0.0:0",
-			"--data-dir", tmpdirs[i],
-			"--advertise-client-urls", "http://0.0.0.0:0",
-			"--listen-peer-urls", fmt.Sprintf("http://127.0.0.1:%d,http://127.0.0.1:%d", etcdProcessBasePort+i, etcdProcessBasePort+len(peers)+i),
-			"--initial-advertise-peer-urls", fmt.Sprintf("http://127.0.0.1:%d", etcdProcessBasePort+i),
-			"--initial-cluster", ic,
-		}
-		p, err := spawnCmd(args)
-		if err != nil {
-			t.Fatal(err)
-		}
-		procs[i] = p
-	}
-
-	for _, p := range procs {
-		if err := waitReadyExpectProc(p, etcdServerReadyLines); err != nil {
-			t.Fatal(err)
-		}
-	}
-}
-
-// TestEtcdUnixPeers checks that etcd will boot with unix socket peers.
-func TestEtcdUnixPeers(t *testing.T) {
-	d, err := ioutil.TempDir("", "e1.etcd")
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer os.RemoveAll(d)
-	proc, err := spawnCmd(
-		[]string{
-			binDir + "/etcd",
-			"--data-dir", d,
-			"--name", "e1",
-			"--listen-peer-urls", "unix://etcd.unix:1",
-			"--initial-advertise-peer-urls", "unix://etcd.unix:1",
-			"--initial-cluster", "e1=unix://etcd.unix:1",
-		},
-	)
-	defer os.Remove("etcd.unix:1")
-	if err != nil {
-		t.Fatal(err)
-	}
-	if err = waitReadyExpectProc(proc, etcdServerReadyLines); err != nil {
-		t.Fatal(err)
-	}
-	if err = proc.Stop(); err != nil {
-		t.Fatal(err)
-	}
-}
-
-// TestEtcdPeerCNAuth checks that the inter peer auth based on CN of cert is working correctly.
-func TestEtcdPeerCNAuth(t *testing.T) {
-	peers, tmpdirs := make([]string, 3), make([]string, 3)
-	for i := range peers {
-		peers[i] = fmt.Sprintf("e%d=https://127.0.0.1:%d", i, etcdProcessBasePort+i)
-		d, err := ioutil.TempDir("", fmt.Sprintf("e%d.etcd", i))
-		if err != nil {
-			t.Fatal(err)
-		}
-		tmpdirs[i] = d
-	}
-	ic := strings.Join(peers, ",")
-
-	procs := make([]*expect.ExpectProcess, len(peers))
-	defer func() {
-		for i := range procs {
-			if procs[i] != nil {
-				procs[i].Stop()
-			}
-			os.RemoveAll(tmpdirs[i])
-		}
-	}()
-
-	// node 0 and 1 have a cert with the correct CN, node 2 doesn't
-	for i := range procs {
-		commonArgs := []string{
-			binDir + "/etcd",
-			"--name", fmt.Sprintf("e%d", i),
-			"--listen-client-urls", "http://0.0.0.0:0",
-			"--data-dir", tmpdirs[i],
-			"--advertise-client-urls", "http://0.0.0.0:0",
-			"--listen-peer-urls", fmt.Sprintf("https://127.0.0.1:%d,https://127.0.0.1:%d", etcdProcessBasePort+i, etcdProcessBasePort+len(peers)+i),
-			"--initial-advertise-peer-urls", fmt.Sprintf("https://127.0.0.1:%d", etcdProcessBasePort+i),
-			"--initial-cluster", ic,
-		}
-
-		var args []string
-		if i <= 1 {
-			args = []string{
-				"--peer-cert-file", certPath,
-				"--peer-key-file", privateKeyPath,
-				"--peer-trusted-ca-file", caPath,
-				"--peer-client-cert-auth",
-				"--peer-cert-allowed-cn", "example.com",
-			}
-		} else {
-			args = []string{
-				"--peer-cert-file", certPath2,
-				"--peer-key-file", privateKeyPath2,
-				"--peer-trusted-ca-file", caPath,
-				"--peer-client-cert-auth",
-				"--peer-cert-allowed-cn", "example2.com",
-			}
-		}
-
-		commonArgs = append(commonArgs, args...)
-
-		p, err := spawnCmd(commonArgs)
-		if err != nil {
-			t.Fatal(err)
-		}
-		procs[i] = p
-	}
-
-	for i, p := range procs {
-		var expect []string
-		if i <= 1 {
-			expect = etcdServerReadyLines
-		} else {
-			expect = []string{"remote error: tls: bad certificate"}
-		}
-		if err := waitReadyExpectProc(p, expect); err != nil {
-			t.Fatal(err)
-		}
-	}
-}

+ 0 - 129
e2e/etcd_corrupt_test.go

@@ -1,129 +0,0 @@
-// Copyright 2017 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 e2e
-
-import (
-	"context"
-	"errors"
-	"fmt"
-	"os"
-	"path/filepath"
-	"testing"
-	"time"
-
-	"github.com/coreos/etcd/clientv3"
-	"github.com/coreos/etcd/mvcc/mvccpb"
-
-	bolt "github.com/coreos/bbolt"
-)
-
-// TODO: test with embedded etcd in integration package
-
-func TestEtcdCorruptHash(t *testing.T) {
-	oldenv := os.Getenv("EXPECT_DEBUG")
-	defer os.Setenv("EXPECT_DEBUG", oldenv)
-	os.Setenv("EXPECT_DEBUG", "1")
-
-	cfg := configNoTLS
-
-	// trigger snapshot so that restart member can load peers from disk
-	cfg.snapCount = 3
-
-	testCtl(t, corruptTest, withQuorum(),
-		withCfg(cfg),
-		withInitialCorruptCheck(),
-		withCorruptFunc(corruptHash),
-	)
-}
-
-func corruptTest(cx ctlCtx) {
-	for i := 0; i < 10; i++ {
-		if err := ctlV3Put(cx, fmt.Sprintf("foo%05d", i), fmt.Sprintf("v%05d", i), ""); err != nil {
-			if cx.dialTimeout > 0 && !isGRPCTimedout(err) {
-				cx.t.Fatalf("putTest ctlV3Put error (%v)", err)
-			}
-		}
-	}
-	// enough time for all nodes sync on the same data
-	time.Sleep(3 * time.Second)
-
-	eps := cx.epc.EndpointsV3()
-	cli1, err := clientv3.New(clientv3.Config{Endpoints: []string{eps[1]}, DialTimeout: 3 * time.Second})
-	if err != nil {
-		cx.t.Fatal(err)
-	}
-	defer cli1.Close()
-
-	sresp, err := cli1.Status(context.TODO(), eps[0])
-	if err != nil {
-		cx.t.Fatal(err)
-	}
-	id0 := sresp.Header.GetMemberId()
-
-	cx.epc.procs[0].Stop()
-
-	// corrupt first member by modifying backend offline.
-	fp := filepath.Join(cx.epc.procs[0].Config().dataDirPath, "member", "snap", "db")
-	if err = cx.corruptFunc(fp); err != nil {
-		cx.t.Fatal(err)
-	}
-
-	ep := cx.epc.procs[0]
-	proc, err := spawnCmd(append([]string{ep.Config().execPath}, ep.Config().args...))
-	if err != nil {
-		cx.t.Fatal(err)
-	}
-	defer proc.Stop()
-
-	// restarting corrupted member should fail
-	waitReadyExpectProc(proc, []string{fmt.Sprintf("etcdmain: %016x found data inconsistency with peers", id0)})
-}
-
-func corruptHash(fpath string) error {
-	db, derr := bolt.Open(fpath, os.ModePerm, &bolt.Options{})
-	if derr != nil {
-		return derr
-	}
-	defer db.Close()
-
-	return db.Update(func(tx *bolt.Tx) error {
-		b := tx.Bucket([]byte("key"))
-		if b == nil {
-			return errors.New("got nil bucket for 'key'")
-		}
-		keys, vals := [][]byte{}, [][]byte{}
-		c := b.Cursor()
-		for k, v := c.First(); k != nil; k, v = c.Next() {
-			keys = append(keys, k)
-			var kv mvccpb.KeyValue
-			if uerr := kv.Unmarshal(v); uerr != nil {
-				return uerr
-			}
-			kv.Key[0]++
-			kv.Value[0]++
-			v2, v2err := kv.Marshal()
-			if v2err != nil {
-				return v2err
-			}
-			vals = append(vals, v2)
-		}
-		for i := range keys {
-			if perr := b.Put(keys[i], vals[i]); perr != nil {
-				return perr
-			}
-		}
-		return nil
-	})
-}

+ 0 - 141
e2e/etcd_process.go

@@ -1,141 +0,0 @@
-// Copyright 2017 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 e2e
-
-import (
-	"fmt"
-	"net/url"
-	"os"
-
-	"github.com/coreos/etcd/pkg/expect"
-	"github.com/coreos/etcd/pkg/fileutil"
-)
-
-var (
-	etcdServerReadyLines = []string{"enabled capabilities for version", "published"}
-	binPath              string
-	ctlBinPath           string
-)
-
-// etcdProcess is a process that serves etcd requests.
-type etcdProcess interface {
-	EndpointsV2() []string
-	EndpointsV3() []string
-	EndpointsMetrics() []string
-
-	Start() error
-	Restart() error
-	Stop() error
-	Close() error
-	WithStopSignal(sig os.Signal) os.Signal
-	Config() *etcdServerProcessConfig
-}
-
-type etcdServerProcess struct {
-	cfg   *etcdServerProcessConfig
-	proc  *expect.ExpectProcess
-	donec chan struct{} // closed when Interact() terminates
-}
-
-type etcdServerProcessConfig struct {
-	execPath string
-	args     []string
-	tlsArgs  []string
-
-	dataDirPath string
-	keepDataDir bool
-
-	name string
-
-	purl url.URL
-
-	acurl string
-	murl  string
-
-	initialToken   string
-	initialCluster string
-}
-
-func newEtcdServerProcess(cfg *etcdServerProcessConfig) (*etcdServerProcess, error) {
-	if !fileutil.Exist(cfg.execPath) {
-		return nil, fmt.Errorf("could not find etcd binary")
-	}
-	if !cfg.keepDataDir {
-		if err := os.RemoveAll(cfg.dataDirPath); err != nil {
-			return nil, err
-		}
-	}
-	return &etcdServerProcess{cfg: cfg, donec: make(chan struct{})}, nil
-}
-
-func (ep *etcdServerProcess) EndpointsV2() []string      { return []string{ep.cfg.acurl} }
-func (ep *etcdServerProcess) EndpointsV3() []string      { return ep.EndpointsV2() }
-func (ep *etcdServerProcess) EndpointsMetrics() []string { return []string{ep.cfg.murl} }
-
-func (ep *etcdServerProcess) Start() error {
-	if ep.proc != nil {
-		panic("already started")
-	}
-	proc, err := spawnCmd(append([]string{ep.cfg.execPath}, ep.cfg.args...))
-	if err != nil {
-		return err
-	}
-	ep.proc = proc
-	return ep.waitReady()
-}
-
-func (ep *etcdServerProcess) Restart() error {
-	if err := ep.Stop(); err != nil {
-		return err
-	}
-	ep.donec = make(chan struct{})
-	return ep.Start()
-}
-
-func (ep *etcdServerProcess) Stop() error {
-	if ep == nil || ep.proc == nil {
-		return nil
-	}
-	if err := ep.proc.Stop(); err != nil {
-		return err
-	}
-	ep.proc = nil
-	<-ep.donec
-	ep.donec = make(chan struct{})
-	if ep.cfg.purl.Scheme == "unix" || ep.cfg.purl.Scheme == "unixs" {
-		os.Remove(ep.cfg.purl.Host + ep.cfg.purl.Path)
-	}
-	return nil
-}
-
-func (ep *etcdServerProcess) Close() error {
-	if err := ep.Stop(); err != nil {
-		return err
-	}
-	return os.RemoveAll(ep.cfg.dataDirPath)
-}
-
-func (ep *etcdServerProcess) WithStopSignal(sig os.Signal) os.Signal {
-	ret := ep.proc.StopSignal
-	ep.proc.StopSignal = sig
-	return ret
-}
-
-func (ep *etcdServerProcess) waitReady() error {
-	defer close(ep.donec)
-	return waitReadyExpectProc(ep.proc, etcdServerReadyLines)
-}
-
-func (ep *etcdServerProcess) Config() *etcdServerProcessConfig { return ep.cfg }

+ 0 - 133
e2e/etcd_spawn_cov.go

@@ -1,133 +0,0 @@
-// Copyright 2017 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.
-
-// +build cov
-
-package e2e
-
-import (
-	"fmt"
-	"os"
-	"path/filepath"
-	"strings"
-	"syscall"
-	"time"
-
-	"github.com/coreos/etcd/pkg/expect"
-	"github.com/coreos/etcd/pkg/fileutil"
-	"github.com/coreos/etcd/pkg/flags"
-)
-
-const noOutputLineCount = 2 // cov-enabled binaries emit PASS and coverage count lines
-
-func spawnCmd(args []string) (*expect.ExpectProcess, error) {
-	if args[0] == binPath {
-		return spawnEtcd(args)
-	}
-	if args[0] == ctlBinPath || args[0] == ctlBinPath+"3" {
-		// avoid test flag conflicts in coverage enabled etcdctl by putting flags in ETCDCTL_ARGS
-		env := []string{
-			// was \xff, but that's used for testing boundary conditions; 0xe7cd should be safe
-			"ETCDCTL_ARGS=" + strings.Join(args, "\xe7\xcd"),
-		}
-		if args[0] == ctlBinPath+"3" {
-			env = append(env, "ETCDCTL_API=3")
-		}
-
-		covArgs, err := getCovArgs()
-		if err != nil {
-			return nil, err
-		}
-		// when withFlagByEnv() is used in testCtl(), env variables for ctl is set to os.env.
-		// they must be included in ctl_cov_env.
-		env = append(env, os.Environ()...)
-		ep, err := expect.NewExpectWithEnv(binDir+"/etcdctl_test", covArgs, env)
-		if err != nil {
-			return nil, err
-		}
-		ep.StopSignal = syscall.SIGTERM
-		return ep, nil
-	}
-
-	return expect.NewExpect(args[0], args[1:]...)
-}
-
-func spawnEtcd(args []string) (*expect.ExpectProcess, error) {
-	covArgs, err := getCovArgs()
-	if err != nil {
-		return nil, err
-	}
-
-	var env []string
-	if args[1] == "grpc-proxy" {
-		// avoid test flag conflicts in coverage enabled etcd by putting flags in ETCDCOV_ARGS
-		env = append(os.Environ(), "ETCDCOV_ARGS="+strings.Join(args, "\xe7\xcd"))
-	} else {
-		env = args2env(args[1:])
-	}
-
-	ep, err := expect.NewExpectWithEnv(binDir+"/etcd_test", covArgs, env)
-	if err != nil {
-		return nil, err
-	}
-	// ep sends SIGTERM to etcd_test process on ep.close()
-	// allowing the process to exit gracefully in order to generate a coverage report.
-	// note: go runtime ignores SIGINT but not SIGTERM
-	// if e2e test is run as a background process.
-	ep.StopSignal = syscall.SIGTERM
-	return ep, nil
-}
-
-func getCovArgs() ([]string, error) {
-	coverPath := os.Getenv("COVERDIR")
-	if !filepath.IsAbs(coverPath) {
-		// COVERDIR is relative to etcd root but e2e test has its path set to be relative to the e2e folder.
-		// adding ".." in front of COVERDIR ensures that e2e saves coverage reports to the correct location.
-		coverPath = filepath.Join("..", coverPath)
-	}
-	if !fileutil.Exist(coverPath) {
-		return nil, fmt.Errorf("could not find coverage folder")
-	}
-	covArgs := []string{
-		fmt.Sprintf("-test.coverprofile=e2e.%v.coverprofile", time.Now().UnixNano()),
-		"-test.outputdir=" + coverPath,
-	}
-	return covArgs, nil
-}
-
-func args2env(args []string) []string {
-	var covEnvs []string
-	for i := range args {
-		if !strings.HasPrefix(args[i], "--") {
-			continue
-		}
-		flag := strings.Split(args[i], "--")[1]
-		val := "true"
-		// split the flag that has "="
-		// e.g --auto-tls=true" => flag=auto-tls and val=true
-		if strings.Contains(args[i], "=") {
-			split := strings.Split(flag, "=")
-			flag = split[0]
-			val = split[1]
-		}
-
-		if i+1 < len(args) {
-			if !strings.HasPrefix(args[i+1], "--") {
-				val = args[i+1]
-			}
-		}
-		covEnvs = append(covEnvs, flags.FlagToEnv("ETCD", flag)+"="+val)
-	}
-	return covEnvs
-}

+ 0 - 33
e2e/etcd_spawn_nocov.go

@@ -1,33 +0,0 @@
-// Copyright 2017 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.
-
-// +build !cov
-
-package e2e
-
-import (
-	"os"
-
-	"github.com/coreos/etcd/pkg/expect"
-)
-
-const noOutputLineCount = 0 // regular binaries emit no extra lines
-
-func spawnCmd(args []string) (*expect.ExpectProcess, error) {
-	if args[0] == ctlBinPath+"3" {
-		env := append(os.Environ(), "ETCDCTL_API=3")
-		return expect.NewExpectWithEnv(ctlBinPath, args[1:], env)
-	}
-	return expect.NewExpect(args[0], args[1:]...)
-}

+ 0 - 60
e2e/gateway_test.go

@@ -1,60 +0,0 @@
-// Copyright 2016 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 e2e
-
-import (
-	"os"
-	"strings"
-	"testing"
-
-	"github.com/coreos/etcd/pkg/expect"
-)
-
-var (
-	defaultGatewayEndpoint = "127.0.0.1:23790"
-)
-
-func TestGateway(t *testing.T) {
-	ec, err := newEtcdProcessCluster(&configNoTLS)
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer ec.Stop()
-
-	eps := strings.Join(ec.EndpointsV3(), ",")
-
-	p := startGateway(t, eps)
-	defer p.Stop()
-
-	os.Setenv("ETCDCTL_API", "3")
-	defer os.Unsetenv("ETCDCTL_API")
-
-	err = spawnWithExpect([]string{ctlBinPath, "--endpoints=" + defaultGatewayEndpoint, "put", "foo", "bar"}, "OK\r\n")
-	if err != nil {
-		t.Errorf("failed to finish put request through gateway: %v", err)
-	}
-}
-
-func startGateway(t *testing.T, endpoints string) *expect.ExpectProcess {
-	p, err := expect.NewExpect(binPath, "gateway", "--endpoints="+endpoints, "start")
-	if err != nil {
-		t.Fatal(err)
-	}
-	_, err = p.Expect("tcpproxy: ready to proxy client requests to")
-	if err != nil {
-		t.Fatal(err)
-	}
-	return p
-}

+ 0 - 57
e2e/main_test.go

@@ -1,57 +0,0 @@
-// 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 e2e
-
-import (
-	"flag"
-	"os"
-	"runtime"
-	"testing"
-
-	"github.com/coreos/etcd/pkg/testutil"
-)
-
-var (
-	binDir  string
-	certDir string
-
-	certPath       string
-	privateKeyPath string
-	caPath         string
-
-	certPath2       string
-	privateKeyPath2 string
-
-	crlPath               string
-	revokedCertPath       string
-	revokedPrivateKeyPath string
-)
-
-func TestMain(m *testing.M) {
-	os.Setenv("ETCD_UNSUPPORTED_ARCH", runtime.GOARCH)
-	os.Unsetenv("ETCDCTL_API")
-
-	flag.StringVar(&binDir, "bin-dir", "../bin", "The directory for store etcd and etcdctl binaries.")
-	flag.StringVar(&certDir, "cert-dir", "../integration/fixtures", "The directory for store certificate files.")
-	flag.Parse()
-
-	binPath = binDir + "/etcd"
-	ctlBinPath = binDir + "/etcdctl"
-	certPath = certDir + "/server.crt"
-	privateKeyPath = certDir + "/server.key.insecure"
-	caPath = certDir + "/ca.crt"
-	revokedCertPath = certDir + "/server-revoked.crt"
-	revokedPrivateKeyPath = certDir + "/server-revoked.key.insecure"
-	crlPath = certDir + "/revoke.crl"
-
-	certPath2 = certDir + "/server2.crt"
-	privateKeyPath2 = certDir + "/server2.key.insecure"
-
-	v := m.Run()
-	if v == 0 && testutil.CheckLeakedGoroutine() {
-		os.Exit(1)
-	}
-	os.Exit(v)
-}

+ 0 - 51
e2e/metrics_test.go

@@ -1,51 +0,0 @@
-// Copyright 2017 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 e2e
-
-import (
-	"fmt"
-	"testing"
-
-	"github.com/coreos/etcd/version"
-)
-
-func TestV3MetricsSecure(t *testing.T) {
-	cfg := configTLS
-	cfg.clusterSize = 1
-	cfg.metricsURLScheme = "https"
-	testCtl(t, metricsTest)
-}
-
-func TestV3MetricsInsecure(t *testing.T) {
-	cfg := configTLS
-	cfg.clusterSize = 1
-	cfg.metricsURLScheme = "http"
-	testCtl(t, metricsTest)
-}
-
-func metricsTest(cx ctlCtx) {
-	if err := ctlV3Put(cx, "k", "v", ""); err != nil {
-		cx.t.Fatal(err)
-	}
-	if err := cURLGet(cx.epc, cURLReq{endpoint: "/metrics", expected: `etcd_debugging_mvcc_keys_total 1`, metricsURLScheme: cx.cfg.metricsURLScheme}); err != nil {
-		cx.t.Fatalf("failed get with curl (%v)", err)
-	}
-	if err := cURLGet(cx.epc, cURLReq{endpoint: "/metrics", expected: fmt.Sprintf(`etcd_server_version{server_version="%s"} 1`, version.Version), metricsURLScheme: cx.cfg.metricsURLScheme}); err != nil {
-		cx.t.Fatalf("failed get with curl (%v)", err)
-	}
-	if err := cURLGet(cx.epc, cURLReq{endpoint: "/health", expected: `{"health":"true"}`, metricsURLScheme: cx.cfg.metricsURLScheme}); err != nil {
-		cx.t.Fatalf("failed get with curl (%v)", err)
-	}
-}

+ 0 - 96
e2e/util.go

@@ -1,96 +0,0 @@
-// Copyright 2017 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 e2e
-
-import (
-	"fmt"
-	"strings"
-	"time"
-
-	"github.com/coreos/etcd/pkg/expect"
-)
-
-func waitReadyExpectProc(exproc *expect.ExpectProcess, readyStrs []string) error {
-	c := 0
-	matchSet := func(l string) bool {
-		for _, s := range readyStrs {
-			if strings.Contains(l, s) {
-				c++
-				break
-			}
-		}
-		return c == len(readyStrs)
-	}
-	_, err := exproc.ExpectFunc(matchSet)
-	return err
-}
-
-func spawnWithExpect(args []string, expected string) error {
-	return spawnWithExpects(args, []string{expected}...)
-}
-
-func spawnWithExpects(args []string, xs ...string) error {
-	_, err := spawnWithExpectLines(args, xs...)
-	return err
-}
-
-func spawnWithExpectLines(args []string, xs ...string) ([]string, error) {
-	proc, err := spawnCmd(args)
-	if err != nil {
-		return nil, err
-	}
-	// process until either stdout or stderr contains
-	// the expected string
-	var (
-		lines    []string
-		lineFunc = func(txt string) bool { return true }
-	)
-	for _, txt := range xs {
-		for {
-			l, lerr := proc.ExpectFunc(lineFunc)
-			if lerr != nil {
-				proc.Close()
-				return nil, fmt.Errorf("%v (expected %q, got %q)", lerr, txt, lines)
-			}
-			lines = append(lines, l)
-			if strings.Contains(l, txt) {
-				break
-			}
-		}
-	}
-	perr := proc.Close()
-	if len(xs) == 0 && proc.LineCount() != noOutputLineCount { // expect no output
-		return nil, fmt.Errorf("unexpected output (got lines %q, line count %d)", lines, proc.LineCount())
-	}
-	return lines, perr
-}
-
-func closeWithTimeout(p *expect.ExpectProcess, d time.Duration) error {
-	errc := make(chan error, 1)
-	go func() { errc <- p.Close() }()
-	select {
-	case err := <-errc:
-		return err
-	case <-time.After(d):
-		p.Stop()
-		// retry close after stopping to collect SIGQUIT data, if any
-		closeWithTimeout(p, time.Second)
-	}
-	return fmt.Errorf("took longer than %v to Close process %+v", d, p)
-}
-
-func toTLS(s string) string {
-	return strings.Replace(s, "http://", "https://", 1)
-}

+ 0 - 195
e2e/v2_curl_test.go

@@ -1,195 +0,0 @@
-// Copyright 2016 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 e2e
-
-import (
-	"fmt"
-	"math/rand"
-	"strings"
-	"testing"
-
-	"github.com/coreos/etcd/pkg/testutil"
-)
-
-func TestV2CurlNoTLS(t *testing.T)      { testCurlPutGet(t, &configNoTLS) }
-func TestV2CurlAutoTLS(t *testing.T)    { testCurlPutGet(t, &configAutoTLS) }
-func TestV2CurlAllTLS(t *testing.T)     { testCurlPutGet(t, &configTLS) }
-func TestV2CurlPeerTLS(t *testing.T)    { testCurlPutGet(t, &configPeerTLS) }
-func TestV2CurlClientTLS(t *testing.T)  { testCurlPutGet(t, &configClientTLS) }
-func TestV2CurlClientBoth(t *testing.T) { testCurlPutGet(t, &configClientBoth) }
-func testCurlPutGet(t *testing.T, cfg *etcdProcessClusterConfig) {
-	defer testutil.AfterTest(t)
-
-	// test doesn't use quorum gets, so ensure there are no followers to avoid
-	// stale reads that will break the test
-	cfg = configStandalone(*cfg)
-
-	epc, err := newEtcdProcessCluster(cfg)
-	if err != nil {
-		t.Fatalf("could not start etcd process cluster (%v)", err)
-	}
-	defer func() {
-		if err := epc.Close(); err != nil {
-			t.Fatalf("error closing etcd processes (%v)", err)
-		}
-	}()
-
-	var (
-		expectPut = `{"action":"set","node":{"key":"/foo","value":"bar","`
-		expectGet = `{"action":"get","node":{"key":"/foo","value":"bar","`
-	)
-	if err := cURLPut(epc, cURLReq{endpoint: "/v2/keys/foo", value: "bar", expected: expectPut}); err != nil {
-		t.Fatalf("failed put with curl (%v)", err)
-	}
-	if err := cURLGet(epc, cURLReq{endpoint: "/v2/keys/foo", expected: expectGet}); err != nil {
-		t.Fatalf("failed get with curl (%v)", err)
-	}
-	if cfg.clientTLS == clientTLSAndNonTLS {
-		if err := cURLGet(epc, cURLReq{endpoint: "/v2/keys/foo", expected: expectGet, isTLS: true}); err != nil {
-			t.Fatalf("failed get with curl (%v)", err)
-		}
-	}
-}
-
-func TestV2CurlIssue5182(t *testing.T) {
-	defer testutil.AfterTest(t)
-
-	epc := setupEtcdctlTest(t, &configNoTLS, false)
-	defer func() {
-		if err := epc.Close(); err != nil {
-			t.Fatalf("error closing etcd processes (%v)", err)
-		}
-	}()
-
-	expectPut := `{"action":"set","node":{"key":"/foo","value":"bar","`
-	if err := cURLPut(epc, cURLReq{endpoint: "/v2/keys/foo", value: "bar", expected: expectPut}); err != nil {
-		t.Fatal(err)
-	}
-
-	expectUserAdd := `{"user":"foo","roles":null}`
-	if err := cURLPut(epc, cURLReq{endpoint: "/v2/auth/users/foo", value: `{"user":"foo", "password":"pass"}`, expected: expectUserAdd}); err != nil {
-		t.Fatal(err)
-	}
-	expectRoleAdd := `{"role":"foo","permissions":{"kv":{"read":["/foo/*"],"write":null}}`
-	if err := cURLPut(epc, cURLReq{endpoint: "/v2/auth/roles/foo", value: `{"role":"foo", "permissions": {"kv": {"read": ["/foo/*"]}}}`, expected: expectRoleAdd}); err != nil {
-		t.Fatal(err)
-	}
-	expectUserUpdate := `{"user":"foo","roles":["foo"]}`
-	if err := cURLPut(epc, cURLReq{endpoint: "/v2/auth/users/foo", value: `{"user": "foo", "grant": ["foo"]}`, expected: expectUserUpdate}); err != nil {
-		t.Fatal(err)
-	}
-
-	if err := etcdctlUserAdd(epc, "root", "a"); err != nil {
-		t.Fatal(err)
-	}
-	if err := etcdctlAuthEnable(epc); err != nil {
-		t.Fatal(err)
-	}
-
-	if err := cURLGet(epc, cURLReq{endpoint: "/v2/keys/foo/", username: "root", password: "a", expected: "bar"}); err != nil {
-		t.Fatal(err)
-	}
-	if err := cURLGet(epc, cURLReq{endpoint: "/v2/keys/foo/", username: "foo", password: "pass", expected: "bar"}); err != nil {
-		t.Fatal(err)
-	}
-	if err := cURLGet(epc, cURLReq{endpoint: "/v2/keys/foo/", username: "foo", password: "", expected: "bar"}); err != nil {
-		if !strings.Contains(err.Error(), `The request requires user authentication`) {
-			t.Fatalf("expected 'The request requires user authentication' error, got %v", err)
-		}
-	} else {
-		t.Fatalf("expected 'The request requires user authentication' error")
-	}
-}
-
-type cURLReq struct {
-	username string
-	password string
-
-	isTLS   bool
-	timeout int
-
-	endpoint string
-
-	value    string
-	expected string
-	header   string
-
-	metricsURLScheme string
-
-	ciphers string
-}
-
-// cURLPrefixArgs builds the beginning of a curl command for a given key
-// addressed to a random URL in the given cluster.
-func cURLPrefixArgs(clus *etcdProcessCluster, method string, req cURLReq) []string {
-	var (
-		cmdArgs = []string{"curl"}
-		acurl   = clus.procs[rand.Intn(clus.cfg.clusterSize)].Config().acurl
-	)
-	if req.metricsURLScheme != "https" {
-		if req.isTLS {
-			if clus.cfg.clientTLS != clientTLSAndNonTLS {
-				panic("should not use cURLPrefixArgsUseTLS when serving only TLS or non-TLS")
-			}
-			cmdArgs = append(cmdArgs, "--cacert", caPath, "--cert", certPath, "--key", privateKeyPath)
-			acurl = toTLS(clus.procs[rand.Intn(clus.cfg.clusterSize)].Config().acurl)
-		} else if clus.cfg.clientTLS == clientTLS {
-			cmdArgs = append(cmdArgs, "--cacert", caPath, "--cert", certPath, "--key", privateKeyPath)
-		}
-	}
-	if req.metricsURLScheme != "" {
-		acurl = clus.procs[rand.Intn(clus.cfg.clusterSize)].EndpointsMetrics()[0]
-	}
-	ep := acurl + req.endpoint
-
-	if req.username != "" || req.password != "" {
-		cmdArgs = append(cmdArgs, "-L", "-u", fmt.Sprintf("%s:%s", req.username, req.password), ep)
-	} else {
-		cmdArgs = append(cmdArgs, "-L", ep)
-	}
-	if req.timeout != 0 {
-		cmdArgs = append(cmdArgs, "-m", fmt.Sprintf("%d", req.timeout))
-	}
-
-	if req.header != "" {
-		cmdArgs = append(cmdArgs, "-H", req.header)
-	}
-
-	if req.ciphers != "" {
-		cmdArgs = append(cmdArgs, "--ciphers", req.ciphers)
-	}
-
-	switch method {
-	case "POST", "PUT":
-		dt := req.value
-		if !strings.HasPrefix(dt, "{") { // for non-JSON value
-			dt = "value=" + dt
-		}
-		cmdArgs = append(cmdArgs, "-X", method, "-d", dt)
-	}
-	return cmdArgs
-}
-
-func cURLPost(clus *etcdProcessCluster, req cURLReq) error {
-	return spawnWithExpect(cURLPrefixArgs(clus, "POST", req), req.expected)
-}
-
-func cURLPut(clus *etcdProcessCluster, req cURLReq) error {
-	return spawnWithExpect(cURLPrefixArgs(clus, "PUT", req), req.expected)
-}
-
-func cURLGet(clus *etcdProcessCluster, req cURLReq) error {
-	return spawnWithExpect(cURLPrefixArgs(clus, "GET", req), req.expected)
-}

+ 0 - 19
e2e/v2_test.go

@@ -1,19 +0,0 @@
-// Copyright 2017 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.
-
-// +build !v2v3
-
-package e2e
-
-func addV2Args(args []string) []string { return args }

+ 0 - 21
e2e/v2v3_test.go

@@ -1,21 +0,0 @@
-// Copyright 2017 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.
-
-// +build v2v3
-
-package e2e
-
-func addV2Args(args []string) []string {
-	return append(args, "--experimental-enable-v2v3", "v2/")
-}

+ 0 - 436
e2e/v3_curl_test.go

@@ -1,436 +0,0 @@
-// Copyright 2016 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 e2e
-
-import (
-	"encoding/base64"
-	"encoding/json"
-	"fmt"
-	"path"
-	"strconv"
-	"testing"
-
-	epb "github.com/coreos/etcd/etcdserver/api/v3election/v3electionpb"
-	pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
-	"github.com/coreos/etcd/pkg/testutil"
-	"github.com/coreos/etcd/version"
-
-	"github.com/grpc-ecosystem/grpc-gateway/runtime"
-)
-
-// TODO: remove /v3alpha tests in 3.4 release
-
-func TestV3CurlPutGetNoTLSAlpha(t *testing.T) { testCurlPutGetGRPCGateway(t, &configNoTLS, "/v3alpha") }
-func TestV3CurlPutGetNoTLSBeta(t *testing.T)  { testCurlPutGetGRPCGateway(t, &configNoTLS, "/v3beta") }
-func TestV3CurlPutGetAutoTLSAlpha(t *testing.T) {
-	testCurlPutGetGRPCGateway(t, &configAutoTLS, "/v3alpha")
-}
-func TestV3CurlPutGetAutoTLSBeta(t *testing.T) {
-	testCurlPutGetGRPCGateway(t, &configAutoTLS, "/v3beta")
-}
-func TestV3CurlPutGetAllTLSAlpha(t *testing.T) { testCurlPutGetGRPCGateway(t, &configTLS, "/v3alpha") }
-func TestV3CurlPutGetAllTLSBeta(t *testing.T)  { testCurlPutGetGRPCGateway(t, &configTLS, "/v3beta") }
-func TestV3CurlPutGetPeerTLSAlpha(t *testing.T) {
-	testCurlPutGetGRPCGateway(t, &configPeerTLS, "/v3alpha")
-}
-func TestV3CurlPutGetPeerTLSBeta(t *testing.T) {
-	testCurlPutGetGRPCGateway(t, &configPeerTLS, "/v3beta")
-}
-func TestV3CurlPutGetClientTLSAlpha(t *testing.T) {
-	testCurlPutGetGRPCGateway(t, &configClientTLS, "/v3alpha")
-}
-func TestV3CurlPutGetClientTLSBeta(t *testing.T) {
-	testCurlPutGetGRPCGateway(t, &configClientTLS, "/v3beta")
-}
-func testCurlPutGetGRPCGateway(t *testing.T, cfg *etcdProcessClusterConfig, pathPrefix string) {
-	defer testutil.AfterTest(t)
-
-	epc, err := newEtcdProcessCluster(cfg)
-	if err != nil {
-		t.Fatalf("could not start etcd process cluster (%v)", err)
-	}
-	defer func() {
-		if cerr := epc.Close(); err != nil {
-			t.Fatalf("error closing etcd processes (%v)", cerr)
-		}
-	}()
-
-	var (
-		key   = []byte("foo")
-		value = []byte("bar") // this will be automatically base64-encoded by Go
-
-		expectPut = `"revision":"`
-		expectGet = `"value":"`
-	)
-	putData, err := json.Marshal(&pb.PutRequest{
-		Key:   key,
-		Value: value,
-	})
-	if err != nil {
-		t.Fatal(err)
-	}
-	rangeData, err := json.Marshal(&pb.RangeRequest{
-		Key: key,
-	})
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	if err := cURLPost(epc, cURLReq{endpoint: path.Join(pathPrefix, "/kv/put"), value: string(putData), expected: expectPut}); err != nil {
-		t.Fatalf("failed put with curl (%v)", err)
-	}
-	if err := cURLPost(epc, cURLReq{endpoint: path.Join(pathPrefix, "/kv/range"), value: string(rangeData), expected: expectGet}); err != nil {
-		t.Fatalf("failed get with curl (%v)", err)
-	}
-
-	if cfg.clientTLS == clientTLSAndNonTLS {
-		if err := cURLPost(epc, cURLReq{endpoint: path.Join(pathPrefix, "/kv/range"), value: string(rangeData), expected: expectGet, isTLS: true}); err != nil {
-			t.Fatalf("failed get with curl (%v)", err)
-		}
-	}
-}
-
-func TestV3CurlWatchAlpha(t *testing.T) { testV3CurlWatch(t, "/v3alpha") }
-func TestV3CurlWatchBeta(t *testing.T)  { testV3CurlWatch(t, "/v3beta") }
-func testV3CurlWatch(t *testing.T, pathPrefix string) {
-	defer testutil.AfterTest(t)
-
-	epc, err := newEtcdProcessCluster(&configNoTLS)
-	if err != nil {
-		t.Fatalf("could not start etcd process cluster (%v)", err)
-	}
-	defer func() {
-		if cerr := epc.Close(); err != nil {
-			t.Fatalf("error closing etcd processes (%v)", cerr)
-		}
-	}()
-
-	// store "bar" into "foo"
-	putreq, err := json.Marshal(&pb.PutRequest{Key: []byte("foo"), Value: []byte("bar")})
-	if err != nil {
-		t.Fatal(err)
-	}
-	if err = cURLPost(epc, cURLReq{endpoint: path.Join(pathPrefix, "/kv/put"), value: string(putreq), expected: "revision"}); err != nil {
-		t.Fatalf("failed put with curl (%v)", err)
-	}
-	// watch for first update to "foo"
-	wcr := &pb.WatchCreateRequest{Key: []byte("foo"), StartRevision: 1}
-	wreq, err := json.Marshal(wcr)
-	if err != nil {
-		t.Fatal(err)
-	}
-	// marshaling the grpc to json gives:
-	// "{"RequestUnion":{"CreateRequest":{"key":"Zm9v","start_revision":1}}}"
-	// but the gprc-gateway expects a different format..
-	wstr := `{"create_request" : ` + string(wreq) + "}"
-	// expects "bar", timeout after 2 seconds since stream waits forever
-	if err = cURLPost(epc, cURLReq{endpoint: path.Join(pathPrefix, "/watch"), value: wstr, expected: `"YmFy"`, timeout: 2}); err != nil {
-		t.Fatal(err)
-	}
-}
-
-func TestV3CurlTxnAlpha(t *testing.T) { testV3CurlTxn(t, "/v3alpha") }
-func TestV3CurlTxnBeta(t *testing.T)  { testV3CurlTxn(t, "/v3beta") }
-func testV3CurlTxn(t *testing.T, pathPrefix string) {
-	defer testutil.AfterTest(t)
-	epc, err := newEtcdProcessCluster(&configNoTLS)
-	if err != nil {
-		t.Fatalf("could not start etcd process cluster (%v)", err)
-	}
-	defer func() {
-		if cerr := epc.Close(); err != nil {
-			t.Fatalf("error closing etcd processes (%v)", cerr)
-		}
-	}()
-
-	txn := &pb.TxnRequest{
-		Compare: []*pb.Compare{
-			{
-				Key:         []byte("foo"),
-				Result:      pb.Compare_EQUAL,
-				Target:      pb.Compare_CREATE,
-				TargetUnion: &pb.Compare_CreateRevision{0},
-			},
-		},
-		Success: []*pb.RequestOp{
-			{
-				Request: &pb.RequestOp_RequestPut{
-					RequestPut: &pb.PutRequest{
-						Key:   []byte("foo"),
-						Value: []byte("bar"),
-					},
-				},
-			},
-		},
-	}
-	m := &runtime.JSONPb{}
-	jsonDat, jerr := m.Marshal(txn)
-	if jerr != nil {
-		t.Fatal(jerr)
-	}
-	expected := `"succeeded":true,"responses":[{"response_put":{"header":{"revision":"2"}}}]`
-	if err = cURLPost(epc, cURLReq{endpoint: path.Join(pathPrefix, "/kv/txn"), value: string(jsonDat), expected: expected}); err != nil {
-		t.Fatalf("failed txn with curl (%v)", err)
-	}
-
-	// was crashing etcd server
-	malformed := `{"compare":[{"result":0,"target":1,"key":"Zm9v","TargetUnion":null}],"success":[{"Request":{"RequestPut":{"key":"Zm9v","value":"YmFy"}}}]}`
-	if err = cURLPost(epc, cURLReq{endpoint: path.Join(pathPrefix, "/kv/txn"), value: malformed, expected: "error"}); err != nil {
-		t.Fatalf("failed put with curl (%v)", err)
-	}
-}
-
-func TestV3CurlAuthAlpha(t *testing.T) { testV3CurlAuth(t, "/v3alpha") }
-func TestV3CurlAuthBeta(t *testing.T)  { testV3CurlAuth(t, "/v3beta") }
-func testV3CurlAuth(t *testing.T, pathPrefix string) {
-	defer testutil.AfterTest(t)
-	epc, err := newEtcdProcessCluster(&configNoTLS)
-	if err != nil {
-		t.Fatalf("could not start etcd process cluster (%v)", err)
-	}
-	defer func() {
-		if cerr := epc.Close(); err != nil {
-			t.Fatalf("error closing etcd processes (%v)", cerr)
-		}
-	}()
-
-	// create root user
-	userreq, err := json.Marshal(&pb.AuthUserAddRequest{Name: string("root"), Password: string("toor")})
-	testutil.AssertNil(t, err)
-
-	if err = cURLPost(epc, cURLReq{endpoint: path.Join(pathPrefix, "/auth/user/add"), value: string(userreq), expected: "revision"}); err != nil {
-		t.Fatalf("failed add user with curl (%v)", err)
-	}
-
-	// create root role
-	rolereq, err := json.Marshal(&pb.AuthRoleAddRequest{Name: string("root")})
-	testutil.AssertNil(t, err)
-
-	if err = cURLPost(epc, cURLReq{endpoint: path.Join(pathPrefix, "/auth/role/add"), value: string(rolereq), expected: "revision"}); err != nil {
-		t.Fatalf("failed create role with curl (%v)", err)
-	}
-
-	// grant root role
-	grantrolereq, err := json.Marshal(&pb.AuthUserGrantRoleRequest{User: string("root"), Role: string("root")})
-	testutil.AssertNil(t, err)
-
-	if err = cURLPost(epc, cURLReq{endpoint: path.Join(pathPrefix, "/auth/user/grant"), value: string(grantrolereq), expected: "revision"}); err != nil {
-		t.Fatalf("failed grant role with curl (%v)", err)
-	}
-
-	// enable auth
-	if err = cURLPost(epc, cURLReq{endpoint: path.Join(pathPrefix, "/auth/enable"), value: string("{}"), expected: "revision"}); err != nil {
-		t.Fatalf("failed enable auth with curl (%v)", err)
-	}
-
-	// put "bar" into "foo"
-	putreq, err := json.Marshal(&pb.PutRequest{Key: []byte("foo"), Value: []byte("bar")})
-	testutil.AssertNil(t, err)
-
-	// fail put no auth
-	if err = cURLPost(epc, cURLReq{endpoint: path.Join(pathPrefix, "/kv/put"), value: string(putreq), expected: "error"}); err != nil {
-		t.Fatalf("failed no auth put with curl (%v)", err)
-	}
-
-	// auth request
-	authreq, err := json.Marshal(&pb.AuthenticateRequest{Name: string("root"), Password: string("toor")})
-	testutil.AssertNil(t, err)
-
-	var (
-		authHeader string
-		cmdArgs    []string
-		lineFunc   = func(txt string) bool { return true }
-	)
-
-	cmdArgs = cURLPrefixArgs(epc, "POST", cURLReq{endpoint: path.Join(pathPrefix, "/auth/authenticate"), value: string(authreq)})
-	proc, err := spawnCmd(cmdArgs)
-	testutil.AssertNil(t, err)
-
-	cURLRes, err := proc.ExpectFunc(lineFunc)
-	testutil.AssertNil(t, err)
-
-	authRes := make(map[string]interface{})
-	testutil.AssertNil(t, json.Unmarshal([]byte(cURLRes), &authRes))
-
-	token, ok := authRes["token"].(string)
-	if !ok {
-		t.Fatalf("failed invalid token in authenticate response with curl")
-	}
-
-	authHeader = "Authorization : " + token
-
-	// put with auth
-	if err = cURLPost(epc, cURLReq{endpoint: path.Join(pathPrefix, "/kv/put"), value: string(putreq), header: authHeader, expected: "revision"}); err != nil {
-		t.Fatalf("failed auth put with curl (%v)", err)
-	}
-}
-
-func TestV3CurlCampaignAlpha(t *testing.T) { testV3CurlCampaign(t, "/v3alpha") }
-func TestV3CurlCampaignBeta(t *testing.T)  { testV3CurlCampaign(t, "/v3beta") }
-func testV3CurlCampaign(t *testing.T, pathPrefix string) {
-	defer testutil.AfterTest(t)
-
-	epc, err := newEtcdProcessCluster(&configNoTLS)
-	if err != nil {
-		t.Fatalf("could not start etcd process cluster (%v)", err)
-	}
-	defer func() {
-		if cerr := epc.Close(); err != nil {
-			t.Fatalf("error closing etcd processes (%v)", cerr)
-		}
-	}()
-
-	cdata, err := json.Marshal(&epb.CampaignRequest{
-		Name:  []byte("/election-prefix"),
-		Value: []byte("v1"),
-	})
-	if err != nil {
-		t.Fatal(err)
-	}
-	cargs := cURLPrefixArgs(epc, "POST", cURLReq{
-		endpoint: path.Join(pathPrefix, "/election/campaign"),
-		value:    string(cdata),
-	})
-	lines, err := spawnWithExpectLines(cargs, `"leader":{"name":"`)
-	if err != nil {
-		t.Fatalf("failed post campaign request (%s) (%v)", pathPrefix, err)
-	}
-	if len(lines) != 1 {
-		t.Fatalf("len(lines) expected 1, got %+v", lines)
-	}
-
-	var cresp campaignResponse
-	if err = json.Unmarshal([]byte(lines[0]), &cresp); err != nil {
-		t.Fatalf("failed to unmarshal campaign response %v", err)
-	}
-	ndata, err := base64.StdEncoding.DecodeString(cresp.Leader.Name)
-	if err != nil {
-		t.Fatalf("failed to decode leader key %v", err)
-	}
-	kdata, err := base64.StdEncoding.DecodeString(cresp.Leader.Key)
-	if err != nil {
-		t.Fatalf("failed to decode leader key %v", err)
-	}
-
-	rev, _ := strconv.ParseInt(cresp.Leader.Rev, 10, 64)
-	lease, _ := strconv.ParseInt(cresp.Leader.Lease, 10, 64)
-	pdata, err := json.Marshal(&epb.ProclaimRequest{
-		Leader: &epb.LeaderKey{
-			Name:  ndata,
-			Key:   kdata,
-			Rev:   rev,
-			Lease: lease,
-		},
-		Value: []byte("v2"),
-	})
-	if err != nil {
-		t.Fatal(err)
-	}
-	if err = cURLPost(epc, cURLReq{
-		endpoint: path.Join(pathPrefix, "/election/proclaim"),
-		value:    string(pdata),
-		expected: `"revision":`,
-	}); err != nil {
-		t.Fatalf("failed post proclaim request (%s) (%v)", pathPrefix, err)
-	}
-}
-
-func TestV3CurlProclaimMissiongLeaderKeyNoTLS(t *testing.T) {
-	testCtl(t, testV3CurlProclaimMissiongLeaderKey, withCfg(configNoTLS))
-}
-
-func testV3CurlProclaimMissiongLeaderKey(cx ctlCtx) {
-	pdata, err := json.Marshal(&epb.ProclaimRequest{Value: []byte("v2")})
-	if err != nil {
-		cx.t.Fatal(err)
-	}
-	if err != nil {
-		cx.t.Fatal(err)
-	}
-	if err = cURLPost(cx.epc, cURLReq{
-		endpoint: path.Join("/v3beta", "/election/proclaim"),
-		value:    string(pdata),
-		expected: `{"error":"\"leader\" field must be provided","code":2}`,
-	}); err != nil {
-		cx.t.Fatalf("failed post proclaim request (%s) (%v)", "/v3beta", err)
-	}
-}
-
-func TestV3CurlResignMissiongLeaderKeyNoTLS(t *testing.T) {
-	testCtl(t, testV3CurlResignMissiongLeaderKey, withCfg(configNoTLS))
-}
-
-func testV3CurlResignMissiongLeaderKey(cx ctlCtx) {
-	if err := cURLPost(cx.epc, cURLReq{
-		endpoint: path.Join("/v3beta", "/election/resign"),
-		value:    `{}`,
-		expected: `{"error":"\"leader\" field must be provided","code":2}`,
-	}); err != nil {
-		cx.t.Fatalf("failed post resign request (%s) (%v)", "/v3beta", err)
-	}
-}
-
-// to manually decode; JSON marshals integer fields with
-// string types, so can't unmarshal with epb.CampaignResponse
-type campaignResponse struct {
-	Leader struct {
-		Name  string `json:"name,omitempty"`
-		Key   string `json:"key,omitempty"`
-		Rev   string `json:"rev,omitempty"`
-		Lease string `json:"lease,omitempty"`
-	} `json:"leader,omitempty"`
-}
-
-func TestV3CurlCipherSuitesValid(t *testing.T)    { testV3CurlCipherSuites(t, true) }
-func TestV3CurlCipherSuitesMismatch(t *testing.T) { testV3CurlCipherSuites(t, false) }
-func testV3CurlCipherSuites(t *testing.T, valid bool) {
-	cc := configClientTLS
-	cc.clusterSize = 1
-	cc.cipherSuites = []string{
-		"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
-		"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
-		"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
-		"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
-		"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
-		"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
-	}
-	testFunc := cipherSuiteTestValid
-	if !valid {
-		testFunc = cipherSuiteTestMismatch
-	}
-	testCtl(t, testFunc, withCfg(cc))
-}
-
-func cipherSuiteTestValid(cx ctlCtx) {
-	if err := cURLGet(cx.epc, cURLReq{
-		endpoint:         "/metrics",
-		expected:         fmt.Sprintf(`etcd_server_version{server_version="%s"} 1`, version.Version),
-		metricsURLScheme: cx.cfg.metricsURLScheme,
-		ciphers:          "ECDHE-RSA-AES128-GCM-SHA256", // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
-	}); err != nil {
-		cx.t.Logf("failed get with curl (%v)", err)
-	}
-}
-
-func cipherSuiteTestMismatch(cx ctlCtx) {
-	if err := cURLGet(cx.epc, cURLReq{
-		endpoint:         "/metrics",
-		expected:         "alert handshake failure",
-		metricsURLScheme: cx.cfg.metricsURLScheme,
-		ciphers:          "ECDHE-RSA-DES-CBC3-SHA", // TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
-	}); err != nil {
-		cx.t.Logf("failed get with curl (%v)", err)
-	}
-}

+ 0 - 0
e2e/etcd_release_upgrade_test.go → tests/e2e/etcd_release_upgrade_test.go