github.com/sandwich-go/boost@v1.3.29/xchan/unbounded_chan_test.go (about) 1 package xchan 2 3 import ( 4 "context" 5 "sync" 6 "testing" 7 "time" 8 9 "github.com/stretchr/testify/assert" 10 "go.uber.org/goleak" 11 ) 12 13 func TestMakeUnboundedChan(t *testing.T) { 14 ctx, cancel := context.WithCancel(context.Background()) 15 defer cancel() 16 ch := NewUnboundedChan[int64](ctx, 100) 17 18 for i := 1; i < 200; i++ { 19 ch.In <- int64(i) 20 } 21 22 var count int64 23 var wg sync.WaitGroup 24 wg.Add(1) 25 go func() { 26 defer wg.Done() 27 28 for v := range ch.Out { 29 count += v 30 } 31 }() 32 33 for i := 200; i <= 1000; i++ { 34 ch.In <- int64(i) 35 } 36 close(ch.In) 37 38 wg.Wait() 39 40 if count != 500500 { 41 t.Fatalf("expected 500500 but got %d", count) 42 } 43 } 44 45 func TestMakeUnboundedChanSize(t *testing.T) { 46 ctx, cancel := context.WithCancel(context.Background()) 47 defer cancel() 48 ch := NewUnboundedChanSize[int64](ctx, 10, 50, 100) 49 50 for i := 1; i < 200; i++ { 51 ch.In <- int64(i) 52 } 53 54 var count int64 55 var wg sync.WaitGroup 56 wg.Add(1) 57 go func() { 58 defer wg.Done() 59 60 for v := range ch.Out { 61 count += v 62 } 63 }() 64 65 for i := 200; i <= 1000; i++ { 66 ch.In <- int64(i) 67 } 68 close(ch.In) 69 70 wg.Wait() 71 72 if count != 500500 { 73 t.Fatalf("expected 500500 but got %d", count) 74 } 75 } 76 77 func TestLen_DataRace(t *testing.T) { 78 ctx, cancel := context.WithCancel(context.Background()) 79 defer cancel() 80 ch := NewUnboundedChan[int64](ctx, 1) 81 stop := make(chan bool) 82 wg := &sync.WaitGroup{} 83 for i := 0; i < 100; i++ { // may tweak the number of iterations 84 wg.Add(1) 85 go func(ctx context.Context) { 86 defer wg.Done() 87 for { 88 select { 89 case <-ctx.Done(): 90 return 91 case <-stop: 92 return 93 default: 94 ch.In <- 42 95 <-ch.Out 96 } 97 } 98 }(ctx) 99 } 100 101 for i := 0; i < 10000; i++ { // may tweak the number of iterations 102 ch.Len() 103 } 104 close(stop) 105 wg.Wait() 106 } 107 108 func TestLen(t *testing.T) { 109 ctx, cancel := context.WithCancel(context.Background()) 110 defer cancel() 111 ch := NewUnboundedChanSize[int64](ctx, 10, 50, 100) 112 113 for i := 1; i < 200; i++ { 114 ch.In <- int64(i) 115 } 116 117 // wait ch processing in normal case 118 time.Sleep(time.Second) 119 assert.Equal(t, 0, len(ch.In)) 120 assert.Equal(t, 50, len(ch.Out)) 121 assert.Equal(t, 199, ch.Len()) 122 assert.Equal(t, 149, ch.BufLen()) 123 124 for i := 0; i < 50; i++ { 125 <-ch.Out 126 } 127 128 time.Sleep(time.Second) 129 assert.Equal(t, 0, len(ch.In)) 130 assert.Equal(t, 50, len(ch.Out)) 131 assert.Equal(t, 149, ch.Len()) 132 assert.Equal(t, 99, ch.BufLen()) 133 134 for i := 0; i < 149; i++ { 135 <-ch.Out 136 } 137 138 time.Sleep(time.Second) 139 assert.Equal(t, 0, len(ch.In)) 140 assert.Equal(t, 0, len(ch.Out)) 141 assert.Equal(t, 0, ch.Len()) 142 assert.Equal(t, 0, ch.BufLen()) 143 } 144 145 func TestGetDataWithGoleak(t *testing.T) { 146 defer goleak.VerifyNone(t) 147 ctx, cancel := context.WithCancel(context.Background()) 148 defer cancel() 149 ch := NewUnboundedChanSize[int64](ctx, 10, 50, 100) 150 for i := 1; i < 200; i++ { 151 ch.In <- int64(i) 152 } 153 }