diff options
Diffstat (limited to 'vendor/github.com/pkg/profile/profile_test.go')
-rw-r--r-- | vendor/github.com/pkg/profile/profile_test.go | 330 |
1 files changed, 330 insertions, 0 deletions
diff --git a/vendor/github.com/pkg/profile/profile_test.go b/vendor/github.com/pkg/profile/profile_test.go new file mode 100644 index 0000000..e33012c --- /dev/null +++ b/vendor/github.com/pkg/profile/profile_test.go @@ -0,0 +1,330 @@ +package profile + +import ( + "bufio" + "bytes" + "io" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "strings" + "testing" +) + +type checkFn func(t *testing.T, stdout, stderr []byte, err error) + +func TestProfile(t *testing.T) { + f, err := ioutil.TempFile("", "profile_test") + if err != nil { + t.Fatal(err) + } + defer os.Remove(f.Name()) + + var profileTests = []struct { + name string + code string + checks []checkFn + }{{ + name: "default profile (cpu)", + code: ` +package main + +import "github.com/pkg/profile" + +func main() { + defer profile.Start().Stop() +} +`, + checks: []checkFn{ + NoStdout, + Stderr("profile: cpu profiling enabled"), + NoErr, + }, + }, { + name: "memory profile", + code: ` +package main + +import "github.com/pkg/profile" + +func main() { + defer profile.Start(profile.MemProfile).Stop() +} +`, + checks: []checkFn{ + NoStdout, + Stderr("profile: memory profiling enabled"), + NoErr, + }, + }, { + name: "memory profile (rate 2048)", + code: ` +package main + +import "github.com/pkg/profile" + +func main() { + defer profile.Start(profile.MemProfileRate(2048)).Stop() +} +`, + checks: []checkFn{ + NoStdout, + Stderr("profile: memory profiling enabled (rate 2048)"), + NoErr, + }, + }, { + name: "double start", + code: ` +package main + +import "github.com/pkg/profile" + +func main() { + profile.Start() + profile.Start() +} +`, + checks: []checkFn{ + NoStdout, + Stderr("cpu profiling enabled", "profile: Start() already called"), + Err, + }, + }, { + name: "block profile", + code: ` +package main + +import "github.com/pkg/profile" + +func main() { + defer profile.Start(profile.BlockProfile).Stop() +} +`, + checks: []checkFn{ + NoStdout, + Stderr("profile: block profiling enabled"), + NoErr, + }, + }, { + name: "mutex profile", + code: ` +package main + +import "github.com/pkg/profile" + +func main() { + defer profile.Start(profile.MutexProfile).Stop() +} +`, + checks: []checkFn{ + NoStdout, + Stderr("profile: mutex profiling enabled"), + NoErr, + }, + }, { + name: "profile path", + code: ` +package main + +import "github.com/pkg/profile" + +func main() { + defer profile.Start(profile.ProfilePath(".")).Stop() +} +`, + checks: []checkFn{ + NoStdout, + Stderr("profile: cpu profiling enabled, cpu.pprof"), + NoErr, + }, + }, { + name: "profile path error", + code: ` +package main + +import "github.com/pkg/profile" + +func main() { + defer profile.Start(profile.ProfilePath("` + f.Name() + `")).Stop() +} +`, + checks: []checkFn{ + NoStdout, + Stderr("could not create initial output"), + Err, + }, + }, { + name: "multiple profile sessions", + code: ` +package main + +import "github.com/pkg/profile" + +func main() { + profile.Start(profile.CPUProfile).Stop() + profile.Start(profile.MemProfile).Stop() + profile.Start(profile.BlockProfile).Stop() + profile.Start(profile.CPUProfile).Stop() + profile.Start(profile.MutexProfile).Stop() +} +`, + checks: []checkFn{ + NoStdout, + Stderr("profile: cpu profiling enabled", + "profile: cpu profiling disabled", + "profile: memory profiling enabled", + "profile: memory profiling disabled", + "profile: block profiling enabled", + "profile: block profiling disabled", + "profile: cpu profiling enabled", + "profile: cpu profiling disabled", + "profile: mutex profiling enabled", + "profile: mutex profiling disabled"), + NoErr, + }, + }, { + name: "profile quiet", + code: ` +package main + +import "github.com/pkg/profile" + +func main() { + defer profile.Start(profile.Quiet).Stop() +} +`, + checks: []checkFn{NoStdout, NoStderr, NoErr}, + }} + for _, tt := range profileTests { + t.Log(tt.name) + stdout, stderr, err := runTest(t, tt.code) + for _, f := range tt.checks { + f(t, stdout, stderr, err) + } + } +} + +// NoStdout checks that stdout was blank. +func NoStdout(t *testing.T, stdout, _ []byte, _ error) { + if len := len(stdout); len > 0 { + t.Errorf("stdout: wanted 0 bytes, got %d", len) + } +} + +// Stderr verifies that the given lines match the output from stderr +func Stderr(lines ...string) checkFn { + return func(t *testing.T, _, stderr []byte, _ error) { + r := bytes.NewReader(stderr) + if !validateOutput(r, lines) { + t.Errorf("stderr: wanted '%s', got '%s'", lines, stderr) + } + } +} + +// NoStderr checks that stderr was blank. +func NoStderr(t *testing.T, _, stderr []byte, _ error) { + if len := len(stderr); len > 0 { + t.Errorf("stderr: wanted 0 bytes, got %d", len) + } +} + +// Err checks that there was an error returned +func Err(t *testing.T, _, _ []byte, err error) { + if err == nil { + t.Errorf("expected error") + } +} + +// NoErr checks that err was nil +func NoErr(t *testing.T, _, _ []byte, err error) { + if err != nil { + t.Errorf("error: expected nil, got %v", err) + } +} + +// validatedOutput validates the given slice of lines against data from the given reader. +func validateOutput(r io.Reader, want []string) bool { + s := bufio.NewScanner(r) + for _, line := range want { + if !s.Scan() || !strings.Contains(s.Text(), line) { + return false + } + } + return true +} + +var validateOutputTests = []struct { + input string + lines []string + want bool +}{{ + input: "", + want: true, +}, { + input: `profile: yes +`, + want: true, +}, { + input: `profile: yes +`, + lines: []string{"profile: yes"}, + want: true, +}, { + input: `profile: yes +profile: no +`, + lines: []string{"profile: yes"}, + want: true, +}, { + input: `profile: yes +profile: no +`, + lines: []string{"profile: yes", "profile: no"}, + want: true, +}, { + input: `profile: yes +profile: no +`, + lines: []string{"profile: no"}, + want: false, +}} + +func TestValidateOutput(t *testing.T) { + for _, tt := range validateOutputTests { + r := strings.NewReader(tt.input) + got := validateOutput(r, tt.lines) + if tt.want != got { + t.Errorf("validateOutput(%q, %q), want %v, got %v", tt.input, tt.lines, tt.want, got) + } + } +} + +// runTest executes the go program supplied and returns the contents of stdout, +// stderr, and an error which may contain status information about the result +// of the program. +func runTest(t *testing.T, code string) ([]byte, []byte, error) { + chk := func(err error) { + if err != nil { + t.Fatal(err) + } + } + gopath, err := ioutil.TempDir("", "profile-gopath") + chk(err) + defer os.RemoveAll(gopath) + + srcdir := filepath.Join(gopath, "src") + err = os.Mkdir(srcdir, 0755) + chk(err) + src := filepath.Join(srcdir, "main.go") + err = ioutil.WriteFile(src, []byte(code), 0644) + chk(err) + + cmd := exec.Command("go", "run", src) + + var stdout, stderr bytes.Buffer + cmd.Stdout = &stdout + cmd.Stderr = &stderr + err = cmd.Run() + return stdout.Bytes(), stderr.Bytes(), err +} |