github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/sync/oncefunc_test.go (about) 1 // Copyright 2022 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 // We assume that the Once.Do tests have already covered parallelism. 13 14 func TestOnceFunc(t *testing.T) { 15 calls := 0 16 f := sync.OnceFunc(func() { calls++ }) 17 allocs := testing.AllocsPerRun(10, f) 18 if calls != 1 { 19 t.Errorf("want calls==1, got %d", calls) 20 } 21 if allocs != 0 { 22 t.Errorf("want 0 allocations per call, got %v", allocs) 23 } 24 } 25 26 func TestOnceValue(t *testing.T) { 27 calls := 0 28 f := sync.OnceValue(func() int { 29 calls++ 30 return calls 31 }) 32 allocs := testing.AllocsPerRun(10, func() { f() }) 33 value := f() 34 if calls != 1 { 35 t.Errorf("want calls==1, got %d", calls) 36 } 37 if value != 1 { 38 t.Errorf("want value==1, got %d", value) 39 } 40 if allocs != 0 { 41 t.Errorf("want 0 allocations per call, got %v", allocs) 42 } 43 } 44 45 func TestOnceValues(t *testing.T) { 46 calls := 0 47 f := sync.OnceValues(func() (int, int) { 48 calls++ 49 return calls, calls + 1 50 }) 51 allocs := testing.AllocsPerRun(10, func() { f() }) 52 v1, v2 := f() 53 if calls != 1 { 54 t.Errorf("want calls==1, got %d", calls) 55 } 56 if v1 != 1 || v2 != 2 { 57 t.Errorf("want v1==1 and v2==2, got %d and %d", v1, v2) 58 } 59 if allocs != 0 { 60 t.Errorf("want 0 allocations per call, got %v", allocs) 61 } 62 } 63 64 // TODO: need to implement more complete panic handling for these tests. 65 // func testOncePanicX(t *testing.T, calls *int, f func()) { 66 // testOncePanicWith(t, calls, f, func(label string, p any) { 67 // if p != "x" { 68 // t.Fatalf("%s: want panic %v, got %v", label, "x", p) 69 // } 70 // }) 71 // } 72 73 // func testOncePanicWith(t *testing.T, calls *int, f func(), check func(label string, p any)) { 74 // // Check that the each call to f panics with the same value, but the 75 // // underlying function is only called once. 76 // for _, label := range []string{"first time", "second time"} { 77 // var p any 78 // panicked := true 79 // func() { 80 // defer func() { 81 // p = recover() 82 // }() 83 // f() 84 // panicked = false 85 // }() 86 // if !panicked { 87 // t.Fatalf("%s: f did not panic", label) 88 // } 89 // check(label, p) 90 // } 91 // if *calls != 1 { 92 // t.Errorf("want calls==1, got %d", *calls) 93 // } 94 // } 95 96 // func TestOnceFuncPanic(t *testing.T) { 97 // calls := 0 98 // f := sync.OnceFunc(func() { 99 // calls++ 100 // panic("x") 101 // }) 102 // testOncePanicX(t, &calls, f) 103 // } 104 105 // func TestOnceValuePanic(t *testing.T) { 106 // calls := 0 107 // f := sync.OnceValue(func() int { 108 // calls++ 109 // panic("x") 110 // }) 111 // testOncePanicX(t, &calls, func() { f() }) 112 // } 113 114 // func TestOnceValuesPanic(t *testing.T) { 115 // calls := 0 116 // f := sync.OnceValues(func() (int, int) { 117 // calls++ 118 // panic("x") 119 // }) 120 // testOncePanicX(t, &calls, func() { f() }) 121 // } 122 // 123 // func TestOnceFuncPanicNil(t *testing.T) { 124 // calls := 0 125 // f := sync.OnceFunc(func() { 126 // calls++ 127 // panic(nil) 128 // }) 129 // testOncePanicWith(t, &calls, f, func(label string, p any) { 130 // switch p.(type) { 131 // case nil, *runtime.PanicNilError: 132 // return 133 // } 134 // t.Fatalf("%s: want nil panic, got %v", label, p) 135 // }) 136 // } 137 // 138 // func TestOnceFuncGoexit(t *testing.T) { 139 // // If f calls Goexit, the results are unspecified. But check that f doesn't 140 // // get called twice. 141 // calls := 0 142 // f := sync.OnceFunc(func() { 143 // calls++ 144 // runtime.Goexit() 145 // }) 146 // var wg sync.WaitGroup 147 // for i := 0; i < 2; i++ { 148 // wg.Add(1) 149 // go func() { 150 // defer wg.Done() 151 // defer func() { recover() }() 152 // f() 153 // }() 154 // wg.Wait() 155 // } 156 // if calls != 1 { 157 // t.Errorf("want calls==1, got %d", calls) 158 // } 159 // }