您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

88 行
1.8 KiB

  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. package singleflight
  5. import (
  6. "errors"
  7. "fmt"
  8. "sync"
  9. "sync/atomic"
  10. "testing"
  11. "time"
  12. )
  13. func TestDo(t *testing.T) {
  14. var g Group
  15. v, err, _ := g.Do("key", func() (interface{}, error) {
  16. return "bar", nil
  17. })
  18. if got, want := fmt.Sprintf("%v (%T)", v, v), "bar (string)"; got != want {
  19. t.Errorf("Do = %v; want %v", got, want)
  20. }
  21. if err != nil {
  22. t.Errorf("Do error = %v", err)
  23. }
  24. }
  25. func TestDoErr(t *testing.T) {
  26. var g Group
  27. someErr := errors.New("Some error")
  28. v, err, _ := g.Do("key", func() (interface{}, error) {
  29. return nil, someErr
  30. })
  31. if err != someErr {
  32. t.Errorf("Do error = %v; want someErr %v", err, someErr)
  33. }
  34. if v != nil {
  35. t.Errorf("unexpected non-nil value %#v", v)
  36. }
  37. }
  38. func TestDoDupSuppress(t *testing.T) {
  39. var g Group
  40. var wg1, wg2 sync.WaitGroup
  41. c := make(chan string, 1)
  42. var calls int32
  43. fn := func() (interface{}, error) {
  44. if atomic.AddInt32(&calls, 1) == 1 {
  45. // First invocation.
  46. wg1.Done()
  47. }
  48. v := <-c
  49. c <- v // pump; make available for any future calls
  50. time.Sleep(10 * time.Millisecond) // let more goroutines enter Do
  51. return v, nil
  52. }
  53. const n = 10
  54. wg1.Add(1)
  55. for i := 0; i < n; i++ {
  56. wg1.Add(1)
  57. wg2.Add(1)
  58. go func() {
  59. defer wg2.Done()
  60. wg1.Done()
  61. v, err, _ := g.Do("key", fn)
  62. if err != nil {
  63. t.Errorf("Do error: %v", err)
  64. return
  65. }
  66. if s, _ := v.(string); s != "bar" {
  67. t.Errorf("Do = %T %v; want %q", v, v, "bar")
  68. }
  69. }()
  70. }
  71. wg1.Wait()
  72. // At least one goroutine is in fn now and all of them have at
  73. // least reached the line before the Do.
  74. c <- "bar"
  75. wg2.Wait()
  76. if got := atomic.LoadInt32(&calls); got <= 0 || got >= n {
  77. t.Errorf("number of calls = %d; want over 0 and less than %d", got, n)
  78. }
  79. }