github.com/c12o16h1/go/src@v0.0.0-20200114212001-5a151c0f00ed/sync/map_test.go (about) 1 // Copyright 2016 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 sync_test 6 7 import ( 8 "math/rand" 9 "reflect" 10 "runtime" 11 "sync" 12 "testing" 13 "testing/quick" 14 ) 15 16 type mapOp string 17 18 const ( 19 opLoad = mapOp("Load") 20 opStore = mapOp("Store") 21 opLoadOrStore = mapOp("LoadOrStore") 22 opDelete = mapOp("Delete") 23 ) 24 25 var mapOps = [...]mapOp{opLoad, opStore, opLoadOrStore, opDelete} 26 27 // mapCall is a quick.Generator for calls on mapInterface. 28 type mapCall struct { 29 op mapOp 30 k, v interface{} 31 } 32 33 func (c mapCall) apply(m mapInterface) (interface{}, bool) { 34 switch c.op { 35 case opLoad: 36 return m.Load(c.k) 37 case opStore: 38 m.Store(c.k, c.v) 39 return nil, false 40 case opLoadOrStore: 41 return m.LoadOrStore(c.k, c.v) 42 case opDelete: 43 m.Delete(c.k) 44 return nil, false 45 default: 46 panic("invalid mapOp") 47 } 48 } 49 50 type mapResult struct { 51 value interface{} 52 ok bool 53 } 54 55 func randValue(r *rand.Rand) interface{} { 56 b := make([]byte, r.Intn(4)) 57 for i := range b { 58 b[i] = 'a' + byte(rand.Intn(26)) 59 } 60 return string(b) 61 } 62 63 func (mapCall) Generate(r *rand.Rand, size int) reflect.Value { 64 c := mapCall{op: mapOps[rand.Intn(len(mapOps))], k: randValue(r)} 65 switch c.op { 66 case opStore, opLoadOrStore: 67 c.v = randValue(r) 68 } 69 return reflect.ValueOf(c) 70 } 71 72 func applyCalls(m mapInterface, calls []mapCall) (results []mapResult, final map[interface{}]interface{}) { 73 for _, c := range calls { 74 v, ok := c.apply(m) 75 results = append(results, mapResult{v, ok}) 76 } 77 78 final = make(map[interface{}]interface{}) 79 m.Range(func(k, v interface{}) bool { 80 final[k] = v 81 return true 82 }) 83 84 return results, final 85 } 86 87 func applyMap(calls []mapCall) ([]mapResult, map[interface{}]interface{}) { 88 return applyCalls(new(sync.Map), calls) 89 } 90 91 func applyRWMutexMap(calls []mapCall) ([]mapResult, map[interface{}]interface{}) { 92 return applyCalls(new(RWMutexMap), calls) 93 } 94 95 func applyDeepCopyMap(calls []mapCall) ([]mapResult, map[interface{}]interface{}) { 96 return applyCalls(new(DeepCopyMap), calls) 97 } 98 99 func TestMapMatchesRWMutex(t *testing.T) { 100 if err := quick.CheckEqual(applyMap, applyRWMutexMap, nil); err != nil { 101 t.Error(err) 102 } 103 } 104 105 func TestMapMatchesDeepCopy(t *testing.T) { 106 if err := quick.CheckEqual(applyMap, applyDeepCopyMap, nil); err != nil { 107 t.Error(err) 108 } 109 } 110 111 func TestConcurrentRange(t *testing.T) { 112 const mapSize = 1 << 10 113 114 m := new(sync.Map) 115 for n := int64(1); n <= mapSize; n++ { 116 m.Store(n, int64(n)) 117 } 118 119 done := make(chan struct{}) 120 var wg sync.WaitGroup 121 defer func() { 122 close(done) 123 wg.Wait() 124 }() 125 for g := int64(runtime.GOMAXPROCS(0)); g > 0; g-- { 126 r := rand.New(rand.NewSource(g)) 127 wg.Add(1) 128 go func(g int64) { 129 defer wg.Done() 130 for i := int64(0); ; i++ { 131 select { 132 case <-done: 133 return 134 default: 135 } 136 for n := int64(1); n < mapSize; n++ { 137 if r.Int63n(mapSize) == 0 { 138 m.Store(n, n*i*g) 139 } else { 140 m.Load(n) 141 } 142 } 143 } 144 }(g) 145 } 146 147 iters := 1 << 10 148 if testing.Short() { 149 iters = 16 150 } 151 for n := iters; n > 0; n-- { 152 seen := make(map[int64]bool, mapSize) 153 154 m.Range(func(ki, vi interface{}) bool { 155 k, v := ki.(int64), vi.(int64) 156 if v%k != 0 { 157 t.Fatalf("while Storing multiples of %v, Range saw value %v", k, v) 158 } 159 if seen[k] { 160 t.Fatalf("Range visited key %v twice", k) 161 } 162 seen[k] = true 163 return true 164 }) 165 166 if len(seen) != mapSize { 167 t.Fatalf("Range visited %v elements of %v-element Map", len(seen), mapSize) 168 } 169 } 170 }