lockedcalls_test.go 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. package syncx
  2. import (
  3. "errors"
  4. "fmt"
  5. "sync"
  6. "testing"
  7. "time"
  8. )
  9. func TestLockedCallDo(t *testing.T) {
  10. g := NewLockedCalls()
  11. v, err := g.Do("key", func() (interface{}, error) {
  12. return "bar", nil
  13. })
  14. if got, want := fmt.Sprintf("%v (%T)", v, v), "bar (string)"; got != want {
  15. t.Errorf("Do = %v; want %v", got, want)
  16. }
  17. if err != nil {
  18. t.Errorf("Do error = %v", err)
  19. }
  20. }
  21. func TestLockedCallDoErr(t *testing.T) {
  22. g := NewLockedCalls()
  23. someErr := errors.New("some error")
  24. v, err := g.Do("key", func() (interface{}, error) {
  25. return nil, someErr
  26. })
  27. if err != someErr {
  28. t.Errorf("Do error = %v; want someErr", err)
  29. }
  30. if v != nil {
  31. t.Errorf("unexpected non-nil value %#v", v)
  32. }
  33. }
  34. func TestLockedCallDoDupSuppress(t *testing.T) {
  35. g := NewLockedCalls()
  36. c := make(chan string)
  37. var calls int
  38. fn := func() (interface{}, error) {
  39. calls++
  40. ret := calls
  41. <-c
  42. calls--
  43. return ret, nil
  44. }
  45. const n = 10
  46. var results []int
  47. var lock sync.Mutex
  48. var wg sync.WaitGroup
  49. for i := 0; i < n; i++ {
  50. wg.Add(1)
  51. go func() {
  52. v, err := g.Do("key", fn)
  53. if err != nil {
  54. t.Errorf("Do error: %v", err)
  55. }
  56. lock.Lock()
  57. results = append(results, v.(int))
  58. lock.Unlock()
  59. wg.Done()
  60. }()
  61. }
  62. time.Sleep(100 * time.Millisecond) // let goroutines above block
  63. for i := 0; i < n; i++ {
  64. c <- "bar"
  65. }
  66. wg.Wait()
  67. lock.Lock()
  68. defer lock.Unlock()
  69. for _, item := range results {
  70. if item != 1 {
  71. t.Errorf("number of calls = %d; want 1", item)
  72. }
  73. }
  74. }