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  }