dd931d9b48
Reviewed-on: https://go-review.googlesource.com/136435 gotools/: * Makefile.am (mostlyclean-local): Run chmod on check-go-dir to make sure it is writable. (check-go-tools): Likewise. (check-vet): Copy internal/objabi to check-vet-dir. * Makefile.in: Rebuild. From-SVN: r264546
134 lines
2.8 KiB
Go
134 lines
2.8 KiB
Go
// Copyright 2014 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package atomic_test
|
|
|
|
import (
|
|
"math/rand"
|
|
"runtime"
|
|
. "sync/atomic"
|
|
"testing"
|
|
)
|
|
|
|
func TestValue(t *testing.T) {
|
|
var v Value
|
|
if v.Load() != nil {
|
|
t.Fatal("initial Value is not nil")
|
|
}
|
|
v.Store(42)
|
|
x := v.Load()
|
|
if xx, ok := x.(int); !ok || xx != 42 {
|
|
t.Fatalf("wrong value: got %+v, want 42", x)
|
|
}
|
|
v.Store(84)
|
|
x = v.Load()
|
|
if xx, ok := x.(int); !ok || xx != 84 {
|
|
t.Fatalf("wrong value: got %+v, want 84", x)
|
|
}
|
|
}
|
|
|
|
func TestValueLarge(t *testing.T) {
|
|
var v Value
|
|
v.Store("foo")
|
|
x := v.Load()
|
|
if xx, ok := x.(string); !ok || xx != "foo" {
|
|
t.Fatalf("wrong value: got %+v, want foo", x)
|
|
}
|
|
v.Store("barbaz")
|
|
x = v.Load()
|
|
if xx, ok := x.(string); !ok || xx != "barbaz" {
|
|
t.Fatalf("wrong value: got %+v, want barbaz", x)
|
|
}
|
|
}
|
|
|
|
func TestValuePanic(t *testing.T) {
|
|
const nilErr = "sync/atomic: store of nil value into Value"
|
|
const badErr = "sync/atomic: store of inconsistently typed value into Value"
|
|
var v Value
|
|
func() {
|
|
defer func() {
|
|
err := recover()
|
|
if err != nilErr {
|
|
t.Fatalf("inconsistent store panic: got '%v', want '%v'", err, nilErr)
|
|
}
|
|
}()
|
|
v.Store(nil)
|
|
}()
|
|
v.Store(42)
|
|
func() {
|
|
defer func() {
|
|
err := recover()
|
|
if err != badErr {
|
|
t.Fatalf("inconsistent store panic: got '%v', want '%v'", err, badErr)
|
|
}
|
|
}()
|
|
v.Store("foo")
|
|
}()
|
|
func() {
|
|
defer func() {
|
|
err := recover()
|
|
if err != nilErr {
|
|
t.Fatalf("inconsistent store panic: got '%v', want '%v'", err, nilErr)
|
|
}
|
|
}()
|
|
v.Store(nil)
|
|
}()
|
|
}
|
|
|
|
func TestValueConcurrent(t *testing.T) {
|
|
tests := [][]interface{}{
|
|
{uint16(0), ^uint16(0), uint16(1 + 2<<8), uint16(3 + 4<<8)},
|
|
{uint32(0), ^uint32(0), uint32(1 + 2<<16), uint32(3 + 4<<16)},
|
|
{uint64(0), ^uint64(0), uint64(1 + 2<<32), uint64(3 + 4<<32)},
|
|
{complex(0, 0), complex(1, 2), complex(3, 4), complex(5, 6)},
|
|
}
|
|
p := 4 * runtime.GOMAXPROCS(0)
|
|
N := int(1e5)
|
|
if testing.Short() {
|
|
p /= 2
|
|
N = 1e3
|
|
}
|
|
for _, test := range tests {
|
|
var v Value
|
|
done := make(chan bool)
|
|
for i := 0; i < p; i++ {
|
|
go func() {
|
|
r := rand.New(rand.NewSource(rand.Int63()))
|
|
loop:
|
|
for j := 0; j < N; j++ {
|
|
x := test[r.Intn(len(test))]
|
|
v.Store(x)
|
|
x = v.Load()
|
|
for _, x1 := range test {
|
|
if x == x1 {
|
|
continue loop
|
|
}
|
|
}
|
|
t.Logf("loaded unexpected value %+v, want %+v", x, test)
|
|
done <- false
|
|
}
|
|
done <- true
|
|
}()
|
|
}
|
|
for i := 0; i < p; i++ {
|
|
if !<-done {
|
|
t.FailNow()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkValueRead(b *testing.B) {
|
|
var v Value
|
|
v.Store(new(int))
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
for pb.Next() {
|
|
x := v.Load().(*int)
|
|
if *x != 0 {
|
|
b.Fatalf("wrong value: got %v, want 0", *x)
|
|
}
|
|
}
|
|
})
|
|
}
|