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
5package sync_test
6
7import (
8	. "sync"
9	"testing"
10)
11
12type one int
13
14func (o *one) Increment() {
15	*o++
16}
17
18func 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
26func 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
42func 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
60func 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