added support for string type
[govpp.git] / vendor / github.com / pkg / profile / profile_test.go
1 package profile
2
3 import (
4         "bufio"
5         "bytes"
6         "io"
7         "io/ioutil"
8         "os"
9         "os/exec"
10         "path/filepath"
11         "strings"
12         "testing"
13 )
14
15 type checkFn func(t *testing.T, stdout, stderr []byte, err error)
16
17 func TestProfile(t *testing.T) {
18         f, err := ioutil.TempFile("", "profile_test")
19         if err != nil {
20                 t.Fatal(err)
21         }
22         defer os.Remove(f.Name())
23
24         var profileTests = []struct {
25                 name   string
26                 code   string
27                 checks []checkFn
28         }{{
29                 name: "default profile (cpu)",
30                 code: `
31 package main
32
33 import "github.com/pkg/profile"
34
35 func main() {
36         defer profile.Start().Stop()
37 }       
38 `,
39                 checks: []checkFn{
40                         NoStdout,
41                         Stderr("profile: cpu profiling enabled"),
42                         NoErr,
43                 },
44         }, {
45                 name: "memory profile",
46                 code: `
47 package main
48
49 import "github.com/pkg/profile"
50
51 func main() {
52         defer profile.Start(profile.MemProfile).Stop()
53 }       
54 `,
55                 checks: []checkFn{
56                         NoStdout,
57                         Stderr("profile: memory profiling enabled"),
58                         NoErr,
59                 },
60         }, {
61                 name: "memory profile (rate 2048)",
62                 code: `
63 package main
64
65 import "github.com/pkg/profile"
66
67 func main() {
68         defer profile.Start(profile.MemProfileRate(2048)).Stop()
69 }       
70 `,
71                 checks: []checkFn{
72                         NoStdout,
73                         Stderr("profile: memory profiling enabled (rate 2048)"),
74                         NoErr,
75                 },
76         }, {
77                 name: "double start",
78                 code: `
79 package main
80
81 import "github.com/pkg/profile"
82
83 func main() {
84         profile.Start()
85         profile.Start()
86 }       
87 `,
88                 checks: []checkFn{
89                         NoStdout,
90                         Stderr("cpu profiling enabled", "profile: Start() already called"),
91                         Err,
92                 },
93         }, {
94                 name: "block profile",
95                 code: `
96 package main
97
98 import "github.com/pkg/profile"
99
100 func main() {
101         defer profile.Start(profile.BlockProfile).Stop()
102 }       
103 `,
104                 checks: []checkFn{
105                         NoStdout,
106                         Stderr("profile: block profiling enabled"),
107                         NoErr,
108                 },
109         }, {
110                 name: "mutex profile",
111                 code: `
112 package main
113
114 import "github.com/pkg/profile"
115
116 func main() {
117         defer profile.Start(profile.MutexProfile).Stop()
118 }
119 `,
120                 checks: []checkFn{
121                         NoStdout,
122                         Stderr("profile: mutex profiling enabled"),
123                         NoErr,
124                 },
125         }, {
126                 name: "profile path",
127                 code: `
128 package main
129
130 import "github.com/pkg/profile"
131
132 func main() {
133         defer profile.Start(profile.ProfilePath(".")).Stop()
134 }       
135 `,
136                 checks: []checkFn{
137                         NoStdout,
138                         Stderr("profile: cpu profiling enabled, cpu.pprof"),
139                         NoErr,
140                 },
141         }, {
142                 name: "profile path error",
143                 code: `
144 package main
145
146 import "github.com/pkg/profile"
147
148 func main() {
149                 defer profile.Start(profile.ProfilePath("` + f.Name() + `")).Stop()
150 }       
151 `,
152                 checks: []checkFn{
153                         NoStdout,
154                         Stderr("could not create initial output"),
155                         Err,
156                 },
157         }, {
158                 name: "multiple profile sessions",
159                 code: `
160 package main
161
162 import "github.com/pkg/profile"
163
164 func main() {
165         profile.Start(profile.CPUProfile).Stop()
166         profile.Start(profile.MemProfile).Stop()
167         profile.Start(profile.BlockProfile).Stop()
168         profile.Start(profile.CPUProfile).Stop()
169         profile.Start(profile.MutexProfile).Stop()
170 }
171 `,
172                 checks: []checkFn{
173                         NoStdout,
174                         Stderr("profile: cpu profiling enabled",
175                                 "profile: cpu profiling disabled",
176                                 "profile: memory profiling enabled",
177                                 "profile: memory profiling disabled",
178                                 "profile: block profiling enabled",
179                                 "profile: block profiling disabled",
180                                 "profile: cpu profiling enabled",
181                                 "profile: cpu profiling disabled",
182                                 "profile: mutex profiling enabled",
183                                 "profile: mutex profiling disabled"),
184                         NoErr,
185                 },
186         }, {
187                 name: "profile quiet",
188                 code: `
189 package main
190
191 import "github.com/pkg/profile"
192
193 func main() {
194         defer profile.Start(profile.Quiet).Stop()
195 }       
196 `,
197                 checks: []checkFn{NoStdout, NoStderr, NoErr},
198         }}
199         for _, tt := range profileTests {
200                 t.Log(tt.name)
201                 stdout, stderr, err := runTest(t, tt.code)
202                 for _, f := range tt.checks {
203                         f(t, stdout, stderr, err)
204                 }
205         }
206 }
207
208 // NoStdout checks that stdout was blank.
209 func NoStdout(t *testing.T, stdout, _ []byte, _ error) {
210         if len := len(stdout); len > 0 {
211                 t.Errorf("stdout: wanted 0 bytes, got %d", len)
212         }
213 }
214
215 // Stderr verifies that the given lines match the output from stderr
216 func Stderr(lines ...string) checkFn {
217         return func(t *testing.T, _, stderr []byte, _ error) {
218                 r := bytes.NewReader(stderr)
219                 if !validateOutput(r, lines) {
220                         t.Errorf("stderr: wanted '%s', got '%s'", lines, stderr)
221                 }
222         }
223 }
224
225 // NoStderr checks that stderr was blank.
226 func NoStderr(t *testing.T, _, stderr []byte, _ error) {
227         if len := len(stderr); len > 0 {
228                 t.Errorf("stderr: wanted 0 bytes, got %d", len)
229         }
230 }
231
232 // Err checks that there was an error returned
233 func Err(t *testing.T, _, _ []byte, err error) {
234         if err == nil {
235                 t.Errorf("expected error")
236         }
237 }
238
239 // NoErr checks that err was nil
240 func NoErr(t *testing.T, _, _ []byte, err error) {
241         if err != nil {
242                 t.Errorf("error: expected nil, got %v", err)
243         }
244 }
245
246 // validatedOutput validates the given slice of lines against data from the given reader.
247 func validateOutput(r io.Reader, want []string) bool {
248         s := bufio.NewScanner(r)
249         for _, line := range want {
250                 if !s.Scan() || !strings.Contains(s.Text(), line) {
251                         return false
252                 }
253         }
254         return true
255 }
256
257 var validateOutputTests = []struct {
258         input string
259         lines []string
260         want  bool
261 }{{
262         input: "",
263         want:  true,
264 }, {
265         input: `profile: yes
266 `,
267         want: true,
268 }, {
269         input: `profile: yes
270 `,
271         lines: []string{"profile: yes"},
272         want:  true,
273 }, {
274         input: `profile: yes
275 profile: no
276 `,
277         lines: []string{"profile: yes"},
278         want:  true,
279 }, {
280         input: `profile: yes
281 profile: no
282 `,
283         lines: []string{"profile: yes", "profile: no"},
284         want:  true,
285 }, {
286         input: `profile: yes
287 profile: no
288 `,
289         lines: []string{"profile: no"},
290         want:  false,
291 }}
292
293 func TestValidateOutput(t *testing.T) {
294         for _, tt := range validateOutputTests {
295                 r := strings.NewReader(tt.input)
296                 got := validateOutput(r, tt.lines)
297                 if tt.want != got {
298                         t.Errorf("validateOutput(%q, %q), want %v, got %v", tt.input, tt.lines, tt.want, got)
299                 }
300         }
301 }
302
303 // runTest executes the go program supplied and returns the contents of stdout,
304 // stderr, and an error which may contain status information about the result
305 // of the program.
306 func runTest(t *testing.T, code string) ([]byte, []byte, error) {
307         chk := func(err error) {
308                 if err != nil {
309                         t.Fatal(err)
310                 }
311         }
312         gopath, err := ioutil.TempDir("", "profile-gopath")
313         chk(err)
314         defer os.RemoveAll(gopath)
315
316         srcdir := filepath.Join(gopath, "src")
317         err = os.Mkdir(srcdir, 0755)
318         chk(err)
319         src := filepath.Join(srcdir, "main.go")
320         err = ioutil.WriteFile(src, []byte(code), 0644)
321         chk(err)
322
323         cmd := exec.Command("go", "run", src)
324
325         var stdout, stderr bytes.Buffer
326         cmd.Stdout = &stdout
327         cmd.Stderr = &stderr
328         err = cmd.Run()
329         return stdout.Bytes(), stderr.Bytes(), err
330 }