github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/sync/once_test.go (about)

     1  package sync_test
     2  
     3  import (
     4  	"sync"
     5  	"testing"
     6  )
     7  
     8  // TestOnceUncontended tests Once on a single goroutine.
     9  func TestOnceUncontended(t *testing.T) {
    10  	var once sync.Once
    11  	{
    12  		var ran bool
    13  		once.Do(func() {
    14  			ran = true
    15  		})
    16  		if !ran {
    17  			t.Error("first call to Do did not run")
    18  		}
    19  	}
    20  	{
    21  		var ran bool
    22  		once.Do(func() {
    23  			ran = true
    24  		})
    25  		if ran {
    26  			t.Error("second call to Do ran")
    27  		}
    28  	}
    29  }
    30  
    31  // TestOnceConcurrent tests multiple concurrent invocations of sync.Once.
    32  func TestOnceConcurrent(t *testing.T) {
    33  	var once sync.Once
    34  	var mu sync.Mutex
    35  	mu.Lock()
    36  	var ran bool
    37  	var ranTwice bool
    38  	once.Do(func() {
    39  		ran = true
    40  
    41  		// Start a goroutine and (approximately) wait for it to enter the call to Do.
    42  		var startWait sync.Mutex
    43  		startWait.Lock()
    44  		go func() {
    45  			startWait.Unlock()
    46  			once.Do(func() {
    47  				ranTwice = true
    48  			})
    49  			mu.Unlock()
    50  		}()
    51  		startWait.Lock()
    52  	})
    53  	if !ran {
    54  		t.Error("first call to Do did not run")
    55  	}
    56  
    57  	// Wait for the goroutine to finish.
    58  	mu.Lock()
    59  	if ranTwice {
    60  		t.Error("second concurrent call to Once also ran")
    61  	}
    62  }