google.golang.org/grpc@v1.62.1/internal/grpcsync/oncefunc_test.go (about)

     1  /*
     2   *
     3   * Copyright 2022 gRPC authors.
     4   *
     5   * Licensed under the Apache License, Version 2.0 (the "License");
     6   * you may not use this file except in compliance with the License.
     7   * You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   *
    17   */
    18  
    19  package grpcsync
    20  
    21  import (
    22  	"sync"
    23  	"sync/atomic"
    24  	"testing"
    25  	"time"
    26  )
    27  
    28  // TestOnceFunc tests that a OnceFunc is executed only once even with multiple
    29  // simultaneous callers of it.
    30  func (s) TestOnceFunc(t *testing.T) {
    31  	var v int32
    32  	inc := OnceFunc(func() { atomic.AddInt32(&v, 1) })
    33  
    34  	const numWorkers = 100
    35  	var wg sync.WaitGroup // Blocks until all workers have called inc.
    36  	wg.Add(numWorkers)
    37  
    38  	block := NewEvent() // Signal to worker goroutines to call inc
    39  
    40  	for i := 0; i < numWorkers; i++ {
    41  		go func() {
    42  			<-block.Done() // Wait for a signal.
    43  			inc()          // Call the OnceFunc.
    44  			wg.Done()
    45  		}()
    46  	}
    47  	time.Sleep(time.Millisecond) // Allow goroutines to get to the block.
    48  	block.Fire()                 // Unblock them.
    49  	wg.Wait()                    // Wait for them to complete.
    50  	if v != 1 {
    51  		t.Fatalf("OnceFunc() called %v times; want 1", v)
    52  	}
    53  }