github.com/spotify/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/pkg/sync/once_test.go (about) 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. 4 5 package sync_test 6 7 import ( 8 "runtime" 9 . "sync" 10 "sync/atomic" 11 "testing" 12 ) 13 14 type one int 15 16 func (o *one) Increment() { 17 *o++ 18 } 19 20 func run(t *testing.T, once *Once, o *one, c chan bool) { 21 once.Do(func() { o.Increment() }) 22 if v := *o; v != 1 { 23 t.Errorf("once failed inside run: %d is not 1", v) 24 } 25 c <- true 26 } 27 28 func TestOnce(t *testing.T) { 29 o := new(one) 30 once := new(Once) 31 c := make(chan bool) 32 const N = 10 33 for i := 0; i < N; i++ { 34 go run(t, once, o, c) 35 } 36 for i := 0; i < N; i++ { 37 <-c 38 } 39 if *o != 1 { 40 t.Errorf("once failed outside run: %d is not 1", *o) 41 } 42 } 43 44 func TestOncePanic(t *testing.T) { 45 once := new(Once) 46 for i := 0; i < 2; i++ { 47 func() { 48 defer func() { 49 if recover() == nil { 50 t.Fatalf("Once.Do() has not panic'ed") 51 } 52 }() 53 once.Do(func() { 54 panic("failed") 55 }) 56 }() 57 } 58 once.Do(func() {}) 59 once.Do(func() { 60 t.Fatalf("Once called twice") 61 }) 62 } 63 64 func BenchmarkOnce(b *testing.B) { 65 const CallsPerSched = 1000 66 procs := runtime.GOMAXPROCS(-1) 67 N := int32(b.N / CallsPerSched) 68 var once Once 69 f := func() {} 70 c := make(chan bool, procs) 71 for p := 0; p < procs; p++ { 72 go func() { 73 for atomic.AddInt32(&N, -1) >= 0 { 74 runtime.Gosched() 75 for g := 0; g < CallsPerSched; g++ { 76 once.Do(f) 77 } 78 } 79 c <- true 80 }() 81 } 82 for p := 0; p < procs; p++ { 83 <-c 84 } 85 }