github.com/yaling888/clash@v1.53.0/common/singledo/singledo_test.go (about) 1 package singledo 2 3 import ( 4 "sync" 5 "testing" 6 "time" 7 8 "github.com/stretchr/testify/assert" 9 "go.uber.org/atomic" 10 ) 11 12 func TestBasic(t *testing.T) { 13 single := NewSingle[int](time.Millisecond * 30) 14 foo := 0 15 shardCount := atomic.NewInt32(0) 16 call := func() (int, error) { 17 foo++ 18 time.Sleep(time.Millisecond * 5) 19 return 0, nil 20 } 21 22 var wg sync.WaitGroup 23 const n = 5 24 wg.Add(n) 25 for i := 0; i < n; i++ { 26 go func() { 27 _, _, shard := single.Do(call) 28 if shard { 29 shardCount.Inc() 30 } 31 wg.Done() 32 }() 33 } 34 35 wg.Wait() 36 assert.Equal(t, 1, foo) 37 assert.Equal(t, int32(4), shardCount.Load()) 38 } 39 40 func TestTimer(t *testing.T) { 41 single := NewSingle[int](time.Millisecond * 30) 42 foo := 0 43 callM := func() (int, error) { 44 foo++ 45 return 0, nil 46 } 47 48 _, _, _ = single.Do(callM) 49 time.Sleep(10 * time.Millisecond) 50 _, _, shard := single.Do(callM) 51 52 assert.Equal(t, 1, foo) 53 assert.True(t, shard) 54 } 55 56 func TestReset(t *testing.T) { 57 single := NewSingle[int](time.Millisecond * 30) 58 foo := 0 59 callM := func() (int, error) { 60 foo++ 61 return 0, nil 62 } 63 64 _, _, _ = single.Do(callM) 65 single.Reset() 66 _, _, _ = single.Do(callM) 67 68 assert.Equal(t, 2, foo) 69 } 70 71 func TestGroup_Do(t *testing.T) { 72 g := &Group[string]{} 73 key := "1" 74 type args struct { 75 key string 76 fn func() (string, error) 77 } 78 tests := []struct { 79 name string 80 args args 81 wantV string 82 wantErr error 83 wantShared bool 84 }{ 85 { 86 name: "1", 87 args: args{ 88 key: key, 89 fn: func() (string, error) { 90 time.Sleep(time.Millisecond * 30) 91 return "1", nil 92 }, 93 }, 94 wantV: "1", 95 wantErr: nil, 96 wantShared: false, 97 }, 98 { 99 name: "2", 100 args: args{ 101 key: key, 102 fn: func() (string, error) { 103 return "2", nil 104 }, 105 }, 106 wantV: "1", 107 wantErr: nil, 108 wantShared: true, 109 }, 110 { 111 name: "3", 112 args: args{ 113 key: key, 114 fn: func() (string, error) { 115 time.Sleep(time.Millisecond * 30) 116 return "3", nil 117 }, 118 }, 119 wantV: "3", 120 wantErr: nil, 121 wantShared: false, 122 }, 123 { 124 name: "4", 125 args: args{ 126 key: key, 127 fn: func() (string, error) { 128 return "4", nil 129 }, 130 }, 131 wantV: "3", 132 wantErr: nil, 133 wantShared: true, 134 }, 135 { 136 name: "5", 137 args: args{ 138 key: key, 139 fn: func() (string, error) { 140 return "5", nil 141 }, 142 }, 143 wantV: "3", 144 wantErr: nil, 145 wantShared: true, 146 }, 147 } 148 149 for _, tt := range tests { 150 if tt.name == "3" { 151 g.Forget(key) 152 } 153 154 t.Run(tt.name, func(t *testing.T) { 155 gotV, gotErr, gotShared := g.Do(tt.args.key, tt.args.fn) 156 assert.Equalf(t, tt.wantV, gotV, "Do(%v, %v)", tt.args.key, tt.args.fn) 157 assert.Equalf(t, tt.wantErr, gotErr, "Do(%v, %v)", tt.args.key, tt.args.fn) 158 assert.Equalf(t, tt.wantShared, gotShared, "Do(%v, %v)", tt.args.key, tt.args.fn) 159 }) 160 } 161 }