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 varKeysMu
.Unlock()
27 for _
, k
:= range varKeys
{
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")
91 t
.Errorf("reqs.f = %v, want 0", reqs
.f
)
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 BenchmarkMapSet(b
*testing
.B
) {
269 b
.RunParallel(func(pb
*testing
.PB
) {
276 func BenchmarkMapSetDifferent(b
*testing
.B
) {
277 procKeys
:= make([][]string, runtime
.GOMAXPROCS(0))
278 for i
:= range procKeys
{
279 keys
:= make([]string, 4)
280 for j
:= range keys
{
281 keys
[j
] = fmt
.Sprint(i
, j
)
291 b
.RunParallel(func(pb
*testing
.PB
) {
292 i
:= int(atomic
.AddInt32(&n
, 1)-1) % len(procKeys
)
296 for _
, k
:= range keys
{
303 // BenchmarkMapSetDifferentRandom simulates such a case where the concerned
304 // keys of Map.Set are generated dynamically and as a result insertion is
305 // out of order and the number of the keys may be large.
306 func BenchmarkMapSetDifferentRandom(b
*testing
.B
) {
307 keys
:= make([]string, 100)
308 for i
:= range keys
{
309 keys
[i
] = fmt
.Sprintf("%x", sha1
.Sum([]byte(fmt
.Sprint(i
))))
315 for i
:= 0; i
< b
.N
; i
++ {
317 for _
, k
:= range keys
{
323 func BenchmarkMapSetString(b
*testing
.B
) {
329 b
.RunParallel(func(pb
*testing
.PB
) {
336 func BenchmarkMapAddSame(b
*testing
.B
) {
337 b
.RunParallel(func(pb
*testing
.PB
) {
348 func BenchmarkMapAddDifferent(b
*testing
.B
) {
349 procKeys
:= make([][]string, runtime
.GOMAXPROCS(0))
350 for i
:= range procKeys
{
351 keys
:= make([]string, 4)
352 for j
:= range keys
{
353 keys
[j
] = fmt
.Sprint(i
, j
)
361 b
.RunParallel(func(pb
*testing
.PB
) {
362 i
:= int(atomic
.AddInt32(&n
, 1)-1) % len(procKeys
)
367 for _
, k
:= range keys
{
374 // BenchmarkMapAddDifferentRandom simulates such a case where that the concerned
375 // keys of Map.Add are generated dynamically and as a result insertion is out of
376 // order and the number of the keys may be large.
377 func BenchmarkMapAddDifferentRandom(b
*testing
.B
) {
378 keys
:= make([]string, 100)
379 for i
:= range keys
{
380 keys
[i
] = fmt
.Sprintf("%x", sha1
.Sum([]byte(fmt
.Sprint(i
))))
385 for i
:= 0; i
< b
.N
; i
++ {
387 for _
, k
:= range keys
{
393 func BenchmarkMapAddSameSteadyState(b
*testing
.B
) {
395 b
.RunParallel(func(pb
*testing
.PB
) {
402 func BenchmarkMapAddDifferentSteadyState(b
*testing
.B
) {
403 procKeys
:= make([][]string, runtime
.GOMAXPROCS(0))
404 for i
:= range procKeys
{
405 keys
:= make([]string, 4)
406 for j
:= range keys
{
407 keys
[j
] = fmt
.Sprint(i
, j
)
416 b
.RunParallel(func(pb
*testing
.PB
) {
417 i
:= int(atomic
.AddInt32(&n
, 1)-1) % len(procKeys
)
421 for _
, k
:= range keys
{
428 func TestFunc(t
*testing
.T
) {
430 var x any
= []string{"a", "b"}
431 f
:= Func(func() any
{ return x
})
432 if s
, exp
:= f
.String(), `["a","b"]`; s
!= exp
{
433 t
.Errorf(`f.String() = %q, want %q`, s
, exp
)
435 if v
:= f
.Value(); !reflect
.DeepEqual(v
, x
) {
436 t
.Errorf(`f.Value() = %q, want %q`, v
, x
)
440 if s
, exp
:= f
.String(), `17`; s
!= exp
{
441 t
.Errorf(`f.String() = %q, want %q`, s
, exp
)
445 func TestHandler(t
*testing
.T
) {
451 for i
:= 0; i
< 9; i
++ {
452 m2
.Add(strconv
.Itoa(i
), int64(i
))
454 rr
:= httptest
.NewRecorder()
455 rr
.Body
= new(bytes
.Buffer
)
456 expvarHandler(rr
, nil)
458 "map1": {"a": 1, "z": 2},
459 "map2": {"0": 0, "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8}
462 if got
:= rr
.Body
.String(); got
!= want
{
463 t
.Errorf("HTTP handler wrote:\n%s\nWant:\n%s", got
, want
)
467 func BenchmarkRealworldExpvarUsage(b
*testing
.B
) {
473 // The benchmark creates GOMAXPROCS client/server pairs.
474 // Each pair creates 4 goroutines: client reader/writer and server reader/writer.
475 // The benchmark stresses concurrent reading and writing to the same connection.
476 // Such pattern is used in net/http and net/rpc.
480 P
:= runtime
.GOMAXPROCS(0)
484 // Setup P client/server connections.
485 clients
:= make([]net
.Conn
, P
)
486 servers
:= make([]net
.Conn
, P
)
487 ln
, err
:= net
.Listen("tcp", "127.0.0.1:0")
489 b
.Fatalf("Listen failed: %v", err
)
492 done
:= make(chan bool, 1)
494 for p
:= 0; p
< P
; p
++ {
495 s
, err
:= ln
.Accept()
497 b
.Errorf("Accept failed: %v", err
)
505 for p
:= 0; p
< P
; p
++ {
506 c
, err
:= net
.Dial("tcp", ln
.Addr().String())
509 b
.Fatalf("Dial failed: %v", err
)
519 var wg sync
.WaitGroup
521 for p
:= 0; p
< P
; p
++ {
523 go func(c net
.Conn
) {
526 for i
:= 0; i
< N
; i
++ {
528 for w
:= 0; w
< W
; w
++ {
532 n
, err
:= c
.Write(buf
[:])
534 b
.Errorf("Write failed: %v", err
)
538 bytesSent
.Add(int64(n
))
542 // Pipe between server reader and server writer.
543 pipe
:= make(chan byte, 128)
546 go func(s net
.Conn
) {
549 for i
:= 0; i
< N
; i
++ {
550 n
, err
:= s
.Read(buf
[:])
553 b
.Errorf("Read failed: %v", err
)
557 bytesRead
.Add(int64(n
))
563 go func(s net
.Conn
) {
566 for i
:= 0; i
< N
; i
++ {
568 for w
:= 0; w
< W
; w
++ {
572 n
, err
:= s
.Write(buf
[:])
574 b
.Errorf("Write failed: %v", err
)
578 bytesSent
.Add(int64(n
))
584 go func(c net
.Conn
) {
587 for i
:= 0; i
< N
; i
++ {
588 n
, err
:= c
.Read(buf
[:])
591 b
.Errorf("Read failed: %v", err
)
595 bytesRead
.Add(int64(n
))