123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- package syncx
- import (
- "errors"
- "fmt"
- "sync"
- "sync/atomic"
- "testing"
- "time"
- )
- func TestExclusiveCallDo(t *testing.T) {
- g := NewSharedCalls()
- v, err := g.Do("key", func() (interface{}, error) {
- return "bar", nil
- })
- if got, want := fmt.Sprintf("%v (%T)", v, v), "bar (string)"; got != want {
- t.Errorf("Do = %v; want %v", got, want)
- }
- if err != nil {
- t.Errorf("Do error = %v", err)
- }
- }
- func TestExclusiveCallDoErr(t *testing.T) {
- g := NewSharedCalls()
- someErr := errors.New("some error")
- v, err := g.Do("key", func() (interface{}, error) {
- return nil, someErr
- })
- if err != someErr {
- t.Errorf("Do error = %v; want someErr", err)
- }
- if v != nil {
- t.Errorf("unexpected non-nil value %#v", v)
- }
- }
- func TestExclusiveCallDoDupSuppress(t *testing.T) {
- g := NewSharedCalls()
- c := make(chan string)
- var calls int32
- fn := func() (interface{}, error) {
- atomic.AddInt32(&calls, 1)
- return <-c, nil
- }
- const n = 10
- var wg sync.WaitGroup
- for i := 0; i < n; i++ {
- wg.Add(1)
- go func() {
- v, err := g.Do("key", fn)
- if err != nil {
- t.Errorf("Do error: %v", err)
- }
- if v.(string) != "bar" {
- t.Errorf("got %q; want %q", v, "bar")
- }
- wg.Done()
- }()
- }
- time.Sleep(100 * time.Millisecond) // let goroutines above block
- c <- "bar"
- wg.Wait()
- if got := atomic.LoadInt32(&calls); got != 1 {
- t.Errorf("number of calls = %d; want 1", got)
- }
- }
- func TestExclusiveCallDoExDupSuppress(t *testing.T) {
- g := NewSharedCalls()
- c := make(chan string)
- var calls int32
- fn := func() (interface{}, error) {
- atomic.AddInt32(&calls, 1)
- return <-c, nil
- }
- const n = 10
- var wg sync.WaitGroup
- var freshes int32
- for i := 0; i < n; i++ {
- wg.Add(1)
- go func() {
- v, fresh, err := g.DoEx("key", fn)
- if err != nil {
- t.Errorf("Do error: %v", err)
- }
- if fresh {
- atomic.AddInt32(&freshes, 1)
- }
- if v.(string) != "bar" {
- t.Errorf("got %q; want %q", v, "bar")
- }
- wg.Done()
- }()
- }
- time.Sleep(100 * time.Millisecond) // let goroutines above block
- c <- "bar"
- wg.Wait()
- if got := atomic.LoadInt32(&calls); got != 1 {
- t.Errorf("number of calls = %d; want 1", got)
- }
- if got := atomic.LoadInt32(&freshes); got != 1 {
- t.Errorf("freshes = %d; want 1", got)
- }
- }
|