blob: 1eec8d18ea52e93aec5c6d115d30227ad3b383fb [file] [log] [blame]
Rob Pike895c5db2010-08-05 13:31:10 +10001// 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
Dmitriy Vyukov801f6e62012-09-20 23:29:29 +040018func run(t *testing.T, once *Once, o *one, c chan bool) {
Rob Pike895c5db2010-08-05 13:31:10 +100019 once.Do(func() { o.Increment() })
Dmitriy Vyukov801f6e62012-09-20 23:29:29 +040020 if v := *o; v != 1 {
21 t.Errorf("once failed inside run: %d is not 1", v)
22 }
Rob Pike895c5db2010-08-05 13:31:10 +100023 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++ {
Dmitriy Vyukov801f6e62012-09-20 23:29:29 +040032 go run(t, once, o, c)
Rob Pike895c5db2010-08-05 13:31:10 +100033 }
34 for i := 0; i < N; i++ {
35 <-c
36 }
37 if *o != 1 {
Dmitriy Vyukov801f6e62012-09-20 23:29:29 +040038 t.Errorf("once failed outside run: %d is not 1", *o)
Rob Pike895c5db2010-08-05 13:31:10 +100039 }
40}
Dmitriy Vyukov3a4a5812011-06-27 16:02:13 -040041
Dmitriy Vyukov801f6e62012-09-20 23:29:29 +040042func TestOncePanic(t *testing.T) {
Josh Bleecher Snyderf1abe0d2014-09-16 14:22:33 -070043 var once Once
44 func() {
45 defer func() {
46 if r := recover(); r == nil {
47 t.Fatalf("Once.Do did not panic")
48 }
Dmitriy Vyukov801f6e62012-09-20 23:29:29 +040049 }()
Josh Bleecher Snyderf1abe0d2014-09-16 14:22:33 -070050 once.Do(func() {
51 panic("failed")
52 })
53 }()
54
Dmitriy Vyukov801f6e62012-09-20 23:29:29 +040055 once.Do(func() {
Josh Bleecher Snyderf1abe0d2014-09-16 14:22:33 -070056 t.Fatalf("Once.Do called twice")
Dmitriy Vyukov801f6e62012-09-20 23:29:29 +040057 })
58}
59
Dmitriy Vyukov3a4a5812011-06-27 16:02:13 -040060func BenchmarkOnce(b *testing.B) {
Dmitriy Vyukov3a4a5812011-06-27 16:02:13 -040061 var once Once
62 f := func() {}
Dmitriy Vyukovec0c9f22014-02-25 14:39:12 +040063 b.RunParallel(func(pb *testing.PB) {
64 for pb.Next() {
65 once.Do(f)
66 }
67 })
Dmitriy Vyukov3a4a5812011-06-27 16:02:13 -040068}