Source file
test/stress/runstress.go
1
2
3
4
5
6
7
8
9 package main
10
11 import (
12 "flag"
13 "fmt"
14 "io"
15 "log"
16 "math/rand"
17 "net"
18 "net/http"
19 "net/http/httptest"
20 "os/exec"
21 "strconv"
22 "time"
23 )
24
25 var (
26 v = flag.Bool("v", false, "verbose")
27 doMaps = flag.Bool("maps", true, "stress maps")
28 doExec = flag.Bool("exec", true, "stress exec")
29 doChan = flag.Bool("chan", true, "stress channels")
30 doNet = flag.Bool("net", true, "stress networking")
31 doParseGo = flag.Bool("parsego", true, "stress parsing Go (generates garbage)")
32 )
33
34 func Println(a ...interface{}) {
35 if *v {
36 log.Println(a...)
37 }
38 }
39
40 func dialStress(a net.Addr) {
41 for {
42 d := net.Dialer{Timeout: time.Duration(rand.Intn(1e9))}
43 c, err := d.Dial("tcp", a.String())
44 if err == nil {
45 Println("did dial")
46 go func() {
47 time.Sleep(time.Duration(rand.Intn(500)) * time.Millisecond)
48 c.Close()
49 Println("closed dial")
50 }()
51 }
52
53 time.Sleep(250 * time.Millisecond)
54 }
55 }
56
57 func stressNet() {
58 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
59 size, _ := strconv.Atoi(r.FormValue("size"))
60 w.Write(make([]byte, size))
61 }))
62 go dialStress(ts.Listener.Addr())
63 for {
64 size := rand.Intn(128 << 10)
65 res, err := http.Get(fmt.Sprintf("%s/?size=%d", ts.URL, size))
66 if err != nil {
67 log.Fatalf("stressNet: http Get error: %v", err)
68 }
69 if res.StatusCode != 200 {
70 log.Fatalf("stressNet: Status code = %d", res.StatusCode)
71 }
72 n, err := io.Copy(io.Discard, res.Body)
73 if err != nil {
74 log.Fatalf("stressNet: io.Copy: %v", err)
75 }
76 if n != int64(size) {
77 log.Fatalf("stressNet: copied = %d; want %d", n, size)
78 }
79 res.Body.Close()
80 Println("did http", size)
81 }
82 }
83
84 func doAnExec() {
85 exit := rand.Intn(2)
86 wantOutput := fmt.Sprintf("output-%d", rand.Intn(1e9))
87 cmd := exec.Command("/bin/sh", "-c", fmt.Sprintf("echo %s; exit %d", wantOutput, exit))
88 out, err := cmd.CombinedOutput()
89 if exit == 1 {
90 if err == nil {
91 log.Fatal("stressExec: unexpected exec success")
92 }
93 return
94 }
95 if err != nil {
96 log.Fatalf("stressExec: exec failure: %v: %s", err, out)
97 }
98 wantOutput += "\n"
99 if string(out) != wantOutput {
100 log.Fatalf("stressExec: exec output = %q; want %q", out, wantOutput)
101 }
102 Println("did exec")
103 }
104
105 func stressExec() {
106 gate := make(chan bool, 10)
107 for {
108 gate <- true
109 go func() {
110 doAnExec()
111 <-gate
112 }()
113 }
114 }
115
116 func ringf(in <-chan int, out chan<- int, donec chan bool) {
117 for {
118 var n int
119 select {
120 case <-donec:
121 return
122 case n = <-in:
123 }
124 if n == 0 {
125 close(donec)
126 return
127 }
128 out <- n - 1
129 }
130 }
131
132 func threadRing(bufsize int) {
133 const N = 100
134 donec := make(chan bool)
135 one := make(chan int, bufsize)
136 var in, out chan int = nil, one
137 for i := 1; i <= N-1; i++ {
138 in, out = out, make(chan int, bufsize)
139 go ringf(in, out, donec)
140 }
141 go ringf(out, one, donec)
142 one <- N
143 <-donec
144 Println("did threadring of", bufsize)
145 }
146
147 func stressChannels() {
148 for {
149 threadRing(0)
150 threadRing(1)
151 }
152 }
153
154 func main() {
155 flag.Parse()
156 for want, f := range map[*bool]func(){
157 doMaps: stressMaps,
158 doNet: stressNet,
159 doExec: stressExec,
160 doChan: stressChannels,
161 doParseGo: stressParseGo,
162 } {
163 if *want {
164 go f()
165 }
166 }
167 select {}
168 }
169
View as plain text