libgo: update to go1.9
[official-gcc.git] / libgo / go / expvar / expvar_test.go
blob7014063d4f7276a3f0dd897a9145700ff9e771b8
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 package expvar
7 import (
8 "bytes"
9 "encoding/json"
10 "fmt"
11 "net"
12 "net/http/httptest"
13 "reflect"
14 "runtime"
15 "strconv"
16 "sync"
17 "sync/atomic"
18 "testing"
21 // RemoveAll removes all exported variables.
22 // This is for tests only.
23 func RemoveAll() {
24 varKeysMu.Lock()
25 defer varKeysMu.Unlock()
26 for _, k := range varKeys {
27 vars.Delete(k)
29 varKeys = nil
32 func TestNil(t *testing.T) {
33 RemoveAll()
34 val := Get("missing")
35 if val != nil {
36 t.Errorf("got %v, want nil", val)
40 func TestInt(t *testing.T) {
41 RemoveAll()
42 reqs := NewInt("requests")
43 if i := reqs.Value(); i != 0 {
44 t.Errorf("reqs.Value() = %v, want 0", i)
46 if reqs != Get("requests").(*Int) {
47 t.Errorf("Get() failed.")
50 reqs.Add(1)
51 reqs.Add(3)
52 if i := reqs.Value(); i != 4 {
53 t.Errorf("reqs.Value() = %v, want 4", i)
56 if s := reqs.String(); s != "4" {
57 t.Errorf("reqs.String() = %q, want \"4\"", s)
60 reqs.Set(-2)
61 if i := reqs.Value(); i != -2 {
62 t.Errorf("reqs.Value() = %v, want -2", i)
66 func BenchmarkIntAdd(b *testing.B) {
67 var v Int
69 b.RunParallel(func(pb *testing.PB) {
70 for pb.Next() {
71 v.Add(1)
76 func BenchmarkIntSet(b *testing.B) {
77 var v Int
79 b.RunParallel(func(pb *testing.PB) {
80 for pb.Next() {
81 v.Set(1)
86 func TestFloat(t *testing.T) {
87 RemoveAll()
88 reqs := NewFloat("requests-float")
89 if reqs.f != 0.0 {
90 t.Errorf("reqs.f = %v, want 0", reqs.f)
92 if reqs != Get("requests-float").(*Float) {
93 t.Errorf("Get() failed.")
96 reqs.Add(1.5)
97 reqs.Add(1.25)
98 if v := reqs.Value(); v != 2.75 {
99 t.Errorf("reqs.Value() = %v, want 2.75", v)
102 if s := reqs.String(); s != "2.75" {
103 t.Errorf("reqs.String() = %q, want \"4.64\"", s)
106 reqs.Add(-2)
107 if v := reqs.Value(); v != 0.75 {
108 t.Errorf("reqs.Value() = %v, want 0.75", v)
112 func BenchmarkFloatAdd(b *testing.B) {
113 var f Float
115 b.RunParallel(func(pb *testing.PB) {
116 for pb.Next() {
117 f.Add(1.0)
122 func BenchmarkFloatSet(b *testing.B) {
123 var f Float
125 b.RunParallel(func(pb *testing.PB) {
126 for pb.Next() {
127 f.Set(1.0)
132 func TestString(t *testing.T) {
133 RemoveAll()
134 name := NewString("my-name")
135 if s := name.Value(); s != "" {
136 t.Errorf(`NewString("my-name").Value() = %q, want ""`, s)
139 name.Set("Mike")
140 if s, want := name.String(), `"Mike"`; s != want {
141 t.Errorf(`after name.Set("Mike"), name.String() = %q, want %q`, s, want)
143 if s, want := name.Value(), "Mike"; s != want {
144 t.Errorf(`after name.Set("Mike"), name.Value() = %q, want %q`, s, want)
147 // Make sure we produce safe JSON output.
148 name.Set("<")
149 if s, want := name.String(), "\"\\u003c\""; s != want {
150 t.Errorf(`after name.Set("<"), name.String() = %q, want %q`, s, want)
154 func BenchmarkStringSet(b *testing.B) {
155 var s String
157 b.RunParallel(func(pb *testing.PB) {
158 for pb.Next() {
159 s.Set("red")
164 func TestMapCounter(t *testing.T) {
165 RemoveAll()
166 colors := NewMap("bike-shed-colors")
168 colors.Add("red", 1)
169 colors.Add("red", 2)
170 colors.Add("blue", 4)
171 colors.AddFloat(`green "midori"`, 4.125)
172 if x := colors.Get("red").(*Int).Value(); x != 3 {
173 t.Errorf("colors.m[\"red\"] = %v, want 3", x)
175 if x := colors.Get("blue").(*Int).Value(); x != 4 {
176 t.Errorf("colors.m[\"blue\"] = %v, want 4", x)
178 if x := colors.Get(`green "midori"`).(*Float).Value(); x != 4.125 {
179 t.Errorf("colors.m[`green \"midori\"] = %v, want 4.125", x)
182 // colors.String() should be '{"red":3, "blue":4}',
183 // though the order of red and blue could vary.
184 s := colors.String()
185 var j interface{}
186 err := json.Unmarshal([]byte(s), &j)
187 if err != nil {
188 t.Errorf("colors.String() isn't valid JSON: %v", err)
190 m, ok := j.(map[string]interface{})
191 if !ok {
192 t.Error("colors.String() didn't produce a map.")
194 red := m["red"]
195 x, ok := red.(float64)
196 if !ok {
197 t.Error("red.Kind() is not a number.")
199 if x != 3 {
200 t.Errorf("red = %v, want 3", x)
204 func BenchmarkMapSet(b *testing.B) {
205 m := new(Map).Init()
207 v := new(Int)
209 b.RunParallel(func(pb *testing.PB) {
210 for pb.Next() {
211 m.Set("red", v)
216 func BenchmarkMapSetDifferent(b *testing.B) {
217 procKeys := make([][]string, runtime.GOMAXPROCS(0))
218 for i := range procKeys {
219 keys := make([]string, 4)
220 for j := range keys {
221 keys[j] = fmt.Sprint(i, j)
223 procKeys[i] = keys
226 m := new(Map).Init()
227 v := new(Int)
228 b.ResetTimer()
230 var n int32
231 b.RunParallel(func(pb *testing.PB) {
232 i := int(atomic.AddInt32(&n, 1)-1) % len(procKeys)
233 keys := procKeys[i]
235 for pb.Next() {
236 for _, k := range keys {
237 m.Set(k, v)
243 func BenchmarkMapSetString(b *testing.B) {
244 m := new(Map).Init()
246 v := new(String)
247 v.Set("Hello, ï €!")
249 b.RunParallel(func(pb *testing.PB) {
250 for pb.Next() {
251 m.Set("red", v)
256 func BenchmarkMapAddSame(b *testing.B) {
257 b.RunParallel(func(pb *testing.PB) {
258 for pb.Next() {
259 m := new(Map).Init()
260 m.Add("red", 1)
261 m.Add("red", 1)
262 m.Add("red", 1)
263 m.Add("red", 1)
268 func BenchmarkMapAddDifferent(b *testing.B) {
269 procKeys := make([][]string, runtime.GOMAXPROCS(0))
270 for i := range procKeys {
271 keys := make([]string, 4)
272 for j := range keys {
273 keys[j] = fmt.Sprint(i, j)
275 procKeys[i] = keys
278 b.ResetTimer()
280 var n int32
281 b.RunParallel(func(pb *testing.PB) {
282 i := int(atomic.AddInt32(&n, 1)-1) % len(procKeys)
283 keys := procKeys[i]
285 for pb.Next() {
286 m := new(Map).Init()
287 for _, k := range keys {
288 m.Add(k, 1)
294 func BenchmarkMapAddSameSteadyState(b *testing.B) {
295 m := new(Map).Init()
296 b.RunParallel(func(pb *testing.PB) {
297 for pb.Next() {
298 m.Add("red", 1)
303 func BenchmarkMapAddDifferentSteadyState(b *testing.B) {
304 procKeys := make([][]string, runtime.GOMAXPROCS(0))
305 for i := range procKeys {
306 keys := make([]string, 4)
307 for j := range keys {
308 keys[j] = fmt.Sprint(i, j)
310 procKeys[i] = keys
313 m := new(Map).Init()
314 b.ResetTimer()
316 var n int32
317 b.RunParallel(func(pb *testing.PB) {
318 i := int(atomic.AddInt32(&n, 1)-1) % len(procKeys)
319 keys := procKeys[i]
321 for pb.Next() {
322 for _, k := range keys {
323 m.Add(k, 1)
329 func TestFunc(t *testing.T) {
330 RemoveAll()
331 var x interface{} = []string{"a", "b"}
332 f := Func(func() interface{} { return x })
333 if s, exp := f.String(), `["a","b"]`; s != exp {
334 t.Errorf(`f.String() = %q, want %q`, s, exp)
336 if v := f.Value(); !reflect.DeepEqual(v, x) {
337 t.Errorf(`f.Value() = %q, want %q`, v, x)
340 x = 17
341 if s, exp := f.String(), `17`; s != exp {
342 t.Errorf(`f.String() = %q, want %q`, s, exp)
346 func TestHandler(t *testing.T) {
347 RemoveAll()
348 m := NewMap("map1")
349 m.Add("a", 1)
350 m.Add("z", 2)
351 m2 := NewMap("map2")
352 for i := 0; i < 9; i++ {
353 m2.Add(strconv.Itoa(i), int64(i))
355 rr := httptest.NewRecorder()
356 rr.Body = new(bytes.Buffer)
357 expvarHandler(rr, nil)
358 want := `{
359 "map1": {"a": 1, "z": 2},
360 "map2": {"0": 0, "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8}
363 if got := rr.Body.String(); got != want {
364 t.Errorf("HTTP handler wrote:\n%s\nWant:\n%s", got, want)
368 func BenchmarkRealworldExpvarUsage(b *testing.B) {
369 var (
370 bytesSent Int
371 bytesRead Int
374 // The benchmark creates GOMAXPROCS client/server pairs.
375 // Each pair creates 4 goroutines: client reader/writer and server reader/writer.
376 // The benchmark stresses concurrent reading and writing to the same connection.
377 // Such pattern is used in net/http and net/rpc.
379 b.StopTimer()
381 P := runtime.GOMAXPROCS(0)
382 N := b.N / P
383 W := 1000
385 // Setup P client/server connections.
386 clients := make([]net.Conn, P)
387 servers := make([]net.Conn, P)
388 ln, err := net.Listen("tcp", "127.0.0.1:0")
389 if err != nil {
390 b.Fatalf("Listen failed: %v", err)
392 defer ln.Close()
393 done := make(chan bool)
394 go func() {
395 for p := 0; p < P; p++ {
396 s, err := ln.Accept()
397 if err != nil {
398 b.Errorf("Accept failed: %v", err)
399 return
401 servers[p] = s
403 done <- true
405 for p := 0; p < P; p++ {
406 c, err := net.Dial("tcp", ln.Addr().String())
407 if err != nil {
408 b.Fatalf("Dial failed: %v", err)
410 clients[p] = c
412 <-done
414 b.StartTimer()
416 var wg sync.WaitGroup
417 wg.Add(4 * P)
418 for p := 0; p < P; p++ {
419 // Client writer.
420 go func(c net.Conn) {
421 defer wg.Done()
422 var buf [1]byte
423 for i := 0; i < N; i++ {
424 v := byte(i)
425 for w := 0; w < W; w++ {
426 v *= v
428 buf[0] = v
429 n, err := c.Write(buf[:])
430 if err != nil {
431 b.Errorf("Write failed: %v", err)
432 return
435 bytesSent.Add(int64(n))
437 }(clients[p])
439 // Pipe between server reader and server writer.
440 pipe := make(chan byte, 128)
442 // Server reader.
443 go func(s net.Conn) {
444 defer wg.Done()
445 var buf [1]byte
446 for i := 0; i < N; i++ {
447 n, err := s.Read(buf[:])
449 if err != nil {
450 b.Errorf("Read failed: %v", err)
451 return
454 bytesRead.Add(int64(n))
455 pipe <- buf[0]
457 }(servers[p])
459 // Server writer.
460 go func(s net.Conn) {
461 defer wg.Done()
462 var buf [1]byte
463 for i := 0; i < N; i++ {
464 v := <-pipe
465 for w := 0; w < W; w++ {
466 v *= v
468 buf[0] = v
469 n, err := s.Write(buf[:])
470 if err != nil {
471 b.Errorf("Write failed: %v", err)
472 return
475 bytesSent.Add(int64(n))
477 s.Close()
478 }(servers[p])
480 // Client reader.
481 go func(c net.Conn) {
482 defer wg.Done()
483 var buf [1]byte
484 for i := 0; i < N; i++ {
485 n, err := c.Read(buf[:])
487 if err != nil {
488 b.Errorf("Read failed: %v", err)
489 return
492 bytesRead.Add(int64(n))
494 c.Close()
495 }(clients[p])
497 wg.Wait()