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  // }