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.
22 // RemoveAll removes all exported variables.
23 // This is for tests only.
26 defer vars.keysMu.Unlock()
27 for _, k := range vars.keys {
33 func TestNil(t *testing.T) {
37 t.Errorf("got %v, want nil", val)
41 func TestInt(t *testing.T) {
43 reqs := NewInt("requests")
44 if i := reqs.Value(); i != 0 {
45 t.Errorf("reqs.Value() = %v, want 0", i)
47 if reqs != Get("requests").(*Int) {
48 t.Errorf("Get() failed.")
53 if i := reqs.Value(); i != 4 {
54 t.Errorf("reqs.Value() = %v, want 4", i)
57 if s := reqs.String(); s != "4" {
58 t.Errorf("reqs.String() = %q, want \"4\"", s)
62 if i := reqs.Value(); i != -2 {
63 t.Errorf("reqs.Value() = %v, want -2", i)
67 func BenchmarkIntAdd(b *testing.B) {
70 b.RunParallel(func(pb *testing.PB) {
77 func BenchmarkIntSet(b *testing.B) {
80 b.RunParallel(func(pb *testing.PB) {
87 func TestFloat(t *testing.T) {
89 reqs := NewFloat("requests-float")
90 if reqs.f.Load() != 0.0 {
91 t.Errorf("reqs.f = %v, want 0", reqs.f.Load())
93 if reqs != Get("requests-float").(*Float) {
94 t.Errorf("Get() failed.")
99 if v := reqs.Value(); v != 2.75 {
100 t.Errorf("reqs.Value() = %v, want 2.75", v)
103 if s := reqs.String(); s != "2.75" {
104 t.Errorf("reqs.String() = %q, want \"4.64\"", s)
108 if v := reqs.Value(); v != 0.75 {
109 t.Errorf("reqs.Value() = %v, want 0.75", v)
113 func BenchmarkFloatAdd(b *testing.B) {
116 b.RunParallel(func(pb *testing.PB) {
123 func BenchmarkFloatSet(b *testing.B) {
126 b.RunParallel(func(pb *testing.PB) {
133 func TestString(t *testing.T) {
135 name := NewString("my-name")
136 if s := name.Value(); s != "" {
137 t.Errorf(`NewString("my-name").Value() = %q, want ""`, s)
141 if s, want := name.String(), `"Mike"`; s != want {
142 t.Errorf(`after name.Set("Mike"), name.String() = %q, want %q`, s, want)
144 if s, want := name.Value(), "Mike"; s != want {
145 t.Errorf(`after name.Set("Mike"), name.Value() = %q, want %q`, s, want)
148 // Make sure we produce safe JSON output.
150 if s, want := name.String(), "\"\\u003c\""; s != want {
151 t.Errorf(`after name.Set("<"), name.String() = %q, want %q`, s, want)
155 func BenchmarkStringSet(b *testing.B) {
158 b.RunParallel(func(pb *testing.PB) {
165 func TestMapInit(t *testing.T) {
167 colors := NewMap("bike-shed-colors")
169 colors.Add("blue", 1)
170 colors.Add("chartreuse", 1)
173 colors.Do(func(KeyValue) { n++ })
175 t.Errorf("after three Add calls with distinct keys, Do should invoke f 3 times; got %v", n)
181 colors.Do(func(KeyValue) { n++ })
183 t.Errorf("after Init, Do should invoke f 0 times; got %v", n)
187 func TestMapDelete(t *testing.T) {
189 colors := NewMap("bike-shed-colors")
193 colors.Add("blue", 4)
196 colors.Do(func(KeyValue) { n++ })
198 t.Errorf("after two Add calls with distinct keys, Do should invoke f 2 times; got %v", n)
203 colors.Do(func(KeyValue) { n++ })
205 t.Errorf("removed red, Do should invoke f 1 times; got %v", n)
208 colors.Delete("notfound")
210 colors.Do(func(KeyValue) { n++ })
212 t.Errorf("attempted to remove notfound, Do should invoke f 1 times; got %v", n)
215 colors.Delete("blue")
216 colors.Delete("blue")
218 colors.Do(func(KeyValue) { n++ })
220 t.Errorf("all keys removed, Do should invoke f 0 times; got %v", n)
224 func TestMapCounter(t *testing.T) {
226 colors := NewMap("bike-shed-colors")
230 colors.Add("blue", 4)
231 colors.AddFloat(`green "midori"`, 4.125)
232 if x := colors.Get("red").(*Int).Value(); x != 3 {
233 t.Errorf("colors.m[\"red\"] = %v, want 3", x)
235 if x := colors.Get("blue").(*Int).Value(); x != 4 {
236 t.Errorf("colors.m[\"blue\"] = %v, want 4", x)
238 if x := colors.Get(`green "midori"`).(*Float).Value(); x != 4.125 {
239 t.Errorf("colors.m[`green \"midori\"] = %v, want 4.125", x)
242 // colors.String() should be '{"red":3, "blue":4}',
243 // though the order of red and blue could vary.
246 err := json.Unmarshal([]byte(s), &j)
248 t.Errorf("colors.String() isn't valid JSON: %v", err)
250 m, ok := j.(map[string]any)
252 t.Error("colors.String() didn't produce a map.")
255 x, ok := red.(float64)
257 t.Error("red.Kind() is not a number.")
260 t.Errorf("red = %v, want 3", x)
264 func TestMapNil(t *testing.T) {
267 m := NewMap("issue527719")
271 if err := json.Unmarshal([]byte(s), &j); err != nil {
272 t.Fatalf("m.String() == %q isn't valid JSON: %v", s, err)
274 m2, ok := j.(map[string]any)
276 t.Fatalf("m.String() produced %T, wanted a map", j)
280 t.Fatalf("missing %q in %v", key, m2)
283 t.Fatalf("m[%q] = %v, want nil", key, v)
287 func BenchmarkMapSet(b *testing.B) {
292 b.RunParallel(func(pb *testing.PB) {
299 func BenchmarkMapSetDifferent(b *testing.B) {
300 procKeys := make([][]string, runtime.GOMAXPROCS(0))
301 for i := range procKeys {
302 keys := make([]string, 4)
303 for j := range keys {
304 keys[j] = fmt.Sprint(i, j)
314 b.RunParallel(func(pb *testing.PB) {
315 i := int(atomic.AddInt32(&n, 1)-1) % len(procKeys)
319 for _, k := range keys {
326 // BenchmarkMapSetDifferentRandom simulates such a case where the concerned
327 // keys of Map.Set are generated dynamically and as a result insertion is
328 // out of order and the number of the keys may be large.
329 func BenchmarkMapSetDifferentRandom(b *testing.B) {
330 keys := make([]string, 100)
331 for i := range keys {
332 keys[i] = fmt.Sprintf("%x", sha1.Sum([]byte(fmt.Sprint(i))))
338 for i := 0; i < b.N; i++ {
340 for _, k := range keys {
346 func BenchmarkMapSetString(b *testing.B) {
352 b.RunParallel(func(pb *testing.PB) {
359 func BenchmarkMapAddSame(b *testing.B) {
360 b.RunParallel(func(pb *testing.PB) {
371 func BenchmarkMapAddDifferent(b *testing.B) {
372 procKeys := make([][]string, runtime.GOMAXPROCS(0))
373 for i := range procKeys {
374 keys := make([]string, 4)
375 for j := range keys {
376 keys[j] = fmt.Sprint(i, j)
384 b.RunParallel(func(pb *testing.PB) {
385 i := int(atomic.AddInt32(&n, 1)-1) % len(procKeys)
390 for _, k := range keys {
397 // BenchmarkMapAddDifferentRandom simulates such a case where that the concerned
398 // keys of Map.Add are generated dynamically and as a result insertion is out of
399 // order and the number of the keys may be large.
400 func BenchmarkMapAddDifferentRandom(b *testing.B) {
401 keys := make([]string, 100)
402 for i := range keys {
403 keys[i] = fmt.Sprintf("%x", sha1.Sum([]byte(fmt.Sprint(i))))
408 for i := 0; i < b.N; i++ {
410 for _, k := range keys {
416 func BenchmarkMapAddSameSteadyState(b *testing.B) {
418 b.RunParallel(func(pb *testing.PB) {
425 func BenchmarkMapAddDifferentSteadyState(b *testing.B) {
426 procKeys := make([][]string, runtime.GOMAXPROCS(0))
427 for i := range procKeys {
428 keys := make([]string, 4)
429 for j := range keys {
430 keys[j] = fmt.Sprint(i, j)
439 b.RunParallel(func(pb *testing.PB) {
440 i := int(atomic.AddInt32(&n, 1)-1) % len(procKeys)
444 for _, k := range keys {
451 func TestFunc(t *testing.T) {
453 var x any = []string{"a", "b"}
454 f := Func(func() any { return x })
455 if s, exp := f.String(), `["a","b"]`; s != exp {
456 t.Errorf(`f.String() = %q, want %q`, s, exp)
458 if v := f.Value(); !reflect.DeepEqual(v, x) {
459 t.Errorf(`f.Value() = %q, want %q`, v, x)
463 if s, exp := f.String(), `17`; s != exp {
464 t.Errorf(`f.String() = %q, want %q`, s, exp)
468 func TestHandler(t *testing.T) {
474 for i := 0; i < 9; i++ {
475 m2.Add(strconv.Itoa(i), int64(i))
477 rr := httptest.NewRecorder()
478 rr.Body = new(bytes.Buffer)
479 expvarHandler(rr, nil)
481 "map1": {"a": 1, "z": 2},
482 "map2": {"0": 0, "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8}
485 if got := rr.Body.String(); got != want {
486 t.Errorf("HTTP handler wrote:\n%s\nWant:\n%s", got, want)
490 func BenchmarkMapString(b *testing.B) {
496 for i := 0; i < 9; i++ {
497 m2.Add(strconv.Itoa(i), int64(i))
501 s1.Set("hello, world!")
507 for i := 0; i < b.N; i++ {
512 func BenchmarkRealworldExpvarUsage(b *testing.B) {
518 // The benchmark creates GOMAXPROCS client/server pairs.
519 // Each pair creates 4 goroutines: client reader/writer and server reader/writer.
520 // The benchmark stresses concurrent reading and writing to the same connection.
521 // Such pattern is used in net/http and net/rpc.
525 P := runtime.GOMAXPROCS(0)
529 // Setup P client/server connections.
530 clients := make([]net.Conn, P)
531 servers := make([]net.Conn, P)
532 ln, err := net.Listen("tcp", "127.0.0.1:0")
534 b.Fatalf("Listen failed: %v", err)
537 done := make(chan bool, 1)
539 for p := 0; p < P; p++ {
540 s, err := ln.Accept()
542 b.Errorf("Accept failed: %v", err)
550 for p := 0; p < P; p++ {
551 c, err := net.Dial("tcp", ln.Addr().String())
554 b.Fatalf("Dial failed: %v", err)
564 var wg sync.WaitGroup
566 for p := 0; p < P; p++ {
568 go func(c net.Conn) {
571 for i := 0; i < N; i++ {
573 for w := 0; w < W; w++ {
577 n, err := c.Write(buf[:])
579 b.Errorf("Write failed: %v", err)
583 bytesSent.Add(int64(n))
587 // Pipe between server reader and server writer.
588 pipe := make(chan byte, 128)
591 go func(s net.Conn) {
594 for i := 0; i < N; i++ {
595 n, err := s.Read(buf[:])
598 b.Errorf("Read failed: %v", err)
602 bytesRead.Add(int64(n))
608 go func(s net.Conn) {
611 for i := 0; i < N; i++ {
613 for w := 0; w < W; w++ {
617 n, err := s.Write(buf[:])
619 b.Errorf("Write failed: %v", err)
623 bytesSent.Add(int64(n))
629 go func(c net.Conn) {
632 for i := 0; i < N; i++ {
633 n, err := c.Read(buf[:])
636 b.Errorf("Read failed: %v", err)
640 bytesRead.Add(int64(n))
648 func TestAppendJSONQuote(t *testing.T) {
650 for i := 0; i < 128; i++ {
651 b = append(b, byte(i))
653 b = append(b, "\u2028\u2029"...)
654 got := string(appendJSONQuote(nil, string(b[:])))
656 `\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008\t\n\u000b\u000c\r\u000e\u000f` +
657 `\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f` +
658 ` !\"#$%\u0026'()*+,-./0123456789:;\u003c=\u003e?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_` +
659 "`" + `abcdefghijklmnopqrstuvwxyz{|}~` + "\x7f" + `\u2028\u2029"`
661 t.Errorf("appendJSONQuote mismatch:\ngot %v\nwant %v", got, want)