...
1
16
17 package singleflight
18
19 import (
20 "errors"
21 "fmt"
22 "sync"
23 "sync/atomic"
24 "testing"
25 "time"
26 )
27
28 func TestDo(t *testing.T) {
29 var g Group
30 v, err := g.Do("key", func() (interface{}, error) {
31 return "bar", nil
32 })
33 if got, want := fmt.Sprintf("%v (%T)", v, v), "bar (string)"; got != want {
34 t.Errorf("Do = %v; want %v", got, want)
35 }
36 if err != nil {
37 t.Errorf("Do error = %v", err)
38 }
39 }
40
41 func TestDoErr(t *testing.T) {
42 var g Group
43 someErr := errors.New("some error")
44 v, err := g.Do("key", func() (interface{}, error) {
45 return nil, someErr
46 })
47 if err != someErr {
48 t.Errorf("Do error = %v; want someErr", err)
49 }
50 if v != nil {
51 t.Errorf("unexpected non-nil value %#v", v)
52 }
53 }
54
55 func TestDoDupSuppress(t *testing.T) {
56 var g Group
57 c := make(chan string)
58 var calls int32
59 fn := func() (interface{}, error) {
60 atomic.AddInt32(&calls, 1)
61 return <-c, nil
62 }
63
64 const n = 10
65 var wg sync.WaitGroup
66 for i := 0; i < n; i++ {
67 wg.Add(1)
68 go func() {
69 v, err := g.Do("key", fn)
70 if err != nil {
71 t.Errorf("Do error: %v", err)
72 }
73 if v.(string) != "bar" {
74 t.Errorf("got %q; want %q", v, "bar")
75 }
76 wg.Done()
77 }()
78 }
79 time.Sleep(100 * time.Millisecond)
80 c <- "bar"
81 wg.Wait()
82 if got := atomic.LoadInt32(&calls); got != 1 {
83 t.Errorf("number of calls = %d; want 1", got)
84 }
85 }
86
View as plain text