Merge pull request #3615 from zmerlynn/random_shuffle_go

cmd/e2e: Port --orderseed and --times to cmd/e2e from hack/e2e
pull/6/head
Alex Robinson 2015-01-20 10:24:50 -08:00
commit 9e3c93a064
2 changed files with 60 additions and 24 deletions

View File

@ -32,6 +32,8 @@ var (
host = flag.String("host", "", "The host to connect to") host = flag.String("host", "", "The host to connect to")
repoRoot = flag.String("repo_root", "./", "Root directory of kubernetes repository, for finding test files. Default assumes working directory is repository root") repoRoot = flag.String("repo_root", "./", "Root directory of kubernetes repository, for finding test files. Default assumes working directory is repository root")
provider = flag.String("provider", "", "The name of the Kubernetes provider") provider = flag.String("provider", "", "The name of the Kubernetes provider")
orderseed = flag.Int64("orderseed", 0, "If non-zero, seed of random test shuffle order. (Otherwise random.)")
times = flag.Int("times", 1, "Number of times each test is eligible to be run. Individual order is determined by shuffling --times instances of each test using --orderseed (like a multi-deck shoe of cards).")
testList util.StringList testList util.StringList
) )
@ -46,5 +48,9 @@ func main() {
glog.Error("e2e needs the have the --provider flag set") glog.Error("e2e needs the have the --provider flag set")
os.Exit(1) os.Exit(1)
} }
e2e.RunE2ETests(*authConfig, *certDir, *host, *repoRoot, *provider, testList) if *times <= 0 {
glog.Error("Invalid --times (negative or no testing requested)!")
os.Exit(1)
}
e2e.RunE2ETests(*authConfig, *certDir, *host, *repoRoot, *provider, *orderseed, *times, testList)
} }

View File

@ -17,6 +17,7 @@ limitations under the License.
package e2e package e2e
import ( import (
"math/rand"
"time" "time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client" "github.com/GoogleCloudPlatform/kubernetes/pkg/client"
@ -29,8 +30,6 @@ type testSpec struct {
test func(c *client.Client) bool test func(c *client.Client) bool
// The human readable name of this test // The human readable name of this test
name string name string
// The id for this test. It should be constant for the life of the test.
id int
} }
type testInfo struct { type testInfo struct {
@ -42,18 +41,26 @@ type testInfo struct {
// See http://testanything.org/ for more info // See http://testanything.org/ for more info
func outputTAPSummary(infoList []testInfo) { func outputTAPSummary(infoList []testInfo) {
glog.Infof("1..%d", len(infoList)) glog.Infof("1..%d", len(infoList))
for _, info := range infoList { for i, info := range infoList {
if info.passed { if info.passed {
glog.Infof("ok %d - %s", info.spec.id, info.spec.name) glog.Infof("ok %d - %s", i+1, info.spec.name)
} else { } else {
glog.Infof("not ok %d - %s", info.spec.id, info.spec.name) glog.Infof("not ok %d - %s", i+1, info.spec.name)
} }
} }
} }
// Fisher-Yates shuffle using the given RNG r
func shuffleTests(tests []testSpec, r *rand.Rand) {
for i := len(tests) - 1; i > 0; i-- {
j := r.Intn(i + 1)
tests[i], tests[j] = tests[j], tests[i]
}
}
// Run each Go end-to-end-test. This function assumes the // Run each Go end-to-end-test. This function assumes the
// creation of a test cluster. // creation of a test cluster.
func RunE2ETests(authConfig, certDir, host, repoRoot, provider string, testList []string) { func RunE2ETests(authConfig, certDir, host, repoRoot, provider string, orderseed int64, times int, testList []string) {
testContext = testContextType{authConfig, certDir, host, repoRoot, provider} testContext = testContextType{authConfig, certDir, host, repoRoot, provider}
util.ReallyCrash = true util.ReallyCrash = true
util.InitLogs() util.InitLogs()
@ -69,23 +76,22 @@ func RunE2ETests(authConfig, certDir, host, repoRoot, provider string, testList
c := loadClientOrDie() c := loadClientOrDie()
tests := []testSpec{ tests := []testSpec{
{TestKubernetesROService, "TestKubernetesROService", 1}, {TestKubernetesROService, "TestKubernetesROService"},
{TestKubeletSendsEvent, "TestKubeletSendsEvent", 2}, {TestKubeletSendsEvent, "TestKubeletSendsEvent"},
{TestImportantURLs, "TestImportantURLs", 3}, {TestImportantURLs, "TestImportantURLs"},
{TestPodUpdate, "TestPodUpdate", 4}, {TestPodUpdate, "TestPodUpdate"},
{TestNetwork, "TestNetwork", 5}, {TestNetwork, "TestNetwork"},
{TestClusterDNS, "TestClusterDNS", 6}, {TestClusterDNS, "TestClusterDNS"},
{TestPodHasServiceEnvVars, "TestPodHasServiceEnvVars", 7}, {TestPodHasServiceEnvVars, "TestPodHasServiceEnvVars"},
{TestBasic, "TestBasic", 8}, {TestBasic, "TestBasic"},
{TestPrivate, "TestPrivate", 9}, {TestPrivate, "TestPrivate"},
} }
// Check testList for non-existent tests and populate a StringSet with tests to run.
validTestNames := util.NewStringSet() validTestNames := util.NewStringSet()
for _, test := range tests { for _, test := range tests {
validTestNames.Insert(test.name) validTestNames.Insert(test.name)
} }
// Check testList for non-existent tests and populate a StringSet with tests to run.
runTestNames := util.NewStringSet() runTestNames := util.NewStringSet()
for _, testName := range testList { for _, testName := range testList {
if validTestNames.Has(testName) { if validTestNames.Has(testName) {
@ -95,15 +101,39 @@ func RunE2ETests(authConfig, certDir, host, repoRoot, provider string, testList
} }
} }
info := []testInfo{} // if testList was specified, filter down now before we expand and shuffle
passed := true if len(testList) > 0 {
newTests := make([]testSpec, 0)
for i, test := range tests { for i, test := range tests {
// Check if this test is supposed to run, either if listed explicitly in // Check if this test is supposed to run, either if listed explicitly in
// a --test flag or if no --test flags were supplied. // a --test flag or if no --test flags were supplied.
if len(testList) > 0 && !runTestNames.Has(test.name) { if !runTestNames.Has(test.name) {
glog.Infof("Skipping test %d %s", i+1, test.name) glog.Infof("Skipping test %d %s", i+1, test.name)
continue continue
} }
newTests = append(newTests, test)
}
tests = newTests
}
if times != 1 {
newTests := make([]testSpec, 0, times*len(tests))
for i := 0; i < times; i++ {
newTests = append(newTests, tests...)
}
tests = newTests
}
if orderseed == 0 {
// Use low order bits of NanoTime as the default seed. (Using
// all the bits makes for a long, very similar looking seed
// between runs.)
orderseed = time.Now().UnixNano() & (1<<32 - 1)
}
shuffleTests(tests, rand.New(rand.NewSource(orderseed)))
glog.Infof("Tests shuffled with orderseed %#x\n", orderseed)
info := []testInfo{}
passed := true
for i, test := range tests {
glog.Infof("Running test %d %s", i+1, test.name) glog.Infof("Running test %d %s", i+1, test.name)
testPassed := test.test(c) testPassed := test.test(c)
if !testPassed { if !testPassed {