Browse Source

Merge pull request #7387 from fanminshi/rework_coverage_ctl

e2e: rework coverage ctl
fanmin shi 8 years ago
parent
commit
d3aebbf0ce

+ 43 - 12
e2e/etcd_spawn_cov.go

@@ -29,20 +29,13 @@ import (
 	"github.com/coreos/etcd/pkg/flags"
 	"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) {
 func spawnCmd(args []string) (*expect.ExpectProcess, error) {
 	if args[0] == binPath {
 	if args[0] == binPath {
-		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,
+		covArgs, err := getCovArgs()
+		if err != nil {
+			return nil, err
 		}
 		}
 		ep, err := expect.NewExpectWithEnv(binDir+"/etcd_test", covArgs, args2env(args[1:]))
 		ep, err := expect.NewExpectWithEnv(binDir+"/etcd_test", covArgs, args2env(args[1:]))
 		if err != nil {
 		if err != nil {
@@ -55,9 +48,47 @@ func spawnCmd(args []string) (*expect.ExpectProcess, error) {
 		ep.StopSignal = syscall.SIGTERM
 		ep.StopSignal = syscall.SIGTERM
 		return ep, nil
 		return ep, nil
 	}
 	}
+
+	if args[0] == ctlBinPath {
+		covArgs, err := getCovArgs()
+		if err != nil {
+			return nil, err
+		}
+		// avoid test flag conflicts in coverage enabled etcdctl by putting flags in ETCDCTL_ARGS
+		ctl_cov_env := []string{
+			"ETCDCTL_ARGS" + "=" + strings.Join(args, "\xff"),
+		}
+		// when withFlagByEnv() is used in testCtl(), env variables for ctl is set to os.env.
+		// they must be included in ctl_cov_env.
+		ctl_cov_env = append(ctl_cov_env, os.Environ()...)
+		ep, err := expect.NewExpectWithEnv(binDir+"/etcdctl_test", covArgs, ctl_cov_env)
+		if err != nil {
+			return nil, err
+		}
+		ep.StopSignal = syscall.SIGTERM
+		return ep, nil
+	}
+
 	return expect.NewExpect(args[0], args[1:]...)
 	return expect.NewExpect(args[0], args[1:]...)
 }
 }
 
 
+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 {
 func args2env(args []string) []string {
 	var covEnvs []string
 	var covEnvs []string
 	for i := range args[1:] {
 	for i := range args[1:] {

+ 2 - 0
e2e/etcd_spawn_nocov.go

@@ -18,6 +18,8 @@ package e2e
 
 
 import "github.com/coreos/etcd/pkg/expect"
 import "github.com/coreos/etcd/pkg/expect"
 
 
+const noOutputLineCount = 0 // regular binaries emit no extra lines
+
 func spawnCmd(args []string) (*expect.ExpectProcess, error) {
 func spawnCmd(args []string) (*expect.ExpectProcess, error) {
 	return expect.NewExpect(args[0], args[1:]...)
 	return expect.NewExpect(args[0], args[1:]...)
 }
 }

+ 1 - 1
e2e/etcd_test.go

@@ -523,7 +523,7 @@ func spawnWithExpects(args []string, xs ...string) error {
 		}
 		}
 	}
 	}
 	perr := proc.Close()
 	perr := proc.Close()
-	if len(xs) == 0 && proc.LineCount() != 0 { // expect no output
+	if len(xs) == 0 && proc.LineCount() != noOutputLineCount { // expect no output
 		return fmt.Errorf("unexpected output (got lines %q, line count %d)", lines, proc.LineCount())
 		return fmt.Errorf("unexpected output (got lines %q, line count %d)", lines, proc.LineCount())
 	}
 	}
 	return perr
 	return perr

+ 1 - 1
etcdctl/ctlv2/ctl.go

@@ -71,7 +71,7 @@ func Start() {
 		command.NewAuthCommands(),
 		command.NewAuthCommands(),
 	}
 	}
 
 
-	err := app.Run(os.Args)
+	err := runCtlV2(app)
 	if err != nil {
 	if err != nil {
 		fmt.Fprintln(os.Stderr, err)
 		fmt.Fprintln(os.Stderr, err)
 		os.Exit(1)
 		os.Exit(1)

+ 28 - 0
etcdctl/ctlv2/ctl_cov.go

@@ -0,0 +1,28 @@
+// 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 ctlv2
+
+import (
+	"os"
+	"strings"
+
+	"github.com/urfave/cli"
+)
+
+func runCtlV2(app *cli.App) error {
+	return app.Run(strings.Split(os.Getenv("ETCDCTL_ARGS"), "\xff"))
+}

+ 27 - 0
etcdctl/ctlv2/ctl_nocov.go

@@ -0,0 +1,27 @@
+// 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 ctlv2
+
+import (
+	"os"
+
+	"github.com/urfave/cli"
+)
+
+func runCtlV2(app *cli.App) error {
+	return app.Run(os.Args)
+}

+ 0 - 11
etcdctl/ctlv3/ctl.go

@@ -86,14 +86,3 @@ func init() {
 func init() {
 func init() {
 	cobra.EnablePrefixMatching = true
 	cobra.EnablePrefixMatching = true
 }
 }
-
-func Start() {
-	rootCmd.SetUsageFunc(usageFunc)
-
-	// Make help just show the usage
-	rootCmd.SetHelpTemplate(`{{.UsageString}}`)
-
-	if err := rootCmd.Execute(); err != nil {
-		command.ExitWithError(command.ExitError, err)
-	}
-}

+ 33 - 0
etcdctl/ctlv3/ctl_cov.go

@@ -0,0 +1,33 @@
+// 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 ctlv3
+
+import (
+	"os"
+	"strings"
+
+	"github.com/coreos/etcd/etcdctl/ctlv3/command"
+)
+
+func Start() {
+	// ETCDCTL_ARGS=etcdctl_test arg1 arg2...
+	// SetArgs() takes arg1 arg2...
+	rootCmd.SetArgs(strings.Split(os.Getenv("ETCDCTL_ARGS"), "\xff")[1:])
+	if err := rootCmd.Execute(); err != nil {
+		command.ExitWithError(command.ExitError, err)
+	}
+}

+ 28 - 0
etcdctl/ctlv3/ctl_nocov.go

@@ -0,0 +1,28 @@
+// 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 ctlv3
+
+import "github.com/coreos/etcd/etcdctl/ctlv3/command"
+
+func Start() {
+	rootCmd.SetUsageFunc(usageFunc)
+	// Make help just show the usage
+	rootCmd.SetHelpTemplate(`{{.UsageString}}`)
+	if err := rootCmd.Execute(); err != nil {
+		command.ExitWithError(command.ExitError, err)
+	}
+}

+ 29 - 0
etcdctl/main_test.go

@@ -0,0 +1,29 @@
+// 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 main
+
+import (
+	"os"
+	"strings"
+	"testing"
+)
+
+func TestMain(t *testing.T) {
+	// don't launch etcdctl when invoked via go test
+	if strings.HasSuffix(os.Args[0], "etcdctl.test") {
+		return
+	}
+	main()
+}

+ 1 - 0
test

@@ -300,6 +300,7 @@ function build_cov_pass {
 	PKGS=$TEST
 	PKGS=$TEST
 	ETCD_PKGS_DELIM=$(echo $PKGS | sed 's/ /,/g')
 	ETCD_PKGS_DELIM=$(echo $PKGS | sed 's/ /,/g')
 	go test -c -covermode=set -coverpkg=$ETCD_PKGS_DELIM -o ${out}/etcd_test
 	go test -c -covermode=set -coverpkg=$ETCD_PKGS_DELIM -o ${out}/etcd_test
+	go test -tags cov -c -covermode=set -coverpkg=$ETCD_PKGS_DELIM -o ${out}/etcdctl_test ${REPO_PATH}/etcdctl/
 }
 }
 
 
 function compile_pass {
 function compile_pass {