...
Run Format

Source file src/sync/atomic/value_test.go

Documentation: sync/atomic

     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)
    95  		for i := 0; i < p; i++ {
    96  			go func() {
    97  				r := rand.New(rand.NewSource(rand.Int63()))
    98  			loop:
    99  				for j := 0; j < N; j++ {
   100  					x := test[r.Intn(len(test))]
   101  					v.Store(x)
   102  					x = v.Load()
   103  					for _, x1 := range test {
   104  						if x == x1 {
   105  							continue loop
   106  						}
   107  					}
   108  					t.Logf("loaded unexpected value %+v, want %+v", x, test)
   109  					done <- false
   110  				}
   111  				done <- true
   112  			}()
   113  		}
   114  		for i := 0; i < p; i++ {
   115  			if !<-done {
   116  				t.FailNow()
   117  			}
   118  		}
   119  	}
   120  }
   121  
   122  func BenchmarkValueRead(b *testing.B) {
   123  	var v Value
   124  	v.Store(new(int))
   125  	b.RunParallel(func(pb *testing.PB) {
   126  		for pb.Next() {
   127  			x := v.Load().(*int)
   128  			if *x != 0 {
   129  				b.Fatalf("wrong value: got %v, want 0", *x)
   130  			}
   131  		}
   132  	})
   133  }
   134  

View as plain text