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  }