github.com/geraldss/go/src@v0.0.0-20210511222824-ac7d0ebfc235/sync/atomic/value_test.go (about) 1 // Copyright 2014 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. 4 5 package atomic_test 6 7 import ( 8 "math/rand" 9 "runtime" 10 . "sync/atomic" 11 "testing" 12 ) 13 14 func TestValue(t *testing.T) { 15 var v Value 16 if v.Load() != nil { 17 t.Fatal("initial Value is not nil") 18 } 19 v.Store(42) 20 x := v.Load() 21 if xx, ok := x.(int); !ok || xx != 42 { 22 t.Fatalf("wrong value: got %+v, want 42", x) 23 } 24 v.Store(84) 25 x = v.Load() 26 if xx, ok := x.(int); !ok || xx != 84 { 27 t.Fatalf("wrong value: got %+v, want 84", x) 28 } 29 } 30 31 func TestValueLarge(t *testing.T) { 32 var v Value 33 v.Store("foo") 34 x := v.Load() 35 if xx, ok := x.(string); !ok || xx != "foo" { 36 t.Fatalf("wrong value: got %+v, want foo", x) 37 } 38 v.Store("barbaz") 39 x = v.Load() 40 if xx, ok := x.(string); !ok || xx != "barbaz" { 41 t.Fatalf("wrong value: got %+v, want barbaz", x) 42 } 43 } 44 45 func TestValuePanic(t *testing.T) { 46 const nilErr = "sync/atomic: store of nil value into Value" 47 const badErr = "sync/atomic: store of inconsistently typed value into Value" 48 var v Value 49 func() { 50 defer func() { 51 err := recover() 52 if err != nilErr { 53 t.Fatalf("inconsistent store panic: got '%v', want '%v'", err, nilErr) 54 } 55 }() 56 v.Store(nil) 57 }() 58 v.Store(42) 59 func() { 60 defer func() { 61 err := recover() 62 if err != badErr { 63 t.Fatalf("inconsistent store panic: got '%v', want '%v'", err, badErr) 64 } 65 }() 66 v.Store("foo") 67 }() 68 func() { 69 defer func() { 70 err := recover() 71 if err != nilErr { 72 t.Fatalf("inconsistent store panic: got '%v', want '%v'", err, nilErr) 73 } 74 }() 75 v.Store(nil) 76 }() 77 } 78 79 func TestValueConcurrent(t *testing.T) { 80 tests := [][]interface{}{ 81 {uint16(0), ^uint16(0), uint16(1 + 2<<8), uint16(3 + 4<<8)}, 82 {uint32(0), ^uint32(0), uint32(1 + 2<<16), uint32(3 + 4<<16)}, 83 {uint64(0), ^uint64(0), uint64(1 + 2<<32), uint64(3 + 4<<32)}, 84 {complex(0, 0), complex(1, 2), complex(3, 4), complex(5, 6)}, 85 } 86 p := 4 * runtime.GOMAXPROCS(0) 87 N := int(1e5) 88 if testing.Short() { 89 p /= 2 90 N = 1e3 91 } 92 for _, test := range tests { 93 var v Value 94 done := make(chan bool, p) 95 for i := 0; i < p; i++ { 96 go func() { 97 r := rand.New(rand.NewSource(rand.Int63())) 98 expected := true 99 loop: 100 for j := 0; j < N; j++ { 101 x := test[r.Intn(len(test))] 102 v.Store(x) 103 x = v.Load() 104 for _, x1 := range test { 105 if x == x1 { 106 continue loop 107 } 108 } 109 t.Logf("loaded unexpected value %+v, want %+v", x, test) 110 expected = false 111 break 112 } 113 done <- expected 114 }() 115 } 116 for i := 0; i < p; i++ { 117 if !<-done { 118 t.FailNow() 119 } 120 } 121 } 122 } 123 124 func BenchmarkValueRead(b *testing.B) { 125 var v Value 126 v.Store(new(int)) 127 b.RunParallel(func(pb *testing.PB) { 128 for pb.Next() { 129 x := v.Load().(*int) 130 if *x != 0 { 131 b.Fatalf("wrong value: got %v, want 0", *x) 132 } 133 } 134 }) 135 }