Home | History | Annotate | Download | only in sync
      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 	. "sync"
      9 	"testing"
     10 )
     11 
     12 type one int
     13 
     14 func (o *one) Increment() {
     15 	*o++
     16 }
     17 
     18 func run(t *testing.T, once *Once, o *one, c chan bool) {
     19 	once.Do(func() { o.Increment() })
     20 	if v := *o; v != 1 {
     21 		t.Errorf("once failed inside run: %d is not 1", v)
     22 	}
     23 	c <- true
     24 }
     25 
     26 func TestOnce(t *testing.T) {
     27 	o := new(one)
     28 	once := new(Once)
     29 	c := make(chan bool)
     30 	const N = 10
     31 	for i := 0; i < N; i++ {
     32 		go run(t, once, o, c)
     33 	}
     34 	for i := 0; i < N; i++ {
     35 		<-c
     36 	}
     37 	if *o != 1 {
     38 		t.Errorf("once failed outside run: %d is not 1", *o)
     39 	}
     40 }
     41 
     42 func TestOncePanic(t *testing.T) {
     43 	var once Once
     44 	func() {
     45 		defer func() {
     46 			if r := recover(); r == nil {
     47 				t.Fatalf("Once.Do did not panic")
     48 			}
     49 		}()
     50 		once.Do(func() {
     51 			panic("failed")
     52 		})
     53 	}()
     54 
     55 	once.Do(func() {
     56 		t.Fatalf("Once.Do called twice")
     57 	})
     58 }
     59 
     60 func BenchmarkOnce(b *testing.B) {
     61 	var once Once
     62 	f := func() {}
     63 	b.RunParallel(func(pb *testing.PB) {
     64 		for pb.Next() {
     65 			once.Do(f)
     66 		}
     67 	})
     68 }
     69