Merge pull request #10176 from sharifelgamal/stress

Add go implementation of stress tests
pull/10314/head
Medya Ghazizadeh 2021-01-29 13:32:17 -08:00 committed by GitHub
commit 861d89ce4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 188 additions and 0 deletions

View File

@ -873,6 +873,10 @@ else
go run update_kubernetes_version.go)
endif
.PHONY: stress
stress: ## run the stress tests
go test -test.v -test.timeout=2h ./test/stress -loops=10 | tee "./out/testout_$(COMMIT_SHORT).txt"
.PHONY: update-gopogh-version
update-gopogh-version: ## update gopogh version
(cd hack/update/gopogh_version && \

36
test/stress/main_test.go Normal file
View File

@ -0,0 +1,36 @@
/*
Copyright 2021 The Kubernetes Authors All rights reserved.
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 stress
import (
"flag"
"os"
"strings"
"testing"
)
var startArgs = flag.String("start-args", "", "Arguments to pass to minikube start")
var upgradeFrom = flag.String("upgrade-from", "v1.11.0", "The version of minikube to start with, and upgrade from.")
var loops = flag.Int("loops", 20, "The number of times to run the test")
func TestMain(m *testing.M) {
flag.Parse()
if !strings.HasPrefix(*upgradeFrom, "v") {
*upgradeFrom = "v" + *upgradeFrom
}
os.Exit(m.Run())
}

148
test/stress/stress_test.go Normal file
View File

@ -0,0 +1,148 @@
/*
Copyright 2021 The Kubernetes Authors All rights reserved.
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 stress
import (
"crypto/md5"
"encoding/hex"
"fmt"
"os"
"os/exec"
"runtime"
"testing"
"time"
"github.com/hashicorp/go-getter"
"k8s.io/minikube/pkg/util"
)
const newPath = "../../out/minikube"
const cmdTimeout = int64(90 * 1000)
// TestStress runs the stress test
func TestStress(t *testing.T) {
profile := "stress"
if *startArgs != "" {
h := md5.Sum([]byte(*startArgs))
profile += hex.EncodeToString(h[:])
}
_, err := os.Stat(newPath)
if os.IsNotExist(err) {
t.Fatalf("latest minikube binary is missing, run make")
}
oldPath := fmt.Sprintf("../../out/minikube-%s", *upgradeFrom)
url := util.GetBinaryDownloadURL(*upgradeFrom, runtime.GOOS)
t.Logf("Downloading minikube %s from %s", *upgradeFrom, url)
err = getter.GetFile(oldPath, url)
if err != nil {
t.Fatalf("failed download minikube %s: %v", *upgradeFrom, err)
}
if runtime.GOOS != "windows" {
err := os.Chmod(oldPath, 0755)
if err != nil {
t.Fatalf("Failed to chmod old binary: %v", err)
}
}
defer Cleanup(t, oldPath, profile)
for i := 1; i <= *loops; i++ {
t.Logf("Loop %d of %d: %s to HEAD", i, *loops, *upgradeFrom)
runStress(t, oldPath, profile, i)
t.Logf("Loop %d of %d done.", i, *loops)
}
}
type stressFunc func(*testing.T, string, string, int)
// This run the guts of the actual test
func runStress(t *testing.T, oldPath string, profile string, loop int) {
// Cleanup old runs
runCommand(t, false, newPath, "delete", "-p", profile)
t.Run("stress", func(t *testing.T) {
tests := []struct {
name string
validator stressFunc
}{
{"HotOldToNewUpgrade", validateHotOldToNewUpgrade},
{"ColdOldToNewUpgrade", validateColdOldToNewUpgrade},
{"HotHeadRestart", validateHotHeadRestart},
{"ColdHeadRestart", validateColdHeadRestart},
}
for _, tc := range tests {
tc := tc
t.Run(tc.name, func(t *testing.T) {
tc.validator(t, oldPath, profile, loop)
})
}
})
}
func validateHotOldToNewUpgrade(t *testing.T, oldPath string, profile string, i int) {
t.Logf("Hot upgrade from %s to HEAD", *upgradeFrom)
runCommand(t, true, oldPath, "start", "-p", profile, *startArgs, "--alsologtostderr")
runCommand(t, true, newPath, "start", "-p", profile, *startArgs, "--alsologtostderr")
runCommand(t, false, newPath, "delete", "-p", profile)
}
func validateColdOldToNewUpgrade(t *testing.T, oldPath string, profile string, i int) {
t.Logf("Cold upgrade from %s to HEAD", *upgradeFrom)
runCommand(t, false, oldPath, "start", "-p", profile, *startArgs, "--alsologtostderr")
runCommand(t, false, oldPath, "stop", "-p", profile)
runCommand(t, true, newPath, "start", "-p", profile, *startArgs, "--alsologtostderr")
}
func validateHotHeadRestart(t *testing.T, oldPath string, profile string, i int) {
t.Logf("Restart HEAD test")
runCommand(t, true, newPath, "start", "-p", profile, *startArgs, "--alsologtostderr")
}
func validateColdHeadRestart(t *testing.T, oldPath string, profile string, i int) {
t.Logf("Cold HEAD restart")
runCommand(t, false, newPath, "stop", "-p", profile)
runCommand(t, true, newPath, "start", "-p", profile, *startArgs, "--alsologtostderr")
}
func Cleanup(t *testing.T, oldPath string, profile string) {
runCommand(t, false, newPath, "delete", "-p", profile)
os.Remove(oldPath)
}
func runCommand(t *testing.T, errorOut bool, mkPath string, args ...string) {
c := exec.Command(mkPath, args...)
t.Logf("Running: %s, %v", mkPath, args)
start := time.Now()
out, err := c.CombinedOutput()
if err != nil {
if errorOut {
t.Errorf("Error running %s %v: %v", mkPath, args, err)
t.Logf("Command output: %q", out)
} else {
t.Logf("Error running %s %v: %v", mkPath, args, err)
}
return
}
elapsed := time.Since(start)
if elapsed.Milliseconds() > cmdTimeout && errorOut {
t.Errorf("Command took too long: %s %v took %f seconds", mkPath, args, elapsed.Seconds())
}
}