golang.org/x/build@v0.0.0-20240506185731-218518f32b70/internal/singleflight/singleflight_test.go (about)

     1  // Copyright 2013 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 singleflight
     6  
     7  import (
     8  	"errors"
     9  	"fmt"
    10  	"sync"
    11  	"sync/atomic"
    12  	"testing"
    13  	"time"
    14  )
    15  
    16  func TestDo(t *testing.T) {
    17  	var g Group
    18  	v, err, _ := g.Do("key", func() (interface{}, error) {
    19  		return "bar", nil
    20  	})
    21  	if got, want := fmt.Sprintf("%v (%T)", v, v), "bar (string)"; got != want {
    22  		t.Errorf("Do = %v; want %v", got, want)
    23  	}
    24  	if err != nil {
    25  		t.Errorf("Do error = %v", err)
    26  	}
    27  }
    28  
    29  func TestDoErr(t *testing.T) {
    30  	var g Group
    31  	someErr := errors.New("Some error")
    32  	v, err, _ := g.Do("key", func() (interface{}, error) {
    33  		return nil, someErr
    34  	})
    35  	if err != someErr {
    36  		t.Errorf("Do error = %v; want someErr %v", err, someErr)
    37  	}
    38  	if v != nil {
    39  		t.Errorf("unexpected non-nil value %#v", v)
    40  	}
    41  }
    42  
    43  func TestDoDupSuppress(t *testing.T) {
    44  	var g Group
    45  	c := make(chan string)
    46  	var calls int32
    47  	fn := func() (interface{}, error) {
    48  		atomic.AddInt32(&calls, 1)
    49  		return <-c, nil
    50  	}
    51  
    52  	const n = 10
    53  	var wg sync.WaitGroup
    54  	for i := 0; i < n; i++ {
    55  		wg.Add(1)
    56  		go func() {
    57  			v, err, _ := g.Do("key", fn)
    58  			if err != nil {
    59  				t.Errorf("Do error: %v", err)
    60  			}
    61  			if v.(string) != "bar" {
    62  				t.Errorf("got %q; want %q", v, "bar")
    63  			}
    64  			wg.Done()
    65  		}()
    66  	}
    67  	time.Sleep(100 * time.Millisecond) // let goroutines above block
    68  	c <- "bar"
    69  	wg.Wait()
    70  	if got := atomic.LoadInt32(&calls); got != 1 {
    71  		t.Errorf("number of calls = %d; want 1", got)
    72  	}
    73  }